diff --git a/docs/index.html b/docs/index.html index 11d968660..0693aba3a 100644 --- a/docs/index.html +++ b/docs/index.html @@ -162,5 +162,6 @@ } })(); + diff --git a/docs/vue.md b/docs/vue.md index 2b3904b19..5e62363d0 100644 --- a/docs/vue.md +++ b/docs/vue.md @@ -1,99 +1,137 @@ -# Compatible with Vue +# Vue compatibility -You can write Vue components directly in the Markdown file, and it will be parsed. You can use this feature to write vue demo and documentation together. +Docsify allows Vue [v2.x](https://vuejs.org) and [v3.x](https://v3.vuejs.org) components to be added directly to you Markdown files. These components can greatly simplify working with data and adding reactivity to your content. -## Basic usage +To get started, load either the production or development version of Vue in your `index.html`: -Load the Vue in `./index.html`. +#### Vue 2.x ```html - - + + - - - + + ``` -Then you can immediately write Vue code at Markdown file. `new Vue({ el: '#main' })` script is executed by default to create instance. +#### Vue 3.x -*README.md* +```html + + + + + +``` -````markdown -# Vue guide +## Basic rendering -`v-for` usage. +Docsify will automatically render basic Vue content that does not require `data`, `methods`, or other instance features. -```html +```markdown ``` +The HTML above will render the following: + -```` -You can manually initialize a Vue instance. +## Advanced usage + +Vue components and templates that require `data`, `methods`, computed properties, lifecycle hooks, etc. require manually creating a new `Vue()` instance within a ` ``` -!> In a Markdown file, only the script within the first script tag is executed. +#### Vue 3.x -## Combine Vuep to write playground +```markdown + +``` -[Vuep](https://github.com/QingWei-Li/vuep) is a component for rendering Vue components with live editor and preview. Supports Vue component spec and JSX. +The HTML & JavaScript above will render the following: -*index.html* + -```html - - - - - - - - - - - - -``` +
+

{{ message }}

-*README.md* -```markdown -# Vuep + - + + {{ counter }} + +
- + }); -``` - -?> Example Refer to the [Vuep documentation](https://qingwei-li.github.io/vuep/). diff --git a/jest.config.js b/jest.config.js index d94e85c54..8cd635e35 100644 --- a/jest.config.js +++ b/jest.config.js @@ -4,7 +4,7 @@ const { globals: serverGlobals } = require('./test/config/server.js'); const sharedConfig = { errorOnDeprecated: true, globals: { - ...serverGlobals, // BLANK_URL, DOCS_URL, LIB_URL, TEST_HOST + ...serverGlobals, // BLANK_URL, DOCS_URL, LIB_URL, NODE_MODULES_URL, TEST_HOST DOCS_PATH: path.resolve(__dirname, 'docs'), LIB_PATH: path.resolve(__dirname, 'lib'), SRC_PATH: path.resolve(__dirname, 'src'), diff --git a/package-lock.json b/package-lock.json index 584c5805a..1ba67dc59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4340,6 +4340,79 @@ } } }, + "@vue/compiler-core": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.0.0.tgz", + "integrity": "sha512-XqPC7vdv4rFE77S71oCHmT1K4Ks3WE2Gi6Lr4B5wn0Idmp+NyQQBUHsCNieMDRiEpgtJrw+yOHslrsV0AfAsfQ==", + "dev": true, + "requires": { + "@babel/parser": "^7.11.5", + "@babel/types": "^7.11.5", + "@vue/shared": "3.0.0", + "estree-walker": "^2.0.1", + "source-map": "^0.6.1" + }, + "dependencies": { + "estree-walker": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.1.tgz", + "integrity": "sha512-tF0hv+Yi2Ot1cwj9eYHtxC0jB9bmjacjQs6ZBTj82H8JwUywFuc+7E83NWfNMwHXZc11mjfFcVXPe9gEP4B8dg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@vue/compiler-dom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.0.0.tgz", + "integrity": "sha512-ukDEGOP8P7lCPyStuM3F2iD5w2QPgUu2xwCW2XNeqPjFKIlR2xMsWjy4raI/cLjN6W16GtlMFaZdK8tLj5PRog==", + "dev": true, + "requires": { + "@vue/compiler-core": "3.0.0", + "@vue/shared": "3.0.0" + } + }, + "@vue/reactivity": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.0.0.tgz", + "integrity": "sha512-mEGkztGQrAPZRhV7C6PorrpT3+NtuA4dY2QjMzzrW31noKhssWTajRZTwpLF39NBRrF5UU6cp9+1I0FfavMgEQ==", + "dev": true, + "requires": { + "@vue/shared": "3.0.0" + } + }, + "@vue/runtime-core": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.0.0.tgz", + "integrity": "sha512-3ABMLeA0ZbeVNLbGGLXr+pNUwqXILOqz8WCVGfDWwQb+jW114Cm8djOHVVDoqdvRETQvDf8yHSUmpKHZpQuTkA==", + "dev": true, + "requires": { + "@vue/reactivity": "3.0.0", + "@vue/shared": "3.0.0" + } + }, + "@vue/runtime-dom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.0.0.tgz", + "integrity": "sha512-f312n5w9gK6mVvkDSj6/Xnot1XjlKXzFBYybmoy6ahAVC8ExbQ+LOWti1IZM/adU8VMNdKaw7Q53Hxz3y5jX8g==", + "dev": true, + "requires": { + "@vue/runtime-core": "3.0.0", + "@vue/shared": "3.0.0", + "csstype": "^2.6.8" + } + }, + "@vue/shared": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.0.0.tgz", + "integrity": "sha512-4XWL/avABGxU2E2ZF1eZq3Tj7fvksCMssDZUHOykBIMmh5d+KcAnQMC5XHMhtnA0NAvktYsA2YpdsVwVmhWzvA==", + "dev": true + }, "@zkochan/cmd-shim": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@zkochan/cmd-shim/-/cmd-shim-3.1.0.tgz", @@ -6770,6 +6843,12 @@ } } }, + "csstype": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", + "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==", + "dev": true + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -19236,6 +19315,23 @@ "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", "dev": true }, + "vue2": { + "version": "npm:vue@2.6.12", + "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.12.tgz", + "integrity": "sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg==", + "dev": true + }, + "vue3": { + "version": "npm:vue@3.0.0", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.0.0.tgz", + "integrity": "sha512-ZMrAARZ32sGIaYKr7Fk2GZEBh/VhulSrGxcGBiAvbN4fhjl3tuJyNFbbbLFqGjndbLoBW66I2ECq8ICdvkKdJw==", + "dev": true, + "requires": { + "@vue/compiler-dom": "3.0.0", + "@vue/runtime-dom": "3.0.0", + "@vue/shared": "3.0.0" + } + }, "w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", diff --git a/package.json b/package.json index 7c3d99f16..2572f7793 100644 --- a/package.json +++ b/package.json @@ -103,6 +103,8 @@ "rollup-plugin-uglify": "^6.0.4", "serve-handler": "^6.1.2", "stylus": "^0.54.5", + "vue2": "npm:vue@^2.6.12", + "vue3": "npm:vue@^3.0.0", "xhr-mock": "^2.5.1" }, "keywords": [ diff --git a/src/core/render/index.js b/src/core/render/index.js index 4b7a08e02..068f66cd6 100644 --- a/src/core/render/index.js +++ b/src/core/render/index.js @@ -26,9 +26,7 @@ function executeScript() { return false; } - setTimeout(_ => { - window.__EXECUTE_RESULT__ = new Function(code)(); - }, 0); + new Function(code)(); } function formatUpdated(html, updated, fn) { @@ -48,22 +46,56 @@ function renderMain(html) { } this._renderTo('.markdown-section', html); + // Render sidebar with the TOC !this.config.loadSidebar && this._renderSidebar(); - // Execute script + // Execute markdown + `, }, - }); + vue3: { + markdown: ` +
+ + {{ counter }} +
+ + + `, + }, + }; + + for (const vueURL of vueURLs) { + const vueVersion = vueURL.match(/vue(\d+)/)[1]; // vue2|vue3 + const vueData = testData[`vue${vueVersion}`]; + + for (const executeScript of ['unspecified', true]) { + test(`handles Vue v${vueVersion}.x advanced usage when executeScript is ${executeScript}`, async () => { + const docsifyInitConfig = { + markdown: { + homepage: vueData.markdown, + }, + scriptURLs: vueURL, + }; + + if (executeScript !== 'unspecified') { + docsifyInitConfig.config = { + executeScript, + }; + } + + await docsifyInit(docsifyInitConfig); + + await expect(page).toEqualText('#test span', '0'); + await page.click('#test button'); + await expect(page).toEqualText('#test span', '1'); + }); + } + + test(`handles Vue v${vueVersion}.x advanced usage when executeScript is false`, async () => { + const docsifyInitConfig = { + config: { + executeScript: false, + }, + markdown: { + homepage: vueData.markdown, + }, + scriptURLs: vueURL, + }; - const testResult = await page.textContent('#test'); + await docsifyInit(docsifyInitConfig); - expect(testResult).toBe('test{{ i }}'); + const textContent = await page.textContent('#test span'); + expect(textContent).toBe(''); + }); + } }); });