@csszyx/unplugin 0.14.5 → 0.15.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 (52) hide show
  1. package/README.md +4 -3
  2. package/dist/index.cjs +8 -7
  3. package/dist/index.d.cts +70 -3
  4. package/dist/index.d.mts +70 -3
  5. package/dist/index.mjs +4 -4
  6. package/dist/next-config.d.cts +1 -2
  7. package/dist/next-config.d.mts +1 -2
  8. package/dist/next-prebuild.cjs +9 -5
  9. package/dist/next-prebuild.d.cts +4 -2
  10. package/dist/next-prebuild.d.mts +4 -2
  11. package/dist/next-prebuild.mjs +8 -4
  12. package/dist/next-turbo-loader.cjs +20 -14
  13. package/dist/next-turbo-loader.d.cts +1 -1
  14. package/dist/next-turbo-loader.d.mts +1 -1
  15. package/dist/next-turbo-loader.mjs +19 -13
  16. package/dist/next-watcher.cjs +2 -2
  17. package/dist/next-watcher.d.cts +2 -2
  18. package/dist/next-watcher.d.mts +2 -2
  19. package/dist/next-watcher.mjs +2 -2
  20. package/dist/postcss.cjs +124 -0
  21. package/dist/postcss.d.cts +42 -0
  22. package/dist/postcss.d.mts +42 -0
  23. package/dist/postcss.mjs +107 -0
  24. package/dist/shared/{unplugin.RGzhYt-D.cjs → unplugin.8KYddE6x.cjs} +394 -226
  25. package/dist/shared/{unplugin.CPEWNSA0.d.cts → unplugin.BGog1Bib.d.cts} +9 -6
  26. package/dist/shared/{unplugin.CPEWNSA0.d.mts → unplugin.BGog1Bib.d.mts} +9 -6
  27. package/dist/shared/{unplugin.BU0O4IkX.mjs → unplugin.BLptVbUe.mjs} +22 -61
  28. package/dist/shared/{unplugin.BXYakiXt.d.cts → unplugin.BT7PqYuK.d.cts} +53 -55
  29. package/dist/shared/{unplugin.BXYakiXt.d.mts → unplugin.BT7PqYuK.d.mts} +53 -55
  30. package/dist/shared/{unplugin.Cji6O5jv.cjs → unplugin.BWnmKv07.cjs} +32 -69
  31. package/dist/shared/{unplugin.NlPvn5P4.mjs → unplugin.Bk9o8_RZ.mjs} +2 -6
  32. package/dist/shared/{unplugin.VtXstzEh.cjs → unplugin.BzF0V2kw.cjs} +6 -11
  33. package/dist/shared/{unplugin.CdZxp0x-.d.mts → unplugin.COlI0dJs.d.mts} +1 -1
  34. package/dist/shared/{unplugin.BnRf0Tvd.mjs → unplugin.D68hyqgb.mjs} +347 -178
  35. package/dist/shared/{unplugin.DN95k991.mjs → unplugin.DAzgbtuZ.mjs} +2 -2
  36. package/dist/shared/unplugin.DDSWQJYX.cjs +289 -0
  37. package/dist/shared/unplugin.DH_ij6cf.mjs +258 -0
  38. package/dist/shared/{unplugin.BZPdvVcj.mjs → unplugin.DK0b4fr7.mjs} +105 -127
  39. package/dist/shared/{unplugin.D8BxOOkA.cjs → unplugin.J6ue_lRJ.cjs} +121 -142
  40. package/dist/shared/{unplugin.DVbPNK3W.cjs → unplugin.gksolKh2.cjs} +6 -6
  41. package/dist/shared/{unplugin.xeED_qwh.d.cts → unplugin.rWOMecQs.d.cts} +1 -1
  42. package/dist/vite.cjs +4 -4
  43. package/dist/vite.d.cts +2 -2
  44. package/dist/vite.d.mts +1 -1
  45. package/dist/vite.mjs +4 -4
  46. package/dist/webpack.cjs +4 -4
  47. package/dist/webpack.d.cts +2 -1
  48. package/dist/webpack.d.mts +1 -1
  49. package/dist/webpack.mjs +4 -4
  50. package/package.json +19 -9
  51. package/dist/shared/unplugin.B3XoSRB8.mjs +0 -40
  52. package/dist/shared/unplugin.BkRah5Ot.cjs +0 -48
@@ -0,0 +1,124 @@
1
+ 'use strict';
2
+
3
+ const path = require('node:path');
4
+ const fs = require('node:fs');
5
+
6
+ function _interopNamespaceCompat(e) {
7
+ if (e && typeof e === 'object' && 'default' in e) return e;
8
+ const n = Object.create(null);
9
+ if (e) {
10
+ for (const k in e) {
11
+ n[k] = e[k];
12
+ }
13
+ }
14
+ n.default = e;
15
+ return n;
16
+ }
17
+
18
+ const path__namespace = /*#__PURE__*/_interopNamespaceCompat(path);
19
+ const fs__namespace = /*#__PURE__*/_interopNamespaceCompat(fs);
20
+
21
+ const WINDOWS_PATH_SEPARATOR = String.fromCodePoint(92);
22
+ function normalizePathSeparators(value) {
23
+ return value.split(WINDOWS_PATH_SEPARATOR).join("/");
24
+ }
25
+
26
+ const SAFELIST_FILE = ".csszyx/csszyx-classes.txt";
27
+ const DEFAULT_SAFELIST_FILES = [SAFELIST_FILE];
28
+ const LEGACY_SAFELIST_FILES = [
29
+ "csszyx-classes.html",
30
+ ".csszyx/next-loader-classes.html"
31
+ ];
32
+ const LEGACY_SAFELIST_BASENAMES = new Set(
33
+ LEGACY_SAFELIST_FILES.map((file) => path__namespace.posix.basename(file))
34
+ );
35
+ function isDanglingLegacySource(target, cssFile) {
36
+ if (!LEGACY_SAFELIST_BASENAMES.has(path__namespace.posix.basename(target))) return false;
37
+ return !fs__namespace.existsSync(path__namespace.resolve(path__namespace.dirname(cssFile), target));
38
+ }
39
+ function legacySourceMessage(cssFile, target) {
40
+ return `[csszyx] ${cssFile}: @source "${target}" names the old safelist, which csszyx no longer writes. The safelist is now ${SAFELIST_FILE}, and csszyx adds the directive itself: remove this line. Vite, Rollup and webpack inject it; on Next.js list '@csszyx/unplugin/postcss' before '@tailwindcss/postcss' in postcss.config.`;
41
+ }
42
+ const TAILWIND_SPECIFIER = String.raw`["']tailwindcss(?:\/[^"']*)?["']`;
43
+ const TAILWIND_IMPORT_PARAMS = new RegExp(`^${TAILWIND_SPECIFIER}`);
44
+ function computeSafelistRelPath(rootDir, safelistFilename, cssId) {
45
+ const safelistPath = normalizePathSeparators(path__namespace.join(rootDir, safelistFilename));
46
+ const cssDir = normalizePathSeparators(path__namespace.dirname(cssId));
47
+ let relPath = path__namespace.posix.relative(cssDir, safelistPath);
48
+ if (!relPath.startsWith("./") && !relPath.startsWith("../")) {
49
+ relPath = `./${relPath}`;
50
+ }
51
+ return relPath;
52
+ }
53
+ function importParamsAreLocal(params) {
54
+ let target = params.trim();
55
+ if (target.startsWith("url(")) target = target.slice(4).trim();
56
+ if (target.startsWith('"') || target.startsWith("'")) target = target.slice(1);
57
+ return target.startsWith("./") || target.startsWith("../") || target.startsWith("/");
58
+ }
59
+ function importParamsNameTailwind(params) {
60
+ return TAILWIND_IMPORT_PARAMS.test(params.trim());
61
+ }
62
+
63
+ function rootMayReachTailwind(root) {
64
+ let found = false;
65
+ root.walkAtRules("import", (rule) => {
66
+ if (importParamsNameTailwind(rule.params) || importParamsAreLocal(rule.params)) {
67
+ found = true;
68
+ return false;
69
+ }
70
+ return void 0;
71
+ });
72
+ return found;
73
+ }
74
+ function existingSourcePaths(root, file) {
75
+ const paths = /* @__PURE__ */ new Set();
76
+ root.walkAtRules("source", (rule) => {
77
+ const match = /^["']([^"']*)["']$/.exec(rule.params.trim());
78
+ const target = match?.[1];
79
+ if (target === void 0) return;
80
+ if (isDanglingLegacySource(target, file)) {
81
+ throw new Error(legacySourceMessage(file, target));
82
+ }
83
+ paths.add(target);
84
+ });
85
+ return paths;
86
+ }
87
+ const csszyxPostcss = (options = {}) => {
88
+ const projectRoot = options.root ?? process.cwd();
89
+ const safelistFiles = options.safelistFiles ?? DEFAULT_SAFELIST_FILES;
90
+ return {
91
+ postcssPlugin: "csszyx",
92
+ Once(root, { AtRule, result }) {
93
+ const names = result.processor.plugins.map(
94
+ (plugin) => plugin.postcssPlugin
95
+ );
96
+ const tailwindAt = names.indexOf("tailwindcss");
97
+ if (tailwindAt !== -1 && tailwindAt < names.indexOf("csszyx")) {
98
+ throw new Error(
99
+ "[csszyx] '@csszyx/unplugin/postcss' is listed after '@tailwindcss/postcss'. Tailwind has already compiled the stylesheet by then, so the safelist is never read: list '@csszyx/unplugin/postcss' before '@tailwindcss/postcss'."
100
+ );
101
+ }
102
+ const file = root.source?.input.file;
103
+ if (file === void 0 || !rootMayReachTailwind(root)) return;
104
+ const present = existingSourcePaths(root, file);
105
+ for (const safelistFile of safelistFiles) {
106
+ const relPath = computeSafelistRelPath(projectRoot, safelistFile, file);
107
+ if (!present.has(relPath)) {
108
+ root.append(new AtRule({ name: "source", params: `"${relPath}"` }));
109
+ }
110
+ const absolute = path__namespace.resolve(projectRoot, safelistFile);
111
+ result.messages.push({
112
+ type: "dir-dependency",
113
+ plugin: "csszyx",
114
+ dir: path__namespace.dirname(absolute),
115
+ glob: path__namespace.basename(absolute),
116
+ parent: file
117
+ });
118
+ }
119
+ }
120
+ };
121
+ };
122
+ csszyxPostcss.postcss = true;
123
+
124
+ module.exports = csszyxPostcss;
@@ -0,0 +1,42 @@
1
+ import { PluginCreator } from 'postcss';
2
+
3
+ /**
4
+ * PostCSS plugin that points a Tailwind stylesheet at csszyx's safelist.
5
+ *
6
+ * Every bundler csszyx has a plugin for injects the `@source` directive into
7
+ * the CSS entry itself. Next's Turbopack lane has no such hook: there csszyx
8
+ * only writes source files, and the stylesheet goes straight to
9
+ * `@tailwindcss/postcss`. This plugin is the one hook that lane does offer,
10
+ * so with it in `postcss.config` no project has to hand-write the directive.
11
+ *
12
+ * Order matters: `@tailwindcss/postcss` compiles the stylesheet in its own
13
+ * `Once`, so this plugin has to be listed BEFORE it. Next serialises the
14
+ * PostCSS config to a worker, so the plugin is referenced by package name
15
+ * (`'@csszyx/unplugin/postcss'`), never as a function.
16
+ */
17
+
18
+ /** Options for {@link csszyxPostcss}. */
19
+ interface CsszyxPostcssOptions {
20
+ /**
21
+ * Project root the safelist files are written under. Defaults to the
22
+ * working directory, which is the project directory under Next.
23
+ */
24
+ root?: string;
25
+ /**
26
+ * Safelist files to point at, relative to `root`. Defaults to every file
27
+ * csszyx writes; a file that does not exist yet costs nothing, Tailwind
28
+ * scans nothing for it and does not fail.
29
+ */
30
+ safelistFiles?: readonly string[];
31
+ }
32
+ /**
33
+ * Create the plugin.
34
+ *
35
+ * @param options - where the safelist files live.
36
+ * @returns a PostCSS plugin that appends one `@source` per safelist file to
37
+ * any stylesheet importing tailwindcss, skipping paths already named.
38
+ */
39
+ declare const csszyxPostcss: PluginCreator<CsszyxPostcssOptions>;
40
+
41
+ export = csszyxPostcss;
42
+ export type { CsszyxPostcssOptions };
@@ -0,0 +1,42 @@
1
+ import { PluginCreator } from 'postcss';
2
+
3
+ /**
4
+ * PostCSS plugin that points a Tailwind stylesheet at csszyx's safelist.
5
+ *
6
+ * Every bundler csszyx has a plugin for injects the `@source` directive into
7
+ * the CSS entry itself. Next's Turbopack lane has no such hook: there csszyx
8
+ * only writes source files, and the stylesheet goes straight to
9
+ * `@tailwindcss/postcss`. This plugin is the one hook that lane does offer,
10
+ * so with it in `postcss.config` no project has to hand-write the directive.
11
+ *
12
+ * Order matters: `@tailwindcss/postcss` compiles the stylesheet in its own
13
+ * `Once`, so this plugin has to be listed BEFORE it. Next serialises the
14
+ * PostCSS config to a worker, so the plugin is referenced by package name
15
+ * (`'@csszyx/unplugin/postcss'`), never as a function.
16
+ */
17
+
18
+ /** Options for {@link csszyxPostcss}. */
19
+ interface CsszyxPostcssOptions {
20
+ /**
21
+ * Project root the safelist files are written under. Defaults to the
22
+ * working directory, which is the project directory under Next.
23
+ */
24
+ root?: string;
25
+ /**
26
+ * Safelist files to point at, relative to `root`. Defaults to every file
27
+ * csszyx writes; a file that does not exist yet costs nothing, Tailwind
28
+ * scans nothing for it and does not fail.
29
+ */
30
+ safelistFiles?: readonly string[];
31
+ }
32
+ /**
33
+ * Create the plugin.
34
+ *
35
+ * @param options - where the safelist files live.
36
+ * @returns a PostCSS plugin that appends one `@source` per safelist file to
37
+ * any stylesheet importing tailwindcss, skipping paths already named.
38
+ */
39
+ declare const csszyxPostcss: PluginCreator<CsszyxPostcssOptions>;
40
+
41
+ export { csszyxPostcss as default };
42
+ export type { CsszyxPostcssOptions };
@@ -0,0 +1,107 @@
1
+ import * as path from 'node:path';
2
+ import * as fs from 'node:fs';
3
+
4
+ const WINDOWS_PATH_SEPARATOR = String.fromCodePoint(92);
5
+ function normalizePathSeparators(value) {
6
+ return value.split(WINDOWS_PATH_SEPARATOR).join("/");
7
+ }
8
+
9
+ const SAFELIST_FILE = ".csszyx/csszyx-classes.txt";
10
+ const DEFAULT_SAFELIST_FILES = [SAFELIST_FILE];
11
+ const LEGACY_SAFELIST_FILES = [
12
+ "csszyx-classes.html",
13
+ ".csszyx/next-loader-classes.html"
14
+ ];
15
+ const LEGACY_SAFELIST_BASENAMES = new Set(
16
+ LEGACY_SAFELIST_FILES.map((file) => path.posix.basename(file))
17
+ );
18
+ function isDanglingLegacySource(target, cssFile) {
19
+ if (!LEGACY_SAFELIST_BASENAMES.has(path.posix.basename(target))) return false;
20
+ return !fs.existsSync(path.resolve(path.dirname(cssFile), target));
21
+ }
22
+ function legacySourceMessage(cssFile, target) {
23
+ return `[csszyx] ${cssFile}: @source "${target}" names the old safelist, which csszyx no longer writes. The safelist is now ${SAFELIST_FILE}, and csszyx adds the directive itself: remove this line. Vite, Rollup and webpack inject it; on Next.js list '@csszyx/unplugin/postcss' before '@tailwindcss/postcss' in postcss.config.`;
24
+ }
25
+ const TAILWIND_SPECIFIER = String.raw`["']tailwindcss(?:\/[^"']*)?["']`;
26
+ const TAILWIND_IMPORT_PARAMS = new RegExp(`^${TAILWIND_SPECIFIER}`);
27
+ function computeSafelistRelPath(rootDir, safelistFilename, cssId) {
28
+ const safelistPath = normalizePathSeparators(path.join(rootDir, safelistFilename));
29
+ const cssDir = normalizePathSeparators(path.dirname(cssId));
30
+ let relPath = path.posix.relative(cssDir, safelistPath);
31
+ if (!relPath.startsWith("./") && !relPath.startsWith("../")) {
32
+ relPath = `./${relPath}`;
33
+ }
34
+ return relPath;
35
+ }
36
+ function importParamsAreLocal(params) {
37
+ let target = params.trim();
38
+ if (target.startsWith("url(")) target = target.slice(4).trim();
39
+ if (target.startsWith('"') || target.startsWith("'")) target = target.slice(1);
40
+ return target.startsWith("./") || target.startsWith("../") || target.startsWith("/");
41
+ }
42
+ function importParamsNameTailwind(params) {
43
+ return TAILWIND_IMPORT_PARAMS.test(params.trim());
44
+ }
45
+
46
+ function rootMayReachTailwind(root) {
47
+ let found = false;
48
+ root.walkAtRules("import", (rule) => {
49
+ if (importParamsNameTailwind(rule.params) || importParamsAreLocal(rule.params)) {
50
+ found = true;
51
+ return false;
52
+ }
53
+ return void 0;
54
+ });
55
+ return found;
56
+ }
57
+ function existingSourcePaths(root, file) {
58
+ const paths = /* @__PURE__ */ new Set();
59
+ root.walkAtRules("source", (rule) => {
60
+ const match = /^["']([^"']*)["']$/.exec(rule.params.trim());
61
+ const target = match?.[1];
62
+ if (target === void 0) return;
63
+ if (isDanglingLegacySource(target, file)) {
64
+ throw new Error(legacySourceMessage(file, target));
65
+ }
66
+ paths.add(target);
67
+ });
68
+ return paths;
69
+ }
70
+ const csszyxPostcss = (options = {}) => {
71
+ const projectRoot = options.root ?? process.cwd();
72
+ const safelistFiles = options.safelistFiles ?? DEFAULT_SAFELIST_FILES;
73
+ return {
74
+ postcssPlugin: "csszyx",
75
+ Once(root, { AtRule, result }) {
76
+ const names = result.processor.plugins.map(
77
+ (plugin) => plugin.postcssPlugin
78
+ );
79
+ const tailwindAt = names.indexOf("tailwindcss");
80
+ if (tailwindAt !== -1 && tailwindAt < names.indexOf("csszyx")) {
81
+ throw new Error(
82
+ "[csszyx] '@csszyx/unplugin/postcss' is listed after '@tailwindcss/postcss'. Tailwind has already compiled the stylesheet by then, so the safelist is never read: list '@csszyx/unplugin/postcss' before '@tailwindcss/postcss'."
83
+ );
84
+ }
85
+ const file = root.source?.input.file;
86
+ if (file === void 0 || !rootMayReachTailwind(root)) return;
87
+ const present = existingSourcePaths(root, file);
88
+ for (const safelistFile of safelistFiles) {
89
+ const relPath = computeSafelistRelPath(projectRoot, safelistFile, file);
90
+ if (!present.has(relPath)) {
91
+ root.append(new AtRule({ name: "source", params: `"${relPath}"` }));
92
+ }
93
+ const absolute = path.resolve(projectRoot, safelistFile);
94
+ result.messages.push({
95
+ type: "dir-dependency",
96
+ plugin: "csszyx",
97
+ dir: path.dirname(absolute),
98
+ glob: path.basename(absolute),
99
+ parent: file
100
+ });
101
+ }
102
+ }
103
+ };
104
+ };
105
+ csszyxPostcss.postcss = true;
106
+
107
+ export { csszyxPostcss as default };