@driftime/sanity-plugin-icon 0.3.0 → 0.4.1

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 (55) hide show
  1. package/README.md +253 -61
  2. package/dist/adapters-Bx_MyEX_.js +633 -0
  3. package/dist/adapters-Bx_MyEX_.js.map +1 -0
  4. package/dist/drawing-ByrcBbWB.js +50 -0
  5. package/dist/drawing-ByrcBbWB.js.map +1 -0
  6. package/dist/index.d.ts +84 -32
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +545 -323
  9. package/dist/index.js.map +1 -1
  10. package/dist/names.d.ts +8 -0
  11. package/dist/names.d.ts.map +1 -0
  12. package/dist/names.js +0 -0
  13. package/dist/next-loader.d.ts +64 -0
  14. package/dist/next-loader.d.ts.map +1 -0
  15. package/dist/next-loader.js +103 -0
  16. package/dist/next-loader.js.map +1 -0
  17. package/dist/next.d.ts +43 -0
  18. package/dist/next.d.ts.map +1 -0
  19. package/dist/next.js +52 -0
  20. package/dist/next.js.map +1 -0
  21. package/dist/nodes-DAzj56Xn.js +139 -0
  22. package/dist/nodes-DAzj56Xn.js.map +1 -0
  23. package/dist/read-worker.d.ts +1 -0
  24. package/dist/read-worker.js +23 -0
  25. package/dist/read-worker.js.map +1 -0
  26. package/dist/registry-B0Dxiwhh.js +68 -0
  27. package/dist/registry-B0Dxiwhh.js.map +1 -0
  28. package/dist/registry-BEEpqK3z.js +13 -0
  29. package/dist/registry-BEEpqK3z.js.map +1 -0
  30. package/dist/render.d.ts +4 -5
  31. package/dist/render.d.ts.map +1 -1
  32. package/dist/render.js +5 -5
  33. package/dist/render.js.map +1 -1
  34. package/dist/sets-D5_YGFll.js +258 -0
  35. package/dist/sets-D5_YGFll.js.map +1 -0
  36. package/dist/sets-kepuObH8.js +90 -0
  37. package/dist/sets-kepuObH8.js.map +1 -0
  38. package/dist/sets.d.ts +50 -0
  39. package/dist/sets.d.ts.map +1 -0
  40. package/dist/sets.js +14 -0
  41. package/dist/sets.js.map +1 -0
  42. package/dist/types-qlHEYDoN.d.ts +20 -0
  43. package/dist/types-qlHEYDoN.d.ts.map +1 -0
  44. package/dist/utils-COPacfAq.js +48 -0
  45. package/dist/utils-COPacfAq.js.map +1 -0
  46. package/dist/vite-ifICG8y9.d.ts +98 -0
  47. package/dist/vite-ifICG8y9.d.ts.map +1 -0
  48. package/dist/vite.d.ts +2 -0
  49. package/dist/vite.js +88 -0
  50. package/dist/vite.js.map +1 -0
  51. package/package.json +42 -5
  52. package/dist/drawing-BThiR2bN.js +0 -129
  53. package/dist/drawing-BThiR2bN.js.map +0 -1
  54. package/dist/types-_D2jGm25.d.ts +0 -16
  55. package/dist/types-_D2jGm25.d.ts.map +0 -1
@@ -0,0 +1,103 @@
1
+ import { n as logger } from "./sets-kepuObH8.js";
2
+ import { r as isRecord } from "./utils-COPacfAq.js";
3
+ import { n as getSetsFolder, t as createRegistryModule } from "./registry-B0Dxiwhh.js";
4
+ import { a as writeIconNames, i as loadIconSet, n as detectLibraries, r as listRegistryDependencies, t as describeReport } from "./sets-D5_YGFll.js";
5
+ import { i as listPluginFiles, s as readPluginBuild } from "./adapters-Bx_MyEX_.js";
6
+ import path from "node:path";
7
+ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
8
+ import { randomUUID } from "node:crypto";
9
+ /**
10
+ * Converts every installed library, writes each set to a file the bundler can split into its own chunk, and returns
11
+ * the registry that replaces the placeholder.
12
+ *
13
+ * @param resourcePath - Path of the placeholder being replaced.
14
+ * @param options - The loader's options.
15
+ * @returns The registry's code, and the files and folders it was generated from.
16
+ */
17
+ async function generateRegistryOnce(resourcePath, options) {
18
+ let root = process.cwd(), custom = isRecord(options) && isRecord(options.custom) ? options.custom : {}, folders = Object.fromEntries(Object.entries(custom).flatMap(([name, folder]) => typeof folder == "string" ? [[name, folder]] : [])), cacheDir = path.join(root, "node_modules", ".cache"), setsDir = getSetsFolder(root);
19
+ await mkdir(setsDir, { recursive: !0 });
20
+ let libraries = await detectLibraries(root, folders), files = /* @__PURE__ */ new Map(), names = /* @__PURE__ */ new Map(), converted = await Promise.all(libraries.flatMap((library) => library.styles.map(async ({ style }) => {
21
+ let { adapter } = library, { set, report } = await loadIconSet(library, style, {
22
+ root,
23
+ cacheDir
24
+ }), file = path.join(setsDir, `${adapter.library}-${style}.json`), temporary = `${file}.${randomUUID()}.tmp`;
25
+ return await writeFile(temporary, JSON.stringify(set)), await rename(temporary, file), logger.info(describeReport(adapter.label, style, report)), {
26
+ library: adapter.library,
27
+ style,
28
+ set,
29
+ file
30
+ };
31
+ })));
32
+ for (let { library, style, set, file } of converted) {
33
+ let libraryNames = names.get(library) ?? /* @__PURE__ */ new Set();
34
+ for (let icon of set.icons) libraryNames.add(icon.name);
35
+ names.set(library, libraryNames), files.set(`${library}/${style}`, file);
36
+ }
37
+ await writeIconNames(new Map([...names].filter(([, libraryNames]) => libraryNames.size > 0)));
38
+ let code = createRegistryModule(libraries, (key) => {
39
+ let file = files.get(key) ?? "", relative = path.relative(path.dirname(resourcePath), file).replaceAll("\\", "/");
40
+ return relative.startsWith(".") ? relative : `./${relative}`;
41
+ }), dependencies = listRegistryDependencies(root, libraries);
42
+ return {
43
+ code,
44
+ files: [...dependencies.files, ...await listPluginFiles()],
45
+ folders: dependencies.folders
46
+ };
47
+ }
48
+ /**
49
+ * Reads the project's `package.json` as text.
50
+ *
51
+ * @returns The contents, or an empty string when there's no file.
52
+ */
53
+ async function readManifest() {
54
+ try {
55
+ return await readFile(path.join(process.cwd(), "package.json"), "utf8");
56
+ } catch {
57
+ return "";
58
+ }
59
+ }
60
+ /**
61
+ * Generates the registry, running again when the project's `package.json` changes while it runs, so a package
62
+ * installed during a run isn't missed.
63
+ *
64
+ * @param resourcePath - Path of the placeholder being replaced.
65
+ * @param options - The loader's options.
66
+ * @param attempts - Runs allowed, including this one.
67
+ * @returns The registry's code, and the files and folders it was generated from.
68
+ * @public
69
+ */
70
+ async function generateRegistry(resourcePath, options, attempts = 3) {
71
+ let before = await readManifest(), result = await generateRegistryOnce(resourcePath, options);
72
+ return before === await readManifest() || attempts <= 1 ? result : generateRegistry(resourcePath, options, attempts - 1);
73
+ }
74
+ /**
75
+ * Checks whether an imported module is a fresh copy of this one.
76
+ *
77
+ * @param value - The imported module.
78
+ * @returns True if the module is this one.
79
+ */
80
+ function isLoaderModule(value) {
81
+ return isRecord(value) && typeof value.generateRegistry == "function";
82
+ }
83
+ /**
84
+ * Webpack and Turbopack loader that replaces the placeholder registry with the project's converted icon sets. The
85
+ * bundler keeps this module loaded, so it imports a fresh copy of itself, versioned by the plugin's code, and runs that
86
+ * copy's build step, so updating the plugin takes effect without restarting the bundler.
87
+ *
88
+ * @param this - The loader context.
89
+ * @returns The registry's code.
90
+ * @throws When the plugin's build step can't be loaded.
91
+ * @public
92
+ */
93
+ async function iconSetsLoader() {
94
+ let fresh = await import(`${import.meta.url}?version=${await readPluginBuild()}`);
95
+ if (!isLoaderModule(fresh)) throw Error(logger.format("The build step couldn't be loaded."));
96
+ let { code, files, folders } = await fresh.generateRegistry(this.resourcePath, this.getOptions());
97
+ for (let file of files) this.addDependency?.(file);
98
+ for (let folder of folders) this.addContextDependency?.(folder);
99
+ return code;
100
+ }
101
+ export { iconSetsLoader as default, generateRegistry };
102
+
103
+ //# sourceMappingURL=next-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next-loader.js","names":["randomUUID","mkdir","readFile","rename","writeFile","path","isRecord","writeIconNames","listPluginFiles","createRegistryModule","getSetsFolder","describeReport","detectLibraries","listRegistryDependencies","loadIconSet","logger","LoaderContext","resourcePath","getOptions","addDependency","file","addContextDependency","folder","generateRegistryOnce","options","root","process","cwd","custom","folders","Object","fromEntries","entries","flatMap","name","cacheDir","join","setsDir","recursive","libraries","files","Map","names","Set","converted","Promise","all","library","styles","map","style","adapter","set","report","temporary","JSON","stringify","info","label","libraryNames","get","icon","icons","add","filter","size","code","key","relative","dirname","replaceAll","startsWith","dependencies","readManifest","generateRegistry","attempts","ReturnType","before","result","after","isRecord","LoaderContext","generateRegistry","readPluginBuild","logger","LoaderModule","isLoaderModule","value","iconSetsLoader","this","fresh","import","meta","url","Error","format","code","files","folders","resourcePath","getOptions","file","addDependency","folder","addContextDependency","\"custom\"","\"generateRegistry\""],"sources":["../src/build/loader.ts","../src/next-loader.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, rename, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { isRecord } from \"@repo/lib/utils\";\n\nimport { writeIconNames } from \"@/build/names\";\nimport { listPluginFiles } from \"@/build/packages\";\nimport { createRegistryModule, getSetsFolder } from \"@/build/registry\";\nimport { describeReport, detectLibraries, listRegistryDependencies, loadIconSet } from \"@/build/sets\";\nimport { logger } from \"@/config/defaults\";\n\n/**\n * The parts of a webpack or Turbopack loader's context the build step uses.\n *\n * @public\n */\nexport interface LoaderContext {\n /** Path of the module being loaded. */\n resourcePath: string;\n /**\n * Reads the loader's options.\n *\n * @returns The options.\n */\n getOptions: () => unknown;\n /**\n * Tells the bundler to run the loader again when a file changes.\n *\n * @param file - The file.\n */\n addDependency?: (file: string) => void;\n /**\n * Tells the bundler to run the loader again when anything in a folder changes.\n *\n * @param folder - The folder.\n */\n addContextDependency?: (folder: string) => void;\n}\n\n/**\n * Converts every installed library, writes each set to a file the bundler can split into its own chunk, and returns\n * the registry that replaces the placeholder.\n *\n * @param resourcePath - Path of the placeholder being replaced.\n * @param options - The loader's options.\n * @returns The registry's code, and the files and folders it was generated from.\n */\nasync function generateRegistryOnce(resourcePath: string, options: unknown) {\n const root = process.cwd();\n const custom = isRecord(options) && isRecord(options[\"custom\"]) ? options[\"custom\"] : {};\n const folders = Object.fromEntries(\n Object.entries(custom).flatMap(([name, folder]) => (typeof folder === \"string\" ? [[name, folder]] : [])),\n );\n\n const cacheDir = path.join(root, \"node_modules\", \".cache\");\n const setsDir = getSetsFolder(root);\n await mkdir(setsDir, { recursive: true });\n\n const libraries = await detectLibraries(root, folders);\n const files = new Map<string, string>();\n const names = new Map<string, Set<string>>();\n\n const converted = await Promise.all(\n libraries.flatMap((library) =>\n library.styles.map(async ({ style }) => {\n const { adapter } = library;\n const { set, report } = await loadIconSet(library, style, { root, cacheDir });\n const file = path.join(setsDir, `${adapter.library}-${style}.json`);\n const temporary = `${file}.${randomUUID()}.tmp`;\n\n // The browser and server builds convert at once, even in one process, so each set is swapped in whole.\n await writeFile(temporary, JSON.stringify(set));\n await rename(temporary, file);\n logger.info(describeReport(adapter.label, style, report));\n\n return { library: adapter.library, style, set, file };\n }),\n ),\n );\n\n for (const { library, style, set, file } of converted) {\n const libraryNames = names.get(library) ?? new Set<string>();\n\n for (const icon of set.icons) libraryNames.add(icon.name);\n names.set(library, libraryNames);\n files.set(`${library}/${style}`, file);\n }\n\n await writeIconNames(new Map([...names].filter(([, libraryNames]) => libraryNames.size > 0)));\n\n const code = createRegistryModule(libraries, (key) => {\n const file = files.get(key) ?? \"\";\n const relative = path.relative(path.dirname(resourcePath), file).replaceAll(\"\\\\\", \"/\");\n\n return relative.startsWith(\".\") ? relative : `./${relative}`;\n });\n\n const dependencies = listRegistryDependencies(root, libraries);\n\n // The plugin's own files are included, so updating it runs the loader again even when `package.json` doesn't change.\n return { code, files: [...dependencies.files, ...(await listPluginFiles())], folders: dependencies.folders };\n}\n\n/**\n * Reads the project's `package.json` as text.\n *\n * @returns The contents, or an empty string when there's no file.\n */\nasync function readManifest() {\n try {\n return await readFile(path.join(process.cwd(), \"package.json\"), \"utf8\");\n } catch {\n return \"\";\n }\n}\n\n/**\n * Generates the registry, running again when the project's `package.json` changes while it runs, so a package\n * installed during a run isn't missed.\n *\n * @param resourcePath - Path of the placeholder being replaced.\n * @param options - The loader's options.\n * @param attempts - Runs allowed, including this one.\n * @returns The registry's code, and the files and folders it was generated from.\n * @public\n */\nexport async function generateRegistry(\n resourcePath: string,\n options: unknown,\n attempts = 3,\n): ReturnType<typeof generateRegistryOnce> {\n const before = await readManifest();\n const result = await generateRegistryOnce(resourcePath, options);\n const after = await readManifest();\n\n return before === after || attempts <= 1 ? result : generateRegistry(resourcePath, options, attempts - 1);\n}\n","import { isRecord } from \"@repo/lib/utils\";\n\nimport type { LoaderContext, generateRegistry } from \"@/build/loader\";\nimport { readPluginBuild } from \"@/build/packages\";\nimport { logger } from \"@/config/defaults\";\n\n/** This module as the loader imports it afresh on every run. */\ninterface LoaderModule {\n /** Generates the registry. */\n generateRegistry: typeof generateRegistry;\n}\n\n/**\n * Checks whether an imported module is a fresh copy of this one.\n *\n * @param value - The imported module.\n * @returns True if the module is this one.\n */\nfunction isLoaderModule(value: unknown): value is LoaderModule {\n return isRecord(value) && typeof value[\"generateRegistry\"] === \"function\";\n}\n\n/**\n * Webpack and Turbopack loader that replaces the placeholder registry with the project's converted icon sets. The\n * bundler keeps this module loaded, so it imports a fresh copy of itself, versioned by the plugin's code, and runs that\n * copy's build step, so updating the plugin takes effect without restarting the bundler.\n *\n * @param this - The loader context.\n * @returns The registry's code.\n * @throws When the plugin's build step can't be loaded.\n * @public\n */\nasync function iconSetsLoader(this: LoaderContext) {\n const fresh: unknown = await import(`${import.meta.url}?version=${await readPluginBuild()}`);\n if (!isLoaderModule(fresh)) throw new Error(logger.format(\"The build step couldn't be loaded.\"));\n\n const { code, files, folders } = await fresh.generateRegistry(this.resourcePath, this.getOptions());\n\n for (const file of files) this.addDependency?.(file);\n for (const folder of folders) this.addContextDependency?.(folder);\n\n return code;\n}\n\nexport default iconSetsLoader;\nexport { generateRegistry } from \"@/build/loader\";\n"],"mappings":"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"}
package/dist/next.d.ts ADDED
@@ -0,0 +1,43 @@
1
+ import { t as SanityIconBuildOptions } from "./vite-ifICG8y9.js";
2
+ /**
3
+ * The parts of a webpack configuration the build step extends.
4
+ *
5
+ * @public
6
+ */
7
+ interface SanityIconWebpackConfig {
8
+ /** Module settings, whose rules the build step adds to. */
9
+ module?: {
10
+ rules?: unknown[];
11
+ };
12
+ }
13
+ /**
14
+ * The parts of a Next.js configuration the build step extends, so the package doesn't depend on Next.js's own types.
15
+ *
16
+ * @public
17
+ */
18
+ interface SanityIconNextConfig {
19
+ /** Turbopack settings, whose rules the build step adds to. */
20
+ turbopack?: {
21
+ rules?: Record<string, unknown>;
22
+ };
23
+ /** Customises webpack, for projects that build with it instead of Turbopack. */
24
+ webpack?: SanityIconWebpackCustomizer | null;
25
+ }
26
+ /**
27
+ * Customises webpack, as Next.js's `webpack` option does. The context is typed `never` because the build step only
28
+ * passes Next.js's own context through, so any context type a project's function declares is accepted.
29
+ *
30
+ * @public
31
+ */
32
+ type SanityIconWebpackCustomizer = (config: SanityIconWebpackConfig, context: never) => SanityIconWebpackConfig;
33
+ /**
34
+ * Adds the icon build step to a Next.js configuration, for Studios embedded in a Next.js app. It works with both
35
+ * Turbopack and webpack.
36
+ *
37
+ * @param options - Options for the build step.
38
+ * @returns A function that extends the Next.js configuration.
39
+ * @public
40
+ */
41
+ export declare function withIcons(options?: SanityIconBuildOptions): <Config extends SanityIconNextConfig>(config: Config) => Config;
42
+ export type { SanityIconNextConfig, SanityIconWebpackConfig, SanityIconWebpackCustomizer };
43
+ //# sourceMappingURL=next.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next.d.ts","names":["SanityIconBuildOptions","SanityIconWebpackConfig","SanityIconNextConfig","Record","SanityIconWebpackCustomizer","withIcons","Config"],"sources":["../src/build/next.ts"],"mappings":";;;;;;UAoBiBC;;EAEf;IAAW;;;;;;;;UAQIC;;EAEf;IAAc,QAAQC;;;EAEtB,UAAUC;;;;;;;;KASAA,+BAA+B,QAAQH,yBAAyB,mBAAmBA;;;;;;;;;wBAa/EI,UAAU,UAASL,0BAOJ,eAAeE,sBAAoB,QAAUI,WAASA"}
package/dist/next.js ADDED
@@ -0,0 +1,52 @@
1
+ import { i as registryModulePath, n as getSetsFolder, r as isRegistryModule } from "./registry-B0Dxiwhh.js";
2
+ import path from "node:path";
3
+ import { mkdirSync } from "node:fs";
4
+ import { fileURLToPath } from "node:url";
5
+ /** Path of the loader, published next to this file. */
6
+ const loaderPath = fileURLToPath(new URL("next-loader.js", import.meta.url));
7
+ /**
8
+ * Adds the icon build step to a Next.js configuration, for Studios embedded in a Next.js app. It works with both
9
+ * Turbopack and webpack.
10
+ *
11
+ * @param options - Options for the build step.
12
+ * @returns A function that extends the Next.js configuration.
13
+ * @public
14
+ */
15
+ function withIcons(options = {}) {
16
+ let loader = {
17
+ loader: loaderPath,
18
+ options: { custom: options.custom ?? {} }
19
+ }, placeholder = path.basename(path.dirname(path.dirname(registryModulePath)));
20
+ return mkdirSync(getSetsFolder(process.cwd()), { recursive: !0 }), function extendConfig(config) {
21
+ let { turbopack, webpack } = config;
22
+ return {
23
+ ...config,
24
+ turbopack: {
25
+ ...turbopack,
26
+ rules: {
27
+ ...turbopack?.rules,
28
+ [`**/${placeholder}/dist/sets.js`]: {
29
+ loaders: [loader],
30
+ as: "*.js"
31
+ }
32
+ }
33
+ },
34
+ webpack(webpackConfig, context) {
35
+ let resolved = webpack?.(webpackConfig, context) ?? webpackConfig, rule = {
36
+ test: isRegistryModule,
37
+ use: [loader]
38
+ };
39
+ return {
40
+ ...resolved,
41
+ module: {
42
+ ...resolved.module,
43
+ rules: [...resolved.module?.rules ?? [], rule]
44
+ }
45
+ };
46
+ }
47
+ };
48
+ };
49
+ }
50
+ export { withIcons };
51
+
52
+ //# sourceMappingURL=next.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next.js","names":["mkdirSync","path","fileURLToPath","getSetsFolder","isRegistryModule","registryModulePath","SanityIconBuildOptions","WebpackRule","test","resource","use","loader","options","custom","Record","SanityIconWebpackConfig","module","rules","SanityIconNextConfig","turbopack","webpack","SanityIconWebpackCustomizer","config","context","loaderPath","URL","import","meta","url","withIcons","placeholder","basename","dirname","process","cwd","recursive","extendConfig","Config","loaders","as","webpackConfig","resolved","rule"],"sources":["../src/build/next.ts"],"sourcesContent":["import { mkdirSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { getSetsFolder, isRegistryModule, registryModulePath } from \"@/build/registry\";\nimport type { SanityIconBuildOptions } from \"@/build/vite\";\n\n/** A webpack rule, limited to what the build step adds. */\ninterface WebpackRule {\n /** Matches the placeholder registry. */\n test: (resource: string) => boolean;\n /** The loader that replaces it, with the build step's options. */\n use: { loader: string; options: { custom: Record<string, string> } }[];\n}\n\n/**\n * The parts of a webpack configuration the build step extends.\n *\n * @public\n */\nexport interface SanityIconWebpackConfig {\n /** Module settings, whose rules the build step adds to. */\n module?: { rules?: unknown[] };\n}\n\n/**\n * The parts of a Next.js configuration the build step extends, so the package doesn't depend on Next.js's own types.\n *\n * @public\n */\nexport interface SanityIconNextConfig {\n /** Turbopack settings, whose rules the build step adds to. */\n turbopack?: { rules?: Record<string, unknown> };\n /** Customises webpack, for projects that build with it instead of Turbopack. */\n webpack?: SanityIconWebpackCustomizer | null;\n}\n\n/**\n * Customises webpack, as Next.js's `webpack` option does. The context is typed `never` because the build step only\n * passes Next.js's own context through, so any context type a project's function declares is accepted.\n *\n * @public\n */\nexport type SanityIconWebpackCustomizer = (config: SanityIconWebpackConfig, context: never) => SanityIconWebpackConfig;\n\n/** Path of the loader, published next to this file. */\nconst loaderPath = fileURLToPath(new URL(\"next-loader.js\", import.meta.url));\n\n/**\n * Adds the icon build step to a Next.js configuration, for Studios embedded in a Next.js app. It works with both\n * Turbopack and webpack.\n *\n * @param options - Options for the build step.\n * @returns A function that extends the Next.js configuration.\n * @public\n */\nexport function withIcons(options: SanityIconBuildOptions = {}) {\n const loader = { loader: loaderPath, options: { custom: options.custom ?? {} } };\n const placeholder = path.basename(path.dirname(path.dirname(registryModulePath)));\n\n // Turbopack never finds files in a folder that was missing when the build started, so it's made before then.\n mkdirSync(getSetsFolder(process.cwd()), { recursive: true });\n\n return function extendConfig<Config extends SanityIconNextConfig>(config: Config): Config {\n const { turbopack, webpack } = config;\n\n return {\n ...config,\n turbopack: {\n ...turbopack,\n rules: { ...turbopack?.rules, [`**/${placeholder}/dist/sets.js`]: { loaders: [loader], as: \"*.js\" } },\n },\n webpack(webpackConfig: SanityIconWebpackConfig, context: never) {\n const resolved = webpack?.(webpackConfig, context) ?? webpackConfig;\n const rule: WebpackRule = { test: isRegistryModule, use: [loader] };\n\n return { ...resolved, module: { ...resolved.module, rules: [...(resolved.module?.rules ?? []), rule] } };\n },\n };\n };\n}\n"],"mappings":";;;;;AA8CA,MAAMwB,aAAatB,cAAc,IAAIuB,IAAI,kBAAkBC,YAAYE,GAAG,CAAC;;;;;;;;;AAU3E,SAAgBC,UAAUjB,UAAkC,CAAC,GAAG;CAC9D,IAAMD,SAAS;EAAEA,QAAQa;EAAYZ,SAAS,EAAEC,QAAQD,QAAQC,UAAU,CAAC,EAAE;CAAE,GACzEiB,cAAc7B,KAAK8B,SAAS9B,KAAK+B,QAAQ/B,KAAK+B,QAAQ3B,kBAAkB,CAAC,CAAC;CAKhF,OAFAL,UAAUG,cAAc8B,QAAQC,IAAI,CAAC,GAAG,EAAEC,WAAW,GAAK,CAAC,GAEpD,SAASC,aAAkDd,QAAwB;EACxF,IAAM,EAAEH,WAAWC,YAAYE;EAE/B,OAAO;GACL,GAAGA;GACHH,WAAW;IACT,GAAGA;IACHF,OAAO;KAAE,GAAGE,WAAWF;MAAQ,MAAMa,YAAW,iBAAkB;MAAEQ,SAAS,CAAC3B,MAAM;MAAG4B,IAAI;KAAO;IAAE;GACtG;GACAnB,QAAQoB,eAAwCjB,SAAgB;IAC9D,IAAMkB,WAAWrB,UAAUoB,eAAejB,OAAO,KAAKiB,eAChDE,OAAoB;KAAElC,MAAMJ;KAAkBM,KAAK,CAACC,MAAM;IAAE;IAElE,OAAO;KAAE,GAAG8B;KAAUzB,QAAQ;MAAE,GAAGyB,SAASzB;MAAQC,OAAO,CAAC,GAAIwB,SAASzB,QAAQC,SAAS,CAAA,GAAKyB,IAAI;KAAE;IAAE;GACzG;EACF;CACF;AACF"}
@@ -0,0 +1,139 @@
1
+ import { n as isDefined, r as isRecord } from "./utils-COPacfAq.js";
2
+ import { stegaClean } from "@sanity/client/stega";
3
+ /**
4
+ * SVG elements a drawing may contain: everything that draws, paints, clips, masks, or filters. Anything that runs
5
+ * code, embeds other content, links away, loads a file, animates, or styles the page around it is left out.
6
+ */
7
+ const iconElements = /* @__PURE__ */ new Set(/* @__PURE__ */ "circle.clipPath.defs.ellipse.feBlend.feColorMatrix.feComponentTransfer.feComposite.feConvolveMatrix.feDiffuseLighting.feDisplacementMap.feDistantLight.feDropShadow.feFlood.feFuncA.feFuncB.feFuncG.feFuncR.feGaussianBlur.feMerge.feMergeNode.feMorphology.feOffset.fePointLight.feSpecularLighting.feSpotLight.feTile.feTurbulence.filter.g.line.linearGradient.marker.mask.path.pattern.polygon.polyline.radialGradient.rect.stop.symbol.text.textPath.tspan.use".split(".")), linkAttributes = /* @__PURE__ */ new Set(["href", "xlinkHref"]), urlPattern = /url\((?<reference>[^)]*)\)/gu, iconSvgAttributes = {
8
+ xmlns: "http://www.w3.org/2000/svg",
9
+ width: 24,
10
+ height: 24
11
+ };
12
+ /**
13
+ * Checks whether a value is a set of attributes, each with a text value.
14
+ *
15
+ * @param value - The value to check.
16
+ * @returns True if the value is a set of attributes.
17
+ */
18
+ function isAttributes(value) {
19
+ return isRecord(value) && Object.values(value).every((attribute) => typeof attribute == "string");
20
+ }
21
+ /**
22
+ * Checks whether a value is an element in a drawing, with text attributes and valid children.
23
+ *
24
+ * @param value - The value to check.
25
+ * @returns True if the value is an element.
26
+ */
27
+ function isIconElement(value) {
28
+ if (!Array.isArray(value) || value.length < 2 || value.length > 3) return !1;
29
+ let [name, attributes, children] = value;
30
+ return typeof name != "string" || !isAttributes(attributes) ? !1 : !isDefined(children) || Array.isArray(children) && children.every((child) => typeof child == "string" || isIconElement(child));
31
+ }
32
+ /**
33
+ * Finds why an element's attributes can't be drawn safely.
34
+ *
35
+ * @param attributes - The attributes.
36
+ * @returns The problem, or undefined when the attributes are safe.
37
+ */
38
+ function findAttributeProblem(attributes) {
39
+ for (let [name, value] of Object.entries(attributes)) {
40
+ if (/^on/iu.test(name)) return `has an event handler (\`${name}\`)`;
41
+ if (!/^[a-zA-Z][a-zA-Z0-9]*$/u.test(name)) return `has an unknown attribute (\`${name}\`)`;
42
+ if (/javascript:/iu.test(value)) return "runs a script";
43
+ if (linkAttributes.has(name) && !value.startsWith("#")) return "links outside the icon";
44
+ if (value.includes("url(")) {
45
+ let references = [...value.matchAll(urlPattern)];
46
+ if (references.some(({ groups }) => !(groups?.reference?.trim().replace(/^["']/u, "").startsWith("#") ?? !1)) || value.split("url(").length - 1 !== references.length) return "refers to something outside the icon";
47
+ }
48
+ }
49
+ }
50
+ /**
51
+ * Finds why part of a drawing can't be drawn safely.
52
+ *
53
+ * @param node - The elements to check.
54
+ * @returns The problem, or undefined when every element is safe.
55
+ */
56
+ function findNodeProblem(node) {
57
+ for (let child of node) {
58
+ if (typeof child == "string") continue;
59
+ let [name, attributes, children] = child;
60
+ if (!iconElements.has(name)) return `uses the \`<${name}>\` element`;
61
+ let problem = findAttributeProblem(attributes) ?? (isDefined(children) ? findNodeProblem(children) : void 0);
62
+ if (isDefined(problem)) return problem;
63
+ }
64
+ }
65
+ /**
66
+ * Finds why a drawing can't be drawn safely: an element or attribute that could run code, load something, or reach
67
+ * outside the icon. The same check guards the build step's output and every stored value before it's drawn.
68
+ *
69
+ * @param drawing - The drawing to check.
70
+ * @returns The problem, or undefined when the drawing is safe.
71
+ */
72
+ function findDrawingProblem({ root, node }) {
73
+ return isDefined(node) ? findAttributeProblem(root) ?? findNodeProblem(node) : "draws nothing";
74
+ }
75
+ /**
76
+ * Reads a drawing's elements from an already parsed value, such as a converted set.
77
+ *
78
+ * @param value - The value to read.
79
+ * @returns The elements, or undefined when the value isn't a list of them.
80
+ */
81
+ function parseIconNode(value) {
82
+ return Array.isArray(value) && value.every((element) => isIconElement(element)) ? value : void 0;
83
+ }
84
+ /**
85
+ * Reads an SVG root from an already parsed value.
86
+ *
87
+ * @param value - The value to read.
88
+ * @returns The root, or undefined when the value isn't one.
89
+ */
90
+ function parseIconRoot(value) {
91
+ return isAttributes(value) ? value : void 0;
92
+ }
93
+ /**
94
+ * Parses stored JSON.
95
+ *
96
+ * @param value - The stored text.
97
+ * @returns The parsed value, or undefined when the text isn't JSON.
98
+ */
99
+ function parseJson(value) {
100
+ try {
101
+ return JSON.parse(value);
102
+ } catch {
103
+ return;
104
+ }
105
+ }
106
+ /**
107
+ * Reads a drawing back from its stored form, removing stega characters first.
108
+ *
109
+ * @param value - The stored drawing.
110
+ * @returns The drawing, or undefined when nothing readable and safe was stored.
111
+ */
112
+ function resolveIconDrawing(value) {
113
+ let cleaned = stegaClean(value);
114
+ if (!isDefined(cleaned)) return;
115
+ let stored = parseJson(cleaned);
116
+ if (!isRecord(stored)) return;
117
+ let root = parseIconRoot(stored.root), node = parseIconNode(stored.node);
118
+ if (!isDefined(root) || !isDefined(node)) return;
119
+ let drawing = {
120
+ root,
121
+ node
122
+ };
123
+ return isDefined(findDrawingProblem(drawing)) ? void 0 : drawing;
124
+ }
125
+ /**
126
+ * Converts a drawing to its stored form.
127
+ *
128
+ * @param drawing - The drawing.
129
+ * @returns The drawing as a string.
130
+ */
131
+ function serializeIconDrawing(drawing) {
132
+ return JSON.stringify({
133
+ root: drawing.root,
134
+ node: drawing.node
135
+ });
136
+ }
137
+ export { resolveIconDrawing as a, parseIconRoot as i, iconSvgAttributes as n, serializeIconDrawing as o, parseIconNode as r, findDrawingProblem as t };
138
+
139
+ //# sourceMappingURL=nodes-DAzj56Xn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodes-DAzj56Xn.js","names":["isDefined","isRecord","stegaClean","IconElement","element","attributes","Record","children","IconNode","IconRoot","IconDrawing","root","node","iconElements","ReadonlySet","Set","linkAttributes","urlPattern","iconSvgAttributes","xmlns","width","height","const","isAttributes","value","Object","values","every","attribute","isIconElement","Array","isArray","length","parts","name","child","findAttributeProblem","entries","test","has","startsWith","includes","references","matchAll","outside","some","groups","trim","replace","split","undefined","findNodeProblem","problem","findDrawingProblem","parseIconNode","parseIconRoot","parseJson","JSON","parse","resolveIconDrawing","cleaned","stored","drawing","serializeIconDrawing","stringify","parts","\"reference\"","\"root\"","\"node\""],"sources":["../src/lib/nodes.ts"],"sourcesContent":["import { isDefined, isRecord } from \"@repo/lib/utils\";\nimport { stegaClean } from \"@sanity/client/stega\";\n\n/** One element in a drawing: its name, its attributes, and any children, which may include text. */\nexport type IconElement = [element: string, attributes: Record<string, string>, children?: (IconElement | string)[]];\n\n/** An icon's drawing, stored as a tree of elements rather than a component. */\nexport type IconNode = IconElement[];\n\n/** Attributes for the SVG around a drawing's elements. */\nexport type IconRoot = Record<string, string>;\n\n/** An icon's elements together with the SVG attributes they're drawn inside. */\nexport interface IconDrawing {\n /** Attributes for the SVG around the elements. */\n root: IconRoot;\n /** Elements the icon is drawn from. */\n node: IconNode;\n}\n\n/**\n * SVG elements a drawing may contain: everything that draws, paints, clips, masks, or filters. Anything that runs\n * code, embeds other content, links away, loads a file, animates, or styles the page around it is left out.\n */\nconst iconElements: ReadonlySet<string> = new Set([\n \"circle\",\n \"clipPath\",\n \"defs\",\n \"ellipse\",\n \"feBlend\",\n \"feColorMatrix\",\n \"feComponentTransfer\",\n \"feComposite\",\n \"feConvolveMatrix\",\n \"feDiffuseLighting\",\n \"feDisplacementMap\",\n \"feDistantLight\",\n \"feDropShadow\",\n \"feFlood\",\n \"feFuncA\",\n \"feFuncB\",\n \"feFuncG\",\n \"feFuncR\",\n \"feGaussianBlur\",\n \"feMerge\",\n \"feMergeNode\",\n \"feMorphology\",\n \"feOffset\",\n \"fePointLight\",\n \"feSpecularLighting\",\n \"feSpotLight\",\n \"feTile\",\n \"feTurbulence\",\n \"filter\",\n \"g\",\n \"line\",\n \"linearGradient\",\n \"marker\",\n \"mask\",\n \"path\",\n \"pattern\",\n \"polygon\",\n \"polyline\",\n \"radialGradient\",\n \"rect\",\n \"stop\",\n \"symbol\",\n \"text\",\n \"textPath\",\n \"tspan\",\n \"use\",\n]);\n\n/** Attributes that point at another element by URL, which must point inside the drawing. */\nconst linkAttributes = new Set([\"href\", \"xlinkHref\"]);\n\n/** A reference to another element in an attribute value, such as `url(#fade)`. */\nconst urlPattern = /url\\((?<reference>[^)]*)\\)/gu;\n\n/** Attributes every drawing's SVG carries, whichever library it came from. */\nexport const iconSvgAttributes = { xmlns: \"http://www.w3.org/2000/svg\", width: 24, height: 24 } as const;\n\n/**\n * Checks whether a value is a set of attributes, each with a text value.\n *\n * @param value - The value to check.\n * @returns True if the value is a set of attributes.\n */\nfunction isAttributes(value: unknown): value is Record<string, string> {\n return isRecord(value) && Object.values(value).every((attribute) => typeof attribute === \"string\");\n}\n\n/**\n * Checks whether a value is an element in a drawing, with text attributes and valid children.\n *\n * @param value - The value to check.\n * @returns True if the value is an element.\n */\nfunction isIconElement(value: unknown): value is IconElement {\n if (!Array.isArray(value) || value.length < 2 || value.length > 3) return false;\n\n const parts: unknown[] = value;\n const [name, attributes, children] = parts;\n if (typeof name !== \"string\" || !isAttributes(attributes)) return false;\n\n return (\n !isDefined(children) ||\n (Array.isArray(children) && children.every((child) => typeof child === \"string\" || isIconElement(child)))\n );\n}\n\n/**\n * Finds why an element's attributes can't be drawn safely.\n *\n * @param attributes - The attributes.\n * @returns The problem, or undefined when the attributes are safe.\n */\nfunction findAttributeProblem(attributes: Record<string, string>) {\n for (const [name, value] of Object.entries(attributes)) {\n if (/^on/iu.test(name)) return `has an event handler (\\`${name}\\`)`;\n if (!/^[a-zA-Z][a-zA-Z0-9]*$/u.test(name)) return `has an unknown attribute (\\`${name}\\`)`;\n if (/javascript:/iu.test(value)) return \"runs a script\";\n\n if (linkAttributes.has(name) && !value.startsWith(\"#\")) return \"links outside the icon\";\n\n if (value.includes(\"url(\")) {\n const references = [...value.matchAll(urlPattern)];\n const outside = references.some(\n ({ groups }) => !(groups?.[\"reference\"]?.trim().replace(/^[\"']/u, \"\").startsWith(\"#\") ?? false),\n );\n\n if (outside || value.split(\"url(\").length - 1 !== references.length) {\n return \"refers to something outside the icon\";\n }\n }\n }\n\n return undefined;\n}\n\n/**\n * Finds why part of a drawing can't be drawn safely.\n *\n * @param node - The elements to check.\n * @returns The problem, or undefined when every element is safe.\n */\nfunction findNodeProblem(node: (IconElement | string)[]): string | undefined {\n for (const child of node) {\n if (typeof child === \"string\") continue;\n\n const [name, attributes, children] = child;\n if (!iconElements.has(name)) return `uses the \\`<${name}>\\` element`;\n\n const problem = findAttributeProblem(attributes) ?? (isDefined(children) ? findNodeProblem(children) : undefined);\n if (isDefined(problem)) return problem;\n }\n\n return undefined;\n}\n\n/**\n * Finds why a drawing can't be drawn safely: an element or attribute that could run code, load something, or reach\n * outside the icon. The same check guards the build step's output and every stored value before it's drawn.\n *\n * @param drawing - The drawing to check.\n * @returns The problem, or undefined when the drawing is safe.\n */\nexport function findDrawingProblem({ root, node }: IconDrawing) {\n if (!isDefined(node)) return \"draws nothing\";\n\n return findAttributeProblem(root) ?? findNodeProblem(node);\n}\n\n/**\n * Reads a drawing's elements from an already parsed value, such as a converted set.\n *\n * @param value - The value to read.\n * @returns The elements, or undefined when the value isn't a list of them.\n */\nexport function parseIconNode(value: unknown) {\n return Array.isArray(value) && value.every((element) => isIconElement(element)) ? value : undefined;\n}\n\n/**\n * Reads an SVG root from an already parsed value.\n *\n * @param value - The value to read.\n * @returns The root, or undefined when the value isn't one.\n */\nexport function parseIconRoot(value: unknown) {\n return isAttributes(value) ? value : undefined;\n}\n\n/**\n * Parses stored JSON.\n *\n * @param value - The stored text.\n * @returns The parsed value, or undefined when the text isn't JSON.\n */\nfunction parseJson(value: string): unknown {\n try {\n return JSON.parse(value);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Reads a drawing back from its stored form, removing stega characters first.\n *\n * @param value - The stored drawing.\n * @returns The drawing, or undefined when nothing readable and safe was stored.\n */\nexport function resolveIconDrawing(value: string | undefined): IconDrawing | undefined {\n const cleaned = stegaClean(value);\n if (!isDefined(cleaned)) return undefined;\n\n const stored = parseJson(cleaned);\n if (!isRecord(stored)) return undefined;\n\n const root = parseIconRoot(stored[\"root\"]);\n const node = parseIconNode(stored[\"node\"]);\n if (!isDefined(root) || !isDefined(node)) return undefined;\n\n const drawing = { root, node };\n\n return isDefined(findDrawingProblem(drawing)) ? undefined : drawing;\n}\n\n/**\n * Converts a drawing to its stored form.\n *\n * @param drawing - The drawing.\n * @returns The drawing as a string.\n */\nexport function serializeIconDrawing(drawing: IconDrawing) {\n return JSON.stringify({ root: drawing.root, node: drawing.node });\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,23 @@
1
+ import { n as isDefined, r as isRecord } from "./utils-COPacfAq.js";
2
+ import { n as createCustomAdapter, t as iconAdapters } from "./adapters-Bx_MyEX_.js";
3
+ import { parentPort, workerData } from "node:worker_threads";
4
+ /**
5
+ * Reads one library style in a worker thread, so every package is imported afresh, and posts the icons back.
6
+ *
7
+ * @param data - The library, style, and where to read from.
8
+ * @returns The icons as the library ships them.
9
+ */
10
+ async function readInWorker(data) {
11
+ if (!isRecord(data)) return [];
12
+ let { library, folder, style, root, directory } = data;
13
+ if (typeof library != "string" || typeof style != "string" || typeof root != "string" || typeof directory != "string") return [];
14
+ let adapter = typeof folder == "string" ? createCustomAdapter(library, folder) : iconAdapters.find((candidate) => candidate.library === library);
15
+ return isDefined(adapter) ? await adapter.read({
16
+ directory,
17
+ style,
18
+ root
19
+ }) : [];
20
+ }
21
+ parentPort?.postMessage(await readInWorker(workerData));
22
+
23
+ //# sourceMappingURL=read-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-worker.js","names":["parentPort","workerData","isDefined","isRecord","createCustomAdapter","iconAdapters","readInWorker","data","library","folder","style","root","directory","adapter","find","candidate","icons","read","postMessage"],"sources":["../src/read-worker.ts"],"sourcesContent":["import { parentPort, workerData } from \"node:worker_threads\";\n\nimport { isDefined, isRecord } from \"@repo/lib/utils\";\n\nimport { createCustomAdapter } from \"@/build/adapters/custom\";\nimport { iconAdapters } from \"@/build/adapters/index\";\n\n/**\n * Reads one library style in a worker thread, so every package is imported afresh, and posts the icons back.\n *\n * @param data - The library, style, and where to read from.\n * @returns The icons as the library ships them.\n */\nasync function readInWorker(data: unknown) {\n if (!isRecord(data)) return [];\n\n const { library, folder, style, root, directory } = data;\n if (typeof library !== \"string\" || typeof style !== \"string\") return [];\n if (typeof root !== \"string\" || typeof directory !== \"string\") return [];\n\n const adapter =\n typeof folder === \"string\"\n ? createCustomAdapter(library, folder)\n : iconAdapters.find((candidate) => candidate.library === library);\n\n if (!isDefined(adapter)) return [];\n\n const icons = await adapter.read({ directory, style, root });\n\n return icons;\n}\n\nparentPort?.postMessage(await readInWorker(workerData));\n"],"mappings":";;;;;;;;;AAaA,eAAeM,aAAaC,MAAe;CACzC,IAAI,CAACJ,SAASI,IAAI,GAAG,OAAO,CAAA;CAE5B,IAAM,EAAEC,SAASC,QAAQC,OAAOC,MAAMC,cAAcL;CAEpD,IADI,OAAOC,WAAY,YAAY,OAAOE,SAAU,YAChD,OAAOC,QAAS,YAAY,OAAOC,aAAc,UAAU,OAAO,CAAA;CAEtE,IAAMC,UACJ,OAAOJ,UAAW,WACdL,oBAAoBI,SAASC,MAAM,IACnCJ,aAAaS,MAAMC,cAAcA,UAAUP,YAAYA,OAAO;CAMpE,OAJKN,UAAUW,OAAO,IAIfG,MAFaH,QAAQI,KAAK;EAAEL;EAAWF;EAAOC;CAAK,CAAC,IAF3B,CAAA;AAKlC;AAEAX,YAAYkB,YAAY,MAAMZ,aAAaL,UAAU,CAAC"}
@@ -0,0 +1,68 @@
1
+ import { n as isDefined } from "./utils-COPacfAq.js";
2
+ import { t as getIconSetKey } from "./registry-BEEpqK3z.js";
3
+ import path from "node:path";
4
+ import { realpathSync } from "node:fs";
5
+ import { fileURLToPath } from "node:url";
6
+ /**
7
+ * Resolves symbolic links in a path, so a package linked into `node_modules` matches its real location.
8
+ *
9
+ * @param file - The path.
10
+ * @returns The real path, or the path unchanged when it doesn't exist.
11
+ */
12
+ function resolveRealPath(file) {
13
+ try {
14
+ return realpathSync(file);
15
+ } catch {
16
+ return file;
17
+ }
18
+ }
19
+ /**
20
+ * Path of the placeholder registry module the Studio imports, which the build step replaces. The build step's own
21
+ * code is published next to it, so the path is found from this file's location.
22
+ */
23
+ const registryModulePath = resolveRealPath(fileURLToPath(new URL("sets.js", import.meta.url)));
24
+ /**
25
+ * Checks whether a module the bundler is loading is the placeholder registry.
26
+ *
27
+ * @param id - The module's path, possibly followed by a query.
28
+ * @returns Whether it's the placeholder.
29
+ */
30
+ function isRegistryModule(id) {
31
+ let [file] = id.split("?");
32
+ return isDefined(file) && resolveRealPath(file) === registryModulePath;
33
+ }
34
+ /**
35
+ * Works out the folder the Next.js build step writes converted sets to, inside the project's `node_modules`.
36
+ *
37
+ * @param root - The project's folder.
38
+ * @returns The folder's path.
39
+ */
40
+ function getSetsFolder(root) {
41
+ return path.join(root, "node_modules", ".cache", "driftime-icon", "sets");
42
+ }
43
+ /**
44
+ * Writes the module that replaces the placeholder registry, with a loader for each installed library style, so each
45
+ * set is only downloaded when a picker for it opens.
46
+ *
47
+ * @param libraries - Every library the build step knows.
48
+ * @param importFor - The specifier the bundler imports a set from, given its key.
49
+ * @returns The module's code.
50
+ */
51
+ function createRegistryModule(libraries, importFor) {
52
+ let loaders = libraries.flatMap(({ adapter, styles }) => styles.map(({ style }) => {
53
+ let key = getIconSetKey(adapter.library, style);
54
+ return `${JSON.stringify(key)}: () => import(${JSON.stringify(importFor(key))})`;
55
+ })), info = Object.fromEntries(libraries.map(({ adapter, styles, listed, sitePackage }) => [adapter.library, {
56
+ label: adapter.label,
57
+ packageName: adapter.packageName ?? adapter.packageExample ?? adapter.library,
58
+ ...isDefined(adapter.packagePrefix) && { packagePrefix: adapter.packagePrefix },
59
+ styles: isDefined(styles) ? styles.map(({ style }) => style) : adapter.styles,
60
+ listed,
61
+ installed: isDefined(styles),
62
+ ...isDefined(sitePackage) && { sitePackage }
63
+ }]));
64
+ return [`const sets = {\n ${loaders.join(",\n ")}\n};`, `export const iconRegistry = { ready: true, sets, libraries: ${JSON.stringify(info)} };`].join("\n");
65
+ }
66
+ export { registryModulePath as i, getSetsFolder as n, isRegistryModule as r, createRegistryModule as t };
67
+
68
+ //# sourceMappingURL=registry-B0Dxiwhh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-B0Dxiwhh.js","names":["realpathSync","path","fileURLToPath","isDefined","DetectedLibrary","getIconSetKey","IconLibraryInfo","resolveRealPath","file","registryModulePath","URL","import","meta","url","isRegistryModule","id","split","getSetsFolder","root","join","createRegistryModule","libraries","importFor","key","loaders","flatMap","adapter","styles","map","style","library","JSON","stringify","info","Record","Object","fromEntries","listed","sitePackage","label","packageName","packageExample","packagePrefix","installed"],"sources":["../src/build/registry.ts"],"sourcesContent":["import { realpathSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { isDefined } from \"@repo/lib/utils\";\n\nimport type { DetectedLibrary } from \"@/build/sets\";\nimport { getIconSetKey } from \"@/lib/registry\";\nimport type { IconLibraryInfo } from \"@/lib/sets\";\n\n/**\n * Resolves symbolic links in a path, so a package linked into `node_modules` matches its real location.\n *\n * @param file - The path.\n * @returns The real path, or the path unchanged when it doesn't exist.\n */\nfunction resolveRealPath(file: string) {\n try {\n return realpathSync(file);\n } catch {\n return file;\n }\n}\n\n/**\n * Path of the placeholder registry module the Studio imports, which the build step replaces. The build step's own\n * code is published next to it, so the path is found from this file's location.\n */\nexport const registryModulePath = resolveRealPath(fileURLToPath(new URL(\"sets.js\", import.meta.url)));\n\n/**\n * Checks whether a module the bundler is loading is the placeholder registry.\n *\n * @param id - The module's path, possibly followed by a query.\n * @returns Whether it's the placeholder.\n */\nexport function isRegistryModule(id: string) {\n const [file] = id.split(\"?\");\n\n return isDefined(file) && resolveRealPath(file) === registryModulePath;\n}\n\n/**\n * Works out the folder the Next.js build step writes converted sets to, inside the project's `node_modules`.\n *\n * @param root - The project's folder.\n * @returns The folder's path.\n */\nexport function getSetsFolder(root: string) {\n return path.join(root, \"node_modules\", \".cache\", \"driftime-icon\", \"sets\");\n}\n\n/**\n * Writes the module that replaces the placeholder registry, with a loader for each installed library style, so each\n * set is only downloaded when a picker for it opens.\n *\n * @param libraries - Every library the build step knows.\n * @param importFor - The specifier the bundler imports a set from, given its key.\n * @returns The module's code.\n */\nexport function createRegistryModule(libraries: DetectedLibrary[], importFor: (key: string) => string) {\n const loaders = libraries.flatMap(({ adapter, styles }) =>\n styles.map(({ style }) => {\n const key = getIconSetKey(adapter.library, style);\n\n return `${JSON.stringify(key)}: () => import(${JSON.stringify(importFor(key))})`;\n }),\n );\n\n const info: Record<string, IconLibraryInfo> = Object.fromEntries(\n libraries.map(({ adapter, styles, listed, sitePackage }) => [\n adapter.library,\n {\n label: adapter.label,\n packageName: adapter.packageName ?? adapter.packageExample ?? adapter.library,\n ...(isDefined(adapter.packagePrefix) && { packagePrefix: adapter.packagePrefix }),\n styles: isDefined(styles) ? styles.map(({ style }) => style) : adapter.styles,\n listed,\n installed: isDefined(styles),\n ...(isDefined(sitePackage) && { sitePackage }),\n },\n ]),\n );\n\n return [\n `const sets = {\\n ${loaders.join(\",\\n \")}\\n};`,\n `export const iconRegistry = { ready: true, sets, libraries: ${JSON.stringify(info)} };`,\n ].join(\"\\n\");\n}\n"],"mappings":";;;;;;;;;;;AAgBA,SAASO,gBAAgBC,MAAc;CACrC,IAAI;EACF,OAAOR,aAAaQ,IAAI;CAC1B,QAAQ;EACN,OAAOA;CACT;AACF;;;;;AAMA,MAAaC,qBAAqBF,gBAAgBL,cAAc,IAAIQ,IAAI,WAAWC,YAAYE,GAAG,CAAC,CAAC;;;;;;;AAQpG,SAAgBC,iBAAiBC,IAAY;CAC3C,IAAM,CAACP,QAAQO,GAAGC,MAAM,GAAG;CAE3B,OAAOb,UAAUK,IAAI,KAAKD,gBAAgBC,IAAI,MAAMC;AACtD;;;;;;;AAQA,SAAgBQ,cAAcC,MAAc;CAC1C,OAAOjB,KAAKkB,KAAKD,MAAM,gBAAgB,UAAU,iBAAiB,MAAM;AAC1E;;;;;;;;;AAUA,SAAgBE,qBAAqBC,WAA8BC,WAAoC;CACrG,IAAME,UAAUH,UAAUI,SAAS,EAAEC,SAASC,aAC5CA,OAAOC,KAAK,EAAEC,YAAY;EACxB,IAAMN,MAAMlB,cAAcqB,QAAQI,SAASD,KAAK;EAEhD,OAAO,GAAGE,KAAKC,UAAUT,GAAG,EAAC,iBAAkBQ,KAAKC,UAAUV,UAAUC,GAAG,CAAC,EAAC;CAC/E,CAAC,CACH,GAEMU,OAAwCE,OAAOC,YACnDf,UAAUO,KAAK,EAAEF,SAASC,QAAQU,QAAQC,kBAAkB,CAC1DZ,QAAQI,SACR;EACES,OAAOb,QAAQa;EACfC,aAAad,QAAQc,eAAed,QAAQe,kBAAkBf,QAAQI;EACtE,GAAI3B,UAAUuB,QAAQgB,aAAa,KAAK,EAAEA,eAAehB,QAAQgB,cAAc;EAC/Ef,QAAQxB,UAAUwB,MAAM,IAAIA,OAAOC,KAAK,EAAEC,YAAYA,KAAK,IAAIH,QAAQC;EACvEU;EACAM,WAAWxC,UAAUwB,MAAM;EAC3B,GAAIxB,UAAUmC,WAAW,KAAK,EAAEA,YAAY;CAC9C,CAAC,CACF,CACH;CAEA,OAAO,CACL,qBAAqBd,QAAQL,KAAK,OAAO,EAAC,OAC1C,+DAA+DY,KAAKC,UAAUC,IAAI,EAAC,IAAK,CACzF,CAACd,KAAK,IAAI;AACb"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Builds the key a set is registered under.
3
+ *
4
+ * @param library - Identifier of the library.
5
+ * @param style - Identifier of the style.
6
+ * @returns The key.
7
+ */
8
+ function getIconSetKey(library, style) {
9
+ return `${library}/${style}`;
10
+ }
11
+ export { getIconSetKey as t };
12
+
13
+ //# sourceMappingURL=registry-BEEpqK3z.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-BEEpqK3z.js","names":["IconLibraryInfo","IconSetLoader","Promise","default","IconRegistry","ready","sets","Record","libraries","getIconSetKey","library","style"],"sources":["../src/lib/registry.ts"],"sourcesContent":["import type { IconLibraryInfo } from \"@/lib/sets\";\n\n/**\n * Loads one converted set, as a module whose default export is the set.\n *\n * @public\n */\nexport type IconSetLoader = () => Promise<{ default: unknown }>;\n\n/**\n * What the build step generates: a loader for every converted set, and every library it knows.\n *\n * @public\n */\nexport interface IconRegistry {\n /** Whether the build step generated the registry, rather than the placeholder being used. */\n ready: boolean;\n /** Loaders keyed by library and style, such as `phosphor/bold`. */\n sets: Record<string, IconSetLoader>;\n /** Libraries the build step knows, keyed by identifier. */\n libraries: Record<string, IconLibraryInfo>;\n}\n\n/**\n * Builds the key a set is registered under.\n *\n * @param library - Identifier of the library.\n * @param style - Identifier of the style.\n * @returns The key.\n */\nexport function getIconSetKey(library: string, style: string) {\n return `${library}/${style}`;\n}\n"],"mappings":";;;;;;;AA8BA,SAAgBS,cAAcC,SAAiBC,OAAe;CAC5D,OAAO,GAAGD,QAAO,GAAIC;AACvB"}
package/dist/render.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { t as SanityIcon } from "./types-_D2jGm25.js";
1
+ import { t as SanityIcon } from "./types-qlHEYDoN.js";
2
2
  import { ComponentProps } from "react";
3
3
  /**
4
- * Properties for drawing a stored icon, extending an SVG element with the value to read it from.
4
+ * Props for drawing a stored icon: an SVG element's props plus the stored value.
5
5
  *
6
6
  * @public
7
7
  */
@@ -10,10 +10,9 @@ type SanityIconProps = Omit<ComponentProps<"svg">, "children"> & {
10
10
  value: SanityIcon | undefined;
11
11
  };
12
12
  /**
13
- * Draws the icon an author chose, taking the shapes from the stored value so nothing has to resolve
14
- * them against an icon library. Renders nothing when the value is absent or unreadable.
13
+ * Draws a stored icon from the shapes saved with it, without loading an icon library.
15
14
  *
16
- * @returns The icon, or nothing when there is nothing to draw.
15
+ * @returns The icon, or nothing when the value is missing or unreadable.
17
16
  * @public
18
17
  */
19
18
  export declare function Icon({ value, ...props }: SanityIconProps): import("react").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","names":[],"sources":["../src/components/icon.tsx"],"mappings":";;;;;;;KAcY,kBAAkB,KAAK;;EAEjC,OAAO;;;;;;;;;wBAUO,OAAO,UAAU,SAAS,kCAAe,IAAA"}
1
+ {"version":3,"file":"render.d.ts","names":["ComponentProps","SanityIcon","SanityIconProps","Omit","Icon","value","JSX"],"sources":["../src/components/icon.tsx"],"mappings":";;;;;;;KAcYE,kBAAkBC,KAAKH;;EAEjC,OAAOC;;;;;;;;wBASOG,OAAOC,UAAU,SAASH,kCAAeI,IAAA"}
package/dist/render.js CHANGED
@@ -1,15 +1,15 @@
1
- import { r as resolveIconNode, t as Drawing } from "./drawing-BThiR2bN.js";
1
+ import { a as resolveIconDrawing } from "./nodes-DAzj56Xn.js";
2
+ import { t as Drawing } from "./drawing-ByrcBbWB.js";
2
3
  import { jsx } from "react/jsx-runtime";
3
4
  /**
4
- * Draws the icon an author chose, taking the shapes from the stored value so nothing has to resolve
5
- * them against an icon library. Renders nothing when the value is absent or unreadable.
5
+ * Draws a stored icon from the shapes saved with it, without loading an icon library.
6
6
  *
7
- * @returns The icon, or nothing when there is nothing to draw.
7
+ * @returns The icon, or nothing when the value is missing or unreadable.
8
8
  * @public
9
9
  */
10
10
  function Icon({ value, ...props }) {
11
11
  return /* @__PURE__ */ jsx(Drawing, {
12
- node: resolveIconNode(value?.node),
12
+ drawing: resolveIconDrawing(value?.node),
13
13
  ...props
14
14
  });
15
15
  }
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","names":["ComponentProps","Drawing","resolveIconNode","SanityIcon","SanityIconProps","Omit","value","Icon","props","node"],"sources":["../src/components/icon.tsx"],"sourcesContent":["// Runs inside a consumer's server components, where the compiler's memo cache hook cannot.\n\"use no memo\";\n\nimport type { ComponentProps } from \"react\";\n\nimport { Drawing } from \"@/components/drawing\";\nimport { resolveIconNode } from \"@/lib/nodes\";\nimport type { SanityIcon } from \"@/types\";\n\n/**\n * Properties for drawing a stored icon, extending an SVG element with the value to read it from.\n *\n * @public\n */\nexport type SanityIconProps = Omit<ComponentProps<\"svg\">, \"children\"> & {\n /** Stored icon to draw. */\n value: SanityIcon | undefined;\n};\n\n/**\n * Draws the icon an author chose, taking the shapes from the stored value so nothing has to resolve\n * them against an icon library. Renders nothing when the value is absent or unreadable.\n *\n * @returns The icon, or nothing when there is nothing to draw.\n * @public\n */\nexport function Icon({ value, ...props }: SanityIconProps) {\n return <Drawing node={resolveIconNode(value?.node)} {...props} />;\n}\n"],"mappings":";;;;;;;;;AA0BA,SAAgBO,KAAK,EAAED,OAAO,GAAGE,SAA0B;CACzD,OAAO,oBAAC,SAAD;EAAS,MAAMN,gBAAgBI,OAAOG,IAAI;EAAG,GAAID;CAAM,CAAA;AAChE"}
1
+ {"version":3,"file":"render.js","names":["ComponentProps","Drawing","resolveIconDrawing","SanityIcon","SanityIconProps","Omit","value","Icon","props","node"],"sources":["../src/components/icon.tsx"],"sourcesContent":["// Consumers render this in server components, where the compiler's memo cache hook can't run.\n\"use no memo\";\n\nimport type { ComponentProps } from \"react\";\n\nimport { Drawing } from \"@/components/drawing\";\nimport { resolveIconDrawing } from \"@/lib/nodes\";\nimport type { SanityIcon } from \"@/types\";\n\n/**\n * Props for drawing a stored icon: an SVG element's props plus the stored value.\n *\n * @public\n */\nexport type SanityIconProps = Omit<ComponentProps<\"svg\">, \"children\"> & {\n /** Stored icon to draw. */\n value: SanityIcon | undefined;\n};\n\n/**\n * Draws a stored icon from the shapes saved with it, without loading an icon library.\n *\n * @returns The icon, or nothing when the value is missing or unreadable.\n * @public\n */\nexport function Icon({ value, ...props }: SanityIconProps) {\n return <Drawing drawing={resolveIconDrawing(value?.node)} {...props} />;\n}\n"],"mappings":";;;;;;;;;AAyBA,SAAgBO,KAAK,EAAED,OAAO,GAAGE,SAA0B;CACzD,OAAO,oBAAC,SAAD;EAAS,SAASN,mBAAmBI,OAAOG,IAAI;EAAG,GAAID;CAAM,CAAA;AACtE"}