diff --git a/build/types.js b/build/types.js new file mode 100644 index 000000000..3cfd66110 --- /dev/null +++ b/build/types.js @@ -0,0 +1,18 @@ +import fs from 'node:fs/promises'; +import path from 'node:path'; + +const projectDir = path.join(import.meta.dirname, '..'); +const sourcePath = path.join(projectDir, 'src/core/module.d.ts'); +const outputDir = path.join(projectDir, 'dist'); +const outputNames = ['docsify.module.d.ts', 'docsify.module.min.d.ts']; + +const declaration = (await fs.readFile(sourcePath, 'utf8')) + .replaceAll('"./', '"../src/core/') + .replace(/\/\/# sourceMappingURL=.*\n?$/, ''); + +await fs.mkdir(outputDir, { recursive: true }); +await Promise.all( + outputNames.map(outputName => + fs.writeFile(path.join(outputDir, outputName), declaration), + ), +); diff --git a/docs/configuration.md b/docs/configuration.md index 5ad0b8958..c8c285076 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -12,6 +12,21 @@ You can configure Docsify by defining `window.$docsify` as an object: ``` +Docsify is also available as an ES module. Import `Docsify` from a CDN and pass +the configuration object to a new `Docsify` instance: + +```html + +``` + The config can also be defined as a function, in which case the first argument is the Docsify `vm` instance. The function should return a config object. This can be useful for referencing `vm` in places like the markdown configuration: ```html diff --git a/package.json b/package.json index 6e6c1a8ec..ac379b941 100644 --- a/package.json +++ b/package.json @@ -27,9 +27,12 @@ }, "type": "module", "main": "dist/docsify.js", - "types": "src/core/Docsify.d.ts", + "types": "dist/docsify.module.d.ts", "exports": { - ".": "./src/core/Docsify.js", + ".": { + "types": "./dist/docsify.module.d.ts", + "import": "./dist/docsify.module.js" + }, "./*": "./*" }, "files": [ @@ -97,7 +100,7 @@ "build:css:min": "cross-env NODE_ENV='production' npm run build:css -- --ext .min.css", "build:emoji": "node ./build/emoji.js", "build:js": "rollup -c", - "build:types": "tsc", + "build:types": "rimraf --glob \"src/**/*.d.ts\" \"src/**/*.d.ts.map\" && tsc && node build/types.js", "build:v4": "git checkout release-v4 && npm clean-install && git checkout docs/emoji.md src/core/render/emoji-data.js && rimraf packages/ && git checkout - && npm clean-install && npm run build:v4:deprecate -- lib/docsify.js && npm run build:v4:deprecate -- lib/docsify.min.js", "build:v4:deprecate": "echo ';console.warn(\"Docsify v4 is no longer supported. See https://docsify.js.org for the latest version.\")' >> ", "build": "run-s clean build:types build:js build:css build:css:min build:cover", diff --git a/rollup.config.js b/rollup.config.js index b0d853c23..18245bcdf 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -18,6 +18,13 @@ const docsifyConfig = { outputName: 'docsify', title: 'Docsify', }; +const docsifyEsmConfig = { + inputPath: 'src/core/module.js', + outputDir: 'dist', + outputName: 'docsify.module', + title: 'Docsify', + format: 'es', +}; // Plugins const pluginPaths = await glob(['src/plugins/*.js', 'src/plugins/*/index.js']); @@ -65,8 +72,9 @@ const baseConfig = { const bundleConfigs = []; // Generate rollup configurations -[docsifyConfig, ...pluginConfigs].forEach(bundleConfig => { - const { inputPath, outputDir, outputName, title } = bundleConfig; +[docsifyConfig, docsifyEsmConfig, ...pluginConfigs].forEach(bundleConfig => { + const { inputPath, outputDir, outputName, title, format } = bundleConfig; + const outputFormat = format || baseConfig.output.format; // prettier-ignore const banner = stripIndent` /*! @@ -83,6 +91,7 @@ const bundleConfigs = []; ...baseConfig.output, banner, file: path.join(outputDir, `${outputName}.min.js`), + format: outputFormat, sourcemap: true, }, plugins: [ @@ -101,6 +110,7 @@ const bundleConfigs = []; ...baseConfig.output, banner, file: path.join(outputDir, `${outputName}.js`), + format: outputFormat, }, plugins: [ ...baseConfig.plugins, diff --git a/test/e2e/module.test.js b/test/e2e/module.test.js new file mode 100644 index 000000000..77715f135 --- /dev/null +++ b/test/e2e/module.test.js @@ -0,0 +1,21 @@ +import { test, expect } from './fixtures/docsify-init-fixture.js'; + +for (const moduleName of ['docsify.module.js', 'docsify.module.min.js']) { + test(`initializes Docsify from ${moduleName}`, async ({ page }) => { + await page.setContent('
'); + await page.addScriptTag({ + type: 'module', + content: ` + import { Docsify } from '/dist/${moduleName}'; + + new Docsify({ + routes: { + '/': '# Docsify ES module', + }, + }); + `, + }); + + await expect(page.locator('#main')).toContainText('Docsify ES module'); + }); +}