@abreen/tada 1.14.1 → 1.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/utils/trace-core.ts +12 -2
- package/build/utils/trace-svg.ts +14 -6
- package/package.json +1 -1
- package/src/question/index.ts +13 -1
- package/src/slides/index.ts +1 -1
|
@@ -42,6 +42,10 @@ function hashTraceFiles(files: { name: string; content: string }[]): string {
|
|
|
42
42
|
return `sha256-${hasher.digest('hex').slice(0, 16)}`;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
function safeSvgIdPart(value: string): string {
|
|
46
|
+
return value.replace(/[^A-Za-z0-9_-]+/g, '-').replace(/^-+|-+$/g, '');
|
|
47
|
+
}
|
|
48
|
+
|
|
45
49
|
function buildTraceOutputPath(
|
|
46
50
|
relDir: string,
|
|
47
51
|
traceName: string,
|
|
@@ -181,13 +185,19 @@ export function chunkTraceOutput(
|
|
|
181
185
|
|
|
182
186
|
const layoutSteps = allSteps.map(step => ({ ...step, ...filterStep(step) }));
|
|
183
187
|
const layout = computeLayout(layoutSteps, ignoreFields);
|
|
188
|
+
const svgIdPrefix = safeSvgIdPart(traceName) || 'trace';
|
|
184
189
|
|
|
185
190
|
let chunkEntries: TraceChunkEntry[] = [];
|
|
186
191
|
let chunkIndex = 0;
|
|
187
192
|
const chunkFiles: { name: string; content: string }[] = [];
|
|
188
193
|
|
|
189
|
-
for (const step of allSteps) {
|
|
190
|
-
const svg = generateStepSvg(
|
|
194
|
+
for (const [stepIndex, step] of allSteps.entries()) {
|
|
195
|
+
const svg = generateStepSvg(
|
|
196
|
+
step,
|
|
197
|
+
layout,
|
|
198
|
+
undefined,
|
|
199
|
+
`trace-${svgIdPrefix}-${stepIndex}`,
|
|
200
|
+
);
|
|
191
201
|
chunkEntries.push({
|
|
192
202
|
file: path.basename(step.file),
|
|
193
203
|
line: step.line,
|
package/build/utils/trace-svg.ts
CHANGED
|
@@ -545,6 +545,7 @@ function generateArrows(
|
|
|
545
545
|
stackLayouts: FrameLayout[],
|
|
546
546
|
heapObjMap: Map<string, HeapObjInfo>,
|
|
547
547
|
dims: { rowH: number; fontSize: number },
|
|
548
|
+
markerIds: { arrowhead: string; arrowheadDim: string },
|
|
548
549
|
): string[] {
|
|
549
550
|
const parts: string[] = [];
|
|
550
551
|
|
|
@@ -558,7 +559,8 @@ function generateArrows(
|
|
|
558
559
|
const ep = heapTargetBoundaryPoint(sx, sy, target, heap[target.id], dims);
|
|
559
560
|
const cpx = Math.round((sx + ep.x) / 2);
|
|
560
561
|
const cls = style === 'fg' ? 'trace-arrow' : 'trace-arrow-dim';
|
|
561
|
-
const marker =
|
|
562
|
+
const marker =
|
|
563
|
+
style === 'fg' ? markerIds.arrowhead : markerIds.arrowheadDim;
|
|
562
564
|
return (
|
|
563
565
|
`<path class="${cls}" d="` +
|
|
564
566
|
`M ${sx} ${sy} Q ${cpx} ${sy}, ${ep.x} ${ep.y}" ` +
|
|
@@ -577,7 +579,7 @@ function generateArrows(
|
|
|
577
579
|
if (Math.abs(tx - sx) < 4) {
|
|
578
580
|
return (
|
|
579
581
|
`<path class="trace-arrow-heap" d="M ${sx} ${sy} L ${tx} ${ty}" ` +
|
|
580
|
-
`marker-end="url(
|
|
582
|
+
`marker-end="url(#${markerIds.arrowheadDim})"/>`
|
|
581
583
|
);
|
|
582
584
|
}
|
|
583
585
|
|
|
@@ -600,7 +602,7 @@ function generateArrows(
|
|
|
600
602
|
|
|
601
603
|
return (
|
|
602
604
|
`<path class="trace-arrow-heap" d="${path}" ` +
|
|
603
|
-
`marker-end="url(
|
|
605
|
+
`marker-end="url(#${markerIds.arrowheadDim})"/>`
|
|
604
606
|
);
|
|
605
607
|
}
|
|
606
608
|
|
|
@@ -644,7 +646,7 @@ function generateArrows(
|
|
|
644
646
|
`<path class="trace-arrow-heap" d="` +
|
|
645
647
|
`M ${sx} ${sy} C ${Math.round(cp1x)} ${Math.round(cp1y)}, ` +
|
|
646
648
|
`${Math.round(cp2x)} ${Math.round(cp2y)}, ${ep.x} ${ep.y}" ` +
|
|
647
|
-
`marker-end="url(
|
|
649
|
+
`marker-end="url(#${markerIds.arrowheadDim})"/>`
|
|
648
650
|
);
|
|
649
651
|
}
|
|
650
652
|
|
|
@@ -772,6 +774,7 @@ export function generateStepSvg(
|
|
|
772
774
|
step: TraceStep,
|
|
773
775
|
layout: TraceLayout,
|
|
774
776
|
fontSize: number = DEFAULT_FONT_SIZE,
|
|
777
|
+
markerIdPrefix = 'trace',
|
|
775
778
|
): string {
|
|
776
779
|
const { stack, heap } = filterStep(step);
|
|
777
780
|
|
|
@@ -836,6 +839,10 @@ export function generateStepSvg(
|
|
|
836
839
|
|
|
837
840
|
// Build SVG
|
|
838
841
|
const parts: string[] = [];
|
|
842
|
+
const markerIds = {
|
|
843
|
+
arrowhead: `${markerIdPrefix}-arrowhead`,
|
|
844
|
+
arrowheadDim: `${markerIdPrefix}-arrowhead-dim`,
|
|
845
|
+
};
|
|
839
846
|
parts.push(
|
|
840
847
|
`<svg class="trace-memory" viewBox="0 0 ${totalWidth} ${totalHeight}" ` +
|
|
841
848
|
`width="${totalWidth}" height="${totalHeight}" ` +
|
|
@@ -845,13 +852,13 @@ export function generateStepSvg(
|
|
|
845
852
|
// Defs: arrowhead markers
|
|
846
853
|
parts.push('<defs>');
|
|
847
854
|
parts.push(
|
|
848
|
-
|
|
855
|
+
`<marker id="${markerIds.arrowhead}" markerWidth="8" markerHeight="6" ` +
|
|
849
856
|
'refX="8" refY="3" orient="auto" markerUnits="strokeWidth">',
|
|
850
857
|
);
|
|
851
858
|
parts.push('<polygon class="trace-arrowhead" points="0 0, 8 3, 0 6"/>');
|
|
852
859
|
parts.push('</marker>');
|
|
853
860
|
parts.push(
|
|
854
|
-
|
|
861
|
+
`<marker id="${markerIds.arrowheadDim}" markerWidth="8" markerHeight="6" ` +
|
|
855
862
|
'refX="8" refY="3" orient="auto" markerUnits="strokeWidth">',
|
|
856
863
|
);
|
|
857
864
|
parts.push('<polygon class="trace-arrowhead-dim" points="0 0, 8 3, 0 6"/>');
|
|
@@ -884,6 +891,7 @@ export function generateStepSvg(
|
|
|
884
891
|
stackLayouts,
|
|
885
892
|
heapObjMap,
|
|
886
893
|
dims,
|
|
894
|
+
markerIds,
|
|
887
895
|
);
|
|
888
896
|
for (const arrow of arrowParts) {
|
|
889
897
|
parts.push(arrow);
|
package/package.json
CHANGED
package/src/question/index.ts
CHANGED
|
@@ -13,10 +13,22 @@ export default (window: Window) => {
|
|
|
13
13
|
el.removeAttribute('aria-label');
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
el.addEventListener('click',
|
|
16
|
+
el.addEventListener('click', (e: MouseEvent) => {
|
|
17
|
+
if (el.hasAttribute('data-revealed')) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
e.stopPropagation();
|
|
22
|
+
reveal();
|
|
23
|
+
});
|
|
17
24
|
el.addEventListener('keydown', (e: KeyboardEvent) => {
|
|
25
|
+
if (el.hasAttribute('data-revealed')) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
18
29
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
19
30
|
e.preventDefault();
|
|
31
|
+
e.stopPropagation();
|
|
20
32
|
reveal();
|
|
21
33
|
}
|
|
22
34
|
});
|
package/src/slides/index.ts
CHANGED
|
@@ -23,7 +23,7 @@ function isInteractive(
|
|
|
23
23
|
target instanceof view.Element ? target : target.parentElement;
|
|
24
24
|
return Boolean(
|
|
25
25
|
element?.closest(
|
|
26
|
-
'a, button, input, select, textarea, summary, label, [role="button"], [contenteditable=""], [contenteditable="true"]
|
|
26
|
+
'a, button, input, select, textarea, summary, label, [role="button"], [contenteditable=""], [contenteditable="true"]',
|
|
27
27
|
),
|
|
28
28
|
);
|
|
29
29
|
}
|