uilint-core 0.1.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/node.js ADDED
@@ -0,0 +1,162 @@
1
+ import {
2
+ OllamaClient,
3
+ buildAnalysisPrompt,
4
+ buildQueryPrompt,
5
+ buildStyleGuidePrompt,
6
+ buildValidationPrompt,
7
+ createColorRule,
8
+ createComponentRule,
9
+ createEmptyStyleGuide,
10
+ createSpacingRule,
11
+ createStyleSummary,
12
+ createTypographyRule,
13
+ deserializeStyles,
14
+ extractStyleValues,
15
+ extractStyles,
16
+ extractStylesFromDOM,
17
+ generateStyleGuideFromStyles,
18
+ getOllamaClient,
19
+ lintSnippet,
20
+ mergeStyleGuides,
21
+ parseStyleGuide,
22
+ parseStyleGuideSections,
23
+ serializeStyles,
24
+ styleGuideToMarkdown,
25
+ truncateHTML,
26
+ validateCode,
27
+ validateStyleGuide
28
+ } from "./chunk-B4HNWMXB.js";
29
+
30
+ // src/scanner/html-parser.ts
31
+ import { JSDOM } from "jsdom";
32
+ function parseHTML(html, options = {}) {
33
+ const { maxHtmlLength = 5e4 } = options;
34
+ const dom = new JSDOM(html, {
35
+ runScripts: "outside-only",
36
+ pretendToBeVisual: true
37
+ });
38
+ const { document, getComputedStyle } = dom.window;
39
+ const root = document.body || document.documentElement;
40
+ const styles = extractStyles(root, getComputedStyle);
41
+ const elementCount = root.querySelectorAll("*").length;
42
+ return {
43
+ html: truncateHTML(html, maxHtmlLength),
44
+ styles,
45
+ elementCount,
46
+ timestamp: Date.now()
47
+ };
48
+ }
49
+ function parseCLIInput(input) {
50
+ try {
51
+ const parsed = JSON.parse(input);
52
+ if (parsed.html && parsed.styles) {
53
+ return {
54
+ html: truncateHTML(parsed.html),
55
+ styles: deserializeStyles(parsed.styles),
56
+ elementCount: 0,
57
+ // Not available for pre-extracted
58
+ timestamp: Date.now()
59
+ };
60
+ } else if (parsed.html) {
61
+ return parseHTML(parsed.html);
62
+ }
63
+ } catch {
64
+ }
65
+ return parseHTML(input);
66
+ }
67
+ function isJSON(str) {
68
+ const trimmed = str.trim();
69
+ return trimmed.startsWith("{") || trimmed.startsWith("[");
70
+ }
71
+ async function readStdin() {
72
+ const chunks = [];
73
+ return new Promise((resolve, reject) => {
74
+ process.stdin.on("data", (chunk) => {
75
+ chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
76
+ });
77
+ process.stdin.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
78
+ process.stdin.on("error", reject);
79
+ });
80
+ }
81
+ function hasStdin() {
82
+ return !process.stdin.isTTY;
83
+ }
84
+
85
+ // src/styleguide/reader.ts
86
+ import { readFile, writeFile, mkdir } from "fs/promises";
87
+ import { existsSync } from "fs";
88
+ import { join, dirname } from "path";
89
+ var STYLEGUIDE_PATHS = [
90
+ ".uilint/styleguide.md",
91
+ "styleguide.md",
92
+ ".uilint/style-guide.md"
93
+ ];
94
+ function findStyleGuidePath(projectPath) {
95
+ for (const relativePath of STYLEGUIDE_PATHS) {
96
+ const fullPath = join(projectPath, relativePath);
97
+ if (existsSync(fullPath)) {
98
+ return fullPath;
99
+ }
100
+ }
101
+ return null;
102
+ }
103
+ async function readStyleGuide(path) {
104
+ return readFile(path, "utf-8");
105
+ }
106
+ async function readStyleGuideFromProject(projectPath) {
107
+ const path = findStyleGuidePath(projectPath);
108
+ if (!path) return null;
109
+ return readStyleGuide(path);
110
+ }
111
+ async function writeStyleGuide(path, content) {
112
+ const dir = dirname(path);
113
+ await mkdir(dir, { recursive: true });
114
+ await writeFile(path, content, "utf-8");
115
+ }
116
+ function getDefaultStyleGuidePath(projectPath) {
117
+ return join(projectPath, ".uilint", "styleguide.md");
118
+ }
119
+ function styleGuideExists(projectPath) {
120
+ return findStyleGuidePath(projectPath) !== null;
121
+ }
122
+ export {
123
+ OllamaClient,
124
+ STYLEGUIDE_PATHS,
125
+ buildAnalysisPrompt,
126
+ buildQueryPrompt,
127
+ buildStyleGuidePrompt,
128
+ buildValidationPrompt,
129
+ createColorRule,
130
+ createComponentRule,
131
+ createEmptyStyleGuide,
132
+ createSpacingRule,
133
+ createStyleSummary,
134
+ createTypographyRule,
135
+ deserializeStyles,
136
+ extractStyleValues,
137
+ extractStyles,
138
+ extractStylesFromDOM,
139
+ findStyleGuidePath,
140
+ generateStyleGuideFromStyles,
141
+ getDefaultStyleGuidePath,
142
+ getOllamaClient,
143
+ hasStdin,
144
+ isJSON,
145
+ lintSnippet,
146
+ mergeStyleGuides,
147
+ parseCLIInput,
148
+ parseHTML,
149
+ parseStyleGuide,
150
+ parseStyleGuideSections,
151
+ readStdin,
152
+ readStyleGuide,
153
+ readStyleGuideFromProject,
154
+ serializeStyles,
155
+ styleGuideExists,
156
+ styleGuideToMarkdown,
157
+ truncateHTML,
158
+ validateCode,
159
+ validateStyleGuide,
160
+ writeStyleGuide
161
+ };
162
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/scanner/html-parser.ts","../src/styleguide/reader.ts"],"sourcesContent":["/**\n * HTML parser for extracting styles using JSDOM\n * Used by CLI and Node.js environments\n */\n\nimport { JSDOM } from \"jsdom\";\nimport type { ExtractedStyles, DOMSnapshot, SerializedStyles } from \"../types.js\";\nimport { extractStyles, deserializeStyles, truncateHTML } from \"./style-extractor.js\";\n\nexport interface ParseOptions {\n /**\n * If true, tries to load and process linked stylesheets\n */\n loadStylesheets?: boolean;\n /**\n * Max length for HTML in snapshot\n */\n maxHtmlLength?: number;\n}\n\n/**\n * Parses raw HTML and extracts styles using JSDOM\n */\nexport function parseHTML(\n html: string,\n options: ParseOptions = {}\n): DOMSnapshot {\n const { maxHtmlLength = 50000 } = options;\n\n const dom = new JSDOM(html, {\n runScripts: \"outside-only\",\n pretendToBeVisual: true,\n });\n\n const { document, getComputedStyle } = dom.window;\n const root = document.body || document.documentElement;\n\n const styles = extractStyles(root, getComputedStyle);\n const elementCount = root.querySelectorAll(\"*\").length;\n\n return {\n html: truncateHTML(html, maxHtmlLength),\n styles,\n elementCount,\n timestamp: Date.now(),\n };\n}\n\n/**\n * Input format for CLI - can be raw HTML or pre-extracted JSON\n */\nexport interface CLIInput {\n html: string;\n styles?: SerializedStyles;\n}\n\n/**\n * Parses CLI input which can be either raw HTML or JSON with pre-extracted styles\n */\nexport function parseCLIInput(input: string): DOMSnapshot {\n // Try to parse as JSON first\n try {\n const parsed = JSON.parse(input) as CLIInput;\n \n if (parsed.html && parsed.styles) {\n // Pre-extracted styles from browser/test environment\n return {\n html: truncateHTML(parsed.html),\n styles: deserializeStyles(parsed.styles),\n elementCount: 0, // Not available for pre-extracted\n timestamp: Date.now(),\n };\n } else if (parsed.html) {\n // Just HTML in JSON format\n return parseHTML(parsed.html);\n }\n } catch {\n // Not JSON, treat as raw HTML\n }\n\n // Parse as raw HTML\n return parseHTML(input);\n}\n\n/**\n * Checks if a string looks like JSON\n */\nexport function isJSON(str: string): boolean {\n const trimmed = str.trim();\n return trimmed.startsWith(\"{\") || trimmed.startsWith(\"[\");\n}\n\n/**\n * Reads input from stdin\n */\nexport async function readStdin(): Promise<string> {\n const chunks: Uint8Array[] = [];\n \n return new Promise((resolve, reject) => {\n process.stdin.on(\"data\", (chunk: Buffer | string) => {\n chunks.push(typeof chunk === \"string\" ? Buffer.from(chunk) : chunk);\n });\n process.stdin.on(\"end\", () => resolve(Buffer.concat(chunks).toString(\"utf-8\")));\n process.stdin.on(\"error\", reject);\n });\n}\n\n/**\n * Detects if stdin has data\n */\nexport function hasStdin(): boolean {\n return !process.stdin.isTTY;\n}\n\n","/**\n * Style guide file operations\n */\n\nimport { readFile, writeFile, mkdir } from \"fs/promises\";\nimport { existsSync } from \"fs\";\nimport { join, dirname } from \"path\";\n\nexport const STYLEGUIDE_PATHS = [\n \".uilint/styleguide.md\",\n \"styleguide.md\",\n \".uilint/style-guide.md\",\n];\n\n/**\n * Finds the style guide file in a project\n */\nexport function findStyleGuidePath(projectPath: string): string | null {\n for (const relativePath of STYLEGUIDE_PATHS) {\n const fullPath = join(projectPath, relativePath);\n if (existsSync(fullPath)) {\n return fullPath;\n }\n }\n return null;\n}\n\n/**\n * Reads the style guide content\n */\nexport async function readStyleGuide(path: string): Promise<string> {\n return readFile(path, \"utf-8\");\n}\n\n/**\n * Reads style guide from project path, finding it automatically\n */\nexport async function readStyleGuideFromProject(\n projectPath: string\n): Promise<string | null> {\n const path = findStyleGuidePath(projectPath);\n if (!path) return null;\n return readStyleGuide(path);\n}\n\n/**\n * Writes style guide content to file\n */\nexport async function writeStyleGuide(path: string, content: string): Promise<void> {\n const dir = dirname(path);\n await mkdir(dir, { recursive: true });\n await writeFile(path, content, \"utf-8\");\n}\n\n/**\n * Gets the default style guide path for a project\n */\nexport function getDefaultStyleGuidePath(projectPath: string): string {\n return join(projectPath, \".uilint\", \"styleguide.md\");\n}\n\n/**\n * Checks if a style guide exists\n */\nexport function styleGuideExists(projectPath: string): boolean {\n return findStyleGuidePath(projectPath) !== null;\n}\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,SAAS,aAAa;AAkBf,SAAS,UACd,MACA,UAAwB,CAAC,GACZ;AACb,QAAM,EAAE,gBAAgB,IAAM,IAAI;AAElC,QAAM,MAAM,IAAI,MAAM,MAAM;AAAA,IAC1B,YAAY;AAAA,IACZ,mBAAmB;AAAA,EACrB,CAAC;AAED,QAAM,EAAE,UAAU,iBAAiB,IAAI,IAAI;AAC3C,QAAM,OAAO,SAAS,QAAQ,SAAS;AAEvC,QAAM,SAAS,cAAc,MAAM,gBAAgB;AACnD,QAAM,eAAe,KAAK,iBAAiB,GAAG,EAAE;AAEhD,SAAO;AAAA,IACL,MAAM,aAAa,MAAM,aAAa;AAAA,IACtC;AAAA,IACA;AAAA,IACA,WAAW,KAAK,IAAI;AAAA,EACtB;AACF;AAaO,SAAS,cAAc,OAA4B;AAExD,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,KAAK;AAE/B,QAAI,OAAO,QAAQ,OAAO,QAAQ;AAEhC,aAAO;AAAA,QACL,MAAM,aAAa,OAAO,IAAI;AAAA,QAC9B,QAAQ,kBAAkB,OAAO,MAAM;AAAA,QACvC,cAAc;AAAA;AAAA,QACd,WAAW,KAAK,IAAI;AAAA,MACtB;AAAA,IACF,WAAW,OAAO,MAAM;AAEtB,aAAO,UAAU,OAAO,IAAI;AAAA,IAC9B;AAAA,EACF,QAAQ;AAAA,EAER;AAGA,SAAO,UAAU,KAAK;AACxB;AAKO,SAAS,OAAO,KAAsB;AAC3C,QAAM,UAAU,IAAI,KAAK;AACzB,SAAO,QAAQ,WAAW,GAAG,KAAK,QAAQ,WAAW,GAAG;AAC1D;AAKA,eAAsB,YAA6B;AACjD,QAAM,SAAuB,CAAC;AAE9B,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAQ,MAAM,GAAG,QAAQ,CAAC,UAA2B;AACnD,aAAO,KAAK,OAAO,UAAU,WAAW,OAAO,KAAK,KAAK,IAAI,KAAK;AAAA,IACpE,CAAC;AACD,YAAQ,MAAM,GAAG,OAAO,MAAM,QAAQ,OAAO,OAAO,MAAM,EAAE,SAAS,OAAO,CAAC,CAAC;AAC9E,YAAQ,MAAM,GAAG,SAAS,MAAM;AAAA,EAClC,CAAC;AACH;AAKO,SAAS,WAAoB;AAClC,SAAO,CAAC,QAAQ,MAAM;AACxB;;;AC5GA,SAAS,UAAU,WAAW,aAAa;AAC3C,SAAS,kBAAkB;AAC3B,SAAS,MAAM,eAAe;AAEvB,IAAM,mBAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AACF;AAKO,SAAS,mBAAmB,aAAoC;AACrE,aAAW,gBAAgB,kBAAkB;AAC3C,UAAM,WAAW,KAAK,aAAa,YAAY;AAC/C,QAAI,WAAW,QAAQ,GAAG;AACxB,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAKA,eAAsB,eAAe,MAA+B;AAClE,SAAO,SAAS,MAAM,OAAO;AAC/B;AAKA,eAAsB,0BACpB,aACwB;AACxB,QAAM,OAAO,mBAAmB,WAAW;AAC3C,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,eAAe,IAAI;AAC5B;AAKA,eAAsB,gBAAgB,MAAc,SAAgC;AAClF,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACpC,QAAM,UAAU,MAAM,SAAS,OAAO;AACxC;AAKO,SAAS,yBAAyB,aAA6B;AACpE,SAAO,KAAK,aAAa,WAAW,eAAe;AACrD;AAKO,SAAS,iBAAiB,aAA8B;AAC7D,SAAO,mBAAmB,WAAW,MAAM;AAC7C;","names":[]}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "uilint-core",
3
+ "version": "0.1.0",
4
+ "description": "Core library for UILint - AI-powered UI consistency checking",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./node": {
15
+ "types": "./dist/node.d.ts",
16
+ "import": "./dist/node.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "engines": {
23
+ "node": ">=20.0.0"
24
+ },
25
+ "dependencies": {
26
+ "jsdom": "^27.4.0"
27
+ },
28
+ "devDependencies": {
29
+ "@types/jsdom": "^27.0.0",
30
+ "tsup": "^8.5.1",
31
+ "typescript": "^5.9.3"
32
+ },
33
+ "keywords": [
34
+ "ui",
35
+ "lint",
36
+ "consistency",
37
+ "design-system",
38
+ "ai",
39
+ "llm",
40
+ "ollama"
41
+ ],
42
+ "license": "MIT",
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
46
+ "scripts": {
47
+ "build": "tsup",
48
+ "dev": "tsup --watch",
49
+ "typecheck": "tsc --noEmit",
50
+ "lint": "eslint src/"
51
+ }
52
+ }