mnfst 0.5.88 → 0.5.89
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/lib/manifest.code.js +49 -30
- package/lib/manifest.integrity.json +1 -1
- package/package.json +1 -1
package/lib/manifest.code.js
CHANGED
|
@@ -587,18 +587,26 @@ const GROUP_INHERITABLE_ATTRS = ['lines', 'edit', 'collapse'];
|
|
|
587
587
|
async function setupCodeGroup(group) {
|
|
588
588
|
if (group.dataset.groupProcessed === 'yes') return;
|
|
589
589
|
|
|
590
|
+
// A "panel" is any direct child with a [name] — these are tab panels.
|
|
591
|
+
// Children without [name] are ambient (always visible alongside whichever
|
|
592
|
+
// panel is active). When nothing is named, the group has no tabs at all
|
|
593
|
+
// and renders as a borderless wrapper around its (always-visible) kids —
|
|
594
|
+
// a frame + code pair, for instance, with no title overhead.
|
|
590
595
|
const sourcePanels = Array.from(group.children).filter(c => c.hasAttribute('name'));
|
|
591
|
-
|
|
596
|
+
const ambientChildren = Array.from(group.children).filter(c => !c.hasAttribute('name'));
|
|
597
|
+
if (sourcePanels.length === 0 && ambientChildren.length === 0) return;
|
|
592
598
|
// Claim the group synchronously so re-entrant callers (the directive +
|
|
593
599
|
// observer can both arrive before the first call's `await` resolves)
|
|
594
600
|
// bail out — otherwise the wrapper accumulates duplicate tab strips.
|
|
595
601
|
group.dataset.groupProcessed = 'yes';
|
|
596
602
|
|
|
597
|
-
// Inherit feature attributes from wrapper to child <pre x-code>
|
|
598
|
-
// that don't set them.
|
|
603
|
+
// Inherit feature attributes from wrapper to child <pre x-code> elements
|
|
604
|
+
// that don't set them. Ambient (unnamed) pres inherit too, so a frame +
|
|
605
|
+
// code pair in an unnamed group still benefits from group-level [lines]
|
|
606
|
+
// / [edit] / [collapse]. Run BEFORE setupBlock so the inherited attrs
|
|
599
607
|
// drive that block's setup.
|
|
600
|
-
|
|
601
|
-
|
|
608
|
+
const allCodeChildren = [...sourcePanels, ...ambientChildren].filter(c => c.tagName === 'PRE');
|
|
609
|
+
for (const panel of allCodeChildren) {
|
|
602
610
|
for (const attr of GROUP_INHERITABLE_ATTRS) {
|
|
603
611
|
if (group.hasAttribute(attr) && !panel.hasAttribute(attr)) {
|
|
604
612
|
panel.setAttribute(attr, group.getAttribute(attr));
|
|
@@ -617,10 +625,11 @@ async function setupCodeGroup(group) {
|
|
|
617
625
|
const active = tabNames[0];
|
|
618
626
|
const slugify = s => s.replace(/\s+/g, '-').toLowerCase();
|
|
619
627
|
|
|
620
|
-
// Preload hljs + every language needed across the group
|
|
621
|
-
// setupBlock can synchronously highlight
|
|
622
|
-
|
|
623
|
-
|
|
628
|
+
// Preload hljs + every language needed across the group (named panels +
|
|
629
|
+
// ambient pres) so each block's setupBlock can synchronously highlight
|
|
630
|
+
// without re-loading.
|
|
631
|
+
const codeLangs = allCodeChildren
|
|
632
|
+
.filter(p => p.hasAttribute('x-code'))
|
|
624
633
|
.map(p => p.getAttribute('x-code'))
|
|
625
634
|
.filter(Boolean);
|
|
626
635
|
let hljs = null;
|
|
@@ -647,34 +656,36 @@ async function setupCodeGroup(group) {
|
|
|
647
656
|
pre.dataset.groupProcessed = 'yes';
|
|
648
657
|
if (!pre.hasAttribute('role')) pre.setAttribute('role', 'region');
|
|
649
658
|
|
|
650
|
-
// Run each code
|
|
651
|
-
// treatment (line numbers, copy button, collapse,
|
|
652
|
-
// as-is. setupBlock detects [x-code-group]
|
|
653
|
-
// per-panel title bar — the
|
|
654
|
-
|
|
655
|
-
|
|
659
|
+
// Run each code child (named or ambient) through setupBlock so it gets
|
|
660
|
+
// its full feature treatment (line numbers, copy button, collapse,
|
|
661
|
+
// editor). Frames stay as-is. setupBlock detects the [x-code-group]
|
|
662
|
+
// ancestor and suppresses the per-panel title bar — the group header
|
|
663
|
+
// (when present) serves that role; for headerless groups, the pre is
|
|
664
|
+
// simply rendered without its own title.
|
|
665
|
+
for (const panel of allCodeChildren) {
|
|
666
|
+
if (panel.hasAttribute('x-code')) {
|
|
656
667
|
await setupBlock(panel, hljs);
|
|
657
668
|
panel.dataset.codeProcessed = 'yes';
|
|
658
669
|
}
|
|
659
670
|
}
|
|
660
671
|
|
|
661
672
|
// Header: tab strip when there are multiple named panels, plain title bar
|
|
662
|
-
// when there's just one
|
|
663
|
-
//
|
|
664
|
-
//
|
|
665
|
-
//
|
|
666
|
-
// wrapper so the wrapper-level copy button and grouped frame siblings still
|
|
667
|
-
// work uniformly.
|
|
668
|
-
const header = document.createElement('header');
|
|
673
|
+
// when there's just one, no header at all when nothing is named. Skipping
|
|
674
|
+
// the header for headerless groups lets authors pair a frame + code block
|
|
675
|
+
// inside <div x-code-group> with no repetitive "HTML" title — both render
|
|
676
|
+
// as ambient siblings inside the wrapper.
|
|
669
677
|
const isSingleTab = tabNames.length === 1;
|
|
678
|
+
const isHeaderless = tabNames.length === 0;
|
|
679
|
+
let header = null;
|
|
670
680
|
let tablist = null;
|
|
671
681
|
let tabButtons = [];
|
|
682
|
+
if (!isHeaderless) header = document.createElement('header');
|
|
672
683
|
if (isSingleTab) {
|
|
673
684
|
const titleEl = document.createElement('div');
|
|
674
685
|
titleEl.textContent = active;
|
|
675
686
|
header.appendChild(titleEl);
|
|
676
687
|
if (!pre.hasAttribute('aria-label')) pre.setAttribute('aria-label', active);
|
|
677
|
-
} else {
|
|
688
|
+
} else if (!isHeaderless) {
|
|
678
689
|
// The role=tablist sits on an inner <div> that holds the tab buttons.
|
|
679
690
|
// That way the tablist can have its own overflow-x scrolling (when
|
|
680
691
|
// there are too many tabs to fit) without dragging sibling header
|
|
@@ -714,12 +725,13 @@ async function setupCodeGroup(group) {
|
|
|
714
725
|
});
|
|
715
726
|
});
|
|
716
727
|
}
|
|
717
|
-
pre.insertBefore(header, pre.firstChild);
|
|
728
|
+
if (header) pre.insertBefore(header, pre.firstChild);
|
|
718
729
|
|
|
719
730
|
// Wire ARIA / IDs on each panel. Multi-tab groups get role="tabpanel" with
|
|
720
731
|
// aria-labelledby pointing at its tab button; single-tab groups keep the
|
|
721
732
|
// standalone role="region" + aria-label shape (label set on the wrapper
|
|
722
|
-
// above) so there's no orphan tabpanel without a tablist.
|
|
733
|
+
// above) so there's no orphan tabpanel without a tablist. Headerless
|
|
734
|
+
// groups have no tabpanels — every child is ambient.
|
|
723
735
|
sourcePanels.forEach((panel, i) => {
|
|
724
736
|
const name = panel.getAttribute('name');
|
|
725
737
|
panel.id = panel.id || `${slugify(name)}-panel-${i}`;
|
|
@@ -743,7 +755,7 @@ async function setupCodeGroup(group) {
|
|
|
743
755
|
// competing with the header's own overflow-scroll region. Same
|
|
744
756
|
// positioning rule as for a standalone <pre x-code copy>.
|
|
745
757
|
const wrapperHasCopy = pre.hasAttribute('copy');
|
|
746
|
-
const anyPanelCopy = sourcePanels.some(p => p.hasAttribute('copy'));
|
|
758
|
+
const anyPanelCopy = [...sourcePanels, ...ambientChildren].some(p => p.hasAttribute('copy'));
|
|
747
759
|
let copyBtn = null;
|
|
748
760
|
if (wrapperHasCopy || anyPanelCopy) {
|
|
749
761
|
copyBtn = document.createElement('button');
|
|
@@ -754,9 +766,15 @@ async function setupCodeGroup(group) {
|
|
|
754
766
|
// When multiple panels share the active name (e.g. a paired
|
|
755
767
|
// frame + code), prefer the <pre x-code> for copy — the source
|
|
756
768
|
// is what an author wants to take, not the rendered frame's
|
|
757
|
-
// text content.
|
|
758
|
-
|
|
759
|
-
|
|
769
|
+
// text content. Headerless groups have no active name, so pick
|
|
770
|
+
// the first ambient <pre x-code> child instead.
|
|
771
|
+
let activePanel;
|
|
772
|
+
if (isHeaderless) {
|
|
773
|
+
activePanel = ambientChildren.find(p => p.tagName === 'PRE' && p.hasAttribute('x-code'));
|
|
774
|
+
} else {
|
|
775
|
+
const sameName = sourcePanels.filter(p => p.getAttribute('name') === activeName);
|
|
776
|
+
activePanel = sameName.find(p => p.tagName === 'PRE' && p.hasAttribute('x-code')) || sameName[0];
|
|
777
|
+
}
|
|
760
778
|
if (!activePanel) return;
|
|
761
779
|
const code = activePanel.querySelector(':scope > code') || activePanel;
|
|
762
780
|
try {
|
|
@@ -774,6 +792,7 @@ async function setupCodeGroup(group) {
|
|
|
774
792
|
// visibility per-tab: when [copy] sits on the wrapper it stays visible
|
|
775
793
|
// for every tab; when it sits only on individual panels, the button
|
|
776
794
|
// shows for tabs whose panels carry [copy] and hides for the rest.
|
|
795
|
+
// Headerless groups have no tabs to switch, so activate() is a no-op.
|
|
777
796
|
let activeName = active;
|
|
778
797
|
function activate(name) {
|
|
779
798
|
activeName = name;
|
|
@@ -792,7 +811,7 @@ async function setupCodeGroup(group) {
|
|
|
792
811
|
copyBtn.style.display = activeCanCopy ? '' : 'none';
|
|
793
812
|
}
|
|
794
813
|
}
|
|
795
|
-
activate(active);
|
|
814
|
+
if (!isHeaderless) activate(active);
|
|
796
815
|
}
|
|
797
816
|
|
|
798
817
|
// ─── Page scan + observation ─────────────────────────────────────────────────
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"manifest.appwrite.auth.js": "sha384-to37ssZJXGeOS6+rf2VI47ox2mEqgsi5oQ1E5vv8XU/lDspbDFE1KHEMm8TxBhxW",
|
|
3
3
|
"manifest.appwrite.data.js": "sha384-00ulLT+GAIuPHA/rRT9p98vYlsyDzkyKXtg86BDQ6FGQa5vVVN+W6kuforniBAsz",
|
|
4
4
|
"manifest.appwrite.presence.js": "sha384-uxRpx9/Jj0kGtklH5QmUlAzD3zdSvFRfK6bcJQqxl+Bsf5tOo4zgwqJTQgtZoHQP",
|
|
5
|
-
"manifest.code.js": "sha384-
|
|
5
|
+
"manifest.code.js": "sha384-r0cbKtg4/bih6lzNiIdnwiCurW2ohbC8E8zNljSSoO5r+5ewPQcWP4QT+jZp3Oec",
|
|
6
6
|
"manifest.color.js": "sha384-Z9G/lzt0vVMxjz4wkPuGG1X9mmQAJR15aOoGX3ephf7r2wnlUWet5GLgkUMtT4vt",
|
|
7
7
|
"manifest.colorpicker.js": "sha384-0EVn+Ha06h7FIvOxc6WjZYnKYXzi+zba08yKvczSEGTRkWRxyKN2TFrZHI1SDCXu",
|
|
8
8
|
"manifest.components.js": "sha384-3dCTD5EwCZTiX+1obYtDNM3WWwPh2JDQUQQsdRUUK3gs6FXjse1ShkKaT/2jsNaI",
|