which-heading-do-i-need 0.1.0 → 0.2.1

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.
@@ -2,9 +2,33 @@
2
2
  * Determines what your heading level should be (h1 - h6).
3
3
  *
4
4
  * In your app, you can use any of `<section>`, `<article>`, and `<aside>` elements to denote when the [_Section Heading_][mdn-h] element should change its level.
5
- Note that this demo starts with `h3`, because this docs page already has an `h1`, and _this_ section (Usage) uses an `h2`.
6
-
7
- * [mdn-h]: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/Heading_Elements
5
+ *
6
+ * [mdn-h]: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/Heading_Elements
7
+ *
8
+ * ```js
9
+ * import { getSectionHeadingLevel } from 'which-heading-do-i-need';
10
+ *
11
+ * getSectionHeadingLevel(nodeRef);
12
+ * ```
13
+ *
14
+ * Can also receive options, such as `startAt`
15
+ * Which is the root heading level to use if traversal makes it to the "top"
16
+ * of the available DOM tree.
17
+ * Defaults to 1 (as in h1)
18
+ *
19
+ * ```js
20
+ * import { getSectionHeadingLevel } from 'which-heading-do-i-need';
21
+ *
22
+ * getSectionHeadingLevel(nodeRef, { startAt: 3 });
23
+ *
8
24
  */
9
- export declare function getSectionHeadingLevel(node: Text): number;
25
+ export declare function getSectionHeadingLevel(node: Text, options?: {
26
+ /**
27
+ * The root heading level to use if traversal makes it to the "top"
28
+ * of the available DOM tree.
29
+ *
30
+ * Defaults to 1 (as in h1)
31
+ */
32
+ startAt?: number;
33
+ }): number;
10
34
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA4LA;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,IAAI,UAWhD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAmMA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,IAAI,EACV,OAAO,CAAC,EAAE;IACR;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,UAgBF"}
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ const BOUNDARY_ELEMENTS = new Set(['SECTION', 'ARTICLE', 'ASIDE', 'HEADER', 'FOO
7
7
  const SECTION_HEADINGS = new Set(['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6']);
8
8
  const TEST_BOUNDARY = 'ember-testing';
9
9
  function isRoot(element) {
10
- return element === document.body || element.id === TEST_BOUNDARY;
10
+ return element === document.body || element.id === TEST_BOUNDARY || !(element.parentElement || element.parentNode?.host);
11
11
  }
12
12
 
13
13
  /**
@@ -136,16 +136,35 @@ function levelOf(node) {
136
136
  * Determines what your heading level should be (h1 - h6).
137
137
  *
138
138
  * In your app, you can use any of `<section>`, `<article>`, and `<aside>` elements to denote when the [_Section Heading_][mdn-h] element should change its level.
139
- Note that this demo starts with `h3`, because this docs page already has an `h1`, and _this_ section (Usage) uses an `h2`.
140
-
141
- * [mdn-h]: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/Heading_Elements
139
+ *
140
+ * [mdn-h]: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/Heading_Elements
141
+ *
142
+ * ```js
143
+ * import { getSectionHeadingLevel } from 'which-heading-do-i-need';
144
+ *
145
+ * getSectionHeadingLevel(nodeRef);
146
+ * ```
147
+ *
148
+ * Can also receive options, such as `startAt`
149
+ * Which is the root heading level to use if traversal makes it to the "top"
150
+ * of the available DOM tree.
151
+ * Defaults to 1 (as in h1)
152
+ *
153
+ * ```js
154
+ * import { getSectionHeadingLevel } from 'which-heading-do-i-need';
155
+ *
156
+ * getSectionHeadingLevel(nodeRef, { startAt: 3 });
157
+ *
142
158
  */
143
- function getSectionHeadingLevel(node) {
159
+ function getSectionHeadingLevel(node, options) {
144
160
  const existing = LOOKUP.get(node);
145
161
  if (existing) return existing;
146
162
  const parentLevel = levelOf(node);
147
163
  const myLevel = parentLevel;
148
164
  LOOKUP.set(node, myLevel);
165
+ if (myLevel === 1 && options?.startAt) {
166
+ return options.startAt;
167
+ }
149
168
  return myLevel;
150
169
  }
151
170
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["const LOOKUP = new WeakMap<Text, number>();\n\nconst BOUNDARY_ELEMENTS = new Set([\n 'SECTION',\n 'ARTICLE',\n 'ASIDE',\n 'HEADER',\n 'FOOTER',\n 'MAIN',\n 'NAV',\n]);\n\n/**\n * A set with both cases is more performant than calling toLowerCase\n */\nconst SECTION_HEADINGS = new Set([\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'H1',\n 'H2',\n 'H3',\n 'H4',\n 'H5',\n 'H6',\n]);\nconst TEST_BOUNDARY = 'ember-testing';\n\nfunction isRoot(element: Element) {\n return element === document.body || element.id === TEST_BOUNDARY;\n}\n\n/**\n * node is our current traversal node as we head up the DOM tree (towards the root)\n * previous node is the immediate child within that current traversal node that we came from.\n *\n * The previousNode is used for an optimization so that we can iterate *from*\n * that child within the current traversal node, rather than always starting from the\n * first child of the current traversal node.\n */\nfunction findHeadingIn(\n node: ParentNode | ChildNode,\n previousNode?: ParentNode,\n): number | undefined {\n if (!(node instanceof Element)) return;\n\n if (SECTION_HEADINGS.has(node.tagName)) {\n const level = parseInt(node.tagName.replace('h', '').replace('H', ''));\n\n return level;\n }\n\n /**\n * Previous traversal does not search within the section boundaies\n * This is because previous traversal is looking for a similar heading level, and crossing a section boundary changes the section level.\n */\n if (previousNode) {\n let previous = previousNode.previousSibling;\n\n while (previous) {\n if (!(previous instanceof Element)) {\n previous = previous.previousSibling;\n continue;\n }\n\n if (BOUNDARY_ELEMENTS.has(previous.tagName)) {\n previous = previous.previousSibling;\n continue;\n }\n\n const level = findHeadingIn(previous);\n\n /**\n * We subtract one, because we may have found\n * an equal heading, due to it being a sibling\n */\n if (level) return level;\n\n previous = previous.previousSibling;\n }\n }\n\n /**\n * Fallback traversal if we still haven't found the\n * heading level, we check all the children\n * of the current node, because headings can be\n * within <a> tags and such.\n */\n for (const child of node.children) {\n const level = findHeadingIn(child);\n\n if (level) return level;\n }\n}\n\n/**\n * The Platform native 'closest' function can't punch through shadow-boundaries\n */\nfunction nearestAncestor(\n node: Text | Element,\n matcher: (el: Element) => boolean,\n) {\n let parent: ParentNode | null = node.parentElement;\n\n if (!parent) return;\n\n while (parent) {\n if (parent instanceof Element) {\n if (matcher(parent)) return parent;\n }\n\n if (parent instanceof ShadowRoot) {\n parent = parent.host;\n }\n\n parent = parent.parentNode;\n }\n}\n\n/**\n * The algorithm:\n *\n * section <- \"our\" level-changing boundary element\n * h# <- the element we want to figure out the level of\n *\n * We start assuming we'll emit an h1.\n * We adjust this based on what we find crawling up the tree.\n *\n * While traversing up, when we go from the h# to the section,\n * and ignore it. Because this alone has no bearing on if the h# should be an h2.\n * We need to continue traversing upwards, until we hit the next boundary element.\n *\n * IF we would change the level the heading, we will find another heading between\n * these two boundary elements.\n * We'll need to check the subtrees between these elements, stopping if we\n * encounter other boundary elements.\n *\n */\nfunction levelOf(node: Text): number {\n const ourBoundary = nearestAncestor(node, (el) =>\n BOUNDARY_ELEMENTS.has(el.tagName),\n );\n\n /**\n * We are the top-level\n */\n if (!ourBoundary) {\n return 1;\n }\n\n const stopAt = nearestAncestor(ourBoundary, (el) => {\n if (BOUNDARY_ELEMENTS.has(el.tagName)) return true;\n\n return isRoot(el);\n });\n\n if (!stopAt) {\n throw new Error(\n `[BUG]: Could not find a stopping boundary for automatic heading level detection. Checked for ${[...BOUNDARY_ELEMENTS, 'body', '#ember-testing'].map((x) => x.toLowerCase()).join(', ')}`,\n );\n }\n\n let previous: ParentNode = ourBoundary;\n let current: ParentNode | null = ourBoundary.parentNode;\n\n while (current) {\n const level = findHeadingIn(current, previous);\n\n if (level) {\n return level + 1;\n }\n\n if (current === stopAt) break;\n\n if (current instanceof ShadowRoot) {\n current = current.host;\n }\n\n previous = current;\n current = current.parentNode;\n }\n\n return 1;\n}\n\n/**\n * Determines what your heading level should be (h1 - h6).\n *\n * In your app, you can use any of `<section>`, `<article>`, and `<aside>` elements to denote when the [_Section Heading_][mdn-h] element should change its level.\nNote that this demo starts with `h3`, because this docs page already has an `h1`, and _this_ section (Usage) uses an `h2`.\n\n * [mdn-h]: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/Heading_Elements\n */\nexport function getSectionHeadingLevel(node: Text) {\n const existing = LOOKUP.get(node);\n\n if (existing) return existing;\n\n const parentLevel = levelOf(node);\n const myLevel = parentLevel;\n\n LOOKUP.set(node, myLevel);\n\n return myLevel;\n}\n"],"names":["LOOKUP","WeakMap","BOUNDARY_ELEMENTS","Set","SECTION_HEADINGS","TEST_BOUNDARY","isRoot","element","document","body","id","findHeadingIn","node","previousNode","Element","has","tagName","level","parseInt","replace","previous","previousSibling","child","children","nearestAncestor","matcher","parent","parentElement","ShadowRoot","host","parentNode","levelOf","ourBoundary","el","stopAt","Error","map","x","toLowerCase","join","current","getSectionHeadingLevel","existing","get","parentLevel","myLevel","set"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["const LOOKUP = new WeakMap<Text, number>();\n\nconst BOUNDARY_ELEMENTS = new Set([\n 'SECTION',\n 'ARTICLE',\n 'ASIDE',\n 'HEADER',\n 'FOOTER',\n 'MAIN',\n 'NAV',\n]);\n\n/**\n * A set with both cases is more performant than calling toLowerCase\n */\nconst SECTION_HEADINGS = new Set([\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'H1',\n 'H2',\n 'H3',\n 'H4',\n 'H5',\n 'H6',\n]);\nconst TEST_BOUNDARY = 'ember-testing';\n\nfunction isRoot(element: Element) {\n return (\n element === document.body ||\n element.id === TEST_BOUNDARY ||\n !(\n element.parentElement ||\n (element.parentNode as unknown as ShadowRoot)?.host\n )\n );\n}\n\n/**\n * node is our current traversal node as we head up the DOM tree (towards the root)\n * previous node is the immediate child within that current traversal node that we came from.\n *\n * The previousNode is used for an optimization so that we can iterate *from*\n * that child within the current traversal node, rather than always starting from the\n * first child of the current traversal node.\n */\nfunction findHeadingIn(\n node: ParentNode | ChildNode,\n previousNode?: ParentNode,\n): number | undefined {\n if (!(node instanceof Element)) return;\n\n if (SECTION_HEADINGS.has(node.tagName)) {\n const level = parseInt(node.tagName.replace('h', '').replace('H', ''));\n\n return level;\n }\n\n /**\n * Previous traversal does not search within the section boundaies\n * This is because previous traversal is looking for a similar heading level, and crossing a section boundary changes the section level.\n */\n if (previousNode) {\n let previous = previousNode.previousSibling;\n\n while (previous) {\n if (!(previous instanceof Element)) {\n previous = previous.previousSibling;\n continue;\n }\n\n if (BOUNDARY_ELEMENTS.has(previous.tagName)) {\n previous = previous.previousSibling;\n continue;\n }\n\n const level = findHeadingIn(previous);\n\n /**\n * We subtract one, because we may have found\n * an equal heading, due to it being a sibling\n */\n if (level) return level;\n\n previous = previous.previousSibling;\n }\n }\n\n /**\n * Fallback traversal if we still haven't found the\n * heading level, we check all the children\n * of the current node, because headings can be\n * within <a> tags and such.\n */\n for (const child of node.children) {\n const level = findHeadingIn(child);\n\n if (level) return level;\n }\n}\n\n/**\n * The Platform native 'closest' function can't punch through shadow-boundaries\n */\nfunction nearestAncestor(\n node: Text | Element,\n matcher: (el: Element) => boolean,\n) {\n let parent: ParentNode | null = node.parentElement;\n\n if (!parent) return;\n\n while (parent) {\n if (parent instanceof Element) {\n if (matcher(parent)) return parent;\n }\n\n if (parent instanceof ShadowRoot) {\n parent = parent.host;\n }\n\n parent = parent.parentNode;\n }\n}\n\n/**\n * The algorithm:\n *\n * section <- \"our\" level-changing boundary element\n * h# <- the element we want to figure out the level of\n *\n * We start assuming we'll emit an h1.\n * We adjust this based on what we find crawling up the tree.\n *\n * While traversing up, when we go from the h# to the section,\n * and ignore it. Because this alone has no bearing on if the h# should be an h2.\n * We need to continue traversing upwards, until we hit the next boundary element.\n *\n * IF we would change the level the heading, we will find another heading between\n * these two boundary elements.\n * We'll need to check the subtrees between these elements, stopping if we\n * encounter other boundary elements.\n *\n */\nfunction levelOf(node: Text): number {\n const ourBoundary = nearestAncestor(node, (el) =>\n BOUNDARY_ELEMENTS.has(el.tagName),\n );\n\n /**\n * We are the top-level\n */\n if (!ourBoundary) {\n return 1;\n }\n\n const stopAt = nearestAncestor(ourBoundary, (el) => {\n if (BOUNDARY_ELEMENTS.has(el.tagName)) return true;\n\n return isRoot(el);\n });\n\n if (!stopAt) {\n throw new Error(\n `[BUG]: Could not find a stopping boundary for automatic heading level detection. Checked for ${[...BOUNDARY_ELEMENTS, 'body', '#ember-testing'].map((x) => x.toLowerCase()).join(', ')}`,\n );\n }\n\n let previous: ParentNode = ourBoundary;\n let current: ParentNode | null = ourBoundary.parentNode;\n\n while (current) {\n const level = findHeadingIn(current, previous);\n\n if (level) {\n return level + 1;\n }\n\n if (current === stopAt) break;\n\n if (current instanceof ShadowRoot) {\n current = current.host;\n }\n\n previous = current;\n current = current.parentNode;\n }\n\n return 1;\n}\n\n/**\n * Determines what your heading level should be (h1 - h6).\n *\n * In your app, you can use any of `<section>`, `<article>`, and `<aside>` elements to denote when the [_Section Heading_][mdn-h] element should change its level.\n *\n * [mdn-h]: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/Heading_Elements\n *\n * ```js\n * import { getSectionHeadingLevel } from 'which-heading-do-i-need';\n *\n * getSectionHeadingLevel(nodeRef);\n * ```\n *\n * Can also receive options, such as `startAt`\n * Which is the root heading level to use if traversal makes it to the \"top\"\n * of the available DOM tree.\n * Defaults to 1 (as in h1)\n *\n * ```js\n * import { getSectionHeadingLevel } from 'which-heading-do-i-need';\n *\n * getSectionHeadingLevel(nodeRef, { startAt: 3 });\n *\n */\nexport function getSectionHeadingLevel(\n node: Text,\n options?: {\n /**\n * The root heading level to use if traversal makes it to the \"top\"\n * of the available DOM tree.\n *\n * Defaults to 1 (as in h1)\n */\n startAt?: number;\n },\n) {\n const existing = LOOKUP.get(node);\n\n if (existing) return existing;\n\n const parentLevel = levelOf(node);\n const myLevel = parentLevel;\n\n LOOKUP.set(node, myLevel);\n\n if (myLevel === 1 && options?.startAt) {\n return options.startAt;\n }\n\n return myLevel;\n}\n"],"names":["LOOKUP","WeakMap","BOUNDARY_ELEMENTS","Set","SECTION_HEADINGS","TEST_BOUNDARY","isRoot","element","document","body","id","parentElement","parentNode","host","findHeadingIn","node","previousNode","Element","has","tagName","level","parseInt","replace","previous","previousSibling","child","children","nearestAncestor","matcher","parent","ShadowRoot","levelOf","ourBoundary","el","stopAt","Error","map","x","toLowerCase","join","current","getSectionHeadingLevel","options","existing","get","parentLevel","myLevel","set","startAt"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "which-heading-do-i-need",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "The default blueprint for Embroider v2 addons.",
5
5
  "type": "module",
6
6
  "keywords": [