@xyd-js/composer 0.1.0-xyd.2
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/CHANGELOG.md +69 -0
- package/LICENSE +21 -0
- package/README.md +7 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +440 -0
- package/dist/index.js.map +1 -0
- package/package.json +40 -0
- package/src/Composer.ts +515 -0
- package/src/decorators.ts +18 -0
- package/src/index.ts +3 -0
- package/tsconfig.json +49 -0
- package/tsup.config.ts +33 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# @xyd-js/themes
|
|
2
|
+
|
|
3
|
+
## 0.1.0-xyd.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- test
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @xyd-js/atlas@0.1.0-xyd.18
|
|
10
|
+
- @xyd-js/content@0.1.0-xyd.16
|
|
11
|
+
- @xyd-js/context@0.1.0-xyd.2
|
|
12
|
+
- @xyd-js/core@0.1.0-xyd.15
|
|
13
|
+
- @xyd-js/uniform@0.1.0-xyd.17
|
|
14
|
+
|
|
15
|
+
## 0.1.0-xyd.1
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- update packages
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
- @xyd-js/atlas@0.1.0-xyd.17
|
|
22
|
+
- @xyd-js/content@0.1.0-xyd.15
|
|
23
|
+
- @xyd-js/context@0.1.0-xyd.1
|
|
24
|
+
- @xyd-js/core@0.1.0-xyd.14
|
|
25
|
+
- @xyd-js/uniform@0.1.0-xyd.16
|
|
26
|
+
|
|
27
|
+
## 0.1.1-xyd.3
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- version
|
|
32
|
+
- Updated dependencies
|
|
33
|
+
- @xyd-js/atlas@0.1.0-xyd.16
|
|
34
|
+
- @xyd-js/components@0.1.0-xyd.11
|
|
35
|
+
- @xyd-js/framework@0.1.0-xyd.32
|
|
36
|
+
- @xyd-js/ui@0.1.0-xyd.16
|
|
37
|
+
|
|
38
|
+
## 0.1.1-xyd.2
|
|
39
|
+
|
|
40
|
+
### Patch Changes
|
|
41
|
+
|
|
42
|
+
- fix again
|
|
43
|
+
- Updated dependencies
|
|
44
|
+
- @xyd-js/atlas@0.1.0-xyd.15
|
|
45
|
+
- @xyd-js/components@0.1.0-xyd.10
|
|
46
|
+
- @xyd-js/framework@0.1.0-xyd.30
|
|
47
|
+
- @xyd-js/ui@0.1.0-xyd.15
|
|
48
|
+
|
|
49
|
+
## 0.1.1-xyd.1
|
|
50
|
+
|
|
51
|
+
### Patch Changes
|
|
52
|
+
|
|
53
|
+
- fix for theme
|
|
54
|
+
- Updated dependencies
|
|
55
|
+
- @xyd-js/atlas@0.1.0-xyd.14
|
|
56
|
+
- @xyd-js/components@0.1.0-xyd.9
|
|
57
|
+
- @xyd-js/framework@0.1.0-xyd.29
|
|
58
|
+
- @xyd-js/ui@0.1.0-xyd.14
|
|
59
|
+
|
|
60
|
+
## 0.1.1-xyd.0
|
|
61
|
+
|
|
62
|
+
### Patch Changes
|
|
63
|
+
|
|
64
|
+
- refactor, ui tweaks
|
|
65
|
+
- Updated dependencies
|
|
66
|
+
- @xyd-js/atlas@0.1.0-xyd.13
|
|
67
|
+
- @xyd-js/components@0.1.0-xyd.8
|
|
68
|
+
- @xyd-js/framework@0.1.0-xyd.28
|
|
69
|
+
- @xyd-js/ui@0.1.0-xyd.13
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 xyd
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
|
|
5
|
+
var __typeError = (msg) => {
|
|
6
|
+
throw TypeError(msg);
|
|
7
|
+
};
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
10
|
+
var __decoratorStart = (base) => [, , , __create((base == null ? void 0 : base[__knownSymbol("metadata")]) ?? null)];
|
|
11
|
+
var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
|
|
12
|
+
var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
|
|
13
|
+
var __decoratorContext = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null)) });
|
|
14
|
+
var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
|
|
15
|
+
var __runInitializers = (array, flags, self, value) => {
|
|
16
|
+
for (var i = 0, fns = array[flags >> 1], n = fns && fns.length; i < n; i++) flags & 1 ? fns[i].call(self) : value = fns[i].call(self, value);
|
|
17
|
+
return value;
|
|
18
|
+
};
|
|
19
|
+
var __decorateElement = (array, flags, name, decorators, target, extra) => {
|
|
20
|
+
var fn, it, done, ctx, access, k = flags & 7, s = !!(flags & 8), p = !!(flags & 16);
|
|
21
|
+
var j = k > 3 ? array.length + 1 : k ? s ? 1 : 2 : 0, key = __decoratorStrings[k + 5];
|
|
22
|
+
var initializers = k > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
|
|
23
|
+
var desc = k && (!p && !s && (target = target.prototype), k < 5 && (k > 3 || !p) && __getOwnPropDesc(k < 4 ? target : { get [name]() {
|
|
24
|
+
return __privateGet(this, extra);
|
|
25
|
+
}, set [name](x) {
|
|
26
|
+
return __privateSet(this, extra, x);
|
|
27
|
+
} }, name));
|
|
28
|
+
k ? p && k < 4 && __name(extra, (k > 2 ? "set " : k > 1 ? "get " : "") + name) : __name(target, name);
|
|
29
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
30
|
+
ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
|
|
31
|
+
if (k) {
|
|
32
|
+
ctx.static = s, ctx.private = p, access = ctx.access = { has: p ? (x) => __privateIn(target, x) : (x) => name in x };
|
|
33
|
+
if (k ^ 3) access.get = p ? (x) => (k ^ 1 ? __privateGet : __privateMethod)(x, target, k ^ 4 ? extra : desc.get) : (x) => x[name];
|
|
34
|
+
if (k > 2) access.set = p ? (x, y) => __privateSet(x, target, y, k ^ 4 ? extra : desc.set) : (x, y) => x[name] = y;
|
|
35
|
+
}
|
|
36
|
+
it = (0, decorators[i])(k ? k < 4 ? p ? extra : desc[key] : k > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
|
|
37
|
+
if (k ^ 4 || it === void 0) __expectFn(it) && (k > 4 ? initializers.unshift(it) : k ? p ? extra = it : desc[key] = it : target = it);
|
|
38
|
+
else if (typeof it !== "object" || it === null) __typeError("Object expected");
|
|
39
|
+
else __expectFn(fn = it.get) && (desc.get = fn), __expectFn(fn = it.set) && (desc.set = fn), __expectFn(fn = it.init) && initializers.unshift(fn);
|
|
40
|
+
}
|
|
41
|
+
return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
|
|
42
|
+
};
|
|
43
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
44
|
+
var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use the "in" operator on this value') : member.has(obj);
|
|
45
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
46
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
47
|
+
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
48
|
+
|
|
49
|
+
// src/Composer.ts
|
|
50
|
+
import * as React from "react";
|
|
51
|
+
import { toMarkdown } from "mdast-util-to-markdown";
|
|
52
|
+
import { mdxToMarkdown } from "mdast-util-mdx";
|
|
53
|
+
import { toHast } from "mdast-util-to-hast";
|
|
54
|
+
import { toHtml } from "hast-util-to-html";
|
|
55
|
+
import { parse } from "@babel/parser";
|
|
56
|
+
import { highlight } from "codehike/code";
|
|
57
|
+
import { marked } from "marked";
|
|
58
|
+
import { fromMarkdown } from "mdast-util-from-markdown";
|
|
59
|
+
import { htmlToJsx } from "html-to-jsx-transform";
|
|
60
|
+
|
|
61
|
+
// src/decorators.ts
|
|
62
|
+
import { registerMetaComponent } from "@xyd-js/context";
|
|
63
|
+
function metaComponent(name, componentName) {
|
|
64
|
+
return function(target, context) {
|
|
65
|
+
registerMetaComponent(
|
|
66
|
+
name,
|
|
67
|
+
componentName || name,
|
|
68
|
+
target
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/Composer.ts
|
|
74
|
+
var _atlasMetaComponent_dec, _init;
|
|
75
|
+
_atlasMetaComponent_dec = [metaComponent("atlas", "Atlas")];
|
|
76
|
+
var Composer = class {
|
|
77
|
+
constructor() {
|
|
78
|
+
__runInitializers(_init, 5, this);
|
|
79
|
+
}
|
|
80
|
+
async atlasMetaComponent(themeSettings, props, vars, treeChilds) {
|
|
81
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
|
|
82
|
+
const outputVarExamples = {
|
|
83
|
+
groups: []
|
|
84
|
+
};
|
|
85
|
+
const oneExample = ((_a = vars.examples) == null ? void 0 : _a.length) === 1 && !Array.isArray(vars.examples[0]);
|
|
86
|
+
function createExampleObject(example) {
|
|
87
|
+
const highlighted = example.highlighted || example;
|
|
88
|
+
return {
|
|
89
|
+
codeblock: {
|
|
90
|
+
title: example.meta,
|
|
91
|
+
tabs: [
|
|
92
|
+
{
|
|
93
|
+
title: example.meta,
|
|
94
|
+
language: example.lang,
|
|
95
|
+
code: example.code,
|
|
96
|
+
highlighted
|
|
97
|
+
}
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (oneExample) {
|
|
103
|
+
const example = (_b = vars.examples) == null ? void 0 : _b[0];
|
|
104
|
+
if (Array.isArray(example) || !example) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
outputVarExamples.groups.push({
|
|
108
|
+
examples: [createExampleObject(example)]
|
|
109
|
+
});
|
|
110
|
+
} else {
|
|
111
|
+
(_c = vars.examples) == null ? void 0 : _c.forEach((item) => {
|
|
112
|
+
if (Array.isArray(item)) {
|
|
113
|
+
const groupTitle = item[0];
|
|
114
|
+
const groupExamples = item.slice(1);
|
|
115
|
+
const exampleGroup = {
|
|
116
|
+
examples: []
|
|
117
|
+
};
|
|
118
|
+
groupExamples.forEach((example) => {
|
|
119
|
+
if (example && typeof example === "object") {
|
|
120
|
+
exampleGroup.examples.push(createExampleObject(example));
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
if (exampleGroup.examples.length > 0) {
|
|
124
|
+
outputVarExamples.groups.push(exampleGroup);
|
|
125
|
+
}
|
|
126
|
+
} else if (item && typeof item === "object") {
|
|
127
|
+
const exampleGroup = {
|
|
128
|
+
examples: [createExampleObject(item)]
|
|
129
|
+
};
|
|
130
|
+
outputVarExamples.groups.push(exampleGroup);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
const reactElements = [];
|
|
135
|
+
for (const child of treeChilds) {
|
|
136
|
+
if (isStandardMdastType(child.type)) {
|
|
137
|
+
const hast = toHast(child);
|
|
138
|
+
const html = toHtml(hast);
|
|
139
|
+
if (child.type === "heading" && child.depth === 1) {
|
|
140
|
+
const firstChild = child.children[0];
|
|
141
|
+
if (firstChild.type === "text") {
|
|
142
|
+
props.references[0].title = firstChild.value;
|
|
143
|
+
}
|
|
144
|
+
} else {
|
|
145
|
+
const jsx = htmlToJsx(html);
|
|
146
|
+
const reactTree = jsxStringToReactTree(jsx);
|
|
147
|
+
if (reactTree) {
|
|
148
|
+
reactElements.push(reactTree);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
continue;
|
|
152
|
+
} else if (isMdxElement(child.type)) {
|
|
153
|
+
const jsxString = toMarkdown(child, {
|
|
154
|
+
extensions: [mdxToMarkdown()],
|
|
155
|
+
handlers: {
|
|
156
|
+
// TODO: find better solution how to convert such as structure?
|
|
157
|
+
list(node, parent, context) {
|
|
158
|
+
const items = node.children.map((item) => context.containerFlow(item, node)).join("\n");
|
|
159
|
+
return `<ul>
|
|
160
|
+
${items}
|
|
161
|
+
</ul>`;
|
|
162
|
+
},
|
|
163
|
+
listItem(node, parent, context) {
|
|
164
|
+
const content = context.containerFlow(node, parent).trim();
|
|
165
|
+
return `<li>${content}</li>`;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
const reactTree = jsxStringToReactTree(jsxString);
|
|
170
|
+
if (reactTree) {
|
|
171
|
+
reactElements.push(reactTree);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const propDescription = (_e = (_d = props.references) == null ? void 0 : _d[0]) == null ? void 0 : _e.description;
|
|
176
|
+
if (propDescription) {
|
|
177
|
+
if (typeof propDescription === "string") {
|
|
178
|
+
const content = propDescription.replace(/^---[\s\S]*?---\n/, "");
|
|
179
|
+
const md = fromMarkdown(content);
|
|
180
|
+
const hast = toHast(md);
|
|
181
|
+
const html = toHtml(hast);
|
|
182
|
+
const jsx = htmlToJsx(html);
|
|
183
|
+
const reactTree = jsxStringToReactTree(jsx);
|
|
184
|
+
if (reactTree) {
|
|
185
|
+
props.references[0].description = reactTree;
|
|
186
|
+
} else {
|
|
187
|
+
props.references[0].description = content;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (reactElements.length > 0) {
|
|
192
|
+
if ((_g = (_f = props.references) == null ? void 0 : _f[0]) == null ? void 0 : _g.description) {
|
|
193
|
+
reactElements.unshift(props.references[0].description);
|
|
194
|
+
}
|
|
195
|
+
const combinedReactTree = React.createElement(React.Fragment, null, ...reactElements);
|
|
196
|
+
if ((_h = props.references) == null ? void 0 : _h[0]) {
|
|
197
|
+
props.references[0].description = combinedReactTree;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (!outputVarExamples.groups.length && ((_j = (_i = props.references[0]) == null ? void 0 : _i.examples.groups) == null ? void 0 : _j.length)) {
|
|
201
|
+
const promises = [];
|
|
202
|
+
(_k = props.references[0].examples) == null ? void 0 : _k.groups.forEach((group) => {
|
|
203
|
+
group.examples.forEach((example) => {
|
|
204
|
+
example.codeblock.tabs.forEach((tab) => {
|
|
205
|
+
async function highlightCode() {
|
|
206
|
+
var _a2;
|
|
207
|
+
const highlighted = await highlight({
|
|
208
|
+
value: tab.code,
|
|
209
|
+
lang: tab.language,
|
|
210
|
+
meta: tab.title
|
|
211
|
+
}, ((_a2 = themeSettings == null ? void 0 : themeSettings.coder) == null ? void 0 : _a2.syntaxHighlight) || "github-dark");
|
|
212
|
+
tab.highlighted = highlighted;
|
|
213
|
+
}
|
|
214
|
+
promises.push(highlightCode());
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
await Promise.all(promises);
|
|
219
|
+
} else {
|
|
220
|
+
if ((_l = props.references) == null ? void 0 : _l[0]) {
|
|
221
|
+
props.references[0].examples = outputVarExamples;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if ((_n = (_m = props.references) == null ? void 0 : _m[0]) == null ? void 0 : _n.definitions) {
|
|
225
|
+
props.references[0].definitions = processDefinitionProperties(props.references[0].definitions);
|
|
226
|
+
}
|
|
227
|
+
return props;
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
_init = __decoratorStart(null);
|
|
231
|
+
__decorateElement(_init, 1, "atlasMetaComponent", _atlasMetaComponent_dec, Composer);
|
|
232
|
+
__decoratorMetadata(_init, Composer);
|
|
233
|
+
function buildElement(node) {
|
|
234
|
+
if (!node) return null;
|
|
235
|
+
switch (node.type) {
|
|
236
|
+
case "JSXElement": {
|
|
237
|
+
let type;
|
|
238
|
+
const nameNode = node.openingElement.name;
|
|
239
|
+
if (nameNode.type === "JSXMemberExpression") {
|
|
240
|
+
const parts = [];
|
|
241
|
+
let curr = nameNode;
|
|
242
|
+
while (curr) {
|
|
243
|
+
if (curr.property) parts.unshift(curr.property.name);
|
|
244
|
+
curr = curr.object;
|
|
245
|
+
}
|
|
246
|
+
type = parts.join(".");
|
|
247
|
+
} else {
|
|
248
|
+
type = nameNode.name;
|
|
249
|
+
}
|
|
250
|
+
const props = {};
|
|
251
|
+
for (const attr of node.openingElement.attributes) {
|
|
252
|
+
if (attr.type === "JSXSpreadAttribute") {
|
|
253
|
+
Object.assign(props, evaluateExpression(attr.argument));
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
const key = attr.name.name;
|
|
257
|
+
let value;
|
|
258
|
+
if (!attr.value) {
|
|
259
|
+
value = true;
|
|
260
|
+
} else if (attr.value.type === "StringLiteral" || attr.value.type === "NumericLiteral" || attr.value.type === "BooleanLiteral") {
|
|
261
|
+
value = attr.value.value;
|
|
262
|
+
} else if (attr.value.type === "JSXExpressionContainer") {
|
|
263
|
+
value = evaluateExpression(attr.value.expression);
|
|
264
|
+
}
|
|
265
|
+
props[key] = value;
|
|
266
|
+
}
|
|
267
|
+
const children = node.children.map((child) => {
|
|
268
|
+
if (child.type === "JSXText") {
|
|
269
|
+
const text = child.value.replace(/\s+/g, " ");
|
|
270
|
+
return text.trim() ? text : null;
|
|
271
|
+
}
|
|
272
|
+
if (child.type === "JSXExpressionContainer") {
|
|
273
|
+
return child.expression.type === "JSXElement" || child.expression.type === "JSXFragment" ? buildElement(child.expression) : evaluateExpression(child.expression);
|
|
274
|
+
}
|
|
275
|
+
if (child.type === "JSXElement" || child.type === "JSXFragment") {
|
|
276
|
+
return buildElement(child);
|
|
277
|
+
}
|
|
278
|
+
return null;
|
|
279
|
+
}).filter((c) => c !== null);
|
|
280
|
+
return React.createElement(type, props, ...children);
|
|
281
|
+
}
|
|
282
|
+
case "JSXFragment": {
|
|
283
|
+
const children = node.children.map(
|
|
284
|
+
(child) => child.type === "JSXElement" || child.type === "JSXFragment" ? buildElement(child) : child.type === "JSXText" ? child.value.trim() || null : null
|
|
285
|
+
).filter(Boolean);
|
|
286
|
+
return React.createElement(React.Fragment, null, ...children);
|
|
287
|
+
}
|
|
288
|
+
default:
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
function evaluateExpression(expr) {
|
|
293
|
+
switch (expr.type) {
|
|
294
|
+
case "StringLiteral":
|
|
295
|
+
return expr.value;
|
|
296
|
+
case "NumericLiteral":
|
|
297
|
+
return expr.value;
|
|
298
|
+
case "BooleanLiteral":
|
|
299
|
+
return expr.value;
|
|
300
|
+
case "ObjectExpression": {
|
|
301
|
+
const obj = {};
|
|
302
|
+
for (const prop of expr.properties) {
|
|
303
|
+
if (prop.type === "ObjectProperty" && prop.key.type === "Identifier") {
|
|
304
|
+
obj[prop.key.name] = evaluateExpression(prop.value);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return obj;
|
|
308
|
+
}
|
|
309
|
+
// Add more cases (Identifier, CallExpression, etc.) as needed
|
|
310
|
+
default:
|
|
311
|
+
return void 0;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
function findJSX(node) {
|
|
315
|
+
if (!node || typeof node !== "object") return null;
|
|
316
|
+
if (node.type === "JSXElement" || node.type === "JSXFragment") return node;
|
|
317
|
+
for (const key of Object.keys(node)) {
|
|
318
|
+
const val = node[key];
|
|
319
|
+
if (Array.isArray(val)) {
|
|
320
|
+
for (const child of val) {
|
|
321
|
+
const found = findJSX(child);
|
|
322
|
+
if (found) return found;
|
|
323
|
+
}
|
|
324
|
+
} else {
|
|
325
|
+
const found = findJSX(val);
|
|
326
|
+
if (found) return found;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
function jsxStringToReactTree(jsxString = "") {
|
|
332
|
+
const ast = parse(jsxString, { sourceType: "module", plugins: ["jsx"] });
|
|
333
|
+
const rootJSX = findJSX(ast);
|
|
334
|
+
if (!rootJSX) {
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
const reactTree = buildElement(rootJSX);
|
|
338
|
+
return reactTree;
|
|
339
|
+
}
|
|
340
|
+
function processDefinitionProperties(definitions) {
|
|
341
|
+
if (!definitions || !Array.isArray(definitions)) {
|
|
342
|
+
return definitions;
|
|
343
|
+
}
|
|
344
|
+
return definitions.map((definition) => {
|
|
345
|
+
if (definition.variants && Array.isArray(definition.variants)) {
|
|
346
|
+
for (const variant of definition.variants) {
|
|
347
|
+
if (variant.properties && Array.isArray(variant.properties)) {
|
|
348
|
+
variant.properties = processDefinitionProperty(variant.properties);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
if (definition.properties && Array.isArray(definition.properties)) {
|
|
353
|
+
definition.properties = processDefinitionProperty(definition.properties);
|
|
354
|
+
}
|
|
355
|
+
if (definition.description && typeof definition.description === "string") {
|
|
356
|
+
const md = fromMarkdown(definition.description);
|
|
357
|
+
const hast = toHast(md);
|
|
358
|
+
const html = toHtml(hast);
|
|
359
|
+
const jsx = htmlToJsx(html);
|
|
360
|
+
const reactTree = jsxStringToReactTree(jsx);
|
|
361
|
+
if (reactTree) {
|
|
362
|
+
definition.description = reactTree;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return definition;
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
function processDefinitionProperty(properties) {
|
|
369
|
+
if (!properties || !Array.isArray(properties)) {
|
|
370
|
+
return properties;
|
|
371
|
+
}
|
|
372
|
+
return properties.map((property) => {
|
|
373
|
+
const newProperty = {
|
|
374
|
+
...property
|
|
375
|
+
};
|
|
376
|
+
if (typeof newProperty.description === "string" && isMarkdownText(newProperty.description)) {
|
|
377
|
+
const mdast = fromMarkdown(newProperty.description);
|
|
378
|
+
const hast = toHast(mdast);
|
|
379
|
+
const html = toHtml(hast);
|
|
380
|
+
const jsx = htmlToJsx(html);
|
|
381
|
+
const reactTree = jsxStringToReactTree(jsx);
|
|
382
|
+
if (reactTree) {
|
|
383
|
+
newProperty.description = reactTree;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
if (property.properties && Array.isArray(property.properties)) {
|
|
387
|
+
newProperty.properties = processDefinitionProperty(property.properties);
|
|
388
|
+
}
|
|
389
|
+
return newProperty;
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
function isMarkdownText(text) {
|
|
393
|
+
const tokens = marked.lexer(text);
|
|
394
|
+
let found = false;
|
|
395
|
+
marked.walkTokens(tokens, (token) => {
|
|
396
|
+
if (!["text", "paragraph", "space", "newline"].includes(token.type)) {
|
|
397
|
+
found = true;
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
return found;
|
|
401
|
+
}
|
|
402
|
+
var standardMdastTypes = [
|
|
403
|
+
"root",
|
|
404
|
+
"paragraph",
|
|
405
|
+
"heading",
|
|
406
|
+
"text",
|
|
407
|
+
"emphasis",
|
|
408
|
+
"strong",
|
|
409
|
+
"delete",
|
|
410
|
+
"blockquote",
|
|
411
|
+
"code",
|
|
412
|
+
"link",
|
|
413
|
+
"image",
|
|
414
|
+
"list",
|
|
415
|
+
"listItem",
|
|
416
|
+
"table",
|
|
417
|
+
"tableRow",
|
|
418
|
+
"tableCell",
|
|
419
|
+
"html",
|
|
420
|
+
"break",
|
|
421
|
+
"thematicBreak",
|
|
422
|
+
"definition",
|
|
423
|
+
"footnoteDefinition",
|
|
424
|
+
"footnoteReference",
|
|
425
|
+
"inlineCode",
|
|
426
|
+
"linkReference",
|
|
427
|
+
"imageReference",
|
|
428
|
+
"footnote",
|
|
429
|
+
"tableCaption"
|
|
430
|
+
];
|
|
431
|
+
function isStandardMdastType(type) {
|
|
432
|
+
return standardMdastTypes.includes(type);
|
|
433
|
+
}
|
|
434
|
+
function isMdxElement(type) {
|
|
435
|
+
return type === "mdxJsxFlowElement";
|
|
436
|
+
}
|
|
437
|
+
export {
|
|
438
|
+
Composer
|
|
439
|
+
};
|
|
440
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/Composer.ts","../src/decorators.ts"],"sourcesContent":["import * as React from \"react\"\nimport type { RootContent } from \"mdast\";\nimport { toMarkdown } from \"mdast-util-to-markdown\";\nimport { mdxToMarkdown } from \"mdast-util-mdx\";\nimport { toHast } from 'mdast-util-to-hast'\nimport { toHtml } from 'hast-util-to-html'\nimport { parse } from '@babel/parser';\nimport { highlight } from \"codehike/code\";\nimport { marked } from 'marked';\nimport { fromMarkdown } from 'mdast-util-from-markdown';\nimport { htmlToJsx } from \"html-to-jsx-transform\";\n\nimport { type AtlasProps } from \"@xyd-js/atlas\";\nimport { type Theme as ThemeSettings } from \"@xyd-js/core\"\n\nimport { VarCode } from \"@xyd-js/content\";\nimport { ExampleRoot, Definition, DefinitionProperty } from \"@xyd-js/uniform\";\n\nimport { metaComponent } from './decorators';\n\n// TODO: !!!! REFACTOR !!!\n\ninterface AtlasVars {\n examples?: VarCode\n}\n\n// TODO: get object from atlas\n// Define the type for an example object\ninterface ExampleObject {\n codeblock: {\n title: string;\n tabs: {\n title: string;\n language: string;\n code: string;\n highlighted: any; // TODO: fix\n }[];\n };\n}\n\n// Define the type for an example group\ninterface ExampleGroup {\n examples: ExampleObject[];\n}\n\nexport class Composer {\n // TODO: !!! COMPOSE API !!!!\n // TODO: this.themeSettings but currently issues with decorators\n @metaComponent(\"atlas\", \"Atlas\")\n private async atlasMetaComponent(\n themeSettings: ThemeSettings,\n props: AtlasProps,\n vars: AtlasVars,\n treeChilds: readonly RootContent[]\n ) {\n //@ts-ignore\n const outputVarExamples: ExampleRoot = {\n groups: []\n }\n\n const oneExample = vars.examples?.length === 1 && !Array.isArray(vars.examples[0])\n\n // Helper function to create an example object\n function createExampleObject(example: any): ExampleObject {\n // Extract the highlighted property correctly\n const highlighted = example.highlighted || example;\n\n return {\n codeblock: {\n title: example.meta,\n tabs: [\n {\n title: example.meta,\n language: example.lang,\n code: example.code,\n highlighted: highlighted\n }\n ]\n }\n };\n }\n\n if (oneExample) {\n const example = vars.examples?.[0]\n if (Array.isArray(example) || !example) {\n return\n }\n\n outputVarExamples.groups.push({\n examples: [createExampleObject(example)]\n })\n } else {\n // Process each example or group of examples\n vars.examples?.forEach((item) => {\n if (Array.isArray(item)) {\n // This is a group with a title as the first element\n const groupTitle = item[0];\n const groupExamples = item.slice(1);\n\n const exampleGroup: ExampleGroup = {\n examples: []\n };\n\n // Process each example in the group\n groupExamples.forEach((example) => {\n if (example && typeof example === 'object') {\n exampleGroup.examples.push(createExampleObject(example));\n }\n });\n\n if (exampleGroup.examples.length > 0) {\n outputVarExamples.groups.push(exampleGroup);\n }\n } else if (item && typeof item === 'object') {\n // This is a single example\n const exampleGroup: ExampleGroup = {\n examples: [createExampleObject(item)]\n };\n\n outputVarExamples.groups.push(exampleGroup);\n }\n });\n }\n\n const reactElements: React.ReactNode[] = []\n\n // TODO: !! IMPORTANT !! BETTER COMPOSE TRANSFORMATION\n for (const child of treeChilds) {\n if (isStandardMdastType(child.type)) {\n const hast = toHast(child)\n const html = toHtml(hast)\n\n if (child.type === \"heading\" && child.depth === 1) {\n const firstChild = child.children[0];\n if (firstChild.type === 'text') {\n props.references[0].title = firstChild.value;\n }\n } else {\n const jsx = htmlToJsx(html);\n const reactTree = jsxStringToReactTree(jsx);\n if (reactTree) {\n reactElements.push(reactTree)\n }\n }\n\n continue\n } else if (isMdxElement(child.type)) {\n const jsxString = toMarkdown(child, {\n extensions: [mdxToMarkdown()],\n handlers: {// TODO: find better solution how to convert such as structure?\n list(node, parent, context) {\n // call containerFlow as a method on context, so `this` stays correct\n const items = node.children\n .map(item => context.containerFlow(item, node))\n .join('\\n')\n return `<ul>\\n${items}\\n</ul>`\n },\n listItem(node, parent, context) {\n // Use a type assertion to handle the parent parameter\n const content = context.containerFlow(node, parent as any).trim()\n return `<li>${content}</li>`\n },\n }\n });\n\n const reactTree = jsxStringToReactTree(jsxString)\n if (reactTree) {\n reactElements.push(reactTree)\n }\n }\n }\n\n const propDescription = props.references?.[0]?.description\n if (propDescription) {\n // Sanitize frontmatter description\n if (typeof propDescription === \"string\") {\n // Remove frontmatter using regex\n const content = propDescription.replace(/^---[\\s\\S]*?---\\n/, '');\n\n const md = fromMarkdown(content)\n const hast = toHast(md)\n const html = toHtml(hast)\n const jsx = htmlToJsx(html);\n const reactTree = jsxStringToReactTree(jsx);\n if (reactTree) {\n props.references[0].description = reactTree;\n } else {\n props.references[0].description = content\n }\n }\n }\n\n if (reactElements.length > 0) {\n if (props.references?.[0]?.description) {\n reactElements.unshift(props.references[0].description)\n }\n // Create a combined React element from all the elements\n const combinedReactTree = React.createElement(React.Fragment, null, ...reactElements)\n\n if (props.references?.[0]) {\n props.references[0].description = combinedReactTree\n }\n }\n\n if (\n !outputVarExamples.groups.length &&\n props.references[0]?.examples.groups?.length\n ) {\n const promises: Promise<void>[] = []\n\n props.references[0].examples?.groups.forEach(group => {\n group.examples.forEach(example => {\n example.codeblock.tabs.forEach(tab => {\n\n async function highlightCode() {\n const highlighted = await highlight({\n value: tab.code,\n lang: tab.language,\n meta: tab.title,\n }, themeSettings?.coder?.syntaxHighlight || \"github-dark\")\n\n tab.highlighted = highlighted\n }\n\n promises.push(highlightCode());\n });\n });\n });\n\n await Promise.all(promises);\n } else {\n if (props.references?.[0]) {\n props.references[0].examples = outputVarExamples;\n }\n }\n\n // Process definition properties recursively to convert markdown descriptions to React trees\n if (props.references?.[0]?.definitions) {\n props.references[0].definitions = processDefinitionProperties(props.references[0].definitions);\n }\n\n return props\n // TODO: in the future return a component directly here but we need good mechanism for transpiling?\n }\n}\n\nfunction buildElement(node) {\n if (!node) return null;\n switch (node.type) {\n case 'JSXElement': {\n // Resolve type (string for custom components)\n let type;\n const nameNode = node.openingElement.name;\n if (nameNode.type === 'JSXMemberExpression') {\n // flatten Foo.Bar to \"Foo.Bar\"\n const parts: string[] = [];\n let curr = nameNode;\n while (curr) {\n if (curr.property) parts.unshift(curr.property.name);\n curr = curr.object;\n }\n type = parts.join('.');\n } else {\n type = nameNode.name;\n }\n\n // Props\n const props = {};\n for (const attr of node.openingElement.attributes) {\n if (attr.type === 'JSXSpreadAttribute') {\n Object.assign(props, evaluateExpression(attr.argument));\n continue;\n }\n const key = attr.name.name;\n let value;\n if (!attr.value) {\n value = true;\n } else if (attr.value.type === 'StringLiteral' || attr.value.type === 'NumericLiteral' || attr.value.type === 'BooleanLiteral') {\n value = attr.value.value;\n } else if (attr.value.type === 'JSXExpressionContainer') {\n value = evaluateExpression(attr.value.expression);\n }\n props[key] = value;\n }\n\n // Children\n const children = node.children\n .map(child => {\n if (child.type === 'JSXText') {\n const text = child.value.replace(/\\s+/g, ' ');\n return text.trim() ? text : null;\n }\n if (child.type === 'JSXExpressionContainer') {\n return child.expression.type === 'JSXElement' || child.expression.type === 'JSXFragment'\n ? buildElement(child.expression)\n : evaluateExpression(child.expression);\n }\n if (child.type === 'JSXElement' || child.type === 'JSXFragment') {\n return buildElement(child);\n }\n return null;\n })\n .filter(c => c !== null);\n\n // Create React element\n return React.createElement(type, props, ...children);\n }\n\n case 'JSXFragment': {\n const children = node.children\n .map(child => (child.type === 'JSXElement' || child.type === 'JSXFragment')\n ? buildElement(child)\n : (child.type === 'JSXText' ? child.value.trim() || null : null)\n )\n .filter(Boolean);\n return React.createElement(React.Fragment, null, ...children);\n }\n\n default:\n return null;\n }\n}\n\n// Simplistic evaluator for static expressions: identifiers -> undefined, literals -> value, objects -> {}\nfunction evaluateExpression(expr) {\n switch (expr.type) {\n case 'StringLiteral': return expr.value;\n case 'NumericLiteral': return expr.value;\n case 'BooleanLiteral': return expr.value;\n case 'ObjectExpression': {\n const obj = {};\n for (const prop of expr.properties) {\n if (prop.type === 'ObjectProperty' && prop.key.type === 'Identifier') {\n obj[prop.key.name] = evaluateExpression(prop.value);\n }\n }\n return obj;\n }\n // Add more cases (Identifier, CallExpression, etc.) as needed\n default:\n return undefined;\n }\n}\n\n// 4) Locate first JSX node\nfunction findJSX(node) {\n if (!node || typeof node !== 'object') return null;\n if (node.type === 'JSXElement' || node.type === 'JSXFragment') return node;\n for (const key of Object.keys(node)) {\n const val = node[key];\n if (Array.isArray(val)) {\n for (const child of val) {\n const found = findJSX(child);\n if (found) return found;\n }\n } else {\n const found = findJSX(val);\n if (found) return found;\n }\n }\n return null;\n}\n\nfunction jsxStringToReactTree(jsxString: string = \"\") {\n const ast = parse(jsxString, { sourceType: 'module', plugins: ['jsx'] });\n const rootJSX = findJSX(ast);\n if (!rootJSX) {\n return null\n }\n\n const reactTree = buildElement(rootJSX)\n\n return reactTree\n}\n\n/**\n * Recursively processes definition properties to convert markdown descriptions to React trees\n * @param definitions The definitions to process\n * @returns The processed definitions with markdown descriptions converted to React trees\n */\nfunction processDefinitionProperties(definitions: Definition[]): Definition[] {\n if (!definitions || !Array.isArray(definitions)) {\n return definitions;\n }\n\n return definitions.map(definition => {\n // Process variants recursively\n if (definition.variants && Array.isArray(definition.variants)) {\n for (const variant of definition.variants) {\n if (variant.properties && Array.isArray(variant.properties)) {\n variant.properties = processDefinitionProperty(variant.properties);\n }\n }\n }\n\n // Process the definition's properties recursively\n if (definition.properties && Array.isArray(definition.properties)) {\n definition.properties = processDefinitionProperty(definition.properties);\n }\n\n if (definition.description && typeof definition.description === \"string\") {\n const md = fromMarkdown(definition.description)\n const hast = toHast(md)\n const html = toHtml(hast)\n const jsx = htmlToJsx(html);\n const reactTree = jsxStringToReactTree(jsx);\n if (reactTree) {\n definition.description = reactTree;\n }\n }\n return definition;\n });\n}\n\n/**\n * Recursively processes definition properties to convert markdown descriptions to React trees\n * @param properties The properties to process\n * @returns The processed properties with markdown descriptions converted to React trees\n */\nfunction processDefinitionProperty(properties: DefinitionProperty[]): DefinitionProperty[] {\n if (!properties || !Array.isArray(properties)) {\n return properties;\n }\n\n return properties.map(property => {\n const newProperty: DefinitionProperty = {\n ...property,\n };\n\n if (typeof newProperty.description === 'string' && isMarkdownText(newProperty.description)) {\n const mdast = fromMarkdown(newProperty.description);\n const hast = toHast(mdast);\n const html = toHtml(hast);\n const jsx = htmlToJsx(html);\n const reactTree = jsxStringToReactTree(jsx);\n if (reactTree) {\n newProperty.description = reactTree;\n }\n }\n\n if (property.properties && Array.isArray(property.properties)) {\n newProperty.properties = processDefinitionProperty(property.properties);\n }\n\n return newProperty;\n });\n}\n\n/**\n * Returns true if the input contains any non-plain-text Markdown tokens.\n */\nfunction isMarkdownText(text: string) {\n // 1) Lex into a token tree\n const tokens = marked.lexer(text);\n let found = false;\n\n // 2) Traverse *every* token (including nested) and flag any non-plain-text kinds\n marked.walkTokens(tokens, token => {\n // ignore pure text/whitespace\n if (!['text', 'paragraph', 'space', 'newline'].includes(token.type)) {\n found = true;\n }\n });\n\n return found;\n}\n\n\n\n/**\n * List of standard MDAST node types\n */\nconst standardMdastTypes = [\n 'root',\n 'paragraph',\n 'heading',\n 'text',\n 'emphasis',\n 'strong',\n 'delete',\n 'blockquote',\n 'code',\n 'link',\n 'image',\n 'list',\n 'listItem',\n 'table',\n 'tableRow',\n 'tableCell',\n 'html',\n 'break',\n 'thematicBreak',\n 'definition',\n 'footnoteDefinition',\n 'footnoteReference',\n 'inlineCode',\n 'linkReference',\n 'imageReference',\n 'footnote',\n 'tableCaption'\n];\n\n\n/**\n * Checks if a given type is a standard MDAST type\n * @param type The node type to check\n * @returns True if the type is a standard MDAST type, false otherwise\n */\nfunction isStandardMdastType(type: string): boolean {\n return standardMdastTypes.includes(type);\n}\n\nfunction isMdxElement(type: string): boolean {\n return type === 'mdxJsxFlowElement'\n}\n","import { registerMetaComponent } from \"@xyd-js/context\";\n\nexport function metaComponent<P, V>(\n name: string,\n componentName?: string\n) {\n return function (\n target: any,\n context: any\n ) {\n registerMetaComponent(\n name,\n componentName || name,\n target\n );\n };\n}\n\n"],"mappings":"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","names":["_a"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xyd-js/composer",
|
|
3
|
+
"version": "0.1.0-xyd.2",
|
|
4
|
+
"description": "xyd composer API",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
"./package.json": "./package.json",
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@babel/parser": "^7.27.2",
|
|
15
|
+
"codehike": "^1.0.7",
|
|
16
|
+
"hast-util-to-html": "^9.0.5",
|
|
17
|
+
"html-to-jsx-transform": "^1.2.0",
|
|
18
|
+
"marked": "^15.0.11",
|
|
19
|
+
"mdast": "^3.0.0",
|
|
20
|
+
"mdast-util-from-markdown": "^2.0.2",
|
|
21
|
+
"mdast-util-mdx": "^3.0.0",
|
|
22
|
+
"mdast-util-to-hast": "^13.2.0",
|
|
23
|
+
"mdast-util-to-markdown": "^2.1.2"
|
|
24
|
+
},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"react": "^19.0.0",
|
|
27
|
+
"@xyd-js/atlas": "0.1.0-xyd.18",
|
|
28
|
+
"@xyd-js/core": "0.1.0-xyd.15",
|
|
29
|
+
"@xyd-js/uniform": "0.1.0-xyd.17",
|
|
30
|
+
"@xyd-js/content": "0.1.0-xyd.16",
|
|
31
|
+
"@xyd-js/context": "0.1.0-xyd.2"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"tsup": "^8.3.0",
|
|
35
|
+
"typescript": "5.6.2"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsup"
|
|
39
|
+
}
|
|
40
|
+
}
|
package/src/Composer.ts
ADDED
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import type { RootContent } from "mdast";
|
|
3
|
+
import { toMarkdown } from "mdast-util-to-markdown";
|
|
4
|
+
import { mdxToMarkdown } from "mdast-util-mdx";
|
|
5
|
+
import { toHast } from 'mdast-util-to-hast'
|
|
6
|
+
import { toHtml } from 'hast-util-to-html'
|
|
7
|
+
import { parse } from '@babel/parser';
|
|
8
|
+
import { highlight } from "codehike/code";
|
|
9
|
+
import { marked } from 'marked';
|
|
10
|
+
import { fromMarkdown } from 'mdast-util-from-markdown';
|
|
11
|
+
import { htmlToJsx } from "html-to-jsx-transform";
|
|
12
|
+
|
|
13
|
+
import { type AtlasProps } from "@xyd-js/atlas";
|
|
14
|
+
import { type Theme as ThemeSettings } from "@xyd-js/core"
|
|
15
|
+
|
|
16
|
+
import { VarCode } from "@xyd-js/content";
|
|
17
|
+
import { ExampleRoot, Definition, DefinitionProperty } from "@xyd-js/uniform";
|
|
18
|
+
|
|
19
|
+
import { metaComponent } from './decorators';
|
|
20
|
+
|
|
21
|
+
// TODO: !!!! REFACTOR !!!
|
|
22
|
+
|
|
23
|
+
interface AtlasVars {
|
|
24
|
+
examples?: VarCode
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// TODO: get object from atlas
|
|
28
|
+
// Define the type for an example object
|
|
29
|
+
interface ExampleObject {
|
|
30
|
+
codeblock: {
|
|
31
|
+
title: string;
|
|
32
|
+
tabs: {
|
|
33
|
+
title: string;
|
|
34
|
+
language: string;
|
|
35
|
+
code: string;
|
|
36
|
+
highlighted: any; // TODO: fix
|
|
37
|
+
}[];
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Define the type for an example group
|
|
42
|
+
interface ExampleGroup {
|
|
43
|
+
examples: ExampleObject[];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export class Composer {
|
|
47
|
+
// TODO: !!! COMPOSE API !!!!
|
|
48
|
+
// TODO: this.themeSettings but currently issues with decorators
|
|
49
|
+
@metaComponent("atlas", "Atlas")
|
|
50
|
+
private async atlasMetaComponent(
|
|
51
|
+
themeSettings: ThemeSettings,
|
|
52
|
+
props: AtlasProps,
|
|
53
|
+
vars: AtlasVars,
|
|
54
|
+
treeChilds: readonly RootContent[]
|
|
55
|
+
) {
|
|
56
|
+
//@ts-ignore
|
|
57
|
+
const outputVarExamples: ExampleRoot = {
|
|
58
|
+
groups: []
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const oneExample = vars.examples?.length === 1 && !Array.isArray(vars.examples[0])
|
|
62
|
+
|
|
63
|
+
// Helper function to create an example object
|
|
64
|
+
function createExampleObject(example: any): ExampleObject {
|
|
65
|
+
// Extract the highlighted property correctly
|
|
66
|
+
const highlighted = example.highlighted || example;
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
codeblock: {
|
|
70
|
+
title: example.meta,
|
|
71
|
+
tabs: [
|
|
72
|
+
{
|
|
73
|
+
title: example.meta,
|
|
74
|
+
language: example.lang,
|
|
75
|
+
code: example.code,
|
|
76
|
+
highlighted: highlighted
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (oneExample) {
|
|
84
|
+
const example = vars.examples?.[0]
|
|
85
|
+
if (Array.isArray(example) || !example) {
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
outputVarExamples.groups.push({
|
|
90
|
+
examples: [createExampleObject(example)]
|
|
91
|
+
})
|
|
92
|
+
} else {
|
|
93
|
+
// Process each example or group of examples
|
|
94
|
+
vars.examples?.forEach((item) => {
|
|
95
|
+
if (Array.isArray(item)) {
|
|
96
|
+
// This is a group with a title as the first element
|
|
97
|
+
const groupTitle = item[0];
|
|
98
|
+
const groupExamples = item.slice(1);
|
|
99
|
+
|
|
100
|
+
const exampleGroup: ExampleGroup = {
|
|
101
|
+
examples: []
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// Process each example in the group
|
|
105
|
+
groupExamples.forEach((example) => {
|
|
106
|
+
if (example && typeof example === 'object') {
|
|
107
|
+
exampleGroup.examples.push(createExampleObject(example));
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
if (exampleGroup.examples.length > 0) {
|
|
112
|
+
outputVarExamples.groups.push(exampleGroup);
|
|
113
|
+
}
|
|
114
|
+
} else if (item && typeof item === 'object') {
|
|
115
|
+
// This is a single example
|
|
116
|
+
const exampleGroup: ExampleGroup = {
|
|
117
|
+
examples: [createExampleObject(item)]
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
outputVarExamples.groups.push(exampleGroup);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const reactElements: React.ReactNode[] = []
|
|
126
|
+
|
|
127
|
+
// TODO: !! IMPORTANT !! BETTER COMPOSE TRANSFORMATION
|
|
128
|
+
for (const child of treeChilds) {
|
|
129
|
+
if (isStandardMdastType(child.type)) {
|
|
130
|
+
const hast = toHast(child)
|
|
131
|
+
const html = toHtml(hast)
|
|
132
|
+
|
|
133
|
+
if (child.type === "heading" && child.depth === 1) {
|
|
134
|
+
const firstChild = child.children[0];
|
|
135
|
+
if (firstChild.type === 'text') {
|
|
136
|
+
props.references[0].title = firstChild.value;
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
const jsx = htmlToJsx(html);
|
|
140
|
+
const reactTree = jsxStringToReactTree(jsx);
|
|
141
|
+
if (reactTree) {
|
|
142
|
+
reactElements.push(reactTree)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
continue
|
|
147
|
+
} else if (isMdxElement(child.type)) {
|
|
148
|
+
const jsxString = toMarkdown(child, {
|
|
149
|
+
extensions: [mdxToMarkdown()],
|
|
150
|
+
handlers: {// TODO: find better solution how to convert such as structure?
|
|
151
|
+
list(node, parent, context) {
|
|
152
|
+
// call containerFlow as a method on context, so `this` stays correct
|
|
153
|
+
const items = node.children
|
|
154
|
+
.map(item => context.containerFlow(item, node))
|
|
155
|
+
.join('\n')
|
|
156
|
+
return `<ul>\n${items}\n</ul>`
|
|
157
|
+
},
|
|
158
|
+
listItem(node, parent, context) {
|
|
159
|
+
// Use a type assertion to handle the parent parameter
|
|
160
|
+
const content = context.containerFlow(node, parent as any).trim()
|
|
161
|
+
return `<li>${content}</li>`
|
|
162
|
+
},
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
const reactTree = jsxStringToReactTree(jsxString)
|
|
167
|
+
if (reactTree) {
|
|
168
|
+
reactElements.push(reactTree)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const propDescription = props.references?.[0]?.description
|
|
174
|
+
if (propDescription) {
|
|
175
|
+
// Sanitize frontmatter description
|
|
176
|
+
if (typeof propDescription === "string") {
|
|
177
|
+
// Remove frontmatter using regex
|
|
178
|
+
const content = propDescription.replace(/^---[\s\S]*?---\n/, '');
|
|
179
|
+
|
|
180
|
+
const md = fromMarkdown(content)
|
|
181
|
+
const hast = toHast(md)
|
|
182
|
+
const html = toHtml(hast)
|
|
183
|
+
const jsx = htmlToJsx(html);
|
|
184
|
+
const reactTree = jsxStringToReactTree(jsx);
|
|
185
|
+
if (reactTree) {
|
|
186
|
+
props.references[0].description = reactTree;
|
|
187
|
+
} else {
|
|
188
|
+
props.references[0].description = content
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (reactElements.length > 0) {
|
|
194
|
+
if (props.references?.[0]?.description) {
|
|
195
|
+
reactElements.unshift(props.references[0].description)
|
|
196
|
+
}
|
|
197
|
+
// Create a combined React element from all the elements
|
|
198
|
+
const combinedReactTree = React.createElement(React.Fragment, null, ...reactElements)
|
|
199
|
+
|
|
200
|
+
if (props.references?.[0]) {
|
|
201
|
+
props.references[0].description = combinedReactTree
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (
|
|
206
|
+
!outputVarExamples.groups.length &&
|
|
207
|
+
props.references[0]?.examples.groups?.length
|
|
208
|
+
) {
|
|
209
|
+
const promises: Promise<void>[] = []
|
|
210
|
+
|
|
211
|
+
props.references[0].examples?.groups.forEach(group => {
|
|
212
|
+
group.examples.forEach(example => {
|
|
213
|
+
example.codeblock.tabs.forEach(tab => {
|
|
214
|
+
|
|
215
|
+
async function highlightCode() {
|
|
216
|
+
const highlighted = await highlight({
|
|
217
|
+
value: tab.code,
|
|
218
|
+
lang: tab.language,
|
|
219
|
+
meta: tab.title,
|
|
220
|
+
}, themeSettings?.coder?.syntaxHighlight || "github-dark")
|
|
221
|
+
|
|
222
|
+
tab.highlighted = highlighted
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
promises.push(highlightCode());
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
await Promise.all(promises);
|
|
231
|
+
} else {
|
|
232
|
+
if (props.references?.[0]) {
|
|
233
|
+
props.references[0].examples = outputVarExamples;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Process definition properties recursively to convert markdown descriptions to React trees
|
|
238
|
+
if (props.references?.[0]?.definitions) {
|
|
239
|
+
props.references[0].definitions = processDefinitionProperties(props.references[0].definitions);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return props
|
|
243
|
+
// TODO: in the future return a component directly here but we need good mechanism for transpiling?
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function buildElement(node) {
|
|
248
|
+
if (!node) return null;
|
|
249
|
+
switch (node.type) {
|
|
250
|
+
case 'JSXElement': {
|
|
251
|
+
// Resolve type (string for custom components)
|
|
252
|
+
let type;
|
|
253
|
+
const nameNode = node.openingElement.name;
|
|
254
|
+
if (nameNode.type === 'JSXMemberExpression') {
|
|
255
|
+
// flatten Foo.Bar to "Foo.Bar"
|
|
256
|
+
const parts: string[] = [];
|
|
257
|
+
let curr = nameNode;
|
|
258
|
+
while (curr) {
|
|
259
|
+
if (curr.property) parts.unshift(curr.property.name);
|
|
260
|
+
curr = curr.object;
|
|
261
|
+
}
|
|
262
|
+
type = parts.join('.');
|
|
263
|
+
} else {
|
|
264
|
+
type = nameNode.name;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Props
|
|
268
|
+
const props = {};
|
|
269
|
+
for (const attr of node.openingElement.attributes) {
|
|
270
|
+
if (attr.type === 'JSXSpreadAttribute') {
|
|
271
|
+
Object.assign(props, evaluateExpression(attr.argument));
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
const key = attr.name.name;
|
|
275
|
+
let value;
|
|
276
|
+
if (!attr.value) {
|
|
277
|
+
value = true;
|
|
278
|
+
} else if (attr.value.type === 'StringLiteral' || attr.value.type === 'NumericLiteral' || attr.value.type === 'BooleanLiteral') {
|
|
279
|
+
value = attr.value.value;
|
|
280
|
+
} else if (attr.value.type === 'JSXExpressionContainer') {
|
|
281
|
+
value = evaluateExpression(attr.value.expression);
|
|
282
|
+
}
|
|
283
|
+
props[key] = value;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Children
|
|
287
|
+
const children = node.children
|
|
288
|
+
.map(child => {
|
|
289
|
+
if (child.type === 'JSXText') {
|
|
290
|
+
const text = child.value.replace(/\s+/g, ' ');
|
|
291
|
+
return text.trim() ? text : null;
|
|
292
|
+
}
|
|
293
|
+
if (child.type === 'JSXExpressionContainer') {
|
|
294
|
+
return child.expression.type === 'JSXElement' || child.expression.type === 'JSXFragment'
|
|
295
|
+
? buildElement(child.expression)
|
|
296
|
+
: evaluateExpression(child.expression);
|
|
297
|
+
}
|
|
298
|
+
if (child.type === 'JSXElement' || child.type === 'JSXFragment') {
|
|
299
|
+
return buildElement(child);
|
|
300
|
+
}
|
|
301
|
+
return null;
|
|
302
|
+
})
|
|
303
|
+
.filter(c => c !== null);
|
|
304
|
+
|
|
305
|
+
// Create React element
|
|
306
|
+
return React.createElement(type, props, ...children);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
case 'JSXFragment': {
|
|
310
|
+
const children = node.children
|
|
311
|
+
.map(child => (child.type === 'JSXElement' || child.type === 'JSXFragment')
|
|
312
|
+
? buildElement(child)
|
|
313
|
+
: (child.type === 'JSXText' ? child.value.trim() || null : null)
|
|
314
|
+
)
|
|
315
|
+
.filter(Boolean);
|
|
316
|
+
return React.createElement(React.Fragment, null, ...children);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
default:
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Simplistic evaluator for static expressions: identifiers -> undefined, literals -> value, objects -> {}
|
|
325
|
+
function evaluateExpression(expr) {
|
|
326
|
+
switch (expr.type) {
|
|
327
|
+
case 'StringLiteral': return expr.value;
|
|
328
|
+
case 'NumericLiteral': return expr.value;
|
|
329
|
+
case 'BooleanLiteral': return expr.value;
|
|
330
|
+
case 'ObjectExpression': {
|
|
331
|
+
const obj = {};
|
|
332
|
+
for (const prop of expr.properties) {
|
|
333
|
+
if (prop.type === 'ObjectProperty' && prop.key.type === 'Identifier') {
|
|
334
|
+
obj[prop.key.name] = evaluateExpression(prop.value);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return obj;
|
|
338
|
+
}
|
|
339
|
+
// Add more cases (Identifier, CallExpression, etc.) as needed
|
|
340
|
+
default:
|
|
341
|
+
return undefined;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// 4) Locate first JSX node
|
|
346
|
+
function findJSX(node) {
|
|
347
|
+
if (!node || typeof node !== 'object') return null;
|
|
348
|
+
if (node.type === 'JSXElement' || node.type === 'JSXFragment') return node;
|
|
349
|
+
for (const key of Object.keys(node)) {
|
|
350
|
+
const val = node[key];
|
|
351
|
+
if (Array.isArray(val)) {
|
|
352
|
+
for (const child of val) {
|
|
353
|
+
const found = findJSX(child);
|
|
354
|
+
if (found) return found;
|
|
355
|
+
}
|
|
356
|
+
} else {
|
|
357
|
+
const found = findJSX(val);
|
|
358
|
+
if (found) return found;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return null;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function jsxStringToReactTree(jsxString: string = "") {
|
|
365
|
+
const ast = parse(jsxString, { sourceType: 'module', plugins: ['jsx'] });
|
|
366
|
+
const rootJSX = findJSX(ast);
|
|
367
|
+
if (!rootJSX) {
|
|
368
|
+
return null
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const reactTree = buildElement(rootJSX)
|
|
372
|
+
|
|
373
|
+
return reactTree
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Recursively processes definition properties to convert markdown descriptions to React trees
|
|
378
|
+
* @param definitions The definitions to process
|
|
379
|
+
* @returns The processed definitions with markdown descriptions converted to React trees
|
|
380
|
+
*/
|
|
381
|
+
function processDefinitionProperties(definitions: Definition[]): Definition[] {
|
|
382
|
+
if (!definitions || !Array.isArray(definitions)) {
|
|
383
|
+
return definitions;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return definitions.map(definition => {
|
|
387
|
+
// Process variants recursively
|
|
388
|
+
if (definition.variants && Array.isArray(definition.variants)) {
|
|
389
|
+
for (const variant of definition.variants) {
|
|
390
|
+
if (variant.properties && Array.isArray(variant.properties)) {
|
|
391
|
+
variant.properties = processDefinitionProperty(variant.properties);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Process the definition's properties recursively
|
|
397
|
+
if (definition.properties && Array.isArray(definition.properties)) {
|
|
398
|
+
definition.properties = processDefinitionProperty(definition.properties);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
if (definition.description && typeof definition.description === "string") {
|
|
402
|
+
const md = fromMarkdown(definition.description)
|
|
403
|
+
const hast = toHast(md)
|
|
404
|
+
const html = toHtml(hast)
|
|
405
|
+
const jsx = htmlToJsx(html);
|
|
406
|
+
const reactTree = jsxStringToReactTree(jsx);
|
|
407
|
+
if (reactTree) {
|
|
408
|
+
definition.description = reactTree;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
return definition;
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Recursively processes definition properties to convert markdown descriptions to React trees
|
|
417
|
+
* @param properties The properties to process
|
|
418
|
+
* @returns The processed properties with markdown descriptions converted to React trees
|
|
419
|
+
*/
|
|
420
|
+
function processDefinitionProperty(properties: DefinitionProperty[]): DefinitionProperty[] {
|
|
421
|
+
if (!properties || !Array.isArray(properties)) {
|
|
422
|
+
return properties;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
return properties.map(property => {
|
|
426
|
+
const newProperty: DefinitionProperty = {
|
|
427
|
+
...property,
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
if (typeof newProperty.description === 'string' && isMarkdownText(newProperty.description)) {
|
|
431
|
+
const mdast = fromMarkdown(newProperty.description);
|
|
432
|
+
const hast = toHast(mdast);
|
|
433
|
+
const html = toHtml(hast);
|
|
434
|
+
const jsx = htmlToJsx(html);
|
|
435
|
+
const reactTree = jsxStringToReactTree(jsx);
|
|
436
|
+
if (reactTree) {
|
|
437
|
+
newProperty.description = reactTree;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
if (property.properties && Array.isArray(property.properties)) {
|
|
442
|
+
newProperty.properties = processDefinitionProperty(property.properties);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
return newProperty;
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Returns true if the input contains any non-plain-text Markdown tokens.
|
|
451
|
+
*/
|
|
452
|
+
function isMarkdownText(text: string) {
|
|
453
|
+
// 1) Lex into a token tree
|
|
454
|
+
const tokens = marked.lexer(text);
|
|
455
|
+
let found = false;
|
|
456
|
+
|
|
457
|
+
// 2) Traverse *every* token (including nested) and flag any non-plain-text kinds
|
|
458
|
+
marked.walkTokens(tokens, token => {
|
|
459
|
+
// ignore pure text/whitespace
|
|
460
|
+
if (!['text', 'paragraph', 'space', 'newline'].includes(token.type)) {
|
|
461
|
+
found = true;
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
return found;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* List of standard MDAST node types
|
|
472
|
+
*/
|
|
473
|
+
const standardMdastTypes = [
|
|
474
|
+
'root',
|
|
475
|
+
'paragraph',
|
|
476
|
+
'heading',
|
|
477
|
+
'text',
|
|
478
|
+
'emphasis',
|
|
479
|
+
'strong',
|
|
480
|
+
'delete',
|
|
481
|
+
'blockquote',
|
|
482
|
+
'code',
|
|
483
|
+
'link',
|
|
484
|
+
'image',
|
|
485
|
+
'list',
|
|
486
|
+
'listItem',
|
|
487
|
+
'table',
|
|
488
|
+
'tableRow',
|
|
489
|
+
'tableCell',
|
|
490
|
+
'html',
|
|
491
|
+
'break',
|
|
492
|
+
'thematicBreak',
|
|
493
|
+
'definition',
|
|
494
|
+
'footnoteDefinition',
|
|
495
|
+
'footnoteReference',
|
|
496
|
+
'inlineCode',
|
|
497
|
+
'linkReference',
|
|
498
|
+
'imageReference',
|
|
499
|
+
'footnote',
|
|
500
|
+
'tableCaption'
|
|
501
|
+
];
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Checks if a given type is a standard MDAST type
|
|
506
|
+
* @param type The node type to check
|
|
507
|
+
* @returns True if the type is a standard MDAST type, false otherwise
|
|
508
|
+
*/
|
|
509
|
+
function isStandardMdastType(type: string): boolean {
|
|
510
|
+
return standardMdastTypes.includes(type);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
function isMdxElement(type: string): boolean {
|
|
514
|
+
return type === 'mdxJsxFlowElement'
|
|
515
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { registerMetaComponent } from "@xyd-js/context";
|
|
2
|
+
|
|
3
|
+
export function metaComponent<P, V>(
|
|
4
|
+
name: string,
|
|
5
|
+
componentName?: string
|
|
6
|
+
) {
|
|
7
|
+
return function (
|
|
8
|
+
target: any,
|
|
9
|
+
context: any
|
|
10
|
+
) {
|
|
11
|
+
registerMetaComponent(
|
|
12
|
+
name,
|
|
13
|
+
componentName || name,
|
|
14
|
+
target
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
package/src/index.ts
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"paths": {
|
|
4
|
+
"@xyd-js/framework/react": [
|
|
5
|
+
"../xyd-framework/packages/react/index.ts"
|
|
6
|
+
],
|
|
7
|
+
"@xyd-js/context": [
|
|
8
|
+
"../xyd-context/src/index.ts"
|
|
9
|
+
],
|
|
10
|
+
"@xyd-js/core": [
|
|
11
|
+
"../xyd-core/src/index.ts"
|
|
12
|
+
]
|
|
13
|
+
},
|
|
14
|
+
"module": "esnext",
|
|
15
|
+
"esModuleInterop": true,
|
|
16
|
+
"moduleResolution": "bundler",
|
|
17
|
+
"target": "ES6",
|
|
18
|
+
"lib": [
|
|
19
|
+
"dom",
|
|
20
|
+
"dom.iterable",
|
|
21
|
+
"esnext"
|
|
22
|
+
],
|
|
23
|
+
"allowJs": true,
|
|
24
|
+
"skipLibCheck": true,
|
|
25
|
+
"strict": false,
|
|
26
|
+
"noEmit": true,
|
|
27
|
+
"incremental": false,
|
|
28
|
+
"resolveJsonModule": true,
|
|
29
|
+
"isolatedModules": true,
|
|
30
|
+
"jsx": "preserve",
|
|
31
|
+
"plugins": [
|
|
32
|
+
{
|
|
33
|
+
"name": "next"
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
"strictNullChecks": true,
|
|
37
|
+
"typeRoots": [
|
|
38
|
+
"./types.d.ts"
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
"include": [
|
|
42
|
+
"src/**/*.ts",
|
|
43
|
+
"src/**/*.tsx",
|
|
44
|
+
"types.d.ts"
|
|
45
|
+
],
|
|
46
|
+
"exclude": [
|
|
47
|
+
"node_modules"
|
|
48
|
+
]
|
|
49
|
+
}
|
package/tsup.config.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { defineConfig } from 'tsup';
|
|
2
|
+
import pkg from './package.json' assert { type: 'json' }
|
|
3
|
+
|
|
4
|
+
const deps = [
|
|
5
|
+
...Object.keys(pkg.devDependencies || {}),
|
|
6
|
+
...Object.keys(pkg.peerDependencies || {}),
|
|
7
|
+
]
|
|
8
|
+
|
|
9
|
+
export default defineConfig({
|
|
10
|
+
entry: {
|
|
11
|
+
index: 'src/index.ts'
|
|
12
|
+
},
|
|
13
|
+
format: ['esm'],
|
|
14
|
+
target: 'node16',
|
|
15
|
+
dts: {
|
|
16
|
+
entry: {
|
|
17
|
+
index: 'src/index.ts'
|
|
18
|
+
},
|
|
19
|
+
resolve: true,
|
|
20
|
+
},
|
|
21
|
+
splitting: false,
|
|
22
|
+
sourcemap: true,
|
|
23
|
+
clean: true,
|
|
24
|
+
external: [
|
|
25
|
+
...deps
|
|
26
|
+
],
|
|
27
|
+
esbuildOptions: (options) => {
|
|
28
|
+
options.platform = 'node';
|
|
29
|
+
options.external = ['node:fs/promises', 'react-router'];
|
|
30
|
+
options.loader = { '.js': 'jsx' };
|
|
31
|
+
},
|
|
32
|
+
ignoreWatch: ['node_modules', 'dist', '.git', 'build']
|
|
33
|
+
});
|