accented 1.2.5 → 1.3.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/dist/constants.d.ts +12 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +32 -0
- package/dist/constants.js.map +1 -1
- package/dist/elements/accented-dialog.d.ts +1 -367
- package/dist/elements/accented-dialog.d.ts.map +1 -1
- package/dist/elements/accented-dialog.js.map +1 -1
- package/dist/elements/accented-trigger.d.ts +1 -366
- package/dist/elements/accented-trigger.d.ts.map +1 -1
- package/dist/elements/accented-trigger.js.map +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +79 -41
- package/dist/scanner.js.map +1 -1
- package/dist/utils/create-extended-element-with-issues.d.ts +3 -0
- package/dist/utils/create-extended-element-with-issues.d.ts.map +1 -0
- package/dist/utils/create-extended-element-with-issues.js +56 -0
- package/dist/utils/create-extended-element-with-issues.js.map +1 -0
- package/dist/utils/css-transforms.d.ts.map +1 -1
- package/dist/utils/css-transforms.js +0 -2
- package/dist/utils/css-transforms.js.map +1 -1
- package/dist/utils/get-all-rules-from-axe-options.d.ts +3 -0
- package/dist/utils/get-all-rules-from-axe-options.d.ts.map +1 -0
- package/dist/utils/get-all-rules-from-axe-options.js +51 -0
- package/dist/utils/get-all-rules-from-axe-options.js.map +1 -0
- package/dist/utils/shadow-dom-aware-mutation-observer.d.ts +1 -9
- package/dist/utils/shadow-dom-aware-mutation-observer.d.ts.map +1 -1
- package/dist/utils/shadow-dom-aware-mutation-observer.js.map +1 -1
- package/dist/utils/transform-violations.d.ts.map +1 -1
- package/dist/utils/transform-violations.js +2 -13
- package/dist/utils/transform-violations.js.map +1 -1
- package/dist/utils/update-elements-with-issues.d.ts +4 -3
- package/dist/utils/update-elements-with-issues.d.ts.map +1 -1
- package/dist/utils/update-elements-with-issues.js +36 -80
- package/dist/utils/update-elements-with-issues.js.map +1 -1
- package/package.json +5 -5
- package/src/constants.ts +34 -0
- package/src/elements/accented-dialog.ts +1 -1
- package/src/elements/accented-trigger.ts +1 -1
- package/src/logger.ts +1 -1
- package/src/scanner.ts +91 -45
- package/src/utils/create-extended-element-with-issues.ts +67 -0
- package/src/utils/css-transforms.ts +0 -2
- package/src/utils/get-all-rules-from-axe-options.test.ts +169 -0
- package/src/utils/get-all-rules-from-axe-options.ts +54 -0
- package/src/utils/shadow-dom-aware-mutation-observer.ts +4 -1
- package/src/utils/transform-violations.ts +2 -14
- package/src/utils/update-elements-with-issues.test.ts +223 -139
- package/src/utils/update-elements-with-issues.ts +76 -107
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { signal } from '@preact/signals-core';
|
|
2
|
+
import { isSvgElement } from './dom-helpers.js';
|
|
3
|
+
import { getElementPosition } from './get-element-position.js';
|
|
4
|
+
import { getParent } from './get-parent.js';
|
|
5
|
+
import { getScrollableAncestors } from './get-scrollable-ancestors.js';
|
|
6
|
+
import { supportsAnchorPositioning } from './supports-anchor-positioning.js';
|
|
7
|
+
function shouldSkipRender(element) {
|
|
8
|
+
// Skip rendering if the element is inside an SVG:
|
|
9
|
+
// https://github.com/pomerantsev/accented/issues/62
|
|
10
|
+
const parent = getParent(element);
|
|
11
|
+
const isInsideSvg = Boolean(parent && isSvgElement(parent));
|
|
12
|
+
// Some issues, such as meta-viewport, are on <head> descendants,
|
|
13
|
+
// but since <head> is never rendered, we don't want to output anything
|
|
14
|
+
// for those in the DOM.
|
|
15
|
+
// We're not anticipating the use of shadow DOM in <head>,
|
|
16
|
+
// so the use of .closest() should be fine.
|
|
17
|
+
const isInsideHead = element.closest('head') !== null;
|
|
18
|
+
return isInsideSvg || isInsideHead;
|
|
19
|
+
}
|
|
20
|
+
let count = 0;
|
|
21
|
+
export function createExtendedElementWithIssues(elementWithIssues, name) {
|
|
22
|
+
const id = count++;
|
|
23
|
+
const trigger = document.createElement(`${name}-trigger`);
|
|
24
|
+
const elementZIndex = Number.parseInt(getComputedStyle(elementWithIssues.element).zIndex, 10);
|
|
25
|
+
if (!Number.isNaN(elementZIndex)) {
|
|
26
|
+
trigger.style.setProperty('z-index', (elementZIndex + 1).toString(), 'important');
|
|
27
|
+
}
|
|
28
|
+
trigger.style.setProperty('position-anchor', `--${name}-anchor-${id}`, 'important');
|
|
29
|
+
trigger.dataset.id = id.toString();
|
|
30
|
+
const accentedDialog = document.createElement(`${name}-dialog`);
|
|
31
|
+
trigger.dialog = accentedDialog;
|
|
32
|
+
const position = getElementPosition(elementWithIssues.element);
|
|
33
|
+
trigger.position = signal(position);
|
|
34
|
+
trigger.visible = signal(true);
|
|
35
|
+
trigger.element = elementWithIssues.element;
|
|
36
|
+
const scrollableAncestors = supportsAnchorPositioning()
|
|
37
|
+
? new Set()
|
|
38
|
+
: getScrollableAncestors(elementWithIssues.element);
|
|
39
|
+
const issues = signal(elementWithIssues.issues);
|
|
40
|
+
accentedDialog.issues = issues;
|
|
41
|
+
accentedDialog.element = elementWithIssues.element;
|
|
42
|
+
return {
|
|
43
|
+
id,
|
|
44
|
+
element: elementWithIssues.element,
|
|
45
|
+
skipRender: shouldSkipRender(elementWithIssues.element),
|
|
46
|
+
rootNode: elementWithIssues.rootNode,
|
|
47
|
+
visible: trigger.visible,
|
|
48
|
+
position: trigger.position,
|
|
49
|
+
scrollableAncestors: signal(scrollableAncestors),
|
|
50
|
+
anchorNameValue: elementWithIssues.element.style.getPropertyValue('anchor-name') ||
|
|
51
|
+
getComputedStyle(elementWithIssues.element).getPropertyValue('anchor-name'),
|
|
52
|
+
trigger,
|
|
53
|
+
issues,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=create-extended-element-with-issues.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-extended-element-with-issues.js","sourceRoot":"","sources":["../../src/utils/create-extended-element-with-issues.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"css-transforms.d.ts","sourceRoot":"","sources":["../../src/utils/css-transforms.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,wBAAgB,oCAAoC,YAEnD;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,
|
|
1
|
+
{"version":3,"file":"css-transforms.d.ts","sourceRoot":"","sources":["../../src/utils/css-transforms.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,wBAAgB,oCAAoC,YAEnD;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,SAsB3C"}
|
|
@@ -20,13 +20,11 @@ export function initializeCssTransformsCheck() {
|
|
|
20
20
|
anchor.style.inlineSize = '100px';
|
|
21
21
|
anchor.style.blockSize = '100px';
|
|
22
22
|
anchor.style.transform = 'translateX(100px)';
|
|
23
|
-
// @ts-expect-error TS is unaware of `anchor-name`
|
|
24
23
|
anchor.style.anchorName = '--test-anchor';
|
|
25
24
|
const anchored = document.createElement('div');
|
|
26
25
|
anchored.style.inlineSize = '10px';
|
|
27
26
|
anchored.style.blockSize = '10px';
|
|
28
27
|
anchored.style.position = 'absolute';
|
|
29
|
-
// @ts-expect-error TS is unaware of `position-anchor`
|
|
30
28
|
anchored.style.positionAnchor = '--test-anchor';
|
|
31
29
|
anchored.style.insetInlineStart = 'anchor(start)';
|
|
32
30
|
anchored.style.insetBlockStart = 'anchor(start)';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"css-transforms.js","sourceRoot":"","sources":["../../src/utils/css-transforms.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,IAAI,UAAmB,CAAC;AAExB,MAAM,UAAU,oCAAoC;IAClD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,4BAA4B;IAC1C,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,OAAO,CAAC;IAClC,MAAM,CAAC,KAAK,CAAC,SAAS,GAAG,OAAO,CAAC;IACjC,MAAM,CAAC,KAAK,CAAC,SAAS,GAAG,mBAAmB,CAAC;IAC7C,
|
|
1
|
+
{"version":3,"file":"css-transforms.js","sourceRoot":"","sources":["../../src/utils/css-transforms.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,IAAI,UAAmB,CAAC;AAExB,MAAM,UAAU,oCAAoC;IAClD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,4BAA4B;IAC1C,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,OAAO,CAAC;IAClC,MAAM,CAAC,KAAK,CAAC,SAAS,GAAG,OAAO,CAAC;IACjC,MAAM,CAAC,KAAK,CAAC,SAAS,GAAG,mBAAmB,CAAC;IAC7C,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,eAAe,CAAC;IAE1C,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC/C,QAAQ,CAAC,KAAK,CAAC,UAAU,GAAG,MAAM,CAAC;IACnC,QAAQ,CAAC,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAC;IACrC,QAAQ,CAAC,KAAK,CAAC,cAAc,GAAG,eAAe,CAAC;IAChD,QAAQ,CAAC,KAAK,CAAC,gBAAgB,GAAG,eAAe,CAAC;IAClD,QAAQ,CAAC,KAAK,CAAC,eAAe,GAAG,eAAe,CAAC;IAEjD,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAEpC,UAAU,GAAG,MAAM,CAAC,qBAAqB,EAAE,CAAC,IAAI,KAAK,QAAQ,CAAC,qBAAqB,EAAE,CAAC,IAAI,CAAC;IAE3F,MAAM,CAAC,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,MAAM,EAAE,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-all-rules-from-axe-options.d.ts","sourceRoot":"","sources":["../../src/utils/get-all-rules-from-axe-options.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA6B9C,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,CAiB7E"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/* Adapts two axe-core behaviors:
|
|
2
|
+
- shorthand string/array runOnly normalization from normalizeOptions:
|
|
3
|
+
https://github.com/dequelabs/axe-core/blob/9261d074b60527a84f4dce5a64a6d5a5843a0772/lib/core/base/audit.js#L408-L428
|
|
4
|
+
- which rules to include for a given runOnly/rules combination, from ruleShouldRun (lines 65–80,
|
|
5
|
+
omitting the rule.pageLevel check — axe applies that itself when we call axe.run):
|
|
6
|
+
https://github.com/dequelabs/axe-core/blob/9261d074b60527a84f4dce5a64a6d5a5843a0772/lib/core/utils/rule-should-run.js */
|
|
7
|
+
import axe from 'axe-core';
|
|
8
|
+
function getRuleIds(tags) {
|
|
9
|
+
return new Set(axe.getRules(tags).map((r) => r.ruleId));
|
|
10
|
+
}
|
|
11
|
+
function applyOverrides(ruleSet, rules) {
|
|
12
|
+
if (!rules)
|
|
13
|
+
return ruleSet;
|
|
14
|
+
for (const [ruleId, ruleConfig] of Object.entries(rules)) {
|
|
15
|
+
if (ruleConfig.enabled === false)
|
|
16
|
+
ruleSet.delete(ruleId);
|
|
17
|
+
else if (ruleConfig.enabled === true)
|
|
18
|
+
ruleSet.add(ruleId);
|
|
19
|
+
}
|
|
20
|
+
return ruleSet;
|
|
21
|
+
}
|
|
22
|
+
// Normalizes the string/array shorthands of runOnly into the { type, values } object form.
|
|
23
|
+
function normalizeRunOnly(runOnly, allRuleIds) {
|
|
24
|
+
if (typeof runOnly !== 'string' && !Array.isArray(runOnly))
|
|
25
|
+
return runOnly;
|
|
26
|
+
const values = typeof runOnly === 'string' ? [runOnly] : runOnly;
|
|
27
|
+
const isRulePath = values.every((v) => allRuleIds.has(v));
|
|
28
|
+
const isTagPath = values.every((v) => !allRuleIds.has(v));
|
|
29
|
+
if (!isRulePath && !isTagPath)
|
|
30
|
+
throw new Error(`runOnly mixes rule IDs and tag values: ${values.join(', ')}`);
|
|
31
|
+
return { type: isRulePath ? 'rule' : 'tag', values };
|
|
32
|
+
}
|
|
33
|
+
export function getAllRulesFromAxeOptions(axeOptions) {
|
|
34
|
+
const allRuleIds = getRuleIds();
|
|
35
|
+
const { rules, runOnly } = axeOptions;
|
|
36
|
+
if (runOnly === undefined) {
|
|
37
|
+
// axe.getRules() includes rules disabled by default; axe skips them via rule.enabled !== false.
|
|
38
|
+
// Replicate that here using the internal _audit.rules, which exposes the enabled flag.
|
|
39
|
+
// @ts-expect-error: _audit is an undocumented internal axe-core API not present in its type definitions
|
|
40
|
+
for (const rule of axe._audit.rules) {
|
|
41
|
+
if (rule.enabled === false)
|
|
42
|
+
allRuleIds.delete(rule.id);
|
|
43
|
+
}
|
|
44
|
+
return applyOverrides(allRuleIds, rules);
|
|
45
|
+
}
|
|
46
|
+
const { type, values } = normalizeRunOnly(runOnly, allRuleIds);
|
|
47
|
+
if (type === 'rule' || type === 'rules')
|
|
48
|
+
return new Set(values);
|
|
49
|
+
return applyOverrides(getRuleIds(values), rules);
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=get-all-rules-from-axe-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-all-rules-from-axe-options.js","sourceRoot":"","sources":["../../src/utils/get-all-rules-from-axe-options.ts"],"names":[],"mappings":"AAAA;;;;;6HAK6H;AAC7H,OAAO,GAAG,MAAM,UAAU,CAAC;AAG3B,SAAS,UAAU,CAAC,IAAoB;IACtC,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,cAAc,CAAC,OAAoB,EAAE,KAA0B;IACtE,IAAI,CAAC,KAAK;QAAE,OAAO,OAAO,CAAC;IAC3B,KAAK,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzD,IAAI,UAAU,CAAC,OAAO,KAAK,KAAK;YAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;aACpD,IAAI,UAAU,CAAC,OAAO,KAAK,IAAI;YAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,2FAA2F;AAC3F,SAAS,gBAAgB,CACvB,OAAkD,EAClD,UAAuB;IAEvB,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IAC3E,MAAM,MAAM,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IACjE,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1D,IAAI,CAAC,UAAU,IAAI,CAAC,SAAS;QAC3B,MAAM,IAAI,KAAK,CAAC,0CAA0C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjF,OAAO,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,UAAsB;IAC9D,MAAM,UAAU,GAAG,UAAU,EAAE,CAAC;IAChC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC;IAEtC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,gGAAgG;QAChG,uFAAuF;QACvF,wGAAwG;QACxG,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACpC,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK;gBAAE,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzD,CAAC;QACD,OAAO,cAAc,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC/D,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IAChE,OAAO,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -1,10 +1,2 @@
|
|
|
1
|
-
export declare function createShadowDOMAwareMutationObserver(name: string, callback: MutationCallback):
|
|
2
|
-
"__#private@#shadowRoots": Map<ShadowRoot, /*elided*/ any>;
|
|
3
|
-
"__#private@#options": MutationObserverInit | undefined;
|
|
4
|
-
observe(target: Node, options?: MutationObserverInit): void;
|
|
5
|
-
disconnect(): void;
|
|
6
|
-
"__#private@#observeShadowRoots": (elements: Array<Element | Document | DocumentFragment>) => void;
|
|
7
|
-
"__#private@#unobserveShadowRoots": (elements: Array<Element | Document | DocumentFragment>) => void;
|
|
8
|
-
takeRecords(): MutationRecord[];
|
|
9
|
-
};
|
|
1
|
+
export declare function createShadowDOMAwareMutationObserver(name: string, callback: MutationCallback): MutationObserver;
|
|
10
2
|
//# sourceMappingURL=shadow-dom-aware-mutation-observer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shadow-dom-aware-mutation-observer.d.ts","sourceRoot":"","sources":["../../src/utils/shadow-dom-aware-mutation-observer.ts"],"names":[],"mappings":"AAaA,wBAAgB,oCAAoC,
|
|
1
|
+
{"version":3,"file":"shadow-dom-aware-mutation-observer.d.ts","sourceRoot":"","sources":["../../src/utils/shadow-dom-aware-mutation-observer.ts"],"names":[],"mappings":"AAaA,wBAAgB,oCAAoC,CAClD,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,gBAAgB,GACzB,gBAAgB,CAmElB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shadow-dom-aware-mutation-observer.js","sourceRoot":"","sources":["../../src/utils/shadow-dom-aware-mutation-observer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7E,SAAS,cAAc,CAAC,QAAsD;IAC5E,OAAO,QAAQ;SACZ,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SAC7E,MAAM,CACL,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CACf,SAAS,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,EACjF,EAAE,CACH,CAAC;AACN,CAAC;AAED,MAAM,UAAU,oCAAoC,
|
|
1
|
+
{"version":3,"file":"shadow-dom-aware-mutation-observer.js","sourceRoot":"","sources":["../../src/utils/shadow-dom-aware-mutation-observer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform-violations.d.ts","sourceRoot":"","sources":["../../src/utils/transform-violations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,KAAK,EAAE,iBAAiB,EAAS,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"transform-violations.d.ts","sourceRoot":"","sources":["../../src/utils/transform-violations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,KAAK,EAAE,iBAAiB,EAAS,MAAM,aAAa,CAAC;AAa5D,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,OAAO,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,uBAsDzF"}
|
|
@@ -1,17 +1,6 @@
|
|
|
1
|
-
import { issuesUrl, orderedImpacts } from '../constants.js';
|
|
2
|
-
// This is a list of axe-core violations (their ids) that may be flagged by axe-core
|
|
3
|
-
// as false positives if an Accented trigger is a descendant of the element with the issue.
|
|
4
|
-
const violationsAffectedByAccentedTriggers = [
|
|
5
|
-
'aria-hidden-focus',
|
|
6
|
-
'aria-text',
|
|
7
|
-
'definition-list',
|
|
8
|
-
'label-content-name-mismatch',
|
|
9
|
-
'list',
|
|
10
|
-
'nested-interactive',
|
|
11
|
-
'scrollable-region-focusable', // The Accented trigger might make the content grow such that scrolling is required.
|
|
12
|
-
];
|
|
1
|
+
import { issuesUrl, orderedImpacts, violationsAffectedByAccentedTriggers } from '../constants.js';
|
|
13
2
|
function maybeCausedByAccented(violationId, element, name) {
|
|
14
|
-
return (violationsAffectedByAccentedTriggers.
|
|
3
|
+
return (violationsAffectedByAccentedTriggers.has(violationId) &&
|
|
15
4
|
Boolean(element.querySelector(`${name}-trigger`)));
|
|
16
5
|
}
|
|
17
6
|
function impactCompare(a, b) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform-violations.js","sourceRoot":"","sources":["../../src/utils/transform-violations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"transform-violations.js","sourceRoot":"","sources":["../../src/utils/transform-violations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,oCAAoC,EAAE,MAAM,iBAAiB,CAAC;AAGlG,SAAS,qBAAqB,CAAC,WAAmB,EAAE,OAAoB,EAAE,IAAY;IACpF,OAAO,CACL,oCAAoC,CAAC,GAAG,CAAC,WAAW,CAAC;QACrD,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI,UAAU,CAAC,CAAC,CAClD,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,CAAkB,EAAE,CAAkB;IAC3D,OAAO,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,UAAwC,EAAE,IAAY;IACxF,MAAM,kBAAkB,GAA6B,EAAE,CAAC;IAExD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;YACnC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;YAEjC,4EAA4E;YAC5E,8EAA8E;YAC9E,2CAA2C;YAC3C,mGAAmG;YACnG,yEAAyE;YACzE,sHAAsH;YACtH,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;YAErC,IAAI,OAAO,IAAI,CAAC,UAAU,IAAI,CAAC,qBAAqB,CAAC,SAAS,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;gBAClF,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;oBACtB,OAAO,CAAC,IAAI,CACV,sKAAsK,SAAS,GAAG,EAClL,SAAS,CACV,CAAC;oBACF,SAAS;gBACX,CAAC;gBACD,MAAM,KAAK,GAAU;oBACnB,EAAE,EAAE,SAAS,CAAC,EAAE;oBAChB,KAAK,EAAE,SAAS,CAAC,IAAI;oBACrB,yDAAyD;oBACzD,WAAW,EAAE,IAAI,CAAC,cAAc,IAAI,SAAS,CAAC,WAAW;oBACzD,GAAG,EAAE,SAAS,CAAC,OAAO;oBACtB,MAAM,EAAE,SAAS,CAAC,MAAM;iBACzB,CAAC;gBACF,MAAM,eAAe,GAAG,kBAAkB,CAAC,IAAI,CAC7C,CAAC,iBAAiB,EAAE,EAAE,CAAC,iBAAiB,CAAC,OAAO,KAAK,OAAO,CAC7D,CAAC;gBACF,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;oBAClC,kBAAkB,CAAC,IAAI,CAAC;wBACtB,OAAO;wBACP,QAAQ,EAAE,OAAO,CAAC,WAAW,EAAE;wBAC/B,MAAM,EAAE,CAAC,KAAK,CAAC;qBAChB,CAAC,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACN,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACrC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,MAAM,iBAAiB,IAAI,kBAAkB,EAAE,CAAC;QACnD,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACrC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,kBAAkB,CAAC;AAC5B,CAAC"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { Signal } from '@preact/signals-core';
|
|
2
2
|
import type { AxeResults } from 'axe-core';
|
|
3
3
|
import type { ExtendedElementWithIssues, ScanContext } from '../types.ts';
|
|
4
|
-
export declare function updateElementsWithIssues({ extendedElementsWithIssues,
|
|
4
|
+
export declare function updateElementsWithIssues({ extendedElementsWithIssues, limitedContext, limitedContextViolations, fullContextViolations, name, }: {
|
|
5
5
|
extendedElementsWithIssues: Signal<Array<ExtendedElementWithIssues>>;
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
limitedContext: ScanContext;
|
|
7
|
+
limitedContextViolations: AxeResults['violations'];
|
|
8
|
+
fullContextViolations: AxeResults['violations'];
|
|
8
9
|
name: string;
|
|
9
10
|
}): void;
|
|
10
11
|
//# sourceMappingURL=update-elements-with-issues.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-elements-with-issues.d.ts","sourceRoot":"","sources":["../../src/utils/update-elements-with-issues.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"update-elements-with-issues.d.ts","sourceRoot":"","sources":["../../src/utils/update-elements-with-issues.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,KAAK,EAGV,yBAAyB,EAEzB,WAAW,EACZ,MAAM,aAAa,CAAC;AA+BrB,wBAAgB,wBAAwB,CAAC,EACvC,0BAA0B,EAC1B,cAAc,EACd,wBAAwB,EACxB,qBAAqB,EACrB,IAAI,GACL,EAAE;IACD,0BAA0B,EAAE,MAAM,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC,CAAC;IACrE,cAAc,EAAE,WAAW,CAAC;IAC5B,wBAAwB,EAAE,UAAU,CAAC,YAAY,CAAC,CAAC;IACnD,qBAAqB,EAAE,UAAU,CAAC,YAAY,CAAC,CAAC;IAChD,IAAI,EAAE,MAAM,CAAC;CACd,QAuDA"}
|
|
@@ -1,93 +1,49 @@
|
|
|
1
|
-
import { batch
|
|
1
|
+
import { batch } from '@preact/signals-core';
|
|
2
|
+
import { descendantDependentRules } from '../constants.js';
|
|
2
3
|
import { areElementsWithIssuesEqual } from './are-elements-with-issues-equal.js';
|
|
3
4
|
import { areIssueSetsEqual } from './are-issue-sets-equal.js';
|
|
4
|
-
import {
|
|
5
|
-
import { getElementPosition } from './get-element-position.js';
|
|
6
|
-
import { getParent } from './get-parent.js';
|
|
7
|
-
import { getScrollableAncestors } from './get-scrollable-ancestors.js';
|
|
5
|
+
import { createExtendedElementWithIssues } from './create-extended-element-with-issues.js';
|
|
8
6
|
import { isNodeInScanContext } from './is-node-in-scan-context.js';
|
|
9
|
-
import { supportsAnchorPositioning } from './supports-anchor-positioning.js';
|
|
10
7
|
import { transformViolations } from './transform-violations.js';
|
|
11
|
-
function
|
|
12
|
-
|
|
13
|
-
// https://github.com/pomerantsev/accented/issues/62
|
|
14
|
-
const parent = getParent(element);
|
|
15
|
-
const isInsideSvg = Boolean(parent && isSvgElement(parent));
|
|
16
|
-
// Some issues, such as meta-viewport, are on <head> descendants,
|
|
17
|
-
// but since <head> is never rendered, we don't want to output anything
|
|
18
|
-
// for those in the DOM.
|
|
19
|
-
// We're not anticipating the use of shadow DOM in <head>,
|
|
20
|
-
// so the use of .closest() should be fine.
|
|
21
|
-
const isInsideHead = element.closest('head') !== null;
|
|
22
|
-
return isInsideSvg || isInsideHead;
|
|
8
|
+
function getIssuesForElement(element, list) {
|
|
9
|
+
return list.find((entry) => areElementsWithIssuesEqual(entry, element))?.issues ?? [];
|
|
23
10
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
11
|
+
function mergeLimitedContextAndFullContextViolations(elementsFromLimitedContext, elementsFromFullContext) {
|
|
12
|
+
const fromLimitedWithFullIssuesMerged = elementsFromLimitedContext.map((limited) => {
|
|
13
|
+
const fullMatch = elementsFromFullContext.find((full) => areElementsWithIssuesEqual(full, limited));
|
|
14
|
+
return fullMatch ? { ...limited, issues: [...limited.issues, ...fullMatch.issues] } : limited;
|
|
15
|
+
});
|
|
16
|
+
const onlyInFullContext = elementsFromFullContext.filter((full) => !elementsFromLimitedContext.some((limited) => areElementsWithIssuesEqual(limited, full)));
|
|
17
|
+
return [...fromLimitedWithFullIssuesMerged, ...onlyInFullContext];
|
|
18
|
+
}
|
|
19
|
+
export function updateElementsWithIssues({ extendedElementsWithIssues, limitedContext, limitedContextViolations, fullContextViolations, name, }) {
|
|
20
|
+
const updatedElementsFromLimitedContext = transformViolations(limitedContextViolations, name);
|
|
21
|
+
const updatedElementsFromFullContext = transformViolations(fullContextViolations, name);
|
|
22
|
+
const allUpdatedElements = mergeLimitedContextAndFullContextViolations(updatedElementsFromLimitedContext, updatedElementsFromFullContext);
|
|
27
23
|
batch(() => {
|
|
28
|
-
for (const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
24
|
+
for (const existing of extendedElementsWithIssues.value) {
|
|
25
|
+
// If the element is inside the limited context, axe just rescanned
|
|
26
|
+
// it — replace its issues with whatever was reported. If it's outside, keep its
|
|
27
|
+
// existing issues, except descendant-dependent ones, which may have changed due
|
|
28
|
+
// to mutations elsewhere; those get repopulated from the full-context scan below.
|
|
29
|
+
const newLimitedContextIssues = isNodeInScanContext(existing.element, limitedContext)
|
|
30
|
+
? getIssuesForElement(existing, updatedElementsFromLimitedContext)
|
|
31
|
+
: existing.issues.value.filter((issue) => !descendantDependentRules.has(issue.id));
|
|
32
|
+
const newFullContextIssues = getIssuesForElement(existing, updatedElementsFromFullContext);
|
|
33
|
+
const newIssues = [...newLimitedContextIssues, ...newFullContextIssues];
|
|
34
|
+
if (!areIssueSetsEqual(existing.issues.value, newIssues)) {
|
|
35
|
+
existing.issues.value = newIssues;
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
|
-
const addedElementsWithIssues =
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
// Only
|
|
41
|
-
//
|
|
42
|
-
// 2. It is within the scan context, but not among updatedElementsWithIssues.
|
|
43
|
-
const removedElementsWithIssues = extendedElementsWithIssues.value.filter((extendedElementWithIssues) => {
|
|
44
|
-
const isConnected = extendedElementWithIssues.element.isConnected;
|
|
45
|
-
const hasNoMoreIssues = isNodeInScanContext(extendedElementWithIssues.element, scanContext) &&
|
|
46
|
-
!updatedElementsWithIssues.some((updatedElementWithIssues) => areElementsWithIssuesEqual(updatedElementWithIssues, extendedElementWithIssues));
|
|
47
|
-
return !isConnected || hasNoMoreIssues;
|
|
48
|
-
});
|
|
38
|
+
const addedElementsWithIssues = allUpdatedElements.filter((updated) => updated.element.isConnected &&
|
|
39
|
+
!extendedElementsWithIssues.value.some((existing) => areElementsWithIssuesEqual(existing, updated)));
|
|
40
|
+
const removedElementsWithIssues = extendedElementsWithIssues.value.filter((existing) => !existing.element.isConnected || existing.issues.value.length === 0);
|
|
41
|
+
// Only rebuild the outer signal when set membership changes; per-element issue
|
|
42
|
+
// updates were already made in the loop above.
|
|
49
43
|
if (addedElementsWithIssues.length > 0 || removedElementsWithIssues.length > 0) {
|
|
50
44
|
extendedElementsWithIssues.value = [...extendedElementsWithIssues.value]
|
|
51
|
-
.filter((
|
|
52
|
-
|
|
53
|
-
})
|
|
54
|
-
.concat(addedElementsWithIssues
|
|
55
|
-
.filter((addedElementWithIssues) => addedElementWithIssues.element.isConnected)
|
|
56
|
-
.map((addedElementWithIssues) => {
|
|
57
|
-
const id = count++;
|
|
58
|
-
const trigger = document.createElement(`${name}-trigger`);
|
|
59
|
-
const elementZIndex = Number.parseInt(getComputedStyle(addedElementWithIssues.element).zIndex, 10);
|
|
60
|
-
if (!Number.isNaN(elementZIndex)) {
|
|
61
|
-
trigger.style.setProperty('z-index', (elementZIndex + 1).toString(), 'important');
|
|
62
|
-
}
|
|
63
|
-
trigger.style.setProperty('position-anchor', `--${name}-anchor-${id}`, 'important');
|
|
64
|
-
trigger.dataset.id = id.toString();
|
|
65
|
-
const accentedDialog = document.createElement(`${name}-dialog`);
|
|
66
|
-
trigger.dialog = accentedDialog;
|
|
67
|
-
const position = getElementPosition(addedElementWithIssues.element);
|
|
68
|
-
trigger.position = signal(position);
|
|
69
|
-
trigger.visible = signal(true);
|
|
70
|
-
trigger.element = addedElementWithIssues.element;
|
|
71
|
-
const scrollableAncestors = supportsAnchorPositioning()
|
|
72
|
-
? new Set()
|
|
73
|
-
: getScrollableAncestors(addedElementWithIssues.element);
|
|
74
|
-
const issues = signal(addedElementWithIssues.issues);
|
|
75
|
-
accentedDialog.issues = issues;
|
|
76
|
-
accentedDialog.element = addedElementWithIssues.element;
|
|
77
|
-
return {
|
|
78
|
-
id,
|
|
79
|
-
element: addedElementWithIssues.element,
|
|
80
|
-
skipRender: shouldSkipRender(addedElementWithIssues.element),
|
|
81
|
-
rootNode: addedElementWithIssues.rootNode,
|
|
82
|
-
visible: trigger.visible,
|
|
83
|
-
position: trigger.position,
|
|
84
|
-
scrollableAncestors: signal(scrollableAncestors),
|
|
85
|
-
anchorNameValue: addedElementWithIssues.element.style.getPropertyValue('anchor-name') ||
|
|
86
|
-
getComputedStyle(addedElementWithIssues.element).getPropertyValue('anchor-name'),
|
|
87
|
-
trigger,
|
|
88
|
-
issues,
|
|
89
|
-
};
|
|
90
|
-
}));
|
|
45
|
+
.filter((existing) => !removedElementsWithIssues.some((removed) => areElementsWithIssuesEqual(removed, existing)))
|
|
46
|
+
.concat(addedElementsWithIssues.map((added) => createExtendedElementWithIssues(added, name)));
|
|
91
47
|
}
|
|
92
48
|
});
|
|
93
49
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-elements-with-issues.js","sourceRoot":"","sources":["../../src/utils/update-elements-with-issues.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"update-elements-with-issues.js","sourceRoot":"","sources":["../../src/utils/update-elements-with-issues.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "accented",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "A frontend library for continuous accessibility testing and issue highlighting",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/accented.js",
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
},
|
|
28
28
|
"homepage": "https://accented.dev",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@preact/signals-core": "^1.14.
|
|
31
|
-
"axe-core": "^4.11.
|
|
30
|
+
"@preact/signals-core": "^1.14.1",
|
|
31
|
+
"axe-core": "^4.11.3"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@types/jsdom": "^
|
|
35
|
-
"jsdom": "^29.0.
|
|
34
|
+
"@types/jsdom": "^28.0.1",
|
|
35
|
+
"jsdom": "^29.0.2"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"build": "pnpm copyCommon && tsc",
|
package/src/constants.ts
CHANGED
|
@@ -5,3 +5,37 @@ export const issuesUrl = 'https://github.com/pomerantsev/accented/issues';
|
|
|
5
5
|
export const getAccentedElementNames = (name: string) => [`${name}-trigger`, `${name}-dialog`];
|
|
6
6
|
|
|
7
7
|
export const orderedImpacts: Array<Issue['impact']> = ['minor', 'moderate', 'serious', 'critical'];
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* axe-core rules whose pass/fail depends on the presence or absence of specific descendants
|
|
11
|
+
* (not just direct children). When any DOM mutation occurs, these rules must be re-evaluated
|
|
12
|
+
* against the full scan context, because the mutated node may be deep inside the element
|
|
13
|
+
* that the violation is reported on — and therefore outside the limited scan context.
|
|
14
|
+
*/
|
|
15
|
+
export const descendantDependentRules = new Set([
|
|
16
|
+
'aria-hidden-focus',
|
|
17
|
+
'aria-required-children',
|
|
18
|
+
'aria-text',
|
|
19
|
+
'document-title',
|
|
20
|
+
'landmark-no-duplicate-banner',
|
|
21
|
+
'landmark-no-duplicate-contentinfo',
|
|
22
|
+
'landmark-no-duplicate-main',
|
|
23
|
+
'landmark-one-main',
|
|
24
|
+
'nested-interactive',
|
|
25
|
+
'page-has-heading-one',
|
|
26
|
+
'scrollable-region-focusable',
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* axe-core violations (their ids) that may be flagged by axe-core
|
|
31
|
+
* as false positives if an Accented trigger is a descendant of the element with the issue.
|
|
32
|
+
*/
|
|
33
|
+
export const violationsAffectedByAccentedTriggers = new Set([
|
|
34
|
+
'aria-hidden-focus',
|
|
35
|
+
'aria-text',
|
|
36
|
+
'definition-list',
|
|
37
|
+
'label-content-name-mismatch',
|
|
38
|
+
'list',
|
|
39
|
+
'nested-interactive',
|
|
40
|
+
'scrollable-region-focusable', // The Accented trigger might make the content grow such that scrolling is required.
|
|
41
|
+
]);
|
|
@@ -25,7 +25,7 @@ export interface AccentedDialog extends HTMLElement {
|
|
|
25
25
|
|
|
26
26
|
// We want Accented to not throw an error in Node, and use static imports,
|
|
27
27
|
// so we can't export `class extends HTMLElement` because HTMLElement is not available in Node.
|
|
28
|
-
export const getAccentedDialog = () => {
|
|
28
|
+
export const getAccentedDialog = (): CustomElementConstructor => {
|
|
29
29
|
const dialogTemplate = document.createElement('template');
|
|
30
30
|
dialogTemplate.innerHTML = `
|
|
31
31
|
<dialog dir="ltr" lang="en" aria-labelledby="title" closedby="any">
|
|
@@ -16,7 +16,7 @@ export interface AccentedTrigger extends HTMLElement {
|
|
|
16
16
|
|
|
17
17
|
// We want Accented to not throw an error in Node, and use static imports,
|
|
18
18
|
// so we can't export `class extends HTMLElement` because HTMLElement is not available in Node.
|
|
19
|
-
export const getAccentedTrigger = (name: string) => {
|
|
19
|
+
export const getAccentedTrigger = (name: string): CustomElementConstructor => {
|
|
20
20
|
const template = document.createElement('template');
|
|
21
21
|
|
|
22
22
|
// I initially tried creating a CSSStyelSheet object with styles instead of having a <style> element in the template,
|
package/src/logger.ts
CHANGED