catom 1.3.0 → 2.0.0

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/css.d.ts CHANGED
@@ -1,5 +1,39 @@
1
- /// <reference types="node" />
2
- import { emitCSS } from "./plugin/cssTransform";
3
- export default function transformCSS(css?: string, ...plugins: any): Promise<Buffer>;
4
- export declare function autoPrefixCSS(css?: string, ...plugins: any): Promise<Buffer>;
5
- export { emitCSS };
1
+ export interface CSSRule {
2
+ className: string;
3
+ rule: string;
4
+ }
5
+ /**
6
+ * Generate a CSS rule from a property-value pair.
7
+ * This is a pure function - same input always gives same output.
8
+ *
9
+ * @param property - CSS property name (camelCase or kebab-case)
10
+ * @param value - CSS value
11
+ * @param context - Optional context like media query or pseudo selector
12
+ * @returns CSSRule with className and the full CSS rule string
13
+ */
14
+ export declare function generateRule(property: string, value: string | number, context?: {
15
+ media?: string;
16
+ pseudo?: string;
17
+ }): CSSRule;
18
+ export interface StyleObject {
19
+ [key: string]: string | number | StyleObject | undefined;
20
+ media?: Record<string, Record<string, string | number>>;
21
+ pseudo?: Record<string, Record<string, string | number>>;
22
+ }
23
+ export interface ProcessResult {
24
+ classNames: string[];
25
+ rules: string[];
26
+ }
27
+ /**
28
+ * Process a style object and return class names + CSS rules.
29
+ * Pure function - no side effects, no global state.
30
+ */
31
+ export declare function processStyleObject(obj: StyleObject, context?: {
32
+ media?: string;
33
+ pseudo?: string;
34
+ }): ProcessResult;
35
+ /**
36
+ * Deduplicate and sort CSS rules for consistent output.
37
+ */
38
+ export declare function dedupeRules(rules: string[]): string;
39
+ //# sourceMappingURL=css.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css.d.ts","sourceRoot":"","sources":["../src/css.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,OAAO;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C,OAAO,CA2BT;AAED,MAAM,WAAW,WAAW;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;CAC1D;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,WAAW,EAChB,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C,aAAa,CAiCf;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAEnD"}
package/dist/css.js CHANGED
@@ -1,35 +1,87 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.emitCSS = exports.autoPrefixCSS = void 0;
4
- const lightningcss_1 = require("lightningcss");
5
- const cssTransform_1 = require("./plugin/cssTransform");
6
- Object.defineProperty(exports, "emitCSS", { enumerable: true, get: function () { return cssTransform_1.emitCSS; } });
7
- async function transformCSS(css, ...plugins) {
8
- css = css || (0, cssTransform_1.emitCSS)();
9
- const { code } = (0, lightningcss_1.transform)({
10
- code: Buffer.from(css),
11
- drafts: { customMedia: true, nesting: true },
12
- minify: true,
13
- filename: "style.css",
14
- sourceMap: false,
15
- // browserslist hardcoded
16
- // probably change or manually audit
17
- targets: {
18
- android: 6422528,
19
- chrome: 6488064,
20
- edge: 6488064,
21
- firefox: 6356992,
22
- ie: 720896,
23
- ios_saf: 983552,
24
- opera: 5439488,
25
- safari: 983552,
26
- samsung: 1048576,
27
- },
28
- });
29
- return code;
1
+ import { murmur2 } from "./hash";
2
+ const KEBAB_CASE_RE = /([a-z0-9]|(?=[A-Z]))([A-Z])/g;
3
+ const NUMERIC_START = /^[0-9-]/;
4
+ function toKebabCase(prop) {
5
+ return prop.replace(KEBAB_CASE_RE, "$1-$2").toLowerCase();
30
6
  }
31
- exports.default = transformCSS;
32
- function autoPrefixCSS(css, ...plugins) {
33
- return transformCSS(css);
7
+ function sanitizeClassName(hash) {
8
+ // CSS class names can't start with a digit or hyphen
9
+ return NUMERIC_START.test(hash) ? `_${hash}` : hash;
10
+ }
11
+ /**
12
+ * Generate a CSS rule from a property-value pair.
13
+ * This is a pure function - same input always gives same output.
14
+ *
15
+ * @param property - CSS property name (camelCase or kebab-case)
16
+ * @param value - CSS value
17
+ * @param context - Optional context like media query or pseudo selector
18
+ * @returns CSSRule with className and the full CSS rule string
19
+ */
20
+ export function generateRule(property, value, context) {
21
+ const cssProp = toKebabCase(property.trim());
22
+ const cssValue = String(value).trim();
23
+ // The identity includes context so same property in different contexts gets different class
24
+ const identity = [
25
+ context?.media || "",
26
+ context?.pseudo || "",
27
+ cssProp,
28
+ cssValue,
29
+ ].join("|");
30
+ const className = sanitizeClassName(murmur2(identity));
31
+ const declaration = `${cssProp}:${cssValue}`;
32
+ let rule;
33
+ const selector = context?.pseudo
34
+ ? `.${className}${context.pseudo}`
35
+ : `.${className}`;
36
+ if (context?.media) {
37
+ rule = `@media ${context.media}{${selector}{${declaration}}}`;
38
+ }
39
+ else {
40
+ rule = `${selector}{${declaration}}`;
41
+ }
42
+ return { className, rule };
43
+ }
44
+ /**
45
+ * Process a style object and return class names + CSS rules.
46
+ * Pure function - no side effects, no global state.
47
+ */
48
+ export function processStyleObject(obj, context) {
49
+ const classNames = [];
50
+ const rules = [];
51
+ for (const key of Object.keys(obj)) {
52
+ const value = obj[key];
53
+ if (value === undefined)
54
+ continue;
55
+ if (key === "media" && typeof value === "object") {
56
+ // Handle media queries: media: { "(max-width: 768px)": { color: "red" } }
57
+ for (const query of Object.keys(value)) {
58
+ const mediaStyles = value[query];
59
+ const result = processStyleObject(mediaStyles, { media: query });
60
+ classNames.push(...result.classNames);
61
+ rules.push(...result.rules);
62
+ }
63
+ }
64
+ else if (key === "pseudo" && typeof value === "object") {
65
+ // Handle pseudo selectors: pseudo: { ":hover": { color: "blue" } }
66
+ for (const selector of Object.keys(value)) {
67
+ const pseudoStyles = value[selector];
68
+ const result = processStyleObject(pseudoStyles, { pseudo: selector });
69
+ classNames.push(...result.classNames);
70
+ rules.push(...result.rules);
71
+ }
72
+ }
73
+ else if (typeof value === "string" || typeof value === "number") {
74
+ // Regular CSS property
75
+ const { className, rule } = generateRule(key, value, context);
76
+ classNames.push(className);
77
+ rules.push(rule);
78
+ }
79
+ }
80
+ return { classNames, rules };
81
+ }
82
+ /**
83
+ * Deduplicate and sort CSS rules for consistent output.
84
+ */
85
+ export function dedupeRules(rules) {
86
+ return [...new Set(rules)].sort().join("\n");
34
87
  }
35
- exports.autoPrefixCSS = autoPrefixCSS;
package/dist/hash.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Murmur2 hash - deterministic hash function.
3
+ * Same input always produces the same output.
4
+ * Adapted from emotion-js.
5
+ */
6
+ export declare function murmur2(str: string): string;
7
+ //# sourceMappingURL=hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAqC3C"}
package/dist/hash.js ADDED
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Murmur2 hash - deterministic hash function.
3
+ * Same input always produces the same output.
4
+ * Adapted from emotion-js.
5
+ */
6
+ export function murmur2(str) {
7
+ let h = 0;
8
+ let k;
9
+ let i = 0;
10
+ let len = str.length;
11
+ for (; len >= 4; ++i, len -= 4) {
12
+ k =
13
+ (str.charCodeAt(i) & 0xff) |
14
+ ((str.charCodeAt(++i) & 0xff) << 8) |
15
+ ((str.charCodeAt(++i) & 0xff) << 16) |
16
+ ((str.charCodeAt(++i) & 0xff) << 24);
17
+ k = (k & 0xffff) * 0x5bd1e995 + (((k >>> 16) * 0xe995) << 16);
18
+ k ^= k >>> 24;
19
+ h =
20
+ ((k & 0xffff) * 0x5bd1e995 + (((k >>> 16) * 0xe995) << 16)) ^
21
+ ((h & 0xffff) * 0x5bd1e995 + (((h >>> 16) * 0xe995) << 16));
22
+ }
23
+ switch (len) {
24
+ case 3:
25
+ h ^= (str.charCodeAt(i + 2) & 0xff) << 16;
26
+ // fallthrough
27
+ case 2:
28
+ h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
29
+ // fallthrough
30
+ case 1:
31
+ h ^= str.charCodeAt(i) & 0xff;
32
+ h = (h & 0xffff) * 0x5bd1e995 + (((h >>> 16) * 0xe995) << 16);
33
+ }
34
+ h ^= h >>> 13;
35
+ h = (h & 0xffff) * 0x5bd1e995 + (((h >>> 16) * 0xe995) << 16);
36
+ return ((h ^ (h >>> 15)) >>> 0).toString(36);
37
+ }
package/dist/index.d.ts CHANGED
@@ -1,13 +1,38 @@
1
- import { Properties } from "csstype";
2
- declare const config: {
3
- allowRuntime: boolean;
4
- };
5
- declare function css(_styleRule: Properties & {
1
+ import type { Properties } from "csstype";
2
+ export { default } from "./plugin";
3
+ export type { CatomOptions } from "./plugin";
4
+ export { processStyleObject, generateRule, dedupeRules } from "./css";
5
+ export type { CSSRule, StyleObject, ProcessResult } from "./css";
6
+ /**
7
+ * Define atomic CSS styles. Transformed at build time to class names.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import { css } from "catom-vite";
12
+ *
13
+ * const className = css({
14
+ * display: "flex",
15
+ * alignItems: "center",
16
+ * padding: "1rem",
17
+ * media: {
18
+ * "(max-width: 768px)": {
19
+ * flexDirection: "column"
20
+ * }
21
+ * },
22
+ * pseudo: {
23
+ * ":hover": {
24
+ * backgroundColor: "#f0f0f0"
25
+ * }
26
+ * }
27
+ * });
28
+ * ```
29
+ */
30
+ export declare function css(_styles: Properties & {
6
31
  media?: {
7
32
  [query: string]: Properties;
8
33
  };
9
34
  pseudo?: {
10
- [psuedoProp: string]: Properties;
35
+ [selector: string]: Properties;
11
36
  };
12
37
  }): string;
13
- export { css, config };
38
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG7C,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACtE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,GAAG,CACjB,OAAO,EAAE,UAAU,GAAG;IACpB,KAAK,CAAC,EAAE;QAAE,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAAA;KAAE,CAAC;IACxC,MAAM,CAAC,EAAE;QAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAAA;KAAE,CAAC;CAC7C,GACA,MAAM,CAKR"}
package/dist/index.js CHANGED
@@ -1,11 +1,31 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.config = exports.css = void 0;
4
- const config = { allowRuntime: false };
5
- exports.config = config;
6
- function css(_styleRule) {
7
- if (!config.allowRuntime)
8
- throw new Error("Catom is in compile mode! Are you sure you ran your webpack transform correctly?");
9
- return "";
1
+ export { default } from "./plugin";
2
+ // Re-export utilities for advanced usage
3
+ export { processStyleObject, generateRule, dedupeRules } from "./css";
4
+ /**
5
+ * Define atomic CSS styles. Transformed at build time to class names.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { css } from "catom-vite";
10
+ *
11
+ * const className = css({
12
+ * display: "flex",
13
+ * alignItems: "center",
14
+ * padding: "1rem",
15
+ * media: {
16
+ * "(max-width: 768px)": {
17
+ * flexDirection: "column"
18
+ * }
19
+ * },
20
+ * pseudo: {
21
+ * ":hover": {
22
+ * backgroundColor: "#f0f0f0"
23
+ * }
24
+ * }
25
+ * });
26
+ * ```
27
+ */
28
+ export function css(_styles) {
29
+ throw new Error("catom css() was called at runtime. " +
30
+ "Ensure the catom-vite plugin is configured in vite.config.ts");
10
31
  }
11
- exports.css = css;
@@ -0,0 +1,16 @@
1
+ import type { Plugin } from "vite";
2
+ import { transform } from "lightningcss";
3
+ export interface CatomOptions {
4
+ /** Function name to transform. Default: "css" */
5
+ functionName?: string;
6
+ /** LightningCSS browser targets */
7
+ targets?: Parameters<typeof transform>[0]["targets"];
8
+ /** Minify CSS output. Default: true in production */
9
+ minify?: boolean;
10
+ /** File patterns to include. Default: /\.[jt]sx?$/ */
11
+ include?: RegExp | RegExp[];
12
+ /** File patterns to exclude */
13
+ exclude?: RegExp | RegExp[];
14
+ }
15
+ export default function catom(options?: CatomOptions): Plugin[];
16
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAKzC,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mCAAmC;IACnC,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACrD,qDAAqD;IACrD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC7B;AAWD,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,MAAM,EAAE,CAwHlE"}
package/dist/plugin.js ADDED
@@ -0,0 +1,114 @@
1
+ import { transform } from "lightningcss";
2
+ import AST from "unplugin-ast/vite";
3
+ import { createCatomTransformer } from "./transformer";
4
+ import { dedupeRules } from "./css";
5
+ const VIRTUAL_ID = "virtual:catom.css";
6
+ const RESOLVED_VIRTUAL_ID = "\0" + VIRTUAL_ID;
7
+ const DEFAULT_TARGETS = {
8
+ chrome: 80 << 16,
9
+ firefox: 80 << 16,
10
+ safari: 14 << 16,
11
+ };
12
+ export default function catom(options = {}) {
13
+ const { functionName = "css", targets = DEFAULT_TARGETS, minify, include = /\.[jt]sx?$/, exclude, } = options;
14
+ // Collect CSS rules from all files.
15
+ // Using a Set for automatic deduplication (deterministic hashing means same rule = same string)
16
+ const collectedRules = new Set();
17
+ let isDev = false;
18
+ // The AST plugin handles transformation
19
+ const astPlugin = AST({
20
+ include: Array.isArray(include) ? include : [include],
21
+ exclude: exclude ? (Array.isArray(exclude) ? exclude : [exclude]) : undefined,
22
+ enforce: "pre",
23
+ transformer: [
24
+ createCatomTransformer(functionName, (rules) => {
25
+ for (const rule of rules) {
26
+ collectedRules.add(rule);
27
+ }
28
+ }),
29
+ ],
30
+ });
31
+ // The CSS plugin handles virtual module and CSS emission
32
+ const cssPlugin = {
33
+ name: "catom:css",
34
+ enforce: "post",
35
+ configResolved(config) {
36
+ isDev = config.command === "serve";
37
+ },
38
+ buildStart() {
39
+ // Clear collected rules at the start of each build
40
+ collectedRules.clear();
41
+ },
42
+ resolveId(id) {
43
+ if (id === VIRTUAL_ID) {
44
+ return RESOLVED_VIRTUAL_ID;
45
+ }
46
+ },
47
+ load(id) {
48
+ if (id === RESOLVED_VIRTUAL_ID) {
49
+ // In dev, return empty - we inject via transformIndexHtml
50
+ // In build, this will be populated by generateBundle
51
+ return "";
52
+ }
53
+ },
54
+ // For dev: inject CSS into HTML
55
+ transformIndexHtml: {
56
+ order: "post",
57
+ handler() {
58
+ if (collectedRules.size === 0)
59
+ return [];
60
+ const css = dedupeRules([...collectedRules]);
61
+ const shouldMinify = minify ?? !isDev;
62
+ let finalCss;
63
+ try {
64
+ const { code } = transform({
65
+ code: Buffer.from(css),
66
+ filename: "catom.css",
67
+ minify: shouldMinify,
68
+ targets,
69
+ });
70
+ finalCss = code.toString();
71
+ }
72
+ catch {
73
+ // Fallback if lightningcss fails
74
+ finalCss = css;
75
+ }
76
+ return [
77
+ {
78
+ tag: "style",
79
+ attrs: { "data-catom": "" },
80
+ children: finalCss,
81
+ injectTo: "head",
82
+ },
83
+ ];
84
+ },
85
+ },
86
+ // For build: emit CSS file
87
+ generateBundle() {
88
+ if (collectedRules.size === 0)
89
+ return;
90
+ const css = dedupeRules([...collectedRules]);
91
+ const shouldMinify = minify ?? true;
92
+ let finalCss;
93
+ try {
94
+ const { code } = transform({
95
+ code: Buffer.from(css),
96
+ filename: "catom.css",
97
+ minify: shouldMinify,
98
+ targets,
99
+ });
100
+ finalCss = code.toString();
101
+ }
102
+ catch {
103
+ finalCss = css;
104
+ }
105
+ this.emitFile({
106
+ type: "asset",
107
+ fileName: "catom.css",
108
+ source: finalCss,
109
+ });
110
+ },
111
+ };
112
+ // Return both plugins - AST first (pre), then CSS (post)
113
+ return [astPlugin, cssPlugin];
114
+ }
@@ -0,0 +1,14 @@
1
+ import type { CallExpression } from "@babel/types";
2
+ import type { Transformer } from "unplugin-ast";
3
+ export interface TransformResult {
4
+ classNames: string;
5
+ rules: string[];
6
+ }
7
+ /**
8
+ * Creates an unplugin-ast transformer that finds css() calls
9
+ * and replaces them with class name strings.
10
+ *
11
+ * Returns the collected CSS rules separately for aggregation.
12
+ */
13
+ export declare function createCatomTransformer(functionName: string, onRules: (rules: string[]) => void): Transformer<CallExpression>;
14
+ //# sourceMappingURL=transformer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transformer.d.ts","sourceRoot":"","sources":["../src/transformer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAA0B,MAAM,cAAc,CAAC;AAC3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAoDhD,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,GACjC,WAAW,CAAC,cAAc,CAAC,CAkC7B"}
@@ -0,0 +1,87 @@
1
+ import { processStyleObject } from "./css";
2
+ /**
3
+ * Extract a JS value from a Babel AST node.
4
+ * Only handles static, compile-time constant values.
5
+ */
6
+ function extractValue(node) {
7
+ switch (node.type) {
8
+ case "StringLiteral":
9
+ return node.value;
10
+ case "NumericLiteral":
11
+ return node.value;
12
+ case "ObjectExpression":
13
+ return extractObject(node);
14
+ case "TSAsExpression":
15
+ return extractValue(node.expression);
16
+ case "Identifier":
17
+ if (node.name === "undefined")
18
+ return undefined;
19
+ throw new Error(`Cannot evaluate identifier "${node.name}" at compile time`);
20
+ default:
21
+ throw new Error(`Cannot evaluate ${node.type} at compile time`);
22
+ }
23
+ }
24
+ function extractObject(node) {
25
+ const result = {};
26
+ for (const prop of node.properties) {
27
+ if (prop.type === "SpreadElement") {
28
+ // Handle spread of object literals
29
+ if (prop.argument.type === "ObjectExpression") {
30
+ Object.assign(result, extractObject(prop.argument));
31
+ }
32
+ else {
33
+ throw new Error("Spread elements must be object literals at compile time");
34
+ }
35
+ }
36
+ else if (prop.type === "ObjectProperty") {
37
+ let key;
38
+ if (prop.key.type === "Identifier") {
39
+ key = prop.key.name;
40
+ }
41
+ else if (prop.key.type === "StringLiteral") {
42
+ key = prop.key.value;
43
+ }
44
+ else {
45
+ throw new Error(`Unsupported key type: ${prop.key.type}`);
46
+ }
47
+ result[key] = extractValue(prop.value);
48
+ }
49
+ }
50
+ return result;
51
+ }
52
+ /**
53
+ * Creates an unplugin-ast transformer that finds css() calls
54
+ * and replaces them with class name strings.
55
+ *
56
+ * Returns the collected CSS rules separately for aggregation.
57
+ */
58
+ export function createCatomTransformer(functionName, onRules) {
59
+ return {
60
+ onNode(node) {
61
+ return (node.type === "CallExpression" &&
62
+ node.callee.type === "Identifier" &&
63
+ node.callee.name === functionName);
64
+ },
65
+ transform(node) {
66
+ const arg = node.arguments[0];
67
+ if (!arg || arg.type !== "ObjectExpression") {
68
+ throw new Error(`${functionName}() requires an object literal argument`);
69
+ }
70
+ try {
71
+ const styleObj = extractObject(arg);
72
+ const { classNames, rules } = processStyleObject(styleObj);
73
+ // Report rules to the plugin
74
+ onRules(rules);
75
+ // Return a string literal with the class names
76
+ return {
77
+ type: "StringLiteral",
78
+ value: classNames.join(" "),
79
+ };
80
+ }
81
+ catch (err) {
82
+ const message = err instanceof Error ? err.message : String(err);
83
+ throw new Error(`Failed to process ${functionName}(): ${message}`);
84
+ }
85
+ },
86
+ };
87
+ }
package/package.json CHANGED
@@ -1,39 +1,46 @@
1
1
  {
2
2
  "name": "catom",
3
- "version": "1.3.0",
4
- "description": "0 runtime CSS in JS tool",
3
+ "version": "2.0.0",
4
+ "description": "Zero-runtime atomic CSS-in-JS for Vite",
5
+ "type": "module",
5
6
  "main": "dist/index.js",
6
- "scripts": {
7
- "prepublishOnly": "npm run build",
8
- "prebuild": "rm -rf ./dist",
9
- "build": "tsc --build tsconfig.json"
10
- },
11
- "repository": {
12
- "type": "git",
13
- "url": "git+https://github.com/Hydrophobefireman/catom.git"
14
- },
15
- "license": "MIT",
16
- "bugs": {
17
- "url": "https://github.com/Hydrophobefireman/catom/issues"
18
- },
19
7
  "module": "dist/index.js",
20
8
  "types": "dist/index.d.ts",
21
- "sideEffects": false,
22
- "homepage": "https://github.com/Hydrophobefireman/catom#readme",
23
- "devDependencies": {
24
- "@babel/types": "^7.20.2",
25
- "@types/babel__template": "^7.4.1",
26
- "@types/babel__traverse": "^7.18.2",
27
- "@types/estree": "^1.0.0",
28
- "@types/node": "^18.11.9",
29
- "typescript": "^4.8.4"
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
30
14
  },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "dev": "tsc --watch",
21
+ "prepublishOnly": "npm run build"
22
+ },
23
+ "keywords": [
24
+ "vite",
25
+ "vite-plugin",
26
+ "css-in-js",
27
+ "atomic-css",
28
+ "zero-runtime"
29
+ ],
30
+ "license": "MIT",
31
31
  "peerDependencies": {
32
+ "vite": "^4.0.0 || ^5.0.0 || ^6.0.0",
32
33
  "lightningcss": "^1.16.0"
33
34
  },
34
35
  "dependencies": {
35
- "@babel/template": "^7.18.10",
36
- "@babel/traverse": "^7.20.1",
36
+ "unplugin-ast": "^0.15.4",
37
37
  "csstype": "^3.1.1"
38
+ },
39
+ "devDependencies": {
40
+ "@babel/types": "^7.26.0",
41
+ "@types/node": "^20.0.0",
42
+ "typescript": "^5.0.0",
43
+ "vite": "^5.0.0",
44
+ "lightningcss": "^1.28.0"
38
45
  }
39
46
  }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2020 Hydrophobefireman
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/README.md DELETED
@@ -1,150 +0,0 @@
1
- # Catom
2
-
3
- ## A 0 runtime css in ~~js~~ css tool
4
-
5
- ### Stage: Pre Alpha ([Caveats](#caveats))
6
-
7
- Catom allows you to write CSS in your javascript/typescript file and creates highly optimized CSS out of it.
8
-
9
- Each rule creates a unique class definition out of it and it gives you 100% freedom about where to put your generated css bundle.
10
-
11
- Your javascript code has 0 references to any styles and all that's left is are the compiled hashed clasnames as a string.
12
-
13
- It's framework agnostic as it emits pure CSS and leaves out just the classnames
14
-
15
- ## Example
16
-
17
- somewhere in our App.js
18
-
19
- ```javascript
20
- import { css } from "catom";
21
-
22
- const styledButton = css({
23
- color: "#ff0000",
24
- borderRadius: "5px",
25
- padding: "4px",
26
- });
27
- const styledDiv = css({ color: "blue", borderRadius: "5px", padding: "4px" });
28
-
29
- function App() {
30
- return (
31
- <div className={styledDiv}>
32
- <button className={styledButton}>Hi</button>
33
- </div>
34
- );
35
- }
36
- ```
37
-
38
- **Css generated:**
39
-
40
- ```css
41
- ._6da32 {
42
- color: #ff0000;
43
- }
44
- .quva1q {
45
- border-radius: 5px;
46
- }
47
- ._2rlxtj {
48
- padding: 4px;
49
- }
50
- ._14ksm7b {
51
- color: blue;
52
- }
53
- ```
54
-
55
- **App.js:**
56
-
57
- ```js
58
- const styledButton = "_6da32 quva1q _2rlxtj";
59
- const styledDiv = "_14ksm7b quva1q _2rlxtj";
60
- ....
61
- ```
62
-
63
- As we had only 4 unique rules, catom generated only 4 classes.
64
-
65
- Catom also supports media queries and pseudo properties passing them in an object
66
-
67
- ```javascript
68
- const mediaQuery = css({
69
- media: { "only screen and (max-width:500px)": { color: "red" } },
70
- });
71
- const pseudoQuery = css({ pseudo: { ":hover": { color: "green" } } });
72
- ```
73
-
74
- # Installation and Usage
75
-
76
- Install using npm or yarn
77
-
78
- ```
79
- npm i catom -D
80
- ```
81
-
82
- In your babel config:
83
-
84
- ```json
85
- {
86
- "plugins": [
87
- "catom/babelPlugin"
88
- `....
89
- ]
90
-
91
- }
92
- ```
93
-
94
- As catom doesn't really interact with your build tool at all, it's your job to inject the generated style.
95
-
96
- Here's an example of how you can use it with HTMLWebpackPlugin.
97
-
98
- `webpack.confg.js`
99
-
100
- ```js
101
- const { emitCSS } = require("catom/css");
102
- // ...
103
- module.exports = {
104
- plugins: [
105
- new HtmlWebpackPlugin({
106
- templateParameters: async function templateParametersGenerator(
107
- compilation,
108
- files,
109
- tags,
110
- options
111
- ) {
112
- return {
113
- compilation,
114
- webpackConfig: compilation.options,
115
- htmlWebpackPlugin: {
116
- tags,
117
- files,
118
- options: Object.assign(options, {
119
- emitCSS,
120
- }),
121
- },
122
- };
123
- },
124
- }),
125
- ],
126
- };
127
- ```
128
-
129
- and then inject it using a template parameter.
130
-
131
- ```html
132
- <head>
133
- <style>
134
- <%= htmlWebpackPlugin.options.emitCSS() %>
135
- </style>
136
- </head>
137
- ```
138
-
139
- it also allows you to use postCSS plugins by importing the `transformCSS` and/or `autoPrefixCSS` functions
140
-
141
- # 0 Runtime
142
-
143
- Catom ships with 0 js code in your bundle. In fact the first thing the babel transform does, is to [remove](https://github.com/Hydrophobefireman/catom/blob/378fefef245c399a550edb60916c051f87f671ea/babelPlugin.ts#L17) all imports of the `css` function from your code.
144
-
145
- # Caveats
146
-
147
- - It's just something I threw together because I wanted it for a project
148
- - Not even close to production ready
149
- - Since it works with AST, it does not allow you to use variable in the values (In work)
150
- - No support for keyframes as of now
package/babelPlugin.d.ts DELETED
@@ -1 +0,0 @@
1
- export * from "./dist/babelPlugin";
package/babelPlugin.js DELETED
@@ -1 +0,0 @@
1
- module.exports = require("./dist/babelPlugin");
package/css.d.ts DELETED
@@ -1 +0,0 @@
1
- export * from "./dist/css";
package/css.js DELETED
@@ -1 +0,0 @@
1
- module.exports = require("./dist/css");
@@ -1,4 +0,0 @@
1
- import { Visitor } from "@babel/traverse";
2
- export default function catomBabelPlugin(): {
3
- visitor: Visitor;
4
- };
@@ -1,63 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- const template = __importStar(require("@babel/template"));
27
- const astObject_1 = require("./plugin/astObject");
28
- function handleExpression(path, expression, removeName) {
29
- if (!expression)
30
- return;
31
- if (expression.type === "CallExpression") {
32
- return commonInject(path, expression, {
33
- name: removeName,
34
- });
35
- }
36
- }
37
- function catomBabelPlugin() {
38
- let removeName = "css";
39
- return {
40
- visitor: {
41
- CallExpression(path) {
42
- return handleExpression(path, path.node, removeName);
43
- },
44
- },
45
- };
46
- }
47
- exports.default = catomBabelPlugin;
48
- function commonInject(path, right, options) {
49
- const callee = right.callee;
50
- if (callee && callee.type === "Identifier") {
51
- if (callee.name === options.name) {
52
- const arg0 = right.arguments[0];
53
- return injectDependency(path, arg0);
54
- }
55
- }
56
- }
57
- function injectDependency(path, arg0) {
58
- if (arg0.type === "ObjectExpression") {
59
- let retArray = [];
60
- (0, astObject_1.parseObjectExpression)(arg0, retArray);
61
- path.replaceWith(template.statement.ast(JSON.stringify(retArray.join(" "))));
62
- }
63
- }
@@ -1,3 +0,0 @@
1
- import { Hashable } from "./constants";
2
- import * as babel from "@babel/types";
3
- export declare function parseObjectExpression(object: babel.ObjectExpression, retArray: Array<string>, hashable?: Hashable): any;
@@ -1,62 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseObjectExpression = void 0;
4
- const cssTransform_1 = require("./cssTransform");
5
- function parseObjectExpression(object, retArray, hashable) {
6
- return object.properties.forEach((p) => handleProperties(p, retArray, hashable));
7
- }
8
- exports.parseObjectExpression = parseObjectExpression;
9
- function handleSpread(spread, retArray, hashable) {
10
- const argument = spread.argument;
11
- if (argument.type === "ObjectExpression") {
12
- return parseObjectExpression(argument, retArray, hashable);
13
- }
14
- throw Error(`Cannot parse ${spread.type}. Catom compiler only accepts compile time constant values`);
15
- }
16
- function handleProperties(propertyOrSpread, retArray, hashable) {
17
- if (propertyOrSpread.type === "SpreadElement") {
18
- return handleSpread(propertyOrSpread, retArray, hashable);
19
- }
20
- let { key, value } = propertyOrSpread;
21
- if (value.type === "TSAsExpression")
22
- value = value.expression;
23
- let keyName;
24
- if (key.type === "StringLiteral") {
25
- keyName = key.value;
26
- }
27
- else if (key.type === "Identifier") {
28
- keyName = key.name;
29
- }
30
- else {
31
- return throwErr();
32
- }
33
- const isMedia = keyName === "media";
34
- const isPseudo = keyName === "pseudo";
35
- const canAcceptObjectLiteralInValue = isMedia || isPseudo;
36
- if (value.type === "StringLiteral" || value.type === "NumericLiteral") {
37
- if (canAcceptObjectLiteralInValue)
38
- throwErr("Need an object literal for media query or pseudo selector");
39
- return retArray.push((0, cssTransform_1.createValueHash)(keyName, value.value, hashable));
40
- }
41
- if (canAcceptObjectLiteralInValue && value.type === "ObjectExpression") {
42
- return value.properties.forEach((prop) => handleMediaOrPseudoProperties(prop, retArray, isMedia, isPseudo));
43
- }
44
- throwErr();
45
- }
46
- function handleMediaOrPseudoProperties(property, retArray, isMedia, isPseudo) {
47
- if (property.type === "ObjectProperty") {
48
- const { key, value } = property;
49
- let keyName;
50
- if (key.type === "StringLiteral")
51
- keyName = key.value;
52
- else if (key.type === "Identifier")
53
- keyName = key.name;
54
- if (value.type === "ObjectExpression") {
55
- return parseObjectExpression(value, retArray, (isMedia && { media: keyName }) || (isPseudo && { pseudo: keyName }));
56
- }
57
- }
58
- throwErr();
59
- }
60
- function throwErr(err) {
61
- throw TypeError(err || "Catom only accepts literals and compile time constant values");
62
- }
@@ -1,17 +0,0 @@
1
- export { Program } from "estree";
2
- export declare type PropMap = Map<string, CSSProps>;
3
- export interface AtomicCSSOptions {
4
- transpileFunctionName: "css";
5
- }
6
- export interface CSSProps {
7
- class: string;
8
- cssRule: string;
9
- }
10
- export interface Hashable {
11
- media?: string;
12
- pseudo?: string;
13
- }
14
- export declare const NAME = "AtomicCssWebpackPlugin";
15
- export declare const defaultOptions: AtomicCSSOptions;
16
- export declare const KEBAB_CASE_REGEXP: RegExp;
17
- export declare const PREFIX_WITH_UNDERSCORE: string[];
@@ -1,9 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PREFIX_WITH_UNDERSCORE = exports.KEBAB_CASE_REGEXP = exports.defaultOptions = exports.NAME = void 0;
4
- exports.NAME = "AtomicCssWebpackPlugin";
5
- exports.defaultOptions = {
6
- transpileFunctionName: "css",
7
- };
8
- exports.KEBAB_CASE_REGEXP = /([a-z0-9]|(?=[A-Z]))([A-Z])/g;
9
- exports.PREFIX_WITH_UNDERSCORE = "1234567890-".split("");
@@ -1,3 +0,0 @@
1
- import { Hashable } from "./constants";
2
- export declare function createValueHash(key: string, unparsed: string | number, hashable?: Hashable): string;
3
- export declare function emitCSS(): string;
@@ -1,92 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.emitCSS = exports.createValueHash = void 0;
4
- const constants_1 = require("./constants");
5
- const hash_1 = require("./hash");
6
- const CSS_PROPERTY_MAP = new Map();
7
- const MEDIA_QUERY_MAP = new Map();
8
- const PSEUDO_SELECTOR_MAP = new Map();
9
- // function clearMaps(): void {
10
- // CSS_PROPERTY_MAP.clear();
11
- // MEDIA_QUERY_MAP.clear();
12
- // PSEUDO_SELECTOR_MAP.clear();
13
- // }
14
- function toCSSProp(prop) {
15
- return prop.replace(constants_1.KEBAB_CASE_REGEXP, "$1-$2").toLowerCase();
16
- }
17
- function makeCSSCompat(str) {
18
- if (constants_1.PREFIX_WITH_UNDERSCORE.indexOf(str[0]) > -1)
19
- return `_${str}`;
20
- return str;
21
- }
22
- const sanitizeRegExp = /([^\w]|_)/g;
23
- function createValueHash(key, unparsed, hashable) {
24
- key = key.trim();
25
- const value = String(unparsed).trim();
26
- const MEDIA_QUERY = hashable && hashable.media;
27
- const PSEUDO_SELECTOR = hashable && hashable.pseudo;
28
- const isSpec = MEDIA_QUERY || PSEUDO_SELECTOR;
29
- // example: const rawCSSRule = "margin:auto;"
30
- const rawCSSRule = `${toCSSProp(key)}:${value};`;
31
- // a unique rule will be one with a different media/pseudo rule + key&value
32
- const identity = ((hashable && (MEDIA_QUERY || PSEUDO_SELECTOR)) || "").trim() + rawCSSRule;
33
- let cache;
34
- const $map = isSpec && MEDIA_QUERY ? MEDIA_QUERY_MAP : PSEUDO_SELECTOR_MAP;
35
- let fetchMap;
36
- if ($map) {
37
- fetchMap = $map.get(isSpec);
38
- if (!fetchMap) {
39
- fetchMap = new Map();
40
- $map.set(isSpec, fetchMap);
41
- }
42
- }
43
- if (isSpec) {
44
- cache = fetchMap.get(identity);
45
- }
46
- else {
47
- cache = CSS_PROPERTY_MAP.get(identity);
48
- }
49
- if (cache)
50
- return cache.class;
51
- const hash = makeCSSCompat((0, hash_1.murmur2)(identity));
52
- const obj = { class: hash, cssRule: rawCSSRule };
53
- if (isSpec) {
54
- fetchMap.set(identity, obj);
55
- }
56
- else {
57
- CSS_PROPERTY_MAP.set(identity, obj);
58
- }
59
- return hash;
60
- }
61
- exports.createValueHash = createValueHash;
62
- const toCSS = (m) => Array.from(m.values())
63
- .map((v) => `.${v.class} { ${v.cssRule} }`)
64
- .sort()
65
- .join("\n");
66
- function mergeDuplicateRules(value, dedupedPropMap, suffix = "") {
67
- const cls = `.${value.class}${suffix}`;
68
- const rule = value.cssRule;
69
- let arr = dedupedPropMap.get(rule);
70
- if (!arr) {
71
- arr = new Set();
72
- dedupedPropMap.set(rule, arr);
73
- }
74
- arr.add(cls);
75
- }
76
- function emitCSS() {
77
- const dedupedPropMap = new Map();
78
- Array.from(CSS_PROPERTY_MAP.values()).forEach((v) => mergeDuplicateRules(v, dedupedPropMap));
79
- Array.from(PSEUDO_SELECTOR_MAP.entries()).forEach(([k, v]) => Array.from(v.values())
80
- .sort()
81
- .forEach((prop) => mergeDuplicateRules(prop, dedupedPropMap, k)));
82
- const mediaQueries = Array.from(MEDIA_QUERY_MAP.entries())
83
- .map(([k, v]) => `@media ${k} {\n${toCSS(v)}\n}\n`)
84
- .sort()
85
- .join("\n");
86
- const cssProps = Array.from(dedupedPropMap.entries())
87
- .map(([rule, classNames]) => `${Array.from(classNames).join(",\n")}{ ${rule} }`)
88
- .sort()
89
- .join("\n");
90
- return [cssProps, mediaQueries].join("\n");
91
- }
92
- exports.emitCSS = emitCSS;
@@ -1 +0,0 @@
1
- export declare function murmur2(str: string): string;
@@ -1,50 +0,0 @@
1
- "use strict";
2
- // from https://github.com/emotion-js/emotion/blob/master/packages/hash/src/index.js
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.murmur2 = void 0;
5
- function murmur2(str) {
6
- // 'm' and 'r' are mixing constants generated offline.
7
- // They're not really 'magic', they just happen to work well.
8
- // const m = 0x5bd1e995;
9
- // const r = 24;
10
- // Initialize the hash
11
- var h = 0;
12
- // Mix 4 bytes at a time into the hash
13
- var k, i = 0, len = str.length;
14
- for (; len >= 4; ++i, len -= 4) {
15
- k =
16
- (str.charCodeAt(i) & 0xff) |
17
- ((str.charCodeAt(++i) & 0xff) << 8) |
18
- ((str.charCodeAt(++i) & 0xff) << 16) |
19
- ((str.charCodeAt(++i) & 0xff) << 24);
20
- k =
21
- /* Math.imul(k, m): */
22
- (k & 0xffff) * 0x5bd1e995 + (((k >>> 16) * 0xe995) << 16);
23
- k ^= /* k >>> r: */ k >>> 24;
24
- h =
25
- /* Math.imul(k, m): */
26
- ((k & 0xffff) * 0x5bd1e995 + (((k >>> 16) * 0xe995) << 16)) ^
27
- /* Math.imul(h, m): */
28
- ((h & 0xffff) * 0x5bd1e995 + (((h >>> 16) * 0xe995) << 16));
29
- }
30
- // Handle the last few bytes of the input array
31
- switch (len) {
32
- case 3:
33
- h ^= (str.charCodeAt(i + 2) & 0xff) << 16;
34
- case 2:
35
- h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
36
- case 1:
37
- h ^= str.charCodeAt(i) & 0xff;
38
- h =
39
- /* Math.imul(h, m): */
40
- (h & 0xffff) * 0x5bd1e995 + (((h >>> 16) * 0xe995) << 16);
41
- }
42
- // Do a few final mixes of the hash to ensure the last few
43
- // bytes are well-incorporated.
44
- h ^= h >>> 13;
45
- h =
46
- /* Math.imul(h, m): */
47
- (h & 0xffff) * 0x5bd1e995 + (((h >>> 16) * 0xe995) << 16);
48
- return ((h ^ (h >>> 15)) >>> 0).toString(36);
49
- }
50
- exports.murmur2 = murmur2;
package/tsconfig.json DELETED
@@ -1,14 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "module": "CommonJS",
4
- "alwaysStrict": true,
5
- "declaration": true,
6
- "incremental": true,
7
- "target": "ESNext",
8
- "outDir": "dist/",
9
- "moduleResolution": "Node",
10
- "esModuleInterop": true
11
- },
12
- "exclude": ["dist/", "./css.js", "./babelPlugin.js"],
13
- "include": ["./src/**/*.ts"]
14
- }