@launchsecure/launch-kit 0.0.24 → 0.0.26
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/README.md +50 -0
- package/dist/beacon/beacon.mjs +1016 -0
- package/dist/beacon/beacon.mjs.map +1 -0
- package/dist/beacon/beacon.umd.js +87 -0
- package/dist/beacon/beacon.umd.js.map +1 -0
- package/dist/beacon/index-DAIDnjfR.mjs +513 -0
- package/dist/beacon/index-DAIDnjfR.mjs.map +1 -0
- package/dist/beacon/types/capture/element.d.ts +3 -0
- package/dist/beacon/types/capture/element.d.ts.map +1 -0
- package/dist/beacon/types/capture/framework.d.ts +3 -0
- package/dist/beacon/types/capture/framework.d.ts.map +1 -0
- package/dist/beacon/types/capture/metadata.d.ts +3 -0
- package/dist/beacon/types/capture/metadata.d.ts.map +1 -0
- package/dist/beacon/types/capture/overlay.d.ts +7 -0
- package/dist/beacon/types/capture/overlay.d.ts.map +1 -0
- package/dist/beacon/types/capture/picker.d.ts +12 -0
- package/dist/beacon/types/capture/picker.d.ts.map +1 -0
- package/dist/beacon/types/capture/screenshot.d.ts +7 -0
- package/dist/beacon/types/capture/screenshot.d.ts.map +1 -0
- package/dist/beacon/types/capture/selector.d.ts +2 -0
- package/dist/beacon/types/capture/selector.d.ts.map +1 -0
- package/dist/beacon/types/element.d.ts +50 -0
- package/dist/beacon/types/element.d.ts.map +1 -0
- package/dist/beacon/types/index.d.ts +4 -0
- package/dist/beacon/types/index.d.ts.map +1 -0
- package/dist/beacon/types/transport/submit.d.ts +3 -0
- package/dist/beacon/types/transport/submit.d.ts.map +1 -0
- package/dist/beacon/types/types.d.ts +88 -0
- package/dist/beacon/types/types.d.ts.map +1 -0
- package/dist/beacon/types/ui/button.d.ts +2 -0
- package/dist/beacon/types/ui/button.d.ts.map +1 -0
- package/dist/beacon/types/ui/drawer.d.ts +31 -0
- package/dist/beacon/types/ui/drawer.d.ts.map +1 -0
- package/dist/beacon/types/ui/icons.d.ts +9 -0
- package/dist/beacon/types/ui/icons.d.ts.map +1 -0
- package/dist/beacon/types/ui/pick-mode-overlay.d.ts +25 -0
- package/dist/beacon/types/ui/pick-mode-overlay.d.ts.map +1 -0
- package/dist/beacon/types/ui/pin-popover.d.ts +14 -0
- package/dist/beacon/types/ui/pin-popover.d.ts.map +1 -0
- package/dist/chart-client/assets/{index-C8ANseEa.js → index-Bk1hawjD.js} +63 -58
- package/dist/chart-client/assets/index-DpaGa3bY.css +1 -0
- package/dist/chart-client/index.html +2 -2
- package/dist/client/assets/index-Bfel4OQ5.css +32 -0
- package/dist/client/assets/{index-Ds9UP_cj.js → index-eC-WuUWB.js} +58 -58
- package/dist/client/index.html +2 -2
- package/dist/council-client/assets/{index-Dc41S-R2.js → index-Cs_MVXHf.js} +14 -14
- package/dist/council-client/assets/index-P5kMsT5a.css +1 -0
- package/dist/council-client/index.html +2 -2
- package/dist/deck-client/assets/{_baseUniq-2gclQXo7.js → _baseUniq-C2xT_eYu.js} +1 -1
- package/dist/deck-client/assets/{arc-DcMY5Wm0.js → arc-CmVL9pGd.js} +1 -1
- package/dist/deck-client/assets/{architectureDiagram-Q4EWVU46-B8iirmmJ.js → architectureDiagram-Q4EWVU46-BSFgdjve.js} +1 -1
- package/dist/deck-client/assets/{blockDiagram-DXYQGD6D-B4JBLjmJ.js → blockDiagram-DXYQGD6D-DuLzscvP.js} +1 -1
- package/dist/deck-client/assets/{c4Diagram-AHTNJAMY-CojrJAk8.js → c4Diagram-AHTNJAMY-CfCJB8eY.js} +1 -1
- package/dist/deck-client/assets/channel-B4aNO8ZB.js +1 -0
- package/dist/deck-client/assets/{chunk-4BX2VUAB-Bmb_BMDo.js → chunk-4BX2VUAB-DxmLYTWZ.js} +1 -1
- package/dist/deck-client/assets/{chunk-4TB4RGXK-CumBy8qe.js → chunk-4TB4RGXK-CCnf7GFE.js} +1 -1
- package/dist/deck-client/assets/{chunk-55IACEB6-Ka8Hb1wD.js → chunk-55IACEB6-Db9DApcj.js} +1 -1
- package/dist/deck-client/assets/{chunk-EDXVE4YY-B3sIPiQo.js → chunk-EDXVE4YY-DmYDq8ZI.js} +1 -1
- package/dist/deck-client/assets/{chunk-FMBD7UC4-C1tYkaqu.js → chunk-FMBD7UC4-BGhUlF20.js} +1 -1
- package/dist/deck-client/assets/{chunk-OYMX7WX6-D7Wacbky.js → chunk-OYMX7WX6-CpEnicQZ.js} +1 -1
- package/dist/deck-client/assets/{chunk-QZHKN3VN-ChXI0vO3.js → chunk-QZHKN3VN-Doa7LKwf.js} +1 -1
- package/dist/deck-client/assets/{chunk-YZCP3GAM-BXhiqf8u.js → chunk-YZCP3GAM-CpkIlH6V.js} +1 -1
- package/dist/deck-client/assets/classDiagram-6PBFFD2Q-BHTI0yWz.js +1 -0
- package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-BHTI0yWz.js +1 -0
- package/dist/deck-client/assets/clone-HduFm7qU.js +1 -0
- package/dist/deck-client/assets/{cose-bilkent-S5V4N54A-Bqp3p68D.js → cose-bilkent-S5V4N54A-Bkh8Bfcb.js} +1 -1
- package/dist/deck-client/assets/{dagre-KV5264BT-BS-rtyhZ.js → dagre-KV5264BT-Bp0XpTgH.js} +1 -1
- package/dist/deck-client/assets/{diagram-5BDNPKRD-BIrj9YGI.js → diagram-5BDNPKRD-ZHiyGYPQ.js} +1 -1
- package/dist/deck-client/assets/{diagram-G4DWMVQ6-noHWPIg4.js → diagram-G4DWMVQ6-BW-Q8_H5.js} +1 -1
- package/dist/deck-client/assets/{diagram-MMDJMWI5-C2qHxvqV.js → diagram-MMDJMWI5-6I3LTafu.js} +1 -1
- package/dist/deck-client/assets/{diagram-TYMM5635-BytnGQr-.js → diagram-TYMM5635-CyM5YK28.js} +1 -1
- package/dist/deck-client/assets/{erDiagram-SMLLAGMA-BfK5m2YQ.js → erDiagram-SMLLAGMA-CjNxVJHk.js} +1 -1
- package/dist/deck-client/assets/{flowDiagram-DWJPFMVM-Cq925G1Z.js → flowDiagram-DWJPFMVM-BDQHuAJR.js} +1 -1
- package/dist/deck-client/assets/{ganttDiagram-T4ZO3ILL-DhhHPAmj.js → ganttDiagram-T4ZO3ILL-B7MnkpbP.js} +1 -1
- package/dist/deck-client/assets/{gitGraphDiagram-UUTBAWPF-B3Lc0h9q.js → gitGraphDiagram-UUTBAWPF-C9dZAcYD.js} +1 -1
- package/dist/deck-client/assets/{graph-RTawgVWm.js → graph-CjdBnzUy.js} +1 -1
- package/dist/deck-client/assets/{index-BfIfJXmS.js → index-DeIVPW63.js} +68 -68
- package/dist/deck-client/assets/index-LKZDAS9S.css +1 -0
- package/dist/deck-client/assets/{infoDiagram-42DDH7IO-BlR584kX.js → infoDiagram-42DDH7IO-C7d3iRC3.js} +1 -1
- package/dist/deck-client/assets/{ishikawaDiagram-UXIWVN3A-DygKoNGY.js → ishikawaDiagram-UXIWVN3A-BcYGKj09.js} +1 -1
- package/dist/deck-client/assets/{journeyDiagram-VCZTEJTY-BnaiYp9N.js → journeyDiagram-VCZTEJTY-DqFlRrOL.js} +1 -1
- package/dist/deck-client/assets/{kanban-definition-6JOO6SKY-BQBUBzJC.js → kanban-definition-6JOO6SKY-BJhPp1NR.js} +1 -1
- package/dist/deck-client/assets/{layout-DeZ8HI1T.js → layout-DIeS6GvK.js} +1 -1
- package/dist/deck-client/assets/{linear-C6roLi_9.js → linear-He_yJy5H.js} +1 -1
- package/dist/deck-client/assets/{min-CbUksbuI.js → min-DQ6Kx06t.js} +1 -1
- package/dist/deck-client/assets/{mindmap-definition-QFDTVHPH-iNxV62yN.js → mindmap-definition-QFDTVHPH-sQ62L8T2.js} +1 -1
- package/dist/deck-client/assets/{pieDiagram-DEJITSTG-DHVA0jaG.js → pieDiagram-DEJITSTG-BqCWmU2K.js} +1 -1
- package/dist/deck-client/assets/{quadrantDiagram-34T5L4WZ-DBeKKLUQ.js → quadrantDiagram-34T5L4WZ-rQ1TJOoe.js} +1 -1
- package/dist/deck-client/assets/{requirementDiagram-MS252O5E-CBwITx7p.js → requirementDiagram-MS252O5E-BO2MPBOM.js} +1 -1
- package/dist/deck-client/assets/{sankeyDiagram-XADWPNL6-BtE-1YTU.js → sankeyDiagram-XADWPNL6-BgsHEVex.js} +1 -1
- package/dist/deck-client/assets/{sequenceDiagram-FGHM5R23-DN96yPP2.js → sequenceDiagram-FGHM5R23-B3j1yMLU.js} +1 -1
- package/dist/deck-client/assets/{stateDiagram-FHFEXIEX-VUkKC2uJ.js → stateDiagram-FHFEXIEX-C8jFlZou.js} +1 -1
- package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-BoqepHW0.js +1 -0
- package/dist/deck-client/assets/{timeline-definition-GMOUNBTQ-oUeZhRns.js → timeline-definition-GMOUNBTQ-tM-qo4Zk.js} +1 -1
- package/dist/deck-client/assets/{vennDiagram-DHZGUBPP-D87fK90n.js → vennDiagram-DHZGUBPP-B0-6kOEu.js} +1 -1
- package/dist/deck-client/assets/wardley-RL74JXVD-HpBk07P-.js +162 -0
- package/dist/deck-client/assets/{wardleyDiagram-NUSXRM2D-Ca_i0QRA.js → wardleyDiagram-NUSXRM2D-BkA1NLDE.js} +1 -1
- package/dist/deck-client/assets/{xychartDiagram-5P7HB3ND-CUOJVIvq.js → xychartDiagram-5P7HB3ND-CEKGSuI-.js} +1 -1
- package/dist/deck-client/index.html +2 -2
- package/dist/server/chart-serve.js +1336 -141
- package/dist/server/cli.js +28423 -6671
- package/dist/server/council-entry.js +0 -0
- package/dist/server/deck-mcp-entry.js +332 -3
- package/dist/server/deck-serve.js +288 -0
- package/dist/server/fb-wizard.js +0 -0
- package/dist/server/graph/queries/classify.scm +8 -0
- package/dist/server/graph/queries/exports.scm +7 -0
- package/dist/server/graph-mcp-entry.js +1987 -224
- package/dist/server/recall-entry.js +1112 -0
- package/package.json +47 -21
- package/dist/chart-client/assets/index--120d9P9.css +0 -1
- package/dist/client/assets/index-Bf8zdL3x.css +0 -32
- package/dist/council-client/assets/index-CofZh7pS.css +0 -1
- package/dist/deck-client/assets/channel-ERh5jKXV.js +0 -1
- package/dist/deck-client/assets/classDiagram-6PBFFD2Q-CMi1Gaev.js +0 -1
- package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-CMi1Gaev.js +0 -1
- package/dist/deck-client/assets/clone-DfWhlD4X.js +0 -1
- package/dist/deck-client/assets/index-765AIQ9z.css +0 -1
- package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-CA0IjulK.js +0 -1
- package/dist/deck-client/assets/wardley-RL74JXVD-DYbYcpDp.js +0 -162
- package/dist/server/deck-server/deck-mcp-entry.js +0 -1789
- package/dist/server/deck-server/deck-serve.js +0 -1275
- package/dist/server/server/chart-serve.js +0 -4643
- package/dist/server/server/cli.js +0 -13360
- package/dist/server/server/fb-wizard.js +0 -136
- package/dist/server/server/graph-mcp-entry.js +0 -6776
|
File without changes
|
|
@@ -892,6 +892,277 @@ var init_contract_generator = __esm({
|
|
|
892
892
|
}
|
|
893
893
|
});
|
|
894
894
|
|
|
895
|
+
// src/server/rich-html-render.ts
|
|
896
|
+
function renderRichHtml(opts) {
|
|
897
|
+
const theme = opts.theme ?? "light";
|
|
898
|
+
const title = escapeHtml(opts.title ?? "LaunchDeck");
|
|
899
|
+
if (opts.framework === "wired") {
|
|
900
|
+
return renderWired(opts.content, theme, title);
|
|
901
|
+
}
|
|
902
|
+
if (opts.framework === "reveal") {
|
|
903
|
+
return renderReveal(opts.content, theme, title);
|
|
904
|
+
}
|
|
905
|
+
return opts.content;
|
|
906
|
+
}
|
|
907
|
+
function themeResolverScript(initial) {
|
|
908
|
+
return `<script>
|
|
909
|
+
(function () {
|
|
910
|
+
function applyTheme(t) {
|
|
911
|
+
if (t !== 'light' && t !== 'dark') return;
|
|
912
|
+
var prev = document.documentElement.dataset.theme;
|
|
913
|
+
document.documentElement.dataset.theme = t;
|
|
914
|
+
if (prev !== t) {
|
|
915
|
+
document.dispatchEvent(new CustomEvent('deck-theme', { detail: t }));
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
// 1) initial preference: URL > prefers-color-scheme (standalone) > baked-in default
|
|
919
|
+
var url = new URL(window.location.href);
|
|
920
|
+
var fromUrl = url.searchParams.get('theme');
|
|
921
|
+
if (fromUrl === 'light' || fromUrl === 'dark') {
|
|
922
|
+
applyTheme(fromUrl);
|
|
923
|
+
} else if (window.parent === window) {
|
|
924
|
+
var prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
925
|
+
applyTheme(prefersDark ? 'dark' : 'light');
|
|
926
|
+
} else {
|
|
927
|
+
applyTheme(${JSON.stringify(initial)});
|
|
928
|
+
}
|
|
929
|
+
// 2) live updates from parent deck
|
|
930
|
+
window.addEventListener('message', function (e) {
|
|
931
|
+
if (e.data && e.data.type === 'deck-theme') applyTheme(e.data.theme);
|
|
932
|
+
});
|
|
933
|
+
// 3) tell parent we are ready so it can push the current theme back
|
|
934
|
+
if (window.parent !== window) {
|
|
935
|
+
window.parent.postMessage({ type: 'deck-iframe-ready' }, '*');
|
|
936
|
+
}
|
|
937
|
+
})();
|
|
938
|
+
</script>`;
|
|
939
|
+
}
|
|
940
|
+
function renderWired(body, initialTheme, title) {
|
|
941
|
+
const LIGHT = { bg: "#ffffff", fg: "#18181b", accent: "#7c3aed", cardBg: "#ffffff" };
|
|
942
|
+
const DARK = { bg: "#0e0e10", fg: "#e4e4e7", accent: "#a78bfa", cardBg: "#1a1a1d" };
|
|
943
|
+
const wiredVarsBlock = (vars) => `
|
|
944
|
+
--wired-card-background-fill: ${vars.cardBg};
|
|
945
|
+
--wired-button-color: ${vars.fg};
|
|
946
|
+
--wired-combo-popup-bg: ${vars.cardBg};
|
|
947
|
+
--wired-progress-color: ${vars.accent};
|
|
948
|
+
--wired-progress-label-background: ${vars.cardBg};
|
|
949
|
+
--wired-progress-label-color: ${vars.fg};
|
|
950
|
+
`;
|
|
951
|
+
return `<!DOCTYPE html>
|
|
952
|
+
<html lang="en" data-theme="${initialTheme}">
|
|
953
|
+
<head>
|
|
954
|
+
<meta charset="utf-8">
|
|
955
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
956
|
+
<title>${title}</title>
|
|
957
|
+
<script type="module" src="${WIRED_CDN}"></script>
|
|
958
|
+
<link href="https://fonts.googleapis.com/css2?family=Gloria+Hallelujah&family=DM+Sans:wght@400;600;700&display=swap" rel="stylesheet">
|
|
959
|
+
<style>
|
|
960
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
961
|
+
html, body {
|
|
962
|
+
margin: 0;
|
|
963
|
+
min-height: 100%;
|
|
964
|
+
font-family: 'Gloria Hallelujah', 'DM Sans', system-ui, sans-serif;
|
|
965
|
+
background: var(--page-bg);
|
|
966
|
+
color: var(--page-fg);
|
|
967
|
+
transition: background 0.15s, color 0.15s;
|
|
968
|
+
}
|
|
969
|
+
body { padding: 24px; }
|
|
970
|
+
h1, h2, h3, h4 { font-family: 'Gloria Hallelujah', cursive; margin: 0.5em 0; color: var(--page-fg); }
|
|
971
|
+
a { color: var(--page-accent); }
|
|
972
|
+
.row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin: 8px 0; }
|
|
973
|
+
.col { display: flex; flex-direction: column; gap: 12px; align-items: stretch; }
|
|
974
|
+
.card { padding: 16px; }
|
|
975
|
+
|
|
976
|
+
/* Light theme */
|
|
977
|
+
:root[data-theme="light"] {
|
|
978
|
+
--page-bg: ${LIGHT.bg};
|
|
979
|
+
--page-fg: ${LIGHT.fg};
|
|
980
|
+
--page-accent: ${LIGHT.accent};
|
|
981
|
+
${wiredVarsBlock(LIGHT)}
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
/* Dark theme */
|
|
985
|
+
:root[data-theme="dark"] {
|
|
986
|
+
--page-bg: ${DARK.bg};
|
|
987
|
+
--page-fg: ${DARK.fg};
|
|
988
|
+
--page-accent: ${DARK.accent};
|
|
989
|
+
${wiredVarsBlock(DARK)}
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
/* Hosts: text color inherits via component "color: inherit" rules.
|
|
993
|
+
Transparent background lets the page bg show through where the
|
|
994
|
+
rough.js rectangle leaves space. */
|
|
995
|
+
wired-button, wired-card, wired-checkbox, wired-radio, wired-toggle,
|
|
996
|
+
wired-input, wired-textarea, wired-search-input, wired-combo, wired-item,
|
|
997
|
+
wired-listbox, wired-link, wired-tabs, wired-tab, wired-fab,
|
|
998
|
+
wired-icon-button, wired-divider, wired-progress, wired-slider,
|
|
999
|
+
wired-calendar, wired-dialog {
|
|
1000
|
+
color: var(--page-fg);
|
|
1001
|
+
background: transparent;
|
|
1002
|
+
}
|
|
1003
|
+
</style>
|
|
1004
|
+
</head>
|
|
1005
|
+
<body>
|
|
1006
|
+
${body}
|
|
1007
|
+
${themeResolverScript(initialTheme)}
|
|
1008
|
+
<script type="module">
|
|
1009
|
+
// wired-input / wired-textarea / wired-search-input render their native
|
|
1010
|
+
// <input>/<textarea> INSIDE shadow DOM. Outer CSS cannot reach those, and
|
|
1011
|
+
// the native control has appearance:auto which the UA repaints over any
|
|
1012
|
+
// "background: transparent" rule. We must set inline styles directly on
|
|
1013
|
+
// the inner element with !important.
|
|
1014
|
+
//
|
|
1015
|
+
// We register one applier per theme. Re-runs when theme changes or new
|
|
1016
|
+
// nodes are added so the page reacts live to the deck sun/moon toggle.
|
|
1017
|
+
const FG = { light: ${JSON.stringify(LIGHT.fg)}, dark: ${JSON.stringify(DARK.fg)} };
|
|
1018
|
+
const TAGS = ['wired-input', 'wired-textarea', 'wired-search-input'];
|
|
1019
|
+
const DARK_PROPS = [
|
|
1020
|
+
'appearance', '-webkit-appearance',
|
|
1021
|
+
'background', 'background-color',
|
|
1022
|
+
'color', '-webkit-text-fill-color', 'caret-color',
|
|
1023
|
+
'border', 'outline',
|
|
1024
|
+
];
|
|
1025
|
+
|
|
1026
|
+
function applyDark(node) {
|
|
1027
|
+
const s = node.style;
|
|
1028
|
+
s.setProperty('appearance', 'none', 'important');
|
|
1029
|
+
s.setProperty('-webkit-appearance', 'none', 'important');
|
|
1030
|
+
s.setProperty('background', 'transparent', 'important');
|
|
1031
|
+
s.setProperty('background-color', 'transparent', 'important');
|
|
1032
|
+
s.setProperty('color', FG.dark, 'important');
|
|
1033
|
+
s.setProperty('-webkit-text-fill-color', FG.dark, 'important');
|
|
1034
|
+
s.setProperty('caret-color', FG.dark, 'important');
|
|
1035
|
+
s.setProperty('border', 'none', 'important');
|
|
1036
|
+
s.setProperty('outline', 'none', 'important');
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
function applyLight(node) {
|
|
1040
|
+
DARK_PROPS.forEach((p) => node.style.removeProperty(p));
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
function placeholderStyle(host, theme) {
|
|
1044
|
+
const existing = host.shadowRoot.querySelector('style[data-deck-theme]');
|
|
1045
|
+
if (existing) existing.remove();
|
|
1046
|
+
if (theme !== 'dark') return;
|
|
1047
|
+
const style = document.createElement('style');
|
|
1048
|
+
style.dataset.deckTheme = '1';
|
|
1049
|
+
style.textContent =
|
|
1050
|
+
'::placeholder{color:' + FG.dark + '99 !important;' +
|
|
1051
|
+
'-webkit-text-fill-color:' + FG.dark + '99 !important;}';
|
|
1052
|
+
host.shadowRoot.appendChild(style);
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
function sweepOnce() {
|
|
1056
|
+
const theme = document.documentElement.dataset.theme;
|
|
1057
|
+
for (const tag of TAGS) {
|
|
1058
|
+
for (const host of document.querySelectorAll(tag)) {
|
|
1059
|
+
if (!host.shadowRoot) continue;
|
|
1060
|
+
const inner = host.shadowRoot.querySelector('input, textarea');
|
|
1061
|
+
if (!inner) continue;
|
|
1062
|
+
if (theme === 'dark') applyDark(inner);
|
|
1063
|
+
else applyLight(inner);
|
|
1064
|
+
placeholderStyle(host, theme);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
// Initial + late-upgrade catch (CDN script loads async).
|
|
1070
|
+
sweepOnce();
|
|
1071
|
+
let elapsed = 0;
|
|
1072
|
+
function tick() {
|
|
1073
|
+
sweepOnce();
|
|
1074
|
+
elapsed += 100;
|
|
1075
|
+
if (elapsed < 3000) setTimeout(tick, 100);
|
|
1076
|
+
}
|
|
1077
|
+
setTimeout(tick, 100);
|
|
1078
|
+
|
|
1079
|
+
// Re-sweep on theme change.
|
|
1080
|
+
document.addEventListener('deck-theme', sweepOnce);
|
|
1081
|
+
// Re-sweep when new nodes are added.
|
|
1082
|
+
new MutationObserver(sweepOnce).observe(document.body, { subtree: true, childList: true });
|
|
1083
|
+
|
|
1084
|
+
// whenDefined fires when each tag is registered \u2014 allSettled-style, never hangs.
|
|
1085
|
+
TAGS.forEach((tag) => {
|
|
1086
|
+
customElements.whenDefined(tag).then(sweepOnce).catch(() => {});
|
|
1087
|
+
});
|
|
1088
|
+
</script>
|
|
1089
|
+
</body>
|
|
1090
|
+
</html>`;
|
|
1091
|
+
}
|
|
1092
|
+
function renderReveal(content, initialTheme, title) {
|
|
1093
|
+
const slides = content.includes("<section") ? content : content.split(/\n\s*---\s*\n/).map((md) => `<section data-markdown><textarea data-template>
|
|
1094
|
+
${md.trim()}
|
|
1095
|
+
</textarea></section>`).join("\n");
|
|
1096
|
+
return `<!DOCTYPE html>
|
|
1097
|
+
<html lang="en" data-theme="${initialTheme}">
|
|
1098
|
+
<head>
|
|
1099
|
+
<meta charset="utf-8">
|
|
1100
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
1101
|
+
<title>${title}</title>
|
|
1102
|
+
<link rel="stylesheet" href="${REVEAL_CSS}">
|
|
1103
|
+
<link id="reveal-theme-light" rel="stylesheet" href="${REVEAL_THEME("light")}" ${initialTheme === "dark" ? "disabled" : ""}>
|
|
1104
|
+
<link id="reveal-theme-dark" rel="stylesheet" href="${REVEAL_THEME("dark")}" ${initialTheme === "dark" ? "" : "disabled"}>
|
|
1105
|
+
<style>
|
|
1106
|
+
html, body { margin: 0; height: 100%; }
|
|
1107
|
+
.reveal .slides { text-align: left; }
|
|
1108
|
+
.reveal .slides section { padding: 0 32px; }
|
|
1109
|
+
</style>
|
|
1110
|
+
</head>
|
|
1111
|
+
<body>
|
|
1112
|
+
<div class="reveal">
|
|
1113
|
+
<div class="slides">
|
|
1114
|
+
${slides}
|
|
1115
|
+
</div>
|
|
1116
|
+
</div>
|
|
1117
|
+
<script src="${REVEAL_JS}"></script>
|
|
1118
|
+
<script src="${REVEAL_MD}"></script>
|
|
1119
|
+
<script src="${REVEAL_HL}"></script>
|
|
1120
|
+
<script src="${REVEAL_NOTES}"></script>
|
|
1121
|
+
<script>
|
|
1122
|
+
Reveal.initialize({
|
|
1123
|
+
hash: true,
|
|
1124
|
+
slideNumber: 'c/t',
|
|
1125
|
+
controls: true,
|
|
1126
|
+
progress: true,
|
|
1127
|
+
transition: 'slide',
|
|
1128
|
+
plugins: [RevealMarkdown, RevealHighlight, RevealNotes],
|
|
1129
|
+
});
|
|
1130
|
+
// React to theme changes: flip which stylesheet is enabled.
|
|
1131
|
+
function syncRevealTheme() {
|
|
1132
|
+
var dark = document.documentElement.dataset.theme === 'dark';
|
|
1133
|
+
var lightLink = document.getElementById('reveal-theme-light');
|
|
1134
|
+
var darkLink = document.getElementById('reveal-theme-dark');
|
|
1135
|
+
if (lightLink) lightLink.disabled = dark;
|
|
1136
|
+
if (darkLink) darkLink.disabled = !dark;
|
|
1137
|
+
}
|
|
1138
|
+
document.addEventListener('deck-theme', syncRevealTheme);
|
|
1139
|
+
syncRevealTheme();
|
|
1140
|
+
</script>
|
|
1141
|
+
${themeResolverScript(initialTheme)}
|
|
1142
|
+
</body>
|
|
1143
|
+
</html>`;
|
|
1144
|
+
}
|
|
1145
|
+
function escapeHtml(s) {
|
|
1146
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
1147
|
+
}
|
|
1148
|
+
function slugify(label) {
|
|
1149
|
+
return label.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "block";
|
|
1150
|
+
}
|
|
1151
|
+
var WIRED_CDN, REVEAL_VER, REVEAL_CSS, REVEAL_THEME, REVEAL_JS, REVEAL_MD, REVEAL_HL, REVEAL_NOTES;
|
|
1152
|
+
var init_rich_html_render = __esm({
|
|
1153
|
+
"src/server/rich-html-render.ts"() {
|
|
1154
|
+
"use strict";
|
|
1155
|
+
WIRED_CDN = "https://unpkg.com/wired-elements?module";
|
|
1156
|
+
REVEAL_VER = "5.1.0";
|
|
1157
|
+
REVEAL_CSS = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/dist/reveal.css`;
|
|
1158
|
+
REVEAL_THEME = (t) => `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/dist/theme/${t === "dark" ? "black" : "white"}.css`;
|
|
1159
|
+
REVEAL_JS = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/dist/reveal.js`;
|
|
1160
|
+
REVEAL_MD = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/plugin/markdown/markdown.js`;
|
|
1161
|
+
REVEAL_HL = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/plugin/highlight/highlight.js`;
|
|
1162
|
+
REVEAL_NOTES = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/plugin/notes/notes.js`;
|
|
1163
|
+
}
|
|
1164
|
+
});
|
|
1165
|
+
|
|
895
1166
|
// src/server/deck-serve.ts
|
|
896
1167
|
var deck_serve_exports = {};
|
|
897
1168
|
__export(deck_serve_exports, {
|
|
@@ -1067,6 +1338,29 @@ async function startDeckServer(opts = {}) {
|
|
|
1067
1338
|
console.error("Failed to generate blast radius HTML:", err);
|
|
1068
1339
|
}
|
|
1069
1340
|
}
|
|
1341
|
+
if (block.type === "rich-html" && block.content) {
|
|
1342
|
+
try {
|
|
1343
|
+
const html = renderRichHtml({
|
|
1344
|
+
framework: block.framework ?? "raw",
|
|
1345
|
+
content: block.content,
|
|
1346
|
+
theme: block.theme,
|
|
1347
|
+
title: block.label
|
|
1348
|
+
});
|
|
1349
|
+
const sessionEncoded = encodeURIComponent(body.session);
|
|
1350
|
+
const baseUrl = `/deck-files/${sessionEncoded}`;
|
|
1351
|
+
const filename = `${slugify(block.label)}.html`;
|
|
1352
|
+
const dir = import_node_path3.default.join(cwd, ".launchsecure", "deck-files", body.session);
|
|
1353
|
+
import_node_fs3.default.mkdirSync(dir, { recursive: true });
|
|
1354
|
+
import_node_fs3.default.writeFileSync(import_node_path3.default.join(dir, filename), html);
|
|
1355
|
+
block.type = "iframe";
|
|
1356
|
+
block.src = `${baseUrl}/${filename}`;
|
|
1357
|
+
delete block.content;
|
|
1358
|
+
delete block.framework;
|
|
1359
|
+
delete block.theme;
|
|
1360
|
+
} catch (err) {
|
|
1361
|
+
console.error("Failed to generate rich-html:", err);
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1070
1364
|
}
|
|
1071
1365
|
broadcastToClients({
|
|
1072
1366
|
type: "session",
|
|
@@ -1280,6 +1574,7 @@ var init_deck_serve = __esm({
|
|
|
1280
1574
|
init_deck_config();
|
|
1281
1575
|
init_blast_radius_render();
|
|
1282
1576
|
init_contract_generator();
|
|
1577
|
+
init_rich_html_render();
|
|
1283
1578
|
DEFAULT_PORT = 52829;
|
|
1284
1579
|
MAX_PORT_SCAN = 3;
|
|
1285
1580
|
MIME_TYPES = {
|
|
@@ -1381,6 +1676,29 @@ async function handleTool(name, args) {
|
|
|
1381
1676
|
return text(JSON.stringify({ error: `Failed to generate blast radius HTML: ${err}` }));
|
|
1382
1677
|
}
|
|
1383
1678
|
}
|
|
1679
|
+
if (block.type === "rich-html" && block.content) {
|
|
1680
|
+
try {
|
|
1681
|
+
const html = renderRichHtml({
|
|
1682
|
+
framework: block.framework ?? "raw",
|
|
1683
|
+
content: block.content,
|
|
1684
|
+
theme: block.theme,
|
|
1685
|
+
title: block.label
|
|
1686
|
+
});
|
|
1687
|
+
const sessionEncoded = encodeURIComponent(session);
|
|
1688
|
+
const baseUrl = `/deck-files/${sessionEncoded}`;
|
|
1689
|
+
const filename = `${slugify(block.label)}.html`;
|
|
1690
|
+
const dir = (0, import_node_path4.join)(projectRoot, ".launchsecure", "deck-files", session);
|
|
1691
|
+
import_node_fs4.default.mkdirSync(dir, { recursive: true });
|
|
1692
|
+
import_node_fs4.default.writeFileSync((0, import_node_path4.join)(dir, filename), html);
|
|
1693
|
+
block.type = "iframe";
|
|
1694
|
+
block.src = `${baseUrl}/${filename}`;
|
|
1695
|
+
delete block.content;
|
|
1696
|
+
delete block.framework;
|
|
1697
|
+
delete block.theme;
|
|
1698
|
+
} catch (err) {
|
|
1699
|
+
return text(JSON.stringify({ error: `Failed to generate rich-html: ${err}` }));
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1384
1702
|
}
|
|
1385
1703
|
try {
|
|
1386
1704
|
await httpPost(`${lock.url}/api/deck`, { session, mode, blocks, prompt });
|
|
@@ -1643,6 +1961,7 @@ var init_deck_mcp = __esm({
|
|
|
1643
1961
|
init_deck_config();
|
|
1644
1962
|
init_blast_radius_render();
|
|
1645
1963
|
init_contract_generator();
|
|
1964
|
+
init_rich_html_render();
|
|
1646
1965
|
SERVER_INFO = {
|
|
1647
1966
|
name: "launch-deck",
|
|
1648
1967
|
version: "0.0.3"
|
|
@@ -1650,7 +1969,7 @@ var init_deck_mcp = __esm({
|
|
|
1650
1969
|
TOOLS = [
|
|
1651
1970
|
{
|
|
1652
1971
|
name: "deck",
|
|
1653
|
-
description: 'Push visual blocks (HTML, Mermaid diagrams, options, markdown) to the LaunchDeck browser.\n\nEach call creates a named session tab in the browser. Tabs accumulate \u2014 previous sessions are preserved.\n\nModes:\n- "show": Display content and return immediately. Terminal confirms delivery. No user feedback.\n- "feedback": Display content with an input bar for the user to respond. Returns immediately with session info. Call `await_feedback` with the same session ID to block until the user responds.\n\nBlock types:\n- html: Raw HTML/CSS (
|
|
1972
|
+
description: 'Push visual blocks (HTML, Mermaid diagrams, options, markdown) to the LaunchDeck browser.\n\nEach call creates a named session tab in the browser. Tabs accumulate \u2014 previous sessions are preserved.\n\nModes:\n- "show": Display content and return immediately. Terminal confirms delivery. No user feedback.\n- "feedback": Display content with an input bar for the user to respond. Returns immediately with session info. Call `await_feedback` with the same session ID to block until the user responds.\n\nBlock types:\n- html: Raw HTML/CSS (sandboxed iframe \u2014 NO scripts). Use for static markup only.\n- mermaid: Mermaid diagram DSL (flowchart, sequence, ERD, etc.)\n- markdown: Rendered markdown text\n- options: Selection cards \u2014 user picks one or more\n- blast-radius: Interactive D3 radial graph for blast radius analysis. Requires `manifest` field.\n- rich-html: Self-contained HTML page with FULL JS support (events, animations, CDN scripts). Specify `framework` and `content`:\n \u2022 framework: "wired" \u2014 wireframe UI via wired-elements (https://wiredjs.com). `content` is body HTML using <wired-button>, <wired-input>, <wired-card>, <wired-checkbox>, <wired-combo>, <wired-slider>, <wired-tabs>/<wired-tab>, etc. Hand-drawn aesthetic. Loads CDN automatically.\n \u2022 framework: "reveal" \u2014 slide presentation via reveal.js (https://revealjs.com). `content` is markdown slides joined by `\\n---\\n` (recommended) OR raw <section>\u2026</section> HTML. Arrow keys navigate. Supports code highlighting and speaker notes. Loads CDN automatically.\n \u2022 framework: "raw" \u2014 `content` is a complete <!DOCTYPE html> document (caller controls everything).\n Optional `theme: "light" | "dark"` sets the INITIAL preference. The deck\'s sun/moon toggle overrides live \u2014 content reacts in place. Usually omit it; only set when the AI has a specific reason (e.g. mockup that only makes sense in one mode). Standalone downloads fall back to OS prefers-color-scheme.\n\nAfter calling this tool, the user should check the LaunchDeck browser tab to view content.',
|
|
1654
1973
|
inputSchema: {
|
|
1655
1974
|
type: "object",
|
|
1656
1975
|
properties: {
|
|
@@ -1669,9 +1988,19 @@ var init_deck_mcp = __esm({
|
|
|
1669
1988
|
items: {
|
|
1670
1989
|
type: "object",
|
|
1671
1990
|
properties: {
|
|
1672
|
-
type: { type: "string", enum: ["html", "mermaid", "options", "markdown", "blast-radius"] },
|
|
1991
|
+
type: { type: "string", enum: ["html", "mermaid", "options", "markdown", "blast-radius", "rich-html"] },
|
|
1673
1992
|
label: { type: "string", description: "Label for this block (shown as sub-tab if multiple blocks)" },
|
|
1674
|
-
content: { type: "string", description: "Content string (HTML, Mermaid DSL, Markdown)" },
|
|
1993
|
+
content: { type: "string", description: "Content string (HTML, Mermaid DSL, Markdown, or rich-html body)" },
|
|
1994
|
+
framework: {
|
|
1995
|
+
type: "string",
|
|
1996
|
+
enum: ["wired", "reveal", "raw"],
|
|
1997
|
+
description: "For rich-html only: which framework to wrap content with."
|
|
1998
|
+
},
|
|
1999
|
+
theme: {
|
|
2000
|
+
type: "string",
|
|
2001
|
+
enum: ["light", "dark"],
|
|
2002
|
+
description: "For rich-html only: theme for the generated page."
|
|
2003
|
+
},
|
|
1675
2004
|
manifest: {
|
|
1676
2005
|
type: "object",
|
|
1677
2006
|
description: 'For blast-radius type: BlastRadiusManifest object. Generates an interactive D3 radial graph.\n\nRequired fields:\n- mode: "structural" (file-level, rings = hops) or "feature" (rings = modify/create/ripple)\n- title: string \u2014 shown in header (e.g. "lib/permissions/types.ts" or "Channels for Comms")\n- layers: array of { id, name, icon, color } \u2014 defines the project layers (e.g. db/api/ui). icon = Lucide icon name, color = hex fill color\n- rings: array of { id, name, color } \u2014 defines concentric rings. For structural: [{id:"hop1",name:"Direct",color:"#f97316"},{id:"hop2",name:"Indirect",color:"#eab308"}]. For feature: [{id:"modify",name:"Modify",color:"#f97316"},{id:"create",name:"Create",color:"#22c55e"},{id:"ripple",name:"Ripple",color:"#eab308"}]\n- center: { name, description } \u2014 the center node label and tooltip\n- nodes: array of { id, name, layer, ring, path?, reason?, type? } \u2014 layer refs layers[].id, ring refs rings[].id\n- edges: array of { source, target } \u2014 source/target are node ids, use "center" for edges from the center node\n\nOptional: subtitle (shown above title)\n\nExample layers: [{id:"db",name:"Database",icon:"database",color:"#172554"},{id:"api",name:"API",icon:"server",color:"#1e3a5f"},{id:"ui",name:"UI",icon:"layout-dashboard",color:"#0c4a6e"}]'
|