@jomae/catalog 0.4.0 → 0.7.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/README.md +21 -3
- package/dist/baseline.d.ts +25 -0
- package/dist/baseline.d.ts.map +1 -1
- package/dist/baseline.js +25 -1
- package/dist/baseline.js.map +1 -1
- package/dist/categories.d.ts +20 -0
- package/dist/categories.d.ts.map +1 -0
- package/dist/categories.js +62 -0
- package/dist/categories.js.map +1 -0
- package/dist/detect.d.ts +2 -1
- package/dist/detect.d.ts.map +1 -1
- package/dist/detect.js +17 -2
- package/dist/detect.js.map +1 -1
- package/dist/generated/baseline-history.d.ts +21 -0
- package/dist/generated/baseline-history.d.ts.map +1 -0
- package/dist/generated/baseline-history.js +20 -0
- package/dist/generated/baseline-history.js.map +1 -0
- package/dist/generated/baseline.d.ts +10 -0
- package/dist/generated/baseline.d.ts.map +1 -1
- package/dist/generated/baseline.js +250 -67
- package/dist/generated/baseline.js.map +1 -1
- package/dist/generated/guides.d.ts +16 -0
- package/dist/generated/guides.d.ts.map +1 -0
- package/dist/generated/guides.js +153 -0
- package/dist/generated/guides.js.map +1 -0
- package/dist/generated/sizes.d.ts.map +1 -1
- package/dist/generated/sizes.js +280 -55
- package/dist/generated/sizes.js.map +1 -1
- package/dist/generated/support-claims.d.ts +15 -0
- package/dist/generated/support-claims.d.ts.map +1 -0
- package/dist/generated/support-claims.js +69 -0
- package/dist/generated/support-claims.js.map +1 -0
- package/dist/guides.d.ts +46 -0
- package/dist/guides.d.ts.map +1 -0
- package/dist/guides.js +55 -0
- package/dist/guides.js.map +1 -0
- package/dist/history.d.ts +11 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +14 -0
- package/dist/history.js.map +1 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/markdown.d.ts +24 -0
- package/dist/markdown.d.ts.map +1 -0
- package/dist/markdown.js +194 -0
- package/dist/markdown.js.map +1 -0
- package/dist/rules/abort-controller.d.ts.map +1 -1
- package/dist/rules/abort-controller.js +2 -1
- package/dist/rules/abort-controller.js.map +1 -1
- package/dist/rules/accordion.d.ts.map +1 -1
- package/dist/rules/accordion.js +3 -0
- package/dist/rules/accordion.js.map +1 -1
- package/dist/rules/array-grouping.d.ts +3 -0
- package/dist/rules/array-grouping.d.ts.map +1 -0
- package/dist/rules/array-grouping.js +29 -0
- package/dist/rules/array-grouping.js.map +1 -0
- package/dist/rules/aspect-ratio.d.ts.map +1 -1
- package/dist/rules/aspect-ratio.js +1 -0
- package/dist/rules/aspect-ratio.js.map +1 -1
- package/dist/rules/base64.d.ts +3 -0
- package/dist/rules/base64.d.ts.map +1 -0
- package/dist/rules/base64.js +41 -0
- package/dist/rules/base64.js.map +1 -0
- package/dist/rules/broadcast-channel.d.ts.map +1 -1
- package/dist/rules/broadcast-channel.js +1 -0
- package/dist/rules/broadcast-channel.js.map +1 -1
- package/dist/rules/carousel.d.ts.map +1 -1
- package/dist/rules/carousel.js +7 -0
- package/dist/rules/carousel.js.map +1 -1
- package/dist/rules/clipboard.d.ts.map +1 -1
- package/dist/rules/clipboard.js +4 -1
- package/dist/rules/clipboard.js.map +1 -1
- package/dist/rules/color-functions.d.ts.map +1 -1
- package/dist/rules/color-functions.js +1 -0
- package/dist/rules/color-functions.js.map +1 -1
- package/dist/rules/compression-streams.d.ts.map +1 -1
- package/dist/rules/compression-streams.js +2 -1
- package/dist/rules/compression-streams.js.map +1 -1
- package/dist/rules/container-queries.d.ts.map +1 -1
- package/dist/rules/container-queries.js +2 -0
- package/dist/rules/container-queries.js.map +1 -1
- package/dist/rules/content-visibility.d.ts.map +1 -1
- package/dist/rules/content-visibility.js +3 -1
- package/dist/rules/content-visibility.js.map +1 -1
- package/dist/rules/custom-highlight.d.ts +3 -0
- package/dist/rules/custom-highlight.d.ts.map +1 -0
- package/dist/rules/custom-highlight.js +39 -0
- package/dist/rules/custom-highlight.js.map +1 -0
- package/dist/rules/date-time-input.d.ts.map +1 -1
- package/dist/rules/date-time-input.js +2 -0
- package/dist/rules/date-time-input.js.map +1 -1
- package/dist/rules/dialog.d.ts.map +1 -1
- package/dist/rules/dialog.js +8 -0
- package/dist/rules/dialog.js.map +1 -1
- package/dist/rules/discrete-transitions.d.ts.map +1 -1
- package/dist/rules/discrete-transitions.js +6 -0
- package/dist/rules/discrete-transitions.js.map +1 -1
- package/dist/rules/drag-and-drop.d.ts.map +1 -1
- package/dist/rules/drag-and-drop.js +26 -8
- package/dist/rules/drag-and-drop.js.map +1 -1
- package/dist/rules/duration-format.d.ts +3 -0
- package/dist/rules/duration-format.d.ts.map +1 -0
- package/dist/rules/duration-format.js +37 -0
- package/dist/rules/duration-format.js.map +1 -0
- package/dist/rules/event-target.d.ts +3 -0
- package/dist/rules/event-target.d.ts.map +1 -0
- package/dist/rules/event-target.js +51 -0
- package/dist/rules/event-target.js.map +1 -0
- package/dist/rules/fetch.d.ts +3 -0
- package/dist/rules/fetch.d.ts.map +1 -0
- package/dist/rules/fetch.js +46 -0
- package/dist/rules/fetch.js.map +1 -0
- package/dist/rules/field-sizing.d.ts.map +1 -1
- package/dist/rules/field-sizing.js +3 -1
- package/dist/rules/field-sizing.js.map +1 -1
- package/dist/rules/fluid-type.d.ts.map +1 -1
- package/dist/rules/fluid-type.js +3 -1
- package/dist/rules/fluid-type.js.map +1 -1
- package/dist/rules/focus-visible.d.ts.map +1 -1
- package/dist/rules/focus-visible.js +1 -0
- package/dist/rules/focus-visible.js.map +1 -1
- package/dist/rules/fullscreen.d.ts.map +1 -1
- package/dist/rules/fullscreen.js +2 -1
- package/dist/rules/fullscreen.js.map +1 -1
- package/dist/rules/height-animation.d.ts.map +1 -1
- package/dist/rules/height-animation.js +2 -0
- package/dist/rules/height-animation.js.map +1 -1
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +64 -3
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/inert.d.ts +3 -0
- package/dist/rules/inert.d.ts.map +1 -0
- package/dist/rules/inert.js +37 -0
- package/dist/rules/inert.js.map +1 -0
- package/dist/rules/intersection-observer.d.ts.map +1 -1
- package/dist/rules/intersection-observer.js +2 -0
- package/dist/rules/intersection-observer.js.map +1 -1
- package/dist/rules/lazy-loading.d.ts.map +1 -1
- package/dist/rules/lazy-loading.js +2 -0
- package/dist/rules/lazy-loading.js.map +1 -1
- package/dist/rules/line-clamp.d.ts.map +1 -1
- package/dist/rules/line-clamp.js +2 -1
- package/dist/rules/line-clamp.js.map +1 -1
- package/dist/rules/masonry.d.ts.map +1 -1
- package/dist/rules/masonry.js +1 -0
- package/dist/rules/masonry.js.map +1 -1
- package/dist/rules/natural-sort.d.ts +3 -0
- package/dist/rules/natural-sort.d.ts.map +1 -0
- package/dist/rules/natural-sort.js +41 -0
- package/dist/rules/natural-sort.js.map +1 -0
- package/dist/rules/number-format.d.ts.map +1 -1
- package/dist/rules/number-format.js +3 -1
- package/dist/rules/number-format.js.map +1 -1
- package/dist/rules/page-visibility.d.ts.map +1 -1
- package/dist/rules/page-visibility.js +5 -0
- package/dist/rules/page-visibility.js.map +1 -1
- package/dist/rules/popover.d.ts.map +1 -1
- package/dist/rules/popover.js +8 -1
- package/dist/rules/popover.js.map +1 -1
- package/dist/rules/random-uuid.d.ts +3 -0
- package/dist/rules/random-uuid.d.ts.map +1 -0
- package/dist/rules/random-uuid.js +31 -0
- package/dist/rules/random-uuid.js.map +1 -0
- package/dist/rules/relative-time.d.ts.map +1 -1
- package/dist/rules/relative-time.js +1 -0
- package/dist/rules/relative-time.js.map +1 -1
- package/dist/rules/resizable-panels.d.ts.map +1 -1
- package/dist/rules/resizable-panels.js +4 -7
- package/dist/rules/resizable-panels.js.map +1 -1
- package/dist/rules/resize-observer.d.ts.map +1 -1
- package/dist/rules/resize-observer.js +2 -1
- package/dist/rules/resize-observer.js.map +1 -1
- package/dist/rules/screen-wake-lock.d.ts.map +1 -1
- package/dist/rules/screen-wake-lock.js +3 -1
- package/dist/rules/screen-wake-lock.js.map +1 -1
- package/dist/rules/scroll-animations.d.ts.map +1 -1
- package/dist/rules/scroll-animations.js +9 -1
- package/dist/rules/scroll-animations.js.map +1 -1
- package/dist/rules/scroll-lock.d.ts.map +1 -1
- package/dist/rules/scroll-lock.js +8 -7
- package/dist/rules/scroll-lock.js.map +1 -1
- package/dist/rules/scrollbars.d.ts.map +1 -1
- package/dist/rules/scrollbars.js +5 -0
- package/dist/rules/scrollbars.js.map +1 -1
- package/dist/rules/select.d.ts.map +1 -1
- package/dist/rules/select.js +7 -0
- package/dist/rules/select.js.map +1 -1
- package/dist/rules/server-sent-events.d.ts +3 -0
- package/dist/rules/server-sent-events.d.ts.map +1 -0
- package/dist/rules/server-sent-events.js +38 -0
- package/dist/rules/server-sent-events.js.map +1 -0
- package/dist/rules/smooth-scroll.d.ts.map +1 -1
- package/dist/rules/smooth-scroll.js +2 -0
- package/dist/rules/smooth-scroll.js.map +1 -1
- package/dist/rules/speech-recognition.d.ts.map +1 -1
- package/dist/rules/speech-recognition.js +19 -10
- package/dist/rules/speech-recognition.js.map +1 -1
- package/dist/rules/speech-synthesis.d.ts.map +1 -1
- package/dist/rules/speech-synthesis.js +3 -0
- package/dist/rules/speech-synthesis.js.map +1 -1
- package/dist/rules/sticky.d.ts.map +1 -1
- package/dist/rules/sticky.js +2 -0
- package/dist/rules/sticky.js.map +1 -1
- package/dist/rules/structured-clone.d.ts.map +1 -1
- package/dist/rules/structured-clone.js +13 -2
- package/dist/rules/structured-clone.js.map +1 -1
- package/dist/rules/text-box-trim.d.ts.map +1 -1
- package/dist/rules/text-box-trim.js +3 -1
- package/dist/rules/text-box-trim.js.map +1 -1
- package/dist/rules/text-wrap-balance.d.ts.map +1 -1
- package/dist/rules/text-wrap-balance.js +2 -0
- package/dist/rules/text-wrap-balance.js.map +1 -1
- package/dist/rules/url-search-params.d.ts +3 -0
- package/dist/rules/url-search-params.d.ts.map +1 -0
- package/dist/rules/url-search-params.js +42 -0
- package/dist/rules/url-search-params.js.map +1 -0
- package/dist/rules/view-transitions.d.ts.map +1 -1
- package/dist/rules/view-transitions.js +9 -0
- package/dist/rules/view-transitions.js.map +1 -1
- package/dist/rules/web-bluetooth.d.ts.map +1 -1
- package/dist/rules/web-bluetooth.js +1 -0
- package/dist/rules/web-bluetooth.js.map +1 -1
- package/dist/rules/web-crypto.d.ts +3 -0
- package/dist/rules/web-crypto.d.ts.map +1 -0
- package/dist/rules/web-crypto.js +32 -0
- package/dist/rules/web-crypto.js.map +1 -0
- package/dist/rules/web-share.d.ts.map +1 -1
- package/dist/rules/web-share.js +1 -0
- package/dist/rules/web-share.js.map +1 -1
- package/dist/schema.d.ts +22 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +63 -4
- package/dist/schema.js.map +1 -1
- package/dist/search.d.ts +29 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +84 -0
- package/dist/search.js.map +1 -0
- package/dist/support.d.ts +11 -0
- package/dist/support.d.ts.map +1 -0
- package/dist/support.js +31 -0
- package/dist/support.js.map +1 -0
- package/package.json +2 -2
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
export const structuredCloneRule = {
|
|
2
2
|
id: "structured-clone",
|
|
3
3
|
title: "Deep cloning",
|
|
4
|
-
|
|
4
|
+
category: "async-data",
|
|
5
|
+
replaces: [
|
|
6
|
+
"lodash.clonedeep",
|
|
7
|
+
"rfdc",
|
|
8
|
+
"clone",
|
|
9
|
+
"klona",
|
|
10
|
+
"clone-deep",
|
|
11
|
+
"fast-copy",
|
|
12
|
+
"just-clone",
|
|
13
|
+
],
|
|
5
14
|
featureIds: ["structured-clone"],
|
|
6
15
|
native: "structuredClone()",
|
|
7
16
|
human: {
|
|
@@ -12,8 +21,10 @@ export const structuredCloneRule = {
|
|
|
12
21
|
agent: {
|
|
13
22
|
when: "deep-copying plain data such as arrays, objects, Maps, Sets, and dates",
|
|
14
23
|
unless: [
|
|
15
|
-
"You need to clone functions
|
|
24
|
+
"You need to clone functions or DOM nodes. structuredClone throws a DataCloneError on both, where lodash's version drops what it cannot handle and carries on.",
|
|
25
|
+
"You clone class instances and need the prototype back. structuredClone does not throw here, which is the trap: it returns a plain object with the same fields and no methods, so the failure shows up later at the first method call.",
|
|
16
26
|
"You need to clone something containing a value structuredClone doesn't support, such as an Error's custom properties beyond message and name.",
|
|
27
|
+
"You clone large objects on a hot path and measured the difference. Being faster than structuredClone on plain data is the whole pitch of rfdc and fast-copy, and a benchmark on your own shapes is the only way to settle it.",
|
|
17
28
|
],
|
|
18
29
|
snippet: "const copy = structuredClone(original);",
|
|
19
30
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"structured-clone.js","sourceRoot":"","sources":["../../src/rules/structured-clone.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,mBAAmB,GAAS;IACvC,EAAE,EAAE,kBAAkB;IACtB,KAAK,EAAE,cAAc;IACrB,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"structured-clone.js","sourceRoot":"","sources":["../../src/rules/structured-clone.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,mBAAmB,GAAS;IACvC,EAAE,EAAE,kBAAkB;IACtB,KAAK,EAAE,cAAc;IACrB,QAAQ,EAAE,YAAY;IACtB,QAAQ,EAAE;QACR,kBAAkB;QAClB,MAAM;QACN,OAAO;QACP,OAAO;QACP,YAAY;QACZ,WAAW;QACX,YAAY;KACb;IACD,UAAU,EAAE,CAAC,kBAAkB,CAAC;IAChC,MAAM,EAAE,mBAAmB;IAC3B,KAAK,EAAE;QACL,SAAS,EACP,4SAA4S;QAC9S,OAAO,EAAE,yCAAyC;QAClD,MAAM,EAAE,kEAAkE;KAC3E;IACD,KAAK,EAAE;QACL,IAAI,EAAE,wEAAwE;QAC9E,MAAM,EAAE;YACN,+JAA+J;YAC/J,uOAAuO;YACvO,+IAA+I;YAC/I,+NAA+N;SAChO;QACD,OAAO,EAAE,yCAAyC;KACnD;CACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-box-trim.d.ts","sourceRoot":"","sources":["../../src/rules/text-box-trim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"text-box-trim.d.ts","sourceRoot":"","sources":["../../src/rules/text-box-trim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,WAAW,EAAE,IAkCzB,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export const textBoxTrim = {
|
|
2
2
|
id: "text-box-trim",
|
|
3
3
|
title: "Trimming font leading",
|
|
4
|
+
category: "typography",
|
|
4
5
|
replaces: ["capsize", "@capsizecss/core", "@capsizecss/metrics"],
|
|
5
6
|
featureIds: ["text-box"],
|
|
6
7
|
native: "text-box-trim and text-box-edge",
|
|
@@ -23,11 +24,12 @@ export const textBoxTrim = {
|
|
|
23
24
|
agent: {
|
|
24
25
|
when: "removing a font's built-in leading so text sits flush in its box",
|
|
25
26
|
unless: [
|
|
26
|
-
"
|
|
27
|
+
"Your support target reaches below Chrome {{chrome:css.properties.text-box}}, Safari {{safari:css.properties.text-box}} or Firefox {{firefox:css.properties.text-box}}. Firefox was last to ship it, so on an older target the fallback is the untrimmed spacing you started with and your vertical rhythm shifts between browsers.",
|
|
27
28
|
"You need the computed metrics as numbers at build time, for example to generate spacing tokens or to lay out text in a canvas or a PDF. Capsize gives you values; CSS only affects rendering.",
|
|
28
29
|
"You need to support a font whose metrics are wrong or missing, which Capsize lets you override by hand.",
|
|
29
30
|
],
|
|
30
31
|
snippet: "h1 { text-box: trim-both cap alphabetic; }",
|
|
31
32
|
},
|
|
33
|
+
guides: ["precise-text-alignment"],
|
|
32
34
|
};
|
|
33
35
|
//# sourceMappingURL=text-box-trim.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-box-trim.js","sourceRoot":"","sources":["../../src/rules/text-box-trim.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,WAAW,GAAS;IAC/B,EAAE,EAAE,eAAe;IACnB,KAAK,EAAE,uBAAuB;IAC9B,QAAQ,EAAE,CAAC,SAAS,EAAE,kBAAkB,EAAE,qBAAqB,CAAC;IAChE,UAAU,EAAE,CAAC,UAAU,CAAC;IACxB,MAAM,EAAE,iCAAiC;IACzC,KAAK,EAAE;QACL,SAAS,EACP,+bAA+b;QACjc,OAAO,EAAE;;;;;;;;;;;EAWX;QACE,MAAM,EAAE,gEAAgE;KACzE;IACD,KAAK,EAAE;QACL,IAAI,EAAE,kEAAkE;QACxE,MAAM,EAAE;YACN,
|
|
1
|
+
{"version":3,"file":"text-box-trim.js","sourceRoot":"","sources":["../../src/rules/text-box-trim.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,WAAW,GAAS;IAC/B,EAAE,EAAE,eAAe;IACnB,KAAK,EAAE,uBAAuB;IAC9B,QAAQ,EAAE,YAAY;IACtB,QAAQ,EAAE,CAAC,SAAS,EAAE,kBAAkB,EAAE,qBAAqB,CAAC;IAChE,UAAU,EAAE,CAAC,UAAU,CAAC;IACxB,MAAM,EAAE,iCAAiC;IACzC,KAAK,EAAE;QACL,SAAS,EACP,+bAA+b;QACjc,OAAO,EAAE;;;;;;;;;;;EAWX;QACE,MAAM,EAAE,gEAAgE;KACzE;IACD,KAAK,EAAE;QACL,IAAI,EAAE,kEAAkE;QACxE,MAAM,EAAE;YACN,oUAAoU;YACpU,+LAA+L;YAC/L,yGAAyG;SAC1G;QACD,OAAO,EAAE,4CAA4C;KACtD;IACD,MAAM,EAAE,CAAC,wBAAwB,CAAC;CACnC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-wrap-balance.d.ts","sourceRoot":"","sources":["../../src/rules/text-wrap-balance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"text-wrap-balance.d.ts","sourceRoot":"","sources":["../../src/rules/text-wrap-balance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,eAAe,EAAE,IAoC7B,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export const textWrapBalance = {
|
|
2
2
|
id: "text-wrap-balance",
|
|
3
3
|
title: "Balanced headings",
|
|
4
|
+
category: "typography",
|
|
4
5
|
replaces: ["react-wrap-balancer", "balance-text"],
|
|
5
6
|
featureIds: ["text-wrap-balance"],
|
|
6
7
|
native: "text-wrap: balance",
|
|
@@ -31,5 +32,6 @@ p {
|
|
|
31
32
|
snippet: `h1, h2, h3 { text-wrap: balance; }
|
|
32
33
|
p { text-wrap: pretty; }`,
|
|
33
34
|
},
|
|
35
|
+
guides: ["improve-text-layout-and-legibility"],
|
|
34
36
|
};
|
|
35
37
|
//# sourceMappingURL=text-wrap-balance.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-wrap-balance.js","sourceRoot":"","sources":["../../src/rules/text-wrap-balance.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAAS;IACnC,EAAE,EAAE,mBAAmB;IACvB,KAAK,EAAE,mBAAmB;IAC1B,QAAQ,EAAE,CAAC,qBAAqB,EAAE,cAAc,CAAC;IACjD,UAAU,EAAE,CAAC,mBAAmB,CAAC;IACjC,MAAM,EAAE,oBAAoB;IAC5B,KAAK,EAAE;QACL,SAAS,EACP,qbAAqb;QACvb,OAAO,EAAE;;;;;;;;;;;EAWX;QACE,MAAM,EAAE,4DAA4D;KACrE;IACD,KAAK,EAAE;QACL,IAAI,EAAE,gFAAgF;QACtF,MAAM,EAAE;YACN,4JAA4J;YAC5J,mKAAmK;YACnK,gIAAgI;YAChI,gJAAgJ;SACjJ;QACD,OAAO,EAAE;yBACY;KACtB;
|
|
1
|
+
{"version":3,"file":"text-wrap-balance.js","sourceRoot":"","sources":["../../src/rules/text-wrap-balance.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAAS;IACnC,EAAE,EAAE,mBAAmB;IACvB,KAAK,EAAE,mBAAmB;IAC1B,QAAQ,EAAE,YAAY;IACtB,QAAQ,EAAE,CAAC,qBAAqB,EAAE,cAAc,CAAC;IACjD,UAAU,EAAE,CAAC,mBAAmB,CAAC;IACjC,MAAM,EAAE,oBAAoB;IAC5B,KAAK,EAAE;QACL,SAAS,EACP,qbAAqb;QACvb,OAAO,EAAE;;;;;;;;;;;EAWX;QACE,MAAM,EAAE,4DAA4D;KACrE;IACD,KAAK,EAAE;QACL,IAAI,EAAE,gFAAgF;QACtF,MAAM,EAAE;YACN,4JAA4J;YAC5J,mKAAmK;YACnK,gIAAgI;YAChI,gJAAgJ;SACjJ;QACD,OAAO,EAAE;yBACY;KACtB;IACD,MAAM,EAAE,CAAC,oCAAoC,CAAC;CAC/C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url-search-params.d.ts","sourceRoot":"","sources":["../../src/rules/url-search-params.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,eAAe,EAAE,IAyC7B,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export const urlSearchParams = {
|
|
2
|
+
id: "url-search-params",
|
|
3
|
+
title: "Query string parsing",
|
|
4
|
+
category: "async-data",
|
|
5
|
+
replaces: ["query-string", "qs", "querystringify", "url-parse"],
|
|
6
|
+
featureIds: [],
|
|
7
|
+
manualBaseline: {
|
|
8
|
+
status: "widely",
|
|
9
|
+
verifiedOn: "2026-09-06",
|
|
10
|
+
note: "web-features folds URLSearchParams into the 'url' feature, which reports Chrome {{chrome:url}} and Safari {{safari:url}} because the URL constructor landed first. URLSearchParams itself is Chrome {{chrome:api.URLSearchParams}}, Firefox {{firefox:api.URLSearchParams}} and Safari {{safari:api.URLSearchParams}}. Deriving from 'url' would understate the floor by three Safari majors. Widely available on its own dates since 2017.",
|
|
11
|
+
},
|
|
12
|
+
native: "URLSearchParams and the URL constructor",
|
|
13
|
+
human: {
|
|
14
|
+
explainer: "URLSearchParams reads and writes query strings, handles percent-encoding in both directions, and gives you get, getAll, set, append and delete. new URL() does the same job for a whole address, so the hostname, the pathname and the search params come apart without a regular expression. Both have been in every browser since 2017 and in Node for as long, and both are what these libraries call underneath once you strip the option handling.",
|
|
15
|
+
snippet: `const url = new URL("/search?tag=css&tag=html&page=2", location.origin);
|
|
16
|
+
|
|
17
|
+
url.searchParams.getAll("tag"); // ["css", "html"]
|
|
18
|
+
url.searchParams.get("page"); // "2", a string
|
|
19
|
+
url.searchParams.set("page", "3");
|
|
20
|
+
|
|
21
|
+
// Build one from scratch.
|
|
22
|
+
new URLSearchParams({ q: "scroll snap", page: "1" }).toString();
|
|
23
|
+
// "q=scroll+snap&page=1"`,
|
|
24
|
+
mdnUrl: "https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams",
|
|
25
|
+
},
|
|
26
|
+
agent: {
|
|
27
|
+
when: "reading or building a query string, or pulling a URL apart",
|
|
28
|
+
unless: [
|
|
29
|
+
"You parse nested objects or arrays from bracket syntax such as filter[status][]=open. That is the reason qs exists, and URLSearchParams has no equivalent.",
|
|
30
|
+
"You round-trip typed data through the query string. Every value comes back as a string, so numbers, booleans and null need converting at each read site.",
|
|
31
|
+
"You depend on the library's options: a custom array format, a configurable delimiter, sorted output, or comma-separated values parsed into arrays.",
|
|
32
|
+
"You parse untrusted input on a server and rely on qs's depth and parameterLimit guards against prototype pollution. URLSearchParams applies no limits of its own.",
|
|
33
|
+
"You need Node's legacy querystring semantics, where a repeated key gives an array rather than needing getAll().",
|
|
34
|
+
"Your support target reaches below Chrome {{chrome:api.URLSearchParams}}, Firefox {{firefox:api.URLSearchParams}} or Safari {{safari:api.URLSearchParams}}. The URL constructor arrived earlier than URLSearchParams, so a browser having one is not proof it has the other.",
|
|
35
|
+
],
|
|
36
|
+
snippet: `const params = new URLSearchParams(location.search);
|
|
37
|
+
params.get("page");
|
|
38
|
+
params.getAll("tag");
|
|
39
|
+
new URLSearchParams({ q: "css" }).toString();`,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=url-search-params.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url-search-params.js","sourceRoot":"","sources":["../../src/rules/url-search-params.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAAS;IACnC,EAAE,EAAE,mBAAmB;IACvB,KAAK,EAAE,sBAAsB;IAC7B,QAAQ,EAAE,YAAY;IACtB,QAAQ,EAAE,CAAC,cAAc,EAAE,IAAI,EAAE,gBAAgB,EAAE,WAAW,CAAC;IAC/D,UAAU,EAAE,EAAE;IACd,cAAc,EAAE;QACd,MAAM,EAAE,QAAQ;QAChB,UAAU,EAAE,YAAY;QACxB,IAAI,EAAE,6aAA6a;KACpb;IACD,MAAM,EAAE,yCAAyC;IACjD,KAAK,EAAE;QACL,SAAS,EACP,ybAAyb;QAC3b,OAAO,EAAE;;;;;;;;0BAQa;QACtB,MAAM,EAAE,kEAAkE;KAC3E;IACD,KAAK,EAAE;QACL,IAAI,EAAE,4DAA4D;QAClE,MAAM,EAAE;YACN,4JAA4J;YAC5J,0JAA0J;YAC1J,oJAAoJ;YACpJ,mKAAmK;YACnK,iHAAiH;YACjH,6QAA6Q;SAC9Q;QACD,OAAO,EAAE;;;8CAGiC;KAC3C;CACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view-transitions.d.ts","sourceRoot":"","sources":["../../src/rules/view-transitions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"view-transitions.d.ts","sourceRoot":"","sources":["../../src/rules/view-transitions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,eAAe,EAAE,IA+D7B,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export const viewTransitions = {
|
|
2
2
|
id: "view-transitions",
|
|
3
3
|
title: "Page and state transitions",
|
|
4
|
+
category: "animation",
|
|
4
5
|
replaces: [
|
|
5
6
|
"next-view-transitions",
|
|
6
7
|
"react-page-transition",
|
|
@@ -50,5 +51,13 @@ document.startViewTransition(() => {
|
|
|
50
51
|
::view-transition-group(*) { animation: none; }
|
|
51
52
|
}`,
|
|
52
53
|
},
|
|
54
|
+
guides: [
|
|
55
|
+
"same-document-transitions",
|
|
56
|
+
"cross-document-transitions",
|
|
57
|
+
"faster-spa-view-transitions",
|
|
58
|
+
"consistent-cross-document-transitions",
|
|
59
|
+
"directional-navigation-transitions",
|
|
60
|
+
"group-element-transitions",
|
|
61
|
+
],
|
|
53
62
|
};
|
|
54
63
|
//# sourceMappingURL=view-transitions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view-transitions.js","sourceRoot":"","sources":["../../src/rules/view-transitions.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAAS;IACnC,EAAE,EAAE,kBAAkB;IACtB,KAAK,EAAE,4BAA4B;IACnC,QAAQ,EAAE;QACR,uBAAuB;QACvB,uBAAuB;QACvB,UAAU;QACV,MAAM;KACP;IACD,UAAU,EAAE,CAAC,kBAAkB,CAAC;IAChC,MAAM,EAAE,0BAA0B;IAClC,KAAK,EAAE;QACL,SAAS,EACP,gcAAgc;QAClc,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;EAoBX;QACE,MAAM,EACJ,uEAAuE;KAC1E;IACD,KAAK,EAAE;QACL,IAAI,EAAE,+FAA+F;QACrG,MAAM,EAAE;YACN,+LAA+L;YAC/L,4JAA4J;YAC5J,6HAA6H;YAC7H,oGAAoG;YACpG,2FAA2F;SAC5F;QACD,OAAO,EAAE;;;;;EAKX;KACC;CACF,CAAC"}
|
|
1
|
+
{"version":3,"file":"view-transitions.js","sourceRoot":"","sources":["../../src/rules/view-transitions.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAAS;IACnC,EAAE,EAAE,kBAAkB;IACtB,KAAK,EAAE,4BAA4B;IACnC,QAAQ,EAAE,WAAW;IACrB,QAAQ,EAAE;QACR,uBAAuB;QACvB,uBAAuB;QACvB,UAAU;QACV,MAAM;KACP;IACD,UAAU,EAAE,CAAC,kBAAkB,CAAC;IAChC,MAAM,EAAE,0BAA0B;IAClC,KAAK,EAAE;QACL,SAAS,EACP,gcAAgc;QAClc,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;EAoBX;QACE,MAAM,EACJ,uEAAuE;KAC1E;IACD,KAAK,EAAE;QACL,IAAI,EAAE,+FAA+F;QACrG,MAAM,EAAE;YACN,+LAA+L;YAC/L,4JAA4J;YAC5J,6HAA6H;YAC7H,oGAAoG;YACpG,2FAA2F;SAC5F;QACD,OAAO,EAAE;;;;;EAKX;KACC;IACD,MAAM,EAAE;QACN,2BAA2B;QAC3B,4BAA4B;QAC5B,6BAA6B;QAC7B,uCAAuC;QACvC,oCAAoC;QACpC,2BAA2B;KAC5B;CACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-bluetooth.d.ts","sourceRoot":"","sources":["../../src/rules/web-bluetooth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"web-bluetooth.d.ts","sourceRoot":"","sources":["../../src/rules/web-bluetooth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,YAAY,EAAE,IA2B1B,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export const webBluetooth = {
|
|
2
2
|
id: "web-bluetooth",
|
|
3
3
|
title: "Bluetooth device access",
|
|
4
|
+
category: "device-apis",
|
|
4
5
|
replaces: ["@capacitor-community/bluetooth-le", "cordova-plugin-ble-central"],
|
|
5
6
|
featureIds: ["web-bluetooth"],
|
|
6
7
|
native: "navigator.bluetooth.requestDevice()",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-bluetooth.js","sourceRoot":"","sources":["../../src/rules/web-bluetooth.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAS;IAChC,EAAE,EAAE,eAAe;IACnB,KAAK,EAAE,yBAAyB;IAChC,QAAQ,EAAE,CAAC,mCAAmC,EAAE,4BAA4B,CAAC;IAC7E,UAAU,EAAE,CAAC,eAAe,CAAC;IAC7B,MAAM,EAAE,qCAAqC;IAC7C,KAAK,EAAE;QACL,SAAS,EACP,4jBAA4jB;QAC9jB,OAAO,EAAE;;;4CAG+B;QACxC,MAAM,EACJ,oEAAoE;KACvE;IACD,KAAK,EAAE;QACL,IAAI,EAAE,sEAAsE;QAC5E,MAAM,EAAE;YACN,uJAAuJ;YACvJ,wHAAwH;YACxH,sJAAsJ;SACvJ;QACD,OAAO,EACL,sEAAsE;KACzE;CACF,CAAC"}
|
|
1
|
+
{"version":3,"file":"web-bluetooth.js","sourceRoot":"","sources":["../../src/rules/web-bluetooth.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAS;IAChC,EAAE,EAAE,eAAe;IACnB,KAAK,EAAE,yBAAyB;IAChC,QAAQ,EAAE,aAAa;IACvB,QAAQ,EAAE,CAAC,mCAAmC,EAAE,4BAA4B,CAAC;IAC7E,UAAU,EAAE,CAAC,eAAe,CAAC;IAC7B,MAAM,EAAE,qCAAqC;IAC7C,KAAK,EAAE;QACL,SAAS,EACP,4jBAA4jB;QAC9jB,OAAO,EAAE;;;4CAG+B;QACxC,MAAM,EACJ,oEAAoE;KACvE;IACD,KAAK,EAAE;QACL,IAAI,EAAE,sEAAsE;QAC5E,MAAM,EAAE;YACN,uJAAuJ;YACvJ,wHAAwH;YACxH,sJAAsJ;SACvJ;QACD,OAAO,EACL,sEAAsE;KACzE;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-crypto.d.ts","sourceRoot":"","sources":["../../src/rules/web-crypto.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,SAAS,EAAE,IA+BvB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export const webCrypto = {
|
|
2
|
+
id: "web-crypto",
|
|
3
|
+
title: "Hashing and encryption",
|
|
4
|
+
category: "async-data",
|
|
5
|
+
replaces: ["crypto-js", "js-sha256", "crypto-hash"],
|
|
6
|
+
featureIds: ["web-cryptography"],
|
|
7
|
+
native: "crypto.subtle",
|
|
8
|
+
human: {
|
|
9
|
+
explainer: "crypto-js ships its own implementations of SHA-256, AES and HMAC as JavaScript, which is both a large download and slower than the same primitives compiled into the browser. crypto.subtle exposes those primitives natively, with key material held as CryptoKey objects the page cannot read out unless you mark them extractable. The API is asynchronous and takes bytes rather than strings, so a call site grows a TextEncoder and an await.",
|
|
10
|
+
snippet: `async function sha256(text) {
|
|
11
|
+
const bytes = new TextEncoder().encode(text);
|
|
12
|
+
const digest = await crypto.subtle.digest("SHA-256", bytes);
|
|
13
|
+
return [...new Uint8Array(digest)]
|
|
14
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
15
|
+
.join("");
|
|
16
|
+
}`,
|
|
17
|
+
mdnUrl: "https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto",
|
|
18
|
+
},
|
|
19
|
+
agent: {
|
|
20
|
+
when: "hashing, signing, or encrypting with SHA-2, HMAC, AES or RSA",
|
|
21
|
+
unless: [
|
|
22
|
+
"You need MD5, SHA-1 signing, or another legacy algorithm. crypto.subtle leaves those out deliberately, so a format that requires one keeps its library.",
|
|
23
|
+
"The call has to be synchronous. Everything on crypto.subtle returns a promise, which changes any function that hashes inside a render pass or a sort comparator.",
|
|
24
|
+
"The code runs on plain http somewhere other than localhost. crypto.subtle is undefined outside a secure context.",
|
|
25
|
+
"You interoperate with crypto-js output that uses its own defaults, such as its OpenSSL-style key derivation for AES, where matching the format by hand is the harder job.",
|
|
26
|
+
"You need password hashing. Neither the library nor crypto.subtle gives you bcrypt, scrypt or Argon2, and PBKDF2 is the only stretching primitive here.",
|
|
27
|
+
],
|
|
28
|
+
snippet: `const bytes = new TextEncoder().encode(text);
|
|
29
|
+
const digest = await crypto.subtle.digest("SHA-256", bytes);`,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=web-crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-crypto.js","sourceRoot":"","sources":["../../src/rules/web-crypto.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,SAAS,GAAS;IAC7B,EAAE,EAAE,YAAY;IAChB,KAAK,EAAE,wBAAwB;IAC/B,QAAQ,EAAE,YAAY;IACtB,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,aAAa,CAAC;IACnD,UAAU,EAAE,CAAC,kBAAkB,CAAC;IAChC,MAAM,EAAE,eAAe;IACvB,KAAK,EAAE;QACL,SAAS,EACP,qbAAqb;QACvb,OAAO,EAAE;;;;;;EAMX;QACE,MAAM,EAAE,+DAA+D;KACxE;IACD,KAAK,EAAE;QACL,IAAI,EAAE,8DAA8D;QACpE,MAAM,EAAE;YACN,yJAAyJ;YACzJ,kKAAkK;YAClK,kHAAkH;YAClH,2KAA2K;YAC3K,wJAAwJ;SACzJ;QACD,OAAO,EAAE;6DACgD;KAC1D;CACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-share.d.ts","sourceRoot":"","sources":["../../src/rules/web-share.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"web-share.d.ts","sourceRoot":"","sources":["../../src/rules/web-share.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,QAAQ,EAAE,IA4BtB,CAAC"}
|
package/dist/rules/web-share.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-share.js","sourceRoot":"","sources":["../../src/rules/web-share.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,QAAQ,GAAS;IAC5B,EAAE,EAAE,WAAW;IACf,KAAK,EAAE,uBAAuB;IAC9B,QAAQ,EAAE,CAAC,aAAa,EAAE,oBAAoB,EAAE,kBAAkB,CAAC;IACnE,UAAU,EAAE,CAAC,OAAO,CAAC;IACrB,MAAM,EAAE,mBAAmB;IAC3B,KAAK,EAAE;QACL,SAAS,EACP,kSAAkS;QACpS,OAAO,EAAE;;;;;EAKX;QACE,MAAM,EAAE,kEAAkE;KAC3E;IACD,KAAK,EAAE;QACL,IAAI,EAAE,0FAA0F;QAChG,MAAM,EAAE;YACN,kLAAkL;YAClL,yFAAyF;YACzF,+JAA+J;SAChK;QACD,OAAO,EACL,uEAAuE;KAC1E;CACF,CAAC"}
|
|
1
|
+
{"version":3,"file":"web-share.js","sourceRoot":"","sources":["../../src/rules/web-share.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,QAAQ,GAAS;IAC5B,EAAE,EAAE,WAAW;IACf,KAAK,EAAE,uBAAuB;IAC9B,QAAQ,EAAE,aAAa;IACvB,QAAQ,EAAE,CAAC,aAAa,EAAE,oBAAoB,EAAE,kBAAkB,CAAC;IACnE,UAAU,EAAE,CAAC,OAAO,CAAC;IACrB,MAAM,EAAE,mBAAmB;IAC3B,KAAK,EAAE;QACL,SAAS,EACP,kSAAkS;QACpS,OAAO,EAAE;;;;;EAKX;QACE,MAAM,EAAE,kEAAkE;KAC3E;IACD,KAAK,EAAE;QACL,IAAI,EAAE,0FAA0F;QAChG,MAAM,EAAE;YACN,kLAAkL;YAClL,yFAAyF;YACzF,+JAA+J;SAChK;QACD,OAAO,EACL,uEAAuE;KAC1E;CACF,CAAC"}
|
package/dist/schema.d.ts
CHANGED
|
@@ -36,6 +36,16 @@ export type ManualBaseline = z.infer<typeof manualBaselineSchema>;
|
|
|
36
36
|
export declare const ruleSchema: z.ZodObject<{
|
|
37
37
|
id: z.ZodString;
|
|
38
38
|
title: z.ZodString;
|
|
39
|
+
category: z.ZodEnum<{
|
|
40
|
+
animation: "animation";
|
|
41
|
+
"async-data": "async-data";
|
|
42
|
+
"device-apis": "device-apis";
|
|
43
|
+
formatting: "formatting";
|
|
44
|
+
forms: "forms";
|
|
45
|
+
layout: "layout";
|
|
46
|
+
scrolling: "scrolling";
|
|
47
|
+
typography: "typography";
|
|
48
|
+
}>;
|
|
39
49
|
replaces: z.ZodArray<z.ZodString>;
|
|
40
50
|
featureIds: z.ZodArray<z.ZodString>;
|
|
41
51
|
native: z.ZodString;
|
|
@@ -50,6 +60,7 @@ export declare const ruleSchema: z.ZodObject<{
|
|
|
50
60
|
unless: z.ZodArray<z.ZodString>;
|
|
51
61
|
snippet: z.ZodString;
|
|
52
62
|
}, z.core.$strip>;
|
|
63
|
+
guides: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
53
64
|
manualBaseline: z.ZodOptional<z.ZodObject<{
|
|
54
65
|
status: z.ZodEnum<{
|
|
55
66
|
limited: "limited";
|
|
@@ -64,6 +75,16 @@ export type Rule = z.infer<typeof ruleSchema>;
|
|
|
64
75
|
export declare const catalogSchema: z.ZodArray<z.ZodObject<{
|
|
65
76
|
id: z.ZodString;
|
|
66
77
|
title: z.ZodString;
|
|
78
|
+
category: z.ZodEnum<{
|
|
79
|
+
animation: "animation";
|
|
80
|
+
"async-data": "async-data";
|
|
81
|
+
"device-apis": "device-apis";
|
|
82
|
+
formatting: "formatting";
|
|
83
|
+
forms: "forms";
|
|
84
|
+
layout: "layout";
|
|
85
|
+
scrolling: "scrolling";
|
|
86
|
+
typography: "typography";
|
|
87
|
+
}>;
|
|
67
88
|
replaces: z.ZodArray<z.ZodString>;
|
|
68
89
|
featureIds: z.ZodArray<z.ZodString>;
|
|
69
90
|
native: z.ZodString;
|
|
@@ -78,6 +99,7 @@ export declare const catalogSchema: z.ZodArray<z.ZodObject<{
|
|
|
78
99
|
unless: z.ZodArray<z.ZodString>;
|
|
79
100
|
snippet: z.ZodString;
|
|
80
101
|
}, z.core.$strip>;
|
|
102
|
+
guides: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
81
103
|
manualBaseline: z.ZodOptional<z.ZodObject<{
|
|
82
104
|
status: z.ZodEnum<{
|
|
83
105
|
limited: "limited";
|
package/dist/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;GAIG;AACH,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;;;EAK/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAmDlE;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;iBAK/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA+FnB,CAAC;AAEL,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAE9C,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA2BxB,CAAC;AAEH,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,EAAE,CAEnD"}
|
package/dist/schema.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { categorySchema } from "./categories.js";
|
|
2
3
|
/**
|
|
3
4
|
* Bumped whenever the shape of a rule changes in a way that breaks consumers.
|
|
4
5
|
* Published alongside the catalog so downstream surfaces can refuse data they
|
|
@@ -19,7 +20,36 @@ export const baselineStatusSchema = z.enum([
|
|
|
19
20
|
]);
|
|
20
21
|
const isoDate = z
|
|
21
22
|
.string()
|
|
22
|
-
.regex(/^\d{4}-\d{2}-\d{2}$/, "expected an ISO date, YYYY-MM-DD")
|
|
23
|
+
.regex(/^\d{4}-\d{2}-\d{2}$/, "expected an ISO date, YYYY-MM-DD")
|
|
24
|
+
// Shape alone is not enough: "2026-99-99" matches the regex, and
|
|
25
|
+
// check-freshness then computes NaN days of age, which is never greater
|
|
26
|
+
// than the limit. A typo would make a hand-verified claim immortal.
|
|
27
|
+
//
|
|
28
|
+
// Checked arithmetically rather than with Date, because the purity test
|
|
29
|
+
// bans constructing one anywhere detect() can reach.
|
|
30
|
+
.refine((value) => {
|
|
31
|
+
const year = Number(value.slice(0, 4));
|
|
32
|
+
const month = Number(value.slice(5, 7));
|
|
33
|
+
const day = Number(value.slice(8, 10));
|
|
34
|
+
if (month < 1 || month > 12 || day < 1)
|
|
35
|
+
return false;
|
|
36
|
+
const leap = (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
|
|
37
|
+
const lengths = [
|
|
38
|
+
31,
|
|
39
|
+
leap ? 29 : 28,
|
|
40
|
+
31,
|
|
41
|
+
30,
|
|
42
|
+
31,
|
|
43
|
+
30,
|
|
44
|
+
31,
|
|
45
|
+
31,
|
|
46
|
+
30,
|
|
47
|
+
31,
|
|
48
|
+
30,
|
|
49
|
+
31,
|
|
50
|
+
];
|
|
51
|
+
return day <= lengths[month - 1];
|
|
52
|
+
}, "expected a real calendar date");
|
|
23
53
|
const slug = z
|
|
24
54
|
.string()
|
|
25
55
|
.regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "expected a lowercase kebab-case slug");
|
|
@@ -27,6 +57,10 @@ const slug = z
|
|
|
27
57
|
const packageName = z
|
|
28
58
|
.string()
|
|
29
59
|
.regex(/^(?:@[a-z0-9][a-z0-9-._]*\/)?[a-z0-9][a-z0-9-._]*$/, "expected a lowercase npm package name");
|
|
60
|
+
/** Rendered as a link on every surface, so nothing but https gets in. */
|
|
61
|
+
const httpsUrl = z
|
|
62
|
+
.url()
|
|
63
|
+
.refine((value) => value.startsWith("https://"), "expected an https URL");
|
|
30
64
|
/**
|
|
31
65
|
* Escape hatch for features that web-features has no ID for yet. Carries the
|
|
32
66
|
* date it was checked by hand so `scripts/check-freshness.ts` can fail CI once
|
|
@@ -44,6 +78,8 @@ export const ruleSchema = z
|
|
|
44
78
|
id: slug,
|
|
45
79
|
/** Short human label, e.g. "Carousels". */
|
|
46
80
|
title: z.string().min(1),
|
|
81
|
+
/** Which entry in packages/catalog/src/categories.ts this rule belongs to. */
|
|
82
|
+
category: categorySchema,
|
|
47
83
|
/** npm packages this rule can replace. Exact names, lowercase. */
|
|
48
84
|
replaces: z.array(packageName).min(1),
|
|
49
85
|
/**
|
|
@@ -54,7 +90,11 @@ export const ruleSchema = z
|
|
|
54
90
|
* Call those out in `agent.unless` instead. Empty only when
|
|
55
91
|
* `manualBaseline` is supplied.
|
|
56
92
|
*/
|
|
57
|
-
featureIds: z
|
|
93
|
+
featureIds: z
|
|
94
|
+
.array(z
|
|
95
|
+
.string()
|
|
96
|
+
.regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "expected a lowercase web-features ID"))
|
|
97
|
+
.refine((ids) => new Set(ids).size === ids.length, "a feature may only be listed once"),
|
|
58
98
|
/** The native approach, one line. */
|
|
59
99
|
native: z.string().min(1),
|
|
60
100
|
human: z.object({
|
|
@@ -63,9 +103,9 @@ export const ruleSchema = z
|
|
|
63
103
|
/** Copy-pasteable CSS, HTML, or JavaScript. */
|
|
64
104
|
snippet: z.string().min(1),
|
|
65
105
|
/** A live demo or a post that walks through it. */
|
|
66
|
-
demoUrl:
|
|
106
|
+
demoUrl: httpsUrl.optional(),
|
|
67
107
|
/** The MDN reference page for the native feature. */
|
|
68
|
-
mdnUrl:
|
|
108
|
+
mdnUrl: httpsUrl.optional(),
|
|
69
109
|
}),
|
|
70
110
|
/** Terse projection for LLM surfaces. Budget roughly 200 tokens. */
|
|
71
111
|
agent: z.object({
|
|
@@ -81,6 +121,15 @@ export const ruleSchema = z
|
|
|
81
121
|
.min(1, "every rule must state when the dependency is still correct"),
|
|
82
122
|
snippet: z.string().min(1),
|
|
83
123
|
}),
|
|
124
|
+
/**
|
|
125
|
+
* IDs of GoogleChrome/modern-web-guidance guides that cover the
|
|
126
|
+
* implementation in depth. Their guides are keyed by use case, ours by
|
|
127
|
+
* package name, so this is the hand-off from "which dependency can go" to
|
|
128
|
+
* "how to build the thing properly". IDs only: the category and the URL
|
|
129
|
+
* are resolved from the committed snapshot in guides.ts, so a guide that
|
|
130
|
+
* is renamed upstream fails a test instead of shipping as a dead link.
|
|
131
|
+
*/
|
|
132
|
+
guides: z.array(slug).optional(),
|
|
84
133
|
manualBaseline: manualBaselineSchema.optional(),
|
|
85
134
|
})
|
|
86
135
|
.superRefine((rule, ctx) => {
|
|
@@ -91,6 +140,16 @@ export const ruleSchema = z
|
|
|
91
140
|
message: "a rule needs at least one web-features ID, or an explicit manualBaseline with a verifiedOn date",
|
|
92
141
|
});
|
|
93
142
|
}
|
|
143
|
+
// resolveBaseline() only consults manualBaseline when featureIds is empty,
|
|
144
|
+
// so carrying both silently discards the hand-verified override while
|
|
145
|
+
// check-freshness keeps ageing its verifiedOn date.
|
|
146
|
+
if (rule.featureIds.length > 0 && rule.manualBaseline) {
|
|
147
|
+
ctx.addIssue({
|
|
148
|
+
code: "custom",
|
|
149
|
+
path: ["manualBaseline"],
|
|
150
|
+
message: "a manualBaseline is only read when featureIds is empty. Drop one or the other.",
|
|
151
|
+
});
|
|
152
|
+
}
|
|
94
153
|
});
|
|
95
154
|
export const catalogSchema = z.array(ruleSchema).superRefine((rules, ctx) => {
|
|
96
155
|
const seenIds = new Set();
|
package/dist/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/search.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Rule } from "./schema.ts";
|
|
2
|
+
export interface SearchResult {
|
|
3
|
+
rule: Rule;
|
|
4
|
+
/**
|
|
5
|
+
* The packages from `rule.replaces` the query matched, in the order the rule
|
|
6
|
+
* lists them. Empty when the rule matched by title or native feature alone,
|
|
7
|
+
* which is what tells a surface whether it has anything to show underneath.
|
|
8
|
+
*/
|
|
9
|
+
packages: readonly string[];
|
|
10
|
+
}
|
|
11
|
+
export interface SearchOptions {
|
|
12
|
+
/** Defaults to the whole catalog. Present so tests can pass their own. */
|
|
13
|
+
rules?: readonly Rule[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Two characters. One is a substring of most of the catalog, and a list of
|
|
17
|
+
* everything is what `/rules` is for.
|
|
18
|
+
*
|
|
19
|
+
* Exported because an empty result means two different things. A surface that
|
|
20
|
+
* cannot tell "no rule covers this" from "the search declined to run" tells
|
|
21
|
+
* the reader the catalog has nothing for a query it never ran.
|
|
22
|
+
*/
|
|
23
|
+
export declare const MIN_QUERY_LENGTH = 2;
|
|
24
|
+
/**
|
|
25
|
+
* Ranks rules against a query. Returns an empty array for a query too short to
|
|
26
|
+
* narrow anything down.
|
|
27
|
+
*/
|
|
28
|
+
export declare function searchRules(query: string, options?: SearchOptions): SearchResult[];
|
|
29
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAqBxC,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,IAAI,CAAC;IACX;;;;OAIG;IACH,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,0EAA0E;IAC1E,KAAK,CAAC,EAAE,SAAS,IAAI,EAAE,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAsClC;;;GAGG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,aAAkB,GAC1B,YAAY,EAAE,CAyBhB"}
|
package/dist/search.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { rules as defaultRules } from "./rules/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Free-text lookup over the catalog.
|
|
4
|
+
*
|
|
5
|
+
* `detect()` answers "here is my package.json, what applies", which needs the
|
|
6
|
+
* whole file. This answers the question someone arrives with instead: one name
|
|
7
|
+
* they already have in their head. The catalog covers far more package names
|
|
8
|
+
* than it has rules, and a rule is titled after the native feature rather than
|
|
9
|
+
* after any package it replaces, so most of those names appear nowhere a
|
|
10
|
+
* reader can find them.
|
|
11
|
+
*
|
|
12
|
+
* Pure, like `detect()`. It reads nothing but the rules handed to it.
|
|
13
|
+
*/
|
|
14
|
+
/** Why a rule came back, strongest first. Also its sort key. */
|
|
15
|
+
const EXACT_PACKAGE = 4;
|
|
16
|
+
const PACKAGE_PREFIX = 3;
|
|
17
|
+
const PACKAGE_SUBSTRING = 2;
|
|
18
|
+
const RULE_TEXT = 1;
|
|
19
|
+
/**
|
|
20
|
+
* Two characters. One is a substring of most of the catalog, and a list of
|
|
21
|
+
* everything is what `/rules` is for.
|
|
22
|
+
*
|
|
23
|
+
* Exported because an empty result means two different things. A surface that
|
|
24
|
+
* cannot tell "no rule covers this" from "the search declined to run" tells
|
|
25
|
+
* the reader the catalog has nothing for a query it never ran.
|
|
26
|
+
*/
|
|
27
|
+
export const MIN_QUERY_LENGTH = 2;
|
|
28
|
+
function scorePackage(name, query) {
|
|
29
|
+
const lower = name.toLowerCase();
|
|
30
|
+
if (lower === query)
|
|
31
|
+
return EXACT_PACKAGE;
|
|
32
|
+
if (lower.startsWith(query))
|
|
33
|
+
return PACKAGE_PREFIX;
|
|
34
|
+
if (lower.includes(query))
|
|
35
|
+
return PACKAGE_SUBSTRING;
|
|
36
|
+
return 0;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Scores one rule. A rule that matches by package never falls back to its
|
|
40
|
+
* title, so the packages array stays a list of what the reader actually
|
|
41
|
+
* typed rather than everything the rule happens to replace.
|
|
42
|
+
*/
|
|
43
|
+
function scoreRule(rule, needle) {
|
|
44
|
+
const packages = [];
|
|
45
|
+
let score = 0;
|
|
46
|
+
for (const name of rule.replaces) {
|
|
47
|
+
const packageScore = scorePackage(name, needle);
|
|
48
|
+
if (packageScore === 0)
|
|
49
|
+
continue;
|
|
50
|
+
packages.push(name);
|
|
51
|
+
score = Math.max(score, packageScore);
|
|
52
|
+
}
|
|
53
|
+
if (score > 0)
|
|
54
|
+
return { packages, score };
|
|
55
|
+
const matchesText = rule.title.toLowerCase().includes(needle) ||
|
|
56
|
+
rule.native.toLowerCase().includes(needle);
|
|
57
|
+
return { packages, score: matchesText ? RULE_TEXT : 0 };
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Ranks rules against a query. Returns an empty array for a query too short to
|
|
61
|
+
* narrow anything down.
|
|
62
|
+
*/
|
|
63
|
+
export function searchRules(query, options = {}) {
|
|
64
|
+
const needle = query.trim().toLowerCase();
|
|
65
|
+
if (needle.length < MIN_QUERY_LENGTH)
|
|
66
|
+
return [];
|
|
67
|
+
const scored = [];
|
|
68
|
+
for (const rule of options.rules ?? defaultRules) {
|
|
69
|
+
const { packages, score } = scoreRule(rule, needle);
|
|
70
|
+
if (score === 0)
|
|
71
|
+
continue;
|
|
72
|
+
scored.push({ result: { rule, packages }, score });
|
|
73
|
+
}
|
|
74
|
+
/*
|
|
75
|
+
* Ties break on how much of the rule the query hit, then on title, so the
|
|
76
|
+
* order is stable rather than dependent on the order rules/index.ts happens
|
|
77
|
+
* to list them in.
|
|
78
|
+
*/
|
|
79
|
+
scored.sort((a, b) => b.score - a.score ||
|
|
80
|
+
b.result.packages.length - a.result.packages.length ||
|
|
81
|
+
a.result.rule.title.localeCompare(b.result.rule.title));
|
|
82
|
+
return scored.map((entry) => entry.result);
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { supportClaims } from "./generated/support-claims.ts";
|
|
2
|
+
/**
|
|
3
|
+
* Replaces every token with its version. An unknown token is left visible
|
|
4
|
+
* rather than silently blanked: a `{{...}}` on screen is obviously broken,
|
|
5
|
+
* where an empty string reads as finished prose. A test asserts none survive.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveSupportClaims(text: string): string;
|
|
8
|
+
/** True when a string still carries an unresolved token. Used by the tests. */
|
|
9
|
+
export declare function hasUnresolvedClaim(text: string): boolean;
|
|
10
|
+
export { supportClaims };
|
|
11
|
+
//# sourceMappingURL=support.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"support.d.ts","sourceRoot":"","sources":["../src/support.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAgB9D;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMzD;AAED,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKxD;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
|