@shortwind/next 0.1.0-beta.10 → 0.1.0-beta.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,15 +12,19 @@ npm i -D @shortwind/next@beta @shortwind/cli@beta
12
12
 
13
13
  ## Usage
14
14
 
15
- Wrap your Next config:
15
+ Wrap your Next config. `withShortwind` is curried — the first call takes
16
+ Shortwind options (usually none), the second your Next config:
16
17
 
17
18
  ```ts
18
19
  // next.config.ts
20
+ import type { NextConfig } from "next";
19
21
  import { withShortwind } from "@shortwind/next";
20
22
 
21
- export default withShortwind({
23
+ const nextConfig: NextConfig = {
22
24
  // your Next config
23
- });
25
+ };
26
+
27
+ export default withShortwind()(nextConfig);
24
28
  ```
25
29
 
26
30
  Reads recipes from `./recipes/`. Run `npx @shortwind/cli@beta init` first to scaffold the catalog, theme, and `SKILL.md`.
package/dist/index.d.ts CHANGED
@@ -1,35 +1,13 @@
1
+ import type { NextConfig } from "next";
1
2
  export type ShortwindNextOptions = {
2
3
  recipesDir?: string;
3
4
  cwd?: string;
4
- };
5
- type WebpackConfig = {
6
- module?: {
7
- rules?: unknown[];
8
- };
9
- [k: string]: unknown;
10
- };
11
- type WebpackContext = {
12
- dev: boolean;
13
- isServer: boolean;
14
- };
15
- type TurbopackRule = {
16
- loaders: Array<{
17
- loader: string;
18
- options?: unknown;
19
- }>;
20
- [k: string]: unknown;
21
- };
22
- type TurbopackConfig = {
23
- rules?: Record<string, TurbopackRule>;
24
- [k: string]: unknown;
25
- };
26
- type NextConfig = {
27
- webpack?: (config: WebpackConfig, ctx: WebpackContext) => WebpackConfig;
28
- turbopack?: TurbopackConfig;
29
- experimental?: Record<string, unknown>;
30
- [k: string]: unknown;
5
+ strict?: boolean;
31
6
  };
32
7
  export declare function withShortwind(options?: ShortwindNextOptions): (nextConfig?: NextConfig) => NextConfig;
33
8
  export { default as shortwindLoader } from "./loader.js";
34
9
  export type { ShortwindLoaderOptions } from "./loader.js";
10
+ export { expandClassList } from "@shortwind/core";
11
+ export { loadRegistryFromDir } from "@shortwind/tailwind";
12
+ export type { Registry } from "@shortwind/core";
35
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,oBAAoB,GAAG;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC;IAC/B,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,GAAG,EAAE,OAAO,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,OAAO,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACtD,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACtC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,cAAc,KAAK,aAAa,CAAC;IACxE,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB,CAAC;AASF,wBAAgB,aAAa,CAC3B,OAAO,GAAE,oBAAyB,GACjC,CAAC,UAAU,CAAC,EAAE,UAAU,KAAK,UAAU,CAwCzC;AAED,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,aAAa,CAAC;AACzD,YAAY,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAEvC,MAAM,MAAM,oBAAoB,GAAG;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IAKb,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAcF,wBAAgB,aAAa,CAC3B,OAAO,GAAE,oBAAyB,GACjC,CAAC,UAAU,CAAC,EAAE,UAAU,KAAK,UAAU,CAuDzC;AAyCD,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,aAAa,CAAC;AACzD,YAAY,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAO1D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,YAAY,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import path from "node:path";
2
2
  import { fileURLToPath } from "node:url";
3
+ import { detectTailwindMajor, findTailwindEntryCssFiles, loadRegistryFromDir, syncSourceDirectiveToFile, TailwindAdapterError, } from "@shortwind/tailwind";
3
4
  import { clearRegistryCache } from "./loader.js";
4
5
  const here = path.dirname(fileURLToPath(import.meta.url));
5
6
  // Resolves to the compiled ESM sibling. If we ever ship a dual CJS/ESM build,
@@ -9,13 +10,28 @@ const SOURCE_TEST = /\.(?:tsx?|jsx?|mdx?)$/;
9
10
  export function withShortwind(options = {}) {
10
11
  const cwd = options.cwd ?? process.cwd();
11
12
  const recipesDir = options.recipesDir ?? path.join(cwd, "recipes");
13
+ // Recipe expansions exist only in loader output, which Tailwind never sees:
14
+ // in Next, Tailwind v4 reads the entry CSS FROM DISK (PostCSS/Turbopack) and
15
+ // scans on-disk sources — there is no CSS pipeline hook equivalent to Vite's
16
+ // load phase. So the registry-derived `@source inline(...)` safelist must
17
+ // live on disk too (#73). next.config is evaluated at the start of every
18
+ // `next dev`/`next build`, which makes this the reliable sync point for both
19
+ // bundlers; the loader refreshes the same files when recipes change
20
+ // mid-session (see loader.ts).
21
+ const entryCss = syncSafelist(cwd, recipesDir);
12
22
  return (nextConfig = {}) => {
13
- const loaderOptions = { recipesDir };
23
+ const loaderOptions = { recipesDir, strict: options.strict ?? false, entryCss };
14
24
  const previousWebpack = nextConfig.webpack;
15
25
  const wrapped = {
16
26
  ...nextConfig,
27
+ // Next types the hook's config as `any`; narrow it locally to the slice
28
+ // we touch and let `ctx` take its contextual WebpackConfigContext type.
29
+ // The truthy guard also covers `webpack: null`, which Next's config type
30
+ // explicitly allows.
17
31
  webpack(config, ctx) {
18
- const next = previousWebpack ? previousWebpack(config, ctx) : config;
32
+ const next = previousWebpack
33
+ ? previousWebpack(config, ctx)
34
+ : config;
19
35
  next.module ??= {};
20
36
  next.module.rules ??= [];
21
37
  const rule = {
@@ -33,10 +49,10 @@ export function withShortwind(options = {}) {
33
49
  const turbo = nextConfig.turbopack ?? {};
34
50
  const rules = { ...(turbo.rules ?? {}) };
35
51
  // Asymmetry vs the webpack rule's `exclude: /node_modules/`: Turbopack rule
36
- // keys are globs with no negation syntax, so a node_modules exclude can't be
37
- // expressed here. Turbopack does not apply custom loader rules to
38
- // node_modules by default, so dependency files aren't transformed; the
39
- // loader is also a no-op on any file without `@recipe` tokens.
52
+ // keys are globs with no negation syntax, so a node_modules exclude can't
53
+ // be expressed here — and Next 16's Turbopack DOES apply custom loader
54
+ // rules to node_modules. The loader itself skips vendored paths (#75), so
55
+ // dependency files pass through untransformed and unscanned.
40
56
  rules["*.{tsx,ts,jsx,js,mdx,md}"] = {
41
57
  loaders: [{ loader: LOADER_PATH, options: loaderOptions }],
42
58
  };
@@ -44,5 +60,50 @@ export function withShortwind(options = {}) {
44
60
  return wrapped;
45
61
  };
46
62
  }
63
+ // Upsert the safelist into every Tailwind v4 entry stylesheet. Failures are
64
+ // reported, never thrown — a broken recipe or a read-only filesystem must not
65
+ // take down config evaluation (the loader will surface recipe errors with
66
+ // proper module attribution).
67
+ function syncSafelist(cwd, recipesDir) {
68
+ try {
69
+ const registry = loadRegistryFromDir(recipesDir);
70
+ const files = findTailwindEntryCssFiles(cwd);
71
+ if (Object.keys(registry.flattened).length > 0 && files.length === 0 && isTailwind4(cwd)) {
72
+ console.warn(`[shortwind] no Tailwind entry CSS found under ${cwd} (a .css with @import "tailwindcss") — ` +
73
+ `recipe-only utilities won't reach Tailwind's generator and will render unstyled`);
74
+ }
75
+ for (const file of files) {
76
+ try {
77
+ syncSourceDirectiveToFile(file, registry);
78
+ }
79
+ catch (err) {
80
+ console.warn(`[shortwind] could not write safelist to ${file}: ${String(err)}`);
81
+ }
82
+ }
83
+ return files;
84
+ }
85
+ catch (err) {
86
+ if (err instanceof TailwindAdapterError) {
87
+ console.error(`[shortwind] ${err.message}`);
88
+ return [];
89
+ }
90
+ throw err;
91
+ }
92
+ }
93
+ function isTailwind4(cwd) {
94
+ try {
95
+ return detectTailwindMajor(cwd) === 4;
96
+ }
97
+ catch {
98
+ return false;
99
+ }
100
+ }
47
101
  export { default as shortwindLoader } from "./loader.js";
102
+ // Re-exported so the documented rc() escape hatch resolves from the package
103
+ // init actually installs — `@shortwind/core` is only a transitive dependency
104
+ // (#63). In Next the registry load is server-side (loadRegistryFromDir reads
105
+ // recipes/ from disk); expand in a server component or route and pass the
106
+ // resulting plain-Tailwind string to the client as a prop.
107
+ export { expandClassList } from "@shortwind/core";
108
+ export { loadRegistryFromDir } from "@shortwind/tailwind";
48
109
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAkCjD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,8EAA8E;AAC9E,+EAA+E;AAC/E,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;AAEjD,MAAM,WAAW,GAAG,uBAAuB,CAAC;AAE5C,MAAM,UAAU,aAAa,CAC3B,UAAgC,EAAE;IAElC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAEnE,OAAO,CAAC,aAAyB,EAAE,EAAE,EAAE;QACrC,MAAM,aAAa,GAAG,EAAE,UAAU,EAAE,CAAC;QACrC,MAAM,eAAe,GAAG,UAAU,CAAC,OAAO,CAAC;QAE3C,MAAM,OAAO,GAAe;YAC1B,GAAG,UAAU;YACb,OAAO,CAAC,MAAM,EAAE,GAAG;gBACjB,MAAM,IAAI,GAAG,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;gBACrE,IAAI,CAAC,MAAM,KAAK,EAAE,CAAC;gBACnB,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,EAAE,CAAC;gBACzB,MAAM,IAAI,GAAG;oBACX,IAAI,EAAE,WAAW;oBACjB,OAAO,EAAE,cAAc;oBACvB,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC;oBACtD,OAAO,EAAE,KAAc;iBACxB,CAAC;gBACF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBAChC,IAAI,GAAG,CAAC,GAAG;oBAAE,kBAAkB,EAAE,CAAC;gBAClC,OAAO,IAAI,CAAC;YACd,CAAC;SACF,CAAC;QAEF,MAAM,KAAK,GAAoB,UAAU,CAAC,SAAS,IAAI,EAAE,CAAC;QAC1D,MAAM,KAAK,GAAkC,EAAE,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;QACxE,4EAA4E;QAC5E,6EAA6E;QAC7E,kEAAkE;QAClE,uEAAuE;QACvE,+DAA+D;QAC/D,KAAK,CAAC,0BAA0B,CAAC,GAAG;YAClC,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC;SAC3D,CAAC;QACF,OAAO,CAAC,SAAS,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,CAAC;QAExC,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/loader.d.ts CHANGED
@@ -2,6 +2,8 @@ import { type TransformOptions } from "@shortwind/tailwind";
2
2
  export type ShortwindLoaderOptions = {
3
3
  recipesDir: string;
4
4
  mode?: TransformOptions["mode"];
5
+ strict?: boolean;
6
+ entryCss?: readonly string[];
5
7
  };
6
8
  export declare function clearRegistryCache(): void;
7
9
  type LoaderContext = {
@@ -10,6 +12,7 @@ type LoaderContext = {
10
12
  addDependency?: (file: string) => void;
11
13
  addContextDependency?: (dir: string) => void;
12
14
  emitError?: (err: Error) => void;
15
+ emitWarning?: (err: Error) => void;
13
16
  };
14
17
  export default function shortwindLoader(this: LoaderContext, source: string): string;
15
18
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,qBAAqB,CAAC;AAG7B,MAAM,MAAM,sBAAsB,GAAG;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;CACjC,CAAC;AAqCF,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED,KAAK,aAAa,GAAG;IACnB,UAAU,EAAE,MAAM,sBAAsB,CAAC;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,oBAAoB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAmBnF"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAEA,OAAO,EAQL,KAAK,gBAAgB,EACtB,MAAM,qBAAqB,CAAC;AAG7B,MAAM,MAAM,sBAAsB,GAAG;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAIhC,MAAM,CAAC,EAAE,OAAO,CAAC;IAKjB,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B,CAAC;AAgDF,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED,KAAK,aAAa,GAAG;IACnB,UAAU,EAAE,MAAM,sBAAsB,CAAC;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,oBAAoB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;CACpC,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAmDnF"}
package/dist/loader.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { existsSync, readdirSync, statSync } from "node:fs";
2
2
  import path from "node:path";
3
- import { loadRegistryFromDir, modeForFile, transformContent, } from "@shortwind/tailwind";
3
+ import { findResidualRecipeTokens, findUnexpandedRecipes, loadRegistryFromDir, modeForFile, residualRecipeMessage, syncSourceDirectiveToFile, transformContent, } from "@shortwind/tailwind";
4
4
  const registryCache = new Map();
5
5
  function recipesSignature(recipesDir) {
6
6
  if (!existsSync(recipesDir))
@@ -16,7 +16,7 @@ function recipesSignature(recipesDir) {
16
16
  }
17
17
  return { signature: parts.join("|"), files };
18
18
  }
19
- function getRegistry(recipesDir) {
19
+ function getRegistry(recipesDir, entryCss = []) {
20
20
  const { signature, files } = recipesSignature(recipesDir);
21
21
  const cached = registryCache.get(recipesDir);
22
22
  if (cached && cached.signature === signature)
@@ -27,18 +27,40 @@ function getRegistry(recipesDir) {
27
27
  signature,
28
28
  };
29
29
  registryCache.set(recipesDir, entry);
30
+ // Recipes changed since withShortwind's config-eval sync — refresh the
31
+ // on-disk safelist so a recipe authored mid-`next dev` renders styled (#73).
32
+ // The write is content-guarded (no-op when nothing changed) and best-effort:
33
+ // a read-only filesystem must not fail the module.
34
+ for (const cssPath of entryCss) {
35
+ try {
36
+ syncSourceDirectiveToFile(cssPath, entry.registry);
37
+ }
38
+ catch {
39
+ // covered again at the next config evaluation
40
+ }
41
+ }
30
42
  return entry;
31
43
  }
32
44
  export function clearRegistryCache() {
33
45
  registryCache.clear();
34
46
  }
35
47
  export default function shortwindLoader(source) {
48
+ // Never transform or strict-scan vendored code (#75). The webpack rule
49
+ // excludes node_modules, but Turbopack rule keys are include-globs with no
50
+ // negation syntax — and Next 16's Turbopack applies custom loader rules to
51
+ // node_modules, so without this guard strict mode fails the build on files
52
+ // the user doesn't own (a JSDoc `{@link …}` in next's own dist collided
53
+ // with the catalog's @link recipe). Guarding here makes the scan scope
54
+ // bundler-independent, matching @shortwind/vite's transform.
55
+ if (this.resourcePath.split(path.sep).join("/").includes("/node_modules/")) {
56
+ return source;
57
+ }
36
58
  const options = this.getOptions();
37
59
  if (this.addContextDependency)
38
60
  this.addContextDependency(options.recipesDir);
39
61
  let entry;
40
62
  try {
41
- entry = getRegistry(options.recipesDir);
63
+ entry = getRegistry(options.recipesDir, options.entryCss ?? []);
42
64
  }
43
65
  catch (err) {
44
66
  const wrapped = err instanceof Error ? err : new Error(`shortwind: failed to load registry: ${String(err)}`);
@@ -51,6 +73,24 @@ export default function shortwindLoader(source) {
51
73
  this.addDependency(file);
52
74
  }
53
75
  const mode = options.mode ?? modeForFile(this.resourcePath);
54
- return transformContent(source, entry.registry, { mode });
76
+ const out = transformContent(source, entry.registry, { mode });
77
+ // Leak reporting (#67), consistent with @shortwind/vite: strict mode scans
78
+ // the whole output (the class-value scan can't see a recipe assigned to a
79
+ // variable/prop) and errors the module so `next build` fails instead of
80
+ // shipping unstyled UI; the default surfaces a webpack warning for the
81
+ // class-value cases it can attribute.
82
+ if (options.strict) {
83
+ const residual = findResidualRecipeTokens(out, entry.registry);
84
+ if (residual.length > 0 && this.emitError) {
85
+ this.emitError(new Error(`${residualRecipeMessage(this.resourcePath, residual)} (strict mode: failing the build — pass strict: false to demote this to a warning)`));
86
+ }
87
+ }
88
+ else {
89
+ const leftover = findUnexpandedRecipes(out, entry.registry);
90
+ if (leftover.length > 0 && this.emitWarning) {
91
+ this.emitWarning(new Error(residualRecipeMessage(this.resourcePath, leftover)));
92
+ }
93
+ }
94
+ return out;
55
95
  }
56
96
  //# sourceMappingURL=loader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"loader.js","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,mBAAmB,EACnB,WAAW,EACX,qBAAqB,EACrB,yBAAyB,EACzB,gBAAgB,GAEjB,MAAM,qBAAqB,CAAC;AAuB7B,MAAM,aAAa,GAAG,IAAI,GAAG,EAAsB,CAAC;AAEpD,SAAS,gBAAgB,CAAC,UAAkB;IAC1C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACjE,MAAM,KAAK,GAAG,WAAW,CAAC,UAAU,CAAC;SAClC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;SACjC,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;IACxC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC;AAC/C,CAAC;AAED,SAAS,WAAW,CAAC,UAAkB,EAAE,WAA8B,EAAE;IACvE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC7C,IAAI,MAAM,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IAC5D,MAAM,KAAK,GAAe;QACxB,QAAQ,EAAE,mBAAmB,CAAC,UAAU,CAAC;QACzC,KAAK;QACL,SAAS;KACV,CAAC;IACF,aAAa,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IACrC,uEAAuE;IACvE,6EAA6E;IAC7E,6EAA6E;IAC7E,mDAAmD;IACnD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,yBAAyB,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QACrD,CAAC;QAAC,MAAM,CAAC;YACP,8CAA8C;QAChD,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,aAAa,CAAC,KAAK,EAAE,CAAC;AACxB,CAAC;AAWD,MAAM,CAAC,OAAO,UAAU,eAAe,CAAsB,MAAc;IACzE,uEAAuE;IACvE,2EAA2E;IAC3E,2EAA2E;IAC3E,2EAA2E;IAC3E,wEAAwE;IACxE,uEAAuE;IACvE,6DAA6D;IAC7D,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC3E,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;IAClC,IAAI,IAAI,CAAC,oBAAoB;QAAE,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAE7E,IAAI,KAAiB,CAAC;IACtB,IAAI,CAAC;QACH,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GACX,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,uCAAuC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC/F,IAAI,IAAI,CAAC,SAAS;YAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAC5C,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK;YAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC3D,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC5D,MAAM,GAAG,GAAG,gBAAgB,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IAE/D,2EAA2E;IAC3E,0EAA0E;IAC1E,wEAAwE;IACxE,uEAAuE;IACvE,sCAAsC;IACtC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,QAAQ,GAAG,wBAAwB,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC/D,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAC1C,IAAI,CAAC,SAAS,CACZ,IAAI,KAAK,CACP,GAAG,qBAAqB,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,oFAAoF,CAC1I,CACF,CAAC;QACJ,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,QAAQ,GAAG,qBAAqB,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC5D,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YAC5C,IAAI,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,qBAAqB,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shortwind/next",
3
- "version": "0.1.0-beta.10",
3
+ "version": "0.1.0-beta.12",
4
4
  "description": "Next.js plugin for Shortwind. Webpack and Turbopack.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -12,11 +12,12 @@
12
12
  "next": ">=14.0.0"
13
13
  },
14
14
  "dependencies": {
15
- "@shortwind/core": "0.1.0-beta.10",
16
- "@shortwind/tailwind": "0.1.0-beta.10"
15
+ "@shortwind/core": "0.1.0-beta.12",
16
+ "@shortwind/tailwind": "0.1.0-beta.12"
17
17
  },
18
18
  "devDependencies": {
19
- "@types/node": "^25.7.0"
19
+ "@types/node": "^25.7.0",
20
+ "next": "^16.2.6"
20
21
  },
21
22
  "publishConfig": {
22
23
  "access": "public",
@@ -33,7 +34,7 @@
33
34
  },
34
35
  "scripts": {
35
36
  "build": "tsc",
36
- "typecheck": "tsc --noEmit",
37
+ "typecheck": "tsc --noEmit && tsc -p tsconfig.typetest.json",
37
38
  "test": "vitest run"
38
39
  }
39
40
  }