From f6ffc04e39725072b1ada93c8b5ace4919dc71f1 Mon Sep 17 00:00:00 2001 From: Joe Pea Date: Wed, 27 Mar 2024 17:39:39 -0700 Subject: [PATCH 1/5] output type definitions and adjust package.json so that types are picked up in consumer projects --- .gitignore | 1 + .vscode/settings.json | 3 ++- package.json | 21 ++++++++++++++++++--- tsconfig.json | 25 +++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore index 545b20a6f..a2461da5c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /_playwright-report /_playwright-results /lib +/dist /node_modules /.husky/_ diff --git a/.vscode/settings.json b/.vscode/settings.json index 39497bbfc..45d2e1804 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,5 @@ { "editor.defaultFormatter": "esbenp.prettier-vscode", - "cSpell.words": ["coverpage"] + "cSpell.words": ["coverpage"], + "typescript.tsdk": "node_modules/typescript/lib" } diff --git a/package.json b/package.json index 54efbff52..e7afe72a4 100644 --- a/package.json +++ b/package.json @@ -12,22 +12,37 @@ "type": "module", "// The 'main' and 'unpkg' fields will remain as legacy for backwards compatibility for now. We will add deprectaion warnings to these outputs to give people time to see the warnings in their apps in a non-breaking way, and eventually we can remove the legacy stuff.": "", "main": "lib/docsify.js", + "types": "dist/core/Docsify.d.ts", "unpkg": "lib/docsify.min.js", "// We're using the 'exports' field as an override of the 'main' field to provide the new ESM setup. Once we remove legacy 'main', we will remove the 'exports' field and have a simple ESM setup with only a 'main' field.": "", + "// These exports require moduleResolution:NodeNext to be enabled in the consumer.": "", + "// TODO native ESM (in browsers) does not work yet because prismjs is not ESM and Docsify source imports it as CommonJS": "", "exports": { - ".": "./src/Docsify.js", - "./*": "./*" + "./*": "./*", + ".": { + "types": "./dist/core/Docsify.d.ts", + "default": "./src/core/Docsify.js" + } }, "files": [ "lib", "themes" ], + "// Using 'typesVersions' here is the only way we could figure out how to get types working for imports of any subpath without any of the problems other approaches have when not using modeResolution:NodeNext (listed in https://stackoverflow.com/questions/77856692/how-to-publish-plain-jsjsdoc-library-for-typescript-consumers)": "", + "typesVersions": { + "*": { + "src/*": [ + "dist/*" + ] + } + }, "scripts": { "build:cover": "node build/cover.js", "build:css:min": "node build/mincss.js", "build:css": "mkdirp lib/themes && node build/css -o lib/themes", "build:emoji": "node ./build/emoji.js", - "build:js": "cross-env NODE_ENV=production node build/build.js", + "build:js": "npm run build:types && cross-env NODE_ENV=production node build/build.js", + "build:types": "tsc -p tsconfig.json || true", "build:test": "npm run build && npm test", "build": "rimraf lib themes && run-s build:js build:css build:css:min build:cover build:emoji", "dev": "run-p serve:dev watch:*", diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..14b09e6c9 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "allowJs": true, + "checkJs": true, + + "module": "NodeNext", + "moduleResolution": "NodeNext", + "target": "ESNext", + "lib": ["DOM", "ESNext"], + "declaration": true, + "emitDeclarationOnly": true, + "resolveJsonModule": true, + "outDir": "dist/" + }, + "include": ["src/**/*.js"], + "exclude": [ + // "./**/*.test.js", + // "test/", + // "jest.config.js", + // "middleware.js", + // "playwright.config.js", + // "server.configs.js", + // "server.js" + ] +} From 2387399555d75fd1ab9c57642d9f85febe1f421f Mon Sep 17 00:00:00 2001 From: Joe Pea Date: Wed, 27 Mar 2024 17:52:56 -0700 Subject: [PATCH 2/5] ignore dist in prettierignore --- .prettierignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.prettierignore b/.prettierignore index 6c424db81..377d4de83 100644 --- a/.prettierignore +++ b/.prettierignore @@ -4,3 +4,6 @@ lib/ themes/ _playwright-*/ emoji-data.* + +# for some reason this is needed in CI, although locally Prettier ignored dist/ already. +dist/ From 1a352afa205342698aee91c3fc07a42c2f01a13a Mon Sep 17 00:00:00 2001 From: Joe Pea Date: Mon, 1 Apr 2024 11:28:16 -0700 Subject: [PATCH 3/5] deprecate globals and global script data-* attributes, and set up the package for people to start importing `Docsify` and passing in non-global configs --- build/build.js | 28 +++++-- docs/index.html | 169 ++++++++++++++++++++++++++++++++++++++++- package.json | 7 +- src/core/Docsify.js | 20 ++++- src/core/config.js | 77 +++++++++++++++++-- src/core/global-api.js | 12 ++- src/core/index.js | 4 - src/core/module.js | 1 + src/core/module.min.js | 2 + tsconfig.json | 11 +-- 10 files changed, 290 insertions(+), 41 deletions(-) create mode 100644 src/core/module.js create mode 100644 src/core/module.min.js diff --git a/build/build.js b/build/build.js index c8b9ab545..eb1fd114a 100644 --- a/build/build.js +++ b/build/build.js @@ -17,6 +17,7 @@ const version = process.env.VERSION || pkg.version; /** * @param {{ * input: string, + * format: 'iife' | 'module', * output?: string, * globalName?: string, * plugins?: Array @@ -46,11 +47,11 @@ async function build(opts) { }, }) .then(bundle => { - const dest = 'lib/' + (opts.output || opts.input); + const dest = opts.output || opts.input; console.log(dest); return bundle.write({ - format: 'iife', + format: opts.format, output: opts.globalName ? { name: opts.globalName } : {}, file: dest, strict: false, @@ -64,7 +65,13 @@ async function buildCore() { promises.push( build({ input: 'src/core/index.js', - output: 'docsify.js', + output: 'lib/docsify.js', + format: 'iife', + }), + build({ + input: 'src/core/module.js', + output: 'dist/core/module.js', + format: 'module', }) ); @@ -72,7 +79,14 @@ async function buildCore() { promises.push( build({ input: 'src/core/index.js', - output: 'docsify.min.js', + output: 'lib/docsify.min.js', + format: 'iife', + plugins: [uglify()], + }), + build({ + input: 'src/core/module.js', + output: 'dist/core/module.min.js', + format: 'module', plugins: [uglify()], }) ); @@ -98,7 +112,7 @@ async function buildAllPlugin() { const promises = plugins.map(item => { return build({ input: 'src/plugins/' + item.input, - output: 'plugins/' + item.name + '.js', + output: 'lib/plugins/' + item.name + '.js', }); }); @@ -107,7 +121,7 @@ async function buildAllPlugin() { promises.push( build({ input: 'src/plugins/' + item.input, - output: 'plugins/' + item.name + '.min.js', + output: 'lib/plugins/' + item.name + '.min.js', plugins: [uglify()], }) ); @@ -140,7 +154,7 @@ async function main() { build({ input, - output: 'plugins/' + name + '.js', + output: 'lib/plugins/' + name + '.js', }); } }) diff --git a/docs/index.html b/docs/index.html index 0a7f78140..9f874f4ec 100644 --- a/docs/index.html +++ b/docs/index.html @@ -71,7 +71,7 @@
Loading ...
- --> + + + + + + + --> + + diff --git a/package.json b/package.json index e7afe72a4..0e106bd3a 100644 --- a/package.json +++ b/package.json @@ -18,13 +18,16 @@ "// These exports require moduleResolution:NodeNext to be enabled in the consumer.": "", "// TODO native ESM (in browsers) does not work yet because prismjs is not ESM and Docsify source imports it as CommonJS": "", "exports": { - "./*": "./*", + "./src/*": "./src/*", + "./dist/core/module.js": "./dist/core/module.js", + "./dist/core/module.min.js": "./dist/core/module.min.js", ".": { "types": "./dist/core/Docsify.d.ts", - "default": "./src/core/Docsify.js" + "default": "./dist/core/module.min.js" } }, "files": [ + "src", "lib", "themes" ], diff --git a/src/core/Docsify.js b/src/core/Docsify.js index ccf414c26..0cad5440a 100644 --- a/src/core/Docsify.js +++ b/src/core/Docsify.js @@ -1,3 +1,4 @@ +import prism from 'prismjs'; import { Router } from './router/index.js'; import { Render } from './render/index.js'; import { Fetch } from './fetch/index.js'; @@ -8,18 +9,31 @@ import config from './config.js'; import { isFn } from './util/core.js'; import { Lifecycle } from './init/lifecycle.js'; +export { prism }; +export { marked } from 'marked'; +export * as util from './util/index.js'; +export * as dom from './util/dom.js'; +export { Compiler } from './render/compiler.js'; +export { slugify } from './render/slugify.js'; +export { get } from './util/ajax.js'; + /** @typedef {new (...args: any[]) => any} Constructor */ +/** @typedef {import('./config.js').DocsifyConfig} DocsifyConfig */ // eslint-disable-next-line new-cap export class Docsify extends Fetch( // eslint-disable-next-line new-cap Events(Render(VirtualRoutes(Router(Lifecycle(Object))))) ) { - config = config(this); + /** @type {DocsifyConfig} */ + config; - constructor() { + /** @param {Partial} conf */ + constructor(conf = {}) { super(); + this.config = config(this, conf); + this.initLifecycle(); // Init hooks this.initPlugin(); // Install plugins this.callHook('init'); @@ -45,3 +59,5 @@ export class Docsify extends Fetch( }); } } + +export const version = '__VERSION__'; diff --git a/src/core/config.js b/src/core/config.js index 9d9f8e31d..083fd8d7d 100644 --- a/src/core/config.js +++ b/src/core/config.js @@ -3,9 +3,65 @@ import { hyphenate, isPrimitive } from './util/core.js'; const currentScript = document.currentScript; -/** @param {import('./Docsify.js').Docsify} vm */ -export default function (vm) { - const config = Object.assign( +/** +@typedef { + { + auto2top: boolean + autoHeader: boolean + basePath: string + catchPluginErrors: boolean + cornerExternalLinkTarget: '_blank' | '_self' | '_parent' | '_top' | '_unfencedTop' + coverpage: boolean | string + el: string + executeScript: null | boolean + ext: string + externalLinkRel: 'noopener' | string + externalLinkTarget: '_blank' | '_self' | '_parent' | '_top' | '_unfencedTop' + formatUpdated: string + ga: string + homepage: string + keyBindings: false | { + [commandName: string]: { + bindings: string[] + callback: Function + } + } + loadNavbar: null | boolean | string + loadSidebar: null | boolean | string + maxLevel: number + mergeNavbar: boolean + name: boolean | string + nameLink: string + nativeEmoji: boolean + noCompileLinks: string[] + noEmoji: boolean + notFoundPage: boolean | string | Record + plugins: Function[] + relativePath: boolean + repo: boolean | string + routes: Record + routerMode: 'hash' | 'history' + subMaxLevel: number, + topMargin: number, + + themeColor: string, + } +} DocsifyConfig +*/ + +/** + * @param {import('./Docsify.js').Docsify} vm + * @param {Partial} config + * @returns {DocsifyConfig} + */ +export default function (vm, config = {}) { + if (window.$docsify) { + console.warn( + 'DEPRECATION: The global $docsify config variable is deprecated. See the latest getting started docs. https://docsify.js.org/#/quickstart' + ); + } + + config = Object.assign( { auto2top: false, autoHeader: false, @@ -21,6 +77,7 @@ export default function (vm) { formatUpdated: '', ga: '', homepage: 'README.md', + keyBindings: {}, loadNavbar: null, loadSidebar: null, maxLevel: 6, @@ -37,7 +94,6 @@ export default function (vm) { routes: {}, routerMode: 'hash', subMaxLevel: 0, - // themeColor: '', topMargin: 0, // Deprecations ////////////////// @@ -63,7 +119,9 @@ export default function (vm) { typeof window.$docsify === 'function' ? window.$docsify(vm) - : window.$docsify + : window.$docsify, + + config ); // Merge default and user-specified key bindings @@ -99,6 +157,11 @@ export default function (vm) { const val = script.getAttribute('data-' + hyphenate(prop)); if (isPrimitive(val)) { + console.warn( + `DEPRECATION: data-* attributes on the docsify global script (f.e. ${ + 'data-' + hyphenate(prop) + }) are deprecated.` + ); config[prop] = val === '' ? true : val; } } @@ -124,7 +187,5 @@ export default function (vm) { config.name = ''; } - window.$docsify = config; - - return config; + return /** @type {DocsifyConfig} */ (config); } diff --git a/src/core/global-api.js b/src/core/global-api.js index 24be8ae2c..e0c3d3504 100644 --- a/src/core/global-api.js +++ b/src/core/global-api.js @@ -6,11 +6,15 @@ import { Compiler } from './render/compiler.js'; import { slugify } from './render/slugify.js'; import { get } from './util/ajax.js'; -// TODO This is deprecated, kept for backwards compatibility. Remove in a -// major release. We'll tell people to get everything from the DOCSIFY global -// when using the global build, but we'll highly recommend for them to import -// from the ESM build (f.e. lib/docsify.esm.js and lib/docsify.min.esm.js). +/** + * @deprecated This will be removed in a major release. Import what you need + * from using ES Modules as per the docs. + */ export default function initGlobalAPI() { + console.warn( + 'DEPRECATION: The Docsify global script is deprecated. See the latest getting started docs. https://docsify.js.org/#/quickstart' + ); + window.Docsify = { util, dom, diff --git a/src/core/index.js b/src/core/index.js index 897ac66b3..43fb5b9c7 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -2,10 +2,6 @@ import { documentReady } from './util/dom.js'; import { Docsify } from './Docsify.js'; import initGlobalAPI from './global-api.js'; -// TODO This global API and auto-running Docsify will be deprecated, and removed -// in a major release. Instead we'll tell users to use `new Docsify()` to create -// and manage their instance(s). - /** * Global API */ diff --git a/src/core/module.js b/src/core/module.js new file mode 100644 index 000000000..4206ebc24 --- /dev/null +++ b/src/core/module.js @@ -0,0 +1 @@ +export * from './Docsify.js'; diff --git a/src/core/module.min.js b/src/core/module.min.js new file mode 100644 index 000000000..c08b05d10 --- /dev/null +++ b/src/core/module.min.js @@ -0,0 +1,2 @@ +// This file exists for type declaration output. +export * from './Docsify.js'; diff --git a/tsconfig.json b/tsconfig.json index 14b09e6c9..1fc7ebd19 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,14 +12,5 @@ "resolveJsonModule": true, "outDir": "dist/" }, - "include": ["src/**/*.js"], - "exclude": [ - // "./**/*.test.js", - // "test/", - // "jest.config.js", - // "middleware.js", - // "playwright.config.js", - // "server.configs.js", - // "server.js" - ] + "include": ["src/**/*.js", "src/core/module.min.js"] } From 355469fbdb6261bd1d3aa8a6144f1f2a35e5b148 Mon Sep 17 00:00:00 2001 From: Joe Pea Date: Tue, 2 Apr 2024 00:23:45 -0700 Subject: [PATCH 4/5] add dist to eslintignore --- .eslintignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintignore b/.eslintignore index aa14c2187..6a93385a2 100644 --- a/.eslintignore +++ b/.eslintignore @@ -6,3 +6,4 @@ lib node_modules server.js themes +dist From 4a867ad92dd9500aeb4b1a216c4571fff2c11216 Mon Sep 17 00:00:00 2001 From: Joe Pea Date: Tue, 2 Apr 2024 00:38:48 -0700 Subject: [PATCH 5/5] fix typo --- docs/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.html b/docs/index.html index 9f874f4ec..fe81e400b 100644 --- a/docs/index.html +++ b/docs/index.html @@ -233,7 +233,7 @@ -->