typewritingclass-next 0.1.5 → 0.2.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.
package/dist/index.cjs CHANGED
@@ -40,8 +40,24 @@ module.exports = __toCommonJS(src_exports);
40
40
  // src/TWCStyles.tsx
41
41
  var import_react = __toESM(require("react"), 1);
42
42
  var import_server = require("typewritingclass-react/server");
43
- function TWCStyles() {
44
- const css = (0, import_server.getStyleSheet)();
43
+ var import_fs = require("fs");
44
+ var import_path = require("path");
45
+ function TWCStyles({ cssFile } = {}) {
46
+ const runtimeCss = (0, import_server.getStyleSheet)();
47
+ let compiledCss = "";
48
+ try {
49
+ const filePath = (0, import_path.resolve)(process.cwd(), cssFile || ".next/twc.css");
50
+ compiledCss = (0, import_fs.readFileSync)(filePath, "utf-8");
51
+ } catch {
52
+ try {
53
+ compiledCss = (0, import_fs.readFileSync)(
54
+ (0, import_path.resolve)(process.cwd(), ".next/cache/twc/compiled.css"),
55
+ "utf-8"
56
+ );
57
+ } catch {
58
+ }
59
+ }
60
+ const css = [compiledCss, runtimeCss].filter(Boolean).join("\n");
45
61
  return import_react.default.createElement("style", {
46
62
  "data-twc": "",
47
63
  dangerouslySetInnerHTML: { __html: css }
package/dist/index.d.cts CHANGED
@@ -2,12 +2,17 @@ import React from 'react';
2
2
  export { useStyle } from 'typewritingclass-react';
3
3
  export { getStyleSheet, getStyleTag } from 'typewritingclass-react/server';
4
4
 
5
+ interface TWCStylesProps {
6
+ /** Path to the compiler-generated CSS file. Default: ".next/twc.css" */
7
+ cssFile?: string;
8
+ }
5
9
  /**
6
10
  * Server component that injects typewritingclass CSS into the document head.
7
11
  *
12
+ * Combines both compiler-extracted CSS (from the build-time Rust transform)
13
+ * and runtime-generated CSS (from dynamic styles resolved during SSR).
14
+ *
8
15
  * Place this in your root layout to ensure all styles are included during SSR.
9
- * This component is safe to use in React Server Components — it has no client-side
10
- * dependencies.
11
16
  *
12
17
  * @example app/layout.tsx
13
18
  * ```tsx
@@ -25,6 +30,6 @@ export { getStyleSheet, getStyleTag } from 'typewritingclass-react/server';
25
30
  * }
26
31
  * ```
27
32
  */
28
- declare function TWCStyles(): React.JSX.Element;
33
+ declare function TWCStyles({ cssFile }?: TWCStylesProps): React.JSX.Element;
29
34
 
30
35
  export { TWCStyles };
package/dist/index.d.ts CHANGED
@@ -2,12 +2,17 @@ import React from 'react';
2
2
  export { useStyle } from 'typewritingclass-react';
3
3
  export { getStyleSheet, getStyleTag } from 'typewritingclass-react/server';
4
4
 
5
+ interface TWCStylesProps {
6
+ /** Path to the compiler-generated CSS file. Default: ".next/twc.css" */
7
+ cssFile?: string;
8
+ }
5
9
  /**
6
10
  * Server component that injects typewritingclass CSS into the document head.
7
11
  *
12
+ * Combines both compiler-extracted CSS (from the build-time Rust transform)
13
+ * and runtime-generated CSS (from dynamic styles resolved during SSR).
14
+ *
8
15
  * Place this in your root layout to ensure all styles are included during SSR.
9
- * This component is safe to use in React Server Components — it has no client-side
10
- * dependencies.
11
16
  *
12
17
  * @example app/layout.tsx
13
18
  * ```tsx
@@ -25,6 +30,6 @@ export { getStyleSheet, getStyleTag } from 'typewritingclass-react/server';
25
30
  * }
26
31
  * ```
27
32
  */
28
- declare function TWCStyles(): React.JSX.Element;
33
+ declare function TWCStyles({ cssFile }?: TWCStylesProps): React.JSX.Element;
29
34
 
30
35
  export { TWCStyles };
package/dist/index.js CHANGED
@@ -1,8 +1,24 @@
1
1
  // src/TWCStyles.tsx
2
2
  import React from "react";
3
3
  import { getStyleSheet } from "typewritingclass-react/server";
4
- function TWCStyles() {
5
- const css = getStyleSheet();
4
+ import { readFileSync } from "fs";
5
+ import { resolve } from "path";
6
+ function TWCStyles({ cssFile } = {}) {
7
+ const runtimeCss = getStyleSheet();
8
+ let compiledCss = "";
9
+ try {
10
+ const filePath = resolve(process.cwd(), cssFile || ".next/twc.css");
11
+ compiledCss = readFileSync(filePath, "utf-8");
12
+ } catch {
13
+ try {
14
+ compiledCss = readFileSync(
15
+ resolve(process.cwd(), ".next/cache/twc/compiled.css"),
16
+ "utf-8"
17
+ );
18
+ } catch {
19
+ }
20
+ }
21
+ const css = [compiledCss, runtimeCss].filter(Boolean).join("\n");
6
22
  return React.createElement("style", {
7
23
  "data-twc": "",
8
24
  dangerouslySetInnerHTML: { __html: css }
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/loader.ts
21
+ var loader_exports = {};
22
+ __export(loader_exports, {
23
+ default: () => twcLoader
24
+ });
25
+ module.exports = __toCommonJS(loader_exports);
26
+
27
+ // ../../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js
28
+ var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
29
+ var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
30
+
31
+ // src/loader.ts
32
+ var import_module = require("module");
33
+ var import_path = require("path");
34
+ var import_url = require("url");
35
+ var import_fs = require("fs");
36
+ var import_loadTheme = require("typewritingclass-compiler/loadTheme");
37
+ var require2 = (0, import_module.createRequire)(importMetaUrl);
38
+ var __dirname = (0, import_path.dirname)((0, import_url.fileURLToPath)(importMetaUrl));
39
+ var compilerDir = (0, import_path.dirname)(require2.resolve("typewritingclass-compiler/package.json"));
40
+ var native = require2((0, import_path.resolve)(compilerDir, "index.node"));
41
+ var themeInput = null;
42
+ var nextLayer = 0;
43
+ var fileRules = /* @__PURE__ */ new Map();
44
+ var fileLayers = /* @__PURE__ */ new Map();
45
+ function twcLoader(source) {
46
+ const filename = this.resourcePath;
47
+ const options = this.getOptions?.() ?? {};
48
+ const strict = options.strict ?? true;
49
+ const outputFile = options.outputFile ?? ".next/twc.css";
50
+ if (!source.includes("typewritingclass")) return source;
51
+ if (filename.includes("node_modules")) return source;
52
+ if (!/\.[jt]sx?$/.test(filename)) return source;
53
+ if (!themeInput) {
54
+ themeInput = (0, import_loadTheme.loadThemeSync)();
55
+ const cacheFile = (0, import_path.resolve)(".next/cache/twc/rules-cache.json");
56
+ if ((0, import_fs.existsSync)(cacheFile)) {
57
+ try {
58
+ const cached = JSON.parse((0, import_fs.readFileSync)(cacheFile, "utf-8"));
59
+ for (const [key, value] of Object.entries(cached.fileRules)) {
60
+ fileRules.set(key, value);
61
+ }
62
+ for (const [key, value] of Object.entries(cached.fileLayers)) {
63
+ fileLayers.set(key, value);
64
+ }
65
+ nextLayer = Math.max(nextLayer, cached.nextLayer ?? 0);
66
+ } catch {
67
+ }
68
+ }
69
+ }
70
+ const layer = fileLayers.get(filename) ?? nextLayer;
71
+ try {
72
+ const result = native.transform(source, filename, layer, themeInput, strict);
73
+ if (!fileLayers.has(filename)) {
74
+ fileLayers.set(filename, layer);
75
+ }
76
+ nextLayer = Math.max(nextLayer, result.nextLayer);
77
+ for (const diag of result.diagnostics) {
78
+ const location = `${filename}:${diag.line}:${diag.column}`;
79
+ if (diag.severity === "error") {
80
+ this.emitError(new Error(`[typewritingclass] ${location} - ${diag.message}`));
81
+ } else {
82
+ this.emitWarning(new Error(`[typewritingclass] ${location} - ${diag.message}`));
83
+ }
84
+ }
85
+ if (result.rules.length > 0) {
86
+ fileRules.set(filename, result.rules.map((r) => r.cssText));
87
+ const allRules = [];
88
+ for (const rules of fileRules.values()) {
89
+ allRules.push(...rules);
90
+ }
91
+ const css = native.generateCss(JSON.stringify(allRules));
92
+ if (css) {
93
+ const outputDir = (0, import_path.dirname)((0, import_path.resolve)(outputFile));
94
+ (0, import_fs.mkdirSync)(outputDir, { recursive: true });
95
+ (0, import_fs.writeFileSync)((0, import_path.resolve)(outputFile), css, "utf-8");
96
+ const cacheDir = (0, import_path.resolve)(".next/cache/twc");
97
+ (0, import_fs.mkdirSync)(cacheDir, { recursive: true });
98
+ (0, import_fs.writeFileSync)((0, import_path.resolve)(cacheDir, "compiled.css"), css, "utf-8");
99
+ (0, import_fs.writeFileSync)(
100
+ (0, import_path.resolve)(cacheDir, "rules-cache.json"),
101
+ JSON.stringify({
102
+ fileRules: Object.fromEntries(fileRules),
103
+ fileLayers: Object.fromEntries(fileLayers),
104
+ nextLayer
105
+ }),
106
+ "utf-8"
107
+ );
108
+ }
109
+ }
110
+ return result.code;
111
+ } catch (err) {
112
+ const message = err instanceof Error ? err.message : String(err);
113
+ console.error(`[typewritingclass] Failed to transform ${filename}: ${message}`);
114
+ return source;
115
+ }
116
+ }
@@ -0,0 +1,11 @@
1
+ interface TwcLoaderOptions {
2
+ outputFile?: string;
3
+ strict?: boolean;
4
+ }
5
+ /**
6
+ * Custom webpack loader that runs the native Rust compiler transform.
7
+ * Only transforms the source code — leaves TypeScript/JSX to SWC/Babel.
8
+ */
9
+ declare function twcLoader(this: any, source: string): string;
10
+
11
+ export { type TwcLoaderOptions, twcLoader as default };
@@ -0,0 +1,11 @@
1
+ interface TwcLoaderOptions {
2
+ outputFile?: string;
3
+ strict?: boolean;
4
+ }
5
+ /**
6
+ * Custom webpack loader that runs the native Rust compiler transform.
7
+ * Only transforms the source code — leaves TypeScript/JSX to SWC/Babel.
8
+ */
9
+ declare function twcLoader(this: any, source: string): string;
10
+
11
+ export { type TwcLoaderOptions, twcLoader as default };
package/dist/loader.js ADDED
@@ -0,0 +1,89 @@
1
+ // src/loader.ts
2
+ import { createRequire } from "module";
3
+ import { resolve, dirname } from "path";
4
+ import { fileURLToPath } from "url";
5
+ import { writeFileSync, readFileSync, mkdirSync, existsSync } from "fs";
6
+ import { loadThemeSync } from "typewritingclass-compiler/loadTheme";
7
+ var require2 = createRequire(import.meta.url);
8
+ var __dirname = dirname(fileURLToPath(import.meta.url));
9
+ var compilerDir = dirname(require2.resolve("typewritingclass-compiler/package.json"));
10
+ var native = require2(resolve(compilerDir, "index.node"));
11
+ var themeInput = null;
12
+ var nextLayer = 0;
13
+ var fileRules = /* @__PURE__ */ new Map();
14
+ var fileLayers = /* @__PURE__ */ new Map();
15
+ function twcLoader(source) {
16
+ const filename = this.resourcePath;
17
+ const options = this.getOptions?.() ?? {};
18
+ const strict = options.strict ?? true;
19
+ const outputFile = options.outputFile ?? ".next/twc.css";
20
+ if (!source.includes("typewritingclass")) return source;
21
+ if (filename.includes("node_modules")) return source;
22
+ if (!/\.[jt]sx?$/.test(filename)) return source;
23
+ if (!themeInput) {
24
+ themeInput = loadThemeSync();
25
+ const cacheFile = resolve(".next/cache/twc/rules-cache.json");
26
+ if (existsSync(cacheFile)) {
27
+ try {
28
+ const cached = JSON.parse(readFileSync(cacheFile, "utf-8"));
29
+ for (const [key, value] of Object.entries(cached.fileRules)) {
30
+ fileRules.set(key, value);
31
+ }
32
+ for (const [key, value] of Object.entries(cached.fileLayers)) {
33
+ fileLayers.set(key, value);
34
+ }
35
+ nextLayer = Math.max(nextLayer, cached.nextLayer ?? 0);
36
+ } catch {
37
+ }
38
+ }
39
+ }
40
+ const layer = fileLayers.get(filename) ?? nextLayer;
41
+ try {
42
+ const result = native.transform(source, filename, layer, themeInput, strict);
43
+ if (!fileLayers.has(filename)) {
44
+ fileLayers.set(filename, layer);
45
+ }
46
+ nextLayer = Math.max(nextLayer, result.nextLayer);
47
+ for (const diag of result.diagnostics) {
48
+ const location = `${filename}:${diag.line}:${diag.column}`;
49
+ if (diag.severity === "error") {
50
+ this.emitError(new Error(`[typewritingclass] ${location} - ${diag.message}`));
51
+ } else {
52
+ this.emitWarning(new Error(`[typewritingclass] ${location} - ${diag.message}`));
53
+ }
54
+ }
55
+ if (result.rules.length > 0) {
56
+ fileRules.set(filename, result.rules.map((r) => r.cssText));
57
+ const allRules = [];
58
+ for (const rules of fileRules.values()) {
59
+ allRules.push(...rules);
60
+ }
61
+ const css = native.generateCss(JSON.stringify(allRules));
62
+ if (css) {
63
+ const outputDir = dirname(resolve(outputFile));
64
+ mkdirSync(outputDir, { recursive: true });
65
+ writeFileSync(resolve(outputFile), css, "utf-8");
66
+ const cacheDir = resolve(".next/cache/twc");
67
+ mkdirSync(cacheDir, { recursive: true });
68
+ writeFileSync(resolve(cacheDir, "compiled.css"), css, "utf-8");
69
+ writeFileSync(
70
+ resolve(cacheDir, "rules-cache.json"),
71
+ JSON.stringify({
72
+ fileRules: Object.fromEntries(fileRules),
73
+ fileLayers: Object.fromEntries(fileLayers),
74
+ nextLayer
75
+ }),
76
+ "utf-8"
77
+ );
78
+ }
79
+ }
80
+ return result.code;
81
+ } catch (err) {
82
+ const message = err instanceof Error ? err.message : String(err);
83
+ console.error(`[typewritingclass] Failed to transform ${filename}: ${message}`);
84
+ return source;
85
+ }
86
+ }
87
+ export {
88
+ twcLoader as default
89
+ };
package/dist/plugin.cjs CHANGED
@@ -23,11 +23,21 @@ __export(plugin_exports, {
23
23
  withTwc: () => withTwc
24
24
  });
25
25
  module.exports = __toCommonJS(plugin_exports);
26
+
27
+ // ../../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js
28
+ var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
29
+ var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
30
+
31
+ // src/plugin.ts
32
+ var import_path = require("path");
33
+ var import_url = require("url");
34
+ var __dirname = (0, import_path.dirname)((0, import_url.fileURLToPath)(importMetaUrl));
26
35
  function withTwc(nextConfig = {}, options = {}) {
27
- const babelOptions = {
36
+ const loaderOptions = {
28
37
  outputFile: options.outputFile ?? ".next/twc.css",
29
38
  strict: options.strict ?? true
30
39
  };
40
+ const loaderPath = (0, import_path.resolve)(__dirname, "loader.cjs");
31
41
  return {
32
42
  ...nextConfig,
33
43
  webpack(config, context) {
@@ -35,12 +45,8 @@ function withTwc(nextConfig = {}, options = {}) {
35
45
  test: /\.[jt]sx?$/,
36
46
  exclude: /node_modules/,
37
47
  use: {
38
- loader: "babel-loader",
39
- options: {
40
- plugins: [
41
- ["typewritingclass-babel", babelOptions]
42
- ]
43
- }
48
+ loader: loaderPath,
49
+ options: loaderOptions
44
50
  }
45
51
  });
46
52
  if (typeof nextConfig.webpack === "function") {
package/dist/plugin.d.cts CHANGED
@@ -11,8 +11,9 @@ interface TwcNextPluginOptions {
11
11
  /**
12
12
  * Next.js plugin that integrates typewritingclass build-time CSS extraction.
13
13
  *
14
- * Configures webpack to run the typewritingclass Babel transform on your source
15
- * files, extracting static CSS at build time.
14
+ * Configures webpack with a custom loader that runs the native Rust compiler
15
+ * on source files, extracting static CSS at build time. Works alongside
16
+ * Next.js's SWC compiler — no Babel required.
16
17
  *
17
18
  * @example next.config.mjs
18
19
  * ```js
@@ -22,15 +23,6 @@ interface TwcNextPluginOptions {
22
23
  * // your next config
23
24
  * })
24
25
  * ```
25
- *
26
- * @example With options
27
- * ```js
28
- * import { withTwc } from 'typewritingclass-next/plugin'
29
- *
30
- * export default withTwc({
31
- * // your next config
32
- * }, { strict: true })
33
- * ```
34
26
  */
35
27
  declare function withTwc(nextConfig?: NextConfig, options?: TwcNextPluginOptions): NextConfig;
36
28
 
package/dist/plugin.d.ts CHANGED
@@ -11,8 +11,9 @@ interface TwcNextPluginOptions {
11
11
  /**
12
12
  * Next.js plugin that integrates typewritingclass build-time CSS extraction.
13
13
  *
14
- * Configures webpack to run the typewritingclass Babel transform on your source
15
- * files, extracting static CSS at build time.
14
+ * Configures webpack with a custom loader that runs the native Rust compiler
15
+ * on source files, extracting static CSS at build time. Works alongside
16
+ * Next.js's SWC compiler — no Babel required.
16
17
  *
17
18
  * @example next.config.mjs
18
19
  * ```js
@@ -22,15 +23,6 @@ interface TwcNextPluginOptions {
22
23
  * // your next config
23
24
  * })
24
25
  * ```
25
- *
26
- * @example With options
27
- * ```js
28
- * import { withTwc } from 'typewritingclass-next/plugin'
29
- *
30
- * export default withTwc({
31
- * // your next config
32
- * }, { strict: true })
33
- * ```
34
26
  */
35
27
  declare function withTwc(nextConfig?: NextConfig, options?: TwcNextPluginOptions): NextConfig;
36
28
 
package/dist/plugin.js CHANGED
@@ -1,9 +1,13 @@
1
1
  // src/plugin.ts
2
+ import { resolve, dirname } from "path";
3
+ import { fileURLToPath } from "url";
4
+ var __dirname = dirname(fileURLToPath(import.meta.url));
2
5
  function withTwc(nextConfig = {}, options = {}) {
3
- const babelOptions = {
6
+ const loaderOptions = {
4
7
  outputFile: options.outputFile ?? ".next/twc.css",
5
8
  strict: options.strict ?? true
6
9
  };
10
+ const loaderPath = resolve(__dirname, "loader.cjs");
7
11
  return {
8
12
  ...nextConfig,
9
13
  webpack(config, context) {
@@ -11,12 +15,8 @@ function withTwc(nextConfig = {}, options = {}) {
11
15
  test: /\.[jt]sx?$/,
12
16
  exclude: /node_modules/,
13
17
  use: {
14
- loader: "babel-loader",
15
- options: {
16
- plugins: [
17
- ["typewritingclass-babel", babelOptions]
18
- ]
19
- }
18
+ loader: loaderPath,
19
+ options: loaderOptions
20
20
  }
21
21
  });
22
22
  if (typeof nextConfig.webpack === "function") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typewritingclass-next",
3
- "version": "0.1.5",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -27,6 +27,16 @@
27
27
  "types": "./dist/plugin.d.cts",
28
28
  "default": "./dist/plugin.cjs"
29
29
  }
30
+ },
31
+ "./loader": {
32
+ "import": {
33
+ "types": "./dist/loader.d.ts",
34
+ "default": "./dist/loader.js"
35
+ },
36
+ "require": {
37
+ "types": "./dist/loader.d.cts",
38
+ "default": "./dist/loader.cjs"
39
+ }
30
40
  }
31
41
  },
32
42
  "main": "./dist/index.cjs",
@@ -38,19 +48,19 @@
38
48
  "peerDependencies": {
39
49
  "next": "^13 || ^14 || ^15",
40
50
  "react": "^18 || ^19",
41
- "typewritingclass": "0.2.6",
42
- "typewritingclass-react": "0.2.2"
51
+ "typewritingclass": "0.3.1",
52
+ "typewritingclass-react": "0.2.4"
43
53
  },
44
54
  "dependencies": {
45
- "typewritingclass-babel": "0.1.4"
55
+ "typewritingclass-compiler": "0.2.1"
46
56
  },
47
57
  "devDependencies": {
48
58
  "next": "^15.0.0",
49
59
  "react": "^19.0.0",
50
60
  "@types/react": "^19.0.0",
51
61
  "typescript": "^5.7.3",
52
- "typewritingclass": "0.2.6",
53
- "typewritingclass-react": "0.2.2"
62
+ "typewritingclass": "0.3.1",
63
+ "typewritingclass-react": "0.2.4"
54
64
  },
55
65
  "scripts": {
56
66
  "build": "tsup",