@herb-tools/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.
Files changed (49) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/README.md +9 -0
  3. package/dist/herb-core.browser.js +2704 -0
  4. package/dist/herb-core.browser.js.map +1 -0
  5. package/dist/herb-core.cjs +2759 -0
  6. package/dist/herb-core.cjs.map +1 -0
  7. package/dist/herb-core.esm.js +2704 -0
  8. package/dist/herb-core.esm.js.map +1 -0
  9. package/dist/herb-core.umd.js +2765 -0
  10. package/dist/herb-core.umd.js.map +1 -0
  11. package/dist/types/ast.d.ts +4 -0
  12. package/dist/types/backend.d.ts +24 -0
  13. package/dist/types/error.d.ts +16 -0
  14. package/dist/types/errors.d.ts +222 -0
  15. package/dist/types/herb-backend.d.ts +87 -0
  16. package/dist/types/index.d.ts +15 -0
  17. package/dist/types/lex-result.d.ts +50 -0
  18. package/dist/types/location.d.ts +18 -0
  19. package/dist/types/node.d.ts +27 -0
  20. package/dist/types/nodes.d.ts +682 -0
  21. package/dist/types/parse-result.d.ts +62 -0
  22. package/dist/types/position.d.ts +15 -0
  23. package/dist/types/range.d.ts +12 -0
  24. package/dist/types/result.d.ts +10 -0
  25. package/dist/types/token-list.d.ts +16 -0
  26. package/dist/types/token.d.ts +22 -0
  27. package/dist/types/util.d.ts +2 -0
  28. package/dist/types/visitor.d.ts +11 -0
  29. package/dist/types/warning.d.ts +11 -0
  30. package/package.json +49 -0
  31. package/src/ast.ts +7 -0
  32. package/src/backend.ts +85 -0
  33. package/src/error.ts +38 -0
  34. package/src/errors.ts +820 -0
  35. package/src/herb-backend.ts +152 -0
  36. package/src/index.ts +15 -0
  37. package/src/lex-result.ts +78 -0
  38. package/src/location.ts +51 -0
  39. package/src/node.ts +106 -0
  40. package/src/nodes.ts +2294 -0
  41. package/src/parse-result.ts +101 -0
  42. package/src/position.ts +38 -0
  43. package/src/range.ts +35 -0
  44. package/src/result.ts +26 -0
  45. package/src/token-list.ts +57 -0
  46. package/src/token.ts +63 -0
  47. package/src/util.ts +19 -0
  48. package/src/visitor.ts +14 -0
  49. package/src/warning.ts +20 -0
@@ -0,0 +1,62 @@
1
+ import { Result } from "./result.js";
2
+ import { DocumentNode } from "./nodes.js";
3
+ import { HerbError } from "./error.js";
4
+ import { HerbWarning } from "./warning.js";
5
+ import type { SerializedHerbError } from "./error.js";
6
+ import type { SerializedHerbWarning } from "./warning.js";
7
+ import type { SerializedDocumentNode } from "./nodes.js";
8
+ import type { Visitor } from "./visitor.js";
9
+ export type SerializedParseResult = {
10
+ value: SerializedDocumentNode;
11
+ source: string;
12
+ warnings: SerializedHerbWarning[];
13
+ errors: SerializedHerbError[];
14
+ };
15
+ /**
16
+ * Represents the result of a parsing operation, extending the base `Result` class.
17
+ * It contains the parsed document node, source code, warnings, and errors.
18
+ */
19
+ export declare class ParseResult extends Result {
20
+ /** The document node generated from the source code. */
21
+ readonly value: DocumentNode;
22
+ /**
23
+ * Creates a `ParseResult` instance from a serialized result.
24
+ * @param result - The serialized parse result containing the value and source.
25
+ * @returns A new `ParseResult` instance.
26
+ */
27
+ static from(result: SerializedParseResult): ParseResult;
28
+ /**
29
+ * Constructs a new `ParseResult`.
30
+ * @param value - The document node.
31
+ * @param source - The source code that was parsed.
32
+ * @param warnings - An array of warnings encountered during parsing.
33
+ * @param errors - An array of errors encountered during parsing.
34
+ */
35
+ constructor(value: DocumentNode, source: string, warnings?: HerbWarning[], errors?: HerbError[]);
36
+ /**
37
+ * Determines if the parsing failed.
38
+ * @returns `true` if there are errors, otherwise `false`.
39
+ */
40
+ failed(): boolean;
41
+ /**
42
+ * Determines if the parsing was successful.
43
+ * @returns `true` if there are no errors, otherwise `false`.
44
+ */
45
+ success(): boolean;
46
+ /**
47
+ * Returns a pretty-printed JSON string of the errors.
48
+ * @returns A string representation of the errors.
49
+ */
50
+ prettyErrors(): string;
51
+ recursiveErrors(): HerbError[];
52
+ /**
53
+ * Returns a pretty-printed string of the parse result.
54
+ * @returns A string representation of the parse result.
55
+ */
56
+ inspect(): string;
57
+ /**
58
+ * Accepts a visitor to traverse the document node.
59
+ * @param visitor - The visitor instance.
60
+ */
61
+ visit(visitor: Visitor): void;
62
+ }
@@ -0,0 +1,15 @@
1
+ export type SerializedPosition = {
2
+ line: number;
3
+ column: number;
4
+ };
5
+ export declare class Position {
6
+ readonly line: number;
7
+ readonly column: number;
8
+ static from(position: SerializedPosition): Position;
9
+ constructor(line: number, column: number);
10
+ toHash(): SerializedPosition;
11
+ toJSON(): SerializedPosition;
12
+ treeInspect(): string;
13
+ inspect(): string;
14
+ toString(): string;
15
+ }
@@ -0,0 +1,12 @@
1
+ export type SerializedRange = [number, number];
2
+ export declare class Range {
3
+ readonly start: number;
4
+ readonly end: number;
5
+ static from(range: SerializedRange): Range;
6
+ constructor(start: number, end: number);
7
+ toArray(): SerializedRange;
8
+ toJSON(): SerializedRange;
9
+ treeInspect(): string;
10
+ inspect(): string;
11
+ toString(): string;
12
+ }
@@ -0,0 +1,10 @@
1
+ import { HerbError } from "./error.js";
2
+ import { HerbWarning } from "./warning.js";
3
+ export declare class Result {
4
+ readonly source: string;
5
+ readonly warnings: HerbWarning[];
6
+ readonly errors: HerbError[];
7
+ constructor(source: string, warnings?: HerbWarning[], errors?: HerbError[]);
8
+ success(): boolean;
9
+ failed(): boolean;
10
+ }
@@ -0,0 +1,16 @@
1
+ import { Token, SerializedToken } from "./token.js";
2
+ export type SerializedTokenList = SerializedToken[];
3
+ export declare class TokenList implements Iterable<Token> {
4
+ private list;
5
+ static from(list: SerializedTokenList): TokenList;
6
+ constructor(list: Token[]);
7
+ get length(): number;
8
+ [Symbol.iterator](): Iterator<Token>;
9
+ at(index: number): Token | undefined;
10
+ forEach(callback: (token: Token, index: number, array: Token[]) => void): void;
11
+ map<U>(callback: (token: Token, index: number, array: Token[]) => U): U[];
12
+ filter(predicate: (token: Token, index: number, array: Token[]) => boolean): Token[];
13
+ __getobj__(): Token[];
14
+ inspect(): string;
15
+ toString(): string;
16
+ }
@@ -0,0 +1,22 @@
1
+ import { Range, SerializedRange } from "./range.js";
2
+ import { Location, SerializedLocation } from "./location.js";
3
+ export type SerializedToken = {
4
+ value: string;
5
+ range: SerializedRange;
6
+ location: SerializedLocation;
7
+ type: string;
8
+ };
9
+ export declare class Token {
10
+ readonly value: string;
11
+ readonly range: Range;
12
+ readonly location: Location;
13
+ readonly type: string;
14
+ static from(token: SerializedToken): Token;
15
+ constructor(value: string, range: Range, location: Location, type: string);
16
+ toHash(): SerializedToken;
17
+ toJSON(): SerializedToken;
18
+ treeInspect(): string;
19
+ valueInspect(): string;
20
+ inspect(): string;
21
+ toString(): string;
22
+ }
@@ -0,0 +1,2 @@
1
+ export declare function ensureString(object: any): string;
2
+ export declare function convertToUTF8(string: string): string;
@@ -0,0 +1,11 @@
1
+ import { Node } from "./node.js";
2
+ /**
3
+ * Represents a visitor that can traverse nodes.
4
+ */
5
+ export declare class Visitor {
6
+ /**
7
+ * Visits a node and performs an action.
8
+ * @param node - The node to visit.
9
+ */
10
+ visit(node: Node): void;
11
+ }
@@ -0,0 +1,11 @@
1
+ import { Location, SerializedLocation } from "./location.js";
2
+ export interface SerializedHerbWarning {
3
+ message: string;
4
+ location: SerializedLocation;
5
+ }
6
+ export declare class HerbWarning {
7
+ message: string;
8
+ location: Location;
9
+ static from(warning: SerializedHerbWarning): HerbWarning;
10
+ constructor(message: string, location: Location);
11
+ }
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@herb-tools/core",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "license": "MIT",
6
+ "homepage": "https://herb-tools.dev",
7
+ "bugs": "https://github.com/marcoroth/herb/issues/new?title=Package%20%60@herb-tools/core%60:%20",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/marcoroth/herb.git",
11
+ "directory": "javascript/packages/core"
12
+ },
13
+ "main": "./dist/herb-core.cjs",
14
+ "module": "./dist/herb-core.esm.js",
15
+ "types": "./dist/types/index.d.ts",
16
+ "scripts": {
17
+ "build": "yarn clean && rollup -c",
18
+ "dev": "rollup -c -w",
19
+ "clean": "rimraf dist",
20
+ "test": "vitest run",
21
+ "prepublishOnly": "yarn clean && yarn build && yarn test"
22
+ },
23
+ "exports": {
24
+ "./package.json": "./package.json",
25
+ ".": {
26
+ "types": "./dist/types/index.d.ts",
27
+ "import": "./dist/herb-core.esm.js",
28
+ "require": "./dist/herb-core.cjs",
29
+ "default": "./dist/herb-core.esm.js"
30
+ }
31
+ },
32
+ "dependencies": {},
33
+ "devDependencies": {
34
+ "@rollup/plugin-json": "^6.1.0",
35
+ "@rollup/plugin-node-resolve": "^16.0.1",
36
+ "@rollup/plugin-typescript": "^12.1.2",
37
+ "rimraf": "^6.0.1",
38
+ "rollup": "^4.35.0",
39
+ "tslib": "^2.8.1",
40
+ "typescript": "^5.8.2",
41
+ "vitest": "^3.0.0"
42
+ },
43
+ "files": [
44
+ "package.json",
45
+ "README.md",
46
+ "dist/",
47
+ "src/"
48
+ ]
49
+ }
package/src/ast.ts ADDED
@@ -0,0 +1,7 @@
1
+ export class ASTNode {
2
+ readonly errors: any[]
3
+
4
+ constructor() {
5
+ this.errors = []
6
+ }
7
+ }
package/src/backend.ts ADDED
@@ -0,0 +1,85 @@
1
+ import type { SerializedParseResult } from "./parse-result.js"
2
+ import type { SerializedLexResult } from "./lex-result.js"
3
+
4
+ interface LibHerbBackendFunctions {
5
+ lex: (source: string) => SerializedLexResult
6
+ lexFile: (path: string) => SerializedLexResult
7
+
8
+ parse: (source: string) => SerializedParseResult
9
+ parseFile: (path: string) => SerializedParseResult
10
+
11
+ extractRuby: (source: string) => string
12
+ extractHTML: (source: string) => string
13
+
14
+ version: () => string
15
+ }
16
+
17
+ export type BackendPromise = () => Promise<LibHerbBackend>
18
+
19
+ const expectedFunctions = [
20
+ "parse",
21
+ "lex",
22
+ "parseFile",
23
+ "lexFile",
24
+ "extractRuby",
25
+ "extractHTML",
26
+ "version",
27
+ ] as const
28
+
29
+ type LibHerbBackendFunctionName = (typeof expectedFunctions)[number]
30
+
31
+ type CheckFunctionsExistInInterface =
32
+ LibHerbBackendFunctionName extends keyof LibHerbBackendFunctions
33
+ ? true
34
+ : "Error: Not all expectedFunctions are defined in LibHerbBackendFunctions"
35
+
36
+ type CheckInterfaceKeysInFunctions =
37
+ keyof LibHerbBackendFunctions extends LibHerbBackendFunctionName
38
+ ? true
39
+ : "Error: LibHerbBackendFunctions has keys not listed in expectedFunctions"
40
+
41
+ // NOTE: This function should never be called and is only for type checking
42
+ // so we can make sure `expectedFunctions` matches the functions defined
43
+ // in `LibHerbBackendFunctions` and the other way around.
44
+ //
45
+ export function _TYPECHECK() {
46
+ const checkFunctionsExist: CheckFunctionsExistInInterface = true
47
+ const checkInterfaceComplete: CheckInterfaceKeysInFunctions = true
48
+
49
+ return { checkFunctionsExist, checkInterfaceComplete }
50
+ }
51
+
52
+ // Exported Types + Functions
53
+
54
+ export type LibHerbBackend = {
55
+ [K in LibHerbBackendFunctionName]: LibHerbBackendFunctions[K]
56
+ }
57
+
58
+ export function isLibHerbBackend(
59
+ object: any,
60
+ libherbpath: string = "unknown",
61
+ ): object is LibHerbBackend {
62
+ for (const expectedFunction of expectedFunctions) {
63
+ if (object[expectedFunction] === undefined) {
64
+ throw new Error(
65
+ `Libherb at "${libherbpath}" doesn't expose function "${expectedFunction}".`,
66
+ )
67
+ }
68
+
69
+ if (typeof object[expectedFunction] !== "function") {
70
+ throw new Error(
71
+ `Libherb at "${libherbpath}" has "${expectedFunction}" but it's not a function.`,
72
+ )
73
+ }
74
+ }
75
+
76
+ return true
77
+ }
78
+
79
+ export function ensureLibHerbBackend(
80
+ object: any,
81
+ libherbpath: string = "unknown",
82
+ ): LibHerbBackend {
83
+ isLibHerbBackend(object, libherbpath)
84
+ return object
85
+ }
package/src/error.ts ADDED
@@ -0,0 +1,38 @@
1
+ import { Location, SerializedLocation } from "./location.js"
2
+ import { fromSerializedError } from "./errors.js"
3
+
4
+ export interface SerializedHerbError {
5
+ type: string
6
+ message: string
7
+ location: SerializedLocation
8
+ }
9
+
10
+ export abstract class HerbError {
11
+ readonly type: string
12
+ readonly message: string
13
+ readonly location: Location
14
+
15
+ static from(error: SerializedHerbError): HerbError {
16
+ return fromSerializedError(error)
17
+ }
18
+
19
+ constructor(type: string, message: string, location: Location) {
20
+ this.type = type
21
+ this.message = message
22
+ this.location = location
23
+ }
24
+
25
+ toJSON(): SerializedHerbError {
26
+ return {
27
+ type: this.type,
28
+ message: this.message,
29
+ location: this.location.toJSON(),
30
+ }
31
+ }
32
+
33
+ inspect(): string {
34
+ return this.treeInspect(0)
35
+ }
36
+
37
+ abstract treeInspect(indent?: number): string
38
+ }