From c95b2729afeaf42679a9905fea7369fd9a1ff19a Mon Sep 17 00:00:00 2001 From: Koy Zhuang <369491420@qq.com> Date: Wed, 26 Oct 2022 22:36:01 +0800 Subject: [PATCH] Revert "feat: Plugin error handling (#1742)" This reverts commit 7a0c50a5f4c609d40d11db772a28818fa49f310a. --- docs/configuration.md | 63 ++++---- docs/write-a-plugin.md | 256 ++++++++------------------------- src/core/Docsify.js | 15 +- src/core/config.js | 1 - src/core/init/lifecycle.js | 36 +---- test/e2e/configuration.test.js | 67 --------- test/e2e/plugins.test.js | 156 -------------------- 7 files changed, 99 insertions(+), 495 deletions(-) delete mode 100644 test/e2e/configuration.test.js delete mode 100644 test/e2e/plugins.test.js diff --git a/docs/configuration.md b/docs/configuration.md index 6f0c4e475b..9762b21438 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -365,7 +365,7 @@ window.$docsify = { ## autoHeader -- Type: `Boolean` +- type: `Boolean` If `loadSidebar` and `autoHeader` are both enabled, for each link in `_sidebar.md`, prepend a header to the page before converting it to HTML. See [#78](https://github.com/docsifyjs/docsify/issues/78). @@ -378,7 +378,7 @@ window.$docsify = { ## executeScript -- Type: `Boolean` +- type: `Boolean` Execute the script on the page. Only parse the first script tag ([demo](themes)). If Vue is present, it is turned on by default. @@ -400,8 +400,8 @@ Note that if you are running an external script, e.g. an embedded jsfiddle demo, ## nativeEmoji -- Type: `Boolean` -- Default: `false` +- type: `Boolean` +- default: `false` Render emoji shorthand codes using GitHub-style emoji images or platform-native emoji characters. @@ -453,8 +453,8 @@ To render shorthand codes as text, replace `:` characters with the `:` HTM ## noEmoji -- Type: `Boolean` -- Default: `false` +- type: `Boolean` +- default: `false` Disabled emoji parsing and render all emoji shorthand as text. @@ -492,7 +492,7 @@ To disable emoji parsing of individual shorthand codes, replace `:` characters w ## mergeNavbar -- Type: `Boolean` +- type: `Boolean` Navbar will be merged with the sidebar on smaller screens. @@ -504,7 +504,7 @@ window.$docsify = { ## formatUpdated -- Type: `String|Function` +- type: `String|Function` We can display the file update date through **{docsify-updated}** variable. And format it by `formatUpdated`. See https://github.com/lukeed/tinydate#patterns @@ -523,8 +523,8 @@ window.$docsify = { ## externalLinkTarget -- Type: `String` -- Default: `_blank` +- type: `String` +- default: `_blank` Target to open external links inside the markdown. Default `'_blank'` (new window/tab) @@ -536,8 +536,8 @@ window.$docsify = { ## cornerExternalLinkTarget -- Type:`String` -- Default:`_blank` +- type:`String` +- default:`_blank` Target to open external link at the top right corner. Default `'_blank'` (new window/tab) @@ -549,8 +549,8 @@ window.$docsify = { ## externalLinkRel -- Type: `String` -- Default: `noopener` +- type: `String` +- default: `noopener` Default `'noopener'` (no opener) prevents the newly opened external page (when [externalLinkTarget](#externallinktarget) is `'_blank'`) from having the ability to control our page. No `rel` is set when it's not `'_blank'`. See [this post](https://mathiasbynens.github.io/rel-noopener/) for more information about why you may want to use this option. @@ -562,8 +562,8 @@ window.$docsify = { ## routerMode -- Type: `String` -- Default: `hash` +- type: `String` +- default: `hash` ```js window.$docsify = { @@ -573,7 +573,7 @@ window.$docsify = { ## crossOriginLinks -- Type: `Array` +- type: `Array` When `routerMode: 'history'`, you may face cross-origin issues. See [#1379](https://github.com/docsifyjs/docsify/issues/1379). In Markdown content, there is a simple way to solve it: see extends Markdown syntax `Cross-Origin link` in [helpers](helpers.md). @@ -586,7 +586,7 @@ window.$docsify = { ## noCompileLinks -- Type: `Array` +- type: `Array` Sometimes we do not want docsify to handle our links. See [#203](https://github.com/docsifyjs/docsify/issues/203). We can skip compiling of certain links by specifying an array of strings. Each string is converted into to a regular expression (`RegExp`) and the _whole_ href of a link is matched against it. @@ -598,7 +598,7 @@ window.$docsify = { ## onlyCover -- Type: `Boolean` +- type: `Boolean` Only coverpage is loaded when visiting the home page. @@ -610,7 +610,7 @@ window.$docsify = { ## requestHeaders -- Type: `Object` +- type: `Object` Set the request resource headers. @@ -634,7 +634,7 @@ window.$docsify = { ## ext -- Type: `String` +- type: `String` Request file extension. @@ -646,7 +646,7 @@ window.$docsify = { ## fallbackLanguages -- Type: `Array` +- type: `Array` List of languages that will fallback to the default language when a page is requested and it doesn't exist for the given locale. @@ -664,7 +664,7 @@ window.$docsify = { ## notFoundPage -- Type: `Boolean` | `String` | `Object` +- type: `Boolean` | `String` | `Object` Load the `_404.md` file: @@ -697,8 +697,8 @@ window.$docsify = { ## topMargin -- Type: `Number` -- Default: `0` +- type: `Number` +- default: `0` Adds a space on top when scrolling the content page to reach the selected section. This is useful in case you have a _sticky-header_ layout and you want to align anchors to the end of your header. @@ -710,7 +710,7 @@ window.$docsify = { ## vueComponents -- Type: `Object` +- type: `Object` Creates and registers global [Vue components](https://vuejs.org/v2/guide/components.html). Components are specified using the component name as the key with an object containing Vue options as the value. Component `data` is unique for each instance and will not persist as users navigate the site. @@ -743,7 +743,7 @@ window.$docsify = { ## vueGlobalOptions -- Type: `Object` +- type: `Object` Specifies [Vue options](https://vuejs.org/v2/api/#Options-Data) for use with Vue content not explicitly mounted with [vueMounts](#mounting-dom-elements), [vueComponents](#components), or a [markdown script](#markdown-script). Changes to global `data` will persist and be reflected anywhere global references are used. @@ -777,7 +777,7 @@ window.$docsify = { ## vueMounts -- Type: `Object` +- type: `Object` Specifies DOM elements to mount as [Vue instances](https://vuejs.org/v2/guide/instance.html) and their associated options. Mount elements are specified using a [CSS selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors) as the key with an object containing Vue options as their value. Docsify will mount the first matching element in the main content area each time a new page is loaded. Mount element `data` is unique for each instance and will not persist as users navigate the site. @@ -808,10 +808,3 @@ window.$docsify = { {{ count }} - -## catchPluginErrors - -- Type: `Boolean` -- Default: `true` - -Determines if Docsify should handle uncaught _synchronous_ plugin errors automatically. This can prevent plugin errors from affecting docsify's ability to properly render live site content. diff --git a/docs/write-a-plugin.md b/docs/write-a-plugin.md index ad9b4bf70e..5495a87712 100644 --- a/docs/write-a-plugin.md +++ b/docs/write-a-plugin.md @@ -1,232 +1,85 @@ # Write a plugin -A docsify plugin is a function with the ability to execute custom JavaScript code at various stages of Docsify's lifecycle. +A plugin is simply a function that takes `hook` as an argument. The hook supports handling of asynchronous tasks. -## Setup - -Docsify plugins can be added directly to the `plugins` array. +## Full configuration ```js window.$docsify = { plugins: [ - function myPlugin1(hook, vm) { - // ... - }, - function myPlugin2(hook, vm) { - // ... - }, - ], -}; -``` - -Alternatively, a plugin can be stored in a separate file and "installed" using a standard ` -``` - -## Template - -Below is a plugin template with placeholders for all available lifecycle hooks. - -1. Copy the template -1. Modify the `myPlugin` name as appropriate -1. Add your plugin logic -1. Remove unused lifecycle hooks -1. Save the file as `docsify-plugin-[name].js` -1. Load your plugin using a standard ` diff --git a/src/core/Docsify.js b/src/core/Docsify.js index ad339311c4..ba6c54b88f 100644 --- a/src/core/Docsify.js +++ b/src/core/Docsify.js @@ -28,18 +28,9 @@ export class Docsify extends Fetch(Events(Render(Router(Lifecycle(Object))))) { } initPlugin() { - [].concat(this.config.plugins).forEach(fn => { - try { - isFn(fn) && fn(this._lifecycle, this); - } catch (err) { - if (this.config.catchPluginErrors) { - const errTitle = 'Docsify plugin error'; - console.error(errTitle, err); - } else { - throw err; - } - } - }); + [] + .concat(this.config.plugins) + .forEach(fn => isFn(fn) && fn(this._lifecycle, this)); } } diff --git a/src/core/config.js b/src/core/config.js index 5830656a93..d766291593 100644 --- a/src/core/config.js +++ b/src/core/config.js @@ -37,7 +37,6 @@ export default function (vm) { crossOriginLinks: [], relativePath: false, topMargin: 0, - catchPluginErrors: true, }, typeof window.$docsify === 'function' ? window.$docsify(vm) diff --git a/src/core/init/lifecycle.js b/src/core/init/lifecycle.js index 94a3981fe7..c04fc1a72c 100644 --- a/src/core/init/lifecycle.js +++ b/src/core/init/lifecycle.js @@ -29,7 +29,6 @@ export function Lifecycle(Base) { callHook(hookName, data, next = noop) { const queue = this._hooks[hookName]; - const catchPluginErrors = this.config.catchPluginErrors; const step = function (index) { const hookFn = queue[index]; @@ -37,38 +36,15 @@ export function Lifecycle(Base) { if (index >= queue.length) { next(data); } else if (typeof hookFn === 'function') { - const errTitle = 'Docsify plugin error'; - if (hookFn.length === 2) { - try { - hookFn(data, result => { - data = result; - step(index + 1); - }); - } catch (err) { - if (catchPluginErrors) { - console.error(errTitle, err); - } else { - throw err; - } - + hookFn(data, result => { + data = result; step(index + 1); - } + }); } else { - try { - const result = hookFn(data); - - data = result === undefined ? data : result; - step(index + 1); - } catch (err) { - if (catchPluginErrors) { - console.error(errTitle, err); - } else { - throw err; - } - - step(index + 1); - } + const result = hookFn(data); + data = result === undefined ? data : result; + step(index + 1); } } else { step(index + 1); diff --git a/test/e2e/configuration.test.js b/test/e2e/configuration.test.js deleted file mode 100644 index 8aa3c5f083..0000000000 --- a/test/e2e/configuration.test.js +++ /dev/null @@ -1,67 +0,0 @@ -const docsifyInit = require('../helpers/docsify-init'); -const { test, expect } = require('./fixtures/docsify-init-fixture'); - -test.describe('Configuration options', () => { - test('catchPluginErrors:true (handles uncaught errors)', async ({ page }) => { - let consoleMsg, errorMsg; - - page.on('console', msg => (consoleMsg = msg.text())); - page.on('pageerror', err => (errorMsg = err.message)); - - await docsifyInit({ - config: { - catchPluginErrors: true, - plugins: [ - function (hook, vm) { - hook.init(function () { - // eslint-disable-next-line no-undef - fail(); - }); - hook.beforeEach(function (markdown) { - return `${markdown}\n\nbeforeEach`; - }); - }, - ], - }, - markdown: { - homepage: '# Hello World', - }, - // _logHTML: true, - }); - - const mainElm = page.locator('#main'); - - expect(errorMsg).toBeUndefined(); - expect(consoleMsg).toContain('Docsify plugin error'); - await expect(mainElm).toContainText('Hello World'); - await expect(mainElm).toContainText('beforeEach'); - }); - - test('catchPluginErrors:false (throws uncaught errors)', async ({ page }) => { - let consoleMsg, errorMsg; - - page.on('console', msg => (consoleMsg = msg.text())); - page.on('pageerror', err => (errorMsg = err.message)); - - await docsifyInit({ - config: { - catchPluginErrors: false, - plugins: [ - function (hook, vm) { - hook.ready(function () { - // eslint-disable-next-line no-undef - fail(); - }); - }, - ], - }, - markdown: { - homepage: '# Hello World', - }, - // _logHTML: true, - }); - - expect(consoleMsg).toBeUndefined(); - expect(errorMsg).toContain('fail'); - }); -}); diff --git a/test/e2e/plugins.test.js b/test/e2e/plugins.test.js deleted file mode 100644 index 92f00ca568..0000000000 --- a/test/e2e/plugins.test.js +++ /dev/null @@ -1,156 +0,0 @@ -const docsifyInit = require('../helpers/docsify-init'); -const { test, expect } = require('./fixtures/docsify-init-fixture'); - -test.describe('Plugins', () => { - test('Hook order', async ({ page }) => { - const consoleMsgs = []; - const expectedMsgs = [ - 'init', - 'mounted', - 'beforeEach-async', - 'beforeEach', - // 'afterEach-async', - 'afterEach', - 'doneEach', - 'ready', - ]; - - page.on('console', msg => consoleMsgs.push(msg.text())); - - await docsifyInit({ - config: { - plugins: [ - function (hook, vm) { - hook.init(function () { - console.log('init'); - }); - - hook.mounted(function () { - console.log('mounted'); - }); - - hook.beforeEach(function (markdown, next) { - setTimeout(function () { - console.log('beforeEach-async'); - next(markdown); - }, 100); - }); - - hook.beforeEach(function (markdown) { - console.log('beforeEach'); - return markdown; - }); - - // FIXME: https://github.com/docsifyjs/docsify/issues/449 - // hook.afterEach(function (html, next) { - // setTimeout(function () { - // console.log('afterEach-async'); - // next(html); - // }, 100); - // }); - - hook.afterEach(function (html) { - console.log('afterEach'); - return html; - }); - - hook.doneEach(function () { - console.log('doneEach'); - }); - - hook.ready(function () { - console.log('ready'); - }); - }, - ], - }, - markdown: { - homepage: '# Hello World', - }, - // _logHTML: true, - }); - - expect(consoleMsgs).toEqual(expectedMsgs); - }); - - test('beforeEach() return value', async ({ page }) => { - await docsifyInit({ - config: { - plugins: [ - function (hook, vm) { - hook.beforeEach(function (markdown) { - return 'beforeEach'; - }); - }, - ], - }, - // _logHTML: true, - }); - - await expect(page.locator('#main')).toContainText('beforeEach'); - }); - - test('beforeEach() async return value', async ({ page }) => { - await docsifyInit({ - config: { - plugins: [ - function (hook, vm) { - hook.beforeEach(function (markdown, next) { - setTimeout(function () { - next('beforeEach'); - }, 100); - }); - }, - ], - }, - markdown: { - homepage: '# Hello World', - }, - // _logHTML: true, - }); - - await expect(page.locator('#main')).toContainText('beforeEach'); - }); - - test('afterEach() return value', async ({ page }) => { - await docsifyInit({ - config: { - plugins: [ - function (hook, vm) { - hook.afterEach(function (html) { - return '

afterEach

'; - }); - }, - ], - }, - markdown: { - homepage: '# Hello World', - }, - // _logHTML: true, - }); - - await expect(page.locator('#main')).toContainText('afterEach'); - }); - - test('afterEach() async return value', async ({ page }) => { - await docsifyInit({ - config: { - plugins: [ - function (hook, vm) { - hook.afterEach(function (html, next) { - setTimeout(function () { - next('

afterEach

'); - }, 100); - }); - }, - ], - }, - markdown: { - homepage: '# Hello World', - }, - // _logHTML: true, - }); - - await expect(page.locator('#main')).toContainText('afterEach'); - }); -});