@lass-lang/core 0.0.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/CHANGELOG.md ADDED
@@ -0,0 +1,23 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+ - Initial release preparation
12
+
13
+ ## [0.0.1] - 2026-02-07
14
+
15
+ ### Added
16
+ - Initial development version
17
+ - Two-zone model with `---` separator for JS preamble
18
+ - Dollar substitution (`$name` variables)
19
+ - Expression interpolation (`{{ expr }}`)
20
+ - Property lookup (`@(prop)` and `@prop` shorthand)
21
+ - Style blocks (`@{ }` CSS fragments from JS)
22
+ - Single-line comment stripping (`//`)
23
+ - Error handling with `LassTranspileError` and error categories
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Long-lazuli
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 ADDED
@@ -0,0 +1,93 @@
1
+ # @lass-lang/core
2
+
3
+ Core transpiler for the Lass language. Converts `.lass` files to executable JavaScript modules that produce CSS.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @lass-lang/core
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { transpile } from '@lass-lang/core';
15
+
16
+ // Transpile Lass source to a JavaScript module
17
+ const source = `
18
+ .button {
19
+ color: blue;
20
+ padding: 8px 16px;
21
+ }
22
+ `;
23
+
24
+ const { code } = transpile(source);
25
+ // code is a JS module string that exports the CSS
26
+
27
+ // Execute the transpiled code to get CSS
28
+ const dataUrl = `data:text/javascript;charset=utf-8,${encodeURIComponent(code)}`;
29
+ const module = await import(dataUrl);
30
+ console.log(module.default); // The CSS string
31
+ ```
32
+
33
+ ## API
34
+
35
+ ### `transpile(source, options?)`
36
+
37
+ Transpiles Lass source code to a JavaScript module.
38
+
39
+ **Parameters:**
40
+ - `source` (string): The Lass source code
41
+ - `options` (TranspileOptions, optional):
42
+ - `filename` (string): Source file path for error messages
43
+ - `sourceMap` (boolean): Generate source maps (future)
44
+
45
+ **Returns:** `TranspileResult`
46
+ - `code` (string): The generated JavaScript module code
47
+ - `map` (string, optional): Source map (future)
48
+
49
+ ### Error Handling
50
+
51
+ ```typescript
52
+ import { LassTranspileError, ErrorCategory } from '@lass-lang/core';
53
+
54
+ try {
55
+ const { code } = transpile(source, { filename: 'style.lass' });
56
+ } catch (error) {
57
+ if (error instanceof LassTranspileError) {
58
+ console.error(`${error.category} error at line ${error.location.line}`);
59
+ }
60
+ }
61
+ ```
62
+
63
+ **Error Categories:**
64
+ - `ErrorCategory.SCAN` - Scanner-level errors
65
+ - `ErrorCategory.SYMBOL` - Symbol detection errors
66
+ - `ErrorCategory.SYNTAX` - Syntax errors
67
+
68
+ ## Features
69
+
70
+ The Lass transpiler supports the full language feature set:
71
+
72
+ - **Two-zone model** - Use `---` separator to define a JS preamble zone followed by a CSS zone
73
+ - **Dollar substitution** - `$name` text substitution from preamble variables
74
+ - **Expression interpolation** - `{{ expr }}` for inline JavaScript expressions
75
+ - **Property lookup** - `@(prop)` or `@prop` shorthand to reference previously defined CSS property values
76
+ - **Style blocks** - `@{ }` to embed CSS fragments generated from JavaScript
77
+ - **Comment stripping** - `//` single-line comments are removed from output
78
+
79
+ ## TypeScript Support
80
+
81
+ For TypeScript projects using `.lass` files, add type declarations:
82
+
83
+ ```typescript
84
+ // lass.d.ts
85
+ declare module '*.lass' {
86
+ const css: string;
87
+ export default css;
88
+ }
89
+ ```
90
+
91
+ ## License
92
+
93
+ MIT
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Runtime helper constants for @lass-lang/core
3
+ *
4
+ * These are JavaScript code strings that get injected into the transpiled
5
+ * output. They provide runtime behavior for Lass symbols.
6
+ */
7
+ /**
8
+ * Runtime helper function for {{ expression }} output.
9
+ * Story 2.4: Array auto-join and null/undefined handling.
10
+ * Enhanced: Falsy suppression and multi-line re-indentation.
11
+ *
12
+ * - null/undefined/false -> '' (React-style silent handling)
13
+ * - arrays -> recursively flattened, filtered, stringified, then joined
14
+ * - If any element contains newline, join with newline (multi-line blocks)
15
+ * - Otherwise join with empty string (inline values)
16
+ * - other values -> String coercion
17
+ * - Multi-line strings are re-indented using the optional indent parameter
18
+ */
19
+ export declare const LASS_SCRIPT_EXPRESSION_HELPER = "const __lassScriptExpression = (v, indent = '') => { if (v == null || v === false) return ''; if (Array.isArray(v)) { const a = v.flat(Infinity).map(x => (x == null || x === false) ? '' : String(x)).filter(x => x); const sep = a.some(x => x.includes('\\n')) ? '\\n' : ''; return a.join(sep); } const s = String(v); if (!indent || !s.includes('\\n')) return s; return s.split('\\n').map((l, i) => i === 0 ? l : indent + l).join('\\n'); };";
20
+ /**
21
+ * Runtime helper function for $param variable substitution.
22
+ * Story 4.1: Variable Substitution
23
+ *
24
+ * - null -> 'unset' (CSS-meaningful fallback)
25
+ * - undefined or ReferenceError -> preserve '$name' unchanged
26
+ * - other values -> String coercion
27
+ *
28
+ * The getter function (g) delays evaluation so we can catch ReferenceError
29
+ * for non-existent variables.
30
+ */
31
+ export declare const LASS_SCRIPT_LOOKUP_HELPER = "const __lassScriptLookup = (n, g) => { try { const v = g(); return v === null ? 'unset' : v === undefined ? '$' + n : v; } catch { return '$' + n; } };";
32
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,6BAA6B,0bAA0b,CAAC;AAEre;;;;;;;;;;GAUG;AACH,eAAO,MAAM,yBAAyB,4JAA4J,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Runtime helper constants for @lass-lang/core
3
+ *
4
+ * These are JavaScript code strings that get injected into the transpiled
5
+ * output. They provide runtime behavior for Lass symbols.
6
+ */
7
+ /**
8
+ * Runtime helper function for {{ expression }} output.
9
+ * Story 2.4: Array auto-join and null/undefined handling.
10
+ * Enhanced: Falsy suppression and multi-line re-indentation.
11
+ *
12
+ * - null/undefined/false -> '' (React-style silent handling)
13
+ * - arrays -> recursively flattened, filtered, stringified, then joined
14
+ * - If any element contains newline, join with newline (multi-line blocks)
15
+ * - Otherwise join with empty string (inline values)
16
+ * - other values -> String coercion
17
+ * - Multi-line strings are re-indented using the optional indent parameter
18
+ */
19
+ export const LASS_SCRIPT_EXPRESSION_HELPER = `const __lassScriptExpression = (v, indent = '') => { if (v == null || v === false) return ''; if (Array.isArray(v)) { const a = v.flat(Infinity).map(x => (x == null || x === false) ? '' : String(x)).filter(x => x); const sep = a.some(x => x.includes('\\n')) ? '\\n' : ''; return a.join(sep); } const s = String(v); if (!indent || !s.includes('\\n')) return s; return s.split('\\n').map((l, i) => i === 0 ? l : indent + l).join('\\n'); };`;
20
+ /**
21
+ * Runtime helper function for $param variable substitution.
22
+ * Story 4.1: Variable Substitution
23
+ *
24
+ * - null -> 'unset' (CSS-meaningful fallback)
25
+ * - undefined or ReferenceError -> preserve '$name' unchanged
26
+ * - other values -> String coercion
27
+ *
28
+ * The getter function (g) delays evaluation so we can catch ReferenceError
29
+ * for non-existent variables.
30
+ */
31
+ export const LASS_SCRIPT_LOOKUP_HELPER = `const __lassScriptLookup = (n, g) => { try { const v = g(); return v === null ? 'unset' : v === undefined ? '$' + n : v; } catch { return '$' + n; } };`;
32
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,ubAAub,CAAC;AAEre;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,yJAAyJ,CAAC"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Shared context tracking utilities for protected zones in CSS.
3
+ *
4
+ * Story 4.2: Extracted to reduce code duplication between
5
+ * findDollarVariablesStatic() and findStyleLookupShorthandsStatic().
6
+ *
7
+ * Protected contexts are zones where Lass symbols ($param, @prop) should
8
+ * NOT be detected:
9
+ * - String literals ("..." or '...')
10
+ * - Block comments (slash-star ... star-slash)
11
+ *
12
+ * Note: url() is NOT a protected context - only strings and comments are.
13
+ */
14
+ /**
15
+ * Tracks context state for protected zones during scanning.
16
+ */
17
+ export interface ContextState {
18
+ /** Currently inside a string literal ("..." or '...') */
19
+ inString: boolean;
20
+ /** The quote character that opened the current string */
21
+ stringChar: string;
22
+ /** Currently inside a block comment */
23
+ inBlockComment: boolean;
24
+ }
25
+ /**
26
+ * Creates a fresh context state for scanning.
27
+ */
28
+ export declare function createContextState(): ContextState;
29
+ /**
30
+ * Checks if currently in a protected context (string or block comment).
31
+ * Protected contexts prevent symbol detection for $param and @prop.
32
+ *
33
+ * Note: url() is NOT a protected context - only strings and comments are.
34
+ */
35
+ export declare function isInProtectedContext(state: ContextState): boolean;
36
+ /**
37
+ * Updates context state based on current character.
38
+ * Handles block comments and string literals with proper escape handling.
39
+ *
40
+ * @param text - The full text being scanned
41
+ * @param index - Current character index
42
+ * @param state - Context state to update (mutated)
43
+ * @returns Number of characters consumed (1 normally, 2 for comment markers)
44
+ */
45
+ export declare function updateContextState(text: string, index: number, state: ContextState): number;
46
+ //# sourceMappingURL=context-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-tracker.d.ts","sourceRoot":"","sources":["../src/context-tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,yDAAyD;IACzD,QAAQ,EAAE,OAAO,CAAC;IAClB,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,YAAY,CAMjD;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAEjE;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,YAAY,GAClB,MAAM,CAoCR"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Shared context tracking utilities for protected zones in CSS.
3
+ *
4
+ * Story 4.2: Extracted to reduce code duplication between
5
+ * findDollarVariablesStatic() and findStyleLookupShorthandsStatic().
6
+ *
7
+ * Protected contexts are zones where Lass symbols ($param, @prop) should
8
+ * NOT be detected:
9
+ * - String literals ("..." or '...')
10
+ * - Block comments (slash-star ... star-slash)
11
+ *
12
+ * Note: url() is NOT a protected context - only strings and comments are.
13
+ */
14
+ /**
15
+ * Creates a fresh context state for scanning.
16
+ */
17
+ export function createContextState() {
18
+ return {
19
+ inString: false,
20
+ stringChar: '',
21
+ inBlockComment: false,
22
+ };
23
+ }
24
+ /**
25
+ * Checks if currently in a protected context (string or block comment).
26
+ * Protected contexts prevent symbol detection for $param and @prop.
27
+ *
28
+ * Note: url() is NOT a protected context - only strings and comments are.
29
+ */
30
+ export function isInProtectedContext(state) {
31
+ return state.inString || state.inBlockComment;
32
+ }
33
+ /**
34
+ * Updates context state based on current character.
35
+ * Handles block comments and string literals with proper escape handling.
36
+ *
37
+ * @param text - The full text being scanned
38
+ * @param index - Current character index
39
+ * @param state - Context state to update (mutated)
40
+ * @returns Number of characters consumed (1 normally, 2 for comment markers)
41
+ */
42
+ export function updateContextState(text, index, state) {
43
+ const char = text[index];
44
+ const nextChar = text[index + 1];
45
+ // Track block comment start: /*
46
+ if (!state.inString && !state.inBlockComment && char === '/' && nextChar === '*') {
47
+ state.inBlockComment = true;
48
+ return 2;
49
+ }
50
+ // Track block comment end: */
51
+ if (state.inBlockComment && char === '*' && nextChar === '/') {
52
+ state.inBlockComment = false;
53
+ return 2;
54
+ }
55
+ // Track string literals (only when not in comment)
56
+ if (!state.inBlockComment && (char === '"' || char === "'")) {
57
+ if (!state.inString) {
58
+ state.inString = true;
59
+ state.stringChar = char;
60
+ }
61
+ else if (char === state.stringChar) {
62
+ // Check for escaped quote - count consecutive backslashes
63
+ let backslashCount = 0;
64
+ for (let j = index - 1; j >= 0 && text[j] === '\\'; j--) {
65
+ backslashCount++;
66
+ }
67
+ // If odd number of backslashes, quote is escaped
68
+ if (backslashCount % 2 === 0) {
69
+ state.inString = false;
70
+ }
71
+ }
72
+ return 1;
73
+ }
74
+ return 1;
75
+ }
76
+ //# sourceMappingURL=context-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-tracker.js","sourceRoot":"","sources":["../src/context-tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAcH;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO;QACL,QAAQ,EAAE,KAAK;QACf,UAAU,EAAE,EAAE;QACd,cAAc,EAAE,KAAK;KACtB,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAmB;IACtD,OAAO,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,cAAc,CAAC;AAChD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAY,EACZ,KAAa,EACb,KAAmB;IAEnB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAE,CAAC;IAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IAEjC,gCAAgC;IAChC,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,IAAI,IAAI,KAAK,GAAG,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;QACjF,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC;QAC5B,OAAO,CAAC,CAAC;IACX,CAAC;IAED,8BAA8B;IAC9B,IAAI,KAAK,CAAC,cAAc,IAAI,IAAI,KAAK,GAAG,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;QAC7D,KAAK,CAAC,cAAc,GAAG,KAAK,CAAC;QAC7B,OAAO,CAAC,CAAC;IACX,CAAC;IAED,mDAAmD;IACnD,IAAI,CAAC,KAAK,CAAC,cAAc,IAAI,CAAC,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC5D,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YACpB,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;YACtB,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;QAC1B,CAAC;aAAM,IAAI,IAAI,KAAK,KAAK,CAAC,UAAU,EAAE,CAAC;YACrC,0DAA0D;YAC1D,IAAI,cAAc,GAAG,CAAC,CAAC;YACvB,KAAK,IAAI,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;gBACxD,cAAc,EAAE,CAAC;YACnB,CAAC;YACD,iDAAiD;YACjD,IAAI,cAAc,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC7B,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC;YACzB,CAAC;QACH,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC;IAED,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Error handling infrastructure for Lass transpiler.
3
+ *
4
+ * Provides structured error types with source location information
5
+ * for actionable error messages following NFR-ERROR requirements.
6
+ */
7
+ /**
8
+ * Error categories for Lass transpilation errors.
9
+ * Used to classify errors and provide appropriate guidance.
10
+ */
11
+ export declare enum ErrorCategory {
12
+ /** Scanner-level errors (context tracking, unexpected characters) */
13
+ SCAN = "SCAN",
14
+ /** Symbol detection errors ($name, {{ }}, @{ }, etc.) */
15
+ SYMBOL = "SYMBOL",
16
+ /** Syntax errors (malformed Lass constructs) */
17
+ SYNTAX = "SYNTAX"
18
+ }
19
+ /**
20
+ * Source location information for error reporting.
21
+ * Provides precise positioning within the source file.
22
+ */
23
+ export interface SourceLocation {
24
+ /** Line number (1-based) */
25
+ line: number;
26
+ /** Column number (1-based) */
27
+ column: number;
28
+ /** Character offset from start of file (0-based) */
29
+ offset: number;
30
+ }
31
+ /**
32
+ * Extended location with optional file path.
33
+ */
34
+ export interface FileLocation extends SourceLocation {
35
+ /** Source file path (if available) */
36
+ filename?: string;
37
+ }
38
+ /**
39
+ * Custom error class for Lass transpilation errors.
40
+ *
41
+ * Provides structured error information including:
42
+ * - Source file path (when provided)
43
+ * - Line and column numbers
44
+ * - Error category for classification
45
+ * - Actionable error description
46
+ *
47
+ * Error message format follows NFR-ERROR requirements:
48
+ * "[filename:]line:column - [CATEGORY] description"
49
+ */
50
+ export declare class LassTranspileError extends Error {
51
+ /** Error category for classification */
52
+ readonly category: ErrorCategory;
53
+ /** Source location where the error occurred */
54
+ readonly location: FileLocation;
55
+ /**
56
+ * Creates a new transpilation error.
57
+ *
58
+ * @param message - Actionable error description
59
+ * @param category - Error category (SCAN, SYMBOL, SYNTAX)
60
+ * @param location - Source location information
61
+ */
62
+ constructor(message: string, category: ErrorCategory, location: FileLocation);
63
+ /**
64
+ * Creates an error with just a source position.
65
+ * Useful when filename is not available.
66
+ */
67
+ static at(message: string, category: ErrorCategory, line: number, column: number, offset?: number): LassTranspileError;
68
+ /**
69
+ * Creates an error with file path and source position.
70
+ */
71
+ static atFile(message: string, category: ErrorCategory, filename: string, line: number, column: number, offset?: number): LassTranspileError;
72
+ }
73
+ /**
74
+ * Helper to format source location for display.
75
+ *
76
+ * @param location - Source location to format
77
+ * @returns Formatted string like "filename:line:column" or "line:column"
78
+ */
79
+ export declare function formatLocation(location: FileLocation): string;
80
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,oBAAY,aAAa;IACvB,qEAAqE;IACrE,IAAI,SAAS;IACb,yDAAyD;IACzD,MAAM,WAAW;IACjB,gDAAgD;IAChD,MAAM,WAAW;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,YAAa,SAAQ,cAAc;IAClD,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IAEjC,+CAA+C;IAC/C,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAEhC;;;;;;OAMG;gBACS,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY;IAiB5E;;;OAGG;IACH,MAAM,CAAC,EAAE,CACP,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,aAAa,EACvB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,MAAU,GACjB,kBAAkB;IAIrB;;OAEG;IACH,MAAM,CAAC,MAAM,CACX,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,aAAa,EACvB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,MAAU,GACjB,kBAAkB;CAGtB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAG7D"}
package/dist/errors.js ADDED
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Error handling infrastructure for Lass transpiler.
3
+ *
4
+ * Provides structured error types with source location information
5
+ * for actionable error messages following NFR-ERROR requirements.
6
+ */
7
+ /**
8
+ * Error categories for Lass transpilation errors.
9
+ * Used to classify errors and provide appropriate guidance.
10
+ */
11
+ export var ErrorCategory;
12
+ (function (ErrorCategory) {
13
+ /** Scanner-level errors (context tracking, unexpected characters) */
14
+ ErrorCategory["SCAN"] = "SCAN";
15
+ /** Symbol detection errors ($name, {{ }}, @{ }, etc.) */
16
+ ErrorCategory["SYMBOL"] = "SYMBOL";
17
+ /** Syntax errors (malformed Lass constructs) */
18
+ ErrorCategory["SYNTAX"] = "SYNTAX";
19
+ })(ErrorCategory || (ErrorCategory = {}));
20
+ /**
21
+ * Custom error class for Lass transpilation errors.
22
+ *
23
+ * Provides structured error information including:
24
+ * - Source file path (when provided)
25
+ * - Line and column numbers
26
+ * - Error category for classification
27
+ * - Actionable error description
28
+ *
29
+ * Error message format follows NFR-ERROR requirements:
30
+ * "[filename:]line:column - [CATEGORY] description"
31
+ */
32
+ export class LassTranspileError extends Error {
33
+ /** Error category for classification */
34
+ category;
35
+ /** Source location where the error occurred */
36
+ location;
37
+ /**
38
+ * Creates a new transpilation error.
39
+ *
40
+ * @param message - Actionable error description
41
+ * @param category - Error category (SCAN, SYMBOL, SYNTAX)
42
+ * @param location - Source location information
43
+ */
44
+ constructor(message, category, location) {
45
+ // Format: "[filename:]line:column - [CATEGORY] message"
46
+ const prefix = location.filename ? `${location.filename}:` : '';
47
+ const formattedMessage = `${prefix}${location.line}:${location.column} - [${category}] ${message}`;
48
+ super(formattedMessage);
49
+ this.name = 'LassTranspileError';
50
+ this.category = category;
51
+ this.location = location;
52
+ // Maintain proper stack trace in V8 environments
53
+ if (Error.captureStackTrace) {
54
+ Error.captureStackTrace(this, LassTranspileError);
55
+ }
56
+ }
57
+ /**
58
+ * Creates an error with just a source position.
59
+ * Useful when filename is not available.
60
+ */
61
+ static at(message, category, line, column, offset = 0) {
62
+ return new LassTranspileError(message, category, { line, column, offset });
63
+ }
64
+ /**
65
+ * Creates an error with file path and source position.
66
+ */
67
+ static atFile(message, category, filename, line, column, offset = 0) {
68
+ return new LassTranspileError(message, category, { filename, line, column, offset });
69
+ }
70
+ }
71
+ /**
72
+ * Helper to format source location for display.
73
+ *
74
+ * @param location - Source location to format
75
+ * @returns Formatted string like "filename:line:column" or "line:column"
76
+ */
77
+ export function formatLocation(location) {
78
+ const prefix = location.filename ? `${location.filename}:` : '';
79
+ return `${prefix}${location.line}:${location.column}`;
80
+ }
81
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,MAAM,CAAN,IAAY,aAOX;AAPD,WAAY,aAAa;IACvB,qEAAqE;IACrE,8BAAa,CAAA;IACb,yDAAyD;IACzD,kCAAiB,CAAA;IACjB,gDAAgD;IAChD,kCAAiB,CAAA;AACnB,CAAC,EAPW,aAAa,KAAb,aAAa,QAOxB;AAuBD;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,wCAAwC;IAC/B,QAAQ,CAAgB;IAEjC,+CAA+C;IACtC,QAAQ,CAAe;IAEhC;;;;;;OAMG;IACH,YAAY,OAAe,EAAE,QAAuB,EAAE,QAAsB;QAC1E,wDAAwD;QACxD,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,MAAM,gBAAgB,GAAG,GAAG,MAAM,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,MAAM,OAAO,QAAQ,KAAK,OAAO,EAAE,CAAC;QAEnG,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAExB,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAEzB,iDAAiD;QACjD,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;YAC5B,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,EAAE,CACP,OAAe,EACf,QAAuB,EACvB,IAAY,EACZ,MAAc,EACd,SAAiB,CAAC;QAElB,OAAO,IAAI,kBAAkB,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,MAAM,CACX,OAAe,EACf,QAAuB,EACvB,QAAgB,EAChB,IAAY,EACZ,MAAc,EACd,SAAiB,CAAC;QAElB,OAAO,IAAI,kBAAkB,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACvF,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,QAAsB;IACnD,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAChE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;AACxD,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * String escape utilities for @lass-lang/core
3
+ *
4
+ * Functions for escaping text when embedding in various contexts.
5
+ */
6
+ /**
7
+ * Escapes special characters for template literal embedding.
8
+ * Only escapes backslash and backtick - NOT dollar sign (needed for substitution).
9
+ *
10
+ * @param text - Text to escape
11
+ * @returns Escaped text safe for template literal
12
+ */
13
+ export declare function escapeForTemplateLiteral(text: string): string;
14
+ /**
15
+ * Escapes a value for embedding in a JavaScript string literal.
16
+ * Story 3.3: Used when @(prop) is inside {{ }} context.
17
+ *
18
+ * Escapes: backslash, double quote, newline, carriage return
19
+ *
20
+ * @param value - The value to escape
21
+ * @returns Escaped value safe for JS string embedding
22
+ */
23
+ export declare function escapeForJs(value: string): string;
24
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMjD"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * String escape utilities for @lass-lang/core
3
+ *
4
+ * Functions for escaping text when embedding in various contexts.
5
+ */
6
+ /**
7
+ * Escapes special characters for template literal embedding.
8
+ * Only escapes backslash and backtick - NOT dollar sign (needed for substitution).
9
+ *
10
+ * @param text - Text to escape
11
+ * @returns Escaped text safe for template literal
12
+ */
13
+ export function escapeForTemplateLiteral(text) {
14
+ return text.replace(/\\/g, '\\\\').replace(/`/g, '\\`');
15
+ }
16
+ /**
17
+ * Escapes a value for embedding in a JavaScript string literal.
18
+ * Story 3.3: Used when @(prop) is inside {{ }} context.
19
+ *
20
+ * Escapes: backslash, double quote, newline, carriage return
21
+ *
22
+ * @param value - The value to escape
23
+ * @returns Escaped value safe for JS string embedding
24
+ */
25
+ export function escapeForJs(value) {
26
+ return value
27
+ .replace(/\\/g, '\\\\')
28
+ .replace(/"/g, '\\"')
29
+ .replace(/\n/g, '\\n')
30
+ .replace(/\r/g, '\\r');
31
+ }
32
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAAY;IACnD,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,KAAK;SACT,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * @lass-lang/core
3
+ *
4
+ * Lass language transpiler core package.
5
+ * Converts .lass files to executable JavaScript modules that produce CSS.
6
+ *
7
+ * Transpilation Pipeline (The Story):
8
+ * 1. detectZones() - Split source into preamble and CSS zones
9
+ * 2. stripLineComments() - Remove // comments from CSS zone
10
+ * 3. normalizeStyleLookupShorthands() - @prop -> @(prop)
11
+ * 4. resolvePropertyAccessors() - @(prop) -> value
12
+ * 5. resolveDollarVariables() - $param -> ${...}
13
+ * 6. processExpressions() - {{ expr }} -> ${...}
14
+ * 7. buildOutput() - Assemble final JS module
15
+ *
16
+ * This is the "igloo" view - each function is a building block.
17
+ * Drill into transpiler.ts for step implementations.
18
+ */
19
+ import type { TranspileResult, TranspileOptions } from './types.js';
20
+ /**
21
+ * Transpiles Lass source code to a JavaScript module.
22
+ *
23
+ * The Story (Igloo Principle):
24
+ * 1. Split the file into preamble and CSS zones at the ---
25
+ * 2. Strip // comments from CSS zone
26
+ * 3. Normalize @prop -> @(prop) shorthands
27
+ * 4. Resolve @(prop) accessors to their values
28
+ * 5. Replace $param with ${...} for variable substitution
29
+ * 6. Find {{ expressions }} and make them interpolations
30
+ * 7. Wrap it all in a JS module that exports CSS
31
+ *
32
+ * Implementation History:
33
+ * - Story 1.4: CSS passthrough - wraps input in JS module export
34
+ * - Story 2.1: Two-zone detection - splits on ---, identifies preamble and CSS zones
35
+ * - Story 2.2: Preamble execution - includes preamble in output, executes when imported
36
+ * - Story 2.3: Expression interpolation - transforms {{ expr }} to ${expr} in template literal
37
+ * - Story 2.4: Array auto-join - wraps expressions in __lassScriptExpression() for array/null handling
38
+ * - Story 2.5: Universal {{ }} - processed everywhere in CSS zone (strings, url(), comments)
39
+ * - Story 3.2: @(prop) resolution - resolves @(prop) to previously-declared CSS values (Phase 1)
40
+ * - Story 3.3: @(prop) in {{ }} - detects @(prop) inside expressions, quotes values for JS context
41
+ * - Refactored: Changed from @prop to @(prop) for unambiguous syntax (supports custom properties)
42
+ * - Story 4.1: $param substitution - replaces $param with ${$param} for template literal interpolation
43
+ * - Story 4.2: @prop shorthand - normalizes @prop to @(prop) before resolution
44
+ * - Story 4.4: // comment stripping - removes single-line comments from CSS zone
45
+ *
46
+ * @param source - The Lass source code
47
+ * @param options - Transpilation options
48
+ * @returns The transpiled JavaScript module code
49
+ */
50
+ export declare function transpile(source: string, options?: TranspileOptions): TranspileResult;
51
+ export type { TranspileResult, TranspileOptions } from './types.js';
52
+ export { Scanner } from './scanner.js';
53
+ /**
54
+ * Re-exported types from scanner module.
55
+ * - ScanResult: Result of a scan operation
56
+ * - ScanOptions: Options for scanner customization
57
+ * - ZoneSplit: Result of zone separation (preamble/CSS)
58
+ * - ExpressionSplit: Result of {{ }} expression splitting
59
+ * - PropertyAccessor: Info about detected @(prop) accessor (propName, indices)
60
+ * - DollarVariable: Info about detected $param variable (varName, indices)
61
+ * - StyleLookupShorthand: Info about detected @prop shorthand (propName, indices)
62
+ */
63
+ export type { ScanResult, ScanOptions, ZoneSplit, ExpressionSplit, PropertyAccessor, DollarVariable, StyleLookupShorthand } from './scanner.js';
64
+ export { LassTranspileError, ErrorCategory, formatLocation, type SourceLocation, type FileLocation, } from './errors.js';
65
+ export { cutByBraces, findPropertyValue, areSiblingTrees, isInsideAtRule, type ScopeSlice, type ScopeSlices, } from './scope-tracker.js';
66
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAWH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAMpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,gBAAqB,GAC7B,eAAe,CAuBjB;AAMD,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAMpE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC;;;;;;;;;GASG;AACH,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,eAAe,EAAE,gBAAgB,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAMhJ,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,YAAY,GAClB,MAAM,aAAa,CAAC;AAMrB,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,KAAK,UAAU,EACf,KAAK,WAAW,GACjB,MAAM,oBAAoB,CAAC"}