@markuplint/spec-generator 4.8.0 → 4.8.2
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/ARCHITECTURE.ja.md +178 -0
- package/ARCHITECTURE.md +178 -0
- package/CHANGELOG.md +9 -5
- package/README.md +29 -41
- package/SKILL.md +134 -0
- package/docs/maintenance.ja.md +212 -0
- package/docs/maintenance.md +212 -0
- package/docs/modules.ja.md +252 -0
- package/docs/modules.md +252 -0
- package/docs/scraping.ja.md +320 -0
- package/docs/scraping.md +320 -0
- package/lib/aria.d.ts +6 -0
- package/lib/aria.js +45 -0
- package/lib/fetch.d.ts +21 -0
- package/lib/fetch.js +28 -1
- package/lib/global-attrs.d.ts +6 -0
- package/lib/global-attrs.js +6 -0
- package/lib/html-elements.d.ts +8 -0
- package/lib/html-elements.js +31 -9
- package/lib/index.d.ts +22 -0
- package/lib/index.js +15 -0
- package/lib/read-json.d.ts +18 -0
- package/lib/read-json.js +18 -0
- package/lib/scraping.d.ts +15 -0
- package/lib/scraping.js +52 -0
- package/lib/svg.d.ts +7 -0
- package/lib/svg.js +7 -0
- package/lib/utils.d.ts +59 -0
- package/lib/utils.js +56 -0
- package/package.json +7 -7
package/lib/read-json.js
CHANGED
|
@@ -2,6 +2,14 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { glob } from 'glob';
|
|
4
4
|
import strip from 'strip-json-comments';
|
|
5
|
+
/**
|
|
6
|
+
* Reads and parses a single JSON file (with support for JSON comments) from an absolute file path.
|
|
7
|
+
*
|
|
8
|
+
* @template T - The expected shape of the parsed JSON data
|
|
9
|
+
* @param filePath - The absolute file path to the JSON file
|
|
10
|
+
* @returns The parsed JSON content
|
|
11
|
+
* @throws If the provided path is not absolute
|
|
12
|
+
*/
|
|
5
13
|
export function readJson(filePath) {
|
|
6
14
|
if (!path.isAbsolute(filePath)) {
|
|
7
15
|
throw new Error(`The path must be absolute path: ${filePath}`);
|
|
@@ -10,6 +18,16 @@ export function readJson(filePath) {
|
|
|
10
18
|
json = strip(json);
|
|
11
19
|
return JSON.parse(json);
|
|
12
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Reads multiple JSON files matching a glob pattern and optionally transforms each result.
|
|
23
|
+
* All matched files are read and parsed in parallel.
|
|
24
|
+
*
|
|
25
|
+
* @template T - The expected shape of each parsed JSON file
|
|
26
|
+
* @param pattern - An absolute glob pattern to match JSON files
|
|
27
|
+
* @param hook - An optional transformation function called with each file path and its parsed body
|
|
28
|
+
* @returns An array of parsed (and optionally transformed) JSON objects
|
|
29
|
+
* @throws If the provided pattern is not an absolute path
|
|
30
|
+
*/
|
|
13
31
|
export async function readJsons(pattern, hook = (_, body) => body) {
|
|
14
32
|
if (!path.isAbsolute(pattern)) {
|
|
15
33
|
throw new Error(`The pattern must be absolute path: ${pattern}`);
|
package/lib/scraping.d.ts
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
1
|
import type { ExtendedElementSpec } from '@markuplint/ml-spec';
|
|
2
|
+
/**
|
|
3
|
+
* Generates minimal element specification stubs for obsolete/deprecated elements
|
|
4
|
+
* that do not already exist in the provided specs array.
|
|
5
|
+
*
|
|
6
|
+
* @param obsoleteList - A list of element names considered obsolete or deprecated
|
|
7
|
+
* @param specs - The existing element specifications to check against for duplicates
|
|
8
|
+
* @returns An array of element spec stubs for elements not already present in `specs`
|
|
9
|
+
*/
|
|
2
10
|
export declare function fetchObsoleteElements(obsoleteList: readonly string[], specs: readonly ExtendedElementSpec[]): ExtendedElementSpec[];
|
|
11
|
+
/**
|
|
12
|
+
* Scrapes an MDN element reference page to extract metadata about an HTML or SVG element.
|
|
13
|
+
* Gathers description, compatibility status flags, content categories, and attributes.
|
|
14
|
+
*
|
|
15
|
+
* @param link - The MDN URL for the element (e.g., `https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/a`)
|
|
16
|
+
* @returns An extended element specification object populated with scraped MDN data
|
|
17
|
+
*/
|
|
3
18
|
export declare function fetchHTMLElement(link: string): Promise<ExtendedElementSpec>;
|
package/lib/scraping.js
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { fetch } from './fetch.js';
|
|
2
2
|
import { sortObjectByKey } from './utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* CSS selector for the main content area on MDN pages.
|
|
5
|
+
*/
|
|
3
6
|
const MAIN_ARTICLE_SELECTOR = 'main#content';
|
|
7
|
+
/**
|
|
8
|
+
* Generates minimal element specification stubs for obsolete/deprecated elements
|
|
9
|
+
* that do not already exist in the provided specs array.
|
|
10
|
+
*
|
|
11
|
+
* @param obsoleteList - A list of element names considered obsolete or deprecated
|
|
12
|
+
* @param specs - The existing element specifications to check against for duplicates
|
|
13
|
+
* @returns An array of element spec stubs for elements not already present in `specs`
|
|
14
|
+
*/
|
|
4
15
|
export function fetchObsoleteElements(obsoleteList, specs) {
|
|
5
16
|
return obsoleteList
|
|
6
17
|
.map(name => {
|
|
@@ -27,6 +38,13 @@ export function fetchObsoleteElements(obsoleteList, specs) {
|
|
|
27
38
|
})
|
|
28
39
|
.filter((e) => !!e);
|
|
29
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Scrapes an MDN element reference page to extract metadata about an HTML or SVG element.
|
|
43
|
+
* Gathers description, compatibility status flags, content categories, and attributes.
|
|
44
|
+
*
|
|
45
|
+
* @param link - The MDN URL for the element (e.g., `https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/a`)
|
|
46
|
+
* @returns An extended element specification object populated with scraped MDN data
|
|
47
|
+
*/
|
|
30
48
|
export async function fetchHTMLElement(link) {
|
|
31
49
|
const $ = await fetch(link);
|
|
32
50
|
const name = link.replace(/.+\/([\w-]+)$/, '$1').toLowerCase();
|
|
@@ -116,6 +134,13 @@ export async function fetchHTMLElement(link) {
|
|
|
116
134
|
};
|
|
117
135
|
return spec;
|
|
118
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Extracts the text value of a specific property from the MDN technical summary table.
|
|
139
|
+
*
|
|
140
|
+
* @param $ - The Cheerio API instance for the page
|
|
141
|
+
* @param prop - The property name to look for in the table header cells (matched case-insensitively)
|
|
142
|
+
* @returns The trimmed text content of the corresponding table cell
|
|
143
|
+
*/
|
|
119
144
|
function getProperty(
|
|
120
145
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
121
146
|
$, prop) {
|
|
@@ -126,6 +151,15 @@ $, prop) {
|
|
|
126
151
|
.filter(el => new RegExp(prop, 'i').test($(el).text())));
|
|
127
152
|
return $th.siblings('td').text().trim().replaceAll(/\s+/g, ' ');
|
|
128
153
|
}
|
|
154
|
+
/**
|
|
155
|
+
* Extracts element attributes from an MDN page section identified by its `aria-labelledby` ID.
|
|
156
|
+
* Parses each `<dt>` entry in the section's definition list to gather attribute name,
|
|
157
|
+
* description, and status flags (experimental, obsolete, deprecated, non-standard).
|
|
158
|
+
*
|
|
159
|
+
* @param $ - The Cheerio API instance for the page
|
|
160
|
+
* @param id - The `aria-labelledby` ID of the section containing the attributes
|
|
161
|
+
* @returns An object containing a record of parsed attribute definitions keyed by attribute name
|
|
162
|
+
*/
|
|
129
163
|
function getAttributes(
|
|
130
164
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
131
165
|
$, id) {
|
|
@@ -185,6 +219,12 @@ $, id) {
|
|
|
185
219
|
}
|
|
186
220
|
return { attributes };
|
|
187
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* Traverses the DOM upward from a starting element to find its nearest preceding heading element.
|
|
224
|
+
*
|
|
225
|
+
* @param $start - The Cheerio element from which to begin the upward search
|
|
226
|
+
* @returns The heading element if found, or `null` if no heading is encountered
|
|
227
|
+
*/
|
|
188
228
|
function getItsHeading(
|
|
189
229
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
190
230
|
$start) {
|
|
@@ -197,6 +237,12 @@ $start) {
|
|
|
197
237
|
}
|
|
198
238
|
return null;
|
|
199
239
|
}
|
|
240
|
+
/**
|
|
241
|
+
* Moves to the previous sibling of the given element, or to its parent if no previous sibling exists.
|
|
242
|
+
*
|
|
243
|
+
* @param $start - The Cheerio element from which to navigate
|
|
244
|
+
* @returns The previous sibling or parent element
|
|
245
|
+
*/
|
|
200
246
|
function upToPrevOrParent(
|
|
201
247
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
202
248
|
$start) {
|
|
@@ -206,6 +252,12 @@ $start) {
|
|
|
206
252
|
}
|
|
207
253
|
return $needle;
|
|
208
254
|
}
|
|
255
|
+
/**
|
|
256
|
+
* Checks whether a Cheerio element is an HTML heading element (`<h1>` through `<h6>`).
|
|
257
|
+
*
|
|
258
|
+
* @param $el - The Cheerio element to test
|
|
259
|
+
* @returns `true` if the element is a heading, `false` otherwise
|
|
260
|
+
*/
|
|
209
261
|
function isHeading(
|
|
210
262
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
211
263
|
$el) {
|
package/lib/svg.d.ts
CHANGED
|
@@ -1 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetches the MDN SVG element index page and extracts the list of
|
|
3
|
+
* obsolete and deprecated SVG element names.
|
|
4
|
+
* Each name is prefixed with `"svg_"` to distinguish it from HTML elements.
|
|
5
|
+
*
|
|
6
|
+
* @returns An array of deprecated/obsolete SVG element names (e.g., `["svg_altGlyph", ...]`)
|
|
7
|
+
*/
|
|
1
8
|
export declare function getSVGElementList(): Promise<string[]>;
|
package/lib/svg.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { fetch } from './fetch.js';
|
|
2
2
|
import { getThisOutline } from './utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* Fetches the MDN SVG element index page and extracts the list of
|
|
5
|
+
* obsolete and deprecated SVG element names.
|
|
6
|
+
* Each name is prefixed with `"svg_"` to distinguish it from HTML elements.
|
|
7
|
+
*
|
|
8
|
+
* @returns An array of deprecated/obsolete SVG element names (e.g., `["svg_altGlyph", ...]`)
|
|
9
|
+
*/
|
|
3
10
|
export async function getSVGElementList() {
|
|
4
11
|
const index = 'https://developer.mozilla.org/en-US/docs/Web/SVG/Element';
|
|
5
12
|
const $ = await fetch(index);
|
package/lib/utils.d.ts
CHANGED
|
@@ -1,14 +1,73 @@
|
|
|
1
1
|
import type * as cheerio from 'cheerio';
|
|
2
2
|
import type { AnyNode } from 'domhandler';
|
|
3
|
+
/**
|
|
4
|
+
* Represents an object that has a `name` property.
|
|
5
|
+
*/
|
|
3
6
|
type HasName = {
|
|
4
7
|
readonly name: string;
|
|
5
8
|
};
|
|
9
|
+
/**
|
|
10
|
+
* Compares two items by their name property (or string value) in a case-insensitive manner.
|
|
11
|
+
* Suitable for use as a comparator function in `Array.prototype.sort`.
|
|
12
|
+
*
|
|
13
|
+
* @param a - The first item to compare, either a string or an object with a `name` property
|
|
14
|
+
* @param b - The second item to compare, either a string or an object with a `name` property
|
|
15
|
+
* @returns A negative number if `a` comes before `b`, positive if after, or zero if equal
|
|
16
|
+
*/
|
|
6
17
|
export declare function nameCompare(a: HasName | string, b: HasName | string): 1 | 0 | -1;
|
|
18
|
+
/**
|
|
19
|
+
* Creates a new object with the same key-value pairs, sorted alphabetically by key.
|
|
20
|
+
*
|
|
21
|
+
* @template T - The type of the object
|
|
22
|
+
* @param o - The object whose keys should be sorted
|
|
23
|
+
* @returns A new object with keys in sorted alphabetical order
|
|
24
|
+
*/
|
|
7
25
|
export declare function sortObjectByKey<T>(o: T): T;
|
|
26
|
+
/**
|
|
27
|
+
* Removes duplicate items from an array based on their `name` property,
|
|
28
|
+
* keeping only the first occurrence.
|
|
29
|
+
*
|
|
30
|
+
* @template T - The type of array items, must have a `name` property
|
|
31
|
+
* @param array - The array to deduplicate
|
|
32
|
+
* @returns A new array with unique items by name
|
|
33
|
+
*/
|
|
8
34
|
export declare function arrayUnique<T extends HasName>(array: readonly T[]): T[];
|
|
35
|
+
/**
|
|
36
|
+
* Collects all sibling elements following a starting element until the next `<h2>` heading
|
|
37
|
+
* (or end of siblings) and wraps them in a container `<div>`.
|
|
38
|
+
* Useful for extracting a section of content defined by a heading.
|
|
39
|
+
*
|
|
40
|
+
* @param $ - The Cheerio API instance for DOM manipulation
|
|
41
|
+
* @param $start - The starting element (typically a heading) from which to collect siblings
|
|
42
|
+
* @returns A Cheerio wrapper around a `<div>` containing cloned elements of the section
|
|
43
|
+
*/
|
|
9
44
|
export declare function getThisOutline($: cheerio.CheerioAPI, $start: cheerio.Cheerio<AnyNode>): cheerio.Cheerio<AnyNode>;
|
|
45
|
+
/**
|
|
46
|
+
* Merges two attribute objects, with values from `fromJSON` taking precedence
|
|
47
|
+
* over values from `fromDocs` when keys overlap.
|
|
48
|
+
*
|
|
49
|
+
* @template T - The type of the attribute objects
|
|
50
|
+
* @param fromDocs - Attribute data sourced from documentation
|
|
51
|
+
* @param fromJSON - Attribute data sourced from JSON specification files
|
|
52
|
+
* @returns A merged object combining both sources
|
|
53
|
+
*/
|
|
10
54
|
export declare function mergeAttributes<T>(fromDocs: T, fromJSON: T): T;
|
|
55
|
+
/**
|
|
56
|
+
* Returns the keys of an object with a custom type cast.
|
|
57
|
+
*
|
|
58
|
+
* @template T - The type of the input object
|
|
59
|
+
* @template K - The desired key type (defaults to `keyof T`)
|
|
60
|
+
* @param object - The object whose keys to extract
|
|
61
|
+
* @returns An array of the object's keys cast to the specified type
|
|
62
|
+
*/
|
|
11
63
|
export declare function keys<T, K = keyof T>(object: T): K[];
|
|
64
|
+
/**
|
|
65
|
+
* Parses an element name string to extract the local name, namespace, and markup language type.
|
|
66
|
+
* Handles SVG-prefixed names (e.g., `"svg_circle"`) and plain HTML names.
|
|
67
|
+
*
|
|
68
|
+
* @param origin - The raw element name, optionally prefixed with `"svg_"` for SVG elements
|
|
69
|
+
* @returns An object containing the `localName`, optional SVG `namespace` URI, and `ml` type (`"SVG"` or `"HTML"`)
|
|
70
|
+
*/
|
|
12
71
|
export declare function getName(origin: string): {
|
|
13
72
|
localName: string;
|
|
14
73
|
namespace: "http://www.w3.org/2000/svg" | undefined;
|
package/lib/utils.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compares two items by their name property (or string value) in a case-insensitive manner.
|
|
3
|
+
* Suitable for use as a comparator function in `Array.prototype.sort`.
|
|
4
|
+
*
|
|
5
|
+
* @param a - The first item to compare, either a string or an object with a `name` property
|
|
6
|
+
* @param b - The second item to compare, either a string or an object with a `name` property
|
|
7
|
+
* @returns A negative number if `a` comes before `b`, positive if after, or zero if equal
|
|
8
|
+
*/
|
|
1
9
|
export function nameCompare(a, b) {
|
|
2
10
|
const nameA = typeof a === 'string' ? a : (a.name?.toUpperCase() ?? String(a));
|
|
3
11
|
const nameB = typeof b === 'string' ? b : (b.name?.toUpperCase() ?? String(b));
|
|
@@ -9,6 +17,13 @@ export function nameCompare(a, b) {
|
|
|
9
17
|
}
|
|
10
18
|
return 0;
|
|
11
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Creates a new object with the same key-value pairs, sorted alphabetically by key.
|
|
22
|
+
*
|
|
23
|
+
* @template T - The type of the object
|
|
24
|
+
* @param o - The object whose keys should be sorted
|
|
25
|
+
* @returns A new object with keys in sorted alphabetical order
|
|
26
|
+
*/
|
|
12
27
|
export function sortObjectByKey(o) {
|
|
13
28
|
// @ts-ignore
|
|
14
29
|
const keys = Object.keys(o);
|
|
@@ -21,6 +36,14 @@ export function sortObjectByKey(o) {
|
|
|
21
36
|
}
|
|
22
37
|
return newObj;
|
|
23
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Removes duplicate items from an array based on their `name` property,
|
|
41
|
+
* keeping only the first occurrence.
|
|
42
|
+
*
|
|
43
|
+
* @template T - The type of array items, must have a `name` property
|
|
44
|
+
* @param array - The array to deduplicate
|
|
45
|
+
* @returns A new array with unique items by name
|
|
46
|
+
*/
|
|
24
47
|
export function arrayUnique(array) {
|
|
25
48
|
const nameStack = [];
|
|
26
49
|
const result = [];
|
|
@@ -33,6 +56,15 @@ export function arrayUnique(array) {
|
|
|
33
56
|
}
|
|
34
57
|
return result;
|
|
35
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Collects all sibling elements following a starting element until the next `<h2>` heading
|
|
61
|
+
* (or end of siblings) and wraps them in a container `<div>`.
|
|
62
|
+
* Useful for extracting a section of content defined by a heading.
|
|
63
|
+
*
|
|
64
|
+
* @param $ - The Cheerio API instance for DOM manipulation
|
|
65
|
+
* @param $start - The starting element (typically a heading) from which to collect siblings
|
|
66
|
+
* @returns A Cheerio wrapper around a `<div>` containing cloned elements of the section
|
|
67
|
+
*/
|
|
36
68
|
export function getThisOutline(
|
|
37
69
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
38
70
|
$,
|
|
@@ -49,16 +81,40 @@ $start) {
|
|
|
49
81
|
$container.append(el);
|
|
50
82
|
return $container;
|
|
51
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Merges two attribute objects, with values from `fromJSON` taking precedence
|
|
86
|
+
* over values from `fromDocs` when keys overlap.
|
|
87
|
+
*
|
|
88
|
+
* @template T - The type of the attribute objects
|
|
89
|
+
* @param fromDocs - Attribute data sourced from documentation
|
|
90
|
+
* @param fromJSON - Attribute data sourced from JSON specification files
|
|
91
|
+
* @returns A merged object combining both sources
|
|
92
|
+
*/
|
|
52
93
|
export function mergeAttributes(fromDocs, fromJSON) {
|
|
53
94
|
return {
|
|
54
95
|
...fromDocs,
|
|
55
96
|
...fromJSON,
|
|
56
97
|
};
|
|
57
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Returns the keys of an object with a custom type cast.
|
|
101
|
+
*
|
|
102
|
+
* @template T - The type of the input object
|
|
103
|
+
* @template K - The desired key type (defaults to `keyof T`)
|
|
104
|
+
* @param object - The object whose keys to extract
|
|
105
|
+
* @returns An array of the object's keys cast to the specified type
|
|
106
|
+
*/
|
|
58
107
|
export function keys(object) {
|
|
59
108
|
// @ts-ignore
|
|
60
109
|
return Object.keys(object);
|
|
61
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Parses an element name string to extract the local name, namespace, and markup language type.
|
|
113
|
+
* Handles SVG-prefixed names (e.g., `"svg_circle"`) and plain HTML names.
|
|
114
|
+
*
|
|
115
|
+
* @param origin - The raw element name, optionally prefixed with `"svg_"` for SVG elements
|
|
116
|
+
* @returns An object containing the `localName`, optional SVG `namespace` URI, and `ml` type (`"SVG"` or `"HTML"`)
|
|
117
|
+
*/
|
|
62
118
|
export function getName(origin) {
|
|
63
119
|
const [, ns, localName] = origin.match(/^(?:(svg)_)?(\w+)/i) ?? [];
|
|
64
120
|
const name = localName ?? origin;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/spec-generator",
|
|
3
|
-
"version": "4.8.
|
|
3
|
+
"version": "4.8.2",
|
|
4
4
|
"description": "Generates @markuplint/html-spec",
|
|
5
5
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
6
6
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
@@ -23,17 +23,17 @@
|
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@types/cheerio": "1.0.0",
|
|
25
25
|
"ajv": "8.17.1",
|
|
26
|
-
"cheerio": "1.
|
|
26
|
+
"cheerio": "1.2.0",
|
|
27
27
|
"cli-progress": "3.12.0",
|
|
28
|
-
"fast-xml-parser": "5.
|
|
29
|
-
"glob": "
|
|
28
|
+
"fast-xml-parser": "5.3.5",
|
|
29
|
+
"glob": "13.0.1",
|
|
30
30
|
"strip-json-comments": "5.0.3"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@markuplint/ml-spec": "4.10.
|
|
34
|
-
"@markuplint/test-tools": "4.5.
|
|
33
|
+
"@markuplint/ml-spec": "4.10.2",
|
|
34
|
+
"@markuplint/test-tools": "4.5.23",
|
|
35
35
|
"@types/cli-progress": "3.11.6",
|
|
36
36
|
"type-fest": "4.41.0"
|
|
37
37
|
},
|
|
38
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "193ee7c1262bbed95424e38efdf1a8e56ff049f4"
|
|
39
39
|
}
|