decaframe 0.1.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/LICENSE +32 -0
- package/README.md +55 -0
- package/dist/archetype.js +1 -0
- package/dist/blocks.css +2822 -0
- package/dist/blocks.js +6 -0
- package/dist/brand.js +1 -0
- package/dist/chart.js +3 -0
- package/dist/chartView.js +1 -0
- package/dist/cli.js +22 -0
- package/dist/colour.js +1 -0
- package/dist/commands.js +1 -0
- package/dist/design.js +1 -0
- package/dist/diagram.js +99 -0
- package/dist/diagramRender.js +1 -0
- package/dist/diagramTheme.js +1 -0
- package/dist/diagramView.js +1 -0
- package/dist/diagramZoom.js +2 -0
- package/dist/export/assets.js +1 -0
- package/dist/export/html.js +6 -0
- package/dist/export/spec.js +1 -0
- package/dist/export/viewer.js +1112 -0
- package/dist/extensions.js +1 -0
- package/dist/figure.js +1 -0
- package/dist/filename.js +1 -0
- package/dist/fit.js +6 -0
- package/dist/fitLoop.js +1 -0
- package/dist/furniture.js +1 -0
- package/dist/icons.js +1 -0
- package/dist/id.js +1 -0
- package/dist/index.js +1 -0
- package/dist/item.js +1 -0
- package/dist/layout.js +1 -0
- package/dist/lint.js +1 -0
- package/dist/markdown.js +32 -0
- package/dist/mcp/browser.js +81 -0
- package/dist/mcp/channel.js +7 -0
- package/dist/mcp/export.js +1 -0
- package/dist/mcp/exportCli.js +11 -0
- package/dist/mcp/fit.js +1 -0
- package/dist/mcp/open.js +1 -0
- package/dist/mcp/openCli.js +1 -0
- package/dist/mcp/read.js +1 -0
- package/dist/mcp/server.js +31 -0
- package/dist/mcp/session.js +2 -0
- package/dist/mcp/stdio.js +2 -0
- package/dist/media.js +1 -0
- package/dist/notes.js +1 -0
- package/dist/page.js +1 -0
- package/dist/placeholder.js +1 -0
- package/dist/present/constants.js +1 -0
- package/dist/prose.js +1 -0
- package/dist/registry.js +1 -0
- package/dist/sizePreview.js +1 -0
- package/dist/slotMarkdown.js +3 -0
- package/dist/table.js +2 -0
- package/dist/template/catalogue.json +1 -0
- package/dist/template/index.js +1 -0
- package/dist/template/look.js +1 -0
- package/dist/text.js +8 -0
- package/dist/theme/atelier.json +1 -0
- package/dist/theme/aurora.json +1 -0
- package/dist/theme/boardroom.json +1 -0
- package/dist/theme/decaframe.json +1 -0
- package/dist/theme/editorial.json +1 -0
- package/dist/theme/emit.js +19 -0
- package/dist/theme/fonts.js +1 -0
- package/dist/theme/foundry.json +1 -0
- package/dist/theme/index.js +1 -0
- package/dist/theme/meadow.json +1 -0
- package/dist/theme/signal.json +1 -0
- package/dist/theme/tokens.json +1 -0
- package/dist/videoPlay.js +1 -0
- package/editor/assets/App-BvOGZ4cc.js +56 -0
- package/editor/assets/PresenterView-Barr5wsl.js +1 -0
- package/editor/assets/Shell-Dvc8Yvly.js +413 -0
- package/editor/assets/_commonjsHelpers-CqkleIqs.js +1 -0
- package/editor/assets/abnfDiagram-N423BO3Z-DMNuYXhv.js +1 -0
- package/editor/assets/arc-DOR9Dhm9.js +1 -0
- package/editor/assets/architectureDiagram-T3A2C74G-CpcCHDGw.js +36 -0
- package/editor/assets/blockDiagram-VBNYF7ZC-CbCqcHim.js +132 -0
- package/editor/assets/c4Diagram-5PPSVZJV-DouVYESX.js +10 -0
- package/editor/assets/channel-Dt7MgGxB.js +1 -0
- package/editor/assets/chunk-2GRJ4B5K-DCJz-Q3N.js +1 -0
- package/editor/assets/chunk-2Q5K7J3B-D5q9RvV7.js +1 -0
- package/editor/assets/chunk-5RXB4S5H-DnaXL-Vg.js +231 -0
- package/editor/assets/chunk-5VM5RSS4-Dsc890tp.js +15 -0
- package/editor/assets/chunk-6Q2QTUOP-B5F620Er.js +88 -0
- package/editor/assets/chunk-GF5L2VYU-D6F2cocl.js +206 -0
- package/editor/assets/chunk-JWPE2WC7-bRknM2iE.js +1 -0
- package/editor/assets/chunk-KBJHAD2P-DOPClpqF.js +1 -0
- package/editor/assets/chunk-RYQCIY6F-CvMFFqLU.js +1 -0
- package/editor/assets/chunk-XXDRQBXY-1qxA3khf.js +1 -0
- package/editor/assets/classDiagram-JCYQIIEL-DCQKoo1F.js +1 -0
- package/editor/assets/classDiagram-v2-OCEON4UE-DCQKoo1F.js +1 -0
- package/editor/assets/cose-bilkent-JH36ORCC-ClwDXN93.js +1 -0
- package/editor/assets/cynefin-VYW2F7L2-D_3oIqit.js +178 -0
- package/editor/assets/cynefinDiagram-MW4NZA55-5VKykgH3.js +62 -0
- package/editor/assets/cytoscape.esm-BjAbmLdb.js +331 -0
- package/editor/assets/dagre-VZM6K2ZE-DcheWwdS.js +4 -0
- package/editor/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/editor/assets/diagram-7IWD3JNH-BKU8hufg.js +30 -0
- package/editor/assets/diagram-B4RE2ZJO-C6NwNXMM.js +3 -0
- package/editor/assets/diagram-LBJQPF4R-D5l8kaaB.js +24 -0
- package/editor/assets/diagram-Q27KOJAE-B839mp_E.js +24 -0
- package/editor/assets/diagram-UB23O5K3-BEJ8nrHN.js +41 -0
- package/editor/assets/ebnfDiagram-BXEA7PRR-Clexv7zP.js +1 -0
- package/editor/assets/erDiagram-JOGREHBK-CQiS9gcI.js +85 -0
- package/editor/assets/flowDiagram-UKHOOZJN-CKnVd1JX.js +156 -0
- package/editor/assets/ganttDiagram-PKOTCBZU-B2_YsT7P.js +292 -0
- package/editor/assets/gitGraphDiagram-DS77QQ5N-woKMsCpe.js +106 -0
- package/editor/assets/graph-C9eacEi8.js +1 -0
- package/editor/assets/index-CBRsrwap.css +1 -0
- package/editor/assets/index-CnMC8Z9d.js +9167 -0
- package/editor/assets/index-CzJ1nSGZ.js +61 -0
- package/editor/assets/infoDiagram-6WML65LV-DQBHUzYs.js +2 -0
- package/editor/assets/init-Gi6I4Gst.js +1 -0
- package/editor/assets/ishikawaDiagram-WSZJBQD7-B0ECJjey.js +70 -0
- package/editor/assets/journeyDiagram-NVQOT4AX-C6IoE7ds.js +139 -0
- package/editor/assets/kanban-definition-27J2QSJJ-BsRx6-QA.js +89 -0
- package/editor/assets/katex-C5jXJg4s.js +257 -0
- package/editor/assets/layout-DEXfKzaS.js +1 -0
- package/editor/assets/linear-CZdkbpsZ.js +1 -0
- package/editor/assets/map-Czzmt4hB.js +1 -0
- package/editor/assets/mermaid.core-BD7SxJD7.js +314 -0
- package/editor/assets/mindmap-definition-FAOFIHXS-zQTmawZC.js +96 -0
- package/editor/assets/ordinal-Cboi1Yqb.js +1 -0
- package/editor/assets/pegDiagram-VL7TDLO6-DwfoSDjb.js +1 -0
- package/editor/assets/pieDiagram-7S7Q4E2Y-CFju-NFP.js +39 -0
- package/editor/assets/quadrantDiagram-CIZ2JOQS-BD6kYPyE.js +7 -0
- package/editor/assets/railroadDiagram-AXF67PYL-RqQwm-lL.js +1 -0
- package/editor/assets/requirementDiagram-LRYGKXZP-piqHrBVs.js +84 -0
- package/editor/assets/sankeyDiagram-W5VNT64P-CiALLT6P.js +40 -0
- package/editor/assets/sequenceDiagram-SI44F4Z6-CjpaYPxa.js +162 -0
- package/editor/assets/sizeCapture-X5ZJPWSS-DG9i3uEZ.js +1 -0
- package/editor/assets/stateDiagram-OKZ733FA-BgfrUiLR.js +1 -0
- package/editor/assets/stateDiagram-v2-UEYNNEHI-OBUiw3fk.js +1 -0
- package/editor/assets/swimlanes-SLNWSIFB-edAhP15G.js +2 -0
- package/editor/assets/swimlanesDiagram-ULZ7WXOC-BvcKTcG0.js +8 -0
- package/editor/assets/timeline-definition-Z64GVDOM-CLCag48V.js +120 -0
- package/editor/assets/vennDiagram-T6HMQDX7-CNuGpJHG.js +34 -0
- package/editor/assets/wardleyDiagram-T6FBY63Y-D-NVpbtn.js +78 -0
- package/editor/assets/xychartDiagram-ELKLHX3M-CmO8305Y.js +7 -0
- package/editor/favicon.ico +0 -0
- package/editor/index.html +15 -0
- package/package.json +61 -0
package/dist/blocks.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{Extension as N,Node as m,mergeAttributes as g}from"@tiptap/core";import{Plugin as U,PluginKey as L}from"@tiptap/pm/state";import{Decoration as I,DecorationSet as P}from"@tiptap/pm/view";import{isEntryArchetype as D}from"./archetype.js";import{LIST_NODES as H}from"./prose.js";import{TABLE_NODES as C,colsOf as M}from"./table.js";import{ARRANGEMENT_ATTR as B,FIGURE_ATTR as q,blockAttributes as T,sizeAttributes as W}from"./design.js";import{DIAGRAM_KINDS as $}from"./diagram.js";import{CHART_NODE as F}from"./chart.js";import{CLIMB_STOPS as x,CLIMB_VIEWBOX as E,CORE_STOPS as k,CORE_VIEWBOX as c,FIGURE_NAMES as G,FIGURE_VIEWBOX as A,ROAD_STOPS as R,SVG_NS as w,climbEnds as Y,climbFaceD as j,climbPathD as _,coreEnds as V,coreLayers as X,figureAttribute as z,roadPathD as K}from"./figure.js";const p=[{type:"box",group:"Boxes",node:"box",archetype:"items",version:1,countRange:[1,9],slots:["icon","meta","title","body"],optional:["meta"],variantSlots:["fill","on-fill","border-top","border-lead","border-trail","border-bottom","border-weight","divider","corner","elevation","head-fill","on-head-fill"],marks:[],arrangements:[{name:"grid",label:"Grid",whenToUse:"The default. Boxes side by side, three to a row, so a set reads as a set. At a count of ONE it is a callout \u2014 a single point set apart. At TWO or THREE it is also how a COMPARISON is written: one column per option, the title naming it and the body holding that option's points, one per line \u2014 a newline in a body is a line break. Note that FOUR is two rows of two rather than four columns, so a four-way comparison reads as a square; keep one to three columns or use `table` when the options share their criteria.",countRange:[1,9]},{name:"list",label:"List",whenToUse:"One box per line, each the whole width of the frame \u2014 so it holds about HALF AGAIN what a grid cell does at two or three entries. The shape for FEW things said at LENGTH: propositions with a paragraph each, principles, objections and answers. Prefer the grid once there are four or more: by six a row holds LESS than a cell, not more. At five and six the body moves BESIDE the title instead of under it, so keep titles to a few words.",countRange:[2,6]}],placeholders:{meta:"Label",title:"Title",body:"What this one is"},description:"Icon-led boxes, as a grid or a list. At one, a callout.",whenToUse:'Parallel things with no order and no dates \u2014 features, capabilities, sources, destinations. The default when items are a set rather than a sequence. Pick the `arrangement` for how much each one has to say: `grid` for captions, `list` for real prose. A body may hold a short list \u2014 lines led by "- " become bullets, which is how a feature card or a comparison column carries its points. `meta` is an optional EYEBROW \u2014 a small label above the title naming its kind or category; give it to every box or to none. Prefer `steps` when the order is the point, since this block draws no numbers and implies no sequence.',example:[{icon:"zap",title:"Incremental compute",body:"Only the partitions a change touches are recomputed."},{icon:"lock",title:"Row-level policy",body:"Enforced in the planner, not bolted onto each client."}]},{type:"steps",group:"Sequence",node:"steps",archetype:"items",version:1,countRange:[2,6],slots:["title","body","icon"],variantSlots:["fill","on-fill","border-top","border-lead","border-trail","border-bottom","border-weight","divider","corner","elevation","marker","marker-fill"],shapesDiffer:"meaning",marks:["numeral","icon","none"],arrangements:[{name:"across",label:"Across",whenToUse:"The default. Numbered steps side by side with a line running between them, so the eye reads left to right. The most room per step of the three, and the only shape that keeps the frame's full height \u2014 prefer it whenever each step has a sentence or more to say. At six it wraps to two rows of three.",countRange:[2,6]},{name:"list",label:"List",whenToUse:"Steps stacked down the page at the FULL width, one per line, with the numeral beside the title. The plain stack: it says the steps are in order and claims nothing else, which is what makes it the one to reach for when the sequence is ordinary \u2014 a procedure, a set-up, an agenda. It holds MORE than any other stacked shape at the same count, because a full-width band wraps its body in fewer lines, and it is the only shape here that runs to six. Use `staircase` instead when the progression itself is the message, and `across` when there are few steps and each has a paragraph to say.",countRange:[2,6]},{name:"staircase",label:"Staircase",whenToUse:'Steps stacked down the page, each one offset further across than the last, so the shape itself says "and then". Every tread is the same size, so every step holds the same. It holds about HALF what `across` does at the same count \u2014 a band is shorter than a full-height column and the offset costs width on top \u2014 so use it when the SEQUENCE is the message and each step is a short label with a line of explanation. At five, that is literally one line each; at two and three there is room for two or three.',countRange:[2,5]},{name:"funnel",label:"Funnel",whenToUse:"Stacked bands, each NARROWER than the one above, for a sequence that filters something down \u2014 a pipeline, a qualification flow, an audience narrowing to a customer. The bottom band is about half the width of the top, so the size below is what the NARROWEST step holds and every step is safe at it; the top band will take nearly twice that. Put the long text at the TOP. If the steps are not narrowing something, use `across`.",countRange:[2,5]},{name:"pyramid",label:"Pyramid",reverses:"funnel",whenToUse:"Stacked bands, each WIDER than the one above, for a structure that rests on what is underneath it \u2014 a hierarchy of needs, a foundation-then-refinement argument, a maturity model. Item one is the apex and the LAST item is the base, which is both the widest band and the most foundational thing you are saying. Put the long text at the BOTTOM. It holds exactly what `funnel` holds, so pick between them on what the sequence MEANS: a funnel filters something down, a pyramid builds something up.",countRange:[2,5]},{name:"ring",label:"Ring",whenToUse:'A closed cycle, for a sequence whose last step feeds the first \u2014 a feedback loop, a flywheel, a lifecycle. The steps sit round a circle with the connector closing it, so the shape itself says "and then it starts again"; use one of the other shapes if the sequence ENDS, because a ring claims it does not. It holds the least of any shape here by a wide margin \u2014 a circle in a wide frame leaves the sides empty, and the room goes to the diameter \u2014 so each step is a label and a line, never a paragraph.',countRange:[2,5]}],figures:[{name:"road",label:"Road",whenToUse:"A winding path with a stop for each item, for a journey or a plan with a beginning and an end \u2014 prefer this over `arrangement` when the picture itself is part of the point, never for a process where the steps are interchangeable in order. Setting a figure clears any stored arrangement \u2014 the two are exclusive, never combined.",countRange:[R.min,R.max]},{name:"climb",label:"Climb",whenToUse:"A rise to a goal \u2014 each stop stands higher than the last on a slope that climbs to the right, so the picture itself says the final item is the summit. Use it when the ASCENT is the message: growth, a maturity model, levels of a plan, a target being approached. Prefer `road` when the point is a journey with stops rather than a rise, and the `staircase` arrangement when you want plain boxes and no drawing. Setting a figure clears any stored arrangement \u2014 the two are exclusive, never combined.",countRange:[x.min,x.max]},{name:"core",label:"Core",whenToUse:"Layers around a core, for things that CONTAIN one another \u2014 a platform with what is built on it, a team inside a company inside a market, a scope widening outward. Item one is the CORE and sits innermost; each item after it wraps around the one before, so put the most fundamental thing FIRST. Prefer `climb` when the last item is the goal rather than the outside, and the `pyramid` arrangement when levels REST on each other instead of surrounding each other. The INNERMOST layer is the smallest circle and holds the least \u2014 a short title and one line \u2014 so put the longest words on the OUTER layers. Setting a figure clears any stored arrangement \u2014 the two are exclusive, never combined.",countRange:[k.min,k.max]}],placeholders:{title:"Step name",body:"What happens in it"},description:"A numbered sequence \u2014 across, as a staircase, a funnel, a pyramid, or a ring.",whenToUse:'Ordered stages where the order is the point \u2014 a process, an onboarding, a how-it-works. It draws its own numbering, so do NOT put "1." or "Step 1" in the titles. Pick the `arrangement` for what the sequence MEANS: `across` when each step has real prose, `staircase` when the progression is the point, `funnel` when each stage narrows the last, `pyramid` when each level rests on the one below it, `ring` when the last step feeds the first. `funnel` and `pyramid` hold the same amount and differ in where the long text goes \u2014 the top of a funnel, the bottom of a pyramid. `ring` holds the least of the five.',example:[{title:"Connect",body:"Read-only credentials against one source.",emphasis:!0},{title:"Compare",body:"Every metric is diffed until the two agree to the row."}]},{type:"timeline",group:"Sequence",node:"timeline",archetype:"items",version:1,countRange:[3,8],slots:["meta","title","body","icon"],marks:["dot","icon"],variantSlots:["fill","on-fill","border-top","border-lead","border-trail","border-bottom","border-weight","divider","corner","elevation","marker","marker-fill"],arrangements:[],placeholders:{meta:"Date",title:"Milestone",body:"What changed"},description:"Dated milestones on a vertical rail.",whenToUse:"Events anchored to a date or period, in chronological order. The date goes in `meta`. If the items are ordered but undated, use `steps` instead.",example:[{meta:"Shipped",title:"Incremental engine",body:"Partition-level recompute across all sources.",emphasis:!0},{meta:"Q3 2026",title:"Branching GA",body:"Fork, test and merge warehouse state without a copy."}]},{type:"stat-row",group:"Numbers",node:"statRow",archetype:"stats",version:1,countRange:[2,5],slots:["value","label","note"],variantSlots:["fill","on-fill","border-top","border-lead","border-trail","border-bottom","border-weight","divider","corner","elevation","row-rule","row-mark"],marks:[],arrangements:[],placeholders:{value:"Figure",label:"What it measures",note:"What qualifies it"},description:"A row of large figures.",whenToUse:"Headline numbers \u2014 metrics, traction, results. `value` is the large figure and is the only required slot in the whole catalogue; `label` names it, `note` qualifies it. Write `value` SHORT \u2014 about five or six characters sit on one line, so `1.2M`, `340ms` and `99.98%` read as figures where `1,200,000` and `$18,400` wrap onto a second.",example:[{label:"Median query",value:"340ms",note:"p50 across all customer workloads, last 30 days."},{label:"Compute saved",value:"61%",note:"Against the warehouse spend each customer replaced."}]},{type:"image",group:"Media",node:"imageBlock",archetype:"media",version:1,countRange:[1,1],slots:["src","alt","caption"],variantSlots:["fill","on-fill","border-top","border-lead","border-trail","border-bottom","border-weight","corner","elevation"],marks:[],arrangements:[],placeholders:{caption:"Caption"},description:"One picture, with an optional caption.",whenToUse:"A photograph, screenshot or diagram that carries the point on its own. `src` is the full web address of an image that is ALREADY online \u2014 there is no upload, and a file path or a relative path is refused. `alt` describes the picture for someone who cannot see it; `caption` is printed under it and is read by everyone, so do not put the same words in both. THE EXAMPLE'S ADDRESS IS A PLACEHOLDER and serves no image: replace it with a real one, or the page renders an empty frame and the export fails.",example:[{src:"https://images.example.com/warehouse-floor.jpg",alt:"Rows of pallet racking in a distribution centre, seen from a gantry",caption:"The Rotterdam site, three weeks after cutover."}]},{type:"image-grid",group:"Media",node:"imageGrid",archetype:"media",version:1,countRange:[2,6],slots:["src","alt","caption"],variantSlots:["fill","on-fill","border-top","border-lead","border-trail","border-bottom","border-weight","corner","elevation"],marks:[],arrangements:[],placeholders:{caption:"Caption"},description:"Two to six pictures in a grid.",whenToUse:"Several pictures that belong together \u2014 a set of screenshots, product shots, or places. Each entry is its own picture with its own `src` and `alt`, exactly as `image` takes them, and there is no upload. `caption` is optional per picture and is printed under it; leave it out and the picture simply has none. The layout changes with the count, so send the pictures you mean and do not pad the list to reach a shape. THE EXAMPLE'S ADDRESSES ARE PLACEHOLDERS and serve no image: replace them with real ones, or the page renders empty frames and the export fails.",example:[{src:"https://images.example.com/rotterdam.jpg",alt:"A container crane over a quay at dusk",caption:"Rotterdam"},{src:"https://images.example.com/antwerp.jpg",alt:"Stacked containers seen from above",caption:"Antwerp"},{src:"https://images.example.com/hamburg.jpg",alt:"A freight train alongside a warehouse",caption:"Hamburg"}]},{type:"image-with-text",group:"Media",node:"imageText",archetype:"media",version:1,countRange:[1,1],slots:["src","alt","title","body","caption"],variantSlots:["fill","on-fill","border-top","border-lead","border-trail","border-bottom","border-weight","corner","elevation"],marks:[],arrangements:[],placeholders:{title:"Heading",body:"What the picture shows",caption:"Credit or place"},description:"One picture on the left, a heading and a paragraph beside it.",whenToUse:"A picture that needs explaining \u2014 a screenshot with the point spelled out, a photograph with its story. `title` is the heading beside the picture and `body` the paragraph under it; both are read as the content, so put the argument there rather than in `caption`. `caption` is optional and prints small under the picture, for a credit or a place and date. Use `image` instead when the picture carries the point on its own. THE EXAMPLE'S ADDRESS IS A PLACEHOLDER and serves no image.",example:[{src:"https://images.example.com/warehouse-floor.jpg",alt:"Rows of pallet racking in a distribution centre, seen from a gantry",title:"One site, three weeks",body:"Rotterdam went from a paper pick list to live allocation in under a month. The racking never moved; only what the floor was told to do with it changed.",caption:"Rotterdam, March."}]},{type:"table",group:"Table",node:"table",archetype:"table",version:1,countRange:[2,9],colRange:[2,6],slots:["headers","rows"],variantSlots:["fill","on-fill","border-top","border-lead","border-trail","border-bottom","border-weight","divider","divider-col","corner","elevation","head-fill","band-fill","table-mark"],marks:[],arrangements:[],placeholders:{headers:"Heading",rows:""},description:"A grid of rows and columns with a header row.",whenToUse:"Values that only make sense at the crossing of two things \u2014 a specification, a price list, a schedule, a set of measurements. `headers` is the top row of column headings and `rows` is a list of rows, each a list of cell text in the SAME ORDER as the headings; every row needs the same number of cells, and '' is a blank one. Send `headers` as an empty list for a table with no header row. Keep cells to a few words \u2014 a table is for scanning, and a sentence in a cell belongs in a `box` instead. You cannot join two cells into one: a person can do that in the editor, and if one has been joined its text belongs to the row and column it starts at, with the cells it covers left empty.",example:{headers:["","Starter","Team","Scale"],rows:[["Included seats","3","25","250"],["Query concurrency","2","8","Unmetered"],["Row-level policy","\u2014","Yes","Yes"],["Audit retention","7 days","1 year","7 years"]]}},{type:"text",group:"Text",node:"paragraph",archetype:"prose",version:1,countRange:[1,1],slots:["text"],variantSlots:[],marks:[],arrangements:[{name:"md",label:"Normal text",whenToUse:"The default. Body copy \u2014 the size everything else on the page is judged against.",countRange:[1,1]},{name:"lg",label:"Large text",whenToUse:"One opening paragraph that sets up the page, or a single sentence a page is built around. It holds about half what normal text does, so it is for a lead rather than a passage \u2014 a whole page at this size does not fit.",countRange:[1,1]},{name:"xl",label:"Display text",whenToUse:"A few words that ARE the page \u2014 a section divider, a closing line, the one sentence a deck turns on. A phrase, never a paragraph: it holds about a quarter of what large text does. Put it on a page with NO title, because at this size the block and the page heading compete and the block is the one carrying the words.",countRange:[1,1]},{name:"sm",label:"Small text",whenToUse:"A footnote, a caveat, a source line \u2014 text that must be present and must not compete. Holds more than normal, which is not a reason to reach for it: small text nobody reads is worse than text that did not fit.",countRange:[1,1]}],placeholders:{text:"Write something, or press / for a block"},description:"A paragraph.",whenToUse:"Running text \u2014 an argument, a summary, a definition. The default when the content is sentences rather than a set of parallel things. Each paragraph is its own block, so send several in one add_prose call rather than packing them into one.",example:[{kind:"text",text:"A flowing document grows without bound, so nothing can overflow and there is nothing to diagnose."}]},{type:"heading",group:"Text",node:"heading",archetype:"prose",version:1,countRange:[1,1],slots:["text"],variantSlots:[],marks:[],arrangements:[],placeholders:{text:"Heading"},description:"A heading inside the page body.",whenToUse:"Sits BELOW the page's own title, which is set with add_blank_page or set_page \u2014 use that for the title itself. This is for sectioning a long passage. `level` is 1 to 6 exactly as markdown's `#` to `######` are, and it defaults to 3 \u2014 so a document that says nothing about levels reads as it always has. Use 1 and 2 for a page that IS a section opener, and 4 to 6 only where a real outline needs the depth: they differ from each other in weight rather than size, because a 16:9 frame has no room for six visible steps.",example:[{kind:"heading",level:2,text:"Why the frame is fixed"}]},{type:"bullets",group:"Text",node:"bulletList",archetype:"prose",version:1,countRange:[2,10],slots:["text"],variantSlots:[],marks:[],arrangements:[],placeholders:{text:"List item"},description:"A bulleted list.",whenToUse:"Short parallel points that need no heading of their own \u2014 caveats, requirements, takeaways. Consecutive `bullets` lines in one add_prose call join into a single list. If each point deserves a heading AND a sentence, it is a box or steps, not a list.",example:[{kind:"bullets",text:"Read-only credentials, one source to start."},{kind:"bullets",text:"Every metric diffed until the two agree to the row."}]},{type:"numbered",group:"Text",node:"orderedList",archetype:"prose",version:1,countRange:[2,10],slots:["text"],variantSlots:[],marks:[],arrangements:[],placeholders:{text:"List item"},description:"A numbered list.",whenToUse:"A sequence where the order is the point but the steps need no separate description. If each step wants a title and a sentence, use the `steps` block instead \u2014 it is designed for it.",example:[{kind:"numbered",text:"Credentials land and the first source mirrors overnight."},{kind:"numbered",text:"Every metric is diffed until the two agree to the row."}]},{type:"quote",group:"Text",node:"quote",archetype:"prose",version:1,countRange:[1,1],slots:["text","attribution"],optional:["attribution"],variantSlots:[],marks:[],arrangements:[],placeholders:{text:"The passage",attribution:"Who said it"},description:"A pull quote and its source.",whenToUse:"One passage worth reading slowly \u2014 a customer sentence, a principle, a finding. The speaker or source goes in this block's `attribution`, NOT in a separate block: they are one thing with two parts, and nothing should have to infer which quote a source belongs to.",example:[{kind:"quote",text:"We turned off the nightly rebuild in week three and nobody noticed.",attribution:"Head of Data, a design partner"}]},{type:"people",group:"Media",node:"people",archetype:"media",version:1,countRange:[2,8],slots:["src","title","body","caption"],variantSlots:["fill","on-fill","border-top","border-lead","border-trail","border-bottom","border-weight","corner","elevation"],marks:[],arrangements:[],placeholders:{title:"Name",caption:"Their role",body:"A line about them"},description:"Two to eight people, each a portrait with a name, a role and a line.",whenToUse:"People, when there are several of them \u2014 a team, a board, a speaker line-up, the customers on a logo wall, the contributors to a release. `title` is the PERSON'S NAME; `caption` is their role or company, one short line, and it prints above the name; `body` is a sentence or two about them. Do not put the role in `body` as well \u2014 the two say different things and repeating one in the other is what makes a roster read as filler. The layout changes with the count: two or three get a wide picture and room for a paragraph, four to six a row of headshots, seven or eight a two-column list with a small thumbnail, so send the people you mean rather than padding to a shape. Use `image-with-text` for ONE person with a lot to say about them. `src` is the full web address of a photograph that is ALREADY online \u2014 there is no upload. THE EXAMPLE'S ADDRESSES ARE PLACEHOLDERS and serve no image: replace them with real ones, or the page renders empty frames and the export fails.",example:[{src:"https://images.example.com/okafor.jpg",title:"Jane Okafor",caption:"Head of Platform",body:"Ran the Rotterdam cutover, and the three before it that taught us how."},{src:"https://images.example.com/lindqvist.jpg",title:"Tomas Lindqvist",caption:"Principal Engineer",body:"Wrote the allocator. Still the person who answers when it pages."}]},{type:"checklist",group:"Text",node:"taskList",archetype:"prose",version:1,countRange:[3,10],slots:["text"],variantSlots:[],marks:[],arrangements:[],placeholders:{text:"Something to do"},description:"A list of things to tick off.",whenToUse:'Items with a DONE state \u2014 a checklist, an agenda you tick through live, acceptance criteria, a launch list. Set `checked` per line; it is the only prose block that reads it, and reading the document back and writing it unchanged preserves whatever a human ticked. Use `bullets` when nothing is ever completed and `numbered` when the ORDER is the point \u2014 a checklist implies neither sequence nor priority. Do not put "[ ]" or "done" in the text: the box is drawn and `checked` is what says so.',example:[{text:"Read-only credentials against one source",checked:!0},{text:"Every metric diffed until the two agree to the row",checked:!0},{text:"Cut the old pipeline over",checked:!1}]},{type:"youtube",group:"Media",node:"videoBlock",archetype:"media",version:1,countRange:[1,1],slots:["src","alt","caption"],variantSlots:["fill","on-fill","border-top","border-lead","border-trail","border-bottom","border-weight","corner","elevation"],marks:[],arrangements:[],placeholders:{caption:"Caption"},description:"One YouTube video, with an optional caption.",whenToUse:"A YouTube video that carries the point \u2014 a demo, a talk, a customer saying it themselves. `src` is the address of the video, copied from the browser on its own page: a 'youtube.com/watch?v=\u2026', a 'youtu.be/\u2026', a '/shorts/\u2026' or an '/embed/\u2026' address. Only YouTube, and only ONE video \u2014 a playlist address names no single video and is refused. THE PAGE DRAWS THE VIDEO'S OWN STILL FRAME, so there is no picture to find and no `poster` to send; `alt` describes the video for someone who cannot see that frame, and `caption` prints under it and is read by everyone, so do not put the same words in both. In an exported file the still frame links out to YouTube rather than playing in place. Use `image` for a picture \u2014 a YouTube address sent there is refused by name.",example:[{src:"https://www.youtube.com/watch?v=aqz-KE-bpKQ",alt:"Big Buck Bunny, the Blender Foundation's open animated short",caption:"The full short, ten minutes."}]},{type:"separator",group:"Text",node:"horizontalRule",archetype:"prose",version:1,countRange:[1,1],slots:[],variantSlots:[],marks:[],arrangements:[],placeholders:{},description:"A horizontal rule.",whenToUse:"A break between two parts of one page \u2014 markdown's `---`. It holds NO TEXT: send it as a line with a `kind` and nothing else, and `text` on it is refused rather than dropped. Use it sparingly on a page that is already a fixed frame: a rule between two paragraphs is usually a second page, and a rule above a heading is what the heading already does.",example:[{kind:"separator"}]},{type:"code",group:"Text",node:"codeBlock",archetype:"prose",version:1,countRange:[1,1],slots:["text"],variantSlots:[],marks:[],arrangements:[],placeholders:{text:"Code"},description:"A block of code, in a monospace face.",whenToUse:"Source code, a command, a configuration snippet \u2014 markdown's fenced ``` block. Newlines in `text` are real line breaks and are kept exactly, so send the code as it should read. `language` is the fence's tag (`js`, `python`, `sql`); it is stored and travels with the document, and NOTHING COLOURS IT \u2014 we ship no syntax highlighter, so the language is metadata rather than an appearance. For a word or two of code inside a sentence, use the inline code mark instead of a block of its own.",example:[{kind:"code",language:"sql",text:`select source, count(*)
|
|
2
|
+
from rows
|
|
3
|
+
group by 1;`}]},{type:"chart",group:"Charts",node:"chart",archetype:"chart",version:1,countRange:[2,11],colRange:[1,6],slots:["title","axisX","axisY"],shapesDiffer:"meaning",variantSlots:[],marks:[],arrangements:[{name:"column",label:"Column",whenToUse:"Vertical bars, one group per category. The default, and the right answer for comparing a handful of named things \u2014 revenue by product line, headcount by team. Set `stack` to `stacked` to put the series in ONE bar rather than side by side, or `proportional` to make every bar the same height and read the SHARES instead of the totals. Past eleven categories the axis starts hiding labels \u2014 use a bar, which has room for more.",countRange:[2,11]},{name:"bar",label:"Bar",whenToUse:"The same comparison lying on its side. Reach for it when the CATEGORY NAMES are long or there are many of them \u2014 a bar grows DOWN the page, so it has room for names a column chart would hide or turn on their side, and it takes half as many again before it runs out. It is also the natural shape for a RANKING, because a reader scans a list downward.",countRange:[2,15]},{name:"line",label:"Line",whenToUse:"A value followed ACROSS the categories rather than compared between them \u2014 months, quarters, versions, anything with an order a reader already knows. The line makes the SHAPE of the change the subject: what rose, what flattened, where two series crossed. Use a column chart instead when the categories have no order, because a line drawn between unordered things invents a trend. A `null` BREAKS the line rather than being drawn through, so a month nobody recorded reads as a gap and never as a measurement. Past eleven categories the axis starts hiding labels, exactly as a column chart does.",countRange:[2,11]},{name:"area",label:"Area",whenToUse:"The line with the ground under it filled in, for a total that ACCUMULATES rather than a value that merely moves \u2014 revenue by quarter, users by month, anything where the area under the curve is itself a quantity. Use a plain line when the series are being COMPARED, because two filled areas overlap and a line never does. Set `stack` to `stacked` to show the parts adding up to a whole that changes over time \u2014 the one thing on this shelf a stacked column cannot say \u2014 or `proportional` to read the SHARES instead. It inherits the line's rule about a gap: a `null` BREAKS the band rather than being drawn through. DO NOT STACK A SERIES THAT HAS GAPS: a missing value is left OUT of the total, so every band ABOVE it drops to the baseline for that one category and the picture reads as all of the series collapsing together when only one reading is absent. Fill the gap or use a plain area. Past eleven categories the axis starts hiding labels, exactly as a line and a column do.",countRange:[2,11]},{name:"pie",label:"Pie",whenToUse:"ONE series, drawn as parts of a whole. Use it only when the numbers really are shares of something and the point is that they add up \u2014 never to compare separate measures, which is what a column chart is for. A second series is REFUSED rather than quietly dropped. Past about six slices the wedges stop being tellable apart, so the count range is short on purpose; for more categories than that, use a bar.",countRange:[2,6]},{name:"donut",label:"Donut",whenToUse:"The pie with its middle removed, and it says the same thing: ONE series, drawn as parts of a whole that add up. Choose it over a pie when the slices are LABELS being read rather than areas being compared \u2014 the ring is calmer on a page and the words sit further from each other \u2014 and choose the pie when a reader has to judge one share against another, because a wedge with its point cut off is harder to compare by area. A second series is REFUSED, exactly as on a pie. DO NOT PUT THE TOTAL IN THE HOLE: nothing is drawn there on purpose, because text inside the plot would scale with the drawing instead of reflowing \u2014 put it in the `title` slot, which is ordinary text. Past about six slices the ring stops being tellable apart, so the count range is short on purpose; for more categories than that, use a bar.",countRange:[2,6]},{name:"waterfall",label:"Waterfall",whenToUse:"THE VALUES ARE STEPS, NOT TOTALS \u2014 this is the one shape on the shelf where that is true, and typing running totals into it draws the wrong picture entirely. Each bar starts where the last one ended, so `[120, 40, -25, 15]` is a balance of 120 that gains 40, loses 25 and gains 15, ending at 150. Reach for it to show how a total GOT to where it is \u2014 opening balance to closing balance, budget to actual, last year's revenue bridged to this year's \u2014 where a column chart would show the ends and hide the middle. ONE series: a second is REFUSED, because a running total has only one thread to walk. The FIRST bar rises from the baseline on its own, so type the opening balance as the first value and it draws as the full-height bar you want. There is NO automatic closing total bar \u2014 every bar is one you typed \u2014 so name the last step for what it is, or put the ending figure in the `title`. A `null` SKIPS that step and carries the total forward, so the bars after it stay where they belong. Past eleven categories the axis starts hiding labels, exactly as a column chart does.",countRange:[2,11]},{name:"heatmap",label:"Heatmap",whenToUse:"THE MATRIX THE PAYLOAD HAS BEEN ALL ALONG: one ROW per series, one COLUMN per category, and each cell shaded by its value. Reach for it when the subject is the PATTERN across two dimensions at once \u2014 which region in which quarter, which feature on which plan, where the hot corner is \u2014 and a grouped column chart would need six sets of bars to say it. The series NAMES label the rows, so name them for what a reader is scanning down. THE TONE IS RELATIVE, NEVER ABSOLUTE: the palest cell is the smallest number in the grid and the strongest is the largest, so a heatmap says which cells are high AGAINST EACH OTHER and never how high. THE CELLS DO NOT SHOW THEIR NUMBERS \u2014 use a `table` when the figures themselves are the point. DO NOT MIX POSITIVE AND NEGATIVE VALUES: one colour at varying strength has one direction, so a loss and a small gain shade alike and nothing on the page says which is which \u2014 use a column chart, where the baseline does. A `null` leaves that cell EMPTY rather than shading it, which is why an absent reading cannot be mistaken for the lowest one. At most six rows, because that is how many series the payload carries. Past eleven categories the axis starts hiding labels, exactly as a column chart does.",countRange:[2,11]}],placeholders:{title:"What this chart shows",axisX:"Category",axisY:"Measure"},description:"A chart of one or more named series over shared categories.",whenToUse:"Numbers that are COMPARED rather than listed \u2014 a trend, a split, a ranking. The payload is ONE shape for every chart: `categories` are the labels along the axis, and each entry in `series` is one named line of numbers whose `values` line up with them EXACTLY, one per category, with `null` for a gap. At most six series, because that is how many colours a theme answers for. Pick the drawing with `arrangement` and the stacking with `stack`. The title and the two axis titles are ordinary editable text and are NOT part of the payload. For numbers that are only being listed, use `table`; for two or three headline figures, use `stat-row`.",example:{categories:["Enterprise","Professional","Starter"],series:[{name:"Revenue ($M)",values:[8500,5e3,3e3]},{name:"Renewals ($M)",values:[4100,3200,900]}]}},{type:"diagram",group:"Diagrams",node:"diagram",archetype:"diagram",version:1,countRange:[1,1],slots:[],variantSlots:[],marks:[],arrangements:[],placeholders:{},description:"A diagram, written as mermaid text.",whenToUse:`A flowchart, a sequence, an org chart, a state machine, an entity diagram \u2014 anything whose meaning is in what connects to what. The payload is \`source\`: mermaid text, which is the same language GitHub and most chat clients render, and it is the ONE block here that survives markdown whole. You place nothing: the layout engine decides where every box goes, so write the RELATIONSHIPS and let it draw. THE FIRST LINE NAMES THE KIND and a wrong one is the commonest mistake, so check it first if a write is refused. The kinds worth knowing: ${$}. A refusal carries the LINE the parser objected to; fix that line rather than rewriting the diagram. Labels are TEXT \u2014 no HTML tags, and nothing that loads a picture. For a chart of NUMBERS use \`chart\`; for a handful of steps with real prose in them use \`steps\`, which is themed and reads better on a slide than a flowchart of the same three boxes.`,example:{source:`flowchart LR
|
|
4
|
+
A[Draft] --> B{Review}
|
|
5
|
+
B -->|approved| C[Publish]
|
|
6
|
+
B -->|changes| A`}}],de=e=>e.figures??[],ce=[...new Set(p.map(e=>e.archetype))],S={youtube:"YouTube"},pe=e=>{if(S[e])return S[e];const t=e.replace(/-/g," ");return t.charAt(0).toUpperCase()+t.slice(1)},ue=e=>p.find(t=>t.type===e),b=e=>p.find(t=>t.node===e),me=e=>b(e)!==void 0||e==="layout";function ge(e,t){const a=b(e.type.name);if(!a||!D(a.archetype)||e.attrs[q])return null;const o=e.attrs[B],n=o?a.arrangements.find(r=>r.name===o):a.arrangements[0],[s,i]=n?.countRange??a.countRange;return t<s?`${a.type}${o?`/${o}`:""} is designed for at least ${s} items`:t>i?`${a.type}${o?`/${o}`:""} is designed for at most ${i} items`:null}function Q(e){if(e==="road"){const t=K();return{svg:[`${w} svg`,{viewBox:`0 0 ${A.w} ${A.h}`,preserveAspectRatio:"none",class:"blk-figure-art","aria-hidden":"true"},["path",{d:t,class:"blk-figure-road"}],["path",{d:t,class:"blk-figure-lane"}]]}}if(e==="climb"){const{y0:t,y1:a}=Y();return{svg:[`${w} svg`,{viewBox:`0 0 ${E.w} ${E.h}`,preserveAspectRatio:"none",class:"blk-figure-art","aria-hidden":"true"},["path",{d:j(),class:"blk-figure-face"}],["path",{d:_(),class:"blk-figure-slope"}]],vars:`--climb-y0: ${t}; --climb-y1: ${a}`}}if(e==="core"){const{r:t,span:a,seat:o}=V();return{svg:[`${w} svg`,{viewBox:`0 0 ${c.w} ${c.h}`,preserveAspectRatio:"none",class:"blk-figure-art","aria-hidden":"true"},...X().map(n=>["ellipse",{cx:String(c.w/2),cy:String(c.h),rx:String(n.rx),ry:String(n.ry),class:"blk-figure-layer"}])],vars:`--core-r: ${t}px; --core-span: ${a}%; --core-seat: ${o}%`}}return null}function f(e,t,a,o,n){return m.create({name:e,group:"block",content:"item+",defining:!0,addAttributes:()=>({...T(a,o,b(e)?.marks??[]),...n?.length?{...z(n),...W()}:{}}),parseHTML:()=>[{tag:`ul[data-node="${e}"]`}],renderHTML:({node:s,HTMLAttributes:i})=>{const r=g(i,{"data-node":e,class:`blk ${t}`}),u=s.attrs.figure;if(!u)return["ul",r,0];const h=Q(u);if(!h)return["ul",r,0];const{style:y,"data-place":v,"data-width":l,"data-id":d,...O}=r;return["div",{class:"blk blk-figure-wrap","data-figure":u,...y?{style:y}:{},...v?{"data-place":v}:{},...l?{"data-width":l}:{},...d?{"data-id":d}:{}},["div",{class:"blk-figure-grid",...h.vars?{style:h.vars}:{}},h.svg,["ul",{...O,...l?{"data-width":l}:{},...d?{"data-id":d}:{}},0]]]}})}const we=f("box","blk-box",1,"grid"),be=f("steps","blk-steps",1,"across",G),fe=f("timeline","blk-timeline",1),ye=m.create({name:"stat",content:"statLabel? statValue statNote?",defining:!0,parseHTML:()=>[{tag:'li[data-node="stat"]'}],renderHTML:({HTMLAttributes:e})=>["li",g(e,{"data-node":"stat",class:"stat"}),0]}),ve=m.create({name:"statRow",group:"block",content:"stat+",defining:!0,addAttributes:()=>({...T(1)}),parseHTML:()=>[{tag:'ul[data-node="statRow"]'}],renderHTML:({HTMLAttributes:e})=>["ul",g(e,{"data-node":"statRow",class:"blk blk-stat-row"}),0]}),J=new Set(p.map(e=>e.node)),Z=e=>e.type.name===F?(e.attrs.categories??[]).length:H.has(e.type.name)?e.childCount:Math.max(1,e.childCount),Te=N.create({name:"countAttr",addProseMirrorPlugins(){return[new U({key:new L("countAttr"),props:{decorations(e){const t=[];return e.doc.descendants((a,o)=>{J.has(a.type.name)&&t.push(I.node(o,o+a.nodeSize,{"data-count":String(Z(a)),...C.has(a.type.name)?{"data-cols":String(M(a))}:{}}))}),P.create(e.doc,t)}}})]}});export{ce as ARCHETYPES,we as Box,p as CATALOGUE,Te as CountAttr,ye as Stat,ve as StatRow,be as Steps,fe as Timeline,pe as blockLabel,b as byNode,ue as byType,Z as countOf,de as figuresOf,me as isBlockNode,ge as shapeCountProblem};
|
package/dist/brand.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const Q="0 0 80 45",V="M5 0H75A5 5 0 0 1 80 5V40A5 5 0 0 1 75 45H5A5 5 0 0 1 0 40V5A5 5 0 0 1 5 0ZM11 12.5H51V20.5H11Z",H="0 -1005 4937 1300",M="M257 12Q189 12 139.5 -22.5Q90 -57 63.5 -119.5Q37 -182 37 -268Q37 -354 64.0 -416.5Q91 -479 140.5 -513.5Q190 -548 257 -548Q314 -548 355.5 -524.5Q397 -501 418 -460V-710H568V0H425L422 -79Q400 -36 356.5 -12.0Q313 12 257 12ZM306 -103Q342 -103 367.0 -122.0Q392 -141 405.0 -177.5Q418 -214 418 -268Q418 -323 405.0 -359.5Q392 -396 367.0 -414.5Q342 -433 306 -433Q253 -433 222.0 -388.5Q191 -344 191 -268Q191 -193 222.5 -148.0Q254 -103 306 -103ZM886.0 12Q804.0 12 743.5 -22.5Q683.0 -57 649.5 -120.0Q616.0 -183 616.0 -268Q616.0 -353 649.5 -415.5Q683.0 -478 743.0 -513.0Q803.0 -548 885.0 -548Q965.0 -548 1024.0 -513.0Q1083.0 -478 1115.5 -413.0Q1148.0 -348 1148.0 -258V-228H771.0Q774.0 -164 805.5 -133.0Q837.0 -102 889.0 -102Q927.0 -102 952.5 -118.0Q978.0 -134 989.0 -167L1140.0 -158Q1119.0 -78 1051.0 -33.0Q983.0 12 886.0 12ZM771.0 -320H994.0Q991.0 -379 961.5 -408.0Q932.0 -437 885.0 -437Q838.0 -437 807.5 -406.5Q777.0 -376 771.0 -320ZM1438.0 12Q1356.0 12 1295.0 -22.5Q1234.0 -57 1200.0 -120.0Q1166.0 -183 1166.0 -268Q1166.0 -353 1200.0 -415.5Q1234.0 -478 1295.0 -513.0Q1356.0 -548 1438.0 -548Q1509.0 -548 1565.5 -523.0Q1622.0 -498 1657.0 -451.0Q1692.0 -404 1700.0 -338L1545.0 -331Q1538.0 -381 1509.5 -406.5Q1481.0 -432 1438.0 -432Q1382.0 -432 1351.0 -389.0Q1320.0 -346 1320.0 -268Q1320.0 -190 1351.0 -146.5Q1382.0 -103 1438.0 -103Q1481.0 -103 1510.0 -129.5Q1539.0 -156 1545.0 -210L1700.0 -204Q1693.0 -138 1658.5 -89.5Q1624.0 -41 1567.5 -14.5Q1511.0 12 1438.0 12ZM1903.0 12Q1820.0 12 1767.5 -26.5Q1715.0 -65 1715.0 -134Q1715.0 -205 1759.5 -243.5Q1804.0 -282 1891.0 -300L2064.0 -334Q2064.0 -386 2040.5 -412.5Q2017.0 -439 1973.0 -439Q1930.0 -439 1906.0 -419.5Q1882.0 -400 1875.0 -362L1724.0 -369Q1739.0 -457 1803.5 -502.5Q1868.0 -548 1973.0 -548Q2093.0 -548 2153.5 -491.0Q2214.0 -434 2214.0 -324V-141Q2214.0 -118 2221.5 -110.5Q2229.0 -103 2244.0 -103H2259.0V0Q2252.0 2 2236.5 4.0Q2221.0 6 2206.0 6Q2174.0 6 2146.5 -5.0Q2119.0 -16 2102.0 -42.5Q2085.0 -69 2085.0 -118L2098.0 -108Q2088.0 -72 2062.5 -45.0Q2037.0 -18 1996.5 -3.0Q1956.0 12 1903.0 12ZM1939.0 -91Q1976.0 -91 2004.0 -105.5Q2032.0 -120 2048.0 -148.0Q2064.0 -176 2064.0 -214V-240L1942.0 -214Q1906.0 -207 1887.5 -190.5Q1869.0 -174 1869.0 -148Q1869.0 -121 1887.0 -106.0Q1905.0 -91 1939.0 -91ZM2341.0 0V-543Q2341.0 -622 2384.0 -666.0Q2427.0 -710 2517.0 -710H2632.0V-598H2550.0Q2519.0 -598 2505.0 -582.5Q2491.0 -567 2491.0 -536V0ZM2263.0 -424V-536H2624.0V-424ZM2661.0 0V-536H2803.0L2808.0 -380L2797.0 -383Q2810.0 -464 2843.0 -500.0Q2876.0 -536 2934.0 -536H2983.0V-412H2934.0Q2892.0 -412 2865.0 -401.0Q2838.0 -390 2824.5 -366.0Q2811.0 -342 2811.0 -301V0ZM3166.0 12Q3083.0 12 3030.5 -26.5Q2978.0 -65 2978.0 -134Q2978.0 -205 3022.5 -243.5Q3067.0 -282 3154.0 -300L3327.0 -334Q3327.0 -386 3303.5 -412.5Q3280.0 -439 3236.0 -439Q3193.0 -439 3169.0 -419.5Q3145.0 -400 3138.0 -362L2987.0 -369Q3002.0 -457 3066.5 -502.5Q3131.0 -548 3236.0 -548Q3356.0 -548 3416.5 -491.0Q3477.0 -434 3477.0 -324V-141Q3477.0 -118 3484.5 -110.5Q3492.0 -103 3507.0 -103H3522.0V0Q3515.0 2 3499.5 4.0Q3484.0 6 3469.0 6Q3437.0 6 3409.5 -5.0Q3382.0 -16 3365.0 -42.5Q3348.0 -69 3348.0 -118L3361.0 -108Q3351.0 -72 3325.5 -45.0Q3300.0 -18 3259.5 -3.0Q3219.0 12 3166.0 12ZM3202.0 -91Q3239.0 -91 3267.0 -105.5Q3295.0 -120 3311.0 -148.0Q3327.0 -176 3327.0 -214V-240L3205.0 -214Q3169.0 -207 3150.5 -190.5Q3132.0 -174 3132.0 -148Q3132.0 -121 3150.0 -106.0Q3168.0 -91 3202.0 -91ZM3556.0 0V-536H3691.0L3696.0 -407L3682.0 -413Q3693.0 -456 3715.5 -486.0Q3738.0 -516 3770.0 -532.0Q3802.0 -548 3840.0 -548Q3907.0 -548 3948.5 -509.0Q3990.0 -470 4002.0 -404L3983.0 -403Q3992.0 -450 4014.5 -482.5Q4037.0 -515 4070.0 -531.5Q4103.0 -548 4144.0 -548Q4200.0 -548 4240.0 -525.0Q4280.0 -502 4302.0 -456.5Q4324.0 -411 4324.0 -345V0H4174.0V-303Q4174.0 -366 4155.0 -397.5Q4136.0 -429 4093.0 -429Q4066.0 -429 4047.0 -414.0Q4028.0 -399 4017.5 -370.5Q4007.0 -342 4007.0 -301V0H3872.0V-301Q3872.0 -363 3854.0 -396.0Q3836.0 -429 3792.0 -429Q3765.0 -429 3745.5 -414.0Q3726.0 -399 3716.0 -370.0Q3706.0 -341 3706.0 -301V0ZM4639.0 12Q4557.0 12 4496.5 -22.5Q4436.0 -57 4402.5 -120.0Q4369.0 -183 4369.0 -268Q4369.0 -353 4402.5 -415.5Q4436.0 -478 4496.0 -513.0Q4556.0 -548 4638.0 -548Q4718.0 -548 4777.0 -513.0Q4836.0 -478 4868.5 -413.0Q4901.0 -348 4901.0 -258V-228H4524.0Q4527.0 -164 4558.5 -133.0Q4590.0 -102 4642.0 -102Q4680.0 -102 4705.5 -118.0Q4731.0 -134 4742.0 -167L4893.0 -158Q4872.0 -78 4804.0 -33.0Q4736.0 12 4639.0 12ZM4524.0 -320H4747.0Q4744.0 -379 4714.5 -408.0Q4685.0 -437 4638.0 -437Q4591.0 -437 4560.5 -406.5Q4530.0 -376 4524.0 -320Z";export{Q as MARK_BOX,V as MARK_PATH,H as WORDMARK_BOX,M as WORDMARK_PATH};
|
package/dist/chart.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{Node as O,mergeAttributes as R}from"@tiptap/core";import{blockAttributes as k,sizeAttributes as I}from"./design.js";import{ChartView as H}from"./chartView.js";const ne=["categories","series"],w=["var(--chart-series-1)","var(--chart-series-2)","var(--chart-series-3)","var(--chart-series-4)","var(--chart-series-5)","var(--chart-series-6)"],f=w.length,T=15,d=["column","bar","line","area","pie","donut","waterfall","heatmap"],D=!1,W=["pie","donut"],E=["pie","donut","waterfall"],ie=!0,_="waterfall",G=["column","bar","area"],g=.1,y=72,P=.6,Y=.16,m=1,le=!0;function F(e){const t=[];for(const s of e.series)for(const o of s.values)C(o)&&t.push(o);return t.length?{min:Math.min(...t),max:Math.max(...t)}:{min:0,max:1}}const x=["none","stacked","proportional"],b="stack",K="chart-plot",ce="decaframe:chart-drawn",L=620,u=e=>w[e]??"var(--fg-muted)",C=e=>typeof e=="number"&&Number.isFinite(e),S=35,A=e=>e?{animation:!0,animationDuration:L-4*S,animationEasing:"cubicOut",animationDelay:t=>Math.min(t,4)*S,animationDurationUpdate:(L-4*S)/2,animationEasingUpdate:"cubicOut"}:{animation:!1};function ue(e,t){if(!e||typeof e!="object")return"a chart takes { categories, series }";const{categories:s,series:o}=e;if(!Array.isArray(s))return"`categories` must be a list of labels";if(!Array.isArray(o))return"`series` must be a list of { name, values }";if(s.length<2)return`a chart needs at least 2 categories, not ${s.length}`;if(s.length>T)return`a chart holds at most ${T} categories, not ${s.length}`;if(s.some(r=>typeof r!="string"))return"every category must be a label string";if(!o.length)return"a chart needs at least one series";if(o.length>f)return`a chart holds at most ${f} series, not ${o.length} \u2014 that is how many colours a theme is required to answer for, so a seventh would repeat a colour`;for(const r of o){if(!r||typeof r!="object")return"every series must be { name, values }";if(typeof r.name!="string"||!r.name.trim())return"every series needs a name";if(!Array.isArray(r.values))return`series "${r.name}" has no \`values\` list`;if(r.values.length!==s.length)return`series "${r.name}" has ${r.values.length} values for ${s.length} categories \u2014 they must line up exactly; use null for a gap`;if(r.values.some(a=>a!==null&&!C(a)))return`series "${r.name}" has a value that is not a number \u2014 use null for a gap`;if(r.as!==void 0&&r.as!=="line")return`series "${r.name}" sets \`as\` to "${r.as}"; the only value is "line"`}if(t&&E.includes(t)&&o.length>1){const r=t==="waterfall"?"a waterfall walks ONE running total through its steps":`a ${t} shows how one measure splits`;return`a ${t} draws ONE series and this has ${o.length} \u2014 ${r}, so either drop the others or use a column chart to compare them`}return null}function U(e){const t=e.categories.map((s,o)=>e.series.reduce((r,a)=>r+Math.abs(a.values[o]??0),0));return e.series.map(s=>s.values.map((o,r)=>o===null||!t[r]?null:o/t[r]*100))}function X(e){const t={riser:[],up:[],down:[]},s=r=>r===0?null:r;let o=0;for(const r of e){if(r===null){t.riser.push(null),t.up.push(null),t.down.push(null);continue}const a=o;o+=r;const l=Math.min(a,o),c=Math.max(a,o),n=Math.max(l,0),i=Math.min(c,0);t.riser.push(s(n+i)),t.up.push(s(Math.max(c,0)-n)),t.down.push(s(Math.min(l,0)-i))}return t}function z(e){const t=e.series[0],s=u(0),o=X(t?.values??e.categories.map(()=>null)),r=(a,l)=>({type:"bar",name:a,stack:_,data:l,itemStyle:{color:s,borderRadius:0},emphasis:{itemStyle:{color:s,opacity:.82}},blur:{itemStyle:{color:s,opacity:.28}},barMaxWidth:56,barCategoryGap:"38%"});return[{type:"bar",name:`${t?.name??""} riser`,stack:_,data:o.riser,itemStyle:{color:"transparent"},silent:!0,barMaxWidth:56,barCategoryGap:"38%"},r(t?.name??"",o.up),r(`${t?.name??""} below`,o.down)]}function pe(e,t={}){const s=d.includes(t.kind??"")?t.kind:d[0];if(W.includes(s))return J(e,s,t.animate);if(s==="heatmap")return Q(e,t.animate);const o=s==="bar",r=x.includes(t.stack??"")&&G.includes(s)?t.stack:"none",a=r!=="none",l=r==="proportional"?U(e):e.series.map(n=>n.values),c=!E.includes(s)&&e.series.length>1;return{...A(t.animate),grid:{left:0,right:o?26:4,top:c?34:8,bottom:0,containLabel:!0},legend:c?{top:0,left:0,itemWidth:10,itemHeight:10,itemGap:18,...s==="line"||s==="area"?{}:{icon:"roundRect"},textStyle:{color:"var(--fg-muted)"}}:{show:!1},xAxis:o?M(r):h(e.categories),yAxis:o?{...h(e.categories),inverse:!0}:M(r),series:s==="waterfall"?z(e):e.series.map((n,i)=>s==="line"||s==="area"||n.as==="line"?j(n,i,l[i],{area:s==="area",stacked:s==="area"&&a}):{type:"bar",name:n.name,...a?{stack:"total"}:{},data:l[i],itemStyle:{color:u(i),borderRadius:a?0:o?[0,3,3,0]:[3,3,0,0]},emphasis:{itemStyle:{color:u(i),opacity:.82}},blur:{itemStyle:{color:u(i),opacity:.28}},barMaxWidth:56,barGap:"4%",barCategoryGap:"38%"})}}function j(e,t,s,o={}){const r=u(t),a=o.area?{areaStyle:{color:r,opacity:g}}:{};return{type:"line",name:e.name,data:s,...o.stacked?{stack:"total"}:{},...a,connectNulls:D,symbol:"circle",symbolSize:8,showSymbol:!0,lineStyle:{color:r,width:2,cap:"round",join:"round"},itemStyle:{color:r,borderColor:"var(--bg)",borderWidth:2},emphasis:{itemStyle:{color:r,borderColor:"var(--bg)",borderWidth:2},lineStyle:{color:r,width:2},...o.area?{areaStyle:{color:r,opacity:g*2}}:{}},blur:{itemStyle:{color:r,opacity:.28},lineStyle:{color:r,opacity:.28},...o.area?{areaStyle:{color:r,opacity:g*.6}}:{}}}}const B=e=>e.includes(" ")?e.split(" "):V(e);function V(e){const t=[];let s="",o=!1;for(let r=0;r<e.length;r++){const a=e[r];o?a==='"'&&e[r+1]==='"'?(s+='"',r++):a==='"'?o=!1:s+=a:a==='"'?o=!0:a===","?(t.push(s),s=""):s+=a}return t.push(s),t}function q(e){const t=e.trim();if(!t)return null;const s=/^\(.*\)$/.test(t),o=t.replace(/^\(|\)$/g,"").replace(/[$£€¥\s]/g,"").replace(/,/g,"").replace(/%$/,"");if(!/^-?\d*\.?\d+$/.test(o))return null;const r=Number(o);return Number.isFinite(r)?s?-r:r:null}function me(e){const t=e.replace(/\r\n?/g,`
|
|
2
|
+
`).split(`
|
|
3
|
+
`).filter(n=>n.trim()!=="").map(B);if(t.length<2||t[0].length<2)return null;const o=(n,i)=>(n[i]??"").trim(),r=t[0].slice(1).map((n,i)=>n.trim()||`Series ${i+1}`),a=t.slice(1),l=a.map((n,i)=>o(n,0)||`Category ${i+1}`),c=r.slice(0,f).map((n,i)=>({name:n,values:a.map(p=>q(o(p,i+1)))}));return c.some(n=>n.values.some(i=>i!==null))?{data:{categories:l,series:c},axisX:o(t[0],0)}:null}const h=e=>({type:"category",data:e,axisTick:{show:!1},axisLine:{lineStyle:{color:"var(--rule)"}},axisLabel:{color:"var(--fg-muted)",hideOverlap:!0}}),M=e=>({type:"value",...e==="proportional"?{max:100}:{},axisLine:{show:!1},axisTick:{show:!1},splitLine:{lineStyle:{color:"var(--rule)"}},axisLabel:{color:"var(--fg-muted)",...e==="proportional"?{formatter:"{value}%"}:{}}});function J(e,t,s){const o=e.series[0];return{...A(s),series:[{type:"pie",center:["50%","58%"],radius:t==="donut"?[`${y*P}%`,`${y}%`]:`${y}%`,data:e.categories.map((r,a)=>({name:r,value:o?.values[a]??null,itemStyle:{color:u(a)},emphasis:{itemStyle:{color:u(a),opacity:.9}},blur:{itemStyle:{color:u(a),opacity:.28}}})),label:{color:"var(--fg-muted)"},labelLine:{lineStyle:{color:"var(--rule)"}},emphasis:{scaleSize:6}}]}}function Q(e,t){const{min:s,max:o}=F(e),r=u(0);return{...A(t),grid:{left:0,right:4,top:8,bottom:0,containLabel:!0},xAxis:h(e.categories),yAxis:{...h(e.series.map(a=>a.name)),inverse:!0},visualMap:{show:!1,min:s,max:o,inRange:{opacity:s===o?[m,m]:[Y,m]}},series:[{type:"heatmap",itemStyle:{color:r},data:e.series.flatMap((a,l)=>e.categories.map((c,n)=>[n,l,a.values[n]??null])),emphasis:{itemStyle:{color:r,opacity:m,borderColor:"var(--fg)",borderWidth:1.5}}}]}}const $=(e,t,s)=>({[e]:{default:s,parseHTML:o=>{const r=o.getAttribute(t);if(!r)return s;try{return JSON.parse(r)}catch{return s}},renderHTML:o=>({[t]:JSON.stringify(o[e]??s)})}}),Z=()=>({[b]:{default:null,parseHTML:e=>{const t=e.getAttribute("data-stack");return t&&x.includes(t)&&t!==x[0]?t:null},renderHTML:e=>e[b]?{"data-stack":String(e[b])}:{}}}),v="chart",N={categories:[],series:[]},he=O.create({name:v,group:"block",content:"chartTitle chartAxisY chartAxisX",defining:!0,addAttributes:()=>({...k(1,d[0]),...I(),...Z(),...$("categories","data-categories",N.categories),...$("series","data-series",N.series)}),parseHTML:()=>[{tag:`figure[data-node="${v}"]`}],addNodeView(){return e=>new H(e.node)},renderHTML:({HTMLAttributes:e})=>["figure",R(e,{"data-node":v,class:"blk blk-chart"}),["div",{class:`${K}`}],["div",{class:"chart-words"},0]]});function fe(e){return{categories:e.attrs.categories??[],series:e.attrs.series??[]}}const de=e=>(e.attrs.series??[]).length;function ee(e,t={}){const s=(o,r)=>{const a=e.nodes[o];return r?.trim()?a.create(null,e.text(r)):a.create()};return[s("chartTitle",t.title),s("chartAxisY",t.y),s("chartAxisX",t.x)]}function te(e,t,s,o={},r={}){return e.nodes[t].create({...o,categories:s.categories,series:s.series},ee(e,{title:r.title,x:r.axisX,y:r.axisY}))}const re=["title","axisY","axisX"];function ge(e,t,s){re.forEach((o,r)=>{const a=s[o];if(a===void 0)return;const l=e.doc.nodeAt(t),c=l?.child(r);if(!l||!c)return;let n=t+1;for(let p=0;p<r;p++)n+=l.child(p).nodeSize;const i=a.trim()?e.doc.type.schema.text(a):null;e.replaceWith(n+1,n+c.nodeSize-1,i??[])})}function ye(e,t,s){try{return te(e,t,s).check(),!0}catch{return!1}}function xe(e,t,s){const o=e.doc.nodeAt(t);o&&e.setNodeMarkup(t,void 0,{...o.attrs,categories:s.categories,series:s.series})}export{g as AREA_FILL_OPACITY,L as CHART_ANIMATION_MS,ce as CHART_DRAWN_EVENT,d as CHART_KINDS,v as CHART_NODE,K as CHART_PLOT_CLASS,x as CHART_STACKS,D as CONNECT_NULLS,he as Chart,P as DONUT_HOLE,le as HEATMAP_NULL_IS_EMPTY,Y as HEATMAP_OPACITY_FLOOR,m as HEATMAP_OPACITY_TOP,T as MAX_CATEGORIES,f as MAX_SERIES,ne as SERIES_FIELDS,w as SERIES_TOKENS,E as SINGLE_SERIES_KINDS,G as STACKABLE_KINDS,b as STACK_ATTR,ie as WATERFALL_CARRY,_ as WATERFALL_STACK,W as WEDGE_KINDS,y as WEDGE_RADIUS,ge as applyChartText,xe as applySeries,te as blockForSeries,ee as chartChildren,pe as chartOption,F as heatmapExtent,q as parseNumber,me as parsePasted,ye as seriesBuildable,u as seriesColour,de as seriesCountOf,fe as seriesOf,ue as seriesProblem,X as waterfallBars};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DOMSerializer as d}from"@tiptap/pm/model";import{CHART_DRAWN_EVENT as l,CHART_PLOT_CLASS as u,chartOption as f,seriesOf as h,seriesProblem as p}from"./chart.js";let c=null;const a=()=>(c??=import("echarts"),c);function O(i,e){let t=null,s=!1,r=e;const o=typeof ResizeObserver>"u"?null:new ResizeObserver(()=>t?.resize());return(async()=>{const n=await a();s||(t=n.init(i,null,{renderer:"svg"}),t.setOption(r,!0),o?.observe(i))})(),{update:n=>{r=n,t?.setOption(n,!0)},dispose:()=>{s=!0,o?.disconnect(),t?.dispose(),t=null}}}const w=i=>JSON.stringify([h(i),i.attrs.arrangement,i.attrs.stack]);class y{dom;contentDOM;plot;chart=null;key="";observer=null;watcher=null;seen=!1;dead=!1;wrote=new Set;node;constructor(e){this.node=e;const t=e.type.spec.toDOM(e),{dom:s,contentDOM:r}=d.renderSpec(document,t);this.dom=s,this.contentDOM=r??null,this.plot=this.dom.querySelector(`.${u}`),this.plot.contentEditable="false",typeof ResizeObserver<"u"&&(this.observer=new ResizeObserver(()=>this.chart?.resize()),this.observer.observe(this.plot)),typeof IntersectionObserver<"u"&&(this.watcher=new IntersectionObserver(o=>{for(const n of o){if(!n.isIntersecting||!this.presenting()){this.seen=!1;continue}this.seen||(this.seen=!0,this.draw(!0))}},{threshold:.25}),this.watcher.observe(this.plot)),this.draw()}presenting(){return!!this.dom.closest("[data-presenting]")}ignoreMutation(e){return this.contentDOM?!this.contentDOM.contains(e.target):!0}update(e){return e.type!==this.node.type?!1:(this.node=e,this.syncAttrs(),this.draw(),!0)}syncAttrs(){const t=this.node.type.spec.toDOM(this.node)[1]??{};for(const[s,r]of Object.entries(t))this.dom.getAttribute(s)!==String(r)&&this.dom.setAttribute(s,String(r));for(const s of this.wrote)s in t||this.dom.removeAttribute(s);this.wrote=new Set(Object.keys(t))}destroy(){this.dead=!0,this.watcher?.disconnect(),this.observer?.disconnect(),this.chart?.dispose(),this.chart=null}async draw(e=!1){const t=w(this.node);if(t===this.key&&this.chart&&!e)return;const s=h(this.node);if(p(s)){this.chart?.dispose(),this.chart=null,this.key=t;return}const r=await a();this.dead||(this.chart??=r.init(this.plot,null,{renderer:"svg"}),e&&this.chart.clear(),this.chart.setOption(f(s,{kind:this.node.attrs.arrangement,stack:this.node.attrs.stack,animate:e}),!0),this.key=t,typeof window<"u"&&window.dispatchEvent(new Event(l)))}}export{y as ChartView,O as mountChart};
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const e=`decaframe \u2014 an agent-first visual document product
|
|
3
|
+
|
|
4
|
+
deca open [file] open a document in the editor, in a browser window. Runs until Ctrl-C
|
|
5
|
+
deca mcp run the MCP server on stdio (a CLIENT spawns this; it is not typed by hand)
|
|
6
|
+
deca help this message
|
|
7
|
+
|
|
8
|
+
A document is a .json file and that is the master copy; an exported .html is an artifact, and a
|
|
9
|
+
document may have as many as it likes. Both commands take the same paths and refuse the same ones.
|
|
10
|
+
|
|
11
|
+
Environment:
|
|
12
|
+
DECAFRAME_DOC the document file to open, default ./document.json
|
|
13
|
+
DECAFRAME_CHANNEL_PORT deca mcp only: serve the change channel on this port. deca open
|
|
14
|
+
always takes a free one, so two decks can be open at once
|
|
15
|
+
DECAFRAME_NO_BROWSER print the URL and open no window
|
|
16
|
+
|
|
17
|
+
Every diagnostic this command writes goes to stderr: stdout is the JSON-RPC stream.
|
|
18
|
+
`,[s,...t]=process.argv.slice(2);switch(s){case"mcp":t.length&&(process.stderr.write(`deca mcp takes no arguments (got ${t.join(" ")})
|
|
19
|
+
|
|
20
|
+
${e}`),process.exit(2)),(await import("./mcp/browser.js")).ensureBrowser(),await import("./mcp/stdio.js");break;case"open":{(await import("./mcp/browser.js")).ensureBrowser();const{runOpen:n}=await import("./mcp/openCli.js");await n(t);break}case void 0:case"help":case"--help":case"-h":process.stderr.write(e),process.exit(0);default:process.stderr.write(`unknown command: ${s}
|
|
21
|
+
|
|
22
|
+
${e}`),process.exit(2)}
|
package/dist/colour.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Color as n,TextStyle as s}from"@tiptap/extension-text-style";import{Highlight as a}from"@tiptap/extension-highlight";const i=["grey","red","orange","yellow","green","teal","blue","purple","pink"],r=t=>i.includes(t),d=t=>`c-${t}`,c=/^#[0-9a-f]{6}$/i,o=t=>r(t)||typeof t=="string"&&c.test(t),l=(t,e)=>r(t)?{[e]:t}:{[e]:t.toLowerCase(),style:`--c-pick: ${t.toLowerCase()}`},g=a.extend({addOptions(){return{HTMLAttributes:{},...this.parent?.(),multicolor:!0}},addAttributes(){return{color:{default:"yellow",parseHTML:t=>{const e=t.getAttribute("data-highlight");return o(e)?e.toLowerCase():"yellow"},renderHTML:t=>l(t.color,"data-highlight")}}}}),h=s.extend({parseHTML:()=>[{tag:"span[data-color]"}]}),L=n.extend({addGlobalAttributes(){return[{types:this.options.types,attributes:{color:{default:null,parseHTML:t=>{const e=t.getAttribute("data-color");return o(e)?e.toLowerCase():null},renderHTML:t=>o(t.color)?l(t.color,"data-color"):{}}}}]}});export{L as ColourMark,h as ColourStyle,g as HighlightMark,i as PALETTE,d as colourToken,o as isColourValue};
|
package/dist/commands.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Extension as se}from"@tiptap/core";import{Selection as ae}from"@tiptap/pm/state";import{ARRANGEMENT_ATTR as O,BLOCK_PLACES as D,CARRIED_DESIGN_ATTRS as F,DESIGN_ATTR as P,EMPHASIS_ATTR as C,FIGURE_ATTR as R,ICON_POSITIONS as ce,ICON_POSITION_ATTR as W,MARK_ATTR as L,MARK_ICON as ie,MARK_STARTER as fe,PLACE_ATTR as K,VARIANT_ATTR as H,WIDTH_ATTR as M,declaresSize as ue,normaliseWidth as de,sameDesign as le}from"./design.js";import{figureProblem as J,widthlessFigureBlock as pe}from"./figure.js";import{byNode as b,byType as G,isBlockNode as k}from"./blocks.js";import{ACCENT_POSITIONS as me,DOC_ATTRS as X}from"./page.js";import{instantiate as he,stampIds as ye,templateById as ge}from"./template/index.js";import{applyEntries as Te,childrenFor as Se,childTypeFor as Y,entriesBuildable as j,entriesOf as be,isEntryArchetype as U,payloadKeyFor as V}from"./archetype.js";import{LIST_NODES as Ne,TEXTLESS_NODES as ke,applyLines as Ae,blockForLines as w,linesBuildable as q,linesOf as z}from"./prose.js";import{COLUMNS_ATTR as $,applyTable as Ee,blockForTable as Oe,colsOf as Re,declaresColumns as Me,normaliseWidths as Ce,tableBuildable as we,tableOf as ze,tableProblem as _e}from"./table.js";import{CHART_KINDS as Be,CHART_STACKS as Q,STACKABLE_KINDS as Ie,STACK_ATTR as _,applyChartText as ve,applySeries as xe,blockForSeries as De,seriesBuildable as Fe,seriesOf as Pe,seriesProblem as Z}from"./chart.js";import{applyDiagram as We,blockForDiagram as Le,diagramBuildable as Ke,diagramOf as He,sourceProblem as ee}from"./diagram.js";import{mintId as S}from"./id.js";import{layoutNamed as te}from"./layout.js";const B=new Set(["page","layoutRegion"]);import{slotContent as E,slotText as I}from"./text.js";const ne=["mode","accent","surface","notes","footer","furniture"];function p(s,n){let o=null;return s.descendants((c,a)=>o?!1:c.attrs?.id===n?(o={node:c,pos:a},!1):!0),o}function Je(s,n,o){const c=s.indexOf(n);if(c<0)return s;const a=s.filter(t=>t!==n),e=o>c?o-1:o;return a.splice(e,0,n),a}function at(s){const n=b(s.type.name)?.archetype;return n==="prose"?{content:z(s)}:n==="table"?{table:ze(s)}:n==="chart"?{chart:Pe(s)}:n==="diagram"?{diagram:He(s)}:{[V(n??"")]:be(s)}}const re=(s,n)=>n[V(s)]??[];function ct(s){const n={};return s.forEach(o=>{const c=A.find(([,a])=>a===o.type.name);c&&(n[c[0]]=I(o))}),n}const A=[["eyebrow","pageEyebrow"],["title","pageTitle"],["subtitle","pageSubtitle"]],oe=new Set(A.map(([,s])=>s)),it=new Set([...oe,"pageAccent"]);function Ge(s,n,o){const c=s.doc.nodeAt(n);if(!c)return;const a=s.steps.length,{schema:e}=s.doc.type,t=new Map;let r=n+1,f=0;c.childCount&&c.child(0).type.name==="pageAccent"&&(r+=c.child(0).nodeSize,f=1);const u=r;for(;f<c.childCount;f++){const l=c.child(f);if(!oe.has(l.type.name))break;t.set(l.type.name,{node:l,pos:r}),r+=l.nodeSize}const i=r,d=new Map;for(const[l,y]of A){const g=o[l],h=g===void 0?(()=>{const N=t.get(y)?.node;return N?I(N):void 0})():g;h&&d.set(y,h)}if(A.some(([,l])=>d.has(l)!==t.has(l))){const l=A.filter(([,y])=>d.has(y)).map(([,y])=>e.nodes[y].create(null,E(e,d.get(y),y)));s.replaceWith(u,i,l);return}const m=A.filter(([,l])=>t.has(l)).map(([,l])=>l);for(let l=m.length-1;l>=0;l--){const{node:y,pos:g}=t.get(m[l]),h=d.get(m[l]);if(h===I(y))continue;const N=s.mapping.slice(a);s.replaceWith(N.map(g+1),N.map(g+y.nodeSize-1),E(e,h,m[l]))}}const ft=se.create({name:"blockCommands",addCommands(){return{setDocument:s=>({tr:n,state:o,dispatch:c})=>{const a=o.doc.attrs,e=X.filter(t=>s[t]!==void 0&&s[t]!==a[t]);if(c)for(const t of e)n.setDocAttribute(t,s[t]);return!0},applyTemplate:(s,n={})=>({tr:o,state:c,dispatch:a})=>{const e=ge(s);if(!e)return!1;const t=n.before?p(c.doc,n.before):null;if(n.before&&!t)return!1;let r;try{r=c.schema.nodeFromJSON(he(e.content))}catch{return!1}if(e.kind==="page")return r.type.name!=="page"?!1:(a&&o.insert(t?t.pos:c.doc.content.size,r),!0);if(r.type.name!=="doc"||r.childCount===0)return!1;if(a){o.replaceWith(0,c.doc.content.size,r.content);for(const f of X){const u=f==="theme"&&e.theme?e.theme:r.attrs[f];u!==void 0&&u!==c.doc.attrs[f]&&o.setDocAttribute(f,u)}}return!0},importMarkdown:(s,n,o)=>({tr:c,state:a,dispatch:e})=>{const{schema:t,doc:r}=a,f=i=>i.map(d=>{const m=t.nodeFromJSON(d);return m.check(),m});if(n){const i=p(r,n);if(!i||i.node.type.name!=="page")return!1;const d=s.flatMap(l=>l.blocks);if(!d.length)return!1;let m;try{m=f(d)}catch{return!1}if(e){const l=o?p(r,o)?.pos??i.pos+i.node.nodeSize-1:i.pos+i.node.nodeSize-1;c.insert(l,m)}return!0}if(!s.length)return!1;const u=[];try{for(const i of s){const d=[...i.accent?[t.nodes.pageAccent.create({src:i.accentSrc??null,alt:i.accentAlt??null})]:[],...i.eyebrow?[t.nodes.pageEyebrow.create(null,E(t,i.eyebrow,"pageEyebrow"))]:[],...i.title?[t.nodes.pageTitle.create(null,E(t,i.title,"pageTitle"))]:[],...i.subtitle?[t.nodes.pageSubtitle.create(null,E(t,i.subtitle,"pageSubtitle"))]:[]],m=t.nodes.page.createAndFill({id:S("page"),notes:i.notes??null,accent:i.accent??null,surface:i.surface??null,mode:i.mode??null},[...d,...f(i.blocks)]);if(!m)return!1;u.push(m)}}catch{return!1}if(e){const i=o?p(r,o)?.pos??r.content.size:r.content.size;c.insert(i,u)}return!0},setHeadingLevel:(s,n)=>({tr:o,state:c,dispatch:a})=>{const e=p(c.doc,s);return!e||!("level"in(e.node.type.spec.attrs??{}))||!Number.isInteger(n)||n<1||n>6?!1:(e.node.attrs.level===n||a&&o.setNodeMarkup(e.pos,void 0,{...e.node.attrs,level:n}),!0)},addPage:(s={})=>({tr:n,state:o,dispatch:c})=>{const{schema:a,doc:e}=o,t=s.before?p(e,s.before):null;if(s.before&&!t)return!1;const r=A.filter(([u])=>s[u]).map(([u,i])=>a.nodes[i].create(null,E(a,s[u],i))),f=a.nodes.page.createAndFill({id:S("page")},r);return f?(c&&n.insert(t?t.pos:e.content.size,f),!0):!1},setPage:(s,n)=>({tr:o,state:c,dispatch:a})=>{const e=p(c.doc,s);if(!e||e.node.type.name!=="page")return!1;if(a){const t={...e.node.attrs};for(const r of ne)n[r]!==void 0&&(t[r]=n[r]);ne.some(r=>t[r]!==e.node.attrs[r])&&o.setNodeMarkup(e.pos,void 0,t),Ge(o,e.pos,n)}return!0},setAccent:(s,n)=>({tr:o,state:c,dispatch:a})=>{const e=p(c.doc,s);if(!e||e.node.type.name!=="page")return!1;const{position:t}=n;if(t!=null&&!me.includes(t))return!1;const r=e.node.firstChild?.type.name==="pageAccent"?e.node.firstChild:null,f=e.pos+1;if(!a)return!0;if(t===null)return r&&o.delete(f,f+r.nodeSize),o.setNodeMarkup(e.pos,void 0,{...e.node.attrs,accent:null}),!0;const u={src:n.src!==void 0?n.src:r?.attrs.src??null,alt:n.alt!==void 0?n.alt:r?.attrs.alt??null,focusX:n.focusX!==void 0?n.focusX:r?.attrs.focusX??null,focusY:n.focusY!==void 0?n.focusY:r?.attrs.focusY??null,zoom:n.zoom!==void 0?n.zoom:r?.attrs.zoom??null},i=c.schema.nodes.pageAccent.create(u);r?o.replaceWith(f,f+r.nodeSize,i):o.insert(f,i);const d=t??e.node.attrs.accent??"full";return d!==e.node.attrs.accent&&o.setNodeMarkup(e.pos,void 0,{...e.node.attrs,accent:d}),!0},removePage:s=>({tr:n,state:o,dispatch:c})=>{const a=p(o.doc,s);return!a||a.node.type.name!=="page"||o.doc.childCount===1?!1:(c&&n.delete(a.pos,a.pos+a.node.nodeSize),!0)},reorderPages:s=>({tr:n,state:o,dispatch:c})=>{const a=[];o.doc.forEach(t=>a.push(t));const e=new Map(a.map(t=>[t.attrs.id,t]));if(s.length!==a.length||!s.every(t=>e.has(t)))return!1;if(s.every((t,r)=>a[r].attrs.id===t))return!0;if(c){const{$from:t}=o.selection;let r=null;for(let f=t.depth;f>=0;f--){const u=t.node(f);if(u.type.name==="page"){r={id:u.attrs.id,into:t.pos-t.before(f)};break}}if(n.replaceWith(0,o.doc.content.size,s.map(f=>e.get(f))),r){let f=-1;if(n.doc.forEach((u,i)=>{u.attrs.id===r.id&&(f=i)}),f>=0){const u=Math.min(f+r.into,n.doc.content.size);n.setSelection(ae.near(n.doc.resolve(u)))}}}return!0},addBlock:(s,n,o,c)=>({tr:a,state:e,dispatch:t})=>{const r=G(n);if(!r)return!1;const f=p(e.doc,s);if(!f||!B.has(f.node.type.name))return!1;let u;if(r.archetype==="table"){const d=o.table??{};if(!we(e.schema,r.node,d))return!1;u=Oe(e.schema,r.node,d)}else if(r.archetype==="chart"){const d=o.chart??{categories:[],series:[]};if(Z(d)||!Fe(e.schema,r.node,d))return!1;u=De(e.schema,r.node,d,{id:S(r.node),v:r.version},o.chartText)}else if(r.archetype==="diagram"){const d=o.diagram??{source:""};if(ee(d.source)||!Ke(e.schema,r.node,d))return!1;u=Le(e.schema,r.node,d,{id:S(r.node),v:r.version})}else if(U(r.archetype)){const d=re(r.archetype,o);if(!d.length)return!1;const m=Y(r.archetype);if(!j(e.schema,m,d))return!1;u=e.schema.nodes[r.node].create({id:S(r.node),v:r.version},Se(e.schema,m,d))}else{const d=o.content??[];if(!q(e.schema,r.node,d))return!1;u=w(e.schema,r.node,d)}let i=f.pos+f.node.nodeSize-1;if(c){const d=p(e.doc,c);if(!d)return!1;i=d.pos}return t&&a.insert(i,u),!0},addLayout:(s,n,o)=>({tr:c,state:a,dispatch:e})=>{const t=te(n);if(!t)return!1;const r=p(a.doc,s);if(!r||r.node.type.name!=="page")return!1;const f=a.schema.nodes.layout.create({id:S("layout"),v:1,layout:t.name},t.regions.map(i=>a.schema.nodes.layoutRegion.create({id:S("layoutRegion"),region:i.name},a.schema.nodes.paragraph.create({id:S("paragraph")}))));let u=r.pos+r.node.nodeSize-1;if(o){const i=p(a.doc,o);if(!i)return!1;u=i.pos}return e&&c.insert(u,f),!0},setLayout:(s,n)=>({tr:o,state:c,dispatch:a})=>{const e=te(n);if(!e)return!1;const t=p(c.doc,s);if(!t||t.node.type.name!=="layout")return!1;if(t.node.attrs.layout===e.name)return!0;const r=e.regions.map(()=>[]),f=e.regions.map(()=>null);t.node.forEach((i,d,m)=>{const l=Math.min(m,e.regions.length-1);i.forEach(y=>r[l].push(y)),m<e.regions.length&&(f[m]=i.attrs.id)});const u=c.schema.nodes.layout.create({...t.node.attrs,layout:e.name},e.regions.map((i,d)=>c.schema.nodes.layoutRegion.createAndFill({id:f[d]??S("layoutRegion"),region:i.name},r[d].length?r[d]:void 0)));return a&&o.replaceWith(t.pos,t.pos+t.node.nodeSize,u),!0},updateBlock:(s,n)=>({tr:o,state:c,dispatch:a})=>{const e=p(c.doc,s);if(!e)return!1;const t=b(e.node.type.name);if(!t)return!1;if(t.archetype==="table"){const i=n.table??{};return _e(i,e.node)?!1:(a&&Ee(o,e.pos,i),!0)}if(t.archetype==="diagram"){const i=n.diagram??{source:""};return ee(i.source)?!1:(a&&We(o,e.pos,i),!0)}if(t.archetype==="chart"){const i=n.chart??{categories:[],series:[]};return Z(i)?!1:(a&&(xe(o,e.pos,i),n.chartText&&ve(o,e.pos,n.chartText)),!0)}if(!U(t.archetype)){const i=n.content??[];if(!q(c.schema,t.node,i))return!1;const d=new Set(z(e.node).map(m=>m.id).filter(Boolean));return i.some(m=>m.id&&!d.has(m.id))?!1:(a&&Ae(o,e.pos,i),!0)}const r=re(t.archetype,n);if(!r.length)return!1;const f=new Set;return e.node.forEach(i=>f.add(i.attrs.id)),r.some(i=>i.id&&!f.has(i.id))||!j(c.schema,Y(t.archetype),r)||J(e.node,r.length)?!1:(a&&Te(o,e.pos,r),!0)},setEmphasis:(s,n)=>({tr:o,state:c,dispatch:a})=>{const e=p(c.doc,s);if(!e||!(C in(e.node.type.spec.attrs??{})))return!1;const t=n?!0:null;return a&&e.node.attrs[C]!==t&&o.setNodeMarkup(e.pos,void 0,{...e.node.attrs,[C]:t}),!0},setVariant:(s,n)=>({tr:o,state:c,dispatch:a})=>{const e=p(c.doc,s);if(!e||!b(e.node.type.name))return!1;const t=n||null;return a&&e.node.attrs[H]!==t&&o.setNodeMarkup(e.pos,void 0,{...e.node.attrs,[H]:t}),!0},setArrangement:(s,n)=>({tr:o,state:c,dispatch:a})=>{const e=p(c.doc,s);if(!e||!b(e.node.type.name))return!1;const t=n||null;return a&&(e.node.attrs[O]!==t||t&&e.node.attrs[R])&&o.setNodeMarkup(e.pos,void 0,{...e.node.attrs,[O]:t,...t?{[R]:null,[M]:null}:{}}),!0},setFigure:(s,n)=>({tr:o,state:c,dispatch:a})=>{const e=p(c.doc,s);if(!e)return!1;const t=b(e.node.type.name);if(!t||n&&!(t.figures??[]).some(f=>f.name===n)||n&&J({attrs:{figure:n}},e.node.childCount))return!1;const r=n||null;return a&&(e.node.attrs[R]!==r||r&&e.node.attrs[O])&&o.setNodeMarkup(e.pos,void 0,{...e.node.attrs,[R]:r,...r?{[O]:null}:{[M]:null}}),!0},setStack:(s,n)=>({tr:o,state:c,dispatch:a})=>{const e=p(c.doc,s);if(!e||!(_ in(e.node.type.spec.attrs??{})))return!1;const t=n&&n!==Q[0]?n:null;if(t&&!Q.includes(t))return!1;const r=e.node.attrs[O]??Be[0];return t&&!Ie.includes(r)?!1:(a&&e.node.attrs[_]!==t&&o.setNodeMarkup(e.pos,void 0,{...e.node.attrs,[_]:t}),!0)},setDesign:(s,n)=>({tr:o,state:c,dispatch:a})=>{const e=p(c.doc,s);if(!e||!b(e.node.type.name))return!1;const t=n&&Object.keys(n).length?n:null,r=e.node.attrs[P];return a&&!le(r,t)&&o.setNodeMarkup(e.pos,void 0,{...e.node.attrs,[P]:t}),!0},setIconPosition:(s,n)=>({tr:o,state:c,dispatch:a})=>{const e=p(c.doc,s);if(!e||!b(e.node.type.name)||n&&!ce.includes(n))return!1;const t=n||null;return a&&e.node.attrs[W]!==t&&o.setNodeMarkup(e.pos,void 0,{...e.node.attrs,[W]:t}),!0},setBlockMark:(s,n)=>({tr:o,state:c,dispatch:a})=>{const e=p(c.doc,s);if(!e)return!1;const t=b(e.node.type.name);if(!t||n&&!t.marks.slice(1).includes(n))return!1;const r=n||null;if(!a)return!0;if(e.node.attrs[L]!==r&&o.setNodeMarkup(e.pos,void 0,{...e.node.attrs,[L]:r}),r===ie){let u=e.pos+1;e.node.forEach(i=>{i.type.name==="item"&&!i.attrs.icon&&o.setNodeMarkup(u,void 0,{...i.attrs,icon:fe}),u+=i.nodeSize})}return!0},setBlockSize:(s,n,o)=>({tr:c,state:a,dispatch:e})=>{const t=p(a.doc,s);if(!t||!ue(t.node.type.spec))return!1;if(n==="width"){if(pe(t.node))return!1;const u=de(o);return e&&t.node.attrs[M]!==u&&c.setNodeMarkup(t.pos,void 0,{...t.node.attrs,[M]:u}),!0}const r=o;if(r&&!D.includes(r))return!1;const f=r&&r!==D[0]?r:null;return e&&t.node.attrs[K]!==f&&c.setNodeMarkup(t.pos,void 0,{...t.node.attrs,[K]:f}),!0},setColumnWidths:(s,n)=>({tr:o,state:c,dispatch:a})=>{const e=p(c.doc,s);if(!e||!Me(e.node.type.spec))return!1;const t=n?Ce(n,Re(e.node)):null,r=e.node.attrs[$];return JSON.stringify(r??null)===JSON.stringify(t)||a&&o.setNodeMarkup(e.pos,void 0,{...e.node.attrs,[$]:t}),!0},removeBlock:s=>({tr:n,state:o,dispatch:c})=>{const a=p(o.doc,s);return!a||!k(a.node.type.name)?!1:(c&&n.delete(a.pos,a.pos+a.node.nodeSize),!0)},duplicateBlock:s=>({tr:n,state:o,dispatch:c})=>{const a=p(o.doc,s);if(!a||!k(a.node.type.name))return!1;if(c){const e=ye(a.node.toJSON());n.insert(a.pos+a.node.nodeSize,o.schema.nodeFromJSON(e))}return!0},reorderBlocks:(s,n)=>({tr:o,state:c,dispatch:a})=>{const e=p(c.doc,s);if(!e||!B.has(e.node.type.name))return!1;const t=[],r=[];e.node.forEach(u=>(k(u.type.name)?r:t).push(u));const f=new Map(r.map(u=>[u.attrs.id,u]));return n.length!==r.length||!n.every(u=>f.has(u))?!1:(n.every((u,i)=>r[i].attrs.id===u)||a&&o.replaceWith(e.pos+1,e.pos+e.node.content.size+1,[...t,...n.map(u=>f.get(u))]),!0)},moveBlockTo:(s,n,o)=>({tr:c,state:a,dispatch:e,commands:t})=>{const r=p(a.doc,n);if(!r||!B.has(r.node.type.name))return!1;const f=p(a.doc,s);if(!f||!k(f.node.type.name))return!1;const u=a.doc.resolve(f.pos).parent;if(u.attrs.id===n){const T=[];return u.forEach(v=>{const x=v.attrs.id;x&&k(v.type.name)&&T.push(x)}),t.reorderBlocks(n,Je(T,s,o))}let i=0;u.forEach(T=>{k(T.type.name)&&i++});const d=u.type.name==="layoutRegion"&&i<=1;let m=0,l=0;r.node.forEach(T=>k(T.type.name)?l++:m++);const y=m+Math.max(0,Math.min(o,l));if(!r.node.canReplaceWith(y,y,f.node.type))return!1;if(!e)return!0;let g=r.pos+1;for(let T=0;T<y;T++)g+=r.node.child(T).nodeSize;const h=f.node,N=f.pos+h.nodeSize;return d?c.replaceWith(f.pos,N,a.schema.nodes.paragraph.create({id:S("paragraph")})):c.delete(f.pos,N),c.insert(c.mapping.map(g),h),!0},setBlockType:(s,n)=>({tr:o,state:c,dispatch:a})=>{const e=G(n);if(!e)return!1;const t=p(c.doc,s);if(!t)return!1;const r=b(t.node.type.name);if(!r)return!1;if(r.node===e.node)return!0;if(r.archetype!==e.archetype)return!1;if(!a)return!0;const f=c.schema.nodes[e.node];if(!c.doc.resolve(t.pos).parent.type.contentMatch.matchType(f))return!1;const i={id:t.node.attrs.id};for(const h of F)i[h]=t.node.attrs[h]??null;if(f.validContent(t.node.content))return o.setNodeMarkup(t.pos,c.schema.nodes[e.node],{...i,v:e.version}),!0;const d=z(t.node),m=h=>ke.has(e.node)?{}:e.node==="quote"?h:{text:h.text},l=Ne.has(e.node)?[w(c.schema,e.node,d)]:d.map(h=>w(c.schema,e.node,[m(h)])),y=Object.fromEntries(F.filter(h=>i[h]!=null).map(h=>[h,i[h]])),g=Object.keys(y).length?l.map(h=>h.type.create({...h.attrs,...y},h.content)):l;return o.replaceWith(t.pos,t.pos+t.node.nodeSize,g),!0}}}});export{ft as BlockCommands,it as NOT_CONTENT,ne as PAGE_ATTRS,ct as chromeOf,p as findById,Je as moveTo,at as propsOf};
|
package/dist/design.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{versionAttribute as b}from"./id.js";import{VARIANT_SLOTS as M,VARIANT_SLOT_SPECS as i}from"./theme/emit.js";const d="emphasis",s="variant",T="arrangement",R="figure",a="design",u="iconPosition",S=["top","lead","none"],A="mark",P=["numeral","dot","icon","none"],j="none",K="icon",G="flag",x="off",c=t=>i[t]?[...i[t].accepts,x]:[];function F(t,e){for(const[n,r]of Object.entries(t)){if(!i[n])return`unknown design slot "${n}"`;if(!e.includes(n))return`this block has no "${n}" to set`;if(!c(n).includes(r))return`"${n}" cannot be "${r}". It takes: ${c(n).join(", ")}`}return null}function _(t){return f(t).map(e=>t[e]===x?`--${e}: initial; --${e}-on: 0`:`--${e}: var(--${t[e]}); --${e}-on: 1`).join("; ")}const f=t=>M.filter(e=>e in t),l=t=>f(t).map(e=>`${e}=${t[e]}`).join(" "),w=(t,e)=>(t?l(t):"")===(e?l(e):"");function L(t){if(!t)return null;const e={};for(const n of t.trim().split(/\s+/)){const[r,o]=n.split("=");r&&o&&i[r]&&c(r).includes(o)&&(e[r]=o)}return Object.keys(e).length?e:null}const I=()=>({[a]:{default:null,parseHTML:t=>L(t.getAttribute("data-design")),renderHTML:t=>{const e=t[a];return!e||!Object.keys(e).length?{}:{"data-design":l(e),style:_(e)}}}}),z=()=>({[d]:{default:null,parseHTML:t=>t.hasAttribute("data-emphasis")?!0:null,renderHTML:t=>t[d]?{"data-emphasis":"true"}:{}}}),H=()=>({[s]:{default:null,parseHTML:t=>t.getAttribute("data-variant")||null,renderHTML:t=>t[s]?{"data-variant":String(t[s])}:{}}}),O=t=>({[T]:{default:null,parseHTML:e=>e.getAttribute("data-arrangement")||null,renderHTML:e=>{if(e[R])return{};const n=e[T]??t;return n?{"data-arrangement":String(n)}:{}}}}),N=()=>({[u]:{default:null,parseHTML:t=>{const e=t.getAttribute("data-icon-position");return e&&S.includes(e)?e:null},renderHTML:t=>t[u]?{"data-icon-position":String(t[u])}:{}}}),p="width",h="place",$=["start","centre","end"],g=100,E=20,k=t=>{if(typeof t!="number"||!Number.isFinite(t)||t<=0)return null;const e=Math.min(g,Math.max(E,t)),n=Math.round(e*10)/10;return n>=g?null:n},m=(t,e,n)=>({[t]:{default:null,parseHTML:r=>{const o=r.getAttribute(e);return o&&o!==n[0]&&n.includes(o)?o:null},renderHTML:r=>r[t]?{[e]:String(r[t])}:{}}}),v=()=>({[p]:{default:null,parseHTML:t=>k(Number(t.getAttribute("data-width"))),renderHTML:t=>{const e=t[p];return e?{"data-width":String(e),style:`inline-size: ${e}%`}:{}}}}),W=()=>({...v(),...m(h,"data-place",$)}),V=t=>!!t?.attrs&&p in t.attrs,y=t=>m(A,"data-mark",t),B=t=>!!t?.attrs&&A in t.attrs,U=(t,e,n=[])=>({...b(t),...H(),...O(e),...I(),...N(),...n.length?y(n):{}}),q=[s,a],J=(t,e)=>{if(!t)return{};const n={};for(const[r,o]of Object.entries(t))r==="id"||r==="v"||e.includes(r)||o!=null&&(n[r]=o);return n};export{T as ARRANGEMENT_ATTR,P as BLOCK_MARKS,$ as BLOCK_PLACES,q as CARRIED_DESIGN_ATTRS,a as DESIGN_ATTR,d as EMPHASIS_ATTR,R as FIGURE_ATTR,S as ICON_POSITIONS,u as ICON_POSITION_ATTR,A as MARK_ATTR,K as MARK_ICON,j as MARK_NONE,G as MARK_STARTER,E as MIN_WIDTH,h as PLACE_ATTR,x as SLOT_OFF,s as VARIANT_ATTR,p as WIDTH_ATTR,g as WIDTH_FULL,O as arrangementAttribute,U as blockAttributes,J as carryDesign,B as declaresMark,V as declaresSize,I as designAttribute,F as designProblem,_ as designStyle,z as emphasisAttribute,N as iconPositionAttribute,y as markAttribute,k as normaliseWidth,L as parseDesign,w as sameDesign,l as serializeDesign,W as sizeAttributes,c as slotAccepts,H as variantAttribute};
|
package/dist/diagram.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import{Node as c,mergeAttributes as l}from"@tiptap/core";import{blockAttributes as d,sizeAttributes as u}from"./design.js";import{DiagramView as m}from"./diagramView.js";const C=["source"],M=["mermaid"],h="diagram-drawing",S="decaframe:diagram-drawn",p=["img","image","picture","source","video","audio","iframe","object","embed","link","script","input","use","track","applet","frame","frameset","base","meta"],f=new RegExp(`<\\s*/?\\s*(${p.join("|")})\\b`,"i"),g=/url\s*\(\s*['"]?\s*(?!#)/i,b=/themeCSS/i,w=/\bon[a-z]+\s*=/i;function A(e){const t=e.split(`
|
|
2
|
+
`);let a=0;if(t[0]?.trim()==="---"){for(a=1;a<t.length&&t[a].trim()!=="---";)a++;a++}const n=[];let i=!1;for(;a<t.length;a++){const r=t[a].trim();if(!(!r||r.startsWith("%%"))){if(!i){i=!0;continue}n.push(r)}}return n}function L(e){if(typeof e!="string")return"a diagram's 'source' must be a string of mermaid text.";const t=e.trim();if(!t)return"a diagram's 'source' is empty. It takes mermaid text, which starts with the kind of diagram you want \u2014 for example 'flowchart TD' followed by lines like 'A[Start] --> B[End]'.";const a=t.match(f);return a?`a diagram's 'source' may not contain '<${a[1]}>'. A label is text, not markup: a tag that loads something would make every reader of the exported file fetch it. Plain text, '<br/>' for a line break, and '<b>'/'<i>' for emphasis are all fine.`:g.test(t)?"a diagram's 'source' may not contain 'url(...)' \u2014 that makes every reader of the exported file fetch whatever it names. Use plain text in labels.":b.test(t)?"a diagram's 'source' may not carry a 'themeCSS' directive. The theme paints every diagram, so a stylesheet in the source has nothing to say \u2014 and it is where a reader of the exported file can be made to fetch an address.":w.test(t)?"a diagram's 'source' may not contain an event handler attribute such as 'onclick'. Labels are text; a diagram has no behaviour of its own.":A(t).length?null:"a diagram's 'source' names a kind of diagram but has nothing in it. 'flowchart TD' on its own is valid mermaid and draws an empty picture \u2014 add the nodes, for example 'A[Start] --> B[End]'."}function P(e,t){return t===null?e:e.replace(/^Parse error on line \d+:/,`Parse error on line ${t}:`)}const F="flowchart TD (or LR) for a process, sequenceDiagram for an exchange over time, stateDiagram-v2 for states and transitions, erDiagram for things and how they relate, mindmap for one idea and its branches, gantt for bars on a calendar, quadrantChart, timeline, kanban, block-beta and venn-beta";function D(e){const t=e.trim();if(!t)return null;const n=(t.startsWith("---")?t.slice(t.indexOf(`
|
|
3
|
+
---`,3)+4):t).split(`
|
|
4
|
+
`).map(r=>r.trim()).find(r=>r&&!r.startsWith("%%"));return n&&n.split(/[\s:{(-]/)[0]?.toLowerCase()||null}const x={gantt:"a gantt chart draws at a fixed width whatever it holds, so on a slide its dates end up around 7px. Consider fewer tasks, or a `timeline` block.",packet:"a packet diagram is very wide and short, so its labels land around 10px on a slide.",treemap:"a treemap puts its smallest labels around 10px on a slide.",erdiagram:"an entity diagram grows tall, so on a slide its type names land around 12px.",quadrantchart:"a quadrant chart puts its axis labels around 14px on a slide."},I=e=>{const t=D(e);return t?x[t]??null:null},o="diagram",v=()=>({zoom:{default:null,parseHTML:e=>{const t=Number(e.getAttribute("data-zoom"));return Number.isFinite(t)&&t>0&&t!==1?t:null},renderHTML:e=>e.zoom?{"data-zoom":String(e.zoom)}:{}}}),k=()=>({source:{default:"",parseHTML:e=>e.getAttribute("data-source")??"",renderHTML:e=>({"data-source":String(e.source??"")})}}),N=c.create({name:o,group:"block",content:"",atom:!0,selectable:!0,defining:!0,addAttributes:()=>({...d(1),...u(),...k(),...v()}),parseHTML:()=>[{tag:`figure[data-node="${o}"]`}],addNodeView(){return e=>new m(e.node,e.view,e.getPos)},renderHTML:({HTMLAttributes:e})=>["figure",l(e,{"data-node":o,class:"blk blk-diagram"}),["div",{class:h}]]}),_=e=>({source:e.attrs.source??""});function E(e,t,a,n={}){return e.nodes[t].create({...n,source:a.source})}function G(e,t,a){try{return E(e,t,a).check(),!0}catch{return!1}}function O(e,t,a){const n=e.doc.nodeAt(t);n&&e.setNodeMarkup(t,void 0,{...n.attrs,source:a.source})}const s={flowchart:{label:"Flowchart",claim:"A process with a decision in it, read left to right",source:`flowchart LR
|
|
5
|
+
A[Draft] --> B{Review}
|
|
6
|
+
B -->|approved| C[Publish]
|
|
7
|
+
B -->|changes| A`},orgchart:{label:"Org chart",claim:"Who reports to whom, read top down",source:`flowchart TD
|
|
8
|
+
CEO[Chief Executive] --> ENG[Engineering]
|
|
9
|
+
CEO --> FIN[Finance]
|
|
10
|
+
CEO --> MKT[Marketing]
|
|
11
|
+
ENG --> PLAT[Platform]
|
|
12
|
+
ENG --> PROD[Product]`},sequence:{label:"Sequence",claim:"Who says what to whom, with time running down the page",source:`sequenceDiagram
|
|
13
|
+
participant U as Person
|
|
14
|
+
participant A as Agent
|
|
15
|
+
participant D as Document
|
|
16
|
+
U->>A: describe the deck
|
|
17
|
+
A->>D: write the pages
|
|
18
|
+
D-->>U: ready to edit`},state:{label:"States",claim:"What a thing can be, and what moves it between those states",source:`stateDiagram-v2
|
|
19
|
+
[*] --> Draft
|
|
20
|
+
Draft --> Review: submit
|
|
21
|
+
Review --> Draft: changes
|
|
22
|
+
Review --> Published: approve
|
|
23
|
+
Published --> [*]`},mindmap:{label:"Mind map",claim:"One idea and everything hanging off it",source:`mindmap
|
|
24
|
+
root((Launch))
|
|
25
|
+
Product
|
|
26
|
+
Pricing
|
|
27
|
+
Onboarding
|
|
28
|
+
Market
|
|
29
|
+
Segments
|
|
30
|
+
Team`},kanban:{label:"Kanban",claim:"Columns of cards: waiting, moving, done",source:`kanban
|
|
31
|
+
Todo
|
|
32
|
+
t1[Write the brief]
|
|
33
|
+
t2[Pick a theme]
|
|
34
|
+
Doing
|
|
35
|
+
t3[Draft the deck]
|
|
36
|
+
Done
|
|
37
|
+
t4[Agree the scope]`},block:{label:"Blocks",claim:"Boxes filling a grid, where the layout is the claim",source:`block-beta
|
|
38
|
+
columns 3
|
|
39
|
+
a["Editor"] b["MCP server"] c["Document"]
|
|
40
|
+
d["Themes"]:3`},quadrant:{label:"Quadrant",claim:"Two axes, and where things fall between them",source:`quadrantChart
|
|
41
|
+
title Effort against value
|
|
42
|
+
x-axis Low effort --> High effort
|
|
43
|
+
y-axis Low value --> High value
|
|
44
|
+
Charts: [0.7, 0.8]
|
|
45
|
+
Diagrams: [0.6, 0.9]
|
|
46
|
+
Theme builder: [0.8, 0.4]`},timeline:{label:"Timeline",claim:"Eras and what happened in each",source:`timeline
|
|
47
|
+
title How the year went
|
|
48
|
+
Q1 : Research : First prototype
|
|
49
|
+
Q2 : Private beta
|
|
50
|
+
Q3 : Launch : First customers`},venn:{label:"Venn",claim:"Overlapping sets, and what they share",source:`venn-beta
|
|
51
|
+
title What we do well
|
|
52
|
+
set Fast
|
|
53
|
+
set Cheap
|
|
54
|
+
set Good
|
|
55
|
+
union Fast, Cheap
|
|
56
|
+
union Cheap, Good
|
|
57
|
+
union Fast, Good
|
|
58
|
+
union Fast, Cheap, Good`},gantt:{label:"Gantt",claim:"Bars on a calendar; its dates read small on a slide",source:`gantt
|
|
59
|
+
title Release
|
|
60
|
+
dateFormat YYYY-MM-DD
|
|
61
|
+
axisFormat %b %d
|
|
62
|
+
section Build
|
|
63
|
+
Schema :a1, 2026-01-05, 18d
|
|
64
|
+
Renderer :after a1, 14d
|
|
65
|
+
section Ship
|
|
66
|
+
Docs :2026-02-09, 10d`},entity:{label:"Entities",claim:"Things, and how many of each connects to how many of the other",source:`erDiagram
|
|
67
|
+
CUSTOMER ||--o{ ORDER : places
|
|
68
|
+
ORDER ||--|{ LINE_ITEM : contains
|
|
69
|
+
PRODUCT ||--o{ LINE_ITEM : "appears in"`},swimlanes:{label:"Swimlanes",claim:"A process that crosses teams, one lane each",source:`swimlane-beta
|
|
70
|
+
subgraph Customer
|
|
71
|
+
A[Places the order]
|
|
72
|
+
end
|
|
73
|
+
subgraph Warehouse
|
|
74
|
+
B[Picks the items]
|
|
75
|
+
C[Packs the box]
|
|
76
|
+
end
|
|
77
|
+
subgraph Courier
|
|
78
|
+
D[Delivers it]
|
|
79
|
+
end
|
|
80
|
+
A --> B --> C --> D`},architecture:{label:"Architecture",claim:"Services inside groups, wired side to side",source:`architecture-beta
|
|
81
|
+
group app(cloud)[Application]
|
|
82
|
+
service editor(server)[Editor] in app
|
|
83
|
+
service mcp(server)[MCP server] in app
|
|
84
|
+
service doc(disk)[Document] in app
|
|
85
|
+
editor:R -- L:mcp
|
|
86
|
+
mcp:R -- L:doc`},treeview:{label:"Tree view",claim:"What contains what, as a file tree",source:`treeView-beta
|
|
87
|
+
packages
|
|
88
|
+
blocks
|
|
89
|
+
diagram.ts
|
|
90
|
+
theme.ts
|
|
91
|
+
mcp
|
|
92
|
+
server.ts
|
|
93
|
+
apps
|
|
94
|
+
editor`},cynefin:{label:"Cynefin",claim:"Which kind of problem each thing is, on the sense-making frame",source:`cynefin-beta
|
|
95
|
+
title Where the work sits
|
|
96
|
+
clear "Export the deck"
|
|
97
|
+
complicated "Theme builder"
|
|
98
|
+
complex "Agent runs"
|
|
99
|
+
chaotic "A live incident"`}},H=e=>e&&s[e]?.source||s.flowchart.source;export{x as CRAMPED_FAMILIES,h as DIAGRAM_DRAWING_CLASS,S as DIAGRAM_DRAWN_EVENT,C as DIAGRAM_FIELDS,F as DIAGRAM_KINDS,o as DIAGRAM_NODE,s as DIAGRAM_STARTERS,M as DIAGRAM_TYPES,N as Diagram,O as applyDiagram,E as blockForDiagram,I as crampedHint,G as diagramBuildable,D as diagramFamily,_ as diagramOf,P as restateLine,L as sourceProblem,H as starterSource};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function y(l,r){const o=getComputedStyle(l),n=[];for(const a of r){const i=o.getPropertyValue(`--${a}`).trim();if(!i)return null;n.push(i)}const s=document.createElement("canvas");s.width=1,s.height=1;const e=s.getContext("2d",{willReadFrequently:!0}),t={};try{if(!e)return null;for(const[a,i]of r.entries()){if(e.clearRect(0,0,1,1),e.fillStyle="#000000",e.fillStyle=n[a],e.fillStyle==="#000000"&&!/^#000000$|^black$|^rgb\(0, ?0, ?0\)$/.test(n[a]))return null;e.fillRect(0,0,1,1);const[c,u,m,f]=e.getImageData(0,0,1,1).data;if(f!==255)return null;t[i]=`#${[c,u,m].map(d=>d.toString(16).padStart(2,"0")).join("")}`}}catch{return null}return t}const g=(l,r,o)=>({startOnLoad:!1,securityLevel:"strict",theme:o?"base":l==="dark"?"dark":"base",htmlLabels:!1,flowchart:{htmlLabels:!1},class:{htmlLabels:!1},fontFamily:r,...o?{themeVariables:o}:{}}),b=["img","image","iframe","object","embed","video","audio","source","link","script","use","foreignObject","set","animate","feImage"],v=["href","xlink:href","src","srcset","data","poster"];function p(l,r=b,o=v){const n=new DOMParser().parseFromString(l,"image/svg+xml"),s=n.documentElement;for(const e of r)for(const t of[...n.querySelectorAll(e)])t.remove();for(const e of[...n.querySelectorAll("*")])for(const t of[...e.attributes]){const a=/^\s*(?:https?:|\/\/|data:(?!image\/svg))/i.test(t.value);(o.includes(t.name)&&a||/url\s*\(\s*['"]?\s*(?:https?:|\/\/)/i.test(t.value)||/^on[a-z]+$/i.test(t.name))&&e.removeAttribute(t.name)}for(const e of[...n.querySelectorAll("style")]){const t=e.textContent??"",a=t.replace(/@import[^;]*;?/gi,"").replace(/url\s*\(\s*['"]?\s*(?!#)[^)]*\)/gi,"none");a!==t&&(e.textContent=a)}return s.removeAttribute("width"),s.removeAttribute("height"),s.removeAttribute("style"),s.setAttribute("preserveAspectRatio","xMidYMid meet"),new XMLSerializer().serializeToString(s)}async function h(l,r){const o=(await import("mermaid")).default;o.initialize(g(r.mode,r.fontFamily,r.themeVariables));const{svg:n}=await o.render(r.id,l);return p(n)}export{b as FETCHING_ELEMENTS,v as URL_BEARING_ATTRS,p as cleanSvg,g as diagramConfig,h as drawDiagram,y as resolveRoles};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const E=["bg","bg-subtle","fg","fg-muted","fg-faint","rule","rule-strong","accent","c-red","chart-series-1","chart-series-2","chart-series-3","chart-series-4","chart-series-5","chart-series-6"];function j(e,a){const t=e.palettes[a]??{},l={};for(const o of E){const r=t[o]??e.tokens[o];r!=null&&(l[o]=String(typeof r=="object"?r.srgb??"":r))}return l}const L=(e,a=0,t=1)=>Math.min(t,Math.max(a,e));function T(e){const a=e.replace("#",""),t=a.length===3?a.split("").map(d=>d+d).join(""):a,[l,o,r]=[0,2,4].map(d=>{const g=parseInt(t.slice(d,d+2),16)/255;return g<=.04045?g/12.92:((g+.055)/1.055)**2.4}),s=Math.cbrt(.4122214708*l+.5363325363*o+.0514459929*r),n=Math.cbrt(.2119034982*l+.6806995451*o+.1073969566*r),i=Math.cbrt(.0883024619*l+.2817188376*o+.6299787005*r);return{l:.2104542553*s+.793617785*n-.0040720468*i,a:1.9779984951*s-2.428592205*n+.4505937099*i,b:.0259040371*s+.7827717662*n-.808675766*i}}function y(e){const{l:a,a:t,b:l}=T(e);return{l:a,c:Math.hypot(t,l),h:Math.atan2(l,t)*180/Math.PI}}function F({l:e,a,b:t}){const l=(e+.3963377774*a+.2158037573*t)**3,o=(e-.1055613458*a-.0638541728*t)**3,r=(e-.0894841775*a-1.291485548*t)**3;return`#${[4.0767416621*l-3.3077115913*o+.2309699292*r,-1.2684380046*l+2.6097574011*o-.3413193965*r,-.0041960863*l-.7034186147*o+1.707614701*r].map(n=>{const i=n<=.0031308?12.92*n:1.055*L(n)**.4166666666666667-.055;return Math.round(L(i)*255).toString(16).padStart(2,"0")}).join("")}`}const q=({l:e,c:a,h:t})=>F({l:e,a:a*Math.cos(t*Math.PI/180),b:a*Math.sin(t*Math.PI/180)}),f=e=>T(e).l;function p(e,a,t){const l=T(e),o=T(a),r=(s,n)=>s+(n-s)*t;return F({l:r(o.l,l.l),a:r(o.a,l.a),b:r(o.b,l.b)})}const O=(e,a)=>{const{l:t,c:l,h:o}=y(e);return q({l:L(t+a),c:l,h:o})},M=(e,a,t)=>Math.abs(f(e)-f(a))>Math.abs(f(e)-f(t))?a:t;function w(e){const a=e.map(y),t=a.map((l,o)=>{const r=a[(o+1)%a.length];let s=(r.h-l.h+540)%360-180;return Math.abs(s)<1&&(s=180),q({l:(l.l+r.l)/2,c:(l.c+r.c)/2,h:l.h+s/2})});return[...e,...t]}function I(e,a){const t=e.bg,l=e["bg-subtle"],o=e.fg,r=e["fg-muted"],s=e["fg-faint"],n=e.rule,i=e["rule-strong"],d=e.accent,g=e["c-red"],C=c=>p(o,t,c),k=C(.04),h=C(.02),S=C(.07),u=w([1,2,3,4,5,6].map(c=>e[`chart-series-${c}`])),m=u.map(c=>M(c,o,t)),B=u.map(c=>O(c,a?.09:-.09)),x=(c,b)=>Object.fromEntries(b.map((v,A)=>[`${c}${A}`,v]));return{darkMode:a,background:t,primaryColor:l,secondaryColor:k,tertiaryColor:h,primaryBorderColor:i,secondaryBorderColor:n,tertiaryBorderColor:n,primaryTextColor:o,secondaryTextColor:o,tertiaryTextColor:o,textColor:o,titleColor:o,border2:n,lineColor:r,arrowheadColor:r,defaultLinkColor:r,edgeLabelBackground:t,errorBkgColor:p(g,t,.12),errorTextColor:g,mainBkg:l,nodeBkg:l,nodeBorder:i,nodeTextColor:o,classText:o,clusterBkg:h,clusterBorder:n,actorBkg:l,actorBorder:i,actorTextColor:o,actorLineColor:s,signalColor:r,signalTextColor:o,labelBoxBkgColor:l,labelBoxBorderColor:i,labelTextColor:o,loopTextColor:o,activationBkgColor:k,activationBorderColor:i,noteBkgColor:p(d,t,.1),noteBorderColor:p(d,t,.36),noteTextColor:o,sequenceNumberColor:M(r,o,t),stateBkg:l,stateLabelColor:o,labelBackgroundColor:t,transitionColor:r,transitionLabelColor:o,compositeBackground:h,compositeTitleBackground:l,compositeBorder:n,altBackground:k,specialStateColor:o,innerEndBackground:t,...x("cScale",u),...x("cScaleInv",B),...x("cScaleLabel",m),...x("cScalePeer",B),scaleLabelColor:o,...x("git",u.slice(0,8)),...x("gitInv",B.slice(0,8)),...x("gitBranchLabel",m.slice(0,8)),branchLabelColor:m[0],commitLabelColor:o,commitLabelBackground:t,tagLabelColor:o,tagLabelBackground:l,tagLabelBorder:i,...Object.fromEntries(u.slice(0,8).map((c,b)=>[`venn${b+1}`,c])),vennTitleTextColor:o,vennSetTextColor:o,quadrant1Fill:C(.035),quadrant2Fill:C(.075),quadrant3Fill:C(.115),quadrant4Fill:C(.155),quadrant1TextFill:o,quadrant2TextFill:o,quadrant3TextFill:o,quadrant4TextFill:o,quadrantPointFill:d,quadrantPointTextFill:o,quadrantXAxisTextFill:r,quadrantYAxisTextFill:r,quadrantInternalBorderStrokeFill:n,quadrantExternalBorderStrokeFill:i,quadrantTitleFill:o,sectionBkgColor:h,sectionBkgColor2:k,altSectionBkgColor:t,excludeBkgColor:S,gridColor:n,vertLineColor:s,taskBkgColor:u[0],taskBorderColor:B[0],activeTaskBkgColor:u[2],activeTaskBorderColor:B[2],doneTaskBkgColor:S,doneTaskBorderColor:i,critBkgColor:p(g,t,.75),critBorderColor:g,todayLineColor:g,taskTextColor:m[0],taskTextDarkColor:o,taskTextLightColor:t,taskTextOutsideColor:o,taskTextClickableColor:d,rowOdd:t,rowEven:h,attributeBackgroundColorOdd:t,attributeBackgroundColorEven:h,treeView:{labelFontSize:"16px",labelColor:o,lineColor:r,iconColor:r,descriptionColor:r,highlightBg:p(d,t,.14),highlightStroke:d},cynefin:{domainFontSize:22,itemFontSize:19,boundaryColor:n,boundaryWidth:2,cliffColor:g,cliffWidth:4,arrowColor:r,arrowWidth:2,clearBg:C(.1),complicatedBg:C(.17),complexBg:C(.24),chaoticBg:C(.31),confusionBg:C(.22),textColor:o,labelColor:o},requirementBackground:l,requirementBorderColor:i,requirementTextColor:o,relationColor:r,relationLabelBackground:t,relationLabelColor:o,...Object.fromEntries(u.map((c,b)=>[`pie${b+1}`,c])),pieTitleTextColor:o,pieSectionTextColor:o,pieLegendTextColor:o,pieStrokeColor:t,pieOuterStrokeColor:n,pieOpacity:"1",...Object.fromEntries(u.slice(0,8).map((c,b)=>[`fillType${b}`,c])),archEdgeColor:r,archEdgeArrowColor:r,archGroupBorderColor:n,xyChart:{backgroundColor:t,titleColor:o,dataLabelColor:o,xAxisTitleColor:o,xAxisLabelColor:r,xAxisTickColor:n,xAxisLineColor:n,yAxisTitleColor:o,yAxisLabelColor:r,yAxisTickColor:n,yAxisLineColor:n,plotColorPalette:u.join(",")},...x("surface",[.03,.05,.07,.09,.11].map(C)),...x("surfacePeer",[.09,.11,.13,.15,.17].map(C)),useGradient:!1,dropShadow:a?"none":`drop-shadow(0 1px 2px ${p(o,t,.18)})`,gradientStart:i,gradientStop:n,fontWeight:"normal",noteFontWeight:"normal"}}export{E as DIAGRAM_TOKENS,w as categorical,I as diagramTheme,j as diagramVars,T as hexToLab,y as hexToLch,F as labToHex,q as lchToHex,f as lightnessOf,p as mix,M as onFill,O as step};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DOMSerializer as c}from"@tiptap/pm/model";import{DIAGRAM_DRAWING_CLASS as h,DIAGRAM_DRAWN_EVENT as u,diagramOf as f,restateLine as l,sourceProblem as p}from"./diagram.js";import{drawDiagram as g,resolveRoles as w}from"./diagramRender.js";import{DIAGRAM_TOKENS as y,diagramTheme as b}from"./diagramTheme.js";import{attachZoom as A}from"./diagramZoom.js";let v=0;const M=64,r=new Map,O=(s,t)=>{r.delete(s),r.set(s,t),r.size>M&&r.delete(r.keys().next().value)},D=s=>s.closest("[data-mode]")?.getAttribute("data-mode")??"light",S=s=>typeof getComputedStyle>"u"?"sans-serif":getComputedStyle(s).fontFamily||"sans-serif",E=s=>typeof document>"u"?null:w(s,y);class R{dom;contentDOM;drawing;key="";dead=!1;modes=null;zoom=null;node;view;getPos;wrote=new Set;constructor(t,e,o){this.node=t,this.view=e,this.getPos=o;const n=t.type.spec.toDOM(t),{dom:i,contentDOM:d}=c.renderSpec(document,n);this.dom=i,this.contentDOM=d??null,this.drawing=this.dom.querySelector(`.${h}`),this.drawing.contentEditable="false",typeof document<"u"&&(this.zoom=A(this.drawing,this.dom,{initial:this.node.attrs.zoom??1,onZoom:a=>this.storeZoom(a)})),queueMicrotask(()=>this.mount())}mount(){if(this.dead)return;const t=[...new Set([this.dom.closest("[data-mode]"),this.dom.closest("[data-theme]")??this.dom.ownerDocument?.documentElement])].filter(e=>!!e);if(t.length&&typeof MutationObserver<"u"){this.modes=new MutationObserver(()=>void this.draw());for(const e of t)this.modes.observe(e,{attributes:!0,attributeFilter:["data-mode","data-theme"]})}this.draw()}ignoreMutation(t){return this.contentDOM?!this.contentDOM.contains(t.target):!0}update(t){return t.type!==this.node.type?!1:(this.node=t,this.syncAttrs(),this.draw(),!0)}syncAttrs(){const e=this.node.type.spec.toDOM(this.node)[1]??{};for(const[o,n]of Object.entries(e))this.dom.getAttribute(o)!==String(n)&&this.dom.setAttribute(o,String(n));for(const o of this.wrote)o in e||this.dom.removeAttribute(o);this.wrote=new Set(Object.keys(e))}storeZoom(t){const e=this.getPos();if(e===void 0)return;const o=this.view.state.doc.nodeAt(e);!o||o.attrs.zoom===t||this.view.dispatch(this.view.state.tr.setNodeMarkup(e,void 0,{...o.attrs,zoom:t}))}destroy(){this.dead=!0,this.modes?.disconnect(),this.zoom?.dispose()}async draw(){const{source:t}=f(this.node),e=D(this.dom),o=S(this.dom),n=E(this.dom),i=JSON.stringify([t,e,o,n]);if(i===this.key)return;this.key=i;const d=p(t);if(d){this.paintProblem(d);return}const a=r.get(i);if(a!==void 0){this.paint(a);return}try{const m=await g(t,{mode:e,fontFamily:o,themeVariables:n?b(n,e==="dark"):void 0,id:`dfx-diagram-${v++}`});if(O(i,m),this.dead)return;this.paint(m)}catch(m){if(this.dead)return;this.paintProblem(k(m))}typeof window<"u"&&window.dispatchEvent(new Event(u))}paint(t){const e=this.zoom?.pane??this.drawing;e.innerHTML=t,this.drawing.removeAttribute("data-problem")}paintProblem(t){const e=this.zoom?.pane??this.drawing;e.textContent="",this.drawing.setAttribute("data-problem",t);const o=document.createElement("p");o.className="diagram-problem",o.textContent=t,e.append(o)}}function k(s){const e=(s instanceof Error?s.message:String(s)).trim()||"this diagram could not be drawn.";return l(e,x(s))}function x(s){const e=s?.hash?.loc?.first_line;return typeof e=="number"&&e>0?e:null}export{R as DiagramView,x as errorLine,k as messageOf};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const b=1.35,x=.2,R=8,h=r=>Math.round(Math.min(8,Math.max(.2,r))*100)/100,g=r=>Math.max(0,(r-1)/2),u={fit:["M3 7V5a2 2 0 0 1 2-2h2","M17 3h2a2 2 0 0 1 2 2v2","M21 17v2a2 2 0 0 1-2 2h-2","M7 21H5a2 2 0 0 1-2-2v-2","M9 8h6a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H9a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1z"],out:["M5 12h14"],in:["M12 5v14M5 12h14"]},D=r=>'<svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">'+r.map(c=>`<path d="${c}"/>`).join("")+"</svg>",d=(r,c,l,o)=>{const n=document.createElement("button");return n.type="button",n.className=`diagram-zoom-btn diagram-zoom-${c}`,n.setAttribute("aria-label",l),n.setAttribute("title",l),n.innerHTML=D(r),n.addEventListener("pointerdown",a=>{a.preventDefault(),a.stopPropagation()}),n.addEventListener("click",a=>{a.preventDefault(),a.stopPropagation(),o()}),n};function E(r,c=r,l={}){let o=h(l.initial??1),n=0,a=0;const e=document.createElement("div");for(e.className="diagram-pane";r.firstChild;)e.append(r.firstChild);r.append(e);const i=document.createElement("div");i.className="diagram-zoom",i.contentEditable="false",i.setAttribute("data-chrome","zoom");const p=()=>{const t=g(o);n=Math.min(t,Math.max(-t,n)),a=Math.min(t,Math.max(-t,a)),e.style.transform=`translate(${n*100}%, ${a*100}%) scale(${o})`,e.style.cursor=o>1?"grab":"",e.style.touchAction=t>0?"none":"",r.toggleAttribute("data-zoomed",o!==1)},O=()=>l.onZoom?.(o===1?null:o),f=t=>{const s=o;o=h(t),o<=1&&s!==o&&(n=0,a=0),p(),o!==s&&O()},_=()=>{o=1,n=0,a=0,p(),O()};i.append(d(u.fit,"fit","Fit",_),d(u.out,"out","Zoom out",()=>f(o/1.35)),d(u.in,"in","Zoom in",()=>f(o*1.35))),c.append(i);let m=!1,v=0,A=0;const I=t=>{o<=1||t.button!==0||(m=!0,v=t.clientX,A=t.clientY,e.style.cursor="grabbing",e.setPointerCapture(t.pointerId),t.preventDefault(),t.stopPropagation())},Z=t=>{if(!m)return;const s=r.getBoundingClientRect();s.width&&(n+=(t.clientX-v)/s.width),s.height&&(a+=(t.clientY-A)/s.height),v=t.clientX,A=t.clientY,p(),t.preventDefault()},M=t=>{m&&(m=!1,e.style.cursor="grab",e.hasPointerCapture(t.pointerId)&&e.releasePointerCapture(t.pointerId))};return e.addEventListener("pointerdown",I),e.addEventListener("pointermove",Z),e.addEventListener("pointerup",M),e.addEventListener("pointercancel",M),p(),{pane:e,controls:i,fit:_,value:()=>o,dispose:()=>{e.removeEventListener("pointerdown",I),e.removeEventListener("pointermove",Z),e.removeEventListener("pointerup",M),e.removeEventListener("pointercancel",M),i.remove()}}}const G=[`var DIAGRAM_ZOOM_STEP = ${1.35}`,`var DIAGRAM_ZOOM_MIN = ${.2}`,"var DIAGRAM_ZOOM_MAX = 8",`var ICONS = ${JSON.stringify(u)}`,`var clampZoom = ${h}`,`var panLimit = ${g}`,`var zoomIcon = ${D}`,`var zoomButton = ${d}`,`var attachZoom = ${E}`].join(`
|
|
2
|
+
`);export{G as DIAGRAM_ZOOM_JS,R as DIAGRAM_ZOOM_MAX,x as DIAGRAM_ZOOM_MIN,b as DIAGRAM_ZOOM_STEP,E as attachZoom,h as clampZoom,g as panLimit,d as zoomButton,D as zoomIcon};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{readFileSync as f}from"node:fs";import{posterCandidates as s}from"../media.js";import{documentIn as m,exportHTML as i,exportReport as u,networkRefs as w,placeholdersIn as p,themesIn as c,undrawnIn as g}from"./html.js";const $=()=>f(new URL("../blocks.css",import.meta.url),"utf8"),b=15e3;async function x(e){if(e.startsWith("data:"))return e;const r=s(e);let t=null;for(const[l,a]of r.entries()){const n=l===r.length-1;try{t=await fetch(a,{signal:AbortSignal.timeout(b),redirect:"follow"})}catch(d){if(!n)continue;throw new Error(`could not fetch the image at ${a} \u2014 ${d.message}. The file carries a placeholder where it should be; check the address, or remove the picture.`)}if(t.ok)break;if(n)throw new Error(`the image at ${a} answered ${t.status} ${t.statusText}, so it could not be embedded and the file carries a placeholder where it should be.`)}if(!t)throw new Error(`no address to fetch for ${e}`);const o=(t.headers.get("content-type")??"").split(";")[0].trim().toLowerCase();if(!/^image\/[a-z0-9.+-]+$/.test(o))throw new Error(`${e} answered with '${o||"no content type"}', which is not an image \u2014 a sign-in page or an error page served as HTML is the usual cause. Use the address of the image itself.`);const h=Buffer.from(await t.arrayBuffer());return`data:${o};base64,${h.toString("base64")}`}const y=async e=>s(e).length>1?x(e):e;function I(e,r={}){const t=c(e);return i({doc:e,themes:t,css:$(),image:y,diagram:r.diagram,chartBox:r.chartBox,fileName:r.fileName})}export{m as documentIn,I as exportDocument,i as exportHTML,u as exportReport,$ as loadBlocksCSS,w as networkRefs,p as placeholdersIn,c as themesIn,g as undrawnIn};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{getSchema as U}from"@tiptap/core";import{Node as q}from"@tiptap/pm/model";import{MARK_BOX as Y,MARK_PATH as X,WORDMARK_BOX as Z,WORDMARK_PATH as z}from"../brand.js";import{decaframeExtensions as Q,loadDocument as tt}from"../extensions.js";import{documentName as et}from"../filename.js";import{docFurnitureAttrs as st,docFurnitureStyle as at}from"../furniture.js";import{embedUrl as nt,youtubeId as rt}from"../media.js";import{themeOrDefault as j}from"../registry.js";import{THEMES as ot,emitTheme as it,fontLinks as ct}from"../theme/index.js";import{escapeAttr as l,escapeText as N,serializeNode as dt}from"./spec.js";import{CHART_NODE as lt,CHART_PLOT_CLASS as pt,chartOption as ft,seriesOf as mt,seriesProblem as ut}from"../chart.js";import{DIAGRAM_DRAWING_CLASS as L,DIAGRAM_NODE as ht,diagramOf as bt,sourceProblem as gt}from"../diagram.js";import{diagramVars as xt}from"../diagramTheme.js";import{fontHref as vt}from"../theme/index.js";import{fitSource as yt}from"../fit.js";import{VIEWER_CSS as $t,VIEWER_JS as wt}from"./viewer.js";function ie(t){const e=t.replace(/\/\*[\s\S]*?\*\//g,"").replace(/"/g,'"'),s=[],r=[[/<link\b[^>]*>/gi,"stylesheet or preload link"],[/<script\b[^>]*\bsrc\s*=[^>]*>/gi,"external script"],[/@import[^;]*/gi,"CSS @import"],[/\bsrcset\s*=\s*"[^"]*"/gi,"srcset"],[/\bsrc\s*=\s*"(?!data:)[^"]*"/gi,"non-data src"],[/url\(\s*"?(?!data:|#)[^)"']*"?\s*\)/gi,"non-data url()"]];for(const[p,m]of r)for(const o of e.match(p)??[])s.push(`${m}: ${o.slice(0,90)}`);return s}const H=t=>t.replace(/"/g,'"').replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&");function Ot(t){const e=[];for(const[,s]of t.matchAll(/\bdata-export-problem="([^"]*)"/g))e.push(H(s));return e}function At(t){const e=[];for(const[,s]of t.matchAll(/\bdata-diagram-problem="([^"]*)"/g))e.push(H(s));return e}function ce(t){const e=t.match(/<script\b[^>]*\bid="dfx-document"[^>]*>([\s\S]*?)<\/script>/);if(!e)return{ok:!1,reason:"absent"};try{const s=JSON.parse(e[1]);return!s||typeof s!="object"||Array.isArray(s)?{ok:!1,reason:"unreadable"}:{ok:!0,doc:s}}catch{return{ok:!1,reason:"unreadable"}}}function de(t){const e=/data-theme-fallback="([^"]*)"/.exec(t)?.[1],s=/data-theme-fallback-reason="([^"]*)"/.exec(t)?.[1],r=/data-diagram-font-missing="([^"]*)"/.exec(t)?.[1];return{missingImages:Ot(t),diagramProblems:At(t),...e?{themeFallback:e,themeFallbackReason:s??"unknown"}:{},...r?{diagramFontMissing:r}:{}}}const F=(t,e)=>`<img class="media-img" src="data:," alt="${l(e?`${e} \u2014 ${t}`:t)}"><span class="dfx-missing" data-export-problem="${l(t)}"><span class="dfx-missing-label">Image unavailable</span><span class="dfx-missing-why">${N(t)}</span></span>`;function Mt(t,e=ot){return[...new Set([t.attrs?.theme??"decaframe"])].map(r=>e.find(p=>p.id===r)??j(r).theme)}const St=/<span class="media-add">.*?<\/span><\/span>/g,Nt="this picture was never given an address \u2014 it was left as an empty frame in the editor, and an exported file has no way to fill one in.",b=(t,e)=>`<svg viewBox="0 0 24 24" width="${e}" height="${e}" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${t}</svg>`,Rt=`<svg viewBox="${Y}" width="28" height="15.75" fill="currentColor"><path fill-rule="evenodd" d="${X}"/></svg>`,_t=`<svg viewBox="${Z}" width="96" height="25.28" fill="currentColor" role="img" aria-label="decaframe"><path d="${z}"/></svg>`,B=b('<rect width="18" height="18" x="3" y="3" rx="2"/><path d="M7 3v18"/><path d="M3 7.5h4"/><path d="M3 12h18"/><path d="M3 16.5h4"/><path d="M17 3v18"/><path d="M17 7.5h4"/><path d="M17 16.5h4"/>',15),kt=b('<path d="m15 18-6-6 6-6"/>',16),It=b('<path d="m9 18 6-6-6-6"/>',16),Ct=b('<polygon points="6 3 20 12 6 21 6 3"/>',14),Et=b('<path d="m6 9 6 6 6-6"/>',14),Pt=b('<circle cx="12" cy="12" r="1"/><circle cx="12" cy="5" r="1"/><circle cx="12" cy="19" r="1"/>',16),Dt=b('<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/>',16),Tt=b('<circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/>',16),jt=b('<rect x="14" y="3" width="5" height="18" rx="1"/><rect x="5" y="3" width="5" height="18" rx="1"/>',13),Lt=b('<path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/>',13),Ht={width:1120,height:300},W=t=>{const e=[];return t.descendants(s=>{s.type.name===lt&&e.push(s)}),e};async function Ft(t,e){const s=W(t);if(!s.length)return{};const r=await import("echarts"),p={};for(const m of s){const o=m.attrs.id,i=mt(m);if(!o||ut(i))continue;const u=e[o]??Ht,d=r.init(null,null,{renderer:"svg",ssr:!0,width:u.width,height:u.height});d.setOption(ft(i,{kind:m.attrs.arrangement,stack:m.attrs.stack})),p[o]={[pt]:d.renderToSVGString().replace(/^<svg width="[^"]*" height="[^"]*"/,"<svg")},d.dispose()}return p}const Bt=["light","dark"],Wt=t=>(t.split(",")[0]??"").trim().replace(/^['"]|['"]$/g,"")||"sans-serif",V=t=>`<p class="diagram-problem" data-diagram-problem="${l(t)}">${N(t)}</p>`,Vt="this diagram could not be drawn, because the file was exported by a process with no renderer. Export through the MCP server, `pnpm export`, or the editor, and the picture will be in the file.";async function Gt(t,e,s){const r=[];if(t.descendants(u=>{u.type.name===ht&&r.push(u)}),!r.length)return{inject:{}};const p=String(e.tokens["font-sans"]??"sans-serif"),m={fontFamily:p,fontFace:Wt(p),fontHref:vt([e])},o={};let i;for(const[u,d]of r.entries()){const g=d.attrs.id;if(!g)continue;const{source:x}=bt(d),A=gt(x);if(A||!s){o[g]={[L]:V(A??Vt)};continue}const M=[];let $;for(const v of Bt){const y=await s({...m,source:x,mode:v,vars:xt(e,v),id:`dfx-diagram-${u}-${v}`});if(i??=y.fontMissing,y.svg===void 0){$=y.problem??"this diagram could not be drawn.";break}M.push(`<span class="diagram-svg" data-mode-svg="${v}">${y.svg}</span>`)}o[g]={[L]:$?V($):M.join("")}}return{inject:o,...i?{fontMissing:i}:{}}}async function le(t){const{css:e,image:s}=t,r=tt(t.doc),p=t.themes??Mt(r),m=U(Q()),o=q.fromJSON(m,r),i=r.attrs??{},u=et(String(i.title??""),t.fileName),d=j(i.theme),g=String(i.mode??"light"),x=await Gt(o,d.theme,t.diagram),A=at(i),M=`<html lang="en" data-format="${l(String(i.format??"16:9"))}" data-align="${l(String(i.align??"middle"))}"`+(i.autoFit===!1?' data-autofit="off"':"")+` data-theme="${l(d.theme.id)}"`+(d.miss?` data-theme-fallback="${l(d.miss.name)}"`:"")+(d.miss?` data-theme-fallback-reason="${l(d.miss.reason)}"`:"")+(x.fontMissing?` data-diagram-font-missing="${l(x.fontMissing)}"`:"")+Object.keys(st(i)).map(a=>` ${a}`).join("")+` style="${A}" data-mode="${l(g)}" data-view="browse">`,$=a=>{const n=[];return o.forEach(k=>{n.push(`<section class="dfx-slide"><div class="dfx-fit">${dt(k,a)}</div></section>`)}),n},v=[];o.forEach(a=>v.push(a.attrs.notes??null));const y=JSON.stringify(v).replace(/</g,"\\u003c"),G=JSON.stringify(r).replace(/</g,"\\u003c"),I=/<img\b[^>]*\bsrc="([^"]+)"[^>]*>/g,J=/\balt="([^"]*)"/,C=a=>{try{return decodeURIComponent(a)}catch{return a}},S=new Map,E=async a=>{const n=$(a);if(s){const f=new Set;for(const c of n)for(const[,h]of c.matchAll(I))f.add(C(h));for(const c of f)if(!S.has(c))try{S.set(c,await s(c))}catch(h){S.set(c,{problem:h.message})}for(let c=0;c<n.length;c++)n[c]=n[c].replace(I,(h,w)=>{const T=C(w),O=S.get(T);return O===void 0?h:typeof O=="string"?O===T?h:h.replace(`src="${w}"`,`src="${O}"`):F(O.problem,J.exec(h)?.[1]??"")})}const k=/<a class="media-play" href="([^"]*)"/g;for(let f=0;f<n.length;f++)n[f]=n[f].replace(k,(c,h)=>{const w=rt(h.replace(/&/g,"&"));return w?`<iframe class="dfx-embed" data-src="${l(nt(w))}" title="Video" allow="accelerometer; encrypted-media; gyroscope; picture-in-picture" allowfullscreen frameborder="0"></iframe>${c}`:c});for(let f=0;f<n.length;f++)n[f]=n[f].replace(St,F(Nt,""));return n},K=p.map(a=>it(a,t.emit??{scale:1,frameWidth:1280})).join(`
|
|
2
|
+
`),R=a=>a.replace(/\/\*[\s\S]*?\*\//g,"").replace(/^[ \t]*\/\/.*$/gm,"").replace(/\n{3,}/g,`
|
|
3
|
+
|
|
4
|
+
`),P=a=>["<!doctype html>",M,"<head>",'<meta charset="utf-8">','<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">',`<title>${N(u)}</title>`,...ct(p).map(n=>`<link rel="${l(n.rel)}" href="${l(n.href)}"`+(n.crossOrigin?" crossorigin":"")+">"),"<style>",R([K,e,$t].join(`
|
|
5
|
+
`)),"</style>","</head>","<body>",`<header class="dfx-titlebar"><div class="dfx-titlebar-left"><span class="dfx-brand" aria-hidden="true">${Rt}</span><span class="dfx-titlebar-title">${N(u)}</span></div><div class="dfx-titlebar-right"><span class="dfx-split"><button class="dfx-present-btn" type="button">${Ct}Present</button><details class="dfx-split-more"><summary class="dfx-present-caret" aria-label="Presenting options">${Et}</summary><div class="dfx-menu" role="menu"><button class="dfx-menu-item" type="button" role="menuitem" data-action="presenter-view">Presenter view</button></div></details></span><button class="dfx-mode-toggle" type="button" aria-label="Switch to ${g==="dark"?"light":"dark"} theme">`+(g==="dark"?Tt:Dt)+"</button></div></header>",`<nav class="dfx-rail" aria-label="Pages"><header class="dfx-rail-head"><button class="dfx-rail-toggle" type="button" aria-label="Hide the page list" aria-expanded="true">${B}</button><span>Pages</span><span class="dfx-count">${a.length}</span></header><div class="dfx-rail-list" role="listbox" aria-label="Pages"></div><footer class="dfx-rail-foot">${_t}</footer></nav><button class="dfx-rail-show" type="button" aria-label="Show the page list" aria-expanded="false">${B}</button>`,`<main class="dfx-deck">${a.join("")}</main>`,`<div class="dfx-hud"><button class="dfx-hud-btn" type="button" data-action="prev" aria-label="Previous page">${kt}</button><span class="dfx-hud-at"><span class="dfx-at">1</span></span><button class="dfx-hud-btn" type="button" data-action="next" aria-label="Next page">${It}</button><details class="dfx-hud-more"><summary class="dfx-hud-btn" aria-label="More">${Pt}</summary><div class="dfx-menu" role="menu"><button class="dfx-menu-item" type="button" role="menuitem" data-action="start-over">Start from beginning</button><button class="dfx-menu-item" type="button" role="menuitem" data-action="exit">Exit presenting</button></div></details></div>`,`<div class="dfx-presenter" hidden><header class="dfx-presenter-head"><span class="dfx-presenter-timer">00:00</span><button class="dfx-presenter-timer-btn" type="button" data-action="pause" aria-label="Pause timer">${jt}</button><button class="dfx-presenter-timer-btn" type="button" data-action="reset" aria-label="Reset timer">${Lt}</button><span class="dfx-presenter-count"></span></header><div class="dfx-presenter-body"><div class="dfx-presenter-current"></div><div class="dfx-presenter-adjacent"><button class="dfx-presenter-thumb" type="button" data-action="prev" aria-label="Previous slide"><span class="dfx-presenter-thumb-pic"></span><span class="dfx-presenter-thumb-label">\u2039 Previous</span></button><button class="dfx-presenter-thumb" type="button" data-action="next" aria-label="Next slide"><span class="dfx-presenter-thumb-pic"></span><span class="dfx-presenter-thumb-label">Next \u203A</span></button></div><section class="dfx-presenter-notes"><p class="dfx-presenter-notes-label">Speaker notes</p><div class="dfx-presenter-notes-body"></div></section></div></div>`,`<script type="application/json" id="dfx-notes">${y}</script>`,`<script type="application/json" id="dfx-document">${G}</script>`,`<script>${R(yt())}</script>`,`<script>${R(wt)}</script>`,"</body>","</html>",""].join(`
|
|
6
|
+
`);let _=await E(x.inject);const D=W(o).map(a=>a.attrs.id).filter(Boolean);if(D.length){const a=t.chartBox?await t.chartBox(P(_),D):{},n=await Ft(o,a);_=await E({...n,...x.inject})}return P(_)}export{Ht as PLOT_FALLBACK,ce as documentIn,le as exportHTML,de as exportReport,ie as networkRefs,Ot as placeholdersIn,Mt as themesIn,At as undrawnIn};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{countOf as $}from"../blocks.js";import{CATALOGUE as y}from"../blocks.js";import{TABLE_NODES as x,colsOf as h}from"../table.js";const S=new Set(y.map(t=>t.node)),D=new Set(["area","br","col","embed","hr","img","input","link","meta","source"]),m=t=>t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"),A=t=>t.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<");function d(t){return Object.entries(t).filter(([,r])=>r!=null&&r!==!1).map(([r,e])=>e===!0?` ${r}`:` ${r}="${A(String(e))}"`).join("")}function p(t,r,e={},n={}){if(t===0)return r;if(typeof t=="string")return m(t);if(!Array.isArray(t))throw new Error(`unrenderable DOMOutputSpec: ${JSON.stringify(t)}`);const[a,...i]=t,f=a.indexOf(" "),o=f>0?a.slice(f+1):a;let s={},u=0;i[0]&&typeof i[0]=="object"&&!Array.isArray(i[0])&&(s=i[0],u=1);const c=d({...s,...e});if(D.has(o))return`<${o}${c}>`;const l=typeof s.class=="string"?n[s.class]:void 0;if(l!==void 0)return`<${o}${c}>${l}</${o}>`;const g=i.slice(u).map(O=>p(O,r,{},n)).join("");return`<${o}${c}>${g}</${o}>`}function w(t){let r=m(t.text??"");for(let e=t.marks.length-1;e>=0;e--){const n=t.marks[e],a=n.type.spec.toDOM;a&&(r=p(a(n,!0),r))}return r}function E(t,r={}){if(t.isText)return w(t);const e=t.type.spec.toDOM;if(!e)throw new Error(`node type "${t.type.name}" has no toDOM \u2014 it cannot be exported`);const n=t.isLeaf?"":T(t,r),a=S.has(t.type.name)?{"data-count":String($(t)),...x.has(t.type.name)?{"data-cols":String(h(t))}:{}}:{};return p(e(t),n,a,r[t.attrs.id]??{})}function T(t,r={}){const e=[];return t.forEach(n=>e.push(E(n,r))),e.join("")}export{A as escapeAttr,m as escapeText,p as renderSpec,T as serializeFragment,E as serializeNode};
|