diff --git a/.gitignore b/.gitignore index 253be23..44a0d26 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ node_modules/ package-lock.json ci/temp bokeh-bokehjs-*.tgz +dist/ diff --git a/ci/typescript/create_vanilla_rspack.sh b/ci/typescript/create_vanilla_rspack.sh index 1a61846..b96f206 100755 --- a/ci/typescript/create_vanilla_rspack.sh +++ b/ci/typescript/create_vanilla_rspack.sh @@ -60,8 +60,8 @@ const config: Configuration = { export default config; EOF -# 5. Create HTML file -mkdir assets +# 5. Create HTML file assets/index.html +mkdir -p assets cat > assets/index.html << EOF @@ -75,13 +75,13 @@ cat > assets/index.html << EOF EOF -# 6. Create source typescript file -mkdir src +# 6. Create source typescript file src/index.ts +mkdir -p src cat > src/index.ts << EOF console.log("Successfully loaded") EOF -# 7. Add build and serve commands to package.json +# 7. Add build and serve commands to the scripts section of package.json cat > temp.json << EOF { "scripts": { @@ -97,11 +97,13 @@ rm temp.json # npm install # npm run build # npm run serve +# In a web browser navigate to http://localhost:4500/ -# 9. Add BokehJS dependency +# 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. npm install ../../../../bokeh-bokehjs-3.7.0-dev.5.tgz -# 10. Replace src/index.ts with code to create BokehJS plot +# 10. Replace contents of src/index.ts with code to create BokehJS plot +mkdir -p src cat > src/index.ts << EOF import * as Bokeh from "@bokeh/bokehjs"; @@ -137,4 +139,5 @@ EOF # 11. Rebuild and serve npm install npm run build -#npm run serve +# npm run serve +# In a web browser navigate to http://localhost:4500/ diff --git a/ci/typescript/create_vanilla_webpack.sh b/ci/typescript/create_vanilla_webpack.sh index e62e838..de00768 100755 --- a/ci/typescript/create_vanilla_webpack.sh +++ b/ci/typescript/create_vanilla_webpack.sh @@ -61,8 +61,8 @@ const config: webpack.Configuration = { export default config; EOF -# 5. Create HTML file -mkdir assets +# 5. Create HTML file assets/index.html +mkdir -p assets cat > assets/index.html << EOF @@ -76,13 +76,13 @@ cat > assets/index.html << EOF EOF -# 6. Create source typescript file -mkdir src +# 6. Create source typescript file src/index.ts +mkdir -p src cat > src/index.ts << EOF console.log("Successfully loaded") EOF -# 7. Add build and serve commands to package.json +# 7. Add build and serve commands to the scripts section of package.json cat > temp.json << EOF { "scripts": { @@ -98,11 +98,13 @@ rm temp.json # npm install # npm run build # npm run serve +# In a web browser navigate to http://localhost:4500/ -# 9. Add BokehJS dependency +# 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. npm install ../../../../bokeh-bokehjs-3.7.0-dev.5.tgz -# 10. Replace src/index.ts with code to create BokehJS plot +# 10. Replace contents of src/index.ts with code to create BokehJS plot +mkdir -p src cat > src/index.ts << EOF import * as Bokeh from "@bokeh/bokehjs"; @@ -138,4 +140,5 @@ EOF # 11. Rebuild and serve npm install npm run build -#npm run serve +# npm run serve +# In a web browser navigate to http://localhost:4500/ diff --git a/recipes/README.md b/recipes/README.md new file mode 100644 index 0000000..afd0d79 --- /dev/null +++ b/recipes/README.md @@ -0,0 +1,12 @@ +Code to create recipes. Each recipe is defined in a TypeScript class and can be written to both a +README markdown file for humans to follow, and a `bash` script that can be used to automatically +create the recipe. + +To recreate all recipes: +```bash +npm install +npm run build +npm run create +``` + +This will overwrite all existing recipes. If you are happy with the changes, `git commit` them. diff --git a/recipes/package.json b/recipes/package.json new file mode 100644 index 0000000..b349255 --- /dev/null +++ b/recipes/package.json @@ -0,0 +1,16 @@ +{ + "name": "recipes", + "version": "1.0.0", + "license": "BSD-3-Clause", + "description": "Automated creation of recipe scripts and readme files", + "main": "index.js", + "types": "lib/index.d.ts", + "scripts": { + "build": "tsc", + "create": "node dist/runner.js" + }, + "devDependencies": { + "@types/node": "^22.13.1", + "typescript": "^5.7.3" + } +} diff --git a/recipes/src/bash_writer.ts b/recipes/src/bash_writer.ts new file mode 100644 index 0000000..f38d3c8 --- /dev/null +++ b/recipes/src/bash_writer.ts @@ -0,0 +1,36 @@ +import * as fs from 'node:fs'; +import * as path from 'node:path'; + +import { Recipe } from './recipe'; +import { Step } from './step'; +import { Writer } from './writer'; + +export class BashWriter extends Writer { + filename(recipe: Recipe): string { + return path.join( + '..', 'ci', recipe.type, 'create_' + recipe.framework + '_' + recipe.bundler + '.sh'); + } + + protected writeStep(fd: number, index: number, step: Step): void { + step.writeToBash(fd, index); + } + + protected writePreable(fd: number, recipe: Recipe): void { + fs.writeSync(fd, `#!/usr/bin/env bash + +set -eux + +export OUTPUT_DIRECTORY=../temp/${recipe.type}/${recipe.framework}_${recipe.bundler} + +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 +} +`); + } +} diff --git a/recipes/src/index.ts b/recipes/src/index.ts new file mode 100644 index 0000000..6ec1288 --- /dev/null +++ b/recipes/src/index.ts @@ -0,0 +1,4 @@ +export * from './bash_writer'; +export * from './readme_writer'; +export * from './recipe'; +export * from './writer'; diff --git a/recipes/src/readme_writer.ts b/recipes/src/readme_writer.ts new file mode 100644 index 0000000..2ddb0ac --- /dev/null +++ b/recipes/src/readme_writer.ts @@ -0,0 +1,30 @@ +import * as fs from 'node:fs'; +import * as path from 'node:path'; + +import { Recipe } from './recipe'; +import { Step } from './step'; +import { Writer } from './writer'; + +export class ReadmeWriter extends Writer { + filename(recipe: Recipe): string { + return path.join('..', recipe.type, recipe.framework + '_' + recipe.bundler, 'README.md'); + } + + protected writeStep(fd: number, index: number, step: Step): void { + step.writeToReadme(fd, index); + } + + protected writePreable(fd: number, recipe: Recipe): void { + const { type, bundler } = recipe; + + let { details, framework } = recipe; + const prefix = framework === 'vanilla' ? ' (no framework)' : ''; + framework = framework.charAt(0).toUpperCase() + framework.slice(1); + + fs.writeSync(fd, `# ${framework}${prefix} ${bundler} ${type} example\n`); + + if (details) { + fs.writeSync(fd, '\n' + details + '\n'); + } + } +} diff --git a/recipes/src/recipe.ts b/recipes/src/recipe.ts new file mode 100644 index 0000000..a3de274 --- /dev/null +++ b/recipes/src/recipe.ts @@ -0,0 +1,23 @@ +import { Step } from './step'; + +/** + * Abstract base class for recipe for making a BokehJS example, consisting of multiple steps. + */ +export abstract class Recipe { + constructor( + readonly type: string, + readonly framework: string, + readonly bundler: string, + readonly details: string = '' + ) {} + + protected add(step: Step): void { + this._steps.push(step); + } + + get steps(): Step[] { + return this._steps; + } + + private _steps: Step[] = []; +} diff --git a/recipes/src/recipes/index.ts b/recipes/src/recipes/index.ts new file mode 100644 index 0000000..83d3207 --- /dev/null +++ b/recipes/src/recipes/index.ts @@ -0,0 +1 @@ +export * from './typescript'; diff --git a/recipes/src/recipes/typescript/common.ts b/recipes/src/recipes/typescript/common.ts new file mode 100644 index 0000000..4d9c087 --- /dev/null +++ b/recipes/src/recipes/typescript/common.ts @@ -0,0 +1,41 @@ +export const baseTSConfig = +`{ + "compilerOptions": { + "baseUrl": ".", + "esModuleInterop": true, + "moduleResolution": "node", + "outDir": "./dist", + "rootDir": "./src", + "target": "ES2022" + }, + "include": ["src"] +}`; + +export const baseTypeScriptExample = +`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); +}`; diff --git a/recipes/src/recipes/typescript/index.ts b/recipes/src/recipes/typescript/index.ts new file mode 100644 index 0000000..a1a2bb9 --- /dev/null +++ b/recipes/src/recipes/typescript/index.ts @@ -0,0 +1,2 @@ +export * from './vanilla_rspack_recipe'; +export * from './vanilla_webpack_recipe'; diff --git a/recipes/src/recipes/typescript/vanilla_rspack_recipe.ts b/recipes/src/recipes/typescript/vanilla_rspack_recipe.ts new file mode 100644 index 0000000..88f04bb --- /dev/null +++ b/recipes/src/recipes/typescript/vanilla_rspack_recipe.ts @@ -0,0 +1,114 @@ +import { Recipe } from '../../recipe'; +import { CommandStep, CreateFileStep, MergeJsonStep } from '../../step'; +import { baseTSConfig, baseTypeScriptExample } from './common'; + +export class VanillaRspackRecipe extends Recipe { + constructor() { + super( + 'typescript', + 'vanilla', + 'rspack', + 'This is almost identical to the vanilla webpack example, as `rspack` is designed to be a ' + + 'drop-in replacement for `webpack`.' + ); + + this.add(new CommandStep( + 'Create initial `package.json` (`npm` project settings)', + ['npm init --yes'] + )); + + this.add(new CommandStep( + 'Install dev dependencies', + ['npm install --save-dev typescript @rspack/core @rspack/cli ts-node ts-loader'] + )); + + this.add(new CreateFileStep( + 'Create typescript configuration `tsconfig.json`', + 'tsconfig.json', + baseTSConfig + )); + + this.add(new CreateFileStep( + 'Create rspack configuration `rspack.config.ts`', + 'rspack.config.ts', +`import path from 'path'; +import { Configuration } from '@rspack/cli'; + +const config: Configuration = { + entry: './src/index.ts', + mode: 'development', + module: { + rules: [ + { test: /\\.ts/, use: "ts-loader", exclude: /node_modules/ } + ], + }, + output: { filename: 'bundle.js' }, + devServer: { + static: { + directory: path.join(__dirname, 'assets'), + }, + port: 4500, + }, +}; + +export default config;`) + ); + + this.add(new CreateFileStep( + 'Create HTML file `assets/index.html`', + 'assets/index.html', +` + + + BokehJS example: typescript vanilla rspack + + + +
+ +`) + ); + + this.add(new CreateFileStep( + 'Create source typescript file `src/index.ts`', + 'src/index.ts', + 'console.log("Successfully loaded")' + )); + + this.add(new MergeJsonStep( + 'Add `build` and `serve` commands to the `scripts` section of `package.json`', + 'package.json', +`{ + "scripts": { + "build": "rspack build", + "serve": "rspack serve" + } +}`) + ); + + this.add(new CommandStep( + 'Build and run basic example without any BokehJS', + ['npm install', 'npm run build', 'npm run serve'], + 'In a web browser navigate to http://localhost:4500/', + 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 CreateFileStep( + 'Replace contents of `src/index.ts` with code to create BokehJS plot', + 'src/index.ts', + baseTypeScriptExample + '\n\ncreate_bokehjs_plot("#target");' + )); + + this.add(new CommandStep( + 'Rebuild and serve', + ['npm install', 'npm run build', 'npm run serve'], + 'In a web browser navigate to http://localhost:4500/' + )); + } +} diff --git a/recipes/src/recipes/typescript/vanilla_webpack_recipe.ts b/recipes/src/recipes/typescript/vanilla_webpack_recipe.ts new file mode 100644 index 0000000..9faeec8 --- /dev/null +++ b/recipes/src/recipes/typescript/vanilla_webpack_recipe.ts @@ -0,0 +1,113 @@ +import { Recipe } from '../../recipe'; +import { CommandStep, CreateFileStep, MergeJsonStep } from '../../step'; +import { baseTSConfig, baseTypeScriptExample } from './common'; + +export class VanillaWebpackRecipe extends Recipe { + constructor() { + super( + 'typescript', + 'vanilla', + 'webpack', + ); + + this.add(new CommandStep( + 'Create initial `package.json` (`npm` project settings)', + ['npm init --yes'] + )); + + this.add(new CommandStep( + 'Install dev dependencies', + ['npm install --save-dev typescript webpack webpack-cli webpack-dev-server ts-node ts-loader'] + )); + + this.add(new CreateFileStep( + 'Create typescript configuration `tsconfig.json`', + 'tsconfig.json', + baseTSConfig + )); + + this.add(new CreateFileStep( + 'Create webpack configuration `webpack.config.ts`', + 'webpack.config.ts', +`import path from 'path'; +import webpack from 'webpack'; +import 'webpack-dev-server'; + +const config: webpack.Configuration = { + entry: './src/index.ts', + mode: 'development', + module: { + rules: [ + { test: /\\.ts/, use: "ts-loader", exclude: /node_modules/ } + ], + }, + output: { filename: 'bundle.js' }, + devServer: { + static: { + directory: path.join(__dirname, 'assets'), + }, + port: 4500, + }, +}; + +export default config;`) + ); + + this.add(new CreateFileStep( + 'Create HTML file `assets/index.html`', + 'assets/index.html', +` + + + BokehJS example: typescript vanilla webpack + + + +
+ +`) + ); + + this.add(new CreateFileStep( + 'Create source typescript file `src/index.ts`', + 'src/index.ts', + 'console.log("Successfully loaded")' + )); + + this.add(new MergeJsonStep( + 'Add `build` and `serve` commands to the `scripts` section of `package.json`', + 'package.json', +`{ + "scripts": { + "build": "webpack build", + "serve": "webpack serve" + } +}`) + ); + + this.add(new CommandStep( + 'Build and run basic example without any BokehJS', + ['npm install', 'npm run build', 'npm run serve'], + 'In a web browser navigate to http://localhost:4500/', + 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 CreateFileStep( + 'Replace contents of `src/index.ts` with code to create BokehJS plot', + 'src/index.ts', + baseTypeScriptExample + '\n\ncreate_bokehjs_plot("#target");' + )); + + this.add(new CommandStep( + 'Rebuild and serve', + ['npm install', 'npm run build', 'npm run serve'], + 'In a web browser navigate to http://localhost:4500/' + )); + } +} diff --git a/recipes/src/runner.ts b/recipes/src/runner.ts new file mode 100644 index 0000000..fb84d8a --- /dev/null +++ b/recipes/src/runner.ts @@ -0,0 +1,14 @@ +import { BashWriter, ReadmeWriter, Recipe, Writer } from '.'; +import * as allRecipes from './recipes/typescript'; + +const writers: Writer[] = [new BashWriter(), new ReadmeWriter()]; + +for (const cls of Object.values(allRecipes)) { + const recipe: Recipe = new (cls as any)(); + console.log(`Recipe ${recipe.type} ${recipe.framework} ${recipe.bundler}`); + + for (const writer of writers) { + console.log(` Writing to ${writer.filename(recipe)}`); + writer.write(recipe); + } +} diff --git a/recipes/src/step.ts b/recipes/src/step.ts new file mode 100644 index 0000000..de2fa69 --- /dev/null +++ b/recipes/src/step.ts @@ -0,0 +1,147 @@ +import * as fs from 'node:fs'; +import * as path from 'node:path'; + +import { fileExtension, languageFromExtension, removeBackticks } from './util'; + +/** + * Single step of a recipe. + */ +export abstract class Step { //} implements IWriteVisitor { + constructor(readonly description: string) {} + + abstract writeToBash(fd: number, index: number): void; + + abstract writeToReadme(fd: number, index: number): void; + + protected writeDescriptionBash(fd: number, index: number, suffix: string = ''): void { + fs.writeSync(fd, `\n# ${index+1}. ${removeBackticks(this.description)}${suffix}\n`); + } + + protected writeDescriptionReadme(fd: number, index: number, suffix: string = ''): void { + fs.writeSync(fd, `\n${index+1}. ${this.description}${suffix}\n`); + } + + protected spacer = ' '; // Spacer for indented lines in README. +} + +/** + * Step consisting of one or more shell commands. + */ +export class CommandStep extends Step { + constructor( + readonly description: string, + readonly commands: string[], + readonly postscript: string = '', + readonly ignoreIfBash: boolean = false + ) { + super(description); + } + + writeToBash(fd: number, index: number): void { + this.writeDescriptionBash(fd, index); + + const allPrefix = this.ignoreIfBash ? '# ' : ''; + for (const command of this.commands) { + const prefix = command === 'npm run serve' ? '# ' : allPrefix; + fs.writeSync(fd, prefix + command + '\n'); + } + if (this.postscript) { + fs.writeSync(fd, '# ' + this.postscript + '\n'); + } + } + + writeToReadme(fd: number, index: number): void { + this.writeDescriptionReadme(fd, index); + + const { spacer } = this; + fs.writeSync(fd, '\n' + spacer + '```bash\n'); + for (const command of this.commands) { + fs.writeSync(fd, spacer + command + '\n'); + } + fs.writeSync(fd, spacer + '```\n'); + + if (this.postscript) { + fs.writeSync(fd, '\n' + spacer + this.postscript + '\n'); + } + } +} + +/** + * Step to create a file. + */ +export class CreateFileStep extends Step { + constructor(readonly description: string, readonly filename: string, readonly contents: string) { + 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`); + } + + fs.writeSync(fd, `cat > ${this.filename} << EOF\n`); + fs.writeSync(fd, this.contents); + if (this.contents.at(-1) !== '\n') { + fs.writeSync(fd, '\n'); + } + fs.writeSync(fd, 'EOF\n'); + } + + writeToReadme(fd: number, index: number): void { + this.writeDescriptionReadme(fd, index, ' containing'); + + const { spacer } = this; + const language = languageFromExtension(this.filename); + fs.writeSync(fd, '\n' + spacer + '```' + language + '\n'); + for (const line of this.contents.split('\n')) { + if (line) { + fs.writeSync(fd, spacer + line + '\n'); + } else { + fs.writeSync(fd, '\n'); + } + } + fs.writeSync(fd, spacer + '```\n'); + } +} + +/** + * Step to create a file. + */ +export class MergeJsonStep extends Step { + constructor(readonly description: string, readonly filename: string, readonly toMerge: string) { + super(description); + } + + writeToBash(fd: number, index: number): void { + this.writeDescriptionBash(fd, index); + + const tempFilename = 'temp' + fileExtension(this.filename); + fs.writeSync(fd, `cat > ${tempFilename} << EOF\n`); + fs.writeSync(fd, this.toMerge); + if (this.toMerge.at(-1) !== '\n') { + fs.writeSync(fd, '\n'); + } + fs.writeSync(fd, 'EOF\n'); + fs.writeSync(fd, `merge-json ${this.filename} ${tempFilename}\n`); + fs.writeSync(fd, `rm ${tempFilename}\n`); + } + + writeToReadme(fd: number, index: number): void { + this.writeDescriptionReadme(fd, index); + + const { spacer } = this; + const language = languageFromExtension(this.filename); + fs.writeSync(fd, '\n' + spacer + '```' + language + '\n'); + for (const line of this.toMerge.split('\n')) { + if (line) { + fs.writeSync(fd, spacer + line + '\n'); + } else { + fs.writeSync(fd, '\n'); + } + } + fs.writeSync(fd, spacer + '```\n'); + } +} diff --git a/recipes/src/util.ts b/recipes/src/util.ts new file mode 100644 index 0000000..f9b9149 --- /dev/null +++ b/recipes/src/util.ts @@ -0,0 +1,28 @@ +import * as path from 'node:path'; + +export function fileExtension(filename: string): string { + const extension = path.extname(filename); + return extension === '.' ? '' : extension; +} + +export function languageFromExtension(filename: string): string { + const extension = fileExtension(filename); + switch (extension) { + case '.html': { + return 'html'; + } + case '.json': { + return 'json'; + } + case '.ts': { + return 'typescript'; + } + default: { + return ''; + } + } +} + +export function removeBackticks(text: string): string { + return text.replaceAll('`', ''); +} diff --git a/recipes/src/writer.ts b/recipes/src/writer.ts new file mode 100644 index 0000000..adcbaea --- /dev/null +++ b/recipes/src/writer.ts @@ -0,0 +1,25 @@ +import * as fs from 'node:fs'; + +import { Recipe } from './recipe'; +import { Step } from './step'; + +export abstract class Writer { + abstract filename(recipe: Recipe): string; + + write(recipe: Recipe) { + const filename = this.filename(recipe); + const fd = fs.openSync(filename, 'w'); + + this.writePreable(fd, recipe); + + for (let i = 0; i < recipe.steps.length; i++) { + this.writeStep(fd, i, recipe.steps[i]); + } + + fs.closeSync(fd); + } + + protected abstract writeStep(fd: number, index: number, step: Step): void; + + protected abstract writePreable(fd: number, recipe: Recipe): void; +} diff --git a/recipes/tsconfig.json b/recipes/tsconfig.json new file mode 100644 index 0000000..a48af9e --- /dev/null +++ b/recipes/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "module": "nodenext", + "outDir": "./dist", + "rootDir": "./src", + "target": "ES2022" + }, + "include": ["src"] +} diff --git a/typescript/vanilla_rspack/README.md b/typescript/vanilla_rspack/README.md index 3fa7e2a..d37bc5a 100644 --- a/typescript/vanilla_rspack/README.md +++ b/typescript/vanilla_rspack/README.md @@ -1,8 +1,6 @@ - # Vanilla (no framework) rspack typescript example -This is almost identical to the vanilla webpack example, as `rspack` is designed to be a drop-in -replacement for `webpack`. +This is almost identical to the vanilla webpack example, as `rspack` is designed to be a drop-in replacement for `webpack`. 1. Create initial `package.json` (`npm` project settings) @@ -16,7 +14,7 @@ replacement for `webpack`. npm install --save-dev typescript @rspack/core @rspack/cli ts-node ts-loader ``` -3. Create typescript configuration `tsconfig.json` containing: +3. Create typescript configuration `tsconfig.json` containing ```json { @@ -32,7 +30,7 @@ replacement for `webpack`. } ``` -4. Create webpack configuration `rspack.config.ts` containing: +4. Create rspack configuration `rspack.config.ts` containing ```typescript import path from 'path'; @@ -58,7 +56,7 @@ replacement for `webpack`. export default config; ``` -5. Create HTML file `assets/index.html` containing: +5. Create HTML file `assets/index.html` containing ```html @@ -73,18 +71,20 @@ replacement for `webpack`. ``` -6. Create source typescript file `src/index.ts` containing: +6. Create source typescript file `src/index.ts` containing - ```ts + ```typescript console.log("Successfully loaded") ``` -7. Add build and serve commands to the `scripts` section of `package.json`: +7. Add `build` and `serve` commands to the `scripts` section of `package.json` ```json - "scripts": { - "build": "rspack build", - "serve": "rspack serve" + { + "scripts": { + "build": "rspack build", + "serve": "rspack serve" + } } ``` @@ -96,16 +96,15 @@ replacement for `webpack`. npm run serve ``` - In a web browser navigate to http://localhost:4500/ + In a web browser navigate to http://localhost:4500/ -9. Add BokehJS dependency to the 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. +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`. ```bash npm install ../../../../bokeh-bokehjs-3.7.0-dev.5.tgz ``` -10. Remove contents of `src/index.ts` and replace with code to create BokehJS plot: +10. Replace contents of `src/index.ts` with code to create BokehJS plot containing ```typescript import * as Bokeh from "@bokeh/bokehjs"; @@ -144,7 +143,7 @@ replacement for `webpack`. ```bash npm install npm run build - #npm run serve + npm run serve ``` - In a web browser navigate to http://localhost:4500/ + In a web browser navigate to http://localhost:4500/ diff --git a/typescript/vanilla_webpack/README.md b/typescript/vanilla_webpack/README.md index 997621a..b532406 100644 --- a/typescript/vanilla_webpack/README.md +++ b/typescript/vanilla_webpack/README.md @@ -1,4 +1,3 @@ - # Vanilla (no framework) webpack typescript example 1. Create initial `package.json` (`npm` project settings) @@ -13,7 +12,7 @@ npm install --save-dev typescript webpack webpack-cli webpack-dev-server ts-node ts-loader ``` -3. Create typescript configuration `tsconfig.json` containing: +3. Create typescript configuration `tsconfig.json` containing ```json { @@ -29,7 +28,7 @@ } ``` -4. Create webpack configuration `webpack.config.ts` containing: +4. Create webpack configuration `webpack.config.ts` containing ```typescript import path from 'path'; @@ -56,7 +55,7 @@ export default config; ``` -5. Create HTML file `assets/index.html` containing: +5. Create HTML file `assets/index.html` containing ```html @@ -71,18 +70,20 @@ ``` -6. Create source typescript file `src/index.ts` containing: +6. Create source typescript file `src/index.ts` containing - ```ts + ```typescript console.log("Successfully loaded") ``` -7. Add build and serve commands to the `scripts` section of `package.json`: +7. Add `build` and `serve` commands to the `scripts` section of `package.json` ```json - "scripts": { - "build": "webpack build", - "serve": "webpack serve" + { + "scripts": { + "build": "webpack build", + "serve": "webpack serve" + } } ``` @@ -94,16 +95,15 @@ npm run serve ``` - In a web browser navigate to http://localhost:4500/ + In a web browser navigate to http://localhost:4500/ -9. Add BokehJS dependency to the 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. +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`. ```bash npm install ../../../../bokeh-bokehjs-3.7.0-dev.5.tgz ``` -10. Remove contents of `src/index.ts` and replace with code to create BokehJS plot: +10. Replace contents of `src/index.ts` with code to create BokehJS plot containing ```typescript import * as Bokeh from "@bokeh/bokehjs"; @@ -142,7 +142,7 @@ ```bash npm install npm run build - #npm run serve + npm run serve ``` - In a web browser navigate to http://localhost:4500/ + In a web browser navigate to http://localhost:4500/