@do11y/docs 0.0.10 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -1
- package/dist/plugins/markdown/markdown.d.ts +1 -6
- package/dist/plugins/markdown/markdown.js +1 -21
- package/dist/plugins/meta/meta-mapper.d.ts +42 -0
- package/dist/plugins/meta/meta-mapper.js +50 -0
- package/dist/plugins/meta/meta.d.ts +7 -0
- package/dist/plugins/meta/meta.js +35 -0
- package/dist/plugins/plugins.js +2 -0
- package/dist/plugins/site/site.d.ts +4 -0
- package/package.json +4 -6
- package/template/Example.md +1 -1
- package/template/site/{SandboxPlayground.vue → SandboxIframe.vue} +10 -5
- package/template/site/Site.vue +8 -14
- package/template/site/index.ts +6 -2
- package/template/site/plugins.ts +1 -8
- package/template/site/style.css +5 -41
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { type MarkdownSfcBlocks } from '@mdit-vue/plugin-sfc';
|
|
2
|
-
import type { PluginOptions, MarkdownItEnv as Env } from 'markdown-it-vue-meta';
|
|
3
2
|
import type { PluginSimple } from 'markdown-it';
|
|
4
3
|
import type { Plugin } from 'vite';
|
|
5
4
|
import type MarkdownIt from 'markdown-it';
|
|
@@ -12,12 +11,8 @@ export interface MarkdownPluginOptions {
|
|
|
12
11
|
* The highlight option for `markdown-it`.
|
|
13
12
|
*/
|
|
14
13
|
highlight?: (md: MarkdownIt, code: string, lang: string, attrs: string) => string;
|
|
15
|
-
/**
|
|
16
|
-
* The renderer option for `markdown-it-vue-meta`.
|
|
17
|
-
*/
|
|
18
|
-
metaRenderer?: PluginOptions['renderer'];
|
|
19
14
|
}
|
|
20
|
-
export interface MarkdownItEnv
|
|
15
|
+
export interface MarkdownItEnv {
|
|
21
16
|
/**
|
|
22
17
|
* Blocks extracted by `@mdit-vue/plugin-sfc`.
|
|
23
18
|
*/
|
|
@@ -1,14 +1,8 @@
|
|
|
1
|
-
import { join } from 'node:path';
|
|
2
|
-
import { existsSync } from 'node:fs';
|
|
3
1
|
import { componentPlugin } from '@mdit-vue/plugin-component';
|
|
4
2
|
import { sfcPlugin } from '@mdit-vue/plugin-sfc';
|
|
5
3
|
import { frontmatterPlugin } from '@mdit-vue/plugin-frontmatter';
|
|
6
|
-
import markPlugin from 'markdown-it-mark';
|
|
7
4
|
import attrsPlugin from 'markdown-it-attrs';
|
|
8
|
-
import anchorPlugin from 'markdown-it-anchor';
|
|
9
|
-
import metaPlugin from 'markdown-it-vue-meta';
|
|
10
5
|
import markdown from 'markdown-it';
|
|
11
|
-
import { root } from '../../files.js';
|
|
12
6
|
/**
|
|
13
7
|
* Processes blocks with the lang set to `md` into HTML,
|
|
14
8
|
* and turns `.md` files into single file vue components
|
|
@@ -24,18 +18,6 @@ export default (options) => {
|
|
|
24
18
|
md.use(frontmatterPlugin);
|
|
25
19
|
md.use(sfcPlugin);
|
|
26
20
|
md.use(componentPlugin);
|
|
27
|
-
if (options?.metaRenderer) {
|
|
28
|
-
let tsconfig = join(root, 'tsconfig.app.json');
|
|
29
|
-
if (!existsSync(tsconfig)) {
|
|
30
|
-
tsconfig = join(root, 'tsconfig.json');
|
|
31
|
-
}
|
|
32
|
-
md.use(metaPlugin, {
|
|
33
|
-
renderer: options.metaRenderer,
|
|
34
|
-
tsconfig,
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
md.use(anchorPlugin, { permalink: anchorPlugin.permalink.headerLink() });
|
|
38
|
-
md.use(markPlugin);
|
|
39
21
|
md.use(attrsPlugin);
|
|
40
22
|
if (options?.setup) {
|
|
41
23
|
md.use(options.setup);
|
|
@@ -45,9 +27,7 @@ export default (options) => {
|
|
|
45
27
|
enforce: 'pre',
|
|
46
28
|
transform(code, id) {
|
|
47
29
|
if (id.endsWith('.md')) {
|
|
48
|
-
const env = {
|
|
49
|
-
path: id.replace(/[?#].*$/, ''),
|
|
50
|
-
};
|
|
30
|
+
const env = {};
|
|
51
31
|
const html = md.render(code, env);
|
|
52
32
|
/**
|
|
53
33
|
* If it's a markdown block, return the
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ComponentMeta } from 'vue-component-meta';
|
|
2
|
+
export declare const mapMeta: (meta: ComponentMeta, render: (input: string) => string) => {
|
|
3
|
+
modelValues: {
|
|
4
|
+
default: string | undefined;
|
|
5
|
+
required: boolean;
|
|
6
|
+
name: string;
|
|
7
|
+
type: string;
|
|
8
|
+
description: string;
|
|
9
|
+
deprecated: string | boolean;
|
|
10
|
+
tags: {
|
|
11
|
+
name: string;
|
|
12
|
+
text: string | undefined;
|
|
13
|
+
}[];
|
|
14
|
+
}[];
|
|
15
|
+
props: {
|
|
16
|
+
default: string | undefined;
|
|
17
|
+
required: boolean;
|
|
18
|
+
name: string;
|
|
19
|
+
type: string;
|
|
20
|
+
description: string;
|
|
21
|
+
deprecated: string | boolean;
|
|
22
|
+
tags: {
|
|
23
|
+
name: string;
|
|
24
|
+
text: string | undefined;
|
|
25
|
+
}[];
|
|
26
|
+
}[];
|
|
27
|
+
events: {
|
|
28
|
+
name: string;
|
|
29
|
+
type: string;
|
|
30
|
+
description: string;
|
|
31
|
+
deprecated: string | boolean;
|
|
32
|
+
tags: {
|
|
33
|
+
name: string;
|
|
34
|
+
text: string | undefined;
|
|
35
|
+
}[];
|
|
36
|
+
}[];
|
|
37
|
+
slots: {
|
|
38
|
+
name: string;
|
|
39
|
+
type: string;
|
|
40
|
+
description: string;
|
|
41
|
+
}[];
|
|
42
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export const mapMeta = (meta, render) => {
|
|
2
|
+
const nonGlobalProps = meta.props.filter((prop) => !prop.global);
|
|
3
|
+
const hasAssociatedEvent = (prop) => {
|
|
4
|
+
return meta.events.some((event) => event.name === `update:${prop.name}`);
|
|
5
|
+
};
|
|
6
|
+
const hasAssociatedProp = (event) => {
|
|
7
|
+
return meta.props.some((prop) => `update:${prop.name}` === event.name);
|
|
8
|
+
};
|
|
9
|
+
const getDeprecated = (tags) => {
|
|
10
|
+
const deprecated = getTag(tags, 'deprecated');
|
|
11
|
+
return deprecated ? deprecated.text || true : false;
|
|
12
|
+
};
|
|
13
|
+
const getFilteredTags = (tags) => {
|
|
14
|
+
const filteredTags = tags.filter((t) => !['default', 'deprecated'].includes(t.name));
|
|
15
|
+
return filteredTags.map((tag) => ({
|
|
16
|
+
name: tag.name,
|
|
17
|
+
text: tag.text ? render(tag.text) : undefined,
|
|
18
|
+
}));
|
|
19
|
+
};
|
|
20
|
+
const mapPropertyAndEvent = (prop) => ({
|
|
21
|
+
name: prop.name,
|
|
22
|
+
type: prop.type,
|
|
23
|
+
description: render(prop.description),
|
|
24
|
+
deprecated: getDeprecated(prop.tags),
|
|
25
|
+
tags: getFilteredTags(prop.tags),
|
|
26
|
+
});
|
|
27
|
+
const mapSlotAndExposed = (m) => ({
|
|
28
|
+
name: m.name,
|
|
29
|
+
type: m.type,
|
|
30
|
+
description: render(m.description),
|
|
31
|
+
});
|
|
32
|
+
const mapProperty = (prop) => ({
|
|
33
|
+
...mapPropertyAndEvent(prop),
|
|
34
|
+
default: prop.default || getTag(prop.tags, 'default')?.text,
|
|
35
|
+
required: prop.required,
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
modelValues: nonGlobalProps
|
|
39
|
+
.filter((prop) => hasAssociatedEvent(prop))
|
|
40
|
+
.map((modelValue) => mapProperty(modelValue)),
|
|
41
|
+
props: nonGlobalProps
|
|
42
|
+
.filter((prop) => !hasAssociatedEvent(prop))
|
|
43
|
+
.map((prop) => mapProperty(prop)),
|
|
44
|
+
events: meta.events
|
|
45
|
+
.filter((event) => !hasAssociatedProp(event))
|
|
46
|
+
.map((event) => mapPropertyAndEvent(event)),
|
|
47
|
+
slots: meta.slots.map((slot) => mapSlotAndExposed(slot)),
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
const getTag = (tags, tag) => tags.find(({ name }) => name === tag);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { createChecker } from 'vue-component-meta';
|
|
4
|
+
import markdown from 'markdown-it';
|
|
5
|
+
import { root } from '../../files.js';
|
|
6
|
+
import { mapMeta } from './meta-mapper.js';
|
|
7
|
+
/**
|
|
8
|
+
* Adds `.vue?meta` imports which returns the results of
|
|
9
|
+
* running the component through `vue-component-meta`.
|
|
10
|
+
*/
|
|
11
|
+
export default () => {
|
|
12
|
+
let tsconfig = join(root, 'tsconfig.app.json');
|
|
13
|
+
if (!existsSync(tsconfig)) {
|
|
14
|
+
tsconfig = join(root, 'tsconfig.json');
|
|
15
|
+
}
|
|
16
|
+
const checker = createChecker(tsconfig, {
|
|
17
|
+
noDeclarations: true,
|
|
18
|
+
});
|
|
19
|
+
const md = markdown();
|
|
20
|
+
return {
|
|
21
|
+
name: 'do11y:meta',
|
|
22
|
+
transform(_, id) {
|
|
23
|
+
if (id.endsWith('.vue?meta')) {
|
|
24
|
+
const file = id.replace('?meta', '');
|
|
25
|
+
const meta = checker.getComponentMeta(file);
|
|
26
|
+
const code = `export default ${JSON.stringify(mapMeta(meta, (content) => md.render(content)))}`;
|
|
27
|
+
return {
|
|
28
|
+
code,
|
|
29
|
+
map: { mappings: '' },
|
|
30
|
+
moduleType: 'js',
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
};
|
package/dist/plugins/plugins.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import markdownPlugin from './markdown/markdown.js';
|
|
2
|
+
import metaPlugin from './meta/meta.js';
|
|
2
3
|
import customBlockPlugin from 'v-custom-block';
|
|
3
4
|
import sitePlugin from './site/site.js';
|
|
4
5
|
import routesPlugin from './routes/routes.js';
|
|
@@ -8,6 +9,7 @@ import { pluginOptions } from '../plugin-options.js';
|
|
|
8
9
|
export const plugins = () => [
|
|
9
10
|
uiPlugin(),
|
|
10
11
|
sandboxPlugin(),
|
|
12
|
+
metaPlugin(),
|
|
11
13
|
markdownPlugin(pluginOptions),
|
|
12
14
|
customBlockPlugin('docs'),
|
|
13
15
|
sitePlugin(),
|
|
@@ -10,6 +10,10 @@ export interface Site {
|
|
|
10
10
|
* Additional setup for the app.
|
|
11
11
|
*/
|
|
12
12
|
setup?(app: App, router: Router): void | Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Additional setup for the sandbox app.
|
|
15
|
+
*/
|
|
16
|
+
setupSandbox?(app: App): void | Promise<void>;
|
|
13
17
|
}
|
|
14
18
|
/**
|
|
15
19
|
* Add ability to access the site options (`docs/site/index.ts`)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@do11y/docs",
|
|
3
3
|
"description": "A very bare-bones tool to help document Vue components.",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.12",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -37,18 +37,16 @@
|
|
|
37
37
|
"fast-glob": "^3.3.3",
|
|
38
38
|
"front-matter": "^4.0.2",
|
|
39
39
|
"markdown-it": "^14.1.0",
|
|
40
|
-
"markdown-it-anchor": "^9.2.0",
|
|
41
40
|
"markdown-it-attrs": "^4.3.1",
|
|
42
|
-
"markdown-it-mark": "^4.0.0",
|
|
43
|
-
"markdown-it-vue-meta": "^0.0.2",
|
|
44
41
|
"v-custom-block": "^1.0.67",
|
|
45
|
-
"
|
|
42
|
+
"vue-component-meta": "^3.1.8",
|
|
43
|
+
"@do11y/ui": "0.0.6"
|
|
46
44
|
},
|
|
47
45
|
"devDependencies": {
|
|
48
46
|
"@tsconfig/node24": "^24.0.3",
|
|
49
|
-
"@types/node": "24.10.3",
|
|
50
47
|
"@types/markdown-it": "^14.1.2",
|
|
51
48
|
"@types/markdown-it-attrs": "^4.1.3",
|
|
49
|
+
"@types/node": "24.10.3",
|
|
52
50
|
"typescript": "5.9.3",
|
|
53
51
|
"vite": "^7.2.7"
|
|
54
52
|
},
|
package/template/Example.md
CHANGED
|
@@ -9,7 +9,7 @@ slug: '/example'
|
|
|
9
9
|
const route = useRoute();
|
|
10
10
|
</script>
|
|
11
11
|
|
|
12
|
-
# {{ route.meta.title }}
|
|
12
|
+
# {{ route.meta.title }} {#title}
|
|
13
13
|
|
|
14
14
|
Lorem ipsum dolor sit amet consectetur adipisicing elit. Asperiores, harum itaque consequatur vel
|
|
15
15
|
voluptatem vero labore aliquam fuga veritatis, voluptatum architecto. Obcaecati, vitae delectus
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<iframe ref="iframe" :title="`Sandbox for ${title}`" :src="url" />
|
|
4
|
-
</div>
|
|
5
|
-
|
|
2
|
+
<iframe ref="iframe" :title="`Sandbox for ${title}`" :src="url" />
|
|
6
3
|
<a :href="url" target="_blank" rel="noopener noreferrer">Open in a new tab</a>
|
|
7
4
|
</template>
|
|
8
5
|
|
|
@@ -10,7 +7,15 @@
|
|
|
10
7
|
import { computed, ref } from 'vue';
|
|
11
8
|
|
|
12
9
|
const props = defineProps<{
|
|
10
|
+
/**
|
|
11
|
+
* The iframe title.
|
|
12
|
+
*/
|
|
13
13
|
title: string;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The `id` of the sandbox - which is the filename
|
|
17
|
+
* without the extension `.sandbox.vue`.
|
|
18
|
+
*/
|
|
14
19
|
id: string;
|
|
15
20
|
}>();
|
|
16
21
|
|
|
@@ -19,7 +24,7 @@
|
|
|
19
24
|
const url = computed(() => `${window.location.origin}/sandbox?id=${props.id}`);
|
|
20
25
|
</script>
|
|
21
26
|
|
|
22
|
-
<style
|
|
27
|
+
<style>
|
|
23
28
|
iframe {
|
|
24
29
|
border: none;
|
|
25
30
|
width: 100%;
|
package/template/site/Site.vue
CHANGED
|
@@ -1,26 +1,20 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<nav>
|
|
3
3
|
<ul>
|
|
4
|
-
<
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
</li>
|
|
10
|
-
</template>
|
|
4
|
+
<li v-for="route of routes" :key="route.path">
|
|
5
|
+
<router-link :to="route.path">
|
|
6
|
+
{{ route.meta.title }}
|
|
7
|
+
</router-link>
|
|
8
|
+
</li>
|
|
11
9
|
</ul>
|
|
12
10
|
</nav>
|
|
13
11
|
|
|
14
|
-
<
|
|
12
|
+
<main>
|
|
13
|
+
<RouterView />
|
|
14
|
+
</main>
|
|
15
15
|
</template>
|
|
16
16
|
|
|
17
17
|
<script lang="ts" setup>
|
|
18
18
|
import routes from 'do11y:routes';
|
|
19
19
|
import './style.css';
|
|
20
20
|
</script>
|
|
21
|
-
|
|
22
|
-
<style>
|
|
23
|
-
button {
|
|
24
|
-
width: max-content;
|
|
25
|
-
}
|
|
26
|
-
</style>
|
package/template/site/index.ts
CHANGED
|
@@ -4,7 +4,11 @@ export default {
|
|
|
4
4
|
Site: () => import('./Site.vue'),
|
|
5
5
|
|
|
6
6
|
async setup(app) {
|
|
7
|
-
const
|
|
8
|
-
app.component('
|
|
7
|
+
const SandboxIframe = (await import('./SandboxIframe.vue')).default;
|
|
8
|
+
app.component('SandboxIframe', SandboxIframe);
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
async setupSandbox(app) {
|
|
12
|
+
/** Setup sandbox app */
|
|
9
13
|
},
|
|
10
14
|
} satisfies Site;
|
package/template/site/plugins.ts
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
1
|
import type { PluginOptions } from '@do11y/docs';
|
|
2
2
|
|
|
3
|
-
export default {
|
|
4
|
-
metaRenderer(meta, title) {
|
|
5
|
-
return `
|
|
6
|
-
<h3>${title}</h3>
|
|
7
|
-
<pre><code>${JSON.stringify(meta, null, 2)}</code></pre>
|
|
8
|
-
`;
|
|
9
|
-
},
|
|
10
|
-
} satisfies PluginOptions;
|
|
3
|
+
export default {} satisfies PluginOptions;
|
package/template/site/style.css
CHANGED
|
@@ -15,6 +15,7 @@ html {
|
|
|
15
15
|
margin: 0;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
[id],
|
|
18
19
|
:target {
|
|
19
20
|
scroll-margin-block: 2em;
|
|
20
21
|
}
|
|
@@ -24,54 +25,17 @@ button {
|
|
|
24
25
|
cursor: pointer;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
button {
|
|
28
|
-
color: inherit;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
28
|
button:disabled,
|
|
32
29
|
button[aria-disabled='true'] {
|
|
33
30
|
cursor: default;
|
|
34
31
|
}
|
|
35
32
|
|
|
36
|
-
button,
|
|
37
|
-
input,
|
|
38
|
-
textarea,
|
|
39
|
-
select {
|
|
40
|
-
font: inherit;
|
|
41
|
-
letter-spacing: inherit;
|
|
42
|
-
word-spacing: inherit;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
textarea {
|
|
46
|
-
field-sizing: content;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
a {
|
|
50
|
-
text-underline-position: from-font;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
33
|
pre {
|
|
54
34
|
white-space: pre-wrap;
|
|
35
|
+
inline-size: 100%;
|
|
55
36
|
}
|
|
56
37
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
pre,
|
|
62
|
-
table,
|
|
63
|
-
img,
|
|
64
|
-
svg,
|
|
65
|
-
picture,
|
|
66
|
-
video,
|
|
67
|
-
canvas,
|
|
68
|
-
iframe {
|
|
69
|
-
max-inline-size: 100%;
|
|
70
|
-
min-inline-size: 0;
|
|
71
|
-
|
|
72
|
-
display: block;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
[id] {
|
|
76
|
-
scroll-margin-top: 2rem;
|
|
38
|
+
body {
|
|
39
|
+
margin-inline: auto;
|
|
40
|
+
inline-size: min(90dvw, 50rem);
|
|
77
41
|
}
|