jssm 5.162.7 → 5.162.9

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 (53) hide show
  1. package/README.md +7 -7
  2. package/custom-elements.json +24 -24
  3. package/dist/cdn/instance.js +5 -3
  4. package/dist/cdn/viz.js +1 -1
  5. package/dist/cli/fsl-export-system-prompt.cjs +27 -24
  6. package/dist/cli/fsl-render.cjs +1 -1
  7. package/dist/cli/fsl.cjs +1 -1
  8. package/dist/cli/lib.cjs +1 -1
  9. package/dist/cli/lib.mjs +1 -1
  10. package/dist/cm6/fsl_language.js +10 -14
  11. package/dist/deno/README.md +7 -7
  12. package/dist/deno/fence.d.ts +0 -1
  13. package/dist/deno/fsl_fence_highlight.d.ts +0 -4
  14. package/dist/deno/fsl_fence_render.d.ts +0 -8
  15. package/dist/deno/fsl_gif.d.ts +0 -8
  16. package/dist/deno/fsl_markdown_fence.d.ts +0 -5
  17. package/dist/deno/fsl_svg_patch.d.ts +0 -6
  18. package/dist/deno/fsl_walk.d.ts +0 -2
  19. package/dist/deno/jssm.d.ts +214 -503
  20. package/dist/deno/jssm.js +1 -1
  21. package/dist/deno/jssm_compiler.d.ts +1 -1
  22. package/dist/deno/jssm_constants.d.ts +0 -3
  23. package/dist/deno/jssm_intern.d.ts +0 -15
  24. package/dist/deno/jssm_theme.d.ts +2 -2
  25. package/dist/deno/jssm_types.d.ts +13 -34
  26. package/dist/deno/jssm_util.d.ts +20 -6
  27. package/dist/deno/jssm_viz.d.ts +5 -51
  28. package/dist/es6/cm6/fsl_language.d.ts +0 -2
  29. package/dist/fence/fence.js +2052 -1857
  30. package/dist/jssm.es5.cjs +1 -1
  31. package/dist/jssm.es5.iife.js +1 -1
  32. package/dist/jssm.es6.mjs +1 -1
  33. package/dist/jssm_viz.cjs +1 -1
  34. package/dist/jssm_viz.iife.cjs +1 -1
  35. package/dist/jssm_viz.mjs +1 -1
  36. package/dist/wc/docs.define.js +0 -5
  37. package/dist/wc/docs.js +79 -43
  38. package/dist/wc/editor.define.js +0 -5
  39. package/dist/wc/editor.js +1 -7
  40. package/dist/wc/instance.define.js +0 -6
  41. package/dist/wc/instance.js +93 -115
  42. package/dist/wc/viz.define.js +0 -6
  43. package/dist/wc/viz.js +22 -36
  44. package/dist/wc/widgets.define.js +0 -5
  45. package/dist/wc/widgets.js +117 -95
  46. package/jssm.cli.d.cts +0 -8
  47. package/jssm.cli.d.ts +0 -8
  48. package/jssm.es5.d.cts +449 -808
  49. package/jssm.es6.d.ts +449 -808
  50. package/jssm.fence.d.ts +213 -508
  51. package/jssm_viz.es5.d.cts +216 -529
  52. package/jssm_viz.es6.d.ts +216 -529
  53. package/package.json +21 -11
@@ -9,11 +9,9 @@ export { FslDocs } from './docs.js';
9
9
  /**
10
10
  * Returns true when `tag_name` is exactly `fsl-<suffix>` or `jssm-<suffix>`
11
11
  * (case-insensitive).
12
- *
13
12
  * @param tag_name - The element tag name to test (e.g. `"FSL-VIZ"`, `"jssm-viz"`).
14
13
  * @param suffix - The suffix to match after the prefix (e.g. `"viz"`).
15
14
  * @returns `true` when `tag_name` is `fsl-<suffix>` or `jssm-<suffix>`.
16
- *
17
15
  * @example
18
16
  * wc_suffix_matches('FSL-VIZ', 'viz'); // true
19
17
  * wc_suffix_matches('jssm-viz', 'viz'); // true
@@ -33,14 +31,11 @@ export { FslDocs } from './docs.js';
33
31
  * dual-named components.
34
32
  *
35
33
  * Idempotent: skips the `define` call when the tag is already registered.
36
- *
37
34
  * @param canonical_tag - The `fsl-*` tag name (e.g. `"fsl-info-panel"`).
38
35
  * @param CanonicalClass - Constructor to register under `canonical_tag`.
39
- *
40
36
  * @example
41
37
  * class FslInfoPanel extends HTMLElement {}
42
38
  * define_canonical('fsl-info-panel', FslInfoPanel);
43
- *
44
39
  * @see define_with_synonym
45
40
  */
46
41
  function define_canonical(canonical_tag, CanonicalClass) {
package/dist/wc/docs.js CHANGED
@@ -1750,11 +1750,16 @@ const DOCS_FEATURES = [
1750
1750
  // the component can wire a "load into editor" button.
1751
1751
  /** Parse a fenced-code info string like `fsl {teaches: x, run: true}`. */
1752
1752
  function parseFenceInfo(info) {
1753
- var _a, _b;
1754
- const m = /^(\S+)\s*(?:\{([^}]*)\})?/.exec(info.trim());
1755
- const lang = (_a = m === null || m === void 0 ? void 0 : m[1]) !== null && _a !== void 0 ? _a : '';
1753
+ var _a, _b, _c;
1754
+ // Two-step scan (first token, then an optional immediately-following {...}
1755
+ // block) rather than one regex, so no quantifier ambiguity exists between
1756
+ // the token and the brace block (regexp/no-super-linear-backtracking).
1757
+ const trimmed = info.trim();
1758
+ const lang = (_b = (_a = /^\S+/.exec(trimmed)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : '';
1759
+ const braced = /^\{([^}]*)\}/.exec(trimmed.slice(lang.length).trimStart());
1756
1760
  const attrs = {};
1757
- for (const pair of ((_b = m === null || m === void 0 ? void 0 : m[2]) !== null && _b !== void 0 ? _b : '').split(',')) {
1761
+ const pairs = ((_c = braced === null || braced === void 0 ? void 0 : braced[1]) !== null && _c !== void 0 ? _c : '').split(',');
1762
+ for (const pair of pairs) {
1758
1763
  const kv = pair.split(':');
1759
1764
  if (kv.length < 2) {
1760
1765
  continue;
@@ -1762,7 +1767,7 @@ function parseFenceInfo(info) {
1762
1767
  const k = kv[0].trim();
1763
1768
  const raw = kv.slice(1).join(':').trim();
1764
1769
  if (k) {
1765
- attrs[k] = raw === 'true' ? true : raw === 'false' ? false : raw;
1770
+ attrs[k] = raw === 'true' ? true : (raw === 'false' ? false : raw);
1766
1771
  }
1767
1772
  }
1768
1773
  return { lang, attrs };
@@ -1785,7 +1790,31 @@ const FSL_COLOR_KEYS = new Set([
1785
1790
  'color', 'text-color', 'background-color', 'border-color', 'edge-color',
1786
1791
  ]);
1787
1792
  /** Whether `text` is a bare FSL identifier (so it can be an attribute key). */
1788
- const isIdentifier = (text) => /^[A-Za-z_][A-Za-z0-9_-]*$/.test(text);
1793
+ const isIdentifier = (text) => /^[A-Z_][\w-]*$/i.test(text);
1794
+ /**
1795
+ * Retro-tag the identifier token immediately preceding a `:` as an attribute
1796
+ * `key` (skipping whitespace runs; keywords keep their class). Returns whether
1797
+ * that key is a color key, i.e. whether the next value token should be tagged
1798
+ * `color`. Extracted from the `tokenizeFsl` scanner loop.
1799
+ * @param toks - The token list built so far; mutated in place.
1800
+ * @returns `true` when the tagged key is one of {@link FSL_COLOR_KEYS}.
1801
+ * @see tokenizeFsl
1802
+ */
1803
+ function tagKeyBeforeColon(toks) {
1804
+ for (let j = toks.length - 1; j >= 0; j--) {
1805
+ if (/^\s+$/.test(toks[j].text)) {
1806
+ continue;
1807
+ } // skip whitespace before the colon
1808
+ if (toks[j].cls === null && isIdentifier(toks[j].text)) {
1809
+ toks[j].cls = 'key';
1810
+ if (FSL_COLOR_KEYS.has(toks[j].text)) {
1811
+ return true;
1812
+ }
1813
+ }
1814
+ break; // only the immediately-preceding token
1815
+ }
1816
+ return false;
1817
+ }
1789
1818
  /**
1790
1819
  * Tokenize FSL source into `{cls, text}` runs for syntax highlighting. A pure,
1791
1820
  * regex-driven scanner — never parses, so it cannot throw on malformed input.
@@ -1796,23 +1825,20 @@ const isIdentifier = (text) => /^[A-Za-z_][A-Za-z0-9_-]*$/.test(text);
1796
1825
  * unless it is already a `keyword`), and the value token after a color key's
1797
1826
  * colon — or any hex literal — is tagged `color`. The context never spans a
1798
1827
  * `;`, so a value can't leak past its statement.
1799
- *
1800
1828
  * @example
1801
1829
  * tokenizeFsl('s : { background-color: pink; }')
1802
1830
  * .filter(t => t.cls).map(t => [t.cls, t.text]);
1803
1831
  * // includes ['key','background-color'] and ['color','pink']
1804
1832
  */
1805
1833
  function tokenizeFsl(src) {
1834
+ var _a;
1806
1835
  const toks = [];
1807
1836
  let p = 0;
1808
1837
  let expectColorValue = false; // the next value token is the value of a color key
1809
1838
  while (p < src.length) {
1810
1839
  const rest = src.slice(p);
1811
1840
  let m;
1812
- if ((m = /^\/\/[^\n]*/.exec(rest))) {
1813
- toks.push({ cls: 'comment', text: m[0] });
1814
- }
1815
- else if ((m = /^\/\*[\s\S]*?\*\//.exec(rest))) {
1841
+ if ((_a = (m = /^\/\/[^\n]*/.exec(rest))) !== null && _a !== void 0 ? _a : (m = /^\/\*[\s\S]*?\*\//.exec(rest))) {
1816
1842
  toks.push({ cls: 'comment', text: m[0] });
1817
1843
  }
1818
1844
  else if ((m = /^"[^"]*"/.exec(rest))) {
@@ -1824,14 +1850,14 @@ function tokenizeFsl(src) {
1824
1850
  else if ((m = /^(?:<?[-=~]+>|[←→↔⇒⇐⇔↦])/.exec(rest))) {
1825
1851
  toks.push({ cls: 'arrow', text: m[0] });
1826
1852
  }
1827
- else if ((m = /^#[0-9A-Fa-f]{3,8}\b/.exec(rest))) {
1853
+ else if ((m = /^#[0-9A-F]{3,8}\b/i.exec(rest))) {
1828
1854
  toks.push({ cls: 'color', text: m[0] });
1829
1855
  expectColorValue = false;
1830
1856
  }
1831
1857
  else if ((m = /^\d+(?:\.\d+)*%?/.exec(rest))) {
1832
1858
  toks.push({ cls: 'number', text: m[0] });
1833
1859
  }
1834
- else if ((m = /^[A-Za-z_][A-Za-z0-9_-]*/.exec(rest))) {
1860
+ else if ((m = /^[A-Z_][\w-]*/i.exec(rest))) {
1835
1861
  const id = m[0];
1836
1862
  const cls = FSL_KEYWORDS.has(id) ? 'keyword' : (expectColorValue ? 'color' : null);
1837
1863
  expectColorValue = false; // any identifier consumes the pending value slot
@@ -1840,17 +1866,8 @@ function tokenizeFsl(src) {
1840
1866
  else {
1841
1867
  const ch = src[p];
1842
1868
  if (ch === ':') {
1843
- for (let j = toks.length - 1; j >= 0; j--) {
1844
- if (/^\s+$/.test(toks[j].text)) {
1845
- continue;
1846
- } // skip whitespace before the colon
1847
- if (toks[j].cls === null && isIdentifier(toks[j].text)) {
1848
- toks[j].cls = 'key';
1849
- if (FSL_COLOR_KEYS.has(toks[j].text)) {
1850
- expectColorValue = true;
1851
- }
1852
- }
1853
- break; // only the immediately-preceding token
1869
+ if (tagKeyBeforeColon(toks)) {
1870
+ expectColorValue = true;
1854
1871
  }
1855
1872
  }
1856
1873
  else if (ch === ';') {
@@ -1901,7 +1918,7 @@ function renderMarkdown(md) {
1901
1918
  const { lang, attrs } = parseFenceInfo(fence[1]);
1902
1919
  const buf = [];
1903
1920
  i++;
1904
- while (i < lines.length && !/^```/.test(lines[i])) {
1921
+ while (i < lines.length && !lines[i].startsWith('```')) {
1905
1922
  buf.push(lines[i]);
1906
1923
  i++;
1907
1924
  }
@@ -1917,13 +1934,16 @@ function renderMarkdown(md) {
1917
1934
  }
1918
1935
  continue;
1919
1936
  }
1920
- const head = /^(#{1,3})\s+(.*)$/.exec(line);
1937
+ // `(\S.*|)` (not `.*`) so the heading-text capture cannot trade characters
1938
+ // with the preceding `\s+` (regexp/no-super-linear-backtracking); the empty
1939
+ // alternative keeps the group defined for text-free headings, as before.
1940
+ const head = /^(#{1,3})\s+(\S.*|)$/.exec(line);
1921
1941
  if (head) {
1922
1942
  out.push(`<h${head[1].length}>${inline(head[2])}</h${head[1].length}>`);
1923
1943
  i++;
1924
1944
  continue;
1925
1945
  }
1926
- if (/^---+\s*$/.test(line)) {
1946
+ if (/^-{3,}\s*$/.test(line)) {
1927
1947
  out.push('<hr>');
1928
1948
  i++;
1929
1949
  continue;
@@ -1951,7 +1971,7 @@ function renderMarkdown(md) {
1951
1971
  continue;
1952
1972
  }
1953
1973
  const para = [];
1954
- while (i < lines.length && !/^\s*$/.test(lines[i]) && !/^(#{1,3}\s|```|\s*[-*]\s|\s*\d+\.\s|---+\s*$)/.test(lines[i])) {
1974
+ while (i < lines.length && !/^\s*$/.test(lines[i]) && !/^(?:#{1,3}\s|```|\s*[-*]\s|\s*\d+\.\s|-{3,}\s*$)/.test(lines[i])) {
1955
1975
  para.push(lines[i]);
1956
1976
  i++;
1957
1977
  }
@@ -2014,7 +2034,6 @@ const SECTIONS = [
2014
2034
  * curriculum (Getting Started / About State Machines / Tutorials / Example
2015
2035
  * Machines / Index / Search), a markdown page renderer, and "load into editor"
2016
2036
  * for tagged FSL examples. Content-only; slot it into `<fsl-help>`.
2017
- *
2018
2037
  * @element fsl-docs
2019
2038
  * @fires {CustomEvent<FslDocsLoadExampleDetail>} load-example - When a fence's "Load into editor" is clicked.
2020
2039
  */
@@ -2055,16 +2074,19 @@ class FslDocs extends LitElement {
2055
2074
  return html `
2056
2075
  <nav class="crumb"><span>Docs</span></nav>
2057
2076
  <ul class="nav">${SECTIONS.map(([id, label]) => html `
2058
- <li><a data-section=${id} @click=${() => id === 'index' ? this._go('index') : id === 'search' ? this._go('search') : this._go('pages', id)}>${label}</a></li>`)}</ul>`;
2077
+ <li><a data-section=${id} @click=${() => id === 'index' ? this._go('index') : (id === 'search' ? this._go('search') : this._go('pages', id))}>${label}</a></li>
2078
+ `)}</ul>
2079
+ `;
2059
2080
  }
2060
2081
  _renderPages() {
2061
2082
  const label = this._sectionLabel(this._section);
2062
2083
  const list = this._pagesIn(this._section);
2063
2084
  return html `
2064
2085
  <nav class="crumb"><a @click=${() => this._go('sections')}>Docs</a> / <span>${label}</span></nav>
2065
- <ul class="nav">${list.length
2086
+ <ul class="nav">${list.length > 0
2066
2087
  ? list.map(p => html `<li><a data-page=${p.id} @click=${() => this._go('page', this._section, p.id)}>${p.title}</a></li>`)
2067
- : html `<li class="empty">No pages yet.</li>`}</ul>`;
2088
+ : html `<li class="empty">No pages yet.</li>`}</ul>
2089
+ `;
2068
2090
  }
2069
2091
  _renderPage() {
2070
2092
  const p = DOCS_PAGES.find(x => x.id === this._pageId);
@@ -2079,19 +2101,30 @@ class FslDocs extends LitElement {
2079
2101
  if (e.target.classList.contains('docs-load-example')) {
2080
2102
  this._loadExample(e);
2081
2103
  }
2082
- }}>${unsafeHTML(this._withButtons(renderMarkdown(p.body)))}</article>`;
2104
+ }}>${unsafeHTML(this._withButtons(renderMarkdown(p.body)))}</article>
2105
+ `;
2083
2106
  }
2084
2107
  /** Append a "Load into editor" button to every runnable fsl fence. */
2085
2108
  _withButtons(htmlStr) {
2086
- return htmlStr.replace(/(<pre data-fsl-example[^>]*data-run="true"[^>]*>[\s\S]*?<\/pre>)/g, (m) => m.replace('</pre>', '<button class="docs-load-example">Load into editor</button></pre>'));
2109
+ return htmlStr.replace(/<pre data-fsl-example[^>]*data-run="true"[^>]*>[\s\S]*?<\/pre>/g, (m) => m.replace('</pre>', '<button class="docs-load-example">Load into editor</button></pre>'));
2087
2110
  }
2088
2111
  render() {
2089
2112
  switch (this._view) {
2090
- case 'pages': return this._renderPages();
2091
- case 'page': return this._renderPage();
2092
- case 'index': return this._renderIndex();
2093
- case 'search': return this._renderSearch();
2094
- default: return this._renderSections();
2113
+ case 'pages': {
2114
+ return this._renderPages();
2115
+ }
2116
+ case 'page': {
2117
+ return this._renderPage();
2118
+ }
2119
+ case 'index': {
2120
+ return this._renderIndex();
2121
+ }
2122
+ case 'search': {
2123
+ return this._renderSearch();
2124
+ }
2125
+ default: {
2126
+ return this._renderSections();
2127
+ }
2095
2128
  }
2096
2129
  }
2097
2130
  _renderIndex() {
@@ -2103,14 +2136,16 @@ class FslDocs extends LitElement {
2103
2136
  }
2104
2137
  return html `
2105
2138
  <nav class="crumb"><a @click=${() => this._go('sections')}>Docs</a> / <span>Index</span></nav>
2106
- ${Object.keys(bySurface).sort().map(surface => html `
2139
+ ${Object.keys(bySurface).sort((a, b) => a.localeCompare(b)).map(surface => html `
2107
2140
  <h3>${surface}</h3>
2108
2141
  <ul class="nav">${[...bySurface[surface]].sort((a, b) => a.title.localeCompare(b.title)).map(f => {
2109
2142
  const pg = teachesOf(f.id);
2110
2143
  return html `<li>${pg
2111
2144
  ? html `<a data-page=${pg.id} @click=${() => this._go('page', pg.section, pg.id)}>${f.title}</a>`
2112
2145
  : html `<span>${f.title}</span>`}</li>`;
2113
- })}</ul>`)}`;
2146
+ })}</ul>
2147
+ `)}
2148
+ `;
2114
2149
  }
2115
2150
  _renderSearch() {
2116
2151
  const q = this._query.trim().toLowerCase();
@@ -2129,11 +2164,12 @@ class FslDocs extends LitElement {
2129
2164
  <nav class="crumb"><a @click=${() => this._go('sections')}>Docs</a> / <span>Search</span></nav>
2130
2165
  <input class="search-input" type="search" placeholder="Search the docs…"
2131
2166
  .value=${this._query} @input=${(e) => { this._query = e.target.value; }}>
2132
- <ul class="nav">${hits.length
2167
+ <ul class="nav">${hits.length > 0
2133
2168
  ? hits.map(h => html `<li>${h.page
2134
2169
  ? html `<a data-page=${h.page} @click=${() => { const p = DOCS_PAGES.find(x => x.id === h.page); this._go('page', p.section, p.id); }}>${h.title}</a>`
2135
2170
  : html `<span>${h.title}</span>`} <em>${h.kind}</em></li>`)
2136
- : (q ? html `<li class="empty">No matches.</li>` : html ``)}</ul>`;
2171
+ : (q ? html `<li class="empty">No matches.</li>` : html ``)}</ul>
2172
+ `;
2137
2173
  }
2138
2174
  }
2139
2175
  FslDocs.styles = css `
@@ -9,11 +9,9 @@ export { FslEditor } from './editor.js';
9
9
  /**
10
10
  * Returns true when `tag_name` is exactly `fsl-<suffix>` or `jssm-<suffix>`
11
11
  * (case-insensitive).
12
- *
13
12
  * @param tag_name - The element tag name to test (e.g. `"FSL-VIZ"`, `"jssm-viz"`).
14
13
  * @param suffix - The suffix to match after the prefix (e.g. `"viz"`).
15
14
  * @returns `true` when `tag_name` is `fsl-<suffix>` or `jssm-<suffix>`.
16
- *
17
15
  * @example
18
16
  * wc_suffix_matches('FSL-VIZ', 'viz'); // true
19
17
  * wc_suffix_matches('jssm-viz', 'viz'); // true
@@ -33,14 +31,11 @@ export { FslEditor } from './editor.js';
33
31
  * dual-named components.
34
32
  *
35
33
  * Idempotent: skips the `define` call when the tag is already registered.
36
- *
37
34
  * @param canonical_tag - The `fsl-*` tag name (e.g. `"fsl-info-panel"`).
38
35
  * @param CanonicalClass - Constructor to register under `canonical_tag`.
39
- *
40
36
  * @example
41
37
  * class FslInfoPanel extends HTMLElement {}
42
38
  * define_canonical('fsl-info-panel', FslInfoPanel);
43
- *
44
39
  * @see define_with_synonym
45
40
  */
46
41
  function define_canonical(canonical_tag, CanonicalClass) {
package/dist/wc/editor.js CHANGED
@@ -41,7 +41,7 @@ function fslCompletionSource(context) {
41
41
  const before = line.text.slice(0, context.pos - line.from);
42
42
  const typed = /([\w-]*)$/.exec(before)[1];
43
43
  const items = fslCompletions(context.state.doc.toString(), context.pos);
44
- if (!items.length) {
44
+ if (items.length === 0) {
45
45
  return null;
46
46
  }
47
47
  return {
@@ -169,11 +169,9 @@ const fslTokens = css `
169
169
  /**
170
170
  * Returns true when `tag_name` is exactly `fsl-<suffix>` or `jssm-<suffix>`
171
171
  * (case-insensitive).
172
- *
173
172
  * @param tag_name - The element tag name to test (e.g. `"FSL-VIZ"`, `"jssm-viz"`).
174
173
  * @param suffix - The suffix to match after the prefix (e.g. `"viz"`).
175
174
  * @returns `true` when `tag_name` is `fsl-<suffix>` or `jssm-<suffix>`.
176
- *
177
175
  * @example
178
176
  * wc_suffix_matches('FSL-VIZ', 'viz'); // true
179
177
  * wc_suffix_matches('jssm-viz', 'viz'); // true
@@ -183,15 +181,12 @@ const fslTokens = css `
183
181
  /**
184
182
  * Returns the nearest ancestor of `el` (or `el` itself) whose tag is
185
183
  * `fsl-<suffix>` or `jssm-<suffix>`, or `null` if none exists.
186
- *
187
184
  * @param el - The element to start the search from.
188
185
  * @param suffix - The suffix to match (e.g. `"instance"`).
189
186
  * @returns The closest matching ancestor element, or `null`.
190
- *
191
187
  * @example
192
188
  * // <fsl-instance><div id="k"></div></fsl-instance>
193
189
  * closest_wc(document.getElementById('k'), 'instance'); // <fsl-instance>
194
- *
195
190
  * @see wc_suffix_matches
196
191
  */
197
192
  function closest_wc(el, suffix) {
@@ -212,7 +207,6 @@ var __decorate = (undefined && undefined.__decorate) || function (decorators, ta
212
207
  * each toggleable via a `no-*` attribute. Light/dark via the reflected `theme`
213
208
  * attribute (which also drives the `--fsl-*` token defaults). White-labeled
214
209
  * through the shared appearance contract. Emits `change` on user edits.
215
- *
216
210
  * @element fsl-editor
217
211
  * @fires {CustomEvent<FslEditorChangeDetail>} change - On every user edit (not on programmatic `fsl` writes).
218
212
  * @csspart editor - The CodeMirror editor container.
@@ -9,11 +9,9 @@ export { FslInstance } from './instance.js';
9
9
  /**
10
10
  * Returns true when `tag_name` is exactly `fsl-<suffix>` or `jssm-<suffix>`
11
11
  * (case-insensitive).
12
- *
13
12
  * @param tag_name - The element tag name to test (e.g. `"FSL-VIZ"`, `"jssm-viz"`).
14
13
  * @param suffix - The suffix to match after the prefix (e.g. `"viz"`).
15
14
  * @returns `true` when `tag_name` is `fsl-<suffix>` or `jssm-<suffix>`.
16
- *
17
15
  * @example
18
16
  * wc_suffix_matches('FSL-VIZ', 'viz'); // true
19
17
  * wc_suffix_matches('jssm-viz', 'viz'); // true
@@ -27,18 +25,15 @@ export { FslInstance } from './instance.js';
27
25
  * callers pass the canonical class and a thin subclass for the synonym.
28
26
  * The function is idempotent: if either tag is already registered it skips
29
27
  * that `define` call rather than throwing.
30
- *
31
28
  * @param canonical_tag - The primary tag name (e.g. `"fsl-instance"`).
32
29
  * @param synonym_tag - The alias tag name (e.g. `"jssm-instance"`).
33
30
  * @param CanonicalClass - Constructor to register under `canonical_tag`.
34
31
  * @param SynonymClass - Constructor to register under `synonym_tag`
35
32
  * (must be a distinct class from `CanonicalClass`).
36
- *
37
33
  * @example
38
34
  * class FslInstance extends HTMLElement {}
39
35
  * class JssmInstance extends FslInstance {}
40
36
  * define_with_synonym('fsl-instance', 'jssm-instance', FslInstance, JssmInstance);
41
- *
42
37
  * @see closest_wc
43
38
  */
44
39
  function define_with_synonym(canonical_tag, synonym_tag, CanonicalClass, SynonymClass) {
@@ -50,7 +45,6 @@ function define_with_synonym(canonical_tag, synonym_tag, CanonicalClass, Synonym
50
45
 
51
46
  /**
52
47
  * Thin subclass so `<jssm-instance>` registers under a distinct constructor.
53
- *
54
48
  * @deprecated The `jssm-*` tag and the `JssmInstance` class alias are
55
49
  * deprecated since v5 in favor of the canonical `<fsl-instance>` /
56
50
  * {@link FslInstance}, for fsl.tools brand alignment. They remain functional