@docfy/ember 0.4.8 → 0.6.0
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/.docfy-config.js +1 -0
- package/docs/writing-demos.md +51 -1
- package/dummy-docs/packages/ember/plugins/manual-demo-insertion-demo/tomster.md +15 -0
- package/dummy-docs/packages/ember/plugins/manual-demo-insertion-demo/zoey.md +9 -0
- package/dummy-docs/packages/ember/plugins/manual-demo-insertion.md +31 -0
- package/helpers/docfy-eq.d.ts +5 -1
- package/lib/index.js +6 -6
- package/lib/plugins/extract-demos-to-components.js +68 -16
- package/lib/plugins/preview-template.js +6 -6
- package/lib/plugins/replace-internal-links-with-docfy-link.js +4 -4
- package/lib/plugins/utils.js +9 -9
- package/package.json +58 -45
- package/src/plugins/extract-demos-to-components.ts +74 -8
- package/tsconfig.json +1 -0
package/.docfy-config.js
CHANGED
package/docs/writing-demos.md
CHANGED
|
@@ -22,7 +22,7 @@ Below you can see how a demo markdown file looks like.
|
|
|
22
22
|
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
The demo will be
|
|
25
|
+
The demo will be inserted into the owner file as a new section called "Examples";
|
|
26
26
|
you can see it below.
|
|
27
27
|
|
|
28
28
|
Please note that you must pass a metadata to the code block, it can be seen
|
|
@@ -57,3 +57,53 @@ And here you can see how it looks like when rendered:
|
|
|
57
57
|
```hbs preview-template
|
|
58
58
|
Click in the link to navigate to the home page: <DocfyLink @to="/">Home</DocfyLink>
|
|
59
59
|
```
|
|
60
|
+
|
|
61
|
+
## Manual Insertion
|
|
62
|
+
|
|
63
|
+
To make getting started with Docfy as simple as possible, by default demos will
|
|
64
|
+
be automatically inserted into the owner file under a new section called
|
|
65
|
+
"Examples" before the second heading of the page.
|
|
66
|
+
|
|
67
|
+
If you want more control over how demos are inserted into the page, you can
|
|
68
|
+
declare `manualDemoInsertion` in a markdown page's frontmatter.
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
---
|
|
72
|
+
title: Document with many examples
|
|
73
|
+
manualDemoInsertion: true
|
|
74
|
+
---
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
When a page is using `manualDemoInsertion`, by default no demos are inserted
|
|
78
|
+
into the page. Instead, you must provide markers in your markdown that will be
|
|
79
|
+
replaced. They follow the form `[[demo:name-of-demo]]`.
|
|
80
|
+
|
|
81
|
+
```md
|
|
82
|
+
# Title here
|
|
83
|
+
|
|
84
|
+
The demo will be inserted after this line.
|
|
85
|
+
|
|
86
|
+
[[demo:demo1]]
|
|
87
|
+
|
|
88
|
+
And the prose of the document will continue exactly how the author wishes.
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Sometimes as an author, you want control over where in the page demos will be
|
|
92
|
+
inserted, but you don't need to control this location demo by demo. As a
|
|
93
|
+
shorthand, you can provide the `[[demos-all]]` marker to insert all demos.
|
|
94
|
+
|
|
95
|
+
```md
|
|
96
|
+
# Title here
|
|
97
|
+
|
|
98
|
+
All demos go here.
|
|
99
|
+
|
|
100
|
+
[[demos-all]]
|
|
101
|
+
|
|
102
|
+
Below is the equivalent if you had to mark all demos individually.
|
|
103
|
+
|
|
104
|
+
[[demo:demo1]]
|
|
105
|
+
|
|
106
|
+
[[demo:demo2]]
|
|
107
|
+
|
|
108
|
+
[[demo:demo3]]
|
|
109
|
+
```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
category: ember
|
|
3
|
+
subcategory: plugins
|
|
4
|
+
manualDemoInsertion: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Manual Demo Insertion
|
|
8
|
+
|
|
9
|
+
Docfy will automatically insert demos for a page into the page at build time. However, this convenience comes at the cost of choosing where the demos should be rendered.
|
|
10
|
+
|
|
11
|
+
If you want control over where demos are rendered in a page, add `manualDemoInsertion: true` to your page's frontmatter. Then you can use `[[demo:name]]` or `[[demos-all]]` to mark where a specific demo or all demos should be rendered.
|
|
12
|
+
|
|
13
|
+
These markers must be on their own line!
|
|
14
|
+
|
|
15
|
+
## It works like this
|
|
16
|
+
|
|
17
|
+
Here is the tomster demo
|
|
18
|
+
|
|
19
|
+
[[demo:tomster]]
|
|
20
|
+
|
|
21
|
+
And here is the zoey demo
|
|
22
|
+
|
|
23
|
+
[[demo:zoey]]
|
|
24
|
+
|
|
25
|
+
## Or you can add all demos
|
|
26
|
+
|
|
27
|
+
[[demos-all]]
|
|
28
|
+
|
|
29
|
+
## Conclusion
|
|
30
|
+
|
|
31
|
+
With Docfy you get demos added to your pages for free, but with a little more work you can also get a bit more control.
|
package/helpers/docfy-eq.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
export declare function docfyEq(params: unknown[]): boolean;
|
|
2
|
-
declare const _default:
|
|
2
|
+
declare const _default: import("@ember/component/helper").FunctionBasedHelper<{
|
|
3
|
+
PositionalArgs: unknown[];
|
|
4
|
+
NamedArgs: Record<string, unknown>;
|
|
5
|
+
Return: boolean;
|
|
6
|
+
}>;
|
|
3
7
|
export default _default;
|
package/lib/index.js
CHANGED
|
@@ -26,7 +26,7 @@ const get_config_1 = __importDefault(require("./get-config"));
|
|
|
26
26
|
const utils_1 = require("./plugins/utils");
|
|
27
27
|
const calculate_cache_key_for_tree_1 = __importDefault(require("calculate-cache-key-for-tree"));
|
|
28
28
|
const debug_1 = __importDefault(require("debug"));
|
|
29
|
-
const debug = debug_1.default('@docfy/ember');
|
|
29
|
+
const debug = (0, debug_1.default)('@docfy/ember');
|
|
30
30
|
const templateOnlyComponent = `
|
|
31
31
|
import Component from '@glimmer/component';
|
|
32
32
|
export default class extends Component {}
|
|
@@ -72,7 +72,7 @@ class DocfyBroccoli extends broccoli_plugin_1.default {
|
|
|
72
72
|
ensureDirectoryExistence(fileName);
|
|
73
73
|
fs_1.default.writeFileSync(fileName, page.rendered);
|
|
74
74
|
const demoComponents = page.pluginData.demoComponents;
|
|
75
|
-
if (utils_1.isDemoComponents(demoComponents)) {
|
|
75
|
+
if ((0, utils_1.isDemoComponents)(demoComponents)) {
|
|
76
76
|
demoComponents.forEach((component) => {
|
|
77
77
|
component.chunks.forEach((chunk) => {
|
|
78
78
|
const chunkPath = path_1.default.join(this.outputPath, 'components', `${component.name.dashCase}.${chunk.ext}`);
|
|
@@ -104,7 +104,7 @@ module.exports = {
|
|
|
104
104
|
docfyConfig: undefined,
|
|
105
105
|
included(...args) {
|
|
106
106
|
if (!isDeepAddonInstance(this)) {
|
|
107
|
-
this.docfyConfig = get_config_1.default(this.project.root);
|
|
107
|
+
this.docfyConfig = (0, get_config_1.default)(this.project.root);
|
|
108
108
|
this.bridge = new broccoli_bridge_1.default();
|
|
109
109
|
}
|
|
110
110
|
this._super.included.apply(this, args);
|
|
@@ -115,10 +115,10 @@ module.exports = {
|
|
|
115
115
|
switch (treeType) {
|
|
116
116
|
case 'app':
|
|
117
117
|
case 'addon': {
|
|
118
|
-
return calculate_cache_key_for_tree_1.default(treeType, this, [this.docfyConfig]);
|
|
118
|
+
return (0, calculate_cache_key_for_tree_1.default)(treeType, this, [this.docfyConfig]);
|
|
119
119
|
}
|
|
120
120
|
default:
|
|
121
|
-
return calculate_cache_key_for_tree_1.default(treeType, this);
|
|
121
|
+
return (0, calculate_cache_key_for_tree_1.default)(treeType, this);
|
|
122
122
|
}
|
|
123
123
|
},
|
|
124
124
|
treeForApp(tree) {
|
|
@@ -144,7 +144,7 @@ module.exports = {
|
|
|
144
144
|
}
|
|
145
145
|
const EmberApp = require('ember-cli/lib/broccoli/ember-app'); // eslint-disable-line
|
|
146
146
|
const modulePrefix = this.project.config(EmberApp.env()).modulePrefix;
|
|
147
|
-
trees.push(new broccoli_file_creator_1.default('output.js', docfy_output_template_1.default(modulePrefix)));
|
|
147
|
+
trees.push(new broccoli_file_creator_1.default('output.js', (0, docfy_output_template_1.default)(modulePrefix)));
|
|
148
148
|
return new broccoli_merge_trees_1.default(trees);
|
|
149
149
|
},
|
|
150
150
|
treeForPublic() {
|
|
@@ -18,17 +18,24 @@ const path_1 = __importDefault(require("path"));
|
|
|
18
18
|
* This is necessary for apps using remark-autolink-headings, for example.
|
|
19
19
|
*/
|
|
20
20
|
function createHeading(ctx) {
|
|
21
|
-
const heading = ctx.remark.runSync(ctx.remark.parse('## Examples'))
|
|
22
|
-
.children[0];
|
|
21
|
+
const heading = ctx.remark.runSync(ctx.remark.parse('## Examples')).children[0];
|
|
23
22
|
heading.depth = 2;
|
|
24
23
|
return heading;
|
|
25
24
|
}
|
|
25
|
+
const isTextMarker = (node) => node.type === 'paragraph' &&
|
|
26
|
+
node.children.length === 1 &&
|
|
27
|
+
node.children[0].type === 'text';
|
|
28
|
+
const demoMarkerRegex = /^\[\[demo:(.+?)\]\]$/;
|
|
29
|
+
const demoMarker = (node) => isTextMarker(node) && demoMarkerRegex.test(node.children[0].value);
|
|
30
|
+
const demosAllMarkerRegex = /^\[\[demos-all\]\]$/;
|
|
31
|
+
const demosAllMarker = (node) => isTextMarker(node) &&
|
|
32
|
+
demosAllMarkerRegex.test(node.children[0].value);
|
|
26
33
|
/*
|
|
27
34
|
* Insert Demo nodes into the page.
|
|
28
35
|
*/
|
|
29
36
|
function insertDemoNodesIntoPage(page, toInsert) {
|
|
30
37
|
if (Array.isArray(page.ast.children)) {
|
|
31
|
-
const secondHeading = unist_util_find_1.default(page.ast, (node) => node.type === 'heading' && node.depth !== 1);
|
|
38
|
+
const secondHeading = (0, unist_util_find_1.default)(page.ast, (node) => node.type === 'heading' && node.depth !== 1);
|
|
32
39
|
if (secondHeading) {
|
|
33
40
|
const index = page.ast.children.findIndex((el) => el === secondHeading);
|
|
34
41
|
page.ast.children.splice(index, 0, ...toInsert);
|
|
@@ -38,7 +45,43 @@ function insertDemoNodesIntoPage(page, toInsert) {
|
|
|
38
45
|
}
|
|
39
46
|
}
|
|
40
47
|
}
|
|
41
|
-
|
|
48
|
+
function replaceDemoMarkers(page, demos) {
|
|
49
|
+
if (Array.isArray(page.ast.children)) {
|
|
50
|
+
const markers = [];
|
|
51
|
+
const allMarkers = [];
|
|
52
|
+
(0, unist_util_visit_1.default)(page.ast, 'paragraph', (node) => {
|
|
53
|
+
if (demoMarker(node))
|
|
54
|
+
markers.push(node);
|
|
55
|
+
if (demosAllMarker(node))
|
|
56
|
+
allMarkers.push(node);
|
|
57
|
+
});
|
|
58
|
+
markers.forEach((marker) => {
|
|
59
|
+
const child = marker.children[0];
|
|
60
|
+
const matches = child.value.match(demoMarkerRegex);
|
|
61
|
+
if (!matches)
|
|
62
|
+
return;
|
|
63
|
+
// TODO: This is an inner loop and can cause perf issues if someone
|
|
64
|
+
// out there has many demos on a single page. It would be better to
|
|
65
|
+
// create a demo component hash that can be looked up by demo name.
|
|
66
|
+
const demoName = matches[1];
|
|
67
|
+
const demo = demos.find((d) => d.name.dashCase.endsWith(demoName));
|
|
68
|
+
if (!demo) {
|
|
69
|
+
console.warn(`Found demo marker "${demoName}" with no matching demo component in ${page.source}`);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
marker.type = 'div';
|
|
73
|
+
marker.children.splice(0, 1, ...(0, utils_1.createDemoNodes)(demo));
|
|
74
|
+
});
|
|
75
|
+
allMarkers.forEach((marker) => {
|
|
76
|
+
const demoNodes = demos
|
|
77
|
+
.map((component) => (0, utils_1.createDemoNodes)(component))
|
|
78
|
+
.flat();
|
|
79
|
+
marker.type = 'div';
|
|
80
|
+
marker.children.splice(0, 1, ...demoNodes);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.default = (0, plugin_1.default)({
|
|
42
85
|
runWithMdast(ctx) {
|
|
43
86
|
const seenNames = new Set();
|
|
44
87
|
ctx.pages.forEach((page) => {
|
|
@@ -46,12 +89,12 @@ exports.default = plugin_1.default({
|
|
|
46
89
|
const demoComponents = [];
|
|
47
90
|
page.demos.forEach((demo) => {
|
|
48
91
|
const chunks = [];
|
|
49
|
-
unist_util_visit_1.default(demo.ast, 'code', (node) => {
|
|
92
|
+
(0, unist_util_visit_1.default)(demo.ast, 'code', (node) => {
|
|
50
93
|
if (['component', 'template', 'styles'].includes(node.meta || '')) {
|
|
51
94
|
chunks.push({
|
|
52
95
|
snippet: node,
|
|
53
96
|
code: node.value.replace(/\\{{/g, '{{'),
|
|
54
|
-
ext: utils_1.getExt(node.lang || (node.meta === 'template' ? 'hbs' : 'js')),
|
|
97
|
+
ext: (0, utils_1.getExt)(node.lang || (node.meta === 'template' ? 'hbs' : 'js')),
|
|
55
98
|
type: node.meta
|
|
56
99
|
});
|
|
57
100
|
}
|
|
@@ -59,8 +102,8 @@ exports.default = plugin_1.default({
|
|
|
59
102
|
// 1. exclude extension
|
|
60
103
|
// 2. remove /index.md because of web conventions
|
|
61
104
|
const baseName = page.source.replace('/index.md', '').split('.')[0];
|
|
62
|
-
const componentName = utils_1.generateDemoComponentName(`docfy-demo-${baseName}-${path_1.default.basename(demo.source).split('.')[0]}`, seenNames);
|
|
63
|
-
const demoTitle = unist_util_find_1.default(demo.ast, (node) => node.type === 'heading' && node.depth === 1);
|
|
105
|
+
const componentName = (0, utils_1.generateDemoComponentName)(`docfy-demo-${baseName}-${path_1.default.basename(demo.source).split('.')[0]}`, seenNames);
|
|
106
|
+
const demoTitle = (0, unist_util_find_1.default)(demo.ast, (node) => node.type === 'heading' && node.depth === 1);
|
|
64
107
|
if (demoTitle) {
|
|
65
108
|
demoTitle.depth = 3;
|
|
66
109
|
demoTitle.data = Object.assign(Object.assign({}, (demoTitle.data || {})), { id: componentName.dashCase, docfyDelete: true // mark the heading to be deleted by @docfy/core TOC plugin
|
|
@@ -70,22 +113,31 @@ exports.default = plugin_1.default({
|
|
|
70
113
|
name: componentName,
|
|
71
114
|
chunks,
|
|
72
115
|
description: {
|
|
73
|
-
title: demoTitle ? mdast_util_to_string_1.default(demoTitle) : undefined,
|
|
116
|
+
title: demoTitle ? (0, mdast_util_to_string_1.default)(demoTitle) : undefined,
|
|
74
117
|
ast: demo.ast,
|
|
75
118
|
editUrl: demo.meta.editUrl
|
|
76
119
|
}
|
|
77
120
|
});
|
|
78
121
|
// Delete used code blocks
|
|
79
122
|
chunks.forEach(({ snippet }) => {
|
|
80
|
-
utils_1.deleteNode(demo.ast.children, snippet);
|
|
123
|
+
(0, utils_1.deleteNode)(demo.ast.children, snippet);
|
|
81
124
|
});
|
|
82
125
|
});
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
126
|
+
if (page.meta.frontmatter.manualDemoInsertion) {
|
|
127
|
+
// Manual demo insertion inserts demos into markdown files
|
|
128
|
+
// wherever there is a demo marker ([[demo:name]] or [[demos-all]])
|
|
129
|
+
replaceDemoMarkers(page, demoComponents);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
// Automatic demo insertion creates an Example block after
|
|
133
|
+
// the first heading.
|
|
134
|
+
const toInsert = [createHeading(ctx)];
|
|
135
|
+
demoComponents.forEach((component) => {
|
|
136
|
+
toInsert.push(...(0, utils_1.createDemoNodes)(component));
|
|
137
|
+
});
|
|
138
|
+
insertDemoNodesIntoPage(page, toInsert);
|
|
139
|
+
}
|
|
140
|
+
if ((0, utils_1.isDemoComponents)(page.pluginData.demoComponents)) {
|
|
89
141
|
page.pluginData.demoComponents.push(...demoComponents);
|
|
90
142
|
}
|
|
91
143
|
else {
|
|
@@ -7,20 +7,20 @@ const unist_util_visit_1 = __importDefault(require("unist-util-visit"));
|
|
|
7
7
|
const plugin_1 = __importDefault(require("@docfy/core/lib/plugin"));
|
|
8
8
|
const utils_1 = require("./utils");
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
|
-
exports.default = plugin_1.default({
|
|
10
|
+
exports.default = (0, plugin_1.default)({
|
|
11
11
|
runWithMdast(ctx) {
|
|
12
12
|
const seenNames = new Set();
|
|
13
13
|
ctx.pages.forEach((page) => {
|
|
14
14
|
const demoComponents = [];
|
|
15
|
-
unist_util_visit_1.default(page.ast, 'code', (node) => {
|
|
15
|
+
(0, unist_util_visit_1.default)(page.ast, 'code', (node) => {
|
|
16
16
|
if (['preview-template'].includes(node.meta || '')) {
|
|
17
17
|
demoComponents.push({
|
|
18
|
-
name: utils_1.generateDemoComponentName(`docfy-demo-preview-${path_1.default.basename(page.meta.url)}`, seenNames),
|
|
18
|
+
name: (0, utils_1.generateDemoComponentName)(`docfy-demo-preview-${path_1.default.basename(page.meta.url)}`, seenNames),
|
|
19
19
|
chunks: [
|
|
20
20
|
{
|
|
21
21
|
snippet: node,
|
|
22
22
|
code: node.value.replace(/\\{{/g, '{{'),
|
|
23
|
-
ext: utils_1.getExt(node.lang || 'hbs'),
|
|
23
|
+
ext: (0, utils_1.getExt)(node.lang || 'hbs'),
|
|
24
24
|
type: node.meta
|
|
25
25
|
}
|
|
26
26
|
]
|
|
@@ -28,9 +28,9 @@ exports.default = plugin_1.default({
|
|
|
28
28
|
}
|
|
29
29
|
});
|
|
30
30
|
demoComponents.forEach((demoComponent) => {
|
|
31
|
-
utils_1.replaceNode(page.ast.children, demoComponent.chunks[0].snippet, ...utils_1.createDemoNodes(demoComponent));
|
|
31
|
+
(0, utils_1.replaceNode)(page.ast.children, demoComponent.chunks[0].snippet, ...(0, utils_1.createDemoNodes)(demoComponent));
|
|
32
32
|
});
|
|
33
|
-
if (utils_1.isDemoComponents(page.pluginData.demoComponents)) {
|
|
33
|
+
if ((0, utils_1.isDemoComponents)(page.pluginData.demoComponents)) {
|
|
34
34
|
page.pluginData.demoComponents.push(...demoComponents);
|
|
35
35
|
}
|
|
36
36
|
else {
|
|
@@ -7,7 +7,7 @@ const plugin_1 = __importDefault(require("@docfy/core/lib/plugin"));
|
|
|
7
7
|
const unist_util_visit_1 = __importDefault(require("unist-util-visit"));
|
|
8
8
|
const unist_builder_1 = __importDefault(require("unist-builder"));
|
|
9
9
|
function visitor(page) {
|
|
10
|
-
unist_util_visit_1.default(page.ast, 'link', (node, index, parent) => {
|
|
10
|
+
(0, unist_util_visit_1.default)(page.ast, 'link', (node, index, parent) => {
|
|
11
11
|
if (node.url[0] === '/') {
|
|
12
12
|
const data = node.data || (node.data = {});
|
|
13
13
|
const props = (data.hProperties || (data.hProperties = {}));
|
|
@@ -18,9 +18,9 @@ function visitor(page) {
|
|
|
18
18
|
})
|
|
19
19
|
.join(' ');
|
|
20
20
|
const toInsert = [
|
|
21
|
-
unist_builder_1.default('html', `<DocfyLink @to="${urlParts[0]}" ${urlParts[1] ? `@anchor="${urlParts[1]}"` : ''} ${attributes}>`),
|
|
21
|
+
(0, unist_builder_1.default)('html', `<DocfyLink @to="${urlParts[0]}" ${urlParts[1] ? `@anchor="${urlParts[1]}"` : ''} ${attributes}>`),
|
|
22
22
|
...node.children,
|
|
23
|
-
unist_builder_1.default('html', `</DocfyLink>`)
|
|
23
|
+
(0, unist_builder_1.default)('html', `</DocfyLink>`)
|
|
24
24
|
];
|
|
25
25
|
parent === null || parent === void 0 ? void 0 : parent.children.splice(index, 1, ...toInsert);
|
|
26
26
|
}
|
|
@@ -30,7 +30,7 @@ function visitor(page) {
|
|
|
30
30
|
* This function finds all the links starting with an `/` and replace them with
|
|
31
31
|
* the `DocfyLink` component.
|
|
32
32
|
*/
|
|
33
|
-
exports.default = plugin_1.default({
|
|
33
|
+
exports.default = (0, plugin_1.default)({
|
|
34
34
|
runWithMdast(ctx) {
|
|
35
35
|
ctx.pages.forEach((page) => {
|
|
36
36
|
visitor(page);
|
package/lib/plugins/utils.js
CHANGED
|
@@ -27,30 +27,30 @@ const unist_builder_1 = __importDefault(require("unist-builder"));
|
|
|
27
27
|
*/
|
|
28
28
|
function createDemoNodes(component) {
|
|
29
29
|
const nodes = [
|
|
30
|
-
unist_builder_1.default('html', `<DocfyDemo @id="${component.name.dashCase}" as |demo|>`)
|
|
30
|
+
(0, unist_builder_1.default)('html', `<DocfyDemo @id="${component.name.dashCase}" as |demo|>`)
|
|
31
31
|
];
|
|
32
32
|
if (component.description) {
|
|
33
|
-
nodes.push(unist_builder_1.default('html', `<demo.Description
|
|
33
|
+
nodes.push((0, unist_builder_1.default)('html', `<demo.Description
|
|
34
34
|
${component.description.title
|
|
35
35
|
? `@title="${component.description.title}" `
|
|
36
36
|
: ''}${component.description.editUrl
|
|
37
37
|
? `@editUrl="${component.description.editUrl}"`
|
|
38
|
-
: ''}>`), component.description.ast, unist_builder_1.default('html', '</demo.Description>'));
|
|
38
|
+
: ''}>`), component.description.ast, (0, unist_builder_1.default)('html', '</demo.Description>'));
|
|
39
39
|
}
|
|
40
|
-
nodes.push(unist_builder_1.default('html', '<demo.Example>'), unist_builder_1.default('html', `<${component.name.pascalCase} />`), unist_builder_1.default('html', '</demo.Example>'));
|
|
40
|
+
nodes.push((0, unist_builder_1.default)('html', '<demo.Example>'), (0, unist_builder_1.default)('html', `<${component.name.pascalCase} />`), (0, unist_builder_1.default)('html', '</demo.Example>'));
|
|
41
41
|
if (component.chunks.length > 1) {
|
|
42
|
-
nodes.push(unist_builder_1.default('html', '<demo.Snippets as |Snippet|>'));
|
|
42
|
+
nodes.push((0, unist_builder_1.default)('html', '<demo.Snippets as |Snippet|>'));
|
|
43
43
|
component.chunks.forEach((chunk) => {
|
|
44
|
-
nodes.push(unist_builder_1.default('html', `<Snippet @name="${chunk.type}">`), chunk.snippet, unist_builder_1.default('html', '</Snippet>'));
|
|
44
|
+
nodes.push((0, unist_builder_1.default)('html', `<Snippet @name="${chunk.type}">`), chunk.snippet, (0, unist_builder_1.default)('html', '</Snippet>'));
|
|
45
45
|
});
|
|
46
|
-
nodes.push(unist_builder_1.default('html', '</demo.Snippets>'));
|
|
46
|
+
nodes.push((0, unist_builder_1.default)('html', '</demo.Snippets>'));
|
|
47
47
|
}
|
|
48
48
|
else {
|
|
49
49
|
component.chunks.forEach((chunk) => {
|
|
50
|
-
nodes.push(unist_builder_1.default('html', `<demo.Snippet @name="${chunk.type}">`), chunk.snippet, unist_builder_1.default('html', '</demo.Snippet>'));
|
|
50
|
+
nodes.push((0, unist_builder_1.default)('html', `<demo.Snippet @name="${chunk.type}">`), chunk.snippet, (0, unist_builder_1.default)('html', '</demo.Snippet>'));
|
|
51
51
|
});
|
|
52
52
|
}
|
|
53
|
-
nodes.push(unist_builder_1.default('html', '</DocfyDemo>'));
|
|
53
|
+
nodes.push((0, unist_builder_1.default)('html', '</DocfyDemo>'));
|
|
54
54
|
return nodes;
|
|
55
55
|
}
|
|
56
56
|
exports.createDemoNodes = createDemoNodes;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docfy/ember",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Ember integration with Docfy",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ember-addon",
|
|
@@ -30,81 +30,94 @@
|
|
|
30
30
|
"test:ember-compatibility": "echo 'ember try:each TODO'"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@docfy/core": "^0.
|
|
33
|
+
"@docfy/core": "^0.6.0",
|
|
34
34
|
"broccoli-bridge": "^1.0.0",
|
|
35
35
|
"broccoli-file-creator": "^2.1.1",
|
|
36
|
-
"broccoli-funnel": "^3.0.
|
|
36
|
+
"broccoli-funnel": "^3.0.8",
|
|
37
37
|
"broccoli-merge-trees": "^4.2.0",
|
|
38
38
|
"broccoli-node-api": "^1.7.0",
|
|
39
|
-
"broccoli-plugin": "^4.0.
|
|
40
|
-
"broccoli-source": "^3.0.
|
|
39
|
+
"broccoli-plugin": "^4.0.7",
|
|
40
|
+
"broccoli-source": "^3.0.1",
|
|
41
41
|
"calculate-cache-key-for-tree": "2.0.0",
|
|
42
|
-
"debug": "^4.3.
|
|
43
|
-
"ember-cli-babel": "^7.
|
|
44
|
-
"ember-cli-htmlbars": "^
|
|
45
|
-
"ember-cli-typescript": "^4.
|
|
46
|
-
"ember-get-config": "^0.
|
|
42
|
+
"debug": "^4.3.3",
|
|
43
|
+
"ember-cli-babel": "^7.26.11",
|
|
44
|
+
"ember-cli-htmlbars": "^6.0.1",
|
|
45
|
+
"ember-cli-typescript": "^4.2.1",
|
|
46
|
+
"ember-get-config": "^1.0.2",
|
|
47
47
|
"mdast-util-to-string": "^2.0.0",
|
|
48
|
-
"remark-hbs": "^0.4.
|
|
48
|
+
"remark-hbs": "^0.4.1",
|
|
49
49
|
"unist-builder": "^2.0.3",
|
|
50
50
|
"unist-util-find": "^1.0.2",
|
|
51
51
|
"unist-util-visit": "^2.0.2"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@
|
|
54
|
+
"@babel/helper-define-map": "^7.16.7",
|
|
55
|
+
"@docfy/plugin-with-prose": "^0.6.0",
|
|
55
56
|
"@ember/optional-features": "^2.0.0",
|
|
56
|
-
"@ember/test-helpers": "^2.
|
|
57
|
-
"@embroider/compat": "^0.
|
|
58
|
-
"@embroider/core": "^0.
|
|
59
|
-
"@embroider/webpack": "^0.
|
|
60
|
-
"@glimmer/component": "^1.0.
|
|
61
|
-
"@glimmer/tracking": "^1.0.
|
|
57
|
+
"@ember/test-helpers": "^2.6.0",
|
|
58
|
+
"@embroider/compat": "^1.0.0",
|
|
59
|
+
"@embroider/core": "^1.0.0",
|
|
60
|
+
"@embroider/webpack": "^1.0.0",
|
|
61
|
+
"@glimmer/component": "^1.0.4",
|
|
62
|
+
"@glimmer/tracking": "^1.0.4",
|
|
62
63
|
"@mapbox/rehype-prism": "^0.5.0",
|
|
63
64
|
"@tailwindcss/typography": "^0.4.0",
|
|
64
|
-
"@types/
|
|
65
|
-
"@types/ember": "^
|
|
66
|
-
"@types/
|
|
67
|
-
"@types/
|
|
68
|
-
"@types/
|
|
69
|
-
"@types/
|
|
70
|
-
"@types/
|
|
65
|
+
"@types/ember-qunit": "^5.0.0",
|
|
66
|
+
"@types/ember-resolver": "^5.0.11",
|
|
67
|
+
"@types/ember__application": "^4.0.0",
|
|
68
|
+
"@types/ember__array": "^4.0.1",
|
|
69
|
+
"@types/ember__component": "^4.0.1",
|
|
70
|
+
"@types/ember__debug": "^4.0.0",
|
|
71
|
+
"@types/ember__error": "^4.0.0",
|
|
72
|
+
"@types/ember__object": "^4.0.0",
|
|
73
|
+
"@types/ember__routing": "^4.0.2",
|
|
74
|
+
"@types/ember__runloop": "^4.0.0",
|
|
75
|
+
"@types/ember__service": "^4.0.0",
|
|
76
|
+
"@types/ember__string": "^3.0.9",
|
|
77
|
+
"@types/ember__template": "^4.0.0",
|
|
78
|
+
"@types/ember__test": "^4.0.0",
|
|
79
|
+
"@types/ember__test-helpers": "^2.6.1",
|
|
80
|
+
"@types/htmlbars-inline-precompile": "^3.0.0",
|
|
81
|
+
"@types/qunit": "^2.11.3",
|
|
82
|
+
"@types/rsvp": "^4.0.4",
|
|
71
83
|
"@types/sinon": "^9.0.10",
|
|
72
|
-
"autoprefixer": "^10.2
|
|
84
|
+
"autoprefixer": "^10.4.2",
|
|
73
85
|
"broccoli-asset-rev": "^3.0.0",
|
|
74
|
-
"ember-auto-import": "^
|
|
75
|
-
"ember-cli": "~
|
|
86
|
+
"ember-auto-import": "^2.4.0",
|
|
87
|
+
"ember-cli": "~4.1.1",
|
|
76
88
|
"ember-cli-dependency-checker": "^3.2.0",
|
|
77
|
-
"ember-cli-fastboot": "^
|
|
78
|
-
"ember-cli-fastboot-testing": "^0.
|
|
79
|
-
"ember-cli-inject-live-reload": "^2.0
|
|
80
|
-
"ember-cli-postcss": "^
|
|
89
|
+
"ember-cli-fastboot": "^3.2.0-beta.5",
|
|
90
|
+
"ember-cli-fastboot-testing": "^0.6.0",
|
|
91
|
+
"ember-cli-inject-live-reload": "^2.1.0",
|
|
92
|
+
"ember-cli-postcss": "^8.0.0",
|
|
81
93
|
"ember-cli-sri": "^2.1.1",
|
|
82
94
|
"ember-cli-typescript-blueprints": "^3.0.0",
|
|
83
95
|
"ember-cli-uglify": "^3.0.0",
|
|
84
96
|
"ember-disable-prototype-extensions": "^1.1.3",
|
|
85
97
|
"ember-export-application-global": "^2.0.1",
|
|
86
98
|
"ember-load-initializers": "^2.1.2",
|
|
87
|
-
"ember-maybe-import-regenerator": "^0.
|
|
88
|
-
"ember-qunit": "^5.1.
|
|
89
|
-
"ember-resolver": "^8.0.
|
|
99
|
+
"ember-maybe-import-regenerator": "^1.0.0",
|
|
100
|
+
"ember-qunit": "^5.1.5",
|
|
101
|
+
"ember-resolver": "^8.0.3",
|
|
90
102
|
"ember-router-helpers": "^0.4.0",
|
|
91
103
|
"ember-sinon": "^5.0.0",
|
|
92
|
-
"ember-source": "~
|
|
104
|
+
"ember-source": "~4.1.0",
|
|
93
105
|
"ember-source-channel-url": "^3.0.0",
|
|
94
106
|
"ember-template-lint": "^2.18.0",
|
|
95
|
-
"ember-try": "^
|
|
107
|
+
"ember-try": "^2.0.0",
|
|
96
108
|
"loader.js": "^4.7.0",
|
|
97
109
|
"npm-run-all": "^4.1.5",
|
|
98
|
-
"postcss-import": "^14.0.
|
|
99
|
-
"postcss-nested": "^5.0.
|
|
100
|
-
"prember": "^1.0
|
|
101
|
-
"qunit": "^2.
|
|
102
|
-
"qunit-dom": "^
|
|
103
|
-
"refractor": "^3.
|
|
110
|
+
"postcss-import": "^14.0.2",
|
|
111
|
+
"postcss-nested": "^5.0.6",
|
|
112
|
+
"prember": "^1.1.0",
|
|
113
|
+
"qunit": "^2.17.2",
|
|
114
|
+
"qunit-dom": "^2.0.0",
|
|
115
|
+
"refractor": "^3.0.0",
|
|
104
116
|
"remark-autolink-headings": "^6.0.0",
|
|
105
117
|
"remark-code-import": "^0.2.0",
|
|
106
118
|
"tailwindcss": "^2.0.2",
|
|
107
|
-
"typescript": "^4.1.3"
|
|
119
|
+
"typescript": "^4.1.3",
|
|
120
|
+
"webpack": "^5.67.0"
|
|
108
121
|
},
|
|
109
122
|
"engines": {
|
|
110
123
|
"node": ">= 12"
|
|
@@ -122,5 +135,5 @@
|
|
|
122
135
|
"prember"
|
|
123
136
|
]
|
|
124
137
|
},
|
|
125
|
-
"gitHead": "
|
|
138
|
+
"gitHead": "3745bd3c8c45202a0c11d8fd502b52a5e3f62493"
|
|
126
139
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import visit from 'unist-util-visit';
|
|
2
2
|
import { Context, PageContent } from '@docfy/core/lib/types';
|
|
3
3
|
import plugin from '@docfy/core/lib/plugin';
|
|
4
|
-
import { Node } from 'unist';
|
|
4
|
+
import { Node, Parent } from 'unist';
|
|
5
5
|
import findNode from 'unist-util-find';
|
|
6
6
|
import toString from 'mdast-util-to-string';
|
|
7
7
|
import { DemoComponent, DemoComponentChunk, CodeNode } from './types';
|
|
@@ -23,12 +23,27 @@ import path from 'path';
|
|
|
23
23
|
* This is necessary for apps using remark-autolink-headings, for example.
|
|
24
24
|
*/
|
|
25
25
|
function createHeading(ctx: Context): Node {
|
|
26
|
-
const heading = (
|
|
27
|
-
.children as Node[]
|
|
26
|
+
const heading = (
|
|
27
|
+
ctx.remark.runSync(ctx.remark.parse('## Examples')).children as Node[]
|
|
28
|
+
)[0];
|
|
28
29
|
heading.depth = 2;
|
|
29
30
|
return heading;
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
const isTextMarker = (node: Parent): boolean =>
|
|
34
|
+
node.type === 'paragraph' &&
|
|
35
|
+
node.children.length === 1 &&
|
|
36
|
+
node.children[0].type === 'text';
|
|
37
|
+
|
|
38
|
+
const demoMarkerRegex = /^\[\[demo:(.+?)\]\]$/;
|
|
39
|
+
const demoMarker = (node: Parent): boolean =>
|
|
40
|
+
isTextMarker(node) && demoMarkerRegex.test(node.children[0].value as string);
|
|
41
|
+
|
|
42
|
+
const demosAllMarkerRegex = /^\[\[demos-all\]\]$/;
|
|
43
|
+
const demosAllMarker = (node: Parent): boolean =>
|
|
44
|
+
isTextMarker(node) &&
|
|
45
|
+
demosAllMarkerRegex.test(node.children[0].value as string);
|
|
46
|
+
|
|
32
47
|
/*
|
|
33
48
|
* Insert Demo nodes into the page.
|
|
34
49
|
*/
|
|
@@ -48,6 +63,49 @@ function insertDemoNodesIntoPage(page: PageContent, toInsert: Node[]): void {
|
|
|
48
63
|
}
|
|
49
64
|
}
|
|
50
65
|
|
|
66
|
+
function replaceDemoMarkers(page: PageContent, demos: DemoComponent[]): void {
|
|
67
|
+
if (Array.isArray(page.ast.children)) {
|
|
68
|
+
const markers: Parent[] = [];
|
|
69
|
+
const allMarkers: Parent[] = [];
|
|
70
|
+
|
|
71
|
+
visit(page.ast, 'paragraph', (node: Parent) => {
|
|
72
|
+
if (demoMarker(node)) markers.push(node);
|
|
73
|
+
if (demosAllMarker(node)) allMarkers.push(node);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
markers.forEach((marker) => {
|
|
77
|
+
const child = marker.children[0];
|
|
78
|
+
const matches = (child.value as string).match(demoMarkerRegex);
|
|
79
|
+
if (!matches) return;
|
|
80
|
+
|
|
81
|
+
// TODO: This is an inner loop and can cause perf issues if someone
|
|
82
|
+
// out there has many demos on a single page. It would be better to
|
|
83
|
+
// create a demo component hash that can be looked up by demo name.
|
|
84
|
+
const demoName = matches[1];
|
|
85
|
+
const demo = demos.find((d) => d.name.dashCase.endsWith(demoName));
|
|
86
|
+
|
|
87
|
+
if (!demo) {
|
|
88
|
+
console.warn(
|
|
89
|
+
`Found demo marker "${demoName}" with no matching demo component in ${page.source}`
|
|
90
|
+
);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
marker.type = 'div';
|
|
95
|
+
marker.children.splice(0, 1, ...createDemoNodes(demo));
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
allMarkers.forEach((marker) => {
|
|
99
|
+
const demoNodes = demos
|
|
100
|
+
.map((component) => createDemoNodes(component))
|
|
101
|
+
.flat();
|
|
102
|
+
|
|
103
|
+
marker.type = 'div';
|
|
104
|
+
marker.children.splice(0, 1, ...demoNodes);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
51
109
|
export default plugin({
|
|
52
110
|
runWithMdast(ctx: Context): void {
|
|
53
111
|
const seenNames: Set<string> = new Set();
|
|
@@ -113,11 +171,19 @@ export default plugin({
|
|
|
113
171
|
});
|
|
114
172
|
});
|
|
115
173
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
174
|
+
if (page.meta.frontmatter.manualDemoInsertion) {
|
|
175
|
+
// Manual demo insertion inserts demos into markdown files
|
|
176
|
+
// wherever there is a demo marker ([[demo:name]] or [[demos-all]])
|
|
177
|
+
replaceDemoMarkers(page, demoComponents);
|
|
178
|
+
} else {
|
|
179
|
+
// Automatic demo insertion creates an Example block after
|
|
180
|
+
// the first heading.
|
|
181
|
+
const toInsert: Node[] = [createHeading(ctx)];
|
|
182
|
+
demoComponents.forEach((component) => {
|
|
183
|
+
toInsert.push(...createDemoNodes(component));
|
|
184
|
+
});
|
|
185
|
+
insertDemoNodesIntoPage(page, toInsert);
|
|
186
|
+
}
|
|
121
187
|
|
|
122
188
|
if (isDemoComponents(page.pluginData.demoComponents)) {
|
|
123
189
|
page.pluginData.demoComponents.push(...demoComponents);
|