Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add vanilla_vite typescript recipe #29

Merged
merged 1 commit into from
Feb 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ci/prepare_playwright.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
set -eux

./single_example.sh typescript vanilla_rspack
./single_example.sh typescript vanilla_vite
./single_example.sh typescript vanilla_webpack
15 changes: 12 additions & 3 deletions ci/single_example.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ fi
export TYPE=$1
export EXAMPLE=$2

if [ $EXAMPLE == "vanilla_vite" ]; then
export PORT=5173
export SERVE_CMD="npm run dev"
else
export PORT=4500
export SERVE_CMD="npm run serve"
fi


function merge-json() {
# merge the second json file into the first.
TEMP_FILE=$(mktemp)
Expand Down Expand Up @@ -44,7 +53,7 @@ export default defineConfig({
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {
baseURL: 'http://localhost:4500',
baseURL: 'http://localhost:$PORT',
trace: 'on-first-retry',
},
projects: [
Expand All @@ -55,7 +64,7 @@ export default defineConfig({
],
webServer: {
command: 'npm run serve',
url: 'http://localhost:4500',
url: 'http://localhost:$PORT',
reuseExistingServer: !process.env.CI
}
});
Expand All @@ -65,7 +74,7 @@ EOF
cat > temp.json << EOF
{
"scripts": {
"serve": "npm explore $EXAMPLE -- npm run serve",
"serve": "npm explore $EXAMPLE -- $SERVE_CMD",
"test": "playwright test",
"test:ui": "playwright test --ui"
}
Expand Down
2 changes: 1 addition & 1 deletion ci/typescript/create_vanilla_rspack.sh
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ rm temp.json
# 8. Build and run basic example without any BokehJS
# npm install
# npm run build
# npm run serve
# # npm run serve
# In a web browser navigate to http://localhost:4500/

# 9. Add BokehJS dependency to this project. This assumes the package has been built and copied to the root directory of this repository as outlined in the top-level README.md.
Expand Down
77 changes: 77 additions & 0 deletions ci/typescript/create_vanilla_vite.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/usr/bin/env bash

set -eux

export OUTPUT_DIRECTORY=../temp/typescript/vanilla_vite

mkdir -p $OUTPUT_DIRECTORY
cd $OUTPUT_DIRECTORY
rm -rf *

function merge-json() {
# merge the second json file into the first.
TEMP_FILE=$(mktemp)
jq '. * input' $1 $2 > TEMP_FILE && mv TEMP_FILE $1
}

# 1. Create base vite project
npm create vite@latest . -- --template vanilla-ts --yes

# 2. Build and run initial basic project
# npm install
# # npm run dev
# In a web browser navigate to http://localhost:5173/

# 3. Simplify by removing some unwanted files
rm public/vite.svg src/counter.ts src/style.css src/typescript.svg

# 4. Replace src/main.ts with a simple hello example
cat > src/main.ts << EOF
document.querySelector<HTMLDivElement>('#app')!.innerHTML = \`<div>Hello</div>\`
EOF

# 5. Build and run the minimal example
# # npm run dev
# In a web browser navigate to http://localhost:5173/

# 6. Add BokehJS dependency to this project. This assumes the package has been built and copied to the root directory of this repository as outlined in the top-level README.md.
npm install ../../../../bokeh-bokehjs-3.7.0-dev.5.tgz

# 7. Replace src/main.ts with a simple hello example
cat > src/main.ts << EOF
import * as Bokeh from "@bokeh/bokehjs";

console.info("BokehJS version:", Bokeh.version);

function create_bokehjs_plot(target_id: string) {
const source = new Bokeh.ColumnDataSource({data: { x: [0.1, 0.9], y: [0.1, 0.9], size: [40, 10] }});

const plot = Bokeh.Plotting.figure({
title: "Example BokehJS plot", height: 500, width: 500,
x_range: [0, 1], y_range: [0, 1], sizing_mode: "stretch_width",
});

plot.scatter({ field: "x" }, { field: "y" }, {source, size: { field: "size" }});

const button = new Bokeh.Widgets.Button({label: "Click me to add a point", button_type: "primary"});
function button_callback() {
const data = source.data as any;
data.x.push(Math.random());
data.y.push(Math.random());
data.size.push(10 + Math.random()*30);
source.change.emit();
}
button.on_click(button_callback);

const column = new Bokeh.Column({children: [plot, button], sizing_mode: "stretch_width"});
Bokeh.Plotting.show(column, target_id);
}

document.querySelector<HTMLDivElement>('#app')!.innerHTML = \`<div id='target'>Hello</div>\`;

create_bokehjs_plot("#target");
EOF

# 8. Rebuild and serve
# npm run dev
# In a web browser navigate to http://localhost:5173/
2 changes: 1 addition & 1 deletion ci/typescript/create_vanilla_webpack.sh
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ rm temp.json
# 8. Build and run basic example without any BokehJS
# npm install
# npm run build
# npm run serve
# # npm run serve
# In a web browser navigate to http://localhost:4500/

# 9. Add BokehJS dependency to this project. This assumes the package has been built and copied to the root directory of this repository as outlined in the top-level README.md.
Expand Down
13 changes: 8 additions & 5 deletions recipes/src/recipes/typescript/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ export const baseTSConfig =
"include": ["src"]
}`;

export const baseTypeScriptExample =
`import * as Bokeh from "@bokeh/bokehjs";

console.info("BokehJS version:", Bokeh.version);
export const baseTypeScriptExample = {
import: 'import * as Bokeh from "@bokeh/bokehjs";\n',
function:
`console.info("BokehJS version:", Bokeh.version);

function create_bokehjs_plot(target_id: string) {
const source = new Bokeh.ColumnDataSource({data: { x: [0.1, 0.9], y: [0.1, 0.9], size: [40, 10] }});
Expand All @@ -38,4 +38,7 @@ function create_bokehjs_plot(target_id: string) {

const column = new Bokeh.Column({children: [plot, button], sizing_mode: "stretch_width"});
Bokeh.Plotting.show(column, target_id);
}`;
}
`,
create: 'create_bokehjs_plot("#target");'
};
1 change: 1 addition & 0 deletions recipes/src/recipes/typescript/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './vanilla_rspack_recipe';
export * from './vanilla_vite_recipe';
export * from './vanilla_webpack_recipe';
4 changes: 3 additions & 1 deletion recipes/src/recipes/typescript/vanilla_rspack_recipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ export default config;`)
this.add(new CreateFileStep(
'Replace contents of `src/index.ts` with code to create BokehJS plot',
'src/index.ts',
baseTypeScriptExample + '\n\ncreate_bokehjs_plot("#target");'
baseTypeScriptExample.import + "\n" +
baseTypeScriptExample.function + "\n" +
baseTypeScriptExample.create
));

this.add(new CommandStep(
Expand Down
65 changes: 65 additions & 0 deletions recipes/src/recipes/typescript/vanilla_vite_recipe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Recipe } from '../../recipe';
import { CommandStep, RemoveFilesStep, ReplaceFileStep } from '../../step';
import { baseTypeScriptExample } from './common';

export class VanillaViteRecipe extends Recipe {
constructor() {
super(
'typescript',
'vanilla',
'vite',
'Create an initial basic project using `create-vite`.'
);

this.add(new CommandStep(
'Create base `vite` project',
['npm create vite@latest . -- --template vanilla-ts --yes']
));

this.add(new CommandStep(
'Build and run initial basic project',
['npm install', 'npm run dev'],
'In a web browser navigate to http://localhost:5173/',
true
));

this.add(new RemoveFilesStep(
'Simplify by removing some unwanted files',
['public/vite.svg', 'src/counter.ts', 'src/style.css', 'src/typescript.svg']
));

this.add(new ReplaceFileStep(
'Replace `src/main.ts` with a simple hello example',
'src/main.ts',
"document.querySelector<HTMLDivElement>('#app')!.innerHTML = \\`<div>Hello</div>\\`")
);

this.add(new CommandStep(
'Build and run the minimal example',
['npm run dev'],
'In a web browser navigate to http://localhost:5173/',
true
));

this.add(new CommandStep(
'Add BokehJS dependency to this project. This assumes the package has been built and ' +
'copied to the root directory of this repository as outlined in the top-level `README.md`.',
['npm install ../../../../bokeh-bokehjs-3.7.0-dev.5.tgz']
));

this.add(new ReplaceFileStep(
'Replace `src/main.ts` with a simple hello example',
'src/main.ts',
baseTypeScriptExample.import + "\n" +
baseTypeScriptExample.function + "\n" +
"document.querySelector<HTMLDivElement>('#app')!.innerHTML = \\`<div id='target'>Hello</div>\\`;\n\n" +
'create_bokehjs_plot("#target");'
));

this.add(new CommandStep(
'Rebuild and serve',
['npm run dev'],
'In a web browser navigate to http://localhost:5173/'
));
}
}
4 changes: 3 additions & 1 deletion recipes/src/recipes/typescript/vanilla_webpack_recipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ export default config;`)
this.add(new CreateFileStep(
'Replace contents of `src/index.ts` with code to create BokehJS plot',
'src/index.ts',
baseTypeScriptExample + '\n\ncreate_bokehjs_plot("#target");'
baseTypeScriptExample.import + "\n" +
baseTypeScriptExample.function + "\n" +
baseTypeScriptExample.create
));

this.add(new CommandStep(
Expand Down
70 changes: 60 additions & 10 deletions recipes/src/step.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ export class CommandStep extends Step {

const allPrefix = this.ignoreIfBash ? '# ' : '';
for (const command of this.commands) {
const prefix = command === 'npm run serve' ? '# ' : allPrefix;
let prefix = allPrefix;
if (command === 'npm run serve' || command === 'npm run dev') {
prefix = '# ' + prefix;
}
fs.writeSync(fd, prefix + command + '\n');
}
if (this.postscript) {
Expand All @@ -66,20 +69,24 @@ export class CommandStep extends Step {
}
}

/**
* Step to create a file.
*/
export class CreateFileStep extends Step {
constructor(readonly description: string, readonly filename: string, readonly contents: string) {
abstract class CreateOrReplaceFileStep extends Step {
constructor(
readonly description: string,
readonly filename: string,
readonly contents: string,
readonly alreadyExists: boolean
) {
super(description);
}

writeToBash(fd: number, index: number): void {
this.writeDescriptionBash(fd, index);

const dirname = path.dirname(this.filename);
if (dirname !== '.') {
fs.writeSync(fd, `mkdir -p ${dirname}\n`);
if (!this.alreadyExists) {
const dirname = path.dirname(this.filename);
if (dirname !== '.') {
fs.writeSync(fd, `mkdir -p ${dirname}\n`);
}
}

fs.writeSync(fd, `cat > ${this.filename} << EOF\n`);
Expand All @@ -96,8 +103,9 @@ export class CreateFileStep extends Step {
const { spacer } = this;
const language = languageFromExtension(this.filename);
fs.writeSync(fd, '\n' + spacer + '```' + language + '\n');
for (const line of this.contents.split('\n')) {
for (let line of this.contents.split('\n')) {
if (line) {
line = line.replaceAll('\\`', '`');
fs.writeSync(fd, spacer + line + '\n');
} else {
fs.writeSync(fd, '\n');
Expand All @@ -107,6 +115,15 @@ export class CreateFileStep extends Step {
}
}

/**
* Step to create a file.
*/
export class CreateFileStep extends CreateOrReplaceFileStep {
constructor(description: string, filename: string, contents: string) {
super(description, filename, contents, false);
}
}

/**
* Step to create a file.
*/
Expand Down Expand Up @@ -145,3 +162,36 @@ export class MergeJsonStep extends Step {
fs.writeSync(fd, spacer + '```\n');
}
}

/**
* Step to remove files.
*/
export class RemoveFilesStep extends Step {
constructor(readonly description: string, readonly filenames: string[]) {
super(description);
}

writeToBash(fd: number, index: number): void {
this.writeDescriptionBash(fd, index);

fs.writeSync(fd, 'rm ' + this.filenames.join(' ') + '\n');
}

writeToReadme(fd: number, index: number): void {
this.writeDescriptionReadme(fd, index);

const { spacer } = this;
fs.writeSync(fd, '\n' + spacer + '```bash\n');
fs.writeSync(fd, spacer + 'rm ' + this.filenames.join(' ') + '\n');
fs.writeSync(fd, spacer + '```\n');
}
}

/**
* Step to replace the contents of an existing file.
*/
export class ReplaceFileStep extends CreateOrReplaceFileStep {
constructor(description: string, filename: string, contents: string) {
super(description, filename, contents, true);
}
}
Loading