diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d630958..387e81e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,47 @@ +## [2.0.0-alpha.4](https://github.com/vuejs/vitepress/compare/v2.0.0-alpha.3...v2.0.0-alpha.4) (2025-03-09) + +### Bug Fixes + +- **build/regression:** langAlias not working ([06ae2bf](https://github.com/vuejs/vitepress/commit/06ae2bf3a4ee02351530b0bd055e577ca6509d62)), closes [#4581](https://github.com/vuejs/vitepress/issues/4581) +- don't hardcode `tabindex` attr in table renderer ([#4082](https://github.com/vuejs/vitepress/issues/4082)) ([aadc517](https://github.com/vuejs/vitepress/commit/aadc517c69fb239bdda99173bbc123ace567484b)) +- hmr not working for watched files in path loaders ([e271695](https://github.com/vuejs/vitepress/commit/e271695d716247455ca620948f814e6c8ca0e3c4)), closes [#4525](https://github.com/vuejs/vitepress/issues/4525) +- ignore non-text content in permalink generation and fix types of markdown.config ([a8a1800](https://github.com/vuejs/vitepress/commit/a8a1800ae578be88027aa4ec7561ada4d055b888)) +- prevent reload on first server start in fresh installations ([d8a884e](https://github.com/vuejs/vitepress/commit/d8a884ed0f754523765058a70149cdbaf6942341)) +- properly merge classes in custom containers ([#4128](https://github.com/vuejs/vitepress/issues/4128)) ([8aad617](https://github.com/vuejs/vitepress/commit/8aad617446c03d39a65a0b21e9fce43bc484af1e)) +- rebuild dynamic routes cache on server restart ([9f54714](https://github.com/vuejs/vitepress/commit/9f54714e7db69fd4902f1917f927456c71b5a292)), closes [#4525](https://github.com/vuejs/vitepress/issues/4525) + +### Features + +- allow matching region end in snippets without tag ([#4287](https://github.com/vuejs/vitepress/issues/4287)) ([1a2f81d](https://github.com/vuejs/vitepress/commit/1a2f81de4d6549dd1adf86ae131d1a861158bd2d)) +- improve region regexes for snippet plugin ([1a6684c](https://github.com/vuejs/vitepress/commit/1a6684cf1054d326bc1dd6eeb9fb78b150ac2b2a)) +- support using header anchors in markdown file inclusion ([#4608](https://github.com/vuejs/vitepress/issues/4608)) ([b99d512](https://github.com/vuejs/vitepress/commit/b99d5123c9b2afdc7461089e03476c34d7816faf)), closes [#4375](https://github.com/vuejs/vitepress/issues/4375) [#4382](https://github.com/vuejs/vitepress/issues/4382) + +## [2.0.0-alpha.3](https://github.com/vuejs/vitepress/compare/v2.0.0-alpha.2...v2.0.0-alpha.3) (2025-02-24) + +### Bug Fixes + +- **build:** `--minify` not working as documented ([9b5c037](https://github.com/vuejs/vitepress/commit/9b5c0377cd3474447c84b2901801287f3caf3d82)), closes [#4523](https://github.com/vuejs/vitepress/issues/4523) +- **build:** deterministic code group ids ([#4565](https://github.com/vuejs/vitepress/issues/4565)) ([b930b8d](https://github.com/vuejs/vitepress/commit/b930b8d5310f1691d8d9f009f45b70122e4ce800)) +- **markdown:** include content of all tokens in heading ids ([68dff2a](https://github.com/vuejs/vitepress/commit/68dff2af8547ae70f6622ac826affd76f2f6378e)), closes [#4561](https://github.com/vuejs/vitepress/issues/4561) +- **client:** set correct oldURL and newURL for hashchange ([#4573](https://github.com/vuejs/vitepress/issues/4573)) ([d1f2afd](https://github.com/vuejs/vitepress/commit/d1f2afdf0fbb022f12cc12295723b3b7c7ef5cb1)) +- **theme:** allow interactions behind scroll shadow ([#4537](https://github.com/vuejs/vitepress/issues/4537)) ([091d584](https://github.com/vuejs/vitepress/commit/091d5840ae15b64e04e8c07fbc0263a2749571bd)) +- **theme:** code block contrast ratio ([#4487](https://github.com/vuejs/vitepress/issues/4487)) ([5dccaee](https://github.com/vuejs/vitepress/commit/5dccaeef055beb109919f8990032975a0d630384)) +- **build:** fix flaky embedded languages highlighting ([#4566](https://github.com/vuejs/vitepress/issues/4566)) ([1969cf4](https://github.com/vuejs/vitepress/commit/1969cf4f3b93ad105595e4e2f8b030b04eb1c975)) + +### Features + +- **cli:** support custom `srcDir` ([#4270](https://github.com/vuejs/vitepress/issues/4270)) ([518c094](https://github.com/vuejs/vitepress/commit/518c0945f159aae679ef710bb48ae3ab3891cc9f)) +- **cli:** support custom npm scripts prefix ([#4271](https://github.com/vuejs/vitepress/issues/4271)) ([e5a0ee8](https://github.com/vuejs/vitepress/commit/e5a0ee8161752a77c5bb9546245a940cb5f28fb8)) +- **build:** dynamic routes plugin overhaul ([#4525](https://github.com/vuejs/vitepress/issues/4525)) ([a62ea6a](https://github.com/vuejs/vitepress/commit/a62ea6a832a33b756642b24ad5d38c248e08b554)) +- **build:** update to shiki v3 ([#4571](https://github.com/vuejs/vitepress/issues/4571)) ([52c2aa1](https://github.com/vuejs/vitepress/commit/52c2aa178d4b3fa98b863cf28f0ccf6d2aabcd93)) +- **build:** use `markdown-it-async`, remove `synckit` ([#4507](https://github.com/vuejs/vitepress/issues/4507)) ([8062235](https://github.com/vuejs/vitepress/commit/80622356f1d648577ee47ee3a44b04bb015ee462)) + +### BREAKING CHANGES + +- markdown-it-async is used instead of markdown-it. If you're using custom content renderer for local search, you'll need to do `await md.renderAsync` instead of `md.render`. +- Internals are modified a bit to better support vite 6 and handle HMR more correctly. For most users this won't need any change on their side. +- shiki is upgraded to v3. There shouldn't be any breaking change but if you see any issue, please report it. + ## [2.0.0-alpha.2](https://github.com/vuejs/vitepress/compare/v2.0.0-alpha.1...v2.0.0-alpha.2) (2025-01-23) ### Bug Fixes diff --git a/__tests__/e2e/.vitepress/config.ts b/__tests__/e2e/.vitepress/config.ts index 43dbfa84..121761e7 100644 --- a/__tests__/e2e/.vitepress/config.ts +++ b/__tests__/e2e/.vitepress/config.ts @@ -173,5 +173,13 @@ export default defineConfig({ } } } + }, + vite: { + server: { + watch: { + usePolling: true, + interval: 100 + } + } } }) diff --git a/__tests__/e2e/dynamic-routes/[id].paths.ts b/__tests__/e2e/dynamic-routes/[id].paths.ts index 3eca4d91..12a8bc32 100644 --- a/__tests__/e2e/dynamic-routes/[id].paths.ts +++ b/__tests__/e2e/dynamic-routes/[id].paths.ts @@ -1,8 +1,14 @@ -export default { - async paths() { - return [ - { params: { id: 'foo' }, content: `# Foo` }, - { params: { id: 'bar' }, content: `# Bar` } - ] +import { defineRoutes } from 'vitepress' +import paths from './paths' + +export default defineRoutes({ + async paths(watchedFiles: string[]) { + // console.log('watchedFiles', watchedFiles) + return paths + }, + watch: ['**/data-loading/**/*.json'], + async transformPageData(pageData) { + // console.log('transformPageData', pageData.filePath) + pageData.title += ' - transformed' } -} +}) diff --git a/__tests__/e2e/dynamic-routes/paths.ts b/__tests__/e2e/dynamic-routes/paths.ts new file mode 100644 index 00000000..5adb0ed4 --- /dev/null +++ b/__tests__/e2e/dynamic-routes/paths.ts @@ -0,0 +1,4 @@ +export default [ + { params: { id: 'foo' }, content: `# Foo` }, + { params: { id: 'bar' }, content: `# Bar` } +] diff --git a/__tests__/e2e/markdown-extensions/header-include.md b/__tests__/e2e/markdown-extensions/header-include.md new file mode 100644 index 00000000..70fac23b --- /dev/null +++ b/__tests__/e2e/markdown-extensions/header-include.md @@ -0,0 +1,27 @@ +# header 1 + +header 1 content + +## header 1.1 + +header 1.1 content + +### header 1.1.1 + +header 1.1.1 content + +### header 1.1.2 + +header 1.1.2 content + +## header 1.2 + +header 1.2 content + +### header 1.2.1 + +header 1.2.1 content + +### header 1.2.2 + +header 1.2.2 content diff --git a/__tests__/e2e/markdown-extensions/index.md b/__tests__/e2e/markdown-extensions/index.md index 855803f2..3446b4ef 100644 --- a/__tests__/e2e/markdown-extensions/index.md +++ b/__tests__/e2e/markdown-extensions/index.md @@ -213,6 +213,10 @@ export default config +## Markdown File Inclusion with Header + + + ## Image Lazy Loading -![vitepress logo](/vitepress.png) \ No newline at end of file +![vitepress logo](/vitepress.png) diff --git a/__tests__/e2e/markdown-extensions/markdown-extensions.test.ts b/__tests__/e2e/markdown-extensions/markdown-extensions.test.ts index e49a137f..839f953c 100644 --- a/__tests__/e2e/markdown-extensions/markdown-extensions.test.ts +++ b/__tests__/e2e/markdown-extensions/markdown-extensions.test.ts @@ -64,8 +64,61 @@ describe('Emoji', () => { describe('Table of Contents', () => { test('render toc', async () => { const items = page.locator('#table-of-contents + nav ul li') - const count = await items.count() - expect(count).toBe(44) + expect( + await items.evaluateAll((elements) => + elements.map((el) => el.childNodes[0].textContent) + ) + ).toMatchInlineSnapshot(` + [ + "Links", + "Internal Links", + "External Links", + "GitHub-Style Tables", + "Emoji", + "Table of Contents", + "Custom Containers", + "Default Title", + "Custom Title", + "Line Highlighting in Code Blocks", + "Single Line", + "Multiple single lines, ranges", + "Comment Highlight", + "Line Numbers", + "Import Code Snippets", + "Basic Code Snippet", + "Specify Region", + "With Other Features", + "Code Groups", + "Basic Code Group", + "With Other Features", + "Markdown File Inclusion", + "Region", + "Markdown At File Inclusion", + "Markdown Nested File Inclusion", + "Region", + "After Foo", + "Sub sub", + "Sub sub sub", + "Markdown File Inclusion with Range", + "Region", + "Markdown File Inclusion with Range without Start", + "Region", + "Markdown File Inclusion with Range without End", + "Region", + "Markdown At File Region Snippet", + "Region Snippet", + "Markdown At File Range Region Snippet", + "Range Region Line 2", + "Markdown At File Range Region Snippet without start", + "Range Region Line 1", + "Markdown At File Range Region Snippet without end", + "Range Region Line 3", + "Markdown File Inclusion with Header", + "header 1.1.1", + "header 1.1.2", + "Image Lazy Loading", + ] + `) }) }) diff --git a/__tests__/unit/node/markdown/plugins/snippet.test.ts b/__tests__/unit/node/markdown/plugins/snippet.test.ts index 0ae97dd2..aa940784 100644 --- a/__tests__/unit/node/markdown/plugins/snippet.test.ts +++ b/__tests__/unit/node/markdown/plugins/snippet.test.ts @@ -1,4 +1,9 @@ -import { dedent, rawPathToToken } from 'node/markdown/plugins/snippet' +import { + dedent, + findRegion, + rawPathToToken +} from 'node/markdown/plugins/snippet' +import { expect } from 'vitest' const removeEmptyKeys = >(obj: T) => { return Object.fromEntries( @@ -94,9 +99,228 @@ describe('node/markdown/plugins/snippet', () => { }) }) - test('rawPathToToken', () => { - rawPathTokenMap.forEach(([rawPath, token]) => { + describe('rawPathToToken', () => { + test.each(rawPathTokenMap)('%s', (rawPath, token) => { expect(removeEmptyKeys(rawPathToToken(rawPath))).toEqual(token) }) }) + + describe('findRegion', () => { + it('returns null when no region markers are present', () => { + const lines = ['function foo() {', ' console.log("hello");', '}'] + expect(findRegion(lines, 'foo')).toBeNull() + }) + + it('ignores non-matching region names', () => { + const lines = [ + '// #region regionA', + 'some code here', + '// #endregion regionA' + ] + expect(findRegion(lines, 'regionC')).toBeNull() + }) + + it('returns null if a region start marker exists without a matching end marker', () => { + const lines = [ + '// #region missingEnd', + 'console.log("inside region");', + 'console.log("still inside");' + ] + expect(findRegion(lines, 'missingEnd')).toBeNull() + }) + + it('returns null if an end marker exists without a preceding start marker', () => { + const lines = [ + '// #endregion ghostRegion', + 'console.log("stray end marker");' + ] + expect(findRegion(lines, 'ghostRegion')).toBeNull() + }) + + it('detects C#/JavaScript style region markers with matching tags', () => { + const lines = [ + 'Console.WriteLine("Before region");', + '#region hello', + 'Console.WriteLine("Hello, World!");', + '#endregion hello', + 'Console.WriteLine("After region");' + ] + const result = findRegion(lines, 'hello') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + 'Console.WriteLine("Hello, World!");' + ) + } + }) + + it('detects region markers even when the end marker omits the region name', () => { + const lines = [ + 'Console.WriteLine("Before region");', + '#region hello', + 'Console.WriteLine("Hello, World!");', + '#endregion', + 'Console.WriteLine("After region");' + ] + const result = findRegion(lines, 'hello') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + 'Console.WriteLine("Hello, World!");' + ) + } + }) + + it('handles indented region markers correctly', () => { + const lines = [ + ' Console.WriteLine("Before region");', + ' #region hello', + ' Console.WriteLine("Hello, World!");', + ' #endregion hello', + ' Console.WriteLine("After region");' + ] + const result = findRegion(lines, 'hello') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + ' Console.WriteLine("Hello, World!");' + ) + } + }) + + it('detects TypeScript style region markers', () => { + const lines = [ + 'let regexp: RegExp[] = [];', + '// #region foo', + 'let start = -1;', + '// #endregion foo' + ] + const result = findRegion(lines, 'foo') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + 'let start = -1;' + ) + } + }) + + it('detects CSS style region markers', () => { + const lines = [ + '.body-content {', + '/* #region foo */', + ' padding-left: 15px;', + '/* #endregion foo */', + ' padding-right: 15px;', + '}' + ] + const result = findRegion(lines, 'foo') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + ' padding-left: 15px;' + ) + } + }) + + it('detects HTML style region markers', () => { + const lines = [ + '
Some content
', + '', + '

Hello world

', + '', + '
Other content
' + ] + const result = findRegion(lines, 'foo') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + '

Hello world

' + ) + } + }) + + it('detects Visual Basic style region markers (with case-insensitive "End")', () => { + const lines = [ + 'Console.WriteLine("VB")', + '#Region VBRegion', + ' Console.WriteLine("Inside region")', + '#End Region VBRegion', + 'Console.WriteLine("Done")' + ] + const result = findRegion(lines, 'VBRegion') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + ' Console.WriteLine("Inside region")' + ) + } + }) + + it('detects Bat style region markers', () => { + const lines = ['::#region foo', 'echo off', '::#endregion foo'] + const result = findRegion(lines, 'foo') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + 'echo off' + ) + } + }) + + it('detects C/C++ style region markers using #pragma', () => { + const lines = [ + '#pragma region foo', + 'int a = 1;', + '#pragma endregion foo' + ] + const result = findRegion(lines, 'foo') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + 'int a = 1;' + ) + } + }) + + it('returns the first complete region when multiple regions exist', () => { + const lines = [ + '// #region foo', + 'first region content', + '// #endregion foo', + '// #region foo', + 'second region content', + '// #endregion foo' + ] + const result = findRegion(lines, 'foo') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + 'first region content' + ) + } + }) + + it('handles nested regions with different names properly', () => { + const lines = [ + '// #region foo', + "console.log('line before nested');", + '// #region bar', + "console.log('nested content');", + '// #endregion bar', + '// #endregion foo' + ] + const result = findRegion(lines, 'foo') + expect(result).not.toBeNull() + if (result) { + const extracted = lines.slice(result.start, result.end).join('\n') + const expected = [ + "console.log('line before nested');", + '// #region bar', + "console.log('nested content');", + '// #endregion bar' + ].join('\n') + expect(extracted).toBe(expected) + } + }) + }) }) diff --git a/__tests__/unit/node/utils/moduleGraph.test.ts b/__tests__/unit/node/utils/moduleGraph.test.ts new file mode 100644 index 00000000..9b3db9e5 --- /dev/null +++ b/__tests__/unit/node/utils/moduleGraph.test.ts @@ -0,0 +1,72 @@ +import { ModuleGraph } from 'node/utils/moduleGraph' + +describe('node/utils/moduleGraph', () => { + let graph: ModuleGraph + + beforeEach(() => { + graph = new ModuleGraph() + }) + + it('should correctly delete a module and its dependents', () => { + graph.add('A', ['B', 'C']) + graph.add('B', ['D']) + graph.add('C', []) + graph.add('D', []) + + expect(graph.delete('D')).toEqual(new Set(['D', 'B', 'A'])) + }) + + it('should handle shared dependencies correctly', () => { + graph.add('A', ['B', 'C']) + graph.add('B', ['D']) + graph.add('C', ['D']) // Shared dependency + graph.add('D', []) + + expect(graph.delete('D')).toEqual(new Set(['A', 'B', 'C', 'D'])) + }) + + it('merges dependencies correctly', () => { + // Add module A with dependency B + graph.add('A', ['B']) + // Merge new dependency C into module A (B should remain) + graph.add('A', ['C']) + + // Deleting B should remove A as well, since A depends on B. + expect(graph.delete('B')).toEqual(new Set(['B', 'A'])) + }) + + it('handles cycles gracefully', () => { + // Create a cycle: A -> B, B -> C, C -> A. + graph.add('A', ['B']) + graph.add('B', ['C']) + graph.add('C', ['A']) + + // Deleting any module in the cycle should delete all modules in the cycle. + expect(graph.delete('A')).toEqual(new Set(['A', 'B', 'C'])) + }) + + it('cleans up dependencies when deletion', () => { + // Setup A -> B relationship. + graph.add('A', ['B']) + graph.add('B', []) + + // Deleting B should remove both B and A from the graph. + expect(graph.delete('B')).toEqual(new Set(['B', 'A'])) + + // After deletion, add modules again. + graph.add('C', []) + graph.add('A', ['C']) // Now A depends only on C. + + expect(graph.delete('C')).toEqual(new Set(['C', 'A'])) + }) + + it('handles independent modules', () => { + // Modules with no dependencies. + graph.add('X', []) + graph.add('Y', []) + + // Deletion of one should only remove that module. + expect(graph.delete('X')).toEqual(new Set(['X'])) + expect(graph.delete('Y')).toEqual(new Set(['Y'])) + }) +}) diff --git a/docs/en/guide/markdown.md b/docs/en/guide/markdown.md index cf052919..88729f3e 100644 --- a/docs/en/guide/markdown.md +++ b/docs/en/guide/markdown.md @@ -897,6 +897,53 @@ You can also use a [VS Code region](https://code.visualstudio.com/docs/editor/co Note that this does not throw errors if your file is not present. Hence, when using this feature make sure that the contents are being rendered as expected. ::: +Instead of VS Code regions, you can also use header anchors to include a specific section of the file. For example, if you have a header in your markdown file like this: + +```md +## My Base Section + +Some content here. + +### My Sub Section + +Some more content here. + +## Another Section + +Content outside `My Base Section`. +``` + +You can include the `My Base Section` section like this: + +```md +## My Extended Section + +``` + +**Equivalent code** + +```md +## My Extended Section + +Some content here. + +### My Sub Section + +Some more content here. +``` + +Here, `my-base-section` is the generated id of the heading element. In case it's not easily guessable, you can open the part file in your browser and click on the heading anchor (`#` symbol left to the heading when hovered) to see the id in the URL bar. Or use browser dev tools to inspect the element. Alternatively, you can also specify the id to the part file like this: + +```md +## My Base Section {#custom-id} +``` + +and include it like this: + +```md + +``` + ## Math Equations This is currently opt-in. To enable it, you need to install `markdown-it-mathjax3` and set `markdown.math` to `true` in your config file: diff --git a/docs/en/guide/using-vue.md b/docs/en/guide/using-vue.md index 5a82dc75..8420ea7f 100644 --- a/docs/en/guide/using-vue.md +++ b/docs/en/guide/using-vue.md @@ -288,4 +288,4 @@ Vue provides IntelliSense support out of the box via the [Vue - Official VS Code "vue.server.includeLanguages": ["vue", "markdown"] } ``` -::: \ No newline at end of file +::: diff --git a/docs/es/guide/using-vue.md b/docs/es/guide/using-vue.md index 9d18d92d..0131cc76 100644 --- a/docs/es/guide/using-vue.md +++ b/docs/es/guide/using-vue.md @@ -286,4 +286,4 @@ Vue ofrece soporte para IntelliSense de forma predeterminada mediante el [Plugin "vue.server.includeLanguages": ["vue", "markdown"] } ``` -::: \ No newline at end of file +::: diff --git a/docs/es/reference/default-theme-sidebar.md b/docs/es/reference/default-theme-sidebar.md index 05dd42f3..cf2af04b 100644 --- a/docs/es/reference/default-theme-sidebar.md +++ b/docs/es/reference/default-theme-sidebar.md @@ -211,7 +211,6 @@ const { hasSidebar } = useSidebar() ``` diff --git a/docs/fa/guide/asset-handling.md b/docs/fa/guide/asset-handling.md index 94554217..efa4710f 100644 --- a/docs/fa/guide/asset-handling.md +++ b/docs/fa/guide/asset-handling.md @@ -60,4 +60,4 @@ const { theme } = useData() -``` \ No newline at end of file +``` diff --git a/docs/fa/guide/frontmatter.md b/docs/fa/guide/frontmatter.md index 7f748b1e..4b4af163 100644 --- a/docs/fa/guide/frontmatter.md +++ b/docs/fa/guide/frontmatter.md @@ -45,4 +45,4 @@ editLink: true "editLink": true } --- -``` \ No newline at end of file +``` diff --git a/docs/fa/guide/migration-from-vitepress-0.md b/docs/fa/guide/migration-from-vitepress-0.md index 8a1380df..211bb0f9 100644 --- a/docs/fa/guide/migration-from-vitepress-0.md +++ b/docs/fa/guide/migration-from-vitepress-0.md @@ -20,4 +20,4 @@ ## پیکربندی Frontmatter - گزینه `home: true` به `layout: home` تغییر کرده است. همچنین، تنظیمات مربوط به صفحه اصلی بسیار تغییر کرده‌اند تا ویژگی‌های اضافی را ارائه دهند. برای جزئیات بیشتر، [راهنمای صفحه اصلی](../reference/default-theme-home-page) را ببینید. -- گزینه `footer` به [`themeConfig.footer`](../reference/default-theme-config#footer) منتقل شده است. \ No newline at end of file +- گزینه `footer` به [`themeConfig.footer`](../reference/default-theme-config#footer) منتقل شده است. diff --git a/docs/fa/guide/migration-from-vuepress.md b/docs/fa/guide/migration-from-vuepress.md index a7f8fbc8..536a37c5 100644 --- a/docs/fa/guide/migration-from-vuepress.md +++ b/docs/fa/guide/migration-from-vuepress.md @@ -27,4 +27,4 @@ --- -ادامه دارد... \ No newline at end of file +ادامه دارد... diff --git a/docs/fa/guide/mpa-mode.md b/docs/fa/guide/mpa-mode.md index 9e08e7b3..a18bb1c2 100644 --- a/docs/fa/guide/mpa-mode.md +++ b/docs/fa/guide/mpa-mode.md @@ -20,4 +20,4 @@ document.querySelector('h1').addEventListener('click', () => { `