@malloydata/malloy-tag 0.0.339 → 0.0.341

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 (45) hide show
  1. package/dist/index.d.ts +1 -3
  2. package/dist/index.js +4 -5
  3. package/dist/index.js.map +1 -1
  4. package/dist/{peggy/index.d.ts → parser.d.ts} +13 -4
  5. package/dist/parser.js +181 -0
  6. package/dist/parser.js.map +1 -0
  7. package/package.json +12 -5
  8. package/src/index.ts +1 -3
  9. package/src/parser.ts +203 -0
  10. package/CONTEXT.md +0 -173
  11. package/README.md +0 -0
  12. package/dist/peggy/dist/peg-tag-parser.d.ts +0 -11
  13. package/dist/peggy/dist/peg-tag-parser.js +0 -3130
  14. package/dist/peggy/dist/peg-tag-parser.js.map +0 -1
  15. package/dist/peggy/index.js +0 -117
  16. package/dist/peggy/index.js.map +0 -1
  17. package/dist/peggy/interpreter.d.ts +0 -32
  18. package/dist/peggy/interpreter.js +0 -208
  19. package/dist/peggy/interpreter.js.map +0 -1
  20. package/dist/peggy/statements.d.ts +0 -51
  21. package/dist/peggy/statements.js +0 -7
  22. package/dist/peggy/statements.js.map +0 -1
  23. package/dist/schema.d.ts +0 -41
  24. package/dist/schema.js +0 -573
  25. package/dist/schema.js.map +0 -1
  26. package/dist/schema.spec.d.ts +0 -1
  27. package/dist/schema.spec.js +0 -980
  28. package/dist/schema.spec.js.map +0 -1
  29. package/dist/tags.spec.d.ts +0 -8
  30. package/dist/tags.spec.js +0 -884
  31. package/dist/tags.spec.js.map +0 -1
  32. package/dist/util.spec.d.ts +0 -1
  33. package/dist/util.spec.js +0 -43
  34. package/dist/util.spec.js.map +0 -1
  35. package/src/motly-schema.motly +0 -52
  36. package/src/peggy/dist/peg-tag-parser.js +0 -2790
  37. package/src/peggy/index.ts +0 -89
  38. package/src/peggy/interpreter.ts +0 -265
  39. package/src/peggy/malloy-tag.peggy +0 -224
  40. package/src/peggy/statements.ts +0 -49
  41. package/src/schema.spec.ts +0 -1280
  42. package/src/schema.ts +0 -852
  43. package/src/tags.spec.ts +0 -967
  44. package/src/util.spec.ts +0 -43
  45. package/tsconfig.json +0 -12
package/dist/index.d.ts CHANGED
@@ -1,5 +1,3 @@
1
1
  export * from './tags';
2
- export { parseTag } from './peggy';
2
+ export { parseTag, TagParser } from './parser';
3
3
  export * as ParseUtil from './util';
4
- export { validateTag } from './schema';
5
- export type { SchemaError } from './schema';
package/dist/index.js CHANGED
@@ -36,7 +36,7 @@ var __importStar = (this && this.__importStar) || (function () {
36
36
  };
37
37
  })();
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.validateTag = exports.ParseUtil = exports.parseTag = void 0;
39
+ exports.ParseUtil = exports.TagParser = exports.parseTag = void 0;
40
40
  /*
41
41
  * Copyright (c) Meta Platforms, Inc. and affiliates.
42
42
  *
@@ -44,9 +44,8 @@ exports.validateTag = exports.ParseUtil = exports.parseTag = void 0;
44
44
  * LICENSE file in the root directory of this source tree.
45
45
  */
46
46
  __exportStar(require("./tags"), exports);
47
- var peggy_1 = require("./peggy");
48
- Object.defineProperty(exports, "parseTag", { enumerable: true, get: function () { return peggy_1.parseTag; } });
47
+ var parser_1 = require("./parser");
48
+ Object.defineProperty(exports, "parseTag", { enumerable: true, get: function () { return parser_1.parseTag; } });
49
+ Object.defineProperty(exports, "TagParser", { enumerable: true, get: function () { return parser_1.TagParser; } });
49
50
  exports.ParseUtil = __importStar(require("./util"));
50
- var schema_1 = require("./schema");
51
- Object.defineProperty(exports, "validateTag", { enumerable: true, get: function () { return schema_1.validateTag; } });
52
51
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;GAKG;AACH,yCAAuB;AACvB,iCAAiC;AAAzB,iGAAA,QAAQ,OAAA;AAChB,oDAAoC;AACpC,mCAAqC;AAA7B,qGAAA,WAAW,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;GAKG;AACH,yCAAuB;AACvB,mCAA6C;AAArC,kGAAA,QAAQ,OAAA;AAAE,mGAAA,SAAS,OAAA;AAC3B,oDAAoC"}
@@ -1,13 +1,22 @@
1
- import type { TagParse } from '../tags';
2
- import { Tag } from '../tags';
1
+ import { Tag } from './tags';
2
+ import type { TagParse } from './tags';
3
+ /**
4
+ * Session-based parser for Malloy tag language. Create an instance,
5
+ * call parse() for each line, then finish() to get the final Tag.
6
+ */
7
+ export declare class TagParser {
8
+ private session;
9
+ constructor();
10
+ parse(source: string): TagParse;
11
+ finish(): Tag;
12
+ }
3
13
  /**
4
14
  * Parse Malloy tag language into a Tag which can be queried.
5
15
  *
6
16
  * @param source - A single string or array of strings to parse. If a string
7
17
  * starts with #, all characters up to the first space are skipped.
8
18
  * When an array is provided, strings are parsed sequentially and merged.
9
- * @param extending - A tag which this parse will extend
10
19
  * @returns TagParse with the resulting tag and any errors. For arrays,
11
20
  * error line numbers indicate the index in the array where the error occurred.
12
21
  */
13
- export declare function parseTag(source: string | string[], extending?: Tag): TagParse;
22
+ export declare function parseTag(source: string | string[]): TagParse;
package/dist/parser.js ADDED
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright Contributors to the Malloy project
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.TagParser = void 0;
8
+ exports.parseTag = parseTag;
9
+ const motly_ts_parser_1 = require("@malloydata/motly-ts-parser");
10
+ const tags_1 = require("./tags");
11
+ /**
12
+ * Strip the Malloy tag prefix (e.g., "# " or "#(docs) ") from source.
13
+ */
14
+ function stripPrefix(source) {
15
+ if (source[0] === '#') {
16
+ const skipTo = source.indexOf(' ');
17
+ if (skipTo > 0) {
18
+ return source.slice(skipTo);
19
+ }
20
+ return '';
21
+ }
22
+ return source;
23
+ }
24
+ /**
25
+ * Map a MOTLYError (from motly-ts parser) to a TagError.
26
+ */
27
+ function mapMOTLYError(error) {
28
+ return {
29
+ code: error.code,
30
+ message: error.message,
31
+ line: error.begin.line,
32
+ offset: error.begin.column,
33
+ };
34
+ }
35
+ /**
36
+ * Parse a reference string like "$^^path.to[0].thing" back into
37
+ * structured form {ups, refPath}.
38
+ */
39
+ function parseRefString(linkTo) {
40
+ let i = 1;
41
+ let ups = 0;
42
+ while (i < linkTo.length && linkTo[i] === '^') {
43
+ ups++;
44
+ i++;
45
+ }
46
+ const refPath = [];
47
+ const rest = linkTo.slice(i);
48
+ if (rest.length === 0) {
49
+ return { ups, refPath };
50
+ }
51
+ let pos = 0;
52
+ let needDot = false;
53
+ while (pos < rest.length) {
54
+ if (rest[pos] === '.') {
55
+ pos++;
56
+ needDot = false;
57
+ continue;
58
+ }
59
+ if (rest[pos] === '[') {
60
+ const close = rest.indexOf(']', pos);
61
+ refPath.push(Number(rest.slice(pos + 1, close)));
62
+ pos = close + 1;
63
+ needDot = true;
64
+ continue;
65
+ }
66
+ if (needDot) {
67
+ // Expected a dot separator but didn't get one
68
+ }
69
+ if (rest[pos] === '`') {
70
+ pos++;
71
+ let seg = '';
72
+ while (pos < rest.length && rest[pos] !== '`') {
73
+ if (rest[pos] === '\\') {
74
+ pos++;
75
+ seg += rest[pos];
76
+ }
77
+ else {
78
+ seg += rest[pos];
79
+ }
80
+ pos++;
81
+ }
82
+ pos++;
83
+ refPath.push(seg);
84
+ needDot = true;
85
+ continue;
86
+ }
87
+ let seg = '';
88
+ while (pos < rest.length &&
89
+ rest[pos] !== '.' &&
90
+ rest[pos] !== '[' &&
91
+ rest[pos] !== '`') {
92
+ seg += rest[pos];
93
+ pos++;
94
+ }
95
+ if (seg.length > 0) {
96
+ refPath.push(seg);
97
+ needDot = true;
98
+ }
99
+ }
100
+ return { ups, refPath };
101
+ }
102
+ function isRef(node) {
103
+ return 'linkTo' in node;
104
+ }
105
+ /**
106
+ * Convert a MOTLYNode tree into a Tag tree with parent links.
107
+ */
108
+ function hydrate(node, parent) {
109
+ if (isRef(node)) {
110
+ const { ups, refPath } = parseRefString(node.linkTo);
111
+ return new tags_1.RefTag(ups, refPath, parent);
112
+ }
113
+ const tag = new tags_1.Tag({}, parent);
114
+ if (node.eq !== undefined) {
115
+ if (Array.isArray(node.eq)) {
116
+ tag.eq = node.eq.map(el => hydrate(el, tag));
117
+ }
118
+ else if (node.eq instanceof Date) {
119
+ tag.eq = new Date(node.eq);
120
+ }
121
+ else {
122
+ tag.eq = node.eq;
123
+ }
124
+ }
125
+ if (node.properties !== undefined) {
126
+ tag.properties = {};
127
+ for (const [key, val] of Object.entries(node.properties)) {
128
+ tag.properties[key] = hydrate(val, tag);
129
+ }
130
+ }
131
+ if (node.deleted) {
132
+ tag.deleted = true;
133
+ }
134
+ return tag;
135
+ }
136
+ /**
137
+ * Session-based parser for Malloy tag language. Create an instance,
138
+ * call parse() for each line, then finish() to get the final Tag.
139
+ */
140
+ class TagParser {
141
+ constructor() {
142
+ this.session = new motly_ts_parser_1.MOTLYSession();
143
+ }
144
+ parse(source) {
145
+ const stripped = stripPrefix(source);
146
+ const errors = this.session.parse(stripped);
147
+ const tagErrors = errors.map(mapMOTLYError);
148
+ const value = this.session.getValue();
149
+ return { tag: hydrate(value), log: tagErrors };
150
+ }
151
+ finish() {
152
+ const value = this.session.getValue();
153
+ this.session.dispose();
154
+ return hydrate(value);
155
+ }
156
+ }
157
+ exports.TagParser = TagParser;
158
+ /**
159
+ * Parse Malloy tag language into a Tag which can be queried.
160
+ *
161
+ * @param source - A single string or array of strings to parse. If a string
162
+ * starts with #, all characters up to the first space are skipped.
163
+ * When an array is provided, strings are parsed sequentially and merged.
164
+ * @returns TagParse with the resulting tag and any errors. For arrays,
165
+ * error line numbers indicate the index in the array where the error occurred.
166
+ */
167
+ function parseTag(source) {
168
+ const session = new TagParser();
169
+ if (typeof source === 'string') {
170
+ return session.parse(source);
171
+ }
172
+ const allErrs = [];
173
+ for (let i = 0; i < source.length; i++) {
174
+ const result = session.parse(source[i]);
175
+ for (const err of result.log) {
176
+ allErrs.push({ ...err, line: i + err.line });
177
+ }
178
+ }
179
+ return { tag: session.finish(), log: allErrs };
180
+ }
181
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,9 +1,17 @@
1
1
  {
2
2
  "name": "@malloydata/malloy-tag",
3
- "version": "0.0.339",
3
+ "version": "0.0.341",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist/**/*.js",
9
+ "dist/**/*.js.map",
10
+ "dist/**/*.d.ts",
11
+ "!dist/**/*.spec.*",
12
+ "src",
13
+ "!src/**/*.spec.*"
14
+ ],
7
15
  "homepage": "https://github.com/malloydata/malloy#readme",
8
16
  "engines": {
9
17
  "node": ">=20"
@@ -14,17 +22,16 @@
14
22
  },
15
23
  "scripts": {
16
24
  "test": "jest --config=../../jest.config.js",
17
- "build-peggy": "mkdir -p src/peggy/dist && peggy -o src/peggy/dist/peg-tag-parser.js src/peggy/malloy-tag.peggy",
18
- "clean": "tsc --build --clean && rm -f tsconfig.tsbuildinfo && rimraf @flowtyped && rm -rf src/peggy/dist",
19
- "build": "npm run build-peggy && tsc --build && npm run generate-flow",
25
+ "clean": "rm -rf dist && tsc --build --clean && rm -f tsconfig.tsbuildinfo && rimraf @flowtyped",
26
+ "build": "tsc --build && npm run generate-flow",
20
27
  "prepublishOnly": "npm run clean && npm run build",
21
28
  "generate-flow": "ts-node ../../scripts/gen-flow.ts"
22
29
  },
23
30
  "dependencies": {
31
+ "@malloydata/motly-ts-parser": "^0.0.2",
24
32
  "assert": "^2.0.0"
25
33
  },
26
34
  "devDependencies": {
27
- "peggy": "^4.2.0",
28
35
  "rimraf": "^6.0.1",
29
36
  "ts-node": "^10.9.2"
30
37
  }
package/src/index.ts CHANGED
@@ -5,7 +5,5 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  export * from './tags';
8
- export {parseTag} from './peggy';
8
+ export {parseTag, TagParser} from './parser';
9
9
  export * as ParseUtil from './util';
10
- export {validateTag} from './schema';
11
- export type {SchemaError} from './schema';
package/src/parser.ts ADDED
@@ -0,0 +1,203 @@
1
+ /*
2
+ * Copyright Contributors to the Malloy project
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import type {MOTLYError, MOTLYNode} from '@malloydata/motly-ts-parser';
7
+ import {MOTLYSession} from '@malloydata/motly-ts-parser';
8
+ import {Tag, RefTag} from './tags';
9
+ import type {TagParse, TagError, Path} from './tags';
10
+
11
+ /**
12
+ * Strip the Malloy tag prefix (e.g., "# " or "#(docs) ") from source.
13
+ */
14
+ function stripPrefix(source: string): string {
15
+ if (source[0] === '#') {
16
+ const skipTo = source.indexOf(' ');
17
+ if (skipTo > 0) {
18
+ return source.slice(skipTo);
19
+ }
20
+ return '';
21
+ }
22
+ return source;
23
+ }
24
+
25
+ /**
26
+ * Map a MOTLYError (from motly-ts parser) to a TagError.
27
+ */
28
+ function mapMOTLYError(error: MOTLYError): TagError {
29
+ return {
30
+ code: error.code,
31
+ message: error.message,
32
+ line: error.begin.line,
33
+ offset: error.begin.column,
34
+ };
35
+ }
36
+
37
+ /**
38
+ * Parse a reference string like "$^^path.to[0].thing" back into
39
+ * structured form {ups, refPath}.
40
+ */
41
+ function parseRefString(linkTo: string): {ups: number; refPath: Path} {
42
+ let i = 1;
43
+ let ups = 0;
44
+ while (i < linkTo.length && linkTo[i] === '^') {
45
+ ups++;
46
+ i++;
47
+ }
48
+
49
+ const refPath: Path = [];
50
+ const rest = linkTo.slice(i);
51
+
52
+ if (rest.length === 0) {
53
+ return {ups, refPath};
54
+ }
55
+
56
+ let pos = 0;
57
+ let needDot = false;
58
+
59
+ while (pos < rest.length) {
60
+ if (rest[pos] === '.') {
61
+ pos++;
62
+ needDot = false;
63
+ continue;
64
+ }
65
+
66
+ if (rest[pos] === '[') {
67
+ const close = rest.indexOf(']', pos);
68
+ refPath.push(Number(rest.slice(pos + 1, close)));
69
+ pos = close + 1;
70
+ needDot = true;
71
+ continue;
72
+ }
73
+
74
+ if (needDot) {
75
+ // Expected a dot separator but didn't get one
76
+ }
77
+
78
+ if (rest[pos] === '`') {
79
+ pos++;
80
+ let seg = '';
81
+ while (pos < rest.length && rest[pos] !== '`') {
82
+ if (rest[pos] === '\\') {
83
+ pos++;
84
+ seg += rest[pos];
85
+ } else {
86
+ seg += rest[pos];
87
+ }
88
+ pos++;
89
+ }
90
+ pos++;
91
+ refPath.push(seg);
92
+ needDot = true;
93
+ continue;
94
+ }
95
+
96
+ let seg = '';
97
+ while (
98
+ pos < rest.length &&
99
+ rest[pos] !== '.' &&
100
+ rest[pos] !== '[' &&
101
+ rest[pos] !== '`'
102
+ ) {
103
+ seg += rest[pos];
104
+ pos++;
105
+ }
106
+ if (seg.length > 0) {
107
+ refPath.push(seg);
108
+ needDot = true;
109
+ }
110
+ }
111
+
112
+ return {ups, refPath};
113
+ }
114
+
115
+ function isRef(node: MOTLYNode): node is {linkTo: string} {
116
+ return 'linkTo' in node;
117
+ }
118
+
119
+ /**
120
+ * Convert a MOTLYNode tree into a Tag tree with parent links.
121
+ */
122
+ function hydrate(node: MOTLYNode, parent?: Tag): Tag {
123
+ if (isRef(node)) {
124
+ const {ups, refPath} = parseRefString(node.linkTo);
125
+ return new RefTag(ups, refPath, parent);
126
+ }
127
+
128
+ const tag = new Tag({}, parent);
129
+
130
+ if (node.eq !== undefined) {
131
+ if (Array.isArray(node.eq)) {
132
+ tag.eq = node.eq.map(el => hydrate(el, tag));
133
+ } else if (node.eq instanceof Date) {
134
+ tag.eq = new Date(node.eq);
135
+ } else {
136
+ tag.eq = node.eq;
137
+ }
138
+ }
139
+
140
+ if (node.properties !== undefined) {
141
+ tag.properties = {};
142
+ for (const [key, val] of Object.entries(node.properties)) {
143
+ tag.properties[key] = hydrate(val, tag);
144
+ }
145
+ }
146
+
147
+ if (node.deleted) {
148
+ tag.deleted = true;
149
+ }
150
+
151
+ return tag;
152
+ }
153
+
154
+ /**
155
+ * Session-based parser for Malloy tag language. Create an instance,
156
+ * call parse() for each line, then finish() to get the final Tag.
157
+ */
158
+ export class TagParser {
159
+ private session: MOTLYSession;
160
+
161
+ constructor() {
162
+ this.session = new MOTLYSession();
163
+ }
164
+
165
+ parse(source: string): TagParse {
166
+ const stripped = stripPrefix(source);
167
+ const errors = this.session.parse(stripped);
168
+ const tagErrors = errors.map(mapMOTLYError);
169
+ const value = this.session.getValue();
170
+ return {tag: hydrate(value), log: tagErrors};
171
+ }
172
+
173
+ finish(): Tag {
174
+ const value = this.session.getValue();
175
+ this.session.dispose();
176
+ return hydrate(value);
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Parse Malloy tag language into a Tag which can be queried.
182
+ *
183
+ * @param source - A single string or array of strings to parse. If a string
184
+ * starts with #, all characters up to the first space are skipped.
185
+ * When an array is provided, strings are parsed sequentially and merged.
186
+ * @returns TagParse with the resulting tag and any errors. For arrays,
187
+ * error line numbers indicate the index in the array where the error occurred.
188
+ */
189
+ export function parseTag(source: string | string[]): TagParse {
190
+ const session = new TagParser();
191
+ if (typeof source === 'string') {
192
+ return session.parse(source);
193
+ }
194
+
195
+ const allErrs: TagError[] = [];
196
+ for (let i = 0; i < source.length; i++) {
197
+ const result = session.parse(source[i]);
198
+ for (const err of result.log) {
199
+ allErrs.push({...err, line: i + err.line});
200
+ }
201
+ }
202
+ return {tag: session.finish(), log: allErrs};
203
+ }
package/CONTEXT.md DELETED
@@ -1,173 +0,0 @@
1
- # Malloy Tag Language (MOTLY)
2
-
3
- The Malloy Tag Language (also called MOTLY - Malloy Object Tagging Language) is a concise, readable syntax for adding structured metadata to Malloy objects through annotations. It's designed to work seamlessly with Malloy's annotation system and can also be used as a standalone configuration language.
4
-
5
- ## Purpose
6
-
7
- While Malloy annotations can contain arbitrary text, the Tag Language provides a standardized way to express structured metadata that is:
8
- - Human-readable and writable
9
- - Easy to parse programmatically
10
- - Flexible enough for various use cases
11
- - Concise and unobtrusive in code
12
-
13
- ## Syntax Overview
14
-
15
- The Tag Language supports several data types:
16
-
17
- ### Boolean Tags
18
- ```malloy
19
- # hidden
20
- ```
21
- A tag name without a value is a boolean (implicitly `true`).
22
-
23
- ### Typed Values
24
- Values prefixed with `@` are typed:
25
- ```malloy
26
- # enabled=@true
27
- # debug=@false
28
- # created=@2024-01-15
29
- # updated=@2024-01-15T10:30:00Z
30
- ```
31
-
32
- ### String Values
33
- ```malloy
34
- # color=blue
35
- # name="User Name"
36
- # description="""
37
- Multi-line string
38
- with preserved newlines.
39
- """
40
- ```
41
- Unquoted strings for simple values (alphanumeric and underscore), quoted strings for values with spaces or special characters, triple-quoted for multi-line.
42
-
43
- ### Numeric Values
44
- ```malloy
45
- # size=10
46
- # width=100.5
47
- # rate=-0.05
48
- ```
49
- Numbers are automatically parsed as numeric types.
50
-
51
- ### Arrays
52
- ```malloy
53
- # colors=[red, green, blue]
54
- # ports=[80, 443, 8080]
55
- # users=[{ name=alice role=admin }, { name=bob role=user }]
56
- ```
57
-
58
- ### Nested Properties
59
- ```malloy
60
- # box: { width=100 height=200 }
61
- ```
62
- Colon and curly braces create nested property groups.
63
-
64
- ### Deep Path Notation
65
- ```malloy
66
- # database.connection.pool.max=100
67
- ```
68
- Dot notation for setting nested values directly.
69
-
70
- ### Delete Property
71
- ```malloy
72
- # -deprecated_field
73
- ```
74
- Minus prefix removes a property.
75
-
76
- ### Combined Example
77
- ```malloy
78
- #(myApp) hidden color=blue size=10 box: { width=100 height=200 } name="Blue Thing"
79
- ```
80
-
81
- ## Colon vs Space Syntax
82
-
83
- Two ways to add properties to objects with different semantics:
84
-
85
- **Colon syntax (`: { }`) replaces all properties:**
86
- ```malloy
87
- # server: { host=localhost port=8080 }
88
- # server: { url="http://example.com" } # Replaces - only url remains
89
- ```
90
-
91
- **Space syntax (`{ }`) merges with existing properties:**
92
- ```malloy
93
- # server: { host=localhost }
94
- # server { port=8080 } # Merges - both host and port exist
95
- ```
96
-
97
- ## Annotation Prefixes
98
-
99
- Different prefixes are used to avoid collision between different uses of annotations:
100
-
101
- - **`# `** (hash-space) - Reserved for Malloy renderer
102
- - **`#!`** - Compiler directives
103
- - **`#(docs)`** - Malloy documentation
104
- - **`#(appName) `** - Encouraged pattern for application-specific tags
105
-
106
- Example with application prefix:
107
- ```malloy
108
- #(myApp) visible theme=dark priority=high
109
- ```
110
-
111
- ## Multi-line Annotations
112
-
113
- The tag language works with single-line annotations. For multi-line text that is NOT in the tag language:
114
-
115
- ```malloy
116
- #" This is a multi-line string annotation
117
- #" which is NOT in the tag language
118
- #" but could be displayed as help text
119
- source: name is VALUE
120
- ```
121
-
122
- ## Usage Pattern
123
-
124
- The expected workflow for using tag annotations:
125
-
126
- 1. **Write annotations** in Malloy code using tag syntax
127
- 2. **Query annotations** from compiled model using pattern matching (filter by prefix)
128
- 3. **Parse tags** using the malloy-tag package
129
- 4. **Extract values** and use in your application
130
-
131
- ## Implementation
132
-
133
- The `malloy-tag` package provides:
134
- - **Peggy-based parser** for tag language syntax
135
- - **Tag class** with methods for type-safe value access
136
- - **Type definitions** for parsed tag structures
137
-
138
- ### Key API Methods
139
-
140
- ```typescript
141
- import {Tag} from '@malloydata/malloy-tag';
142
-
143
- const {tag, log} = Tag.parse('enabled=@true port=8080 name="My App"');
144
-
145
- // Convert to plain JavaScript object
146
- const obj = tag.toObject(); // { enabled: true, port: 8080, name: "My App" }
147
-
148
- // Type-safe accessors
149
- tag.text('name'); // "My App"
150
- tag.numeric('port'); // 8080
151
- tag.boolean('enabled'); // true
152
- tag.isTrue('enabled'); // true
153
- tag.date('created'); // Date object
154
- tag.textArray('features'); // string[]
155
- tag.has('name'); // true
156
-
157
- // Nested access
158
- tag.text('server', 'host');
159
- tag.tag('server'); // Get nested Tag object
160
- ```
161
-
162
- ## Documentation
163
-
164
- For complete tag language syntax and examples, see:
165
- - `docs/motly.md` in this package (comprehensive reference)
166
- - https://docs.malloydata.dev/documentation/language/tags
167
-
168
- ## Important Notes
169
-
170
- - Not all annotations use the tag language - raw text is also valid
171
- - The tag language is optional - annotations can be simple strings
172
- - Each application defines its own conventions for tag usage
173
- - Tags are metadata only - they don't affect query execution
package/README.md DELETED
File without changes
@@ -1,11 +0,0 @@
1
- declare function peg$SyntaxError(message: any, expected: any, found: any, location: any): Error;
2
- declare class peg$SyntaxError {
3
- constructor(message: any, expected: any, found: any, location: any);
4
- format(sources: any): string;
5
- }
6
- declare namespace peg$SyntaxError {
7
- function buildMessage(expected: any, found: any): string;
8
- }
9
- declare function peg$parse(input: any, options: any): any;
10
- export declare let StartRules: string[];
11
- export { peg$SyntaxError as SyntaxError, peg$parse as parse };