test: add unit test (#262)

* test: add unit test

* chore: tweak

* chore: tweak
This commit is contained in:
pengzhanbo 2024-10-12 02:09:15 +08:00 committed by GitHub
parent f655249b07
commit 4464703b7b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
50 changed files with 2379 additions and 84 deletions

37
.github/workflows/test.yml vendored Normal file
View File

@ -0,0 +1,37 @@
name: Test
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
unit-test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Install deps
run: pnpm install --frozen-lockfile
- name: Unit Test
env:
NODE_OPTIONS: --max_old_space_size=8192
run: pnpm run test --run
- name: Upload coverage
if: github.ref == 'refs/heads/main'
uses: codecov/codecov-action@v4

2
.gitignore vendored
View File

@ -12,3 +12,5 @@ dist/
*.log
*.tsbuildinfo
.mind
coverage/

View File

@ -31,6 +31,7 @@
"lint:fix": "pnpm lint:check --fix && pnpm lint:css --fix",
"lint:check": "eslint .",
"lint:css": "stylelint **/*.{css,vue}",
"test": "cross-env TZ=Etc/UTC vitest --coverage",
"prepare": "husky",
"release": "pnpm release:check && pnpm release:version && pnpm -r publish",
"release:changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
@ -45,19 +46,23 @@
"@types/lodash.merge": "^4.6.9",
"@types/node": "20.12.10",
"@types/webpack-env": "^1.18.5",
"@vitest/coverage-istanbul": "^2.1.2",
"bumpp": "^9.6.1",
"commitizen": "^4.3.1",
"conventional-changelog-cli": "^5.0.0",
"cpx2": "^8.0.0",
"cross-env": "7.0.3",
"cz-conventional-changelog": "^3.3.0",
"eslint": "^9.12.0",
"husky": "^9.1.6",
"lint-staged": "^15.2.10",
"markdown-it": "^14.1.0",
"rimraf": "^6.0.1",
"stylelint": "^16.9.0",
"tsconfig-vuepress": "^5.2.0",
"tsup": "^8.3.0",
"typescript": "^5.6.2",
"vitest": "^2.1.2",
"wait-on": "^8.0.1"
},
"resolutions": {
@ -65,7 +70,8 @@
},
"lint-staged": {
"*": "eslint --fix",
"*.{css,vue}": "stylelint --fix"
"*.{css,vue}": "stylelint --fix",
"*.{js,ts,mjs,cjs}": "cross-env TZ=Etc/UTC vitest related --run"
},
"config": {
"commitizen": {

View File

@ -0,0 +1,10 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`bilibiliPlugin > should not work 1`] = `
"<VideoBilibili src="https://player.bilibili.com/player.html?autoplay=0" width="100%" height="" ratio="" title="undefined" /><p>@[bilibili]xxx</p>
<p>@[ bilibili]BV12345</p>
<p>@[bilibili](BV12345</p>
"
`;
exports[`bilibiliPlugin > should work 1`] = `"<VideoBilibili src="https://player.bilibili.com/player.html?bvid=BV12345&autoplay=0" width="100%" height="" ratio="" title="undefined" /><VideoBilibili src="https://player.bilibili.com/player.html?aid=12432&cid=12345&autoplay=0" width="100%" height="" ratio="" title="undefined" /><VideoBilibili src="https://player.bilibili.com/player.html?bvid=BV12345&aid=12343&cid=45678&autoplay=0" width="100%" height="" ratio="" title="undefined" /><VideoBilibili src="https://player.bilibili.com/player.html?bvid=BV12345&p=1&t=1&autoplay=1" width="100%" height="" ratio="" title="undefined" /><VideoBilibili src="https://player.bilibili.com/player.html?bvid=BV12345&p=1&autoplay=1" width="100%" height="600px" ratio="" title="undefined" /><VideoBilibili src="https://player.bilibili.com/player.html?bvid=BV12345&p=1&autoplay=1" width="100%" height="" ratio="16:9" title="undefined" />"`;

View File

@ -0,0 +1,90 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`caniusePlugin > should not work 1`] = `""`;
exports[`caniusePlugin > should not work 2`] = `
"<p>@[caniuse]xxx</p>
"
`;
exports[`caniusePlugin > should not work 3`] = `
"<p>@<a href=""> caniuse</a></p>
"
`;
exports[`caniusePlugin > should not work 4`] = `
"<p>@[caniuse](xxx</p>
"
`;
exports[`caniusePlugin > should not work 5`] = `
"<p>@[caniuse](</p>
"
`;
exports[`caniusePlugin > should not work 6`] = `
"<p>@[caniuse</p>
"
`;
exports[`caniusePlugin > should not work 7`] = `
"<p>@<a href="">caniuse)</a></p>
"
`;
exports[`caniusePlugin > should not work 8`] = `
"<p>@<a href="">caniuseee)</a></p>
"
`;
exports[`caniusePlugin > should work 1`] = `"<CanIUseViewer feature="feature" meta="test-id" past="2" future="1" />"`;
exports[`caniusePlugin > should work 2`] = `
"<ClientOnly><p><picture>
<source type="image/webp" srcset="https://caniuse.bitsofco.de/image/feature.webp">
<source type="image/png" srcset="https://caniuse.bitsofco.de/image/feature.png">
<img src="https://caniuse.bitsofco.de/image/feature.jpg" alt="Data on support for the feature feature across the major browsers from caniuse.com" width="100%">
</picture></p></ClientOnly>"
`;
exports[`caniusePlugin > should work 3`] = `"<CanIUseViewer feature="feature" meta="test-id" past="2" future="1" />"`;
exports[`caniusePlugin > should work 4`] = `"<CanIUseViewer feature="feature" meta="test-id" past="2" future="0" />"`;
exports[`caniusePlugin > should work 5`] = `"<CanIUseViewer feature="feature" meta="test-id" past="2" future="0" /><CanIUseViewer feature="feature" meta="test-id" past="2" future="0" />"`;
exports[`caniusePlugin > should work 6`] = `"<CanIUseViewer feature="feature" meta="test-id" past="2" future="0" />"`;
exports[`caniusePlugin > should work with options 1`] = `
"<ClientOnly><p><picture>
<source type="image/webp" srcset="https://caniuse.bitsofco.de/image/feature.webp">
<source type="image/png" srcset="https://caniuse.bitsofco.de/image/feature.png">
<img src="https://caniuse.bitsofco.de/image/feature.jpg" alt="Data on support for the feature feature across the major browsers from caniuse.com" width="100%">
</picture></p></ClientOnly>"
`;
exports[`caniusePlugin > should work with options 2`] = `"<CanIUseViewer feature="feature" meta="test-id" past="2" future="1" />"`;
exports[`caniusePlugin > should work with options 3`] = `"<CanIUseViewer feature="feature" meta="test-id" past="2" future="0" />"`;
exports[`legacyCaniuse > should work 1`] = `"<CanIUseViewer feature="feature" meta="test-id" past="2" future="1" />"`;
exports[`legacyCaniuse > should work 2`] = `"<CanIUseViewer feature="feature{-2,4}" meta="test-id" past="2" future="0" />"`;
exports[`legacyCaniuse > should work 3`] = `""`;
exports[`legacyCaniuse > should work with unknown mode 1`] = `
"<ClientOnly><p><picture>
<source type="image/webp" srcset="https://caniuse.bitsofco.de/image/feature.webp">
<source type="image/png" srcset="https://caniuse.bitsofco.de/image/feature.png">
<img src="https://caniuse.bitsofco.de/image/feature.jpg" alt="Data on support for the feature feature across the major browsers from caniuse.com" width="100%">
</picture></p></ClientOnly>"
`;
exports[`legacyCaniuse > should work with unknown mode 2`] = `
"<ClientOnly><p><picture>
<source type="image/webp" srcset="https://caniuse.bitsofco.de/image/feature{-2,4}.webp">
<source type="image/png" srcset="https://caniuse.bitsofco.de/image/feature{-2,4}.png">
<img src="https://caniuse.bitsofco.de/image/feature{-2,4}.jpg" alt="Data on support for the feature{-2,4} feature across the major browsers from caniuse.com" width="100%">
</picture></p></ClientOnly>"
`;

View File

@ -0,0 +1,9 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`codeSandboxPlugin > should not work 1`] = `
"<CodeSandboxViewer title="" height="500px" width="100%" user="" id="" type="embed" filepath="" :console=false :navbar=true layout="" /><p>@[codesandbox]xxx</p>
<p>@[codesandbox embed](</p>
"
`;
exports[`codeSandboxPlugin > should work 1`] = `"<CodeSandboxViewer title="" height="500px" width="100%" user="user" id="id" type="embed" filepath="" :console=false :navbar=true layout="" /><CodeSandboxViewer title="" height="500px" width="100%" user="user" id="id" type="embed" filepath="" :console=false :navbar=true layout="" /><CodeSandboxViewer title="" height="500px" width="100%" user="user" id="id" type="button" filepath="" :console=false :navbar=true layout="" /><CodeSandboxViewer title="xxx" height="500px" width="100%" user="user" id="slash" type="embed" filepath="filepath" :console=false :navbar=false layout="Editor+Preview" />"`;

View File

@ -0,0 +1,81 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`codeTabsPlugin > should work with default 1`] = `
"<CodeTabs id="0" :data='[{"id":"tab-1"},{"id":"tab-2"},{"id":"tab-3"}]'><template #title0="{ value, isActive }"><span>tab-1</span></template><template #title1="{ value, isActive }"><span>tab-2</span></template><template #title2="{ value, isActive }"><span>tab-3</span></template><template #tab0="{ value, isActive }"><pre><code class="language-js"><div class="language-js"><pre><code>const a = 1
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-js"><div class="language-js"><pre><code>const b = 2
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-js"><div class="language-js"><pre><code>const c = 3
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="11" :data='[{"id":"npm"},{"id":"pnpm"},{"id":"yarn"}]' :active="1"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npm i
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm i
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="22" :data='[{"id":"a.ts"},{"id":"a.js"}]' tab-id="pm"><template #title0="{ value, isActive }"><VPIcon name="vscode-icons:file-type-typescript"/><span>a.ts</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-js"/><span>a.js</span></template><template #tab0="{ value, isActive }"><pre><code class="language-ts"><div class="language-ts"><pre><code>const a = 1
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-js"><div class="language-js"><pre><code>const a = 1
</code></pre></div></code></pre>
</template></CodeTabs>"
`;
exports[`codeTabsPlugin > should work with no icon 1`] = `
"<CodeTabs id="0" :data='[{"id":"tab-1"},{"id":"tab-2"},{"id":"tab-3"}]'><template #title0="{ value, isActive }"><span>tab-1</span></template><template #title1="{ value, isActive }"><span>tab-2</span></template><template #title2="{ value, isActive }"><span>tab-3</span></template><template #tab0="{ value, isActive }"><pre><code class="language-js"><div class="language-js"><pre><code>const a = 1
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-js"><div class="language-js"><pre><code>const b = 2
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-js"><div class="language-js"><pre><code>const c = 3
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="11" :data='[{"id":"npm"},{"id":"pnpm"},{"id":"yarn"}]' :active="1"><template #title0="{ value, isActive }"><span>npm</span></template><template #title1="{ value, isActive }"><span>pnpm</span></template><template #title2="{ value, isActive }"><span>yarn</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npm i
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm i
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="22" :data='[{"id":"a.ts"},{"id":"a.js"}]' tab-id="pm"><template #title0="{ value, isActive }"><span>a.ts</span></template><template #title1="{ value, isActive }"><span>a.js</span></template><template #tab0="{ value, isActive }"><pre><code class="language-ts"><div class="language-ts"><pre><code>const a = 1
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-js"><div class="language-js"><pre><code>const a = 1
</code></pre></div></code></pre>
</template></CodeTabs>"
`;
exports[`codeTabsPlugin > should work with options: \`{ named: false, extensions: false }\` 1`] = `
"<CodeTabs id="0" :data='[{"id":"tab-1"},{"id":"tab-2"},{"id":"tab-3"}]'><template #title0="{ value, isActive }"><span>tab-1</span></template><template #title1="{ value, isActive }"><span>tab-2</span></template><template #title2="{ value, isActive }"><span>tab-3</span></template><template #tab0="{ value, isActive }"><pre><code class="language-js"><div class="language-js"><pre><code>const a = 1
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-js"><div class="language-js"><pre><code>const b = 2
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-js"><div class="language-js"><pre><code>const c = 3
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="11" :data='[{"id":"npm"},{"id":"pnpm"},{"id":"yarn"}]' :active="1"><template #title0="{ value, isActive }"><span>npm</span></template><template #title1="{ value, isActive }"><span>pnpm</span></template><template #title2="{ value, isActive }"><span>yarn</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npm i
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm i
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="22" :data='[{"id":"a.ts"},{"id":"a.js"}]' tab-id="pm"><template #title0="{ value, isActive }"><span>a.ts</span></template><template #title1="{ value, isActive }"><span>a.js</span></template><template #tab0="{ value, isActive }"><pre><code class="language-ts"><div class="language-ts"><pre><code>const a = 1
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-js"><div class="language-js"><pre><code>const a = 1
</code></pre></div></code></pre>
</template></CodeTabs>"
`;
exports[`codeTabsPlugin > should work with options: { named: [npm,pnpm,yarn], extensions: [.js,.ts] } 1`] = `
"<CodeTabs id="0" :data='[{"id":"tab-1"},{"id":"tab-2"},{"id":"tab-3"}]'><template #title0="{ value, isActive }"><span>tab-1</span></template><template #title1="{ value, isActive }"><span>tab-2</span></template><template #title2="{ value, isActive }"><span>tab-3</span></template><template #tab0="{ value, isActive }"><pre><code class="language-js"><div class="language-js"><pre><code>const a = 1
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-js"><div class="language-js"><pre><code>const b = 2
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-js"><div class="language-js"><pre><code>const c = 3
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="11" :data='[{"id":"npm"},{"id":"pnpm"},{"id":"yarn"}]' :active="1"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npm i
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm i
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="22" :data='[{"id":"a.ts"},{"id":"a.js"}]' tab-id="pm"><template #title0="{ value, isActive }"><VPIcon name="vscode-icons:file-type-typescript"/><span>a.ts</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-js"/><span>a.js</span></template><template #tab0="{ value, isActive }"><pre><code class="language-ts"><div class="language-ts"><pre><code>const a = 1
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-js"><div class="language-js"><pre><code>const a = 1
</code></pre></div></code></pre>
</template></CodeTabs>"
`;

View File

@ -0,0 +1,9 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`codepenPlugin > should not work 1`] = `
"<iframe class="code-pen-iframe-wrapper" src="https://codepen.io//embed/undefined?default-tab=result" title="Codepen" style="width:100%;height:400px;margin:16px auto;border-radius:5px;" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">See the Pen <a href="https://codepen.io//pen/undefined">Codepen</a> by (<a href="https://codepen.io/">@</a>) on <a href="https://codepen.io/">CodePen</a>.</iframe><p>@[codepen]xxx</p>
<p>@[codepen preview](</p>
"
`;
exports[`codepenPlugin > should work 1`] = `"<iframe class="code-pen-iframe-wrapper" src="https://codepen.io/user/embed/slash?default-tab=result" title="Codepen" style="width:100%;height:400px;margin:16px auto;border-radius:5px;" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">See the Pen <a href="https://codepen.io/user/pen/slash">Codepen</a> by user (<a href="https://codepen.io/user">@user</a>) on <a href="https://codepen.io/">CodePen</a>.</iframe><iframe class="code-pen-iframe-wrapper" src="https://codepen.io/user/embed/preview/slash?default-tab=result" title="Codepen" style="width:100%;height:400px;margin:16px auto;border-radius:5px;" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">See the Pen <a href="https://codepen.io/user/pen/slash">Codepen</a> by user (<a href="https://codepen.io/user">@user</a>) on <a href="https://codepen.io/">CodePen</a>.</iframe><iframe class="code-pen-iframe-wrapper" src="https://codepen.io/user/embed/preview/slash?editable=true&default-tab=css%2Cresult&theme-id=dark" title="codepen" style="width:100%;height:400px;margin:16px auto;border-radius:5px;" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">See the Pen <a href="https://codepen.io/user/pen/slash">codepen</a> by user (<a href="https://codepen.io/user">@user</a>) on <a href="https://codepen.io/">CodePen</a>.</iframe>"`;

View File

@ -0,0 +1,66 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`fileTreePlugin > should work with default options 1`] = `
"<div class="vp-file-tree"><ul>
<FileTreeItem type="folder" :expanded="true" :empty="false"><span class="tree-node folder"><VPIcon name="vscode-icons:folder-type-docs"></VPIcon><span class="name">docs</span></span>
<ul>
<FileTreeItem type="file" :expanded="false" :empty="true"><span class="tree-node file"><VPIcon name="flat-color-icons:info"></VPIcon><span class="name">README.md</span></span></FileTreeItem>
<FileTreeItem type="file" :expanded="false" :empty="true"><span class="tree-node file"><VPIcon name="vscode-icons:file-type-markdown"></VPIcon><span class="name">foo.md</span></span></FileTreeItem>
</ul>
</FileTreeItem>
<FileTreeItem type="folder" :expanded="true" :empty="false"><span class="tree-node folder"><VPIcon name="vscode-icons:folder-type-src"></VPIcon><span class="name">src</span></span>
<ul>
<FileTreeItem type="folder" :expanded="true" :empty="false"><span class="tree-node folder"><VPIcon name="vscode-icons:folder-type-client"></VPIcon><span class="name">client</span></span>
<ul>
<FileTreeItem type="folder" :expanded="true" :empty="false"><span class="tree-node folder"><VPIcon name="vscode-icons:folder-type-component"></VPIcon><span class="name">components</span></span>
<ul>
<FileTreeItem type="file" :expanded="false" :empty="true"><span class="tree-node file"><VPIcon name="vscode-icons:file-type-vue"></VPIcon><span class="name focus"><strong>Navbar.vue</strong></span></span></FileTreeItem>
</ul>
</FileTreeItem>
<FileTreeItem type="file" :expanded="false" :empty="true"><span class="tree-node file"><VPIcon name="vscode-icons:file-type-typescript"></VPIcon><span class="name">index.ts</span><span class="comment"># comment</span></span></FileTreeItem>
</ul>
</FileTreeItem>
<FileTreeItem type="folder" :expanded="true" :empty="false"><span class="tree-node folder"><VPIcon name="vscode-icons:default-folder"></VPIcon><span class="name">node</span></span>
<ul>
<FileTreeItem type="file" :expanded="false" :empty="true"><span class="tree-node file"><VPIcon name="vscode-icons:file-type-typescript"></VPIcon><span class="name">index.ts</span></span></FileTreeItem>
</ul>
</FileTreeItem>
</ul>
</FileTreeItem>
<FileTreeItem type="file" :expanded="false" :empty="true"><span class="tree-node file"><VPIcon name="vscode-icons:file-type-git"></VPIcon><span class="name">.gitignore</span></span></FileTreeItem>
<FileTreeItem type="file" :expanded="false" :empty="true"><span class="tree-node file"><VPIcon name="vscode-icons:file-type-node"></VPIcon><span class="name">package.json</span></span></FileTreeItem>
</ul>
</div><div class="vp-file-tree"><p class="vp-file-tree-title">files</p><ul>
<FileTreeItem type="folder" :expanded="true" :empty="false"><span class="tree-node folder"><VPIcon name="vscode-icons:folder-type-src"></VPIcon><span class="name">src</span></span>
<ul>
<FileTreeItem type="folder" :expanded="true" :empty="false"><span class="tree-node folder"><VPIcon name="vscode-icons:default-folder"></VPIcon><span class="name">js</span></span>
<ul>
<FileTreeItem type="file" :expanded="false" :empty="true"><span class="tree-node file"><span class="name">…</span></span></FileTreeItem>
</ul>
</FileTreeItem>
<FileTreeItem type="folder" :expanded="false" :empty="true"><span class="tree-node folder"><VPIcon name="vscode-icons:default-folder"></VPIcon><span class="name">vue</span></span></FileTreeItem>
<FileTreeItem type="folder" :expanded="false" :empty="true"><span class="tree-node folder"><VPIcon name="vscode-icons:folder-type-css"></VPIcon><span class="name">css</span></span></FileTreeItem>
</ul>
</FileTreeItem>
<FileTreeItem type="file" :expanded="false" :empty="true"><span class="tree-node file"><VPIcon name="flat-color-icons:info"></VPIcon><span class="name">README.md</span></span></FileTreeItem>
</ul>
</div><div class="vp-file-tree"><ul>
<FileTreeItem type="file" :expanded="false" :empty="true"><span class="tree-node file"><VPIcon name="vscode-icons:default-file"></VPIcon><span class="name">docs</span></span></FileTreeItem>
<FileTreeItem type="folder" :expanded="true" :empty="false"><span class="tree-node folder"><VPIcon name="vscode-icons:default-folder"></VPIcon><span class="name">src</span></span>
<ul>
<FileTreeItem type="file" :expanded="false" :empty="true"><span class="tree-node file"><VPIcon name="vscode-icons:default-file"></VPIcon><span class="name">a.js</span></span></FileTreeItem>
<FileTreeItem type="file" :expanded="false" :empty="true"><span class="tree-node file"><VPIcon name="vscode-icons:default-file"></VPIcon><span class="name">b.ts</span></span></FileTreeItem>
</ul>
</FileTreeItem>
<FileTreeItem type="file" :expanded="false" :empty="true"><span class="tree-node file"><VPIcon name="vscode-icons:default-file"></VPIcon><span class="name">README.md</span></span></FileTreeItem>
</ul>
</div><div class="vp-file-tree"><ul>
<li></li>
<li>
<ul>
<li></li>
</ul>
</li>
</ul>
</div><div class="vp-file-tree"></div>"
`;

View File

@ -0,0 +1,108 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`iconsPlugin > should not work with invalid icon 1`] = `
"<p>:[ mdi:11 ]:</p>
"
`;
exports[`iconsPlugin > should not work with invalid icon 2`] = `
"<p>:[]:</p>
"
`;
exports[`iconsPlugin > should not work with invalid icon 3`] = `
"<p>:[]&amp;</p>
"
`;
exports[`iconsPlugin > should not work with invalid icon 4`] = `
"<p>:[:[</p>
"
`;
exports[`iconsPlugin > should not work with invalid icon 5`] = `
"<p>:[mdi:11</p>
"
`;
exports[`iconsPlugin > should work 1`] = `
"<p><VPIcon name="mdi:11"></VPIcon></p>
"
`;
exports[`iconsPlugin > should work 2`] = `
"<p><strong>strong</strong> <VPIcon name="mdi:11"></VPIcon> <VPIcon name="mdi:11"></VPIcon></p>
"
`;
exports[`iconsPlugin > should work 3`] = `
"<p><strong>strong</strong>
<VPIcon name="mdi:11"></VPIcon>
<VPIcon name="mdi:11"></VPIcon></p>
"
`;
exports[`iconsPlugin > should work with options 1`] = `
"<p><VPIcon name="mdi:11" size="1.25em" color="#ccc"></VPIcon></p>
"
`;
exports[`iconsPlugin > should work with options 2`] = `
"<p><strong>strong</strong> <VPIcon name="mdi:11" size="1.25em" color="#ccc"></VPIcon> <VPIcon name="mdi:11" size="1.25em" color="#ccc"></VPIcon></p>
"
`;
exports[`iconsPlugin > should work with single icon options 1`] = `
"<p><VPIcon name="mdi:11" size="36px"></VPIcon></p>
"
`;
exports[`iconsPlugin > should work with single icon options 2`] = `
"<p><VPIcon name="mdi:11" size="32px" color="#eee"></VPIcon></p>
"
`;
exports[`iconsPlugin > should work with single icon options 3`] = `
"<p><VPIcon name="mdi:11" color="#eee"></VPIcon></p>
"
`;
exports[`iconsPlugin > should work with single icon options 4`] = `
"<p><VPIcon name="mdi:11" size="32px"></VPIcon></p>
"
`;
exports[`iconsPlugin > should work with single icon options 5`] = `
"<p><VPIcon name="mdi:11"></VPIcon></p>
"
`;
exports[`iconsPlugin > should work with single icon options 6`] = `
"<p><VPIcon name="mdi:11" size="1.25em" color="#ccc"></VPIcon></p>
"
`;
exports[`iconsPlugin > should work with single icon options 7`] = `
"<p><VPIcon name="mdi:11" size="36px" color="#ccc"></VPIcon></p>
"
`;
exports[`iconsPlugin > should work with single icon options 8`] = `
"<p><VPIcon name="mdi:11" size="32px" color="#eee"></VPIcon></p>
"
`;
exports[`iconsPlugin > should work with single icon options 9`] = `
"<p><VPIcon name="mdi:11" size="1.25em" color="#eee"></VPIcon></p>
"
`;
exports[`iconsPlugin > should work with single icon options 10`] = `
"<p><VPIcon name="mdi:11" size="32px"></VPIcon></p>
"
`;
exports[`iconsPlugin > should work with single icon options 11`] = `
"<p><VPIcon name="mdi:11" size="1.25em"></VPIcon></p>
"
`;

View File

@ -0,0 +1,9 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`codeSandboxPlugin > should not work 1`] = `
"<iframe class="js-fiddle-iframe-wrapper" style="width:100%;height:400px;margin:16px auto;border:none;border-radius:5px;" title="JS Fiddle" src="https://jsfiddle.net//undefined/embedded/js,css,html,result/dark/" allowfullscreen="true" allowpaymentrequest="true"></iframe><p>@[jsfiddle]xxx</p>
<p>@[jsfiddle](</p>
"
`;
exports[`codeSandboxPlugin > should work 1`] = `"<iframe class="js-fiddle-iframe-wrapper" style="width:100%;height:400px;margin:16px auto;border:none;border-radius:5px;" title="JS Fiddle" src="https://jsfiddle.net/user/id/embedded/js,css,html,result/dark/" allowfullscreen="true" allowpaymentrequest="true"></iframe><iframe class="js-fiddle-iframe-wrapper" style="width:100%;height:400px;margin:16px auto;border:none;border-radius:5px;" title="JS Fiddle" src="https://jsfiddle.net/user/id/embedded/js,css,html,result/dark/" allowfullscreen="true" allowpaymentrequest="true"></iframe><iframe class="js-fiddle-iframe-wrapper" style="width:100%;height:400px;margin:16px auto;border:none;border-radius:5px;" title="JS Fiddle" src="https://jsfiddle.net/user/id/embedded/js,css,html,result" allowfullscreen="true" allowpaymentrequest="true"></iframe><iframe class="js-fiddle-iframe-wrapper" style="width:100%;height:500px;margin:16px auto;border:none;border-radius:5px;" title="xxx" src="https://jsfiddle.net/user/id/embedded/js,css,html,result/dark/" allowfullscreen="true" allowpaymentrequest="true"></iframe>"`;

View File

@ -0,0 +1,361 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`npmToPlugin > should work width options: [npm, yarn, pnpm] 1`] = `
"<CodeTabs id="0" :data='[{"id":"npm"},{"id":"yarn"},{"id":"pnpm"}]' tab-id="npm-to-0"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"yarn"},{"id":"pnpm"}]' tab-id="npm-to-3"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npm install
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm install
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"yarn"},{"id":"pnpm"}]' tab-id="npm-to-6"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #tab0="{ value, isActive }"><pre><code class="language-shell"><div class="language-shell"><pre><code>npm install
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-shell"><div class="language-shell"><pre><code>yarn
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-shell"><div class="language-shell"><pre><code>pnpm install
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"yarn"},{"id":"pnpm"}]' tab-id="npm-to-9"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #tab0="{ value, isActive }"><pre><code class="language-bash"><div class="language-bash"><pre><code>npm install
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-bash"><div class="language-bash"><pre><code>yarn
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-bash"><div class="language-bash"><pre><code>pnpm install
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"yarn"},{"id":"pnpm"}]' tab-id="npm-to-12"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>cross-env NODE_ENV=production npm run docs
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>cross-env NODE_ENV=production yarn docs
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>cross-env NODE_ENV=production pnpm docs
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"yarn"},{"id":"pnpm"}]' tab-id="npm-to-15"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npm i -D package1 package2
npm i --save-peer package3
npm run docs
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn add -D package1package2
yarn add --peer package3
yarn docs
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm add -D package1package2
pnpm add --save-peer package3
pnpm docs
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"yarn"},{"id":"pnpm"}]' tab-id="npm-to-18"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npm install && npm run docs
mkdir foo
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn && yarn docs
mkdir foo
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm install && pnpm docs
mkdir foo
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"yarn"},{"id":"pnpm"}]' tab-id="npm-to-21"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npm run docs -- --clean-cache --clean-temp
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn docs --clean-cache --clean-temp
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm docs --clean-cache --clean-temp
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"pnpm"},{"id":"yarn"}]' tab-id="npm-to-24"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npm create vuepress-theme-plume@latest
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm create vuepress-theme-plume@latest
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn create vuepress-theme-plume@latest
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"pnpm"},{"id":"yarn"},{"id":"bun"},{"id":"deno"}]' tab-id="npm-to-27"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title3="{ value, isActive }"><VPIcon name="vscode-icons:file-type-bun"/><span>bun</span></template><template #title4="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-deno"/><span>deno</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npx vp-update
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm dlx vp-update
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn dlx vp-update
</code></pre></div></code></pre>
</template><template #tab3="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>bunx vp-update
</code></pre></div></code></pre>
</template><template #tab4="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>deno run -A vp-update
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"yarn"},{"id":"pnpm"}]' tab-id="npm-to-30"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>mkdir foo
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>mkdir foo
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>mkdir foo
</code></pre></div></code></pre>
</template></CodeTabs><p>anything</p>
<pre><code class="language-sh"><div class="language-sh"><pre><code></code></pre></div></code></pre>
"
`;
exports[`npmToPlugin > should work width options: { tabs: [npm, yarn, pnpm] } 1`] = `
"<CodeTabs id="0" :data='[{"id":"npm"},{"id":"yarn"},{"id":"pnpm"}]' tab-id="npm-to-0"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"yarn"},{"id":"pnpm"}]' tab-id="npm-to-3"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npm install
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm install
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"yarn"},{"id":"pnpm"}]' tab-id="npm-to-6"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #tab0="{ value, isActive }"><pre><code class="language-shell"><div class="language-shell"><pre><code>npm install
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-shell"><div class="language-shell"><pre><code>yarn
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-shell"><div class="language-shell"><pre><code>pnpm install
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"yarn"},{"id":"pnpm"}]' tab-id="npm-to-9"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #tab0="{ value, isActive }"><pre><code class="language-bash"><div class="language-bash"><pre><code>npm install
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-bash"><div class="language-bash"><pre><code>yarn
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-bash"><div class="language-bash"><pre><code>pnpm install
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"yarn"},{"id":"pnpm"}]' tab-id="npm-to-12"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>cross-env NODE_ENV=production npm run docs
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>cross-env NODE_ENV=production yarn docs
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>cross-env NODE_ENV=production pnpm docs
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"yarn"},{"id":"pnpm"}]' tab-id="npm-to-15"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npm i -D package1 package2
npm i --save-peer package3
npm run docs
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn add -D package1package2
yarn add --peer package3
yarn docs
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm add -D package1package2
pnpm add --save-peer package3
pnpm docs
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"yarn"},{"id":"pnpm"}]' tab-id="npm-to-18"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npm install && npm run docs
mkdir foo
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn && yarn docs
mkdir foo
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm install && pnpm docs
mkdir foo
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"yarn"},{"id":"pnpm"}]' tab-id="npm-to-21"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npm run docs -- --clean-cache --clean-temp
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn docs --clean-cache --clean-temp
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm docs --clean-cache --clean-temp
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"pnpm"},{"id":"yarn"}]' tab-id="npm-to-24"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npm create vuepress-theme-plume@latest
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm create vuepress-theme-plume@latest
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn create vuepress-theme-plume@latest
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"pnpm"},{"id":"yarn"},{"id":"bun"},{"id":"deno"}]' tab-id="npm-to-27"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title3="{ value, isActive }"><VPIcon name="vscode-icons:file-type-bun"/><span>bun</span></template><template #title4="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-deno"/><span>deno</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npx vp-update
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm dlx vp-update
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn dlx vp-update
</code></pre></div></code></pre>
</template><template #tab3="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>bunx vp-update
</code></pre></div></code></pre>
</template><template #tab4="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>deno run -A vp-update
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"yarn"},{"id":"pnpm"}]' tab-id="npm-to-30"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>mkdir foo
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>mkdir foo
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>mkdir foo
</code></pre></div></code></pre>
</template></CodeTabs><p>anything</p>
<pre><code class="language-sh"><div class="language-sh"><pre><code></code></pre></div></code></pre>
"
`;
exports[`npmToPlugin > should work with default options 1`] = `
"<CodeTabs id="0" :data='[{"id":"npm"},{"id":"pnpm"},{"id":"yarn"}]' tab-id="npm-to-0"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"pnpm"},{"id":"yarn"}]' tab-id="npm-to-3"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npm install
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm install
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"pnpm"},{"id":"yarn"}]' tab-id="npm-to-6"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #tab0="{ value, isActive }"><pre><code class="language-shell"><div class="language-shell"><pre><code>npm install
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-shell"><div class="language-shell"><pre><code>pnpm install
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-shell"><div class="language-shell"><pre><code>yarn
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"pnpm"},{"id":"yarn"}]' tab-id="npm-to-9"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #tab0="{ value, isActive }"><pre><code class="language-bash"><div class="language-bash"><pre><code>npm install
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-bash"><div class="language-bash"><pre><code>pnpm install
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-bash"><div class="language-bash"><pre><code>yarn
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"pnpm"},{"id":"yarn"}]' tab-id="npm-to-12"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>cross-env NODE_ENV=production npm run docs
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>cross-env NODE_ENV=production pnpm docs
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>cross-env NODE_ENV=production yarn docs
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"pnpm"},{"id":"yarn"}]' tab-id="npm-to-15"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npm i -D package1 package2
npm i --save-peer package3
npm run docs
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm add -D package1package2
pnpm add --save-peer package3
pnpm docs
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn add -D package1package2
yarn add --peer package3
yarn docs
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"pnpm"},{"id":"yarn"}]' tab-id="npm-to-18"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npm install && npm run docs
mkdir foo
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm install && pnpm docs
mkdir foo
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn && yarn docs
mkdir foo
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"pnpm"},{"id":"yarn"}]' tab-id="npm-to-21"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npm run docs -- --clean-cache --clean-temp
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm docs --clean-cache --clean-temp
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn docs --clean-cache --clean-temp
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"pnpm"},{"id":"yarn"}]' tab-id="npm-to-24"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npm create vuepress-theme-plume@latest
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm create vuepress-theme-plume@latest
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn create vuepress-theme-plume@latest
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"pnpm"},{"id":"yarn"},{"id":"bun"},{"id":"deno"}]' tab-id="npm-to-27"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #title3="{ value, isActive }"><VPIcon name="vscode-icons:file-type-bun"/><span>bun</span></template><template #title4="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-deno"/><span>deno</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>npx vp-update
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>pnpm dlx vp-update
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>yarn dlx vp-update
</code></pre></div></code></pre>
</template><template #tab3="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>bunx vp-update
</code></pre></div></code></pre>
</template><template #tab4="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>deno run -A vp-update
</code></pre></div></code></pre>
</template></CodeTabs><CodeTabs id="0" :data='[{"id":"npm"},{"id":"pnpm"},{"id":"yarn"}]' tab-id="npm-to-30"><template #title0="{ value, isActive }"><VPIcon name="logos:npm-icon"/><span>npm</span></template><template #title1="{ value, isActive }"><VPIcon name="vscode-icons:file-type-light-pnpm"/><span>pnpm</span></template><template #title2="{ value, isActive }"><VPIcon name="vscode-icons:file-type-yarn"/><span>yarn</span></template><template #tab0="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>mkdir foo
</code></pre></div></code></pre>
</template><template #tab1="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>mkdir foo
</code></pre></div></code></pre>
</template><template #tab2="{ value, isActive }"><pre><code class="language-sh"><div class="language-sh"><pre><code>mkdir foo
</code></pre></div></code></pre>
</template></CodeTabs><p>anything</p>
<pre><code class="language-sh"><div class="language-sh"><pre><code></code></pre></div></code></pre>
"
`;

View File

@ -0,0 +1,12 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`pdfPlugin > should not work 1`] = `
"<PDFViewer src="" title="" :page="1" :no-toolbar="false" width="100%" height="" ratio="" :zoom="50" /><p>@[pdf]xxx</p>
<p>@<a href=""> pdf</a></p>
<p>@[pdf]</p>
"
`;
exports[`pdfPlugin > should work 1`] = `"<PDFViewer src="foo.pdf" title="foo.pdf" :page="1" :no-toolbar="false" width="100%" height="" ratio="" :zoom="50" />"`;
exports[`pdfPlugin > should work 2`] = `"<PDFViewer src="foo.pdf" title="foo.pdf" :page="1" :no-toolbar="false" width="100%" height="" ratio="" :zoom="50" /><PDFViewer src="foo.pdf" title="foo.pdf" :page="1" :no-toolbar="true" width="100%" height="" ratio="" :zoom="50" /><PDFViewer src="foo.pdf" title="foo.pdf" :page="2" :no-toolbar="false" width="100%" height="" ratio="" :zoom="50" /><PDFViewer src="foo.pdf" title="foo.pdf" :page="2" :no-toolbar="true" width="100%" height="" ratio="" :zoom="50" /><PDFViewer src="foo.pdf" title="foo.pdf" :page="2" :no-toolbar="true" width="100%" height="600px" ratio="" :zoom="1" /><PDFViewer src="foo.pdf" title="foo.pdf" :page="2" :no-toolbar="true" width="100%" height="" ratio="1:1" :zoom="1" />"`;

View File

@ -0,0 +1,38 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`plotPlugin > should not work with invalid tag 1`] = `
"<p>!!!!</p>
"
`;
exports[`plotPlugin > should not work with invalid tag 2`] = `
"<p>!!plot!</p>
"
`;
exports[`plotPlugin > should not work with invalid tag 3`] = `
"<p>!!!</p>
"
`;
exports[`plotPlugin > should not work with invalid tag 4`] = `
"<p>!! plot !!</p>
"
`;
exports[`plotPlugin > should work 1`] = `
"<p><Plot>plot</Plot></p>
"
`;
exports[`plotPlugin > should work 2`] = `
"<p>hidden: <Plot>plot</Plot> <strong>strong</strong></p>
"
`;
exports[`plotPlugin > should work 3`] = `
"<p>hidden:<br>
<Plot>plot</Plot><br>
<Plot>plot</Plot></p>
"
`;

View File

@ -0,0 +1,10 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`youtubePlugin > should not work 1`] = `
"<VideoYoutube src="https://www.youtube.com/embed//?" width="100%" height="" ratio="" title="undefined" /><p>@[youtube]xxx</p>
<p>@[ youtube]123456</p>
<p>@<a href="123456"> youtube</a></p>
"
`;
exports[`youtubePlugin > should work 1`] = `"<VideoYoutube src="https://www.youtube.com/embed//123456?" width="100%" height="" ratio="" title="undefined" /><VideoYoutube src="https://www.youtube.com/embed//123456?autoplay=1&loop=1" width="100%" height="" ratio="" title="test" /><VideoYoutube src="https://www.youtube.com/embed//123456?autoplay=1&start=40&end=80" width="100%" height="" ratio="" title="undefined" /><VideoYoutube src="https://www.youtube.com/embed//123456?" width="100%" height="600px" ratio="" title="undefined" /><VideoYoutube src="https://www.youtube.com/embed//123456?" width="100%" height="" ratio="16:9" title="undefined" />"`;

View File

@ -0,0 +1,13 @@
import MarkdownIt from 'markdown-it'
import { describe, expect, it } from 'vitest'
import { alignPlugin } from '../src/node/container/align.js'
describe('alignPlugin', () => {
const md = new MarkdownIt().use(alignPlugin)
it('should work', () => {
expect(md.render(':::left\n:::')).toContain('style="text-align:left"')
expect(md.render(':::center\n:::')).toContain('style="text-align:center"')
expect(md.render(':::right\n:::')).toContain('style="text-align:right"')
expect(md.render(':::justify\n:::')).toContain('style="text-align:justify"')
})
})

View File

@ -0,0 +1,44 @@
import MarkdownIt from 'markdown-it'
import { describe, expect, it } from 'vitest'
import { bilibiliPlugin } from '../src/node/embed/video/bilibili.js'
function createMarkdown() {
return MarkdownIt().use((md) => {
md.block.ruler.before('code', 'import_code', () => false)
md.renderer.rules.import_code = () => ''
}).use(bilibiliPlugin)
}
describe('bilibiliPlugin', () => {
it('should work', () => {
const md = createMarkdown()
const code = `\
@[bilibili](BV12345)
@[bilibili](12432 12345)
@[bilibili](BV12345 12343 45678)
@[bilibili p1 autoplay time="1"](BV12345)
@[bilibili p1 autoplay width="100%" height="600px"](BV12345)
@[bilibili p1 autoplay width="100%" ratio="16:9"](BV12345)
`
expect(md.render(code)).toMatchSnapshot()
})
it('should not work', () => {
const md = createMarkdown()
const code = `\
@[bilibili]()
@[bilibili]xxx
@[ bilibili]BV12345
@[bilibili](BV12345
`
expect(md.render(code)).toMatchSnapshot()
})
})

View File

@ -0,0 +1,73 @@
import type { CanIUseOptions } from '../src/shared/index.js'
import MarkdownIt from 'markdown-it'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { caniusePlugin, legacyCaniuse } from '../src/node/embed/caniuse.js'
beforeEach(() => {
vi.mock('../src/node/utils/nanoid.js', () => ({
nanoid: vi.fn(() => 'test-id'),
}))
})
function createMarkdown(options?: CanIUseOptions) {
return MarkdownIt().use((md) => {
md.block.ruler.before('code', 'import_code', () => false)
md.renderer.rules.import_code = () => ''
}).use(caniusePlugin, options)
}
describe('caniusePlugin', () => {
it('should work', () => {
const md = createMarkdown()
expect(md.render('@[caniuse](feature)')).toMatchSnapshot()
expect(md.render('@[caniuse image](feature)')).toMatchSnapshot()
expect(md.render('@[caniuse embed](feature)')).toMatchSnapshot()
expect(md.render('@[caniuse {-2,4}](feature)')).toMatchSnapshot()
expect(md.render(`\
@[caniuse {-2,4}](feature)
@[caniuse {-2,}](feature)
`)).toMatchSnapshot()
expect(md.render('@[caniuse embed{-2,4}](feature)')).toMatchSnapshot()
})
it('should work with options', () => {
const md = createMarkdown({ mode: 'image' })
expect(md.render('@[caniuse](feature)')).toMatchSnapshot()
expect(md.render('@[caniuse embed](feature)')).toMatchSnapshot()
expect(md.render('@[caniuse embed{-2,4}](feature)')).toMatchSnapshot()
})
it('should not work', () => {
const md = createMarkdown()
expect(md.render('@[caniuse]()')).toMatchSnapshot()
expect(md.render('@[caniuse]xxx')).toMatchSnapshot()
expect(md.render('@[ caniuse]()')).toMatchSnapshot()
expect(md.render('@[caniuse](xxx')).toMatchSnapshot()
expect(md.render('@[caniuse](')).toMatchSnapshot()
expect(md.render('@[caniuse')).toMatchSnapshot()
expect(md.render('@[caniuse)]()')).toMatchSnapshot()
expect(md.render('@[caniuseee)]()')).toMatchSnapshot()
})
})
describe('legacyCaniuse', () => {
it('should work', () => {
const md = MarkdownIt()
legacyCaniuse(md)
expect(md.render(':::caniuse feature\n:::')).toMatchSnapshot()
expect(md.render(':::caniuse feature{-2,4}\n:::')).toMatchSnapshot()
expect(md.render(':::caniuse\n:::')).toMatchSnapshot()
})
it('should work with unknown mode', () => {
const md = MarkdownIt()
legacyCaniuse(md, { mode: 'unknown' as any })
expect(md.render(':::caniuse feature\n:::')).toMatchSnapshot()
expect(md.render(':::caniuse feature{-2,4}\n:::')).toMatchSnapshot()
})
})

View File

@ -0,0 +1,40 @@
import MarkdownIt from 'markdown-it'
import { describe, expect, it } from 'vitest'
import { codeSandboxPlugin } from '../src/node/embed/code/codeSandbox.js'
function createMarkdown() {
return MarkdownIt().use((md) => {
md.block.ruler.before('code', 'import_code', () => false)
md.renderer.rules.import_code = () => ''
}).use(codeSandboxPlugin)
}
describe('codeSandboxPlugin', () => {
it('should work', () => {
const md = createMarkdown()
const code = `\
@[codesandbox](user/id)
@[codesandbox embed](user/id)
@[codesandbox button](user/id)
@[codesandbox title="xxx" layout="Editor+Preview" width="100%" height="500px" navbar="false" console="false"](user/slash#filepath)
`
expect(md.render(code)).toMatchSnapshot()
})
it('should not work', () => {
const md = createMarkdown()
const code = `\
@[codesandbox]()
@[codesandbox]xxx
@[codesandbox embed](
`
expect(md.render(code)).toMatchSnapshot()
})
})

View File

@ -0,0 +1,79 @@
import type { CodeTabsOptions } from '../src/shared/codeTabs.js'
import MarkdownIt from 'markdown-it'
import { describe, expect, it } from 'vitest'
import { codeTabs } from '../src/node/container/codeTabs.js'
function createMarkdown(options?: CodeTabsOptions) {
const md = new MarkdownIt()
md.options.highlight = (str, lang) => {
return `<div class="language-${lang}"><pre><code>${str}</code></pre></div>`
}
md.use(codeTabs, options)
return md
}
const FENCE = '```'
describe('codeTabsPlugin', () => {
const code = `\
::: code-tabs
@tab tab-1
${FENCE}js
const a = 1
${FENCE}
@tab tab-2
${FENCE}js
const b = 2
${FENCE}
@tab tab-3
${FENCE}js
const c = 3
${FENCE}
:::
::: code-tabs
@tab npm
${FENCE}sh
npm i
${FENCE}
@tab:active pnpm
${FENCE}sh
pnpm i
${FENCE}
@tab yarn
${FENCE}sh
yarn
${FENCE}
:::
::: code-tabs#pm
@tab a.ts
${FENCE}ts
const a = 1
${FENCE}
@tab a.js
${FENCE}js
const a = 1
${FENCE}
:::
`
it('should work with default', () => {
const md = createMarkdown()
expect(md.render(code)).toMatchSnapshot()
})
it('should work with no icon', () => {
const md = createMarkdown({ icon: false })
expect(md.render(code)).toMatchSnapshot()
})
it('should work with options: `{ named: false, extensions: false }`', () => {
const md = createMarkdown({ icon: { named: false, extensions: false } })
expect(md.render(code)).toMatchSnapshot()
})
it('should work with options: { named: [npm,pnpm,yarn], extensions: [.js,.ts] }', () => {
const md = createMarkdown({ icon: { named: ['npm', 'pnpm', 'yarn'], extensions: ['.js', '.ts'] } })
expect(md.render(code)).toMatchSnapshot()
})
})

View File

@ -0,0 +1,38 @@
import MarkdownIt from 'markdown-it'
import { describe, expect, it } from 'vitest'
import { codepenPlugin } from '../src/node/embed/code/codepen.js'
function createMarkdown() {
return MarkdownIt().use((md) => {
md.block.ruler.before('code', 'import_code', () => false)
md.renderer.rules.import_code = () => ''
}).use(codepenPlugin)
}
describe('codepenPlugin', () => {
it('should work', () => {
const md = createMarkdown()
const code = `\
@[codepen](user/slash)
@[codepen preview](user/slash)
@[codepen preview editable title="codepen" width="100%" height="400px" tab="css,result" theme="dark"](user/slash)
`
expect(md.render(code)).toMatchSnapshot()
})
it('should not work', () => {
const md = createMarkdown()
const code = `\
@[codepen]()
@[codepen]xxx
@[codepen preview](
`
expect(md.render(code)).toMatchSnapshot()
})
})

View File

@ -0,0 +1,58 @@
import type { FileTreeOptions } from '../src/shared/fileTree.js'
import MarkdownIt from 'markdown-it'
import { describe, expect, it } from 'vitest'
import { fileTreePlugin } from '../src/node/container/fileTree.js'
function createMarkdown(options?: FileTreeOptions) {
return new MarkdownIt().use(fileTreePlugin, options)
}
describe('fileTreePlugin', () => {
const code = `\
:::file-tree
- docs
- README.md
- foo.md
- src
- client
- components
- **Navbar.vue**
- index.ts \# comment
- node
- index.ts
- .gitignore
- package.json
:::
::: file-tree title="files"
- src
- js
-
- vue/
- css/
- README.md
:::
::: file-tree icon="simple"
- docs
- src
- a.js
- b.ts
- README.md
:::
::: file-tree
-
-
-
:::
::: file-tree
:::
`
it('should work with default options', () => {
const md = createMarkdown()
expect(md.render(code)).toMatchSnapshot()
})
})

View File

@ -0,0 +1,48 @@
import { describe, expect, it } from 'vitest'
import { getFileIcon } from '../src/node/fileIcons/index.js'
describe('getFileIcon(filename, type)', () => {
it('should find icon with default', () => {
expect(getFileIcon('a.js')).toBe('vscode-icons:file-type-js')
expect(getFileIcon('a.cjs')).toBe('vscode-icons:file-type-js')
expect(getFileIcon('a.mjs')).toBe('vscode-icons:file-type-js')
expect(getFileIcon('a.jsx')).toBe('vscode-icons:file-type-reactjs')
expect(getFileIcon('a.ts')).toBe('vscode-icons:file-type-typescript')
expect(getFileIcon('a.d.ts')).toBe('vscode-icons:file-type-typescript')
expect(getFileIcon('a.cjs.map')).toBe('vscode-icons:file-type-jsmap')
expect(getFileIcon('a.mjs.map')).toBe('vscode-icons:file-type-jsmap')
expect(getFileIcon('vue')).toBe('vscode-icons:file-type-vue')
expect(getFileIcon('Svelte')).toBe('vscode-icons:file-type-svelte')
})
it('should find icon with folder', () => {
expect(getFileIcon('xxx', 'folder')).toBe('vscode-icons:default-folder')
expect(getFileIcon('src', 'folder')).toBe('vscode-icons:folder-type-src')
expect(getFileIcon('src/client', 'folder')).toBe('vscode-icons:folder-type-client')
})
it('should find icon with named file', () => {
expect(getFileIcon('webpack.config.js')).toBe('vscode-icons:file-type-webpack')
expect(getFileIcon('vite.config.mjs')).toBe('vscode-icons:file-type-vite')
expect(getFileIcon('test/vitest.config.js')).toBe('vscode-icons:file-type-js')
})
it('should find icon with extensions', () => {
expect(getFileIcon('a.cpp')).toBe('vscode-icons:file-type-cpp')
expect(getFileIcon('a.spec.mjs')).toBe('vscode-icons:file-type-light-testjs')
})
it('should find icon with partials', () => {
expect(getFileIcon('LICENSE')).toBe('vscode-icons:file-type-license')
expect(getFileIcon('Gemfile')).toBe('vscode-icons:file-type-ruby')
})
it('should return default icon when not find', () => {
expect(getFileIcon('a.abcxxx')).toBe('vscode-icons:default-file')
expect(getFileIcon('a.abcxxx.tbnmmb.z')).toBe('vscode-icons:default-file')
expect(getFileIcon('abc.', 'file')).toBe('vscode-icons:default-file')
expect(getFileIcon('abc.', 'folder')).toBe('vscode-icons:default-folder')
expect(getFileIcon('')).toBe('vscode-icons:default-file')
})
})

View File

@ -0,0 +1,48 @@
import MarkdownIt from 'markdown-it'
import { describe, expect, it } from 'vitest'
import { iconsPlugin } from '../src/node/inline/icons.js'
describe('iconsPlugin', () => {
it('should work', () => {
const md = MarkdownIt().use(iconsPlugin)
expect(md.render(':[mdi:11]:')).toMatchSnapshot()
expect(md.render('**strong** :[mdi:11]: :[mdi:11]:')).toMatchSnapshot()
expect(md.render('**strong**\n:[mdi:11]:\n :[mdi:11]:')).toMatchSnapshot()
})
it('should work with options', () => {
const md = MarkdownIt().use(iconsPlugin, { size: '1.25em', color: '#ccc' })
expect(md.render(':[mdi:11]:')).toMatchSnapshot()
expect(md.render('**strong** :[mdi:11]: :[mdi:11]:')).toMatchSnapshot()
})
it('should work with single icon options', () => {
const md = MarkdownIt().use(iconsPlugin)
expect(md.render(':[mdi:11 36px]:')).toMatchSnapshot()
expect(md.render(':[mdi:11 32px/#eee]:')).toMatchSnapshot()
expect(md.render(':[mdi:11 /#eee]:')).toMatchSnapshot()
expect(md.render(':[mdi:11 32px/]:')).toMatchSnapshot()
expect(md.render(':[mdi:11 /]:')).toMatchSnapshot()
const md2 = MarkdownIt().use(iconsPlugin, { size: '1.25em', color: '#ccc' })
expect(md2.render(':[mdi:11]:')).toMatchSnapshot()
expect(md2.render(':[mdi:11 36px]:')).toMatchSnapshot()
expect(md2.render(':[mdi:11 32px/#eee]:')).toMatchSnapshot()
expect(md2.render(':[mdi:11 /#eee]:')).toMatchSnapshot()
expect(md2.render(':[mdi:11 32px/]:')).toMatchSnapshot()
expect(md2.render(':[mdi:11 /]:')).toMatchSnapshot()
})
it('should not work with invalid icon', () => {
const md = MarkdownIt().use(iconsPlugin)
expect(md.render(':[ mdi:11 ]:')).toMatchSnapshot()
expect(md.render(':[]:')).toMatchSnapshot()
expect(md.render(':[]&')).toMatchSnapshot()
expect(md.render(':[:[')).toMatchSnapshot()
expect(md.render(':[mdi:11')).toMatchSnapshot()
})
})

View File

@ -0,0 +1,40 @@
import MarkdownIt from 'markdown-it'
import { describe, expect, it } from 'vitest'
import { jsfiddlePlugin } from '../src/node/embed/code/jsfiddle.js'
function createMarkdown() {
return MarkdownIt().use((md) => {
md.block.ruler.before('code', 'import_code', () => false)
md.renderer.rules.import_code = () => ''
}).use(jsfiddlePlugin)
}
describe('codeSandboxPlugin', () => {
it('should work', () => {
const md = createMarkdown()
const code = `\
@[jsfiddle](user/id)
@[jsfiddle](user/id)
@[jsfiddle theme="light"](user/id)
@[jsfiddle title="xxx" width="100%" height="500px" theme="dark" tab="js,css,html,result"](user/id)
`
expect(md.render(code)).toMatchSnapshot()
})
it('should not work', () => {
const md = createMarkdown()
const code = `\
@[jsfiddle]()
@[jsfiddle]xxx
@[jsfiddle](
`
expect(md.render(code)).toMatchSnapshot()
})
})

View File

@ -0,0 +1,131 @@
import type { NpmToOptions } from '../src/shared/npmTo.js'
import MarkdownIt from 'markdown-it'
import { describe, expect, it } from 'vitest'
import { codeTabs } from '../src/node/container/codeTabs.js'
import { npmToPlugins, parseLine } from '../src/node/container/npmTo.js'
function createMarkdown(options?: NpmToOptions) {
return new MarkdownIt({
highlight: (str, lang) => `<div class="language-${lang}"><pre><code>${str}</code></pre></div>`,
}).use(codeTabs).use(npmToPlugins, options)
}
const FENCE = '```'
describe('npmToPlugin', () => {
const code = `\
::: npm-to
${FENCE}sh
${FENCE}
:::
::: npm-to
${FENCE}sh
npm install
${FENCE}
:::
::: npm-to
${FENCE}shell
npm install
${FENCE}
:::
::: npm-to
${FENCE}bash
npm install
${FENCE}
:::
::: npm-to
${FENCE}sh
cross-env NODE_ENV=production npm run docs
${FENCE}
:::
::: npm-to
${FENCE}sh
npm i -D package1 package2
npm i --save-peer package3
npm run docs
${FENCE}
:::
::: npm-to
${FENCE}sh
npm install && npm run docs
mkdir foo
${FENCE}
:::
::: npm-to
${FENCE}sh
npm run docs -- --clean-cache --clean-temp
${FENCE}
:::
::: npm-to tabs=","
${FENCE}sh
npm create vuepress-theme-plume@latest
${FENCE}
:::
::: npm-to tabs="npm,pnpm,yarn,bun,deno"
${FENCE}sh
npx vp-update
${FENCE}
:::
::: npm-to
${FENCE}sh
mkdir foo
${FENCE}
:::
::: npm-to
anything
${FENCE}sh
${FENCE}
:::
`
it('should work with default options', () => {
const md = createMarkdown()
expect(md.render(code)).toMatchSnapshot()
})
it('should work width options: { tabs: [npm, yarn, pnpm] }', () => {
const md = createMarkdown({ tabs: ['npm', 'yarn', 'pnpm'] })
expect(md.render(code)).toMatchSnapshot()
})
it('should work width options: [npm, yarn, pnpm]', () => {
const md = createMarkdown(['npm', 'yarn', 'pnpm'])
expect(md.render(code)).toMatchSnapshot()
})
})
describe('parseLine', () => {
it('should work', () => {
expect(parseLine('npm install')).toMatchObject({ env: '', cli: 'npm install', cmd: '' })
expect(parseLine('npx vp-update')).toMatchObject({ env: '', cli: 'npx', cmd: 'vp-update' })
expect(parseLine('npx vp-update --foo')).toMatchObject({ env: '', cli: 'npx', cmd: 'vp-update', scriptArgs: '--foo' })
expect(parseLine('npm run docs')).toMatchObject({ env: '', cli: 'npm run', cmd: 'docs' })
expect(parseLine('npm i -D package1 -- --foo'))
.toMatchObject({ env: '', cli: 'npm i', cmd: 'package1', args: '-D', scriptArgs: '--foo' })
expect(parseLine('npm install -y')).toMatchObject({ env: '', cli: 'npm install', cmd: '', args: '-y' })
expect(parseLine('npm create vuepress-theme-plume my-blog')).toMatchObject({ env: '', cli: 'npm create', cmd: 'vuepress-theme-plume my-blog' })
expect(parseLine('npm create "vuepress-theme-plume my-blog"')).toMatchObject({ env: '', cli: 'npm create', cmd: '"vuepress-theme-plume my-blog"' })
expect(parseLine('npm create vuepress-theme-plume my-blog --foo -B')).toMatchObject({ env: '', cli: 'npm create', cmd: 'vuepress-theme-plume my-blog', args: '--foo -B' })
expect(parseLine('npm run -w="my-workspace" docs')).toMatchObject({ env: '', cli: 'npm run', cmd: 'docs', args: '-w="my-workspace"' })
})
it('should not match', () => {
expect(parseLine('mkdir foo')).toBe(false)
expect(parseLine('')).toBe(false)
})
})

View File

@ -0,0 +1,20 @@
import { describe, expect, it } from 'vitest'
import { parseRect } from '../src/node/utils/parseRect.js'
describe('parseRect(str)', () => {
it('should parse rect', () => {
expect(parseRect('')).toBe('')
expect(parseRect('1')).toBe('1px')
expect(parseRect('1px')).toBe('1px')
expect(parseRect('1%')).toBe('1%')
expect(parseRect('1em')).toBe('1em')
expect(parseRect('1cm')).toBe('1cm')
})
it('should parse rect with unit', () => {
expect(parseRect('1', 'px')).toBe('1px')
expect(parseRect('1px', 'px')).toBe('1px')
expect(parseRect('1%', 'px')).toBe('1%')
expect(parseRect('1em', 'px')).toBe('1em')
})
})

View File

@ -0,0 +1,47 @@
import MarkdownIt from 'markdown-it'
import { describe, expect, it } from 'vitest'
import { pdfPlugin } from '../src/node/embed/pdf.js'
function createMarkdown() {
return MarkdownIt().use((md) => {
md.block.ruler.before('code', 'import_code', () => false)
md.renderer.rules.import_code = () => ''
}).use(pdfPlugin)
}
describe('pdfPlugin', () => {
it('should work', () => {
const md = createMarkdown()
const code = `\
@[pdf](foo.pdf)
@[pdf no-toolbar](foo.pdf)
@[pdf 2](foo.pdf)
@[pdf 2 no-toolbar](foo.pdf)
@[pdf 2 no-toolbar width="100%" height="600px" zoom="1"](foo.pdf)
@[pdf 2 no-toolbar width="100%" zoom="1" ratio="1:1"](foo.pdf)
`
expect(md.render('@[pdf](foo.pdf)')).toMatchSnapshot()
expect(md.render(code)).toMatchSnapshot()
})
it('should not work', () => {
const md = createMarkdown()
const code = `\
@[pdf]()
@[pdf]xxx
@[ pdf]()
@[pdf]
`
expect(md.render(code)).toMatchSnapshot()
})
})

View File

@ -0,0 +1,22 @@
import MarkdownIt from 'markdown-it'
import { describe, expect, it } from 'vitest'
import { plotPlugin } from '../src/node/inline/plot.js'
describe('plotPlugin', () => {
it('should work', () => {
const md = MarkdownIt().use(plotPlugin)
expect(md.render('!!plot!!')).toMatchSnapshot()
expect(md.render('hidden: !!plot!! **strong**')).toMatchSnapshot()
expect(md.render('hidden: \n!!plot!! \n!!plot!!')).toMatchSnapshot()
})
it('should not work with invalid tag', () => {
const md = MarkdownIt().use(plotPlugin)
expect(md.render('!!!!')).toMatchSnapshot()
expect(md.render('!!plot!')).toMatchSnapshot()
expect(md.render('!!!')).toMatchSnapshot()
expect(md.render('!! plot !!')).toMatchSnapshot()
})
})

View File

@ -0,0 +1,35 @@
import { describe, expect, it } from 'vitest'
import { resolveAttrs } from '../src/node/utils/resolveAttrs.js'
describe('resolveAttrs(info)', () => {
it('should resolve attrs', () => {
expect(resolveAttrs('')).toMatchObject({ rawAttrs: '', attrs: {} })
expect(resolveAttrs('a="1"')).toMatchObject({
rawAttrs: 'a="1"',
attrs: { a: '1' },
})
expect(resolveAttrs('a="1" b="2"')).toMatchObject({
rawAttrs: 'a="1" b="2"',
attrs: { a: '1', b: '2' },
})
expect(resolveAttrs('a="1" b="2" c')).toMatchObject({
rawAttrs: 'a="1" b="2" c',
attrs: { a: '1', b: '2', c: true },
})
expect(resolveAttrs('a b="true" c="false"')).toMatchObject({
rawAttrs: 'a b="true" c="false"',
attrs: { a: true, b: true, c: false },
})
})
it('should resolve attrs with include `-`', () => {
expect(resolveAttrs('foo-bar="1" fizz-buzz')).toMatchObject({
rawAttrs: 'foo-bar="1" fizz-buzz',
attrs: { 'fooBar': '1', 'fizzBuzz': true, 'foo-bar': '1', 'fizz-buzz': true },
})
})
})

View File

@ -0,0 +1,26 @@
import { describe, expect, it } from 'vitest'
import { timeToSeconds } from '../src/node/utils/timeToSeconds.js'
describe('timeToSeconds(timeLike)', () => {
it('should return seconds', () => {
expect(timeToSeconds('')).toBe(0)
expect(timeToSeconds('1')).toBe(1)
expect(timeToSeconds('69')).toBe(69)
})
it('should return seconds with h:m:s', () => {
expect(timeToSeconds('1:2')).toBe(62)
expect(timeToSeconds('1:2:3')).toBe(3723)
expect(timeToSeconds('1:2:3.4')).toBe(3723.4)
expect(timeToSeconds('1:2:')).toBe(3720)
expect(timeToSeconds(':2:3')).toBe(123)
expect(timeToSeconds('::3')).toBe(3)
})
it('show return seconds with include incorrect char', () => {
expect(timeToSeconds('1:a:b')).toBe(3600)
expect(timeToSeconds('1:2:a')).toBe(3720)
expect(timeToSeconds('a:b')).toBe(0)
expect(timeToSeconds('a : b : c')).toBe(0)
})
})

View File

@ -0,0 +1,44 @@
import MarkdownIt from 'markdown-it'
import { describe, expect, it } from 'vitest'
import { youtubePlugin } from '../src/node/embed/video/youtube.js'
function createMarkdown() {
return MarkdownIt().use((md) => {
md.block.ruler.before('code', 'import_code', () => false)
md.renderer.rules.import_code = () => ''
}).use(youtubePlugin)
}
describe('youtubePlugin', () => {
it('should work', () => {
const md = createMarkdown()
const code = `\
@[youtube](123456)
@[youtube loop autoplay title="test"](123456)
@[youtube autoplay start="40" end="1:20"](123456)
@[youtube width="100%" height="600px"](123456)
@[youtube width="100%" ratio="16:9"](123456)
`
expect(md.render(code)).toMatchSnapshot()
})
it('should not work', () => {
const md = createMarkdown()
const code = `\
@[youtube]()
@[youtube]xxx
@[ youtube]123456
@[ youtube](123456)
`
expect(md.render(code)).toMatchSnapshot()
})
})

View File

@ -6,7 +6,7 @@ import { definitions, getFileIconName, getFileIconTypeFromExtension } from '../f
import { stringifyProp } from '../utils/stringifyProp.js'
export const codeTabs: PluginWithOptions<CodeTabsOptions> = (md, options: CodeTabsOptions = {}) => {
const getIcon = (filename: string): string | undefined => {
const getIcon = (filename: string): string | void => {
if (options.icon === false)
return undefined
const { named, extensions } = isPlainObject(options.icon) ? options.icon : {}
@ -54,20 +54,18 @@ export const codeTabs: PluginWithOptions<CodeTabsOptions> = (md, options: CodeTa
// Hide all elements excerpt the first fence
for (let i = tokenIndex; i < tokens.length; i++) {
const { block, type } = tokens[i]
const { type } = tokens[i]
if (block) {
if (type === 'code-tabs_tab_close')
break
if (type === 'code-tabs_tab_close')
break
if ((type === 'fence' || type === 'import_code') && !foundFence) {
foundFence = true
continue
}
tokens[i].type = 'code_tab_empty'
tokens[i].hidden = true
if ((type === 'fence' || type === 'import_code') && !foundFence) {
foundFence = true
continue
}
tokens[i].type = 'code_tab_empty'
tokens[i].hidden = true
}
return `<template #tab${index}="{ value, isActive }">`

View File

@ -128,8 +128,8 @@ export function resolveTreeNodeInfo(
}
export function updateInlineToken(inline: Token, info: FileTreeNode, icon: string) {
const children = inline.children
if (!children)
const children = inline.children!
if (!children || children.length === 0)
return
const tokens: Token[] = []

View File

@ -189,7 +189,7 @@ const MANAGERS_CONFIG: CommandConfigs = {
},
}
export function npmToPlugins(md: Markdown, options: NpmToOptions): void {
export function npmToPlugins(md: Markdown, options: NpmToOptions = {}): void {
const type = 'npm-to'
const validate = (info: string): boolean => info.trim().startsWith(type)
@ -197,7 +197,7 @@ export function npmToPlugins(md: Markdown, options: NpmToOptions): void {
const defaultTabs = opt.tabs?.length ? opt.tabs : DEFAULT_TABS
const render = (tokens: Token[], idx: number): string => {
const { attrs } = resolveAttrs(tokens[idx].info.slice(type.length - 1))
const { attrs } = resolveAttrs(tokens[idx].info.trim().slice(type.length))
const tabs = (attrs.tabs ? attrs.tabs.split(/,\s*/) : defaultTabs) as NpmToPackageManager[]
if (tokens[idx].nesting === 1) {
const token = tokens[idx + 1]
@ -229,25 +229,24 @@ function resolveNpmTo(lines: string[], info: string, idx: number, tabs: NpmToPac
for (const line of lines) {
const config = findConfig(line)
if (config && config[tab]) {
const parsed = (map[line] ??= parseLine(line))
const parsed = (map[line] ??= parseLine(line)) as LineParsed
const { cli, flags } = config[tab] as CommandConfigItem
if (parsed) {
let newLine = `${parsed.env ? `${parsed.env} ` : ''}${cli}`
if (parsed.args && flags) {
let args = parsed.args
for (const [key, value] of Object.entries(flags)) {
args = args.replaceAll(key, value)
}
newLine += ` ${args.replace(/\s+-/g, ' -').trim()}`
let newLine = `${parsed.env ? `${parsed.env} ` : ''}${cli}`
if (parsed.args && flags) {
let args = parsed.args
for (const [key, value] of Object.entries(flags)) {
args = args.replaceAll(key, value)
}
if (parsed.cmd)
newLine += ` ${parsed.cmd}`
if (parsed.scriptArgs)
newLine += ` ${parsed.scriptArgs}`
newLines.push(newLine.trim())
newLine += ` ${args.replace(/\s+-/g, ' -').trim()}`
}
if (parsed.cmd)
newLine += ` ${parsed.cmd}`
if (parsed.scriptArgs)
newLine += ` ${parsed.scriptArgs}`
newLines.push(newLine.trim())
}
else {
newLines.push(line)
@ -268,10 +267,11 @@ function findConfig(line: string): CommandConfig | undefined {
}
function validateTabs(tabs: NpmToPackageManager[]): NpmToPackageManager[] {
tabs = tabs.filter(tab => ALLOW_LIST.includes(tab))
if (tabs.length === 0) {
return DEFAULT_TABS
}
return tabs.filter(tab => ALLOW_LIST.includes(tab))
return tabs
}
interface LineParsed {
@ -289,10 +289,20 @@ export function parseLine(line: string): false | LineParsed {
return false
const [, env, cli, rest] = match
if (cli === 'npx')
return { env, cli, cmd: '', scriptArgs: rest?.trim() }
const idx = rest.trim().indexOf(' ')
if (cli === 'npx') {
let cmd = ''
let scriptArgs = ''
if (idx !== -1) {
cmd = rest.slice(0, idx)
scriptArgs = rest.slice(idx + 1).trim()
}
else {
cmd = rest
}
return { env, cli, cmd, scriptArgs }
}
const idx = rest.indexOf(' ')
if (idx === -1)
return { env, cli: `${cli} ${rest.trim()}`, cmd: '' }
@ -301,8 +311,6 @@ export function parseLine(line: string): false | LineParsed {
function parseArgs(line: string): { cmd: string, args?: string, scriptArgs?: string } {
line = line?.trim()
if (!line)
return { cmd: '' }
const [npmArgs, scriptArgs] = line.split(/\s+--\s+/)
let cmd = ''
@ -310,11 +318,11 @@ function parseArgs(line: string): { cmd: string, args?: string, scriptArgs?: str
if (npmArgs[0] !== '-') {
if (npmArgs[0] === '"' || npmArgs[0] === '\'') {
const idx = npmArgs.slice(1).indexOf(npmArgs[0])
cmd = npmArgs.slice(0, idx)
args = npmArgs.slice(idx + 1)
cmd = npmArgs.slice(0, idx + 2)
args = npmArgs.slice(idx + 2)
}
else {
const idx = npmArgs.indexOf(' ')
const idx = npmArgs.indexOf(' -')
if (idx === -1) {
cmd = npmArgs
}
@ -346,16 +354,17 @@ function parseArgs(line: string): { cmd: string, args?: string, scriptArgs?: str
if (i === npmArgs.length - 1) {
value += v
}
const isKey = value[0] === '-'
if (isKey) {
isBool = BOOL_FLAGS.includes(value)
isNextValue = !isBool
}
if (!isKey && !isNextValue) {
cmd += `${value} `
cmd += `${value}`
}
else {
newLine += `${value}${v || ''}`
newLine += `${value}${i !== npmArgs.length - 1 ? v : ''}`
if (!isKey && isNextValue) {
isNextValue = false
}
@ -369,5 +378,5 @@ function parseArgs(line: string): { cmd: string, args?: string, scriptArgs?: str
args = newLine
}
return { cmd, args: args.trim(), scriptArgs }
return { cmd: cmd.trim(), args: args.trim(), scriptArgs }
}

View File

@ -1,5 +1,5 @@
/**
* @[caniuse embed{1,2,3,4}](feature_name)
* @[caniuse embed{-2,4}](feature_name)
* @[caniuse image](feature_name)
*/
import type { PluginWithOptions } from 'markdown-it'
@ -7,10 +7,9 @@ import type MarkdownIt from 'markdown-it'
import type Token from 'markdown-it/lib/token.mjs'
import type { CanIUseMode, CanIUseOptions, CanIUseTokenMeta } from '../../shared/index.js'
import container from 'markdown-it-container'
import { customAlphabet } from 'nanoid'
import { nanoid } from '../utils/nanoid.js'
import { createEmbedRuleBlock } from './createEmbedRuleBlock.js'
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz', 5)
const UNDERLINE_RE = /_+/g
/**
* @example

View File

@ -13,7 +13,7 @@ export const codeSandboxPlugin: PluginWithOptions<never> = (md) => {
createEmbedRuleBlock<CodeSandboxTokenMeta>(md, {
type: 'codesandbox',
syntaxPattern: /^@\[codesandbox(?:\s+(embed|button))?([^\]]*)\]\(([^)]*)\)/,
meta([, type, info = '', source = '']) {
meta([, type, info, source]) {
const { attrs } = resolveAttrs(info)
const [profile, filepath = ''] = source.split('#')
const [user, id] = profile.includes('/') ? profile.split('/') : ['', profile]

View File

@ -15,7 +15,7 @@ export const codepenPlugin: PluginWithOptions<never> = (md) => {
createEmbedRuleBlock<CodepenTokenMeta>(md, {
type: 'codepen',
syntaxPattern: /^@\[codepen([^\]]*)\]\(([^)]*)\)/,
meta: ([, info = '', source = '']) => {
meta: ([, info, source]) => {
const { attrs } = resolveAttrs(info)
const [user, slash] = source.split('/')
@ -27,7 +27,7 @@ export const codepenPlugin: PluginWithOptions<never> = (md) => {
title: attrs.title,
preview: attrs.preview,
editable: attrs.editable,
tab: attrs.tab ?? 'result',
tab: attrs.tab || 'result',
theme: attrs.theme,
}
},
@ -38,9 +38,9 @@ export const codepenPlugin: PluginWithOptions<never> = (md) => {
if (meta.editable) {
params.set('editable', 'true')
}
if (meta.tab) {
params.set('default-tab', meta.tab)
}
params.set('default-tab', meta.tab!)
if (meta.theme) {
params.set('theme-id', meta.theme)
}

View File

@ -12,7 +12,7 @@ export const jsfiddlePlugin: PluginWithOptions<never> = (md) => {
createEmbedRuleBlock<JSFiddleTokenMeta>(md, {
type: 'jsfiddle',
syntaxPattern: /^@\[jsfiddle([^\]]*)\]\(([^)]*)\)/,
meta([, info = '', source]) {
meta([, info, source]) {
const { attrs } = resolveAttrs(info)
const [user, id] = source.split('/')
@ -26,7 +26,7 @@ export const jsfiddlePlugin: PluginWithOptions<never> = (md) => {
theme: attrs.theme || 'dark',
}
},
content: ({ title = 'JS Fiddle', height, width, user, id, tab, theme }) => {
content: ({ title, height, width, user, id, tab, theme }) => {
theme = theme === 'dark' ? '/dark/' : ''
const link = `https://jsfiddle.net/${user}/${id}/embedded/${tab}${theme}`

View File

@ -15,7 +15,7 @@ export const pdfPlugin: PluginWithOptions<never> = (md) => {
type: 'pdf',
// eslint-disable-next-line regexp/no-super-linear-backtracking
syntaxPattern: /^@\[pdf(?:\s+(\d+))?([^\]]*)\]\(([^)]*)\)/,
meta([, page, info = '', src = '']) {
meta([, page, info, src]) {
const { attrs } = resolveAttrs(info)
return {
src,

View File

@ -20,14 +20,14 @@ export const bilibiliPlugin: PluginWithOptions<never> = (md) => {
name: 'video_bilibili',
// eslint-disable-next-line regexp/no-super-linear-backtracking
syntaxPattern: /^@\[bilibili(?:\s+p(\d+))?([^\]]*)\]\(([^)]*)\)/,
meta([, page, info = '', source = '']) {
meta([, page, info, source]) {
const { attrs } = resolveAttrs(info)
const ids = source.trim().split(/\s+/)
const bvid = ids.find(id => id.startsWith('BV'))
const [aid, cid] = ids.filter(id => !id.startsWith('BV'))
return {
page: +page || 1,
page: +page,
bvid,
aid,
cid,

View File

@ -16,7 +16,7 @@ export const youtubePlugin: PluginWithOptions<never> = (md) => {
type: 'youtube',
name: 'video_youtube',
syntaxPattern: /^@\[youtube([^\]]*)\]\(([^)]*)\)/,
meta([, info = '', id = '']) {
meta([, info, id]) {
const { attrs } = resolveAttrs(info)
return {

View File

@ -1,9 +1,9 @@
import { defaultFile, defaultFolder, definitions } from './definitions.js'
export function getFileIcon(fileName: string, type: 'file' | 'folder' = 'file'): string {
export function getFileIcon(fileName: string, type?: 'file' | 'folder'): string {
const name = getFileIconName(fileName, type)
if (!name)
return type === 'file' ? defaultFile : defaultFolder
return type !== 'folder' ? defaultFile : defaultFolder
return name
}
@ -20,7 +20,7 @@ export function getFileIconName(fileName: string, type: 'file' | 'folder' = 'fil
let icon: string | undefined = definitions.named[fileName] || definitions.files[fileName]
if (icon)
return icon
icon = getFileIconTypeFromExtension(fileName)
icon = getFileIconTypeFromExtension(fileName) || undefined
if (icon)
return icon
for (const [partial, partialIcon] of Object.entries(definitions.partials)) {
@ -30,7 +30,7 @@ export function getFileIconName(fileName: string, type: 'file' | 'folder' = 'fil
return icon
}
export function getFileIconTypeFromExtension(fileName: string): string | undefined {
export function getFileIconTypeFromExtension(fileName: string): string | void {
const firstDotIndex = fileName.indexOf('.')
if (firstDotIndex === -1)
return
@ -44,5 +44,4 @@ export function getFileIconTypeFromExtension(fileName: string): string | undefin
return
extension = extension.slice(nextDotIndex)
}
return undefined
}

View File

@ -58,15 +58,14 @@ function createTokenizer(options: IconsOptions): RuleInline {
state.pos = start + 2
const [name, opt = ''] = content.split(/\s+/)
const [size = options.size, color = options.color] = opt.split('/')
const [size, color = options.color] = opt.split('/')
const icon = state.push('vp_iconify_open', 'VPIcon', 1)
icon.markup = openTag
if (name)
icon.attrSet('name', name)
if (size)
icon.attrSet('size', String(size))
icon.attrSet('name', name)
if (size || options.size)
icon.attrSet('size', String(size || options.size))
if (color)
icon.attrSet('color', color)

View File

@ -0,0 +1,3 @@
import { customAlphabet } from 'nanoid'
export const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz', 5)

View File

@ -16,7 +16,7 @@ export function resolveAttrs<T extends Record<string, any> = Record<string, any>
// eslint-disable-next-line no-cond-assign
while (matched = info.match(RE_ATTR_VALUE)) {
const { attr, value } = matched.groups || {}
const { attr, value } = matched.groups!
attrs[attr] = value ?? true
info = info.slice(matched[0].length)
}

View File

@ -5,7 +5,10 @@ export function timeToSeconds(time: string): number {
if (Number.parseFloat(time) === Number(time))
return Number(time)
const [s, m, h] = time.split(':').reverse().map(n => Number(n) || 0)
const [s, m, h = 0] = time
.split(/\s*:\s*/)
.reverse()
.map(n => Number(n) || 0)
return s + m * 60 + h * 3600
}

View File

@ -1,6 +1,6 @@
export interface PlotOptions {
/**
* `=| |=` markdown
* `!! !!` markdown
* @default true
*/
tag?: boolean

641
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

12
vitest.config.ts Normal file
View File

@ -0,0 +1,12 @@
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
coverage: {
enabled: true,
provider: 'istanbul',
all: false,
reporter: ['text', 'clover', 'json'],
},
},
})