@qds.dev/tools 0.7.5 → 0.8.5

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.
Files changed (38) hide show
  1. package/lib/docs/component-props.qwik.mjs +500 -0
  2. package/lib/docs/index.qwik.mjs +3 -0
  3. package/lib/playground/generate-jsx.qwik.mjs +153 -0
  4. package/lib/playground/index.qwik.mjs +10 -0
  5. package/lib/playground/prop-extraction.qwik.mjs +500 -0
  6. package/lib/playground/scenario-injection.qwik.mjs +68 -0
  7. package/lib/repl/bundler/bundled.qwik.mjs +38 -0
  8. package/lib/repl/bundler/index.qwik.mjs +89 -0
  9. package/lib/repl/index.qwik.mjs +21 -0
  10. package/lib/repl/repl-constants.qwik.mjs +5 -0
  11. package/lib/rolldown/index.qwik.mjs +2 -1
  12. package/lib/rolldown/inline-asset.qwik.mjs +171 -0
  13. package/lib/rolldown/playground.qwik.mjs +67 -0
  14. package/lib/vite/index.qwik.mjs +2 -1
  15. package/lib/vite/minify-content.qwik.mjs +6 -4
  16. package/lib-types/tools/docs/component-props.d.ts +32 -0
  17. package/lib-types/tools/docs/component-props.unit.d.ts +1 -0
  18. package/lib-types/tools/docs/generate-metadata.d.ts +1 -0
  19. package/lib-types/tools/docs/generate-metadata.unit.d.ts +1 -0
  20. package/lib-types/tools/docs/index.d.ts +2 -0
  21. package/lib-types/tools/playground/generate-jsx.d.ts +9 -0
  22. package/lib-types/tools/playground/generate-metadata.d.ts +1 -0
  23. package/lib-types/tools/playground/generate-metadata.unit.d.ts +1 -0
  24. package/lib-types/tools/playground/index.d.ts +5 -0
  25. package/lib-types/tools/playground/prop-extraction.d.ts +32 -0
  26. package/lib-types/tools/playground/prop-extraction.unit.d.ts +1 -0
  27. package/lib-types/tools/playground/scenario-injection.d.ts +2 -0
  28. package/lib-types/tools/playground/scenario-injection.unit.d.ts +1 -0
  29. package/lib-types/tools/rolldown/index.d.ts +2 -0
  30. package/lib-types/tools/rolldown/inline-asset.d.ts +18 -0
  31. package/lib-types/tools/rolldown/inline-asset.unit.d.ts +1 -0
  32. package/lib-types/tools/rolldown/playground.d.ts +8 -0
  33. package/lib-types/tools/rolldown/playground.unit.d.ts +1 -0
  34. package/lib-types/tools/src/vite.d.ts +1 -0
  35. package/lib-types/tools/utils/fs-mock.d.ts +17 -0
  36. package/lib-types/tools/vite/index.d.ts +3 -2
  37. package/package.json +6 -2
  38. package/lib-types/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,89 @@
1
+ import { getDeps } from "./bundled.qwik.mjs";
2
+
3
+ //#region repl/bundler/index.ts
4
+ var Bundler = class {
5
+ worker = null;
6
+ initP = null;
7
+ ready = null;
8
+ timer = null;
9
+ buildPromises = /* @__PURE__ */ new Map();
10
+ nextBuildId = 1;
11
+ constructor() {
12
+ this.initWorker();
13
+ this.keepAlive();
14
+ }
15
+ initWorker() {
16
+ this.initP = new Promise((res) => this.ready = res);
17
+ this.worker = new Worker(new URL("./repl-bundler-worker.ts", import.meta.url), { type: "module" });
18
+ this.worker.addEventListener("message", this.messageHandler);
19
+ this.worker.addEventListener("error", (e) => {
20
+ console.error(`Bundler worker failed`, e.message);
21
+ this.terminateWorker();
22
+ });
23
+ }
24
+ messageHandler = (e) => {
25
+ const { type } = e.data;
26
+ if (type === "ready") {
27
+ const message = {
28
+ type: "init",
29
+ deps: getDeps()
30
+ };
31
+ this.worker.postMessage.bind(this.worker)(message);
32
+ this.ready();
33
+ } else if (type === "result" || type === "error") {
34
+ const { buildId } = e.data;
35
+ const promise = this.buildPromises.get(buildId);
36
+ if (promise) {
37
+ this.buildPromises.delete(buildId);
38
+ if (type === "result") promise.resolve(e.data.result);
39
+ else {
40
+ const { error, stack } = e.data;
41
+ const err = new Error(error);
42
+ if (stack) err.stack = stack;
43
+ promise.reject(err);
44
+ }
45
+ }
46
+ }
47
+ };
48
+ keepAlive() {
49
+ clearTimeout(this.timer);
50
+ this.timer = setTimeout(() => this.terminateWorker(), 1e3 * 60 * 5);
51
+ }
52
+ bundle(options) {
53
+ if (!this.worker) this.initWorker();
54
+ this.keepAlive();
55
+ return this.initP.then(() => {
56
+ return new Promise((resolve, reject) => {
57
+ const buildId = this.nextBuildId++;
58
+ this.buildPromises.set(buildId, {
59
+ resolve,
60
+ reject
61
+ });
62
+ const message = {
63
+ type: "bundle",
64
+ buildId,
65
+ data: options
66
+ };
67
+ const postMessage = this.worker?.postMessage.bind(this.worker);
68
+ postMessage?.(message);
69
+ });
70
+ });
71
+ }
72
+ terminateWorker() {
73
+ if (this.worker) {
74
+ this.worker.removeEventListener("message", this.messageHandler);
75
+ this.worker.terminate();
76
+ this.worker = null;
77
+ this.buildPromises.forEach((p) => p.reject(/* @__PURE__ */ new Error("Worker terminated")));
78
+ this.buildPromises.clear();
79
+ }
80
+ }
81
+ };
82
+ let bundler;
83
+ const getBundler = () => {
84
+ if (!bundler) bundler = new Bundler();
85
+ return bundler;
86
+ };
87
+
88
+ //#endregion
89
+ export { getBundler };
@@ -0,0 +1,21 @@
1
+ import { getBundler } from "./bundler/index.qwik.mjs";
2
+
3
+ //#region repl/index.ts
4
+ var ReplCompiler = class {
5
+ options;
6
+ bundler;
7
+ constructor(options) {
8
+ this.options = options;
9
+ this.bundler = getBundler();
10
+ }
11
+ async compile(input) {
12
+ const finalOptions = {
13
+ ...this.options,
14
+ ...input
15
+ };
16
+ return this.bundler.bundle(finalOptions);
17
+ }
18
+ };
19
+
20
+ //#endregion
21
+ export { ReplCompiler };
@@ -0,0 +1,5 @@
1
+ //#region repl/repl-constants.ts
2
+ const QWIK_PKG_NAME = "@qwik.dev/core";
3
+
4
+ //#endregion
5
+ export { QWIK_PKG_NAME };
@@ -1,6 +1,7 @@
1
1
  import { asChild } from "./as-child.qwik.mjs";
2
2
  import { icons } from "./icons.qwik.mjs";
3
+ import { inlineAsset } from "./inline-asset.qwik.mjs";
3
4
  import { inlineCssPlugin } from "./inline-css.qwik.mjs";
4
5
  import { qwikRolldown } from "./qwik-rolldown.qwik.mjs";
5
6
 
6
- export { asChild, icons, inlineCssPlugin, qwikRolldown };
7
+ export { asChild, icons, inlineAsset, inlineCssPlugin, qwikRolldown };
@@ -0,0 +1,171 @@
1
+ import { anyOf, char, createRegExp, exactly, maybe, oneOrMore } from "magic-regexp";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { createRequire } from "node:module";
4
+ import { basename, dirname, join } from "node:path";
5
+ import { createHash } from "node:crypto";
6
+
7
+ //#region rolldown/inline-asset.ts
8
+ const nodeRequire = createRequire(import.meta.url);
9
+ /**
10
+ * Embeds file content as build-time assets, returning URLs to the inlined content.
11
+ * Supports both relative paths and package imports (e.g., @qwik.dev/core/dist/...).
12
+ *
13
+ * Supports two query parameters:
14
+ * - `?inline-asset` - Inlines the file content as an asset
15
+ * - `?no-transform` - Returns raw file content without any transformations
16
+ *
17
+ * @param options - Plugin configuration options
18
+ * @returns Rolldown/Vite-compatible plugin object
19
+ */ const inlineAsset = (options = {}) => {
20
+ const { debug: isDebugMode = false, outDir = "public/.qds-inline-assets" } = options;
21
+ const debugInlineAsset = (...args) => {
22
+ if (!isDebugMode) return;
23
+ console.log("[inline-asset]", ...args);
24
+ };
25
+ let isDevMode = false;
26
+ const assetDir = join(process.cwd(), outDir);
27
+ if (!existsSync(assetDir)) {
28
+ mkdirSync(assetDir, { recursive: true });
29
+ debugInlineAsset("Created asset directory:", assetDir);
30
+ }
31
+ const inlineAssetQuery = createRegExp(anyOf("?", "&"), exactly("inline-asset"));
32
+ const noTransformQuery = createRegExp(anyOf("?", "&"), exactly("no-transform"));
33
+ const combinedQuery = createRegExp(anyOf("?", "&"), anyOf(exactly("inline-asset"), exactly("no-transform")));
34
+ const inlineAssetPattern = createRegExp(anyOf(exactly("?"), exactly("&")), exactly("inline-asset"), maybe(exactly("&"), oneOrMore(char)), ["g"]);
35
+ const noTransformPattern = createRegExp(anyOf(exactly("?"), exactly("&")), exactly("no-transform"), maybe(exactly("&"), oneOrMore(char)), ["g"]);
36
+ return {
37
+ name: "inline-asset",
38
+ configResolved(config) {
39
+ isDevMode = config.command === "serve";
40
+ debugInlineAsset("Dev mode:", isDevMode);
41
+ },
42
+ resolveId: {
43
+ order: "pre",
44
+ filter: { id: combinedQuery },
45
+ async handler(id, importer, options$1) {
46
+ const isInlineAsset = inlineAssetQuery.test(id);
47
+ const isNoTransform = noTransformQuery.test(id);
48
+ if (!isInlineAsset && !isNoTransform) return;
49
+ debugInlineAsset("resolveId:", {
50
+ id,
51
+ importer,
52
+ isInlineAsset,
53
+ isNoTransform
54
+ });
55
+ const basePath = id.replace(inlineAssetPattern, "").replace(noTransformPattern, "");
56
+ debugInlineAsset("Resolving base path:", basePath);
57
+ let resolvedPath = null;
58
+ try {
59
+ const resolved = await this.resolve(basePath, importer, {
60
+ ...options$1,
61
+ skipSelf: true
62
+ });
63
+ if (resolved) resolvedPath = resolved.id.split("?")[0];
64
+ } catch {
65
+ if (basePath.startsWith("@") || !basePath.startsWith(".") && !basePath.startsWith("/")) {
66
+ const parts = basePath.split("/");
67
+ let packageName;
68
+ let subpathStartIndex;
69
+ if (basePath.startsWith("@")) {
70
+ packageName = `${parts[0]}/${parts[1]}`;
71
+ subpathStartIndex = 2;
72
+ } else {
73
+ packageName = parts[0];
74
+ subpathStartIndex = 1;
75
+ }
76
+ const subpath = parts.slice(subpathStartIndex).join("/");
77
+ try {
78
+ const basePath$1 = importer ? dirname(importer) : process.cwd();
79
+ resolvedPath = join(dirname(nodeRequire.resolve(`${packageName}/package.json`, { paths: [basePath$1] })), subpath);
80
+ debugInlineAsset("Manually resolved package import:", resolvedPath);
81
+ } catch (err) {
82
+ debugInlineAsset("Failed to manually resolve:", err);
83
+ }
84
+ }
85
+ }
86
+ if (!resolvedPath) {
87
+ debugInlineAsset("Could not resolve path:", basePath, "- returning null");
88
+ return null;
89
+ }
90
+ if (!existsSync(resolvedPath)) {
91
+ debugInlineAsset("Resolved path does not exist:", resolvedPath, "- returning null");
92
+ return null;
93
+ }
94
+ debugInlineAsset("Resolved to:", resolvedPath);
95
+ let queryParam;
96
+ if (isInlineAsset) queryParam = "inline-asset-resolved";
97
+ else queryParam = "no-transform-resolved";
98
+ const resolvedId = `${resolvedPath}?${queryParam}`;
99
+ debugInlineAsset("Returning resolved ID:", resolvedId);
100
+ return {
101
+ id: resolvedId,
102
+ external: false
103
+ };
104
+ }
105
+ },
106
+ load(id) {
107
+ const isInlineAsset = id.includes("?inline-asset-resolved");
108
+ const isNoTransform = id.includes("?no-transform-resolved");
109
+ if (!isInlineAsset && !isNoTransform) return null;
110
+ let path = id.split("?")[0];
111
+ if (path.startsWith("/@fs/")) path = path.slice(4);
112
+ if (path.startsWith("\0")) path = path.slice(1);
113
+ debugInlineAsset("Loading file:", path, {
114
+ isInlineAsset,
115
+ isNoTransform
116
+ });
117
+ if (!existsSync(path)) throw new Error(`[inline-asset] File not found: ${path}`);
118
+ const fileContent = readFileSync(path);
119
+ debugInlineAsset("Read file:", path, `(${fileContent.length} bytes)`);
120
+ const isTestMode = typeof process !== "undefined" && (process.env.VITEST || process.env.NODE_ENV === "test");
121
+ debugInlineAsset("Test mode:", isTestMode, "Dev mode:", isDevMode);
122
+ if (isTestMode || isDevMode) {
123
+ debugInlineAsset("Using data URL for", isTestMode ? "test" : "dev", "mode:", basename(path));
124
+ const base64 = fileContent.toString("base64");
125
+ const dataUrl = `data:${{
126
+ js: "application/javascript",
127
+ mjs: "application/javascript",
128
+ wasm: "application/wasm",
129
+ json: "application/json",
130
+ css: "text/css",
131
+ html: "text/html",
132
+ ts: "application/typescript",
133
+ dts: "application/typescript"
134
+ }[path.split(".").pop() || ""] || "application/octet-stream"};base64,${base64}`;
135
+ debugInlineAsset("Returning data URL, length:", dataUrl.length);
136
+ return {
137
+ code: `export default ${JSON.stringify(dataUrl)};`,
138
+ map: {
139
+ version: 3,
140
+ sources: [path],
141
+ mappings: ""
142
+ }
143
+ };
144
+ }
145
+ const hash = createHash("sha256").update(fileContent).digest("hex").slice(0, 8);
146
+ const ext = path.split(".").pop() || "bin";
147
+ const fileName = `${basename(path, `.${ext}`)}-${hash}.${ext}`;
148
+ const outputPath = join(assetDir, fileName);
149
+ try {
150
+ writeFileSync(outputPath, fileContent);
151
+ debugInlineAsset("Wrote asset file:", outputPath);
152
+ } catch (err) {
153
+ throw new Error(`[inline-asset] Failed to write file ${outputPath}`, { cause: err });
154
+ }
155
+ const publicPrefixRegex = createRegExp(exactly("public/").at.lineStart());
156
+ const publicUrl = `/${outDir.replace(publicPrefixRegex, "")}/${fileName}`;
157
+ debugInlineAsset("Returning public URL:", publicUrl);
158
+ return {
159
+ code: `export default ${JSON.stringify(publicUrl)};`,
160
+ map: {
161
+ version: 3,
162
+ sources: [path],
163
+ mappings: ""
164
+ }
165
+ };
166
+ }
167
+ };
168
+ };
169
+
170
+ //#endregion
171
+ export { inlineAsset };
@@ -0,0 +1,67 @@
1
+ import { createRegExp, exactly } from "magic-regexp";
2
+ import MagicString from "magic-string";
3
+ import { walk } from "oxc-walker";
4
+ import { existsSync, readdirSync, statSync } from "node:fs";
5
+ import { basename, dirname, extname, join } from "node:path";
6
+ import { remark } from "remark";
7
+ import remarkMdx from "remark-mdx";
8
+
9
+ //#region rolldown/playground.ts
10
+ const playground = () => {
11
+ const isMDX = createRegExp(exactly(".").and("mdx").at.lineEnd());
12
+ return {
13
+ name: "vite-plugin-qds-playground",
14
+ enforce: "pre",
15
+ async transform(code, id) {
16
+ if (!isMDX.test(id)) return;
17
+ try {
18
+ const mdast = remark().use(remarkMdx).parse(code);
19
+ const s = new MagicString(code);
20
+ let hasPlayground = false;
21
+ const scenariosDir = join(dirname(id), "scenarios");
22
+ if (!existsSync(scenariosDir) || !statSync(scenariosDir).isDirectory()) return null;
23
+ const scenarioFiles = readdirSync(scenariosDir).filter((file) => file.endsWith(".tsx") || file.endsWith(".ts")).map((file) => {
24
+ const name = basename(file, extname(file));
25
+ return {
26
+ name,
27
+ file,
28
+ componentVar: `Scenario_${name.replace(/[^a-zA-Z0-9]/g, "_")}`,
29
+ sourceVar: `Source_${name.replace(/[^a-zA-Z0-9]/g, "_")}`
30
+ };
31
+ });
32
+ if (scenarioFiles.length === 0) return null;
33
+ walk(mdast, { enter(node) {
34
+ const mdxNode = node;
35
+ if ((mdxNode.type === "mdxJsxFlowElement" || mdxNode.type === "mdxJsxTextElement") && mdxNode.name === "Playground") {
36
+ if (mdxNode.position?.start?.offset !== void 0 && mdxNode.position?.end?.offset !== void 0) {
37
+ if (!mdxNode.attributes.some((attr) => attr.name === "scenarios")) {
38
+ const scenariosArrayString = `[${scenarioFiles.map((s$1) => `{name: "${s$1.name}", component: ${s$1.componentVar}, source: ${s$1.sourceVar}}`).join(", ")}]`;
39
+ const insertPos$1 = mdxNode.position.start.offset + 11;
40
+ s.appendLeft(insertPos$1, ` scenarios={${scenariosArrayString}}`);
41
+ hasPlayground = true;
42
+ }
43
+ }
44
+ }
45
+ } });
46
+ if (!hasPlayground) return null;
47
+ const imports = scenarioFiles.map((file) => `import ${file.componentVar} from "./scenarios/${file.file}";\nimport ${file.sourceVar} from "./scenarios/${file.file}?raw";`).join("\n");
48
+ let insertPos = 0;
49
+ if (code.startsWith("---")) {
50
+ const secondDelimiter = code.indexOf("---", 3);
51
+ if (secondDelimiter !== -1) insertPos = secondDelimiter + 3;
52
+ }
53
+ s.appendLeft(insertPos, `\n${imports}\n`);
54
+ return {
55
+ code: s.toString(),
56
+ map: s.generateMap({ hires: true })
57
+ };
58
+ } catch (error) {
59
+ console.error(`Error transforming Playground in ${id}:`, error);
60
+ return null;
61
+ }
62
+ }
63
+ };
64
+ };
65
+
66
+ //#endregion
67
+ export { playground };
@@ -1,6 +1,7 @@
1
1
  import { asChild } from "../rolldown/as-child.qwik.mjs";
2
2
  import { icons } from "../rolldown/icons.qwik.mjs";
3
+ import { inlineAsset } from "../rolldown/inline-asset.qwik.mjs";
3
4
  import "../rolldown/index.qwik.mjs";
4
5
  import { minifyContentPlugin } from "./minify-content.qwik.mjs";
5
6
 
6
- export { asChild, icons, minifyContentPlugin };
7
+ export { asChild, icons, inlineAsset, minifyContentPlugin };
@@ -8,15 +8,16 @@ import { transform } from "oxc-transform";
8
8
  /**
9
9
  * This plugin strips types, then minifies the contents of files with the ".script." extension. We watch the components library files and update the injected scripts when the contents change. Useful for dynamic client-only code without waking up the Qwik runtime.
10
10
  */ function minifyContentPlugin(options) {
11
+ const isTestMode = typeof process !== "undefined" && (process.env.VITEST || process.env.NODE_ENV === "test");
11
12
  const scriptsMap = {};
12
13
  const outputFileName = options?.outputFileName || "injected-scripts.ts";
13
14
  const outputTsPath = resolve(options?.outputDir || process.cwd(), outputFileName);
14
15
  const partString = `.${options?.part || "script"}.`;
15
16
  const scriptExtension = createRegExp(exactly(partString).and(oneOrMore(char)).at.lineEnd());
16
17
  const processMap = async (id, code) => {
17
- const basename = id.split(sep).join("/").split("/").pop() || "";
18
- if (!scriptExtension.test(basename)) return false;
19
- const [name] = basename.split(partString);
18
+ const basename$1 = id.split(sep).join("/").split("/").pop() || "";
19
+ if (!scriptExtension.test(basename$1)) return false;
20
+ const [name] = basename$1.split(partString);
20
21
  if (!name) return false;
21
22
  try {
22
23
  scriptsMap[name] = minifySync(id, (await transform(id, code, { typescript: { onlyRemoveTypeImports: false } })).code, {
@@ -24,6 +25,7 @@ import { transform } from "oxc-transform";
24
25
  mangle: { toplevel: true }
25
26
  }).code;
26
27
  const newFileContent = `export const INJECTED_SCRIPTS = ${JSON.stringify(scriptsMap, null, 2)} as const;`;
28
+ if (isTestMode) return true;
27
29
  let shouldWrite = true;
28
30
  if (existsSync(outputTsPath)) {
29
31
  if (readFileSync(outputTsPath, "utf-8") === newFileContent) shouldWrite = false;
@@ -35,7 +37,7 @@ import { transform } from "oxc-transform";
35
37
  return false;
36
38
  }
37
39
  };
38
- if (!existsSync(outputTsPath)) writeFileSync(outputTsPath, "export const INJECTED_SCRIPTS = {} as const;", "utf-8");
40
+ if (!isTestMode && !existsSync(outputTsPath)) writeFileSync(outputTsPath, "export const INJECTED_SCRIPTS = {} as const;", "utf-8");
39
41
  return {
40
42
  name: "vite-plugin-script-injector",
41
43
  enforce: "pre",
@@ -0,0 +1,32 @@
1
+ import type { Node } from "@oxc-project/types";
2
+ import type { Plugin as VitePlugin } from "vite";
3
+ export type PropType = {
4
+ name: string;
5
+ type: "boolean" | "string" | "number" | "union" | "function" | "unknown";
6
+ unionValues?: string[];
7
+ isBindable: boolean;
8
+ isFunction?: boolean;
9
+ initialValue?: unknown;
10
+ comment?: string;
11
+ scenario?: string;
12
+ };
13
+ export type ComponentPiece = {
14
+ name: string;
15
+ props: PropType[];
16
+ };
17
+ export type ComponentMetadata = {
18
+ componentName: string;
19
+ pieces: ComponentPiece[];
20
+ };
21
+ export type ComponentPropsPluginOptions = {
22
+ componentsDir: string;
23
+ outputDir: string;
24
+ debug?: boolean;
25
+ };
26
+ export declare const componentProps: (options: ComponentPropsPluginOptions) => VitePlugin;
27
+ export declare function generateAllComponentMetadata(componentsDir: string, outputDir: string, debug: (message: string, ...data: unknown[]) => void): Promise<void>;
28
+ export declare function generateComponentMetadata(componentName: string, componentsDir: string, outputDir: string, debug: (message: string, ...data: unknown[]) => void): Promise<void>;
29
+ export declare function extractJSDoc(node: Node, source: string, propName?: string): {
30
+ comment?: string;
31
+ scenario?: string;
32
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export * from "./component-props";
2
+ export type { ComponentMetadata, ComponentPiece, PropType } from "./component-props";
@@ -0,0 +1,9 @@
1
+ import type { ComponentMetadata } from "./prop-extraction";
2
+ export type GenerateJsxOptions = {
3
+ metadata: ComponentMetadata;
4
+ selectedPieceName: string;
5
+ propValues: Record<string, Record<string, unknown>>;
6
+ isBindProps: boolean;
7
+ baseSource?: string;
8
+ };
9
+ export declare function generateJsx({ metadata, selectedPieceName, propValues, isBindProps, baseSource }: GenerateJsxOptions): string;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ import type { Plugin as VitePlugin } from "vite";
2
+ import { type ComponentPropsPluginOptions } from "./prop-extraction";
3
+ export type PlaygroundPluginOptions = ComponentPropsPluginOptions;
4
+ export declare const playground: (options: PlaygroundPluginOptions) => VitePlugin[];
5
+ export type { ComponentMetadata, ComponentPiece, PropType } from "./prop-extraction";
@@ -0,0 +1,32 @@
1
+ import type { Node } from "@oxc-project/types";
2
+ import type { Plugin as VitePlugin } from "vite";
3
+ export type PropType = {
4
+ name: string;
5
+ type: "boolean" | "string" | "number" | "union" | "function" | "unknown";
6
+ unionValues?: string[];
7
+ isBindable: boolean;
8
+ isFunction?: boolean;
9
+ initialValue?: unknown;
10
+ comment?: string;
11
+ scenario?: string;
12
+ };
13
+ export type ComponentPiece = {
14
+ name: string;
15
+ props: PropType[];
16
+ };
17
+ export type ComponentMetadata = {
18
+ componentName: string;
19
+ pieces: ComponentPiece[];
20
+ };
21
+ export type ComponentPropsPluginOptions = {
22
+ componentsDir: string;
23
+ outputDir: string;
24
+ debug?: boolean;
25
+ };
26
+ export declare const propExtraction: (options: ComponentPropsPluginOptions) => VitePlugin;
27
+ export declare function generateAllComponentMetadata(componentsDir: string, outputDir: string, debug: (message: string, ...data: unknown[]) => void): Promise<void>;
28
+ export declare function generateComponentMetadata(componentName: string, componentsDir: string, outputDir: string, debug: (message: string, ...data: unknown[]) => void): Promise<void>;
29
+ export declare function extractJSDoc(node: Node, source: string, propName?: string): {
30
+ comment?: string;
31
+ scenario?: string;
32
+ };
@@ -0,0 +1,2 @@
1
+ import type { Plugin as VitePlugin } from "vite";
2
+ export declare const scenarioInjection: () => VitePlugin;
@@ -2,5 +2,7 @@ export type { AsChildPluginOptions, AsChildTypes } from "./as-child";
2
2
  export { asChild } from "./as-child";
3
3
  export type { IconsPluginOptions, PacksMap } from "./icons";
4
4
  export { icons } from "./icons";
5
+ export type { InlineAssetPluginOptions } from "./inline-asset";
6
+ export { inlineAsset } from "./inline-asset";
5
7
  export { inlineCssPlugin } from "./inline-css";
6
8
  export { qwikRolldown } from "./qwik-rolldown";
@@ -0,0 +1,18 @@
1
+ import type { Plugin } from "rolldown";
2
+ export type InlineAssetPluginOptions = {
3
+ debug?: boolean;
4
+ /** Directory to write inline assets (relative to project root). Defaults to 'public/.qds-inline-assets' */
5
+ outDir?: string;
6
+ };
7
+ /**
8
+ * Embeds file content as build-time assets, returning URLs to the inlined content.
9
+ * Supports both relative paths and package imports (e.g., @qwik.dev/core/dist/...).
10
+ *
11
+ * Supports two query parameters:
12
+ * - `?inline-asset` - Inlines the file content as an asset
13
+ * - `?no-transform` - Returns raw file content without any transformations
14
+ *
15
+ * @param options - Plugin configuration options
16
+ * @returns Rolldown/Vite-compatible plugin object
17
+ */
18
+ export declare const inlineAsset: (options?: InlineAssetPluginOptions) => Plugin;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ export declare const playground: () => {
2
+ name: string;
3
+ enforce: "pre";
4
+ transform(code: string, id: string): Promise<{
5
+ code: string;
6
+ map: import("magic-string").SourceMap;
7
+ } | null | undefined>;
8
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export type { AsChildTypes } from "../vite";
@@ -0,0 +1,17 @@
1
+ export declare const readFile: () => Promise<string>;
2
+ export declare const readFileSync: () => string;
3
+ export declare const existsSync: () => boolean;
4
+ export declare const statSync: () => {};
5
+ export declare const mkdir: () => Promise<void>;
6
+ export declare const readdir: () => Promise<never[]>;
7
+ export declare const writeFile: () => Promise<void>;
8
+ declare const _default: {
9
+ readFile: () => Promise<string>;
10
+ readFileSync: () => string;
11
+ existsSync: () => boolean;
12
+ statSync: () => {};
13
+ mkdir: () => Promise<void>;
14
+ readdir: () => Promise<never[]>;
15
+ writeFile: () => Promise<void>;
16
+ };
17
+ export default _default;
@@ -1,3 +1,4 @@
1
- export type { AsChildPluginOptions, AsChildTypes, IconsPluginOptions, PacksMap } from "../rolldown";
2
- export { asChild, icons } from "../rolldown";
1
+ export type { AsChildPluginOptions, AsChildTypes, IconsPluginOptions, InlineAssetPluginOptions, PacksMap } from "../rolldown/index";
2
+ export type { Plugin as VitePlugin, PluginOption as VitePluginOption } from "vite";
3
+ export { asChild, icons, inlineAsset } from "../rolldown/index";
3
4
  export { minifyContentPlugin } from "./minify-content";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qds.dev/tools",
3
- "version": "0.7.5",
3
+ "version": "0.8.5",
4
4
  "private": false,
5
5
  "description": "Tools and utilities for Qwik Design System",
6
6
  "type": "module",
@@ -28,6 +28,10 @@
28
28
  "./rolldown": {
29
29
  "import": "./lib/rolldown/index.qwik.mjs",
30
30
  "types": "./lib-types/tools/rolldown/index.d.ts"
31
+ },
32
+ "./playground": {
33
+ "import": "./lib/playground/index.qwik.mjs",
34
+ "types": "./lib-types/tools/playground/index.d.ts"
31
35
  }
32
36
  },
33
37
  "devDependencies": {
@@ -35,7 +39,7 @@
35
39
  "magic-string": "^0.30.17",
36
40
  "rolldown": "1.0.0-beta.45",
37
41
  "typescript": "5.4.5",
38
- "vite": "^7.0.6"
42
+ "vite": "^7.3.1"
39
43
  },
40
44
  "dependencies": {
41
45
  "@iconify/json": "^2.2.382",