@templatical/editor 0.25.0 → 0.25.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{AiChatSidebar-CIkS8DsO.js → AiChatSidebar-JLsbPnsH.js} +14 -14
- package/dist/{AiFeatureMenu-Cji1LBJJ.js → AiFeatureMenu-BvA-lViN.js} +7 -7
- package/dist/{BlockIssueBadge-BQiT0FML.js → BlockIssueBadge-Cf0-GC3o.js} +5 -5
- package/dist/{BlockPreviewCanvas-DAnwZofk.js → BlockPreviewCanvas-CnJIM5TO.js} +3 -3
- package/dist/{CloudEditor-CXaft6Ej.js → CloudEditor-Caq7z4-7.js} +25 -25
- package/dist/{CollaboratorBar-BR-rL2wG.js → CollaboratorBar-BFz4LgA0.js} +4 -4
- package/dist/{ColorPicker-B4ArSUhy.js → ColorPicker-B5xXWWX5.js} +6 -6
- package/dist/{CommentsSidebar-Bm5GLDts.js → CommentsSidebar-CGihWwn9.js} +15 -15
- package/dist/{CountdownBlock-CIVAQDVu.js → CountdownBlock-DuyvGcr8.js} +3 -3
- package/dist/{CountdownToolbar-DBmb3tlb.js → CountdownToolbar-DpNCZAUI.js} +4 -4
- package/dist/{DesignReferenceSidebar-CnyJ8L-j.js → DesignReferenceSidebar-CiIHHiil.js} +11 -11
- package/dist/{IssuesPanel-D3XgmYCt.js → IssuesPanel-CUkmAC_S.js} +8 -8
- package/dist/{LoadingTrack-XK_eeUdq.js → LoadingTrack-BexpNuTV.js} +1 -1
- package/dist/{MergeTagModeToggle-BK0fI3P2.js → MergeTagModeToggle-C6nS3qri.js} +5 -5
- package/dist/{MergeTagSuggestion-D0OHRv7L.js → MergeTagSuggestion-98fAcuM-.js} +26 -24
- package/dist/{NumberWithSuffix-Cjj9UNIp.js → NumberWithSuffix-DB-1GNvx.js} +2 -2
- package/dist/{ParagraphEditor-jGnbJEA2.js → ParagraphEditor-NgW-T9YV.js} +114 -97
- package/dist/{RichTextEditorContent-DaaKdzjb.js → RichTextEditorContent-CN7OVR6u.js} +8 -8
- package/dist/{SaveBlockDialog-B3ngEldp.js → SaveBlockDialog-lgcmhAsO.js} +10 -10
- package/dist/{SavedBlocksBrowserModal-DawN3XaB.js → SavedBlocksBrowserModal-3u247V2z.js} +11 -11
- package/dist/{SavedBlocksPanels-eDC9Y46N.js → SavedBlocksPanels-Dh6dABJt.js} +2 -2
- package/dist/{SavedBlocksPickBar-CQbbXmzj.js → SavedBlocksPickBar-Bo82D3Qy.js} +4 -4
- package/dist/{SnapshotHistory-COxKtHM-.js → SnapshotHistory-Dsb1i40w.js} +16 -16
- package/dist/{TemplateScoringPanel-bUuqOO1z.js → TemplateScoringPanel-Bzd_YSag.js} +15 -15
- package/dist/{TestEmailModal-CytkbZVQ.js → TestEmailModal-DvqDTOcO.js} +10 -10
- package/dist/{TestEmailPanel-CHUY7VZn.js → TestEmailPanel-BXoVnAqu.js} +2 -2
- package/dist/{TitleEditor-aMR1bOyY.js → TitleEditor-DWSi998C.js} +12 -12
- package/dist/{TplModal-fmYNYdyp.js → TplModal-DKn0h2qe.js} +5 -5
- package/dist/{blockTypeIcons-C6b9rg88.js → blockTypeIcons-DKlza6aR.js} +2 -2
- package/dist/bundle-stats.json +6 -6
- package/dist/{ca-8Dvbwo50.js → ca-D1zgI9fQ.js} +1 -0
- package/dist/cdn/chunks/{AiChatSidebar-bkBKpNgE.js → AiChatSidebar-BY1Iy-e8.js} +14 -14
- package/dist/cdn/chunks/{AiChatSidebar-bkBKpNgE.js.map → AiChatSidebar-BY1Iy-e8.js.map} +1 -1
- package/dist/cdn/chunks/{AiFeatureMenu-CI4SYTq2.js → AiFeatureMenu-BS4Rek6j.js} +6 -6
- package/dist/cdn/chunks/{AiFeatureMenu-CI4SYTq2.js.map → AiFeatureMenu-BS4Rek6j.js.map} +1 -1
- package/dist/cdn/chunks/{BlockIssueBadge-CRnx8Dv9.js → BlockIssueBadge-BcIQUe_Q.js} +5 -5
- package/dist/cdn/chunks/{BlockIssueBadge-CRnx8Dv9.js.map → BlockIssueBadge-BcIQUe_Q.js.map} +1 -1
- package/dist/cdn/chunks/{BlockPreviewCanvas-CXCWhqbp.js → BlockPreviewCanvas-oND1iXLL.js} +4 -4
- package/dist/cdn/chunks/{BlockPreviewCanvas-CXCWhqbp.js.map → BlockPreviewCanvas-oND1iXLL.js.map} +1 -1
- package/dist/cdn/chunks/{CloudEditor-D-t7RyDh.js → CloudEditor-BaqiFbf0.js} +28 -28
- package/dist/cdn/chunks/{CloudEditor-D-t7RyDh.js.map → CloudEditor-BaqiFbf0.js.map} +1 -1
- package/dist/cdn/chunks/{CollaboratorBar-DcXYo47v.js → CollaboratorBar-DF02nTwF.js} +5 -5
- package/dist/cdn/chunks/{CollaboratorBar-DcXYo47v.js.map → CollaboratorBar-DF02nTwF.js.map} +1 -1
- package/dist/cdn/chunks/{ColorPicker-_1O7YU2z.js → ColorPicker-BXH44v2H.js} +7 -7
- package/dist/cdn/chunks/{ColorPicker-_1O7YU2z.js.map → ColorPicker-BXH44v2H.js.map} +1 -1
- package/dist/cdn/chunks/{CommentsSidebar-BEgLBYX-.js → CommentsSidebar-B9bWvvbl.js} +10 -10
- package/dist/cdn/chunks/{CommentsSidebar-BEgLBYX-.js.map → CommentsSidebar-B9bWvvbl.js.map} +1 -1
- package/dist/cdn/chunks/{CountdownBlock-CPnQA44g.js → CountdownBlock-BTpRd0Hn.js} +4 -4
- package/dist/cdn/chunks/{CountdownBlock-CPnQA44g.js.map → CountdownBlock-BTpRd0Hn.js.map} +1 -1
- package/dist/cdn/chunks/{CountdownToolbar-Cdo-30U4.js → CountdownToolbar-CW10rbWt.js} +5 -5
- package/dist/cdn/chunks/{CountdownToolbar-Cdo-30U4.js.map → CountdownToolbar-CW10rbWt.js.map} +1 -1
- package/dist/cdn/chunks/{DesignReferenceSidebar-DPqBr-ut.js → DesignReferenceSidebar-BXjH47QC.js} +9 -9
- package/dist/cdn/chunks/{DesignReferenceSidebar-DPqBr-ut.js.map → DesignReferenceSidebar-BXjH47QC.js.map} +1 -1
- package/dist/cdn/chunks/{IssuesPanel-DoQWb23r.js → IssuesPanel-DStHCHfr.js} +7 -7
- package/dist/cdn/chunks/{IssuesPanel-DoQWb23r.js.map → IssuesPanel-DStHCHfr.js.map} +1 -1
- package/dist/cdn/chunks/{LoadingTrack-G2tuXqCJ.js → LoadingTrack-DQowK3MV.js} +2 -2
- package/dist/cdn/chunks/{LoadingTrack-G2tuXqCJ.js.map → LoadingTrack-DQowK3MV.js.map} +1 -1
- package/dist/cdn/chunks/{MergeTagModeToggle-CWuVC3MU.js → MergeTagModeToggle-BCmQg4Qe.js} +5 -5
- package/dist/cdn/chunks/{MergeTagModeToggle-CWuVC3MU.js.map → MergeTagModeToggle-BCmQg4Qe.js.map} +1 -1
- package/dist/cdn/chunks/{MergeTagSuggestion-Ces5Ua78.js → MergeTagSuggestion-BgExdloL.js} +3 -3
- package/dist/cdn/chunks/{MergeTagSuggestion-Ces5Ua78.js.map → MergeTagSuggestion-BgExdloL.js.map} +1 -1
- package/dist/cdn/chunks/{NumberWithSuffix-DQ4sgvt5.js → NumberWithSuffix-BANVbpT0.js} +3 -3
- package/dist/cdn/chunks/{NumberWithSuffix-DQ4sgvt5.js.map → NumberWithSuffix-BANVbpT0.js.map} +1 -1
- package/dist/cdn/chunks/{ParagraphEditor-Uv5LPF3W.js → ParagraphEditor-DqilB4_f.js} +142 -132
- package/dist/cdn/chunks/ParagraphEditor-DqilB4_f.js.map +1 -0
- package/dist/cdn/chunks/{RichTextEditorContent-Bt3s09qY.js → RichTextEditorContent-BeJx4LVH.js} +7 -7
- package/dist/cdn/chunks/{RichTextEditorContent-Bt3s09qY.js.map → RichTextEditorContent-BeJx4LVH.js.map} +1 -1
- package/dist/cdn/chunks/{SaveBlockDialog-BAew6EFd.js → SaveBlockDialog-Dm31xRZy.js} +8 -8
- package/dist/cdn/chunks/{SaveBlockDialog-BAew6EFd.js.map → SaveBlockDialog-Dm31xRZy.js.map} +1 -1
- package/dist/cdn/chunks/{SavedBlocksBrowserModal-Dn4IJDJW.js → SavedBlocksBrowserModal-Tp37b4y7.js} +9 -9
- package/dist/cdn/chunks/{SavedBlocksBrowserModal-Dn4IJDJW.js.map → SavedBlocksBrowserModal-Tp37b4y7.js.map} +1 -1
- package/dist/cdn/chunks/{SavedBlocksPanels-B62U5DYW.js → SavedBlocksPanels-ElerTTa_.js} +3 -3
- package/dist/cdn/chunks/{SavedBlocksPanels-B62U5DYW.js.map → SavedBlocksPanels-ElerTTa_.js.map} +1 -1
- package/dist/cdn/chunks/{SavedBlocksPickBar-CyRKZg2T.js → SavedBlocksPickBar-QHJ-Mjx0.js} +7 -7
- package/dist/cdn/chunks/{SavedBlocksPickBar-CyRKZg2T.js.map → SavedBlocksPickBar-QHJ-Mjx0.js.map} +1 -1
- package/dist/cdn/chunks/{SnapshotHistory-QQt0DKey.js → SnapshotHistory-jogWGLB-.js} +12 -12
- package/dist/cdn/chunks/{SnapshotHistory-QQt0DKey.js.map → SnapshotHistory-jogWGLB-.js.map} +1 -1
- package/dist/cdn/chunks/{TemplateScoringPanel-BwyCMcit.js → TemplateScoringPanel-B2XIOTl-.js} +52 -52
- package/dist/cdn/chunks/{TemplateScoringPanel-BwyCMcit.js.map → TemplateScoringPanel-B2XIOTl-.js.map} +1 -1
- package/dist/cdn/chunks/{TestEmailModal-B5UQkDJp.js → TestEmailModal-BcPjQygV.js} +9 -9
- package/dist/cdn/chunks/{TestEmailModal-B5UQkDJp.js.map → TestEmailModal-BcPjQygV.js.map} +1 -1
- package/dist/cdn/chunks/{TestEmailPanel-CvuBq4RA.js → TestEmailPanel-1zxRa00s.js} +3 -3
- package/dist/cdn/chunks/{TestEmailPanel-CvuBq4RA.js.map → TestEmailPanel-1zxRa00s.js.map} +1 -1
- package/dist/cdn/chunks/{TitleEditor-B9W954u9.js → TitleEditor-DTrmublj.js} +14 -14
- package/dist/cdn/chunks/{TitleEditor-B9W954u9.js.map → TitleEditor-DTrmublj.js.map} +1 -1
- package/dist/cdn/chunks/{TplModal-B8UsvWc8.js → TplModal-By50gtwa.js} +5 -5
- package/dist/cdn/chunks/{TplModal-B8UsvWc8.js.map → TplModal-By50gtwa.js.map} +1 -1
- package/dist/cdn/chunks/blockTypeIcons-BhFhHuFt.js +21 -0
- package/dist/cdn/chunks/{blockTypeIcons-B8s3_ahs.js.map → blockTypeIcons-BhFhHuFt.js.map} +1 -1
- package/dist/cdn/chunks/{ca-8Dvbwo50.js → ca-D1zgI9fQ.js} +2 -1
- package/dist/cdn/chunks/ca-D1zgI9fQ.js.map +1 -0
- package/dist/cdn/chunks/{cloud-DOaGUdR0.js → cloud-B0f7Ub8f.js} +3 -3
- package/dist/cdn/chunks/{cloud-DOaGUdR0.js.map → cloud-B0f7Ub8f.js.map} +1 -1
- package/dist/cdn/chunks/{de-CieSMCUp.js → de-DHra3lvx.js} +2 -1
- package/dist/cdn/chunks/de-DHra3lvx.js.map +1 -0
- package/dist/cdn/chunks/{dist-lZgXNk4G.js → dist-B4VIlp1g.js} +3 -3
- package/dist/cdn/chunks/{dist-lZgXNk4G.js.map → dist-B4VIlp1g.js.map} +1 -1
- package/dist/cdn/chunks/{dist-B8AX9np4.js → dist-H51neg3K.js} +10 -8
- package/dist/cdn/chunks/{dist-B8AX9np4.js.map → dist-H51neg3K.js.map} +1 -1
- package/dist/cdn/chunks/{draggable-JcMTNF3U.js → draggable-Z4XXmbPC.js} +556 -522
- package/dist/cdn/chunks/draggable-Z4XXmbPC.js.map +1 -0
- package/dist/cdn/chunks/{en-D0t_2Fq_.js → en-DlqX2YWZ.js} +2 -1
- package/dist/cdn/chunks/en-DlqX2YWZ.js.map +1 -0
- package/dist/cdn/chunks/{es-DwDoNuLM.js → es-Cuss2snv.js} +2 -1
- package/dist/cdn/chunks/es-Cuss2snv.js.map +1 -0
- package/dist/cdn/chunks/{extensions-5jgtarD-.js → extensions-Dq0D79tq.js} +6 -6
- package/dist/cdn/chunks/{extensions-5jgtarD-.js.map → extensions-Dq0D79tq.js.map} +1 -1
- package/dist/cdn/chunks/{fr-CSEEzv1_.js → fr-Cm85vB2g.js} +2 -1
- package/dist/cdn/chunks/fr-Cm85vB2g.js.map +1 -0
- package/dist/cdn/chunks/{htmlparser-CPhs2cYE.js → htmlparser-DTML8Gvz.js} +8 -7
- package/dist/cdn/chunks/{htmlparser-CPhs2cYE.js.map → htmlparser-DTML8Gvz.js.map} +1 -1
- package/dist/cdn/chunks/{icons-Cp4ZIJw-.js → icons-C_kRN0_C.js} +104 -97
- package/dist/cdn/chunks/icons-C_kRN0_C.js.map +1 -0
- package/dist/cdn/chunks/{keys-BxPCfHBH.js → keys-DsoX52o_.js} +2 -2
- package/dist/cdn/chunks/{keys-BxPCfHBH.js.map → keys-DsoX52o_.js.map} +1 -1
- package/dist/cdn/chunks/{liquid.browser-CZaQe87t.js → liquid.browser-DrGys_ek.js} +22 -20
- package/dist/cdn/chunks/{liquid.browser-CZaQe87t.js.map → liquid.browser-DrGys_ek.js.map} +1 -1
- package/dist/cdn/chunks/{nl-xyk1T2mA.js → nl-dmiIX7oT.js} +2 -1
- package/dist/cdn/chunks/nl-dmiIX7oT.js.map +1 -0
- package/dist/cdn/chunks/{pt-BR-yr6uOJgn.js → pt-BR-CaIG-7EM.js} +2 -1
- package/dist/cdn/chunks/pt-BR-CaIG-7EM.js.map +1 -0
- package/dist/cdn/chunks/{pusher-kUlkqMvR.js → pusher-BbIHJKf3.js} +29 -25
- package/dist/cdn/chunks/{pusher-kUlkqMvR.js.map → pusher-BbIHJKf3.js.map} +1 -1
- package/dist/cdn/chunks/{src-C417zeUg.js → src-Aea1Vl1H.js} +2 -2
- package/dist/cdn/chunks/{src-C417zeUg.js.map → src-Aea1Vl1H.js.map} +1 -1
- package/dist/cdn/chunks/{src-Dpj0x27M.js → src-CRvTVX4F.js} +427 -424
- package/dist/cdn/chunks/{src-Dpj0x27M.js.map → src-CRvTVX4F.js.map} +1 -1
- package/dist/cdn/chunks/{src-B8W42vT-.js → src-_GNJgPcS.js} +216 -176
- package/dist/cdn/chunks/src-_GNJgPcS.js.map +1 -0
- package/dist/cdn/chunks/{styles-DANwMzW2.js → styles-znpPfrFd.js} +79 -79
- package/dist/cdn/chunks/{styles-DANwMzW2.js.map → styles-znpPfrFd.js.map} +1 -1
- package/dist/cdn/chunks/{tiptap-rsib432n.js → tiptap-C5vzWlHv.js} +225 -183
- package/dist/cdn/chunks/tiptap-C5vzWlHv.js.map +1 -0
- package/dist/cdn/chunks/{useAliveFlag-CseYNikC.js → useAliveFlag-4IDYQRNu.js} +2 -2
- package/dist/cdn/chunks/{useAliveFlag-CseYNikC.js.map → useAliveFlag-4IDYQRNu.js.map} +1 -1
- package/dist/cdn/chunks/{useCloudI18n-CjVzv11v.js → useCloudI18n-D4JpHTPk.js} +3 -3
- package/dist/cdn/chunks/{useCloudI18n-CjVzv11v.js.map → useCloudI18n-D4JpHTPk.js.map} +1 -1
- package/dist/cdn/chunks/{useEditorCore-DfW-thCr.js → useEditorCore-BMXBmdd8.js} +28 -28
- package/dist/cdn/chunks/useEditorCore-BMXBmdd8.js.map +1 -0
- package/dist/cdn/chunks/{useI18n-DniEFeIl.js → useI18n-BvcEYzrI.js} +3 -3
- package/dist/cdn/chunks/{useI18n-DniEFeIl.js.map → useI18n-BvcEYzrI.js.map} +1 -1
- package/dist/cdn/chunks/{useMergeTag-Bk9_f5cc.js → useMergeTag-BSdxMUzg.js} +3 -3
- package/dist/cdn/chunks/{useMergeTag-Bk9_f5cc.js.map → useMergeTag-BSdxMUzg.js.map} +1 -1
- package/dist/cdn/chunks/{usePopoverPosition-C4xFJCJ2.js → usePopoverPosition-ig-71caO.js} +3 -3
- package/dist/cdn/chunks/{usePopoverPosition-C4xFJCJ2.js.map → usePopoverPosition-ig-71caO.js.map} +1 -1
- package/dist/cdn/editor.js +15 -15
- package/dist/{check-CIhIDh4h.js → check-COV27dGb.js} +1 -1
- package/dist/{chevron-down-CZ0m6G3s.js → chevron-down-vsU88vcr.js} +1 -1
- package/dist/{chevron-up-BH_tJLeb.js → chevron-up-RrZ0Rjn9.js} +1 -1
- package/dist/{circle-alert-DkEXnGPV.js → circle-alert-B6GlHmmi.js} +1 -1
- package/dist/{clock-BDIJZUET.js → clock-egOt8zjQ.js} +1 -1
- package/dist/{cloud-BZn3jqoL.js → cloud-D-2StbvU.js} +1 -1
- package/dist/{createLucideIcon-AEltGIse.js → createLucideIcon-D6cqT5Pm.js} +3 -3
- package/dist/{de-CieSMCUp.js → de-DHra3lvx.js} +1 -0
- package/dist/{dist-iCEDH3cC.js → dist-B56SufAv.js} +1 -1
- package/dist/{dist-CkPvZCld.js → dist-BQZkRg05.js} +1 -1
- package/dist/{dist-DT1XnEnj.js → dist-BpKxrUi2.js} +2 -2
- package/dist/{dist-CcQFPJMF.js → dist-CHxPjcxA.js} +181 -145
- package/dist/{dist-BxbTVeY0.js → dist-CqV4XslQ.js} +1 -1
- package/dist/{dist-Dx71pluS.js → dist-D4GoAr2g.js} +9 -7
- package/dist/{dist-DSIgxp0v.js → dist-DHwnYYx0.js} +1 -1
- package/dist/{dist-DX4x6mQ1.js → dist-Du95Y9M3.js} +1 -1
- package/dist/{dist-B6Px6GPj.js → dist-DzzTB4eE.js} +1 -1
- package/dist/{dist-DyCHUyRR.js → dist-GUZZpDK3.js} +1 -1
- package/dist/{dist-nR6mxyqI.js → dist-MwT7T6Xp.js} +1 -1
- package/dist/{dist-CIqhVQ1O.js → dist-UkG5ZJ1P.js} +17 -15
- package/dist/{dist-CRH880TV.js → dist-vpuiQ7_Q.js} +1 -1
- package/dist/{en-D0t_2Fq_.js → en-DlqX2YWZ.js} +1 -0
- package/dist/{es-DwDoNuLM.js → es-Cuss2snv.js} +1 -0
- package/dist/{extensions-BjvyU9Ea.js → extensions-y6KjLr9t.js} +7 -7
- package/dist/{fr-CSEEzv1_.js → fr-Cm85vB2g.js} +1 -0
- package/dist/{image-up-8ktdYdaZ.js → image-up-CycES-MQ.js} +1 -1
- package/dist/{info-CvrCgTLH.js → info-BUdvm046.js} +1 -1
- package/dist/{keys-BFPiNAIn.js → keys-fwF3qZax.js} +1 -1
- package/dist/{liquid.browser-BECWFL5Z.js → liquid.browser-Di5zMIEx.js} +21 -19
- package/dist/{list-checks-yzGT93ZL.js → list-checks-BAeuuATD.js} +1 -1
- package/dist/{loader-circle-B6euendB.js → loader-circle-L5yuAx_j.js} +1 -1
- package/dist/{message-circle-BMldLVcA.js → message-circle-DRdaapVc.js} +1 -1
- package/dist/{nl-xyk1T2mA.js → nl-dmiIX7oT.js} +1 -0
- package/dist/{pencil-CkKkSd6N.js → pencil-BfErVPf_.js} +1 -1
- package/dist/{pt-BR-yr6uOJgn.js → pt-BR-CaIG-7EM.js} +1 -0
- package/dist/{refresh-cw-fBPgB97G.js → refresh-cw-D0PYatER.js} +1 -1
- package/dist/{runtime-dom.esm-bundler-CBbDt7sw.js → runtime-dom.esm-bundler-CepEmvwF.js} +172 -168
- package/dist/{scan-line-CRoEOUiK.js → scan-line-Byi3fJcr.js} +1 -1
- package/dist/{send-B9Tt2qBi.js → send-DuyNexMY.js} +1 -1
- package/dist/{shield-check-QfZkYeIo.js → shield-check-BkkN_1qw.js} +1 -1
- package/dist/{sparkles-8UeMmZb8.js → sparkles-DAw2sBXk.js} +1 -1
- package/dist/{styles-C9GM-bBC.js → styles-BzwheHH_.js} +32 -32
- package/dist/templatical-editor.js +17 -17
- package/dist/{text-align-start-Dn8uIheW.js → text-align-start-Ba3xJKn6.js} +1 -1
- package/dist/{trash-2-DDyvqj0E.js → trash-2-CapEBXBI.js} +1 -1
- package/dist/{triangle-alert-B3PydLzl.js → triangle-alert-52pdw8jI.js} +1 -1
- package/dist/{upload-hE8ItfyG.js → upload-oAgigC31.js} +1 -1
- package/dist/{useAliveFlag-AfoTE_AY.js → useAliveFlag-cvyBxHp7.js} +1 -1
- package/dist/{useCloudI18n-B2lItQ6O.js → useCloudI18n-DKVm6PCa.js} +2 -2
- package/dist/{useEditorCore-Ck_hBiGA.js → useEditorCore-BhjEMSeE.js} +23 -23
- package/dist/{useI18n-C1KcdX_K.js → useI18n-DoVKdCTH.js} +2 -2
- package/dist/{useMergeTag-DHCwRMfH.js → useMergeTag-DTSOQnyr.js} +2 -2
- package/dist/{usePopoverPosition-ClnEh_Cp.js → usePopoverPosition-C0dPEF4X.js} +4 -4
- package/dist/{vue.runtime.esm-bundler-Xpz-L9Fn.js → vue.runtime.esm-bundler-D1diBMsm.js} +297 -251
- package/dist/{x-C4lETLDx.js → x-DvBgbDuf.js} +1 -1
- package/package.json +11 -11
- package/dist/cdn/chunks/ParagraphEditor-Uv5LPF3W.js.map +0 -1
- package/dist/cdn/chunks/blockTypeIcons-B8s3_ahs.js +0 -21
- package/dist/cdn/chunks/ca-8Dvbwo50.js.map +0 -1
- package/dist/cdn/chunks/de-CieSMCUp.js.map +0 -1
- package/dist/cdn/chunks/draggable-JcMTNF3U.js.map +0 -1
- package/dist/cdn/chunks/en-D0t_2Fq_.js.map +0 -1
- package/dist/cdn/chunks/es-DwDoNuLM.js.map +0 -1
- package/dist/cdn/chunks/fr-CSEEzv1_.js.map +0 -1
- package/dist/cdn/chunks/icons-Cp4ZIJw-.js.map +0 -1
- package/dist/cdn/chunks/nl-xyk1T2mA.js.map +0 -1
- package/dist/cdn/chunks/pt-BR-yr6uOJgn.js.map +0 -1
- package/dist/cdn/chunks/src-B8W42vT-.js.map +0 -1
- package/dist/cdn/chunks/tiptap-rsib432n.js.map +0 -1
- package/dist/cdn/chunks/useEditorCore-DfW-thCr.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"nl-xyk1T2mA.js","names":[],"sources":["../../../src/i18n/locales/nl.ts"],"sourcesContent":["import type en from \"./en\";\n\nconst nl: typeof en = {\n footer: {\n poweredBy: \"Mogelijk gemaakt door\",\n openSource: \"Open Source\",\n },\n history: {\n undo: \"Ongedaan maken\",\n redo: \"Opnieuw\",\n collabWarning:\n \"Ongedaan maken kan recente wijzigingen van medewerkers beïnvloeden\",\n },\n viewport: {\n label: \"Weergave\",\n desktop: \"Desktop\",\n mobile: \"Mobiel\",\n },\n darkMode: {\n enable: \"Voorbeeld in donkere modus\",\n disable: \"Voorbeeld in lichte modus\",\n },\n previewMode: {\n enable: \"Voorbeeldmodus\",\n disable: \"Voorbeeld sluiten\",\n },\n blocks: {\n section: \"Sectie\",\n image: \"Afbeelding\",\n title: \"Titel\",\n paragraph: \"Alinea\",\n button: \"Knop\",\n divider: \"Scheidingslijn\",\n video: \"Video\",\n social: \"Sociale media\",\n spacer: \"Tussenruimte\",\n html: \"HTML\",\n menu: \"Menu\",\n table: \"Tabel\",\n countdown: \"Aftelklok\",\n },\n sidebar: {\n content: \"Inhoud\",\n settings: \"Instellingen\",\n noSelection: \"Geen element geselecteerd\",\n noSelectionHint: \"Selecteer een blok op het canvas om het te bewerken\",\n },\n toolbar: {\n duplicate: \"Dupliceren\",\n delete: \"Verwijderen\",\n },\n titleEditor: {\n toolbar: \"Titelopmaak\",\n bold: \"Vet (Ctrl+B)\",\n italic: \"Cursief (Ctrl+I)\",\n addLink: \"Link toevoegen\",\n },\n paragraphEditor: {\n toolbar: \"Tekstopmaak\",\n bold: \"Vet (Ctrl+B)\",\n italic: \"Cursief (Ctrl+I)\",\n underline: \"Onderstreept (Ctrl+U)\",\n strikethrough: \"Doorgehaald\",\n subscript: \"Subscript\",\n superscript: \"Superscript\",\n addLink: \"Link toevoegen\",\n bulletList: \"Opsommingslijst\",\n numberedList: \"Genummerde lijst\",\n alignLeft: \"Links uitlijnen\",\n alignCenter: \"Centreren\",\n alignRight: \"Rechts uitlijnen\",\n clearFormatting: \"Opmaak wissen\",\n insertEmoji: \"Emoji invoegen\",\n fontFamily: \"Lettertype\",\n defaultFont: \"Standaard\",\n fontSize: \"Tekengrootte\",\n defaultSize: \"Standaard\",\n textColor: \"Tekstkleur\",\n highlightColor: \"Markeerkleur\",\n lineHeight: \"Regelafstand\",\n letterSpacing: \"Letterafstand\",\n emojiItemLabel: \"Emoji {emoji} invoegen\",\n closeEmojiPicker: \"Emoji-kiezer sluiten\",\n },\n blockActions: {\n drag: \"Sleep om te herschikken, of druk op de spatiebalk om met het toetsenbord te verplaatsen\",\n dragLifted:\n \"{block} wordt verplaatst. Gebruik de pijltjestoetsen omhoog en omlaag om te herpositioneren, spatiebalk of Enter om neer te zetten, Escape om te annuleren.\",\n duplicate: \"Blok dupliceren\",\n delete: \"Blok verwijderen\",\n hiddenOnViewport: \"Verborgen op {viewport}\",\n saveAsBlock: \"Opslaan als blok\",\n conditionToggle: \"Weergavevoorwaarde in- of uitschakelen\",\n comments: \"Opmerkingen ({count})\",\n lifted: \"{block} opgetild. Positie {position} van {total}.\",\n moved: \"{block} verplaatst naar positie {position} van {total}.\",\n dropped: \"{block} neergezet op positie {position} van {total}.\",\n cancelled:\n \"Verplaatsing geannuleerd. {block} is terug op positie {position}.\",\n },\n section: {\n dropHere: \"Sleep blokken hierheen\",\n columns: \"Kolommen\",\n column1: \"1 kolom\",\n column2: \"2 kolommen\",\n column3: \"3 kolommen\",\n ratio12: \"Verhouding 1:2\",\n ratio21: \"Verhouding 2:1\",\n borderRadius: \"Hoekafronding\",\n wrapperEnable: \"Omhulsel toevoegen\",\n stackOnMobile: \"Stapelen op mobiel\",\n },\n linkDialog: {\n editLink: \"Link bewerken\",\n insertLink: \"Link invoegen\",\n updateLink: \"Link bijwerken\",\n removeLink: \"Link verwijderen\",\n cancel: \"Annuleren\",\n urlPlaceholder: \"https://example.com\",\n urlLabel: \"URL\",\n colorLabel: \"Linkkleur\",\n },\n title: {\n level: \"Titelniveau\",\n heading1: \"Titel 1 (36px)\",\n heading2: \"Titel 2 (28px)\",\n heading3: \"Titel 3 (22px)\",\n heading4: \"Titel 4 (18px)\",\n fontFamily: \"Lettertype\",\n inheritFont: \"Lettertype van het sjabloon gebruiken\",\n color: \"Kleur\",\n align: \"Uitlijnen\",\n alignLeft: \"Links\",\n alignCenter: \"Midden\",\n alignRight: \"Rechts\",\n },\n emoji: {\n smileys: \"Smileys\",\n gestures: \"Gebaren\",\n objects: \"Objecten\",\n },\n image: {\n imageUrl: \"URL van de afbeelding\",\n imageUrlPlaceholder: \"https://...\",\n altText: \"Alt-tekst\",\n altTextPlaceholder: \"Beschrijving van de afbeelding\",\n width: \"Breedte\",\n fullWidth: \"Volledige breedte\",\n widthCustom: \"Aangepast\",\n linkUrl: \"Link-URL\",\n openInNewTab: \"Openen in nieuw tabblad\",\n placeholderUrl: \"Tijdelijke afbeelding\",\n placeholderUrlPlaceholder: \"https://... (alleen tijdens ontwerp)\",\n placeholderUrlTooltip:\n \"Omdat de afbeeldings-URL een samenvoegveld gebruikt, kunt u hier een echte afbeelding opgeven om de lay-out tijdens het ontwerpen te bekijken. Deze wordt niet opgenomen in het eindresultaat.\",\n clickToAdd: \"Klik om een afbeeldings-URL toe te voegen\",\n browseMedia: \"Mediabibliotheek openen\",\n dropToUpload: \"Sleep een afbeelding hierheen om te uploaden\",\n uploading: \"Uploaden…\",\n decorative: \"Decoratieve afbeelding\",\n decorativeHint:\n \"Verborgen voor schermlezers. Alleen gebruiken voor tussenruimtes en visuele versieringen.\",\n },\n video: {\n videoUrl: \"URL van de video\",\n videoUrlPlaceholder: \"https://youtube.com/...\",\n youtube: \"YouTube\",\n vimeo: \"Vimeo\",\n detected: \"Video gedetecteerd — de miniatuur wordt automatisch gegenereerd\",\n openInNewTab: \"Openen in nieuw tabblad\",\n customThumbnail: \"Aangepaste miniatuur\",\n optional: \"(optioneel)\",\n thumbnailPlaceholder: \"Automatisch gegenereerd uit de video-URL\",\n altText: \"Alt-tekst\",\n altTextPlaceholder: \"Beschrijving van de video\",\n width: \"Breedte\",\n fullWidth: \"Volledige breedte\",\n placeholderUrl: \"Tijdelijke miniatuur\",\n placeholderUrlPlaceholder: \"https://... (alleen tijdens ontwerp)\",\n placeholderUrlTooltip:\n \"Omdat de video-URL een samenvoegveld gebruikt, kunt u hier een echte miniatuur opgeven om de lay-out tijdens het ontwerpen te bekijken. Deze wordt niet opgenomen in het eindresultaat.\",\n addVideo: \"Voeg een video-URL toe\",\n },\n button: {\n fontFamily: \"Lettertype\",\n inheritFont: \"Lettertype van het sjabloon gebruiken\",\n text: \"Tekst\",\n url: \"URL\",\n urlPlaceholder: \"https://...\",\n openInNewTab: \"Openen in nieuw tabblad\",\n background: \"Achtergrond\",\n textColor: \"Tekstkleur\",\n borderRadius: \"Hoekafronding\",\n fontSize: \"Tekengrootte\",\n width: \"Breedte\",\n widthAuto: \"Aanpassen aan inhoud\",\n fullWidth: \"Volledige breedte\",\n widthCustom: \"Aangepast\",\n },\n divider: {\n style: \"Stijl\",\n solid: \"Doorlopend\",\n dashed: \"Streepjes\",\n dotted: \"Stippellijn\",\n color: \"Kleur\",\n thickness: \"Dikte\",\n },\n social: {\n icons: \"Iconen\",\n addIcon: \"Icoon toevoegen\",\n addIcons: \"Voeg sociale-media-iconen toe\",\n removeIcon: \"Verwijderen\",\n platform: \"Platform\",\n url: \"URL\",\n urlPlaceholder: \"https://...\",\n style: \"Stijl\",\n styleSolid: \"Gevuld\",\n styleOutlined: \"Omlijnd\",\n styleRounded: \"Afgerond\",\n styleSquare: \"Vierkant\",\n styleCircle: \"Cirkel\",\n size: \"Grootte\",\n sizeSmall: \"S\",\n sizeMedium: \"M\",\n sizeLarge: \"L\",\n spacing: \"Afstand\",\n align: \"Uitlijning\",\n platforms: {\n facebook: \"Facebook\",\n twitter: \"X (Twitter)\",\n instagram: \"Instagram\",\n linkedin: \"LinkedIn\",\n youtube: \"YouTube\",\n tiktok: \"TikTok\",\n pinterest: \"Pinterest\",\n email: \"E-mail\",\n website: \"Website\",\n whatsapp: \"WhatsApp\",\n telegram: \"Telegram\",\n discord: \"Discord\",\n snapchat: \"Snapchat\",\n reddit: \"Reddit\",\n github: \"GitHub\",\n dribbble: \"Dribbble\",\n behance: \"Behance\",\n },\n },\n menu: {\n items: \"Menu-items\",\n addItem: \"Item toevoegen\",\n removeItem: \"Verwijderen\",\n text: \"Tekst\",\n url: \"URL\",\n urlPlaceholder: \"https://example.com\",\n openInNewTab: \"Openen in nieuw tabblad\",\n bold: \"Vet\",\n underline: \"Onderstreept\",\n color: \"Kleur\",\n linkColor: \"Linkkleur\",\n fontSize: \"Tekengrootte\",\n fontFamily: \"Lettertype\",\n separator: \"Scheidingsteken\",\n separatorColor: \"Kleur van het scheidingsteken\",\n spacing: \"Afstand\",\n textAlign: \"Uitlijning\",\n addLinks: \"Voeg menulinks toe\",\n },\n table: {\n dimensions: \"Afmetingen\",\n rows: \"Rijen\",\n columns: \"Kolommen\",\n addRow: \"Rij toevoegen\",\n removeRow: \"Rij verwijderen\",\n addColumn: \"Kolom toevoegen\",\n removeColumn: \"Kolom verwijderen\",\n hasHeaderRow: \"Koprij\",\n headerBackgroundColor: \"Achtergrond van de koprij\",\n noHeaderBg: \"Geen achtergrond\",\n borderColor: \"Randkleur\",\n borderWidth: \"Randdikte\",\n cellPadding: \"Binnenmarge van cellen\",\n fontFamily: \"Lettertype\",\n fontSize: \"Tekengrootte\",\n color: \"Tekstkleur\",\n textAlign: \"Uitlijning\",\n cellPlaceholder: \"Voer tekst in...\",\n empty: \"Voeg een tabel toe\",\n },\n spacer: {\n height: \"Hoogte\",\n },\n countdown: {\n targetDate: \"Doeldatum\",\n timezone: \"Tijdzone\",\n display: \"Weergave\",\n days: \"Dagen\",\n hours: \"Uren\",\n minutes: \"Minuten\",\n seconds: \"Seconden\",\n separator: \"Scheidingsteken\",\n fontFamily: \"Lettertype\",\n inheritFont: \"Standaard\",\n digitFontSize: \"Cijfergrootte\",\n digitColor: \"Cijferkleur\",\n labelColor: \"Labelkleur\",\n labelFontSize: \"Labelgrootte\",\n background: \"Achtergrond\",\n labels: \"Labels\",\n expiry: \"Bericht na afloop\",\n expiredMessagePlaceholder: \"Deze aanbieding is verlopen\",\n expiredImageUrl: \"URL van de afbeelding na afloop\",\n hideOnExpiry: \"Verbergen na afloop\",\n setDate: \"Stel een doeldatum in via het instellingenpaneel\",\n hidden: \"Verborgen (verlopen)\",\n },\n customBlocks: {\n definitionNotFound: \"Onbekend bloktype — dit blok is niet geregistreerd\",\n renderError:\n \"Dit blok kon niet worden weergegeven. Controleer het bloksjabloon op fouten.\",\n fields: {\n required: \"Verplicht\",\n addItem: \"Item toevoegen\",\n removeItem: \"Verwijderen\",\n maxItemsReached: \"Maximaal aantal items bereikt\",\n minItemsRequired: \"Minimaal {count} items vereist\",\n },\n toolbar: {\n noDefinition:\n \"Registreer dit bloktype in uw SDK-configuratie om de eigenschappen te bewerken\",\n },\n dataSource: {\n fetchButton: \"Inhoud laden\",\n changeButton: \"Wijzigen\",\n fetching: \"Laden...\",\n readOnlyTooltip: \"Deze waarde wordt geladen uit uw gegevensbron\",\n fetchError: \"Inhoud laden mislukt\",\n },\n },\n html: {\n content: \"HTML-inhoud\",\n preview: \"Aangepast HTML-blok\",\n empty: \"Voeg HTML-inhoud toe in het paneel\",\n sanitizationHint:\n \"HTML wordt ongewijzigd geëxporteerd en niet opgeschoond — zorg dat de inhoud veilig is.\",\n },\n blockSettings: {\n spacing: \"Afstand\",\n padding: \"Binnenmarge\",\n background: \"Achtergrond\",\n color: \"Kleur\",\n display: \"Weergave\",\n showOnDesktop: \"Tonen op desktop\",\n showOnMobile: \"Tonen op mobiel\",\n hiddenOnDevice: \"Verborgen op {device}\",\n displayCondition: \"Weergavevoorwaarde\",\n selectCondition: \"Voorwaarde selecteren\",\n removeCondition: \"Voorwaarde verwijderen\",\n noCondition: \"Altijd zichtbaar\",\n conditionApplied: \"Voorwaarde toegepast\",\n customCondition: \"Aangepaste voorwaarde\",\n customConditionLabel: \"Naam van de voorwaarde\",\n customConditionBefore: \"Voor (openingslogica)\",\n customConditionAfter: \"Na (sluitingslogica)\",\n applyCondition: \"Toepassen\",\n cancelCondition: \"Annuleren\",\n customBadge: \"Aangepast\",\n restoreHiddenBlocks: \"Alle verborgen blokken tonen\",\n },\n templateSettings: {\n layout: \"Lay-out\",\n widthPreset: \"Vooraf ingestelde breedte\",\n customWidth: \"Aangepaste breedte\",\n appearance: \"Uiterlijk\",\n backgroundColor: \"Achtergrondkleur\",\n textColor: \"Tekstkleur\",\n linkColor: \"Linkkleur\",\n linkUnderline: \"Links onderstrepen\",\n fontFamily: \"Lettertype\",\n preheaderText: \"Voorbeeldtekst (preheader)\",\n preheaderTextPlaceholder:\n \"Voorbeeldtekst die na de onderwerpregel in de inbox wordt getoond...\",\n preheaderTextHint:\n \"Deze tekst verschijnt na de onderwerpregel in de voorbeelden van e-mailprogramma's. Samenvoegvelden worden ondersteund.\",\n language: \"Taal\",\n contentLocale: \"Taal van de inhoud\",\n contentLocaleHint:\n \"BCP 47-code (bv. nl, de, pt-BR). Bepaalt het lang-attribuut van de gerenderde e-mail zodat schermlezers de inhoud correct uitspreken.\",\n tips: \"Tips\",\n tip1: \"600px is de standaardbreedte voor e-mailsjablonen\",\n tip2: \"Gebruik webveilige lettertypen voor de beste compatibiliteit\",\n tip3: \"Lichte achtergronden lezen het prettigst\",\n },\n spacingControl: {\n lockAll: \"Alle zijden vergrendelen\",\n unlock: \"Zijden ontgrendelen\",\n top: \"Boven\",\n right: \"Rechts\",\n bottom: \"Onder\",\n left: \"Links\",\n decreaseTop: \"Boven verkleinen\",\n increaseTop: \"Boven vergroten\",\n decreaseLeft: \"Links verkleinen\",\n increaseLeft: \"Links vergroten\",\n decreaseRight: \"Rechts verkleinen\",\n increaseRight: \"Rechts vergroten\",\n decreaseBottom: \"Onder verkleinen\",\n increaseBottom: \"Onder vergroten\",\n },\n colorPicker: {\n pickColor: \"Kies een kleur\",\n hexValue: \"Hexadecimale kleurwaarde\",\n notSet: \"Niet ingesteld\",\n clear: \"Kleur wissen\",\n presetColors: \"Vooraf ingestelde kleuren\",\n },\n mergeTag: {\n clickToEdit: \"Klik om te bewerken\",\n remove: \"Samenvoegveld verwijderen\",\n insert: \"Samenvoegveld invoegen\",\n insertShort: \"Samenvoegveld\",\n editValue: \"Waarde van het samenvoegveld bewerken\",\n deleteMergeTag: \"Samenvoegveld verwijderen\",\n suggestionEmpty: \"Geen overeenkomende samenvoegvelden\",\n picker: {\n title: \"Samenvoegveld invoegen\",\n searchPlaceholder: \"Samenvoegvelden zoeken\",\n searchAriaLabel: \"Samenvoegvelden zoeken\",\n noResults: \"Geen overeenkomende samenvoegvelden\",\n empty: \"Geen samenvoegvelden geconfigureerd\",\n otherGroup: \"Overige\",\n cancel: \"Annuleren\",\n close: \"Sluiten\",\n groupCount: \"{count}\",\n sample: \"Voorbeeld: {sample}\",\n },\n },\n logicTag: {\n insert: \"Logica invoegen\",\n insertShort: \"Logica\",\n picker: {\n title: \"Logica invoegen\",\n searchPlaceholder: \"Logicatags zoeken\",\n searchAriaLabel: \"Logicatags zoeken\",\n noResults: \"Geen overeenkomende logicatags\",\n empty: \"Geen logicatags geconfigureerd\",\n otherGroup: \"Overige\",\n close: \"Sluiten\",\n },\n },\n canvas: {\n noBlocks: \"Nog geen blokken\",\n dragHint: \"Begin vanaf nul door blokken vanuit de zijbalk te slepen\",\n dropHere: \"Hier neerzetten\",\n aiHintChat: \"of laat\",\n aiHintChatSuffix:\n \"in enkele seconden een volledig sjabloon voor u genereren\",\n aiHintDesign:\n \"Heeft u al een ontwerp? Upload een schermafbeelding, afbeelding of PDF en\",\n aiHintDesignSuffix: \"maakt het direct na\",\n },\n mediaLibrary: {\n title: \"Mediabibliotheek\",\n searchPlaceholder: \"Bestanden zoeken...\",\n allFiles: \"Alle bestanden\",\n filterAll: \"Alle types\",\n filterImages: \"Afbeeldingen\",\n filterDocuments: \"Documenten\",\n filterVideos: \"Video's\",\n filterAudio: \"Audio\",\n newFolder: \"Nieuwe map\",\n folderName: \"Mapnaam\",\n noFiles: \"Geen bestanden gevonden\",\n dropOrClick: \"Sleep bestanden hierheen of klik om te uploaden\",\n acceptedFormats: \"Afbeeldingen, PDF, video, audio, documenten (max. 10 MB)\",\n uploading: \"Uploaden...\",\n uploadingProgress: \"Uploaden van {current} van {total}...\",\n selectImage: \"Afbeelding selecteren\",\n selectFile: \"Bestand selecteren\",\n deleteSelected: \"Verwijderen\",\n copyUrl: \"URL kopiëren\",\n copied: \"Gekopieerd!\",\n browseMedia: \"Mediabibliotheek openen\",\n renameFolder: \"Map hernoemen\",\n addSubfolder: \"Submap toevoegen\",\n subfolderName: \"Naam van de submap\",\n sortNewest: \"Nieuwste eerst\",\n sortOldest: \"Oudste eerst\",\n sortNameAsc: \"Naam A-Z\",\n sortNameDesc: \"Naam Z-A\",\n sortSizeAsc: \"Kleinste eerst\",\n sortSizeDesc: \"Grootste eerst\",\n moveSelected: \"Verplaatsen\",\n moveToRoot: \"Alle bestanden\",\n currentFolder: \"(huidige)\",\n confirmDelete: \"Dit bestand verwijderen?\",\n renameFile: \"Hernoemen\",\n editFile: \"Bestand bewerken\",\n fileName: \"Bestandsnaam\",\n altText: \"Alt-tekst\",\n altTextPlaceholder: \"Beschrijf deze afbeelding voor toegankelijkheid\",\n saveChanges: \"Opslaan\",\n cancel: \"Annuleren\",\n frequentlyUsed: \"Vaak gebruikt\",\n deleteWarningTitle: \"Bestand verwijderen\",\n deleteWarningMessage:\n \"Dit bestand wordt definitief verwijderd en kan niet worden hersteld.\",\n deleteWarningUsageNote:\n \"De volgende bestanden worden gebruikt in sjablonen. Verwijderen kan die sjablonen breken.\",\n deleteAnyway: \"Bestand verwijderen\",\n usedInTemplates: \"Gebruikt in {count} sjabloon(en)\",\n viewGrid: \"Rasterweergave\",\n viewList: \"Lijstweergave\",\n showFolders: \"Mappen tonen\",\n hideFolders: \"Mappen verbergen\",\n importFromUrl: \"Importeren vanaf URL\",\n importUrlPlaceholder: \"https://example.com/image.jpg\",\n import: \"Importeren\",\n importing: \"Importeren...\",\n importError: \"Importeren vanaf URL mislukt\",\n conversionLabel: \"Grootte\",\n conversionOriginal: \"Origineel\",\n conversionSmall: \"Klein (150px)\",\n conversionMedium: \"Middel (600px)\",\n conversionLarge: \"Groot (1200px)\",\n replaceFile: \"Bestand vervangen\",\n replaceWarningTitle: \"Bestand vervangen\",\n replaceWarningMessage:\n \"U staat op het punt dit bestand te vervangen. De vervanging moet dezelfde bestandsextensie hebben ({extension}).\",\n replaceWarningUsageNote:\n \"Dit bestand wordt gebruikt in {count} sjabloon(en). Vervangen werkt alle verwijzingen bij.\",\n replaceSelectFile: \"Vervangend bestand selecteren\",\n replace: \"Vervangen\",\n replacing: \"Vervangen...\",\n replaceError: \"Bestand vervangen mislukt\",\n saving: \"Opslaan...\",\n cropAspectRatio: \"Beeldverhouding\",\n cropFree: \"Vrij\",\n cropSquare: \"1:1\",\n cropLandscape43: \"4:3\",\n cropLandscape169: \"16:9\",\n cropOriginal: \"Origineel\",\n cropMaxWidth: \"Max. breedte\",\n cropMaxHeight: \"Max. hoogte\",\n cropOutputSize: \"Uitvoergrootte\",\n cropPixels: \"px\",\n cropOptional: \"(optioneel)\",\n storageTooltip: \"{used} van {total} gebruikt ({remaining} resterend)\",\n },\n savedBlocks: {\n title: \"Opgeslagen blokken\",\n saveAsBlock: \"Opslaan als blok\",\n name: \"Naam\",\n namePlaceholder: \"bv. Koptekst, Voettekst, CTA...\",\n save: \"Blok opslaan\",\n saving: \"Opslaan...\",\n cancel: \"Annuleren\",\n empty: \"Nog geen opgeslagen blokken\",\n emptyHint:\n \"Sla blokken uit uw sjablonen op om ze later opnieuw te gebruiken.\",\n noResults: \"Geen opgeslagen blokken gevonden voor uw zoekopdracht\",\n search: \"Opgeslagen blokken zoeken...\",\n loading: \"Opgeslagen blokken laden…\",\n category: \"Categorie\",\n categoryPlaceholder: \"bv. Kopteksten, Promoties... (optioneel)\",\n allCategories: \"Alle categorieën\",\n filterByCategory: \"Filteren op categorie\",\n insert: \"Invoegen\",\n rename: \"Hernoemen\",\n delete: \"Verwijderen\",\n deleteConfirm: \"Dit opgeslagen blok verwijderen?\",\n blockCount: \"{count} blok(ken)\",\n browse: \"Opgeslagen blokken bekijken\",\n selectToPreview: \"Selecteer een opgeslagen blok voor een voorbeeld\",\n insertAtBeginning: \"Aan het begin\",\n insertAfterBlock: \"Na {block}\",\n insertAtEnd: \"Aan het einde\",\n insertPosition: \"Invoegpositie\",\n close: \"Sluiten\",\n pickToolbar: \"Selectie van opgeslagen blokken\",\n pickCount: \"{count} blok(ken) geselecteerd\",\n pickHint: \"Klik op blokken om ze toe te voegen of te verwijderen\",\n savingCount: \"{count} blok(ken) opslaan:\",\n reorderHint:\n \"Sleep om te herschikken — blokken worden in deze volgorde opgeslagen\",\n reorderHandle: \"{block} herschikken, positie {position} van {total}\",\n reorderAnnouncement:\n \"{block} verplaatst naar positie {position} van {total}\",\n expand: \"Uitklappen\",\n collapse: \"Inklappen\",\n expandPreview: \"Voorbeeld van {block} uitklappen\",\n collapsePreview: \"Voorbeeld van {block} inklappen\",\n time: {\n justNow: \"Zojuist\",\n minutesAgo: \"{minutes} min geleden\",\n hoursAgo: \"{hours} u geleden\",\n daysAgo: \"{days} d geleden\",\n },\n },\n previewResolution: {\n resolving: \"Voorbeeld wordt opgelost…\",\n failed:\n \"Het voorbeeld kon niet worden opgelost — het niet-opgeloste sjabloon wordt weergegeven.\",\n hint: \"Het voorbeeld gebruikt opgeloste gegevens uit uw backend.\",\n },\n mergeTagPreview: {\n label: \"Weergave van samenvoegvelden\",\n sample: \"Voorbeeldwaarde\",\n labelView: \"Naam\",\n },\n testEmail: {\n title: \"Test-e-mail verzenden\",\n recipientLabel: \"Ontvanger\",\n recipientPlaceholder: \"u@voorbeeld.nl\",\n invalidAddress: \"Voer een geldig e-mailadres in.\",\n preview: \"Voorbeeld\",\n previewHint:\n \"Samenvoegvelden worden onopgelost weergegeven — uw backend vult ze in.\",\n previewHintSample:\n \"Samenvoegvelden tonen voorbeeldwaarden — uw backend vult de echte gegevens in.\",\n recipientNotAllowed:\n \"Dit adres staat niet in de lijst met toegestane ontvangers.\",\n send: \"Verzenden\",\n sending: \"Wordt verzonden...\",\n cancel: \"Annuleren\",\n success: \"Test-e-mail succesvol verzonden\",\n button: \"Test\",\n },\n sidebarNav: {\n browseSavedBlocks: \"Opgeslagen blokken bekijken\",\n expandSidebar: \"Blokzijbalk uitvouwen\",\n palette: \"Blokkenpalet\",\n insertBlock: \"Blok {block} invoegen\",\n },\n landmarks: {\n canvas: \"E-mailcanvas\",\n blockToolbar: \"Blokeigenschappen\",\n rightSidebar: \"Blokeigenschappen en sjablooninstellingen\",\n reorderAnnouncements: \"Aankondigingen van blokherschikking\",\n },\n errors: {\n editorLoading: \"Editor laden...\",\n editorLoadFailed: \"Editor laden mislukt.\",\n retry: \"Opnieuw proberen\",\n },\n issues: {\n panelTitle: \"Problemen\",\n panelTabLabel: \"Problemen\",\n groupErrors: \"Fouten\",\n groupWarnings: \"Waarschuwingen\",\n groupInfo: \"Info\",\n jump: \"Naar het blok springen\",\n fix: \"Herstellen\",\n emptyState: \"Geen problemen — ziet er goed uit.\",\n badgeError: \"Bevat fouten\",\n badgeWarning: \"Bevat waarschuwingen\",\n issueCountTooltip: \"{count} probleem(en)\",\n },\n smallScreen: {\n title: \"Groter scherm vereist\",\n message:\n \"De editor heeft meer ruimte nodig dan dit scherm biedt. Open hem op een tablet of desktop om te beginnen met bewerken.\",\n },\n};\n\nexport default nl;\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pt-BR-yr6uOJgn.js","names":[],"sources":["../../../src/i18n/locales/pt-BR.ts"],"sourcesContent":["import type en from \"./en\";\n\nconst ptBR: typeof en = {\n // Footer (OSS only)\n footer: {\n poweredBy: \"Desenvolvido por\",\n openSource: \"Código Aberto\",\n },\n\n // History (undo/redo)\n history: {\n undo: \"Desfazer\",\n redo: \"Refazer\",\n collabWarning: \"Desfazer pode afetar alterações recentes de colaboradores\",\n },\n\n // Viewport toggle\n viewport: {\n label: \"Viewport\",\n desktop: \"Desktop\",\n mobile: \"Mobile\",\n },\n\n // Dark mode preview\n darkMode: {\n enable: \"Visualizar Modo Escuro\",\n disable: \"Visualizar Modo Claro\",\n },\n\n // Preview mode\n previewMode: {\n enable: \"Modo de Visualização\",\n disable: \"Sair da Visualização\",\n },\n\n // Sidebar - Block types\n blocks: {\n section: \"Seção\",\n image: \"Imagem\",\n title: \"Título\",\n paragraph: \"Parágrafo\",\n button: \"Botão\",\n divider: \"Divisor\",\n video: \"Vídeo\",\n social: \"Redes Sociais\",\n spacer: \"Espaçador\",\n html: \"HTML\",\n menu: \"Menu\",\n table: \"Tabela\",\n countdown: \"Contagem Regressiva\",\n },\n\n // Right sidebar\n sidebar: {\n content: \"Conteúdo\",\n settings: \"Configurações\",\n noSelection: \"Nenhum elemento selecionado\",\n noSelectionHint: \"Selecione um bloco na tela para editá-lo\",\n },\n\n // Toolbar - Common\n toolbar: {\n duplicate: \"Duplicar\",\n delete: \"Excluir\",\n },\n\n // Title editor toolbar\n titleEditor: {\n toolbar: \"Formatação de título\",\n bold: \"Negrito (Ctrl+B)\",\n italic: \"Itálico (Ctrl+I)\",\n addLink: \"Adicionar Link\",\n },\n\n // Paragraph editor toolbar\n paragraphEditor: {\n toolbar: \"Formatação de texto\",\n bold: \"Negrito (Ctrl+B)\",\n italic: \"Itálico (Ctrl+I)\",\n underline: \"Sublinhado (Ctrl+U)\",\n strikethrough: \"Tachado\",\n subscript: \"Subscrito\",\n superscript: \"Sobrescrito\",\n addLink: \"Adicionar Link\",\n bulletList: \"Lista com Marcadores\",\n numberedList: \"Lista Numerada\",\n alignLeft: \"Alinhar à Esquerda\",\n alignCenter: \"Centralizar\",\n alignRight: \"Alinhar à Direita\",\n clearFormatting: \"Limpar Formatação\",\n insertEmoji: \"Inserir Emoji\",\n fontFamily: \"Família da Fonte\",\n defaultFont: \"Padrão\",\n fontSize: \"Tamanho da Fonte\",\n defaultSize: \"Padrão\",\n textColor: \"Cor do Texto\",\n highlightColor: \"Cor de Destaque\",\n lineHeight: \"Altura da Linha\",\n letterSpacing: \"Espaçamento entre Letras\",\n emojiItemLabel: \"Inserir emoji {emoji}\",\n closeEmojiPicker: \"Fechar seletor de emojis\",\n },\n\n // Block actions (BlockWrapper)\n blockActions: {\n drag: \"Arraste para reordenar, ou pressione Espaço para mover com o teclado\",\n dragLifted:\n \"Movendo {block}. Use as setas para cima e para baixo para reposicionar, Espaço ou Enter para soltar, Escape para cancelar.\",\n duplicate: \"Duplicar bloco\",\n delete: \"Excluir bloco\",\n hiddenOnViewport: \"Oculto em {viewport}\",\n saveAsBlock: \"Salvar como Bloco\",\n conditionToggle: \"Alternar condição de exibição\",\n comments: \"Comentários ({count})\",\n lifted: \"{block} levantado. Posição {position} de {total}.\",\n moved: \"{block} movido para a posição {position} de {total}.\",\n dropped: \"{block} solto na posição {position} de {total}.\",\n cancelled: \"Movimento cancelado. {block} retornou à posição {position}.\",\n },\n\n // Toolbar - Section\n section: {\n dropHere: \"Solte blocos aqui\",\n columns: \"Colunas\",\n column1: \"1 Coluna\",\n column2: \"2 Colunas\",\n column3: \"3 Colunas\",\n ratio12: \"Proporção 1:2\",\n ratio21: \"Proporção 2:1\",\n borderRadius: \"Arredondamento das Bordas\",\n wrapperEnable: \"Adicionar wrapper\",\n stackOnMobile: \"Empilhar no celular\",\n },\n\n // Text editor link dialog\n linkDialog: {\n editLink: \"Editar Link\",\n insertLink: \"Inserir Link\",\n updateLink: \"Atualizar Link\",\n removeLink: \"Remover Link\",\n cancel: \"Cancelar\",\n urlPlaceholder: \"https://exemplo.com\",\n urlLabel: \"URL\",\n colorLabel: \"Cor do Link\",\n },\n\n // Toolbar - Title\n title: {\n level: \"Nível do Cabeçalho\",\n heading1: \"Cabeçalho 1 (36px)\",\n heading2: \"Cabeçalho 2 (28px)\",\n heading3: \"Cabeçalho 3 (22px)\",\n heading4: \"Cabeçalho 4 (18px)\",\n fontFamily: \"Família da Fonte\",\n inheritFont: \"Usar fonte do template\",\n color: \"Cor\",\n align: \"Alinhamento\",\n alignLeft: \"Esquerda\",\n alignCenter: \"Centro\",\n alignRight: \"Direita\",\n },\n\n // Emoji picker\n emoji: {\n smileys: \"Sorrisos\",\n gestures: \"Gestos\",\n objects: \"Objetos\",\n },\n\n // Toolbar - Image\n image: {\n imageUrl: \"URL da Imagem\",\n imageUrlPlaceholder: \"https://...\",\n altText: \"Texto Alternativo\",\n altTextPlaceholder: \"Descrição da imagem\",\n width: \"Largura\",\n fullWidth: \"Largura Total\",\n widthCustom: \"Personalizada\",\n linkUrl: \"URL do Link\",\n openInNewTab: \"Abrir em nova aba\",\n placeholderUrl: \"Imagem de Espaço Reservado\",\n placeholderUrlPlaceholder: \"https://... (somente em design)\",\n placeholderUrlTooltip:\n \"Como a URL da imagem usa uma merge tag, você pode fornecer uma imagem real aqui para visualizar o layout durante o design. Isso não é incluído na saída final.\",\n clickToAdd: \"Clique para adicionar a URL da imagem\",\n browseMedia: \"Explorar Mídia\",\n dropToUpload: \"Solte a imagem para enviar\",\n uploading: \"Enviando…\",\n decorative: \"Imagem decorativa\",\n decorativeHint:\n \"Oculta para leitores de tela. Use apenas para espaçadores e elementos visuais.\",\n },\n\n // Toolbar - Video\n video: {\n videoUrl: \"URL do Vídeo\",\n videoUrlPlaceholder: \"https://youtube.com/...\",\n youtube: \"YouTube\",\n vimeo: \"Vimeo\",\n detected: \"Vídeo detectado — a miniatura será gerada automaticamente\",\n openInNewTab: \"Abrir em nova aba\",\n customThumbnail: \"Miniatura Personalizada\",\n optional: \"(opcional)\",\n thumbnailPlaceholder: \"Gerada automaticamente a partir da URL do vídeo\",\n altText: \"Texto Alternativo\",\n altTextPlaceholder: \"Descrição do vídeo\",\n width: \"Largura\",\n fullWidth: \"Largura Total\",\n placeholderUrl: \"Miniatura de Espaço Reservado\",\n placeholderUrlPlaceholder: \"https://... (somente em design)\",\n placeholderUrlTooltip:\n \"Como a URL do vídeo usa uma merge tag, você pode fornecer uma miniatura real aqui para visualizar o layout durante o design. Isso não é incluído na saída final.\",\n addVideo: \"Adicionar URL de vídeo\",\n },\n\n // Toolbar - Button\n button: {\n fontFamily: \"Família da Fonte\",\n inheritFont: \"Usar fonte do template\",\n text: \"Texto\",\n url: \"URL\",\n urlPlaceholder: \"https://...\",\n openInNewTab: \"Abrir em nova aba\",\n background: \"Plano de Fundo\",\n textColor: \"Cor do Texto\",\n borderRadius: \"Arredondamento das Bordas\",\n fontSize: \"Tamanho da Fonte\",\n width: \"Largura\",\n widthAuto: \"Ajustar ao conteúdo\",\n fullWidth: \"Largura Total\",\n widthCustom: \"Personalizada\",\n },\n\n // Toolbar - Divider\n divider: {\n style: \"Estilo\",\n solid: \"Sólido\",\n dashed: \"Tracejado\",\n dotted: \"Pontilhado\",\n color: \"Cor\",\n thickness: \"Espessura\",\n },\n\n // Toolbar - Social Icons\n social: {\n icons: \"Ícones\",\n addIcon: \"Adicionar Ícone\",\n addIcons: \"Adicionar ícones de redes sociais\",\n removeIcon: \"Remover\",\n platform: \"Plataforma\",\n url: \"URL\",\n urlPlaceholder: \"https://...\",\n style: \"Estilo\",\n styleSolid: \"Sólido\",\n styleOutlined: \"Contornado\",\n styleRounded: \"Arredondado\",\n styleSquare: \"Quadrado\",\n styleCircle: \"Circular\",\n size: \"Tamanho\",\n sizeSmall: \"P\",\n sizeMedium: \"M\",\n sizeLarge: \"G\",\n spacing: \"Espaçamento\",\n align: \"Alinhamento\",\n platforms: {\n facebook: \"Facebook\",\n twitter: \"X (Twitter)\",\n instagram: \"Instagram\",\n linkedin: \"LinkedIn\",\n youtube: \"YouTube\",\n tiktok: \"TikTok\",\n pinterest: \"Pinterest\",\n email: \"E-mail\",\n website: \"Site\",\n whatsapp: \"WhatsApp\",\n telegram: \"Telegram\",\n discord: \"Discord\",\n snapchat: \"Snapchat\",\n reddit: \"Reddit\",\n github: \"GitHub\",\n dribbble: \"Dribbble\",\n behance: \"Behance\",\n },\n },\n\n // Toolbar - Menu\n menu: {\n items: \"Itens do Menu\",\n addItem: \"Adicionar Item\",\n removeItem: \"Remover\",\n text: \"Texto\",\n url: \"URL\",\n urlPlaceholder: \"https://exemplo.com\",\n openInNewTab: \"Abrir em nova aba\",\n bold: \"Negrito\",\n underline: \"Sublinhado\",\n color: \"Cor\",\n linkColor: \"Cor do Link\",\n fontSize: \"Tamanho da Fonte\",\n fontFamily: \"Família da Fonte\",\n separator: \"Separador\",\n separatorColor: \"Cor do Separador\",\n spacing: \"Espaçamento\",\n textAlign: \"Alinhamento\",\n addLinks: \"Adicionar links ao menu\",\n },\n\n // Toolbar - Table\n table: {\n dimensions: \"Dimensões\",\n rows: \"Linhas\",\n columns: \"Colunas\",\n addRow: \"Adicionar Linha\",\n removeRow: \"Remover Linha\",\n addColumn: \"Adicionar Coluna\",\n removeColumn: \"Remover Coluna\",\n hasHeaderRow: \"Linha de cabeçalho\",\n headerBackgroundColor: \"Plano de Fundo do Cabeçalho\",\n noHeaderBg: \"Sem plano de fundo\",\n borderColor: \"Cor da Borda\",\n borderWidth: \"Espessura da Borda\",\n cellPadding: \"Preenchimento da Célula\",\n fontFamily: \"Família da Fonte\",\n fontSize: \"Tamanho da Fonte\",\n color: \"Cor do Texto\",\n textAlign: \"Alinhamento\",\n cellPlaceholder: \"Digite o texto...\",\n empty: \"Adicionar uma tabela\",\n },\n\n // Toolbar - Spacer\n spacer: {\n height: \"Altura\",\n },\n\n // Toolbar - Countdown\n countdown: {\n targetDate: \"Data Alvo\",\n timezone: \"Fuso Horário\",\n display: \"Exibição\",\n days: \"Dias\",\n hours: \"Horas\",\n minutes: \"Minutos\",\n seconds: \"Segundos\",\n separator: \"Separador\",\n fontFamily: \"Família da Fonte\",\n inheritFont: \"Padrão\",\n digitFontSize: \"Tamanho dos Dígitos\",\n digitColor: \"Cor dos Dígitos\",\n labelColor: \"Cor dos Rótulos\",\n labelFontSize: \"Tamanho dos Rótulos\",\n background: \"Plano de Fundo\",\n labels: \"Rótulos\",\n expiry: \"Mensagem de Expiração\",\n expiredMessagePlaceholder: \"Esta oferta expirou\",\n expiredImageUrl: \"URL da Imagem de Expiração\",\n hideOnExpiry: \"Ocultar ao expirar\",\n setDate: \"Defina uma data alvo no painel de configurações\",\n hidden: \"Oculto (expirado)\",\n },\n\n // Custom Blocks\n customBlocks: {\n definitionNotFound:\n \"Tipo de bloco desconhecido — este bloco não está registrado\",\n renderError:\n \"Este bloco não pôde ser renderizado. Verifique se há erros no template do bloco.\",\n fields: {\n required: \"Obrigatório\",\n addItem: \"Adicionar item\",\n removeItem: \"Remover\",\n maxItemsReached: \"Número máximo de itens atingido\",\n minItemsRequired: \"Mínimo de {count} itens obrigatório\",\n },\n toolbar: {\n noDefinition:\n \"Registre este tipo de bloco na sua configuração do SDK para editar suas propriedades\",\n },\n dataSource: {\n fetchButton: \"Carregar conteúdo\",\n changeButton: \"Alterar\",\n fetching: \"Carregando...\",\n readOnlyTooltip: \"Este valor é carregado da sua fonte de dados\",\n fetchError: \"Falha ao carregar conteúdo\",\n },\n },\n\n // Toolbar - HTML\n html: {\n content: \"Conteúdo HTML\",\n preview: \"Bloco HTML personalizado\",\n empty: \"Adicione conteúdo HTML no painel\",\n sanitizationHint:\n \"O HTML é exportado como está e não é sanitizado — garanta que o conteúdo seja seguro.\",\n },\n\n // Toolbar - Common block settings\n blockSettings: {\n spacing: \"Espaçamento\",\n padding: \"Preenchimento\",\n background: \"Plano de Fundo\",\n color: \"Cor\",\n display: \"Exibição\",\n showOnDesktop: \"Mostrar no desktop\",\n showOnMobile: \"Mostrar no mobile\",\n hiddenOnDevice: \"Oculto em {device}\",\n displayCondition: \"Condição de Exibição\",\n selectCondition: \"Selecionar condição\",\n removeCondition: \"Remover condição\",\n noCondition: \"Sempre visível\",\n conditionApplied: \"Condição aplicada\",\n customCondition: \"Condição personalizada\",\n customConditionLabel: \"Nome da condição\",\n customConditionBefore: \"Antes (lógica de abertura)\",\n customConditionAfter: \"Depois (lógica de fechamento)\",\n applyCondition: \"Aplicar\",\n cancelCondition: \"Cancelar\",\n customBadge: \"Personalizado\",\n restoreHiddenBlocks: \"Mostrar todos os blocos ocultos\",\n },\n\n // Template settings\n templateSettings: {\n layout: \"Layout\",\n widthPreset: \"Largura Predefinida\",\n customWidth: \"Largura Personalizada\",\n appearance: \"Aparência\",\n backgroundColor: \"Cor de Fundo\",\n textColor: \"Cor do Texto\",\n linkColor: \"Cor do Link\",\n linkUnderline: \"Sublinhar Links\",\n fontFamily: \"Família da Fonte\",\n preheaderText: \"Texto de Pré-cabeçalho\",\n preheaderTextPlaceholder:\n \"Texto de prévia exibido após o assunto na caixa de entrada...\",\n preheaderTextHint:\n \"Este texto aparece após o assunto nas pré-visualizações dos clientes de e-mail. Suporta merge tags.\",\n language: \"Idioma\",\n contentLocale: \"Idioma do conteúdo\",\n contentLocaleHint:\n \"Código BCP 47 (ex.: en, de, pt-BR). Define o atributo lang do e-mail renderizado para que leitores de tela pronunciem o conteúdo corretamente.\",\n tips: \"Dicas\",\n tip1: \"600px é a largura padrão para templates de e-mail\",\n tip2: \"Use fontes seguras para web para melhor compatibilidade\",\n tip3: \"Fundos claros funcionam melhor para legibilidade\",\n },\n\n // Spacing control\n spacingControl: {\n lockAll: \"Travar todos os lados\",\n unlock: \"Destravar lados\",\n top: \"Superior\",\n right: \"Direito\",\n bottom: \"Inferior\",\n left: \"Esquerdo\",\n decreaseTop: \"Diminuir superior\",\n increaseTop: \"Aumentar superior\",\n decreaseLeft: \"Diminuir esquerdo\",\n increaseLeft: \"Aumentar esquerdo\",\n decreaseRight: \"Diminuir direito\",\n increaseRight: \"Aumentar direito\",\n decreaseBottom: \"Diminuir inferior\",\n increaseBottom: \"Aumentar inferior\",\n },\n\n // Color Picker\n colorPicker: {\n pickColor: \"Escolher uma cor\",\n hexValue: \"Valor hexadecimal da cor\",\n notSet: \"Não definido\",\n clear: \"Limpar cor\",\n presetColors: \"Cores predefinidas\",\n },\n\n // Merge Tag\n mergeTag: {\n clickToEdit: \"Clique para editar\",\n remove: \"Remover merge tag\",\n insert: \"Inserir merge tag\",\n insertShort: \"Merge tag\",\n editValue: \"Editar valor da merge tag\",\n deleteMergeTag: \"Excluir merge tag\",\n suggestionEmpty: \"Nenhuma merge tag correspondente\",\n picker: {\n title: \"Inserir merge tag\",\n searchPlaceholder: \"Pesquisar merge tags\",\n searchAriaLabel: \"Pesquisar merge tags\",\n noResults: \"Nenhuma merge tag correspondente\",\n empty: \"Nenhuma merge tag configurada\",\n otherGroup: \"Outros\",\n cancel: \"Cancelar\",\n close: \"Fechar\",\n groupCount: \"{count}\",\n sample: \"Pré-visualização: {sample}\",\n },\n },\n\n // Logic tags (standalone, separate from merge tags)\n logicTag: {\n insert: \"Inserir lógica\",\n insertShort: \"Lógica\",\n picker: {\n title: \"Inserir lógica\",\n searchPlaceholder: \"Buscar tags de lógica\",\n searchAriaLabel: \"Buscar tags de lógica\",\n noResults: \"Nenhuma tag de lógica correspondente\",\n empty: \"Nenhuma tag de lógica configurada\",\n otherGroup: \"Outros\",\n close: \"Fechar\",\n },\n },\n\n // Canvas\n canvas: {\n noBlocks: \"Nenhum bloco ainda\",\n dragHint: \"Comece do zero arrastando blocos da barra lateral\",\n dropHere: \"Solte aqui\",\n aiHintChat: \"ou deixe a\",\n aiHintChatSuffix: \"gerar um template completo para você em segundos\",\n aiHintDesign:\n \"Tem um design existente? Envie uma captura de tela, imagem ou PDF e a\",\n aiHintDesignSuffix: \"recriará instantaneamente\",\n },\n\n // Media Library (cloud)\n mediaLibrary: {\n title: \"Biblioteca de Mídia\",\n searchPlaceholder: \"Buscar arquivos...\",\n allFiles: \"Todos os Arquivos\",\n filterAll: \"Todos os Tipos\",\n filterImages: \"Imagens\",\n filterDocuments: \"Documentos\",\n filterVideos: \"Vídeos\",\n filterAudio: \"Áudio\",\n newFolder: \"Nova Pasta\",\n folderName: \"Nome da pasta\",\n noFiles: \"Nenhum arquivo encontrado\",\n dropOrClick: \"Solte arquivos aqui ou clique para enviar\",\n acceptedFormats: \"Imagens, PDF, Vídeo, Áudio, Documentos (máx. 10MB)\",\n uploading: \"Enviando...\",\n uploadingProgress: \"Enviando {current} de {total}...\",\n selectImage: \"Selecionar Imagem\",\n selectFile: \"Selecionar Arquivo\",\n deleteSelected: \"Excluir\",\n copyUrl: \"Copiar URL\",\n copied: \"Copiado!\",\n browseMedia: \"Explorar Biblioteca de Mídia\",\n renameFolder: \"Renomear pasta\",\n addSubfolder: \"Adicionar subpasta\",\n subfolderName: \"Nome da subpasta\",\n sortNewest: \"Mais Recentes\",\n sortOldest: \"Mais Antigos\",\n sortNameAsc: \"Nome A-Z\",\n sortNameDesc: \"Nome Z-A\",\n sortSizeAsc: \"Menores Primeiro\",\n sortSizeDesc: \"Maiores Primeiro\",\n moveSelected: \"Mover\",\n moveToRoot: \"Todos os Arquivos\",\n currentFolder: \"(atual)\",\n confirmDelete: \"Excluir este arquivo?\",\n renameFile: \"Renomear\",\n editFile: \"Editar Arquivo\",\n fileName: \"Nome do arquivo\",\n altText: \"Texto Alternativo\",\n altTextPlaceholder: \"Descreva esta imagem para acessibilidade\",\n saveChanges: \"Salvar\",\n cancel: \"Cancelar\",\n frequentlyUsed: \"Usados Frequentemente\",\n deleteWarningTitle: \"Excluir Arquivo\",\n deleteWarningMessage:\n \"Este arquivo será excluído permanentemente e não poderá ser recuperado.\",\n deleteWarningUsageNote:\n \"Os arquivos a seguir estão sendo usados em templates. Excluí-los pode quebrar esses templates.\",\n deleteAnyway: \"Excluir arquivo\",\n usedInTemplates: \"Usado em {count} template(s)\",\n viewGrid: \"Visualização em grade\",\n viewList: \"Visualização em lista\",\n showFolders: \"Mostrar pastas\",\n hideFolders: \"Ocultar pastas\",\n importFromUrl: \"Importar de URL\",\n importUrlPlaceholder: \"https://exemplo.com/imagem.jpg\",\n import: \"Importar\",\n importing: \"Importando...\",\n importError: \"Falha ao importar da URL\",\n conversionLabel: \"Tamanho\",\n conversionOriginal: \"Original\",\n conversionSmall: \"Pequeno (150px)\",\n conversionMedium: \"Médio (600px)\",\n conversionLarge: \"Grande (1200px)\",\n replaceFile: \"Substituir Arquivo\",\n replaceWarningTitle: \"Substituir Arquivo\",\n replaceWarningMessage:\n \"Você está prestes a substituir este arquivo. O substituto deve ter a mesma extensão ({extension}).\",\n replaceWarningUsageNote:\n \"Este arquivo é usado em {count} template(s). Substituí-lo atualizará todas as referências.\",\n replaceSelectFile: \"Selecionar arquivo substituto\",\n replace: \"Substituir\",\n replacing: \"Substituindo...\",\n replaceError: \"Falha ao substituir arquivo\",\n saving: \"Salvando...\",\n cropAspectRatio: \"Proporção\",\n cropFree: \"Livre\",\n cropSquare: \"1:1\",\n cropLandscape43: \"4:3\",\n cropLandscape169: \"16:9\",\n cropOriginal: \"Original\",\n cropMaxWidth: \"Largura Máxima\",\n cropMaxHeight: \"Altura Máxima\",\n cropOutputSize: \"Tamanho de Saída\",\n cropPixels: \"px\",\n cropOptional: \"(opcional)\",\n storageTooltip: \"{used} de {total} usados ({remaining} restantes)\",\n },\n\n // Sidebar\n savedBlocks: {\n title: \"Blocos Salvos\",\n saveAsBlock: \"Salvar como Bloco\",\n name: \"Nome\",\n namePlaceholder: \"ex.: Cabeçalho, Rodapé, CTA...\",\n save: \"Salvar Bloco\",\n saving: \"Salvando...\",\n cancel: \"Cancelar\",\n empty: \"Nenhum bloco salvo ainda\",\n emptyHint: \"Salve blocos dos seus templates para reutilizá-los depois.\",\n noResults: \"Nenhum bloco salvo corresponde à sua busca\",\n search: \"Buscar blocos salvos...\",\n loading: \"Carregando blocos salvos…\",\n category: \"Categoria\",\n categoryPlaceholder: \"ex.: Cabeçalhos, Promoções... (opcional)\",\n allCategories: \"Todas as categorias\",\n filterByCategory: \"Filtrar por categoria\",\n insert: \"Inserir\",\n rename: \"Renomear\",\n delete: \"Excluir\",\n deleteConfirm: \"Excluir este bloco salvo?\",\n blockCount: \"{count} bloco(s)\",\n browse: \"Explorar Blocos Salvos\",\n selectToPreview: \"Selecione um bloco salvo para visualizar\",\n insertAtBeginning: \"No início\",\n insertAfterBlock: \"Após {block}\",\n insertAtEnd: \"No final\",\n insertPosition: \"Posição de inserção\",\n close: \"Fechar\",\n pickToolbar: \"Seleção de bloco salvo\",\n pickCount: \"{count} bloco(s) selecionado(s)\",\n pickHint: \"Clique nos blocos para adicionar ou remover\",\n savingCount: \"Salvando {count} bloco(s):\",\n reorderHint: \"Arraste para reordenar — os blocos são salvos nesta ordem\",\n reorderHandle: \"Reordenar {block}, posição {position} de {total}\",\n reorderAnnouncement: \"{block} movido para a posição {position} de {total}\",\n expand: \"Expandir\",\n collapse: \"Recolher\",\n expandPreview: \"Expandir a prévia de {block}\",\n collapsePreview: \"Recolher a prévia de {block}\",\n time: {\n justNow: \"Agora mesmo\",\n minutesAgo: \"há {minutes}min\",\n hoursAgo: \"há {hours}h\",\n daysAgo: \"há {days}d\",\n },\n },\n previewResolution: {\n resolving: \"Resolvendo a pré-visualização…\",\n failed:\n \"Não foi possível resolver a pré-visualização — exibindo o modelo não resolvido.\",\n hint: \"A pré-visualização usa dados resolvidos pelo seu backend.\",\n },\n mergeTagPreview: {\n label: \"Exibição de merge tags\",\n sample: \"Exemplo\",\n labelView: \"Rótulo\",\n },\n testEmail: {\n title: \"Enviar E-mail de Teste\",\n recipientLabel: \"Destinatário\",\n recipientPlaceholder: \"voce@exemplo.com\",\n invalidAddress: \"Informe um endereço de e-mail válido.\",\n preview: \"Pré-visualização\",\n previewHint:\n \"As merge tags aparecem sem resolução — seu backend as preenche.\",\n previewHintSample:\n \"As merge tags mostram valores de exemplo — seu backend insere os dados reais.\",\n recipientNotAllowed:\n \"Esse endereço não está na lista de destinatários permitidos.\",\n send: \"Enviar\",\n sending: \"Enviando...\",\n cancel: \"Cancelar\",\n success: \"E-mail de teste enviado com sucesso\",\n button: \"Testar\",\n },\n sidebarNav: {\n browseSavedBlocks: \"Explorar blocos salvos\",\n expandSidebar: \"Expandir barra lateral de blocos\",\n palette: \"Paleta de blocos\",\n insertBlock: \"Inserir bloco {block}\",\n },\n\n // Landmark region labels for assistive technology\n landmarks: {\n canvas: \"Tela do e-mail\",\n blockToolbar: \"Propriedades do bloco\",\n rightSidebar: \"Propriedades do bloco e configurações do template\",\n reorderAnnouncements: \"Anúncios de reordenação de blocos\",\n },\n\n // Design Reference (cloud)\n errors: {\n editorLoading: \"Carregando editor...\",\n editorLoadFailed: \"Falha ao carregar o editor.\",\n retry: \"Tentar novamente\",\n },\n\n issues: {\n panelTitle: \"Problemas\",\n panelTabLabel: \"Problemas\",\n groupErrors: \"Erros\",\n groupWarnings: \"Avisos\",\n groupInfo: \"Informações\",\n jump: \"Ir para o bloco\",\n fix: \"Corrigir\",\n emptyState: \"Nenhum problema — tudo certo.\",\n badgeError: \"Possui erros\",\n badgeWarning: \"Possui avisos\",\n issueCountTooltip: \"{count} problema(s)\",\n },\n\n smallScreen: {\n title: \"Tela maior necessária\",\n message:\n \"O editor precisa de mais espaço do que esta tela oferece. Abra-o em um tablet ou desktop para começar a editar.\",\n },\n};\n\nexport default ptBR;\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"src-B8W42vT-.js","names":[],"sources":["../../../../quality/src/types.ts","../../../../quality/src/contrast.ts","../../../../quality/src/walk.ts","../../../../quality/src/run-rules.ts","../../../../quality/src/accessibility/messages/de.ts","../../../../quality/src/accessibility/messages/en.ts","../../../../quality/src/accessibility/messages/index.ts","../../../../quality/src/accessibility/rules/img-missing-alt.ts","../../../../quality/src/accessibility/rules/img-alt-is-filename.ts","../../../../quality/src/accessibility/rules/img-alt-too-long.ts","../../../../quality/src/accessibility/rules/img-decorative-needs-empty-alt.ts","../../../../quality/src/accessibility/dictionaries/de.ts","../../../../quality/src/accessibility/dictionaries/en.ts","../../../../quality/src/accessibility/dictionaries/index.ts","../../../../quality/src/accessibility/rules/img-linked-no-context.ts","../../../../quality/src/html-utils.ts","../../../../quality/src/accessibility/rules/heading-empty.ts","../../../../quality/src/accessibility/rules/heading-skip-level.ts","../../../../quality/src/accessibility/rules/heading-multiple-h1.ts","../../../../quality/src/accessibility/rules/link-empty.ts","../../../../quality/src/accessibility/rules/link-vague-text.ts","../../../../quality/src/accessibility/rules/link-href-empty.ts","../../../../quality/src/accessibility/rules/link-target-blank-no-rel.ts","../../../../quality/src/accessibility/rules/link-nested-anchor.ts","../../../../quality/src/accessibility/rules/text-all-caps.ts","../../../../quality/src/accessibility/rules/text-low-contrast.ts","../../../../quality/src/accessibility/rules/text-too-small.ts","../../../../quality/src/accessibility/rules/button-vague-label.ts","../../../../quality/src/accessibility/rules/button-touch-target.ts","../../../../quality/src/accessibility/rules/button-low-contrast.ts","../../../../quality/src/accessibility/rules/missing-preheader.ts","../../../../quality/src/accessibility/index.ts","../../../../quality/src/structure/messages/de.ts","../../../../quality/src/structure/messages/en.ts","../../../../quality/src/structure/messages/index.ts","../../../../quality/src/structure/rules/duplicate-block-id.ts","../../../../quality/src/structure/rules/empty-column.ts","../../../../quality/src/structure/rules/empty-section.ts","../../../../quality/src/structure/rules/nested-section.ts","../../../../quality/src/structure/rules/section-column-mismatch.ts","../../../../quality/src/structure/index.ts","../../../../quality/src/links/messages/de.ts","../../../../quality/src/links/messages/en.ts","../../../../quality/src/links/messages/index.ts","../../../../quality/src/url-walker.ts","../../../../quality/src/links/rules/javascript-protocol.ts","../../../../quality/src/links/rules/unsupported-protocol.ts","../../../../quality/src/links/rules/malformed-mailto.ts","../../../../quality/src/links/rules/malformed-tel.ts","../../../../quality/src/links/rules/localhost-or-staging.ts","../../../../quality/src/links/index.ts","../../../../quality/src/util.ts","../../../../quality/src/lint-template.ts"],"sourcesContent":["import type {\n Block,\n SectionBlock,\n TemplateContent,\n TemplateSettings,\n} from \"@templatical/types\";\n\nexport type Severity = \"error\" | \"warning\" | \"info\" | \"off\";\n\nexport interface LintIssue {\n /** Block id, or null for template-level issues. */\n blockId: string | null;\n ruleId: string;\n severity: Exclude<Severity, \"off\">;\n message: string;\n fix?: LintPatch;\n}\n\nexport interface LintPatchContext {\n updateBlock: (blockId: string, patch: Partial<Block>) => void;\n updateSettings: (patch: Partial<TemplateSettings>) => void;\n removeBlock: (blockId: string) => void;\n}\n\nexport interface LintPatch {\n description: string;\n apply: (ctx: LintPatchContext) => void;\n}\n\nexport interface LintThresholds {\n altMaxLength: number;\n minFontSize: number;\n allCapsMinLength: number;\n minTouchTargetPx: number;\n}\n\n/**\n * Per-rule severity override. Set a rule to `'off'` to disable it.\n * Keys are the full prefixed rule IDs (`a11y.*`, `structure.*`, `link.*`)\n * so a value copied from `LintIssue.ruleId` pastes straight in.\n */\nexport type RuleOverrides = Record<string, Severity>;\n\n/** Options consumed only by the accessibility linter. */\nexport interface AccessibilityLintOptions {\n rules?: RuleOverrides;\n thresholds?: Partial<LintThresholds>;\n}\n\n/** Options consumed only by the structure linter. */\nexport interface StructureLintOptions {\n rules?: RuleOverrides;\n}\n\n/** Options consumed only by the links linter. */\nexport interface LinksLintOptions {\n rules?: RuleOverrides;\n /**\n * Host patterns that should flag as \"staging / non-production\".\n * Each entry is a glob-style pattern matched against the URL host.\n * `*` matches any run of characters (including `.`), so `*.staging.*`\n * matches `app.staging.example.com`.\n *\n * Default: ['localhost', '127.0.0.1', '0.0.0.0', '*.local',\n * '*.staging.*', '*.dev.*']\n */\n nonProductionHosts?: string[];\n}\n\nexport interface LintOptions {\n /**\n * Fully disable linting. When true, the editor skips lazy-loading the\n * package, hides the sidebar tab, and suppresses inline badges.\n */\n disabled?: boolean;\n /** Locale for vague-text dictionaries and message text. Falls back to `en`. */\n locale?: string;\n /**\n * Accessibility linter config. Set to `false` to disable the whole\n * `lintAccessibility` linter without enumerating its rules.\n */\n accessibility?: false | AccessibilityLintOptions;\n /**\n * Structure linter config. Set to `false` to disable the whole\n * `lintStructure` linter without enumerating its rules.\n */\n structure?: false | StructureLintOptions;\n /**\n * Links linter config. Set to `false` to disable the whole `lintLinks`\n * linter without enumerating its rules.\n */\n links?: false | LinksLintOptions;\n}\n\nexport interface ResolvedLinksOptions {\n nonProductionHosts: string[];\n}\n\nexport interface ResolvedOptions {\n locale: string;\n rules: RuleOverrides;\n thresholds: LintThresholds;\n links: ResolvedLinksOptions;\n /** Returns the effective severity for a rule (override or default). */\n severity: (ruleId: string) => Severity;\n}\n\nexport interface WalkContext {\n parent: Block | null;\n section: SectionBlock | null;\n columnIndex: number | null;\n depth: number;\n /**\n * Nearest opaque ancestor background, or template settings background.\n * Hex string, lowercased.\n */\n resolvedBackgroundColor: string;\n /**\n * Document-level default text color (`settings.textColor`), lowercased hex.\n * A text block that doesn't set its own `color` inherits this, so contrast\n * rules resolve the effective color against it.\n */\n resolvedTextColor: string;\n}\n\nexport interface RuleMeta {\n /** Stable identifier — used for severity overrides and message lookup. */\n id: string;\n /** Default severity when no override is supplied. */\n severity: Exclude<Severity, \"off\">;\n}\n\n/**\n * What a rule emits per match. The orchestrator combines this with the\n * rule's `meta` (for `ruleId` + default severity) and resolves the\n * localized message via the active locale's message map.\n */\nexport interface RuleHit {\n blockId: string | null;\n /** Interpolation values for the rule's localized message template. */\n params?: Record<string, string | number>;\n fix?: LintPatch;\n}\n\nexport interface Rule {\n meta: RuleMeta;\n /** Block-level rule. Returns a hit or null. */\n block?: (\n block: Block,\n ctx: WalkContext,\n opts: ResolvedOptions,\n ) => RuleHit | null;\n /** Template-level rule. Runs once after the walk. */\n template?: (content: TemplateContent, opts: ResolvedOptions) => RuleHit[];\n}\n\nexport const DEFAULT_A11Y_THRESHOLDS: LintThresholds = {\n altMaxLength: 125,\n minFontSize: 14,\n allCapsMinLength: 20,\n minTouchTargetPx: 44,\n};\n\nexport const DEFAULT_NON_PRODUCTION_HOSTS: string[] = [\n \"localhost\",\n \"127.0.0.1\",\n \"0.0.0.0\",\n \"*.local\",\n \"*.staging.*\",\n \"*.dev.*\",\n];\n","/**\n * WCAG 2.1 sRGB relative-luminance contrast.\n *\n * Inputs are hex strings (`#rgb`, `#rrggbb`, optional leading `#`).\n * Returns the contrast ratio (1–21) per WCAG, or `NaN` if either input\n * cannot be parsed as an opaque solid hex color.\n *\n * The codebase uses OKLch for design tokens, but contrast math is\n * sRGB-defined; mixing the two gives incorrect results.\n */\nexport function getContrastRatio(fg: string, bg: string): number {\n const fgRgb = parseHex(fg);\n const bgRgb = parseHex(bg);\n\n if (!fgRgb || !bgRgb) {\n return Number.NaN;\n }\n\n const l1 = relativeLuminance(fgRgb);\n const l2 = relativeLuminance(bgRgb);\n const lighter = Math.max(l1, l2);\n const darker = Math.min(l1, l2);\n\n return (lighter + 0.05) / (darker + 0.05);\n}\n\nexport interface Rgb {\n r: number;\n g: number;\n b: number;\n}\n\nconst HEX3 = /^#?([0-9a-f])([0-9a-f])([0-9a-f])$/i;\nconst HEX6 = /^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i;\nconst HEX8 = /^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i;\n\nexport function parseHex(input: string | undefined | null): Rgb | null {\n if (typeof input !== \"string\") {\n return null;\n }\n\n const trimmed = input.trim();\n\n const match8 = HEX8.exec(trimmed);\n if (match8) {\n // Only treat fully-opaque (alpha = ff) as a valid RGB color; partial\n // alpha can't be flattened without knowing the underlay.\n if (match8[4].toLowerCase() !== \"ff\") return null;\n return {\n r: parseInt(match8[1], 16),\n g: parseInt(match8[2], 16),\n b: parseInt(match8[3], 16),\n };\n }\n\n const match6 = HEX6.exec(trimmed);\n if (match6) {\n return {\n r: parseInt(match6[1], 16),\n g: parseInt(match6[2], 16),\n b: parseInt(match6[3], 16),\n };\n }\n\n const match3 = HEX3.exec(trimmed);\n if (match3) {\n return {\n r: parseInt(match3[1] + match3[1], 16),\n g: parseInt(match3[2] + match3[2], 16),\n b: parseInt(match3[3] + match3[3], 16),\n };\n }\n\n return null;\n}\n\nexport function isOpaqueHex(input: string | undefined | null): boolean {\n return parseHex(input ?? \"\") !== null;\n}\n\nfunction relativeLuminance({ r, g, b }: Rgb): number {\n const rs = channel(r / 255);\n const gs = channel(g / 255);\n const bs = channel(b / 255);\n return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;\n}\n\nfunction channel(c: number): number {\n return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n}\n","import type { Block, TemplateContent } from \"@templatical/types\";\nimport { isSection } from \"@templatical/types\";\nimport type { WalkContext } from \"./types\";\nimport { isOpaqueHex } from \"./contrast\";\n\nexport type Visitor = (block: Block, ctx: WalkContext) => void;\n\nconst DEFAULT_BG = \"#ffffff\";\nconst DEFAULT_TEXT = \"#1a1a1a\";\n\n/**\n * Pure traversal of the block tree. Calls `visit` once per block in\n * document order, providing a `WalkContext` that includes the resolved\n * background color (nearest opaque ancestor) and structural refs.\n *\n * Sections cannot nest (renderer enforces this), so the walker doesn't\n * descend into a section that lives inside a column. Custom blocks are\n * visited but not descended into.\n */\nexport function walkBlocks(content: TemplateContent, visit: Visitor): void {\n const rootBg = isOpaqueHex(content.settings.backgroundColor)\n ? content.settings.backgroundColor.toLowerCase()\n : DEFAULT_BG;\n // Document-level default text color — constant across the tree. Text blocks\n // that don't set their own `color` inherit it, so it's the effective color\n // contrast rules compare against.\n const rootTextColor = isOpaqueHex(content.settings.textColor)\n ? content.settings.textColor.toLowerCase()\n : DEFAULT_TEXT;\n\n const walk = (block: Block, ctx: WalkContext): void => {\n // A block's own opaque backgroundColor is what's behind its content —\n // visit it with that resolved bg so contrast rules compare against the\n // right surface. Falls back to the inherited section/template bg.\n const ownBg = block.styles?.backgroundColor;\n const effectiveBg = isOpaqueHex(ownBg)\n ? (ownBg as string).toLowerCase()\n : ctx.resolvedBackgroundColor;\n const blockCtx: WalkContext =\n effectiveBg === ctx.resolvedBackgroundColor\n ? ctx\n : { ...ctx, resolvedBackgroundColor: effectiveBg };\n\n visit(block, blockCtx);\n\n if (!isSection(block)) {\n return;\n }\n\n block.children.forEach((column, columnIndex) => {\n column.forEach((child) =>\n walk(child, {\n parent: block,\n section: block,\n columnIndex,\n depth: ctx.depth + 1,\n resolvedBackgroundColor: effectiveBg,\n resolvedTextColor: ctx.resolvedTextColor,\n }),\n );\n });\n };\n\n for (const block of content.blocks) {\n walk(block, {\n parent: null,\n section: null,\n columnIndex: null,\n depth: 0,\n resolvedBackgroundColor: rootBg,\n resolvedTextColor: rootTextColor,\n });\n }\n}\n","import type { TemplateContent } from \"@templatical/types\";\nimport type {\n AccessibilityLintOptions,\n LinksLintOptions,\n LintIssue,\n ResolvedOptions,\n Rule,\n RuleHit,\n RuleOverrides,\n Severity,\n StructureLintOptions,\n} from \"./types\";\nimport { DEFAULT_A11Y_THRESHOLDS, DEFAULT_NON_PRODUCTION_HOSTS } from \"./types\";\nimport { walkBlocks } from \"./walk\";\n\nexport type MessageFormatter = (\n locale: string,\n ruleId: string,\n params?: Record<string, string | number>,\n) => string;\n\n/**\n * Walk the tree once, dispatch every block-level rule, then run every\n * template-level rule. Each tool (lintAccessibility, lintStructure, …)\n * wraps this with its own rule list + message formatter and a pre-built\n * `ResolvedOptions` containing that tool's overrides and tool-scoped config.\n */\nexport function runRules(\n content: TemplateContent,\n rules: Rule[],\n opts: ResolvedOptions,\n formatMessage: MessageFormatter,\n): LintIssue[] {\n const issues: LintIssue[] = [];\n\n function buildIssue(\n ruleId: string,\n severity: Exclude<Severity, \"off\">,\n hit: RuleHit,\n ): LintIssue {\n return {\n blockId: hit.blockId,\n ruleId,\n severity,\n message: formatMessage(opts.locale, ruleId, hit.params),\n fix: hit.fix,\n };\n }\n\n walkBlocks(content, (block, ctx) => {\n for (const rule of rules) {\n const sev = opts.severity(rule.meta.id);\n if (sev === \"off\" || !rule.block) continue;\n const hit = rule.block(block, ctx, opts);\n if (hit !== null) {\n issues.push(buildIssue(rule.meta.id, sev, hit));\n }\n }\n });\n\n for (const rule of rules) {\n const sev = opts.severity(rule.meta.id);\n if (sev === \"off\" || !rule.template) continue;\n const hits = rule.template(content, opts);\n for (const hit of hits) {\n issues.push(buildIssue(rule.meta.id, sev, hit));\n }\n }\n\n return issues;\n}\n\n/**\n * Build a `ResolvedOptions` for a given tool. Each tool wrapper passes its\n * own per-tool bag; fields not relevant to the tool fall back to defaults\n * (e.g. `lintStructure` still gets `thresholds` populated, but no structure\n * rule reads them).\n */\nexport function resolveOptions(args: {\n locale: string | undefined;\n rules: Rule[];\n overrides: RuleOverrides | undefined;\n thresholds: Partial<import(\"./types\").LintThresholds> | undefined;\n nonProductionHosts: string[] | undefined;\n}): ResolvedOptions {\n const overrides = args.overrides ?? {};\n const thresholds = {\n ...DEFAULT_A11Y_THRESHOLDS,\n ...(args.thresholds ?? {}),\n };\n const links = {\n nonProductionHosts: args.nonProductionHosts ?? DEFAULT_NON_PRODUCTION_HOSTS,\n };\n const locale = args.locale ?? \"en\";\n const rules = args.rules;\n\n return {\n locale,\n rules: overrides,\n thresholds,\n links,\n severity: (ruleId: string): Severity => {\n const override = overrides[ruleId];\n if (override !== undefined) {\n return override;\n }\n const rule = rules.find((r) => r.meta.id === ruleId);\n return rule?.meta.severity ?? \"warning\";\n },\n };\n}\n\n/**\n * Resolver for the accessibility linter — reads `options.accessibility`.\n */\nexport function resolveAccessibilityOptions(\n locale: string | undefined,\n tool: AccessibilityLintOptions,\n rules: Rule[],\n): ResolvedOptions {\n return resolveOptions({\n locale,\n rules,\n overrides: tool.rules,\n thresholds: tool.thresholds,\n nonProductionHosts: undefined,\n });\n}\n\n/**\n * Resolver for the structure linter — reads `options.structure`.\n */\nexport function resolveStructureOptions(\n locale: string | undefined,\n tool: StructureLintOptions,\n rules: Rule[],\n): ResolvedOptions {\n return resolveOptions({\n locale,\n rules,\n overrides: tool.rules,\n thresholds: undefined,\n nonProductionHosts: undefined,\n });\n}\n\n/**\n * Resolver for the links linter — reads `options.links`.\n */\nexport function resolveLinksOptions(\n locale: string | undefined,\n tool: LinksLintOptions,\n rules: Rule[],\n): ResolvedOptions {\n return resolveOptions({\n locale,\n rules,\n overrides: tool.rules,\n thresholds: undefined,\n nonProductionHosts: tool.nonProductionHosts,\n });\n}\n","import type en from \"./en\";\n\nconst de: typeof en = {\n \"a11y.img-missing-alt\":\n \"Bild ohne Alt-Text. Füge eine kurze Beschreibung hinzu oder markiere das Bild als dekorativ.\",\n \"a11y.img-alt-is-filename\":\n 'Alt-Text sieht wie ein Dateiname aus (\"{alt}\"). Beschreibe stattdessen kurz, was das Bild zeigt.',\n \"a11y.img-alt-too-long\":\n \"Alt-Text ist {length} Zeichen lang; bleibe unter {max}.\",\n \"a11y.img-decorative-needs-empty-alt\":\n \"Dekoratives Bild hat Alt-Text. Entferne den Alt-Text oder hebe die Markierung als dekorativ auf.\",\n \"a11y.img-linked-no-context\":\n \"Verlinktes Bild beschreibt nur das Motiv, nicht das Linkziel. Nenne das Ziel (z. B. „Frühlingssale ansehen“).\",\n \"a11y.heading-empty\":\n \"Überschrift ist leer. Füge Text hinzu oder entferne den Block.\",\n \"a11y.heading-skip-level\":\n \"Überschrift springt von H{from} auf H{to}. Eine Ebene pro Schritt.\",\n \"a11y.heading-multiple-h1\":\n \"E-Mail enthält mehr als eine H1. Verwende H1 nur einmal für die Hauptüberschrift.\",\n \"a11y.link-empty\":\n \"Ein Link in diesem Block hat keinen Text und kein beschriebenes Bild.\",\n \"a11y.link-vague-text\":\n \"Link-Text „{text}“ ist unspezifisch. Beschreibe stattdessen das Ziel.\",\n \"a11y.link-href-empty\":\n \"Ein Link in diesem Block hat ein leeres oder „#“-href.\",\n \"a11y.link-target-blank-no-rel\":\n 'Link öffnet in neuem Tab, aber rel=\"noopener\" fehlt – ergänze es, damit das Ziel nicht auf window.opener zugreifen kann.',\n \"a11y.link-nested-anchor\":\n \"Ein Link liegt innerhalb eines anderen Links. Verschachtelte Anker sind ungültiges HTML und werden von E-Mail-Clients unterschiedlich gerendert – flache einen einzigen Anker daraus.\",\n \"a11y.text-all-caps\":\n \"Längere Texte in Großbuchstaben sind schwerer lesbar. Verwende Groß- und Kleinschreibung.\",\n \"a11y.text-low-contrast\":\n \"Überschriftskontrast beträgt {ratio}:1; WCAG AA verlangt mindestens {required}:1.\",\n \"a11y.text-too-small\": \"Text ist {size}px; mindestens {min}px verwenden.\",\n \"a11y.button-vague-label\":\n \"Button-Beschriftung „{text}“ ist unspezifisch. Beschreibe die Aktion.\",\n \"a11y.button-touch-target\":\n \"Button ist etwa {height}px hoch; mindestens {min}px verwenden, um Fehltipper auf Mobilgeräten zu vermeiden.\",\n \"a11y.button-low-contrast\":\n \"Buttontextkontrast beträgt {ratio}:1; WCAG AA verlangt mindestens {required}:1.\",\n \"a11y.missing-preheader\":\n \"Kein Preheader-Text gesetzt. Postfächer zeigen sonst Bruchstücke des ersten Blocks an.\",\n};\n\nexport default de;\n","/**\n * English rule messages. The source of truth — other locales annotate\n * themselves `typeof en` so missing or extra keys fail typecheck.\n *\n * Templates use `{name}` placeholders, interpolated by `formatMessage`.\n */\nconst en = {\n \"a11y.img-missing-alt\":\n \"Image is missing alt text. Add a short description, or mark the image as decorative.\",\n \"a11y.img-alt-is-filename\":\n 'Alt text looks like a filename (\"{alt}\"). Replace with a short description of what the image conveys.',\n \"a11y.img-alt-too-long\":\n \"Alt text is {length} characters; aim for under {max}.\",\n \"a11y.img-decorative-needs-empty-alt\":\n \"Decorative image has alt text. Either clear the alt text or unmark the image as decorative.\",\n \"a11y.img-linked-no-context\":\n \"Linked image alt describes the image but not the link destination. Include where the link goes (e.g. 'Buy spring sale').\",\n \"a11y.heading-empty\": \"Heading is empty. Add text or remove the block.\",\n \"a11y.heading-skip-level\":\n \"Heading jumps from H{from} to H{to}. Step one level at a time.\",\n \"a11y.heading-multiple-h1\":\n \"Email has more than one H1. Use H1 once for the main heading.\",\n \"a11y.link-empty\": \"A link in this block has no text and no described image.\",\n \"a11y.link-vague-text\":\n 'Link text \"{text}\" is vague. Describe the destination instead.',\n \"a11y.link-href-empty\": \"A link in this block has an empty or '#' href.\",\n \"a11y.link-target-blank-no-rel\":\n 'Link opens in a new tab but is missing rel=\"noopener\" — add it to prevent the destination from accessing window.opener.',\n \"a11y.link-nested-anchor\":\n \"A link is nested inside another link. Nested anchors are invalid HTML and clients render them inconsistently — flatten to a single anchor.\",\n \"a11y.text-all-caps\":\n \"Long all-caps text is harder to read for everyone. Use sentence case.\",\n \"a11y.text-low-contrast\":\n \"Heading contrast is {ratio}:1; WCAG AA requires at least {required}:1.\",\n \"a11y.text-too-small\": \"Text is {size}px; aim for at least {min}px.\",\n \"a11y.button-vague-label\":\n 'Button label \"{text}\" is vague. Describe the action.',\n \"a11y.button-touch-target\":\n \"Button is roughly {height}px tall; aim for at least {min}px to avoid mis-taps on mobile.\",\n \"a11y.button-low-contrast\":\n \"Button text contrast is {ratio}:1; WCAG AA requires at least {required}:1.\",\n \"a11y.missing-preheader\":\n \"No preheader text set. Inboxes will fall back to fragments of the first block.\",\n};\n\nexport default en;\n","import en from \"./en\";\n\nexport type MessageMap = typeof en;\nexport type RuleMessageId = keyof MessageMap;\n\n/**\n * Auto-discovered locale registry. Drop a `messages/<lang>.ts` file and\n * it's bundled automatically — same pattern as the editor's i18n.\n *\n * Eager glob: synchronous, all locales bundled into the package. Tiny\n * (a few hundred bytes per locale) so the cost is negligible compared\n * to the lazy-loading overhead.\n */\nconst modules = import.meta.glob<{ default: MessageMap }>(\"./*.ts\", {\n eager: true,\n});\n\nconst MESSAGES: Record<string, MessageMap> = {};\nfor (const path in modules) {\n const match = /\\.\\/([^/]+)\\.ts$/.exec(path);\n if (!match) continue;\n const locale = match[1];\n if (locale === \"index\") continue;\n MESSAGES[locale] = modules[path].default;\n}\n\nexport const SUPPORTED_MESSAGE_LOCALES = Object.keys(MESSAGES);\n\nexport function getMessages(locale: string): MessageMap {\n const base = locale.split(\"-\")[0]?.toLowerCase() ?? \"en\";\n return MESSAGES[base] ?? MESSAGES.en ?? en;\n}\n\n/**\n * Resolve a localized message for a rule. `params` interpolate `{name}`\n * placeholders. Falls back to English when the locale doesn't ship the\n * key (shouldn't happen — the parity test enforces it).\n */\nexport function formatMessage(\n locale: string,\n ruleId: RuleMessageId,\n params?: Record<string, string | number>,\n): string {\n const map = getMessages(locale);\n const template = map[ruleId] ?? en[ruleId];\n if (!params) return template;\n return template.replace(/\\{(\\w+)\\}/g, (_, key: string) => {\n const value = params[key];\n return value === undefined ? `{${key}}` : String(value);\n });\n}\n","import { isImage } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.img-missing-alt\",\n severity: \"error\",\n};\n\nexport const imgMissingAlt: Rule = {\n meta,\n block(block) {\n if (!isImage(block)) return null;\n if (block.decorative === true) return null;\n const alt = block.alt?.trim() ?? \"\";\n if (alt !== \"\") return null;\n if ((block.src ?? \"\").trim() === \"\") return null;\n return { blockId: block.id };\n },\n};\n","import { isImage } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.img-alt-is-filename\",\n severity: \"warning\",\n};\n\nconst FILENAME_PATTERNS: RegExp[] = [\n /\\.(jpe?g|png|gif|webp|svg)$/i,\n /^IMG[_-]?\\d+/i,\n /^Untitled/i,\n /^Screen[\\s_-]?Shot/i,\n /^DSC[_-]?\\d+/i,\n];\n\nexport const imgAltIsFilename: Rule = {\n meta,\n block(block) {\n if (!isImage(block) || block.decorative === true) return null;\n const alt = block.alt?.trim() ?? \"\";\n if (alt === \"\") return null;\n if (!FILENAME_PATTERNS.some((re) => re.test(alt))) return null;\n\n return {\n blockId: block.id,\n params: { alt },\n };\n },\n};\n","import { isImage } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.img-alt-too-long\",\n severity: \"warning\",\n};\n\nexport const imgAltTooLong: Rule = {\n meta,\n block(block, _ctx, opts) {\n if (!isImage(block) || block.decorative === true) return null;\n const alt = block.alt ?? \"\";\n if (alt.length <= opts.thresholds.altMaxLength) return null;\n return {\n blockId: block.id,\n params: { length: alt.length, max: opts.thresholds.altMaxLength },\n };\n },\n};\n","import { isImage } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.img-decorative-needs-empty-alt\",\n severity: \"info\",\n};\n\nexport const imgDecorativeNeedsEmptyAlt: Rule = {\n meta,\n block(block) {\n if (!isImage(block)) return null;\n if (block.decorative !== true) return null;\n if ((block.alt ?? \"\").trim() === \"\") return null;\n return {\n blockId: block.id,\n fix: {\n description: \"Clear alt text\",\n apply: (ctx) => ctx.updateBlock(block.id, { alt: \"\" }),\n },\n };\n },\n};\n","import type en from \"./en\";\n\nconst de: typeof en = {\n vagueLinkText: [\n \"hier klicken\",\n \"hier\",\n \"mehr lesen\",\n \"mehr\",\n \"weiter\",\n \"weiterlesen\",\n \"siehe mehr\",\n \"dies\",\n \"dieser link\",\n \"link\",\n \"klick\",\n ],\n vagueButtonLabels: [\n \"hier klicken\",\n \"klicken\",\n \"senden\",\n \"los\",\n \"ok\",\n \"okay\",\n \"ja\",\n \"nein\",\n ],\n linkedImageActionHints: [\n \"kaufen\",\n \"shoppen\",\n \"ansehen\",\n \"lesen\",\n \"lernen\",\n \"öffnen\",\n \"los\",\n \"sehen\",\n \"entdecken\",\n \"erkunden\",\n \"stöbern\",\n \"herunterladen\",\n \"holen\",\n \"abholen\",\n \"einlösen\",\n \"anschauen\",\n \"jetzt\",\n ],\n};\n\nexport default de;\n","/**\n * English vague-text dictionaries. Treated as the source of truth — other\n * locales annotate themselves `typeof en` so missing/extra phrases fail\n * typecheck.\n *\n * Phrases are matched case-insensitively against trimmed text content.\n */\nconst en = {\n vagueLinkText: [\n \"click here\",\n \"here\",\n \"read more\",\n \"more\",\n \"learn more\",\n \"see more\",\n \"this\",\n \"this link\",\n \"link\",\n \"click\",\n ],\n vagueButtonLabels: [\n \"click here\",\n \"click\",\n \"submit\",\n \"go\",\n \"ok\",\n \"okay\",\n \"yes\",\n \"no\",\n ],\n /**\n * Action verbs that signal a linked image's alt describes the link\n * destination, not just the visual subject. Used by `img-linked-no-context`.\n * Stored lowercase; tokenized matching is case-insensitive.\n */\n linkedImageActionHints: [\n \"buy\",\n \"shop\",\n \"view\",\n \"read\",\n \"learn\",\n \"open\",\n \"go\",\n \"see\",\n \"explore\",\n \"discover\",\n \"browse\",\n \"download\",\n \"get\",\n \"claim\",\n \"redeem\",\n \"watch\",\n ],\n};\n\nexport default en;\n","import en from \"./en\";\n\nexport type Dictionary = typeof en;\n\n/**\n * Auto-discovered locale registry. Drop a `dictionaries/<lang>.ts` file\n * and it's bundled automatically — same pattern as the editor's i18n\n * and the sibling `messages/` registry.\n *\n * Eager glob: synchronous, all locales bundled into the package. Tiny\n * (a few hundred bytes per locale) so the cost is negligible.\n */\nconst modules = import.meta.glob<{ default: Dictionary }>(\"./*.ts\", {\n eager: true,\n});\n\nconst DICTIONARIES: Record<string, Dictionary> = {};\nfor (const path in modules) {\n const match = /\\.\\/([^/]+)\\.ts$/.exec(path);\n if (!match) continue;\n const locale = match[1];\n if (locale === \"index\") continue;\n DICTIONARIES[locale] = modules[path].default;\n}\n\n/**\n * Returns a dictionary that unions every registered locale. Vague phrases\n * are universally vague — a German-locale email with an English \"Click here\"\n * CTA, or an English email with a French \"cliquez ici\", is still a vague\n * CTA, so the rule must detect across languages regardless of editor locale.\n *\n * The `locale` argument is accepted for API symmetry and future use (e.g.\n * weighted matching) but currently doesn't change the returned set.\n */\nexport function getDictionary(_locale: string): Dictionary {\n return UNIONED_DICTIONARY;\n}\n\nfunction unionAll(pick: (d: Dictionary) => readonly string[]): string[] {\n const set = new Set<string>();\n for (const dict of Object.values(DICTIONARIES)) {\n for (const phrase of pick(dict)) set.add(phrase);\n }\n return Array.from(set);\n}\n\nconst UNIONED_DICTIONARY: Dictionary = {\n vagueLinkText: unionAll((d) => d.vagueLinkText),\n vagueButtonLabels: unionAll((d) => d.vagueButtonLabels),\n linkedImageActionHints: unionAll((d) => d.linkedImageActionHints),\n};\n\nexport const SUPPORTED_DICTIONARY_LOCALES = Object.keys(DICTIONARIES);\n\n/**\n * Normalize text for dictionary matching: lowercase, collapse whitespace,\n * strip leading/trailing non-alphanumeric characters (punctuation, arrows,\n * emoji, decorative symbols). \"Click here!\", \"→ click here\", \"click here?\"\n * all collapse to \"click here\" so the dictionary's plain phrase matches.\n */\nexport function normalizeForMatch(input: string): string {\n return input\n .toLowerCase()\n .replace(/\\s+/g, \" \")\n .replace(/^[^\\p{L}\\p{N}]+|[^\\p{L}\\p{N}]+$/gu, \"\")\n .trim();\n}\n","import { isImage } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\nimport { getDictionary } from \"../dictionaries\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.img-linked-no-context\",\n severity: \"warning\",\n};\n\nexport const imgLinkedNoContext: Rule = {\n meta,\n block(block, _ctx, opts) {\n if (!isImage(block) || block.decorative === true) return null;\n if (!block.linkUrl || block.linkUrl.trim() === \"\") return null;\n const alt = (block.alt ?? \"\").trim();\n if (alt === \"\") return null;\n const tokens = alt\n .toLocaleLowerCase()\n .split(/[^\\p{L}\\p{N}]+/u)\n .filter(Boolean);\n const hints = getDictionary(opts.locale).linkedImageActionHints;\n if (tokens.some((token) => hints.includes(token))) return null;\n return { blockId: block.id };\n },\n};\n","import { Parser } from \"htmlparser2\";\n\nexport interface AnchorInfo {\n href: string;\n text: string;\n target: string | null;\n rel: string | null;\n /** True if the anchor wraps an image with non-empty alt. */\n hasImageWithAlt: boolean;\n}\n\n/**\n * Extract every anchor from a TipTap-style HTML fragment. Used by\n * link-* rules. Doesn't try to be a full DOM — only the data the rules\n * need.\n *\n * Nested `<a>` is invalid HTML; htmlparser2 follows the HTML5 spec and\n * emits an implicit `</a>` when a second `<a>` opens, so anchors are\n * effectively flat siblings. We mirror that with a single in-flight\n * anchor (no stack); a defensive finalize-on-reopen handles the\n * theoretical case where the parser ever stops emitting the implicit\n * close. Detecting nested-anchor markup as its own concern lives in\n * the `a11y.link-nested-anchor` rule, which inspects the raw input\n * before this normalization.\n */\nexport function extractAnchors(html: string): AnchorInfo[] {\n const anchors: AnchorInfo[] = [];\n let current: AnchorInfo | null = null;\n let buffer = \"\";\n\n const finalize = () => {\n if (current === null) return;\n current.text = buffer.trim();\n anchors.push(current);\n current = null;\n buffer = \"\";\n };\n\n const parser = new Parser({\n onopentag(name, attribs) {\n if (name === \"a\") {\n finalize();\n current = {\n href: attribs.href ?? \"\",\n text: \"\",\n target: attribs.target ?? null,\n rel: attribs.rel ?? null,\n hasImageWithAlt: false,\n };\n return;\n }\n\n if (name === \"img\" && current !== null) {\n const alt = (attribs.alt ?? \"\").trim();\n if (alt !== \"\") {\n current.hasImageWithAlt = true;\n }\n }\n },\n ontext(text) {\n if (current !== null) {\n buffer += text;\n }\n },\n onclosetag(name) {\n if (name === \"a\") {\n finalize();\n }\n },\n });\n\n parser.write(html);\n parser.end();\n finalize();\n\n return anchors;\n}\n\n/**\n * Whether the raw HTML contains an `<a>` opened inside another open\n * `<a>` — invalid markup that htmlparser2 silently normalizes by\n * emitting an implicit `</a>` before the inner open. `extractAnchors`\n * runs against the normalized parse and therefore can't distinguish\n * nested-from-sibling input; this helper inspects the raw text so the\n * `a11y.link-nested-anchor` rule can flag the structural problem.\n *\n * Tokenization here ignores anchor-like tokens inside HTML comments,\n * which is enough for TipTap email-template HTML. CDATA, `<script>`,\n * and attribute-value occurrences aren't expected in this surface.\n */\nexport function hasNestedAnchors(html: string): boolean {\n const stripped = stripHtmlComments(html);\n const tokens = stripped.matchAll(/<\\/?a\\b[^<>]*>/gi);\n let depth = 0;\n for (const match of tokens) {\n if (match[0].startsWith(\"</\")) {\n if (depth > 0) depth--;\n continue;\n }\n if (depth > 0) return true;\n depth++;\n }\n return false;\n}\n\n/**\n * Linear-time `<!-- … -->` stripper. Replaces the original\n * `replace(/<!--[\\s\\S]*?-->/g, \"\")`, which had two related problems:\n *\n * - Polynomial ReDoS: each `<!--` start re-scanned the rest of the\n * input for `-->`, costing O(n²) over inputs like `<!--<!--<!--…`.\n * - Incomplete sanitization: an unterminated `<!--` left the literal\n * `<!--` in the output, so downstream rendering could still parse it\n * as an open HTML comment and swallow the rest of the document.\n *\n * The scanner discards an unterminated comment entirely — there is no\n * way to recover meaningful content after a stray `<!--`, and leaving\n * it in would re-introduce the sanitizer gap.\n */\nfunction stripHtmlComments(html: string): string {\n let out = \"\";\n let i = 0;\n while (i < html.length) {\n const start = html.indexOf(\"<!--\", i);\n if (start === -1) {\n out += html.substring(i);\n break;\n }\n out += html.substring(i, start);\n const end = html.indexOf(\"-->\", start + 4);\n if (end === -1) {\n // Unterminated comment — drop everything from this point onward.\n break;\n }\n i = end + 3;\n }\n return out;\n}\n\n/**\n * Strip tags and return the visible text content of an HTML fragment.\n * Used by heading-empty and other text-presence rules.\n */\nexport function extractText(html: string): string {\n let text = \"\";\n const parser = new Parser({\n ontext(chunk) {\n text += chunk;\n },\n });\n parser.write(html);\n parser.end();\n return text.trim();\n}\n","import { isTitle } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\nimport { extractText } from \"../../html-utils\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.heading-empty\",\n severity: \"error\",\n};\n\nexport const headingEmpty: Rule = {\n meta,\n block(block) {\n if (!isTitle(block)) return null;\n const text = extractText(block.content ?? \"\");\n if (text !== \"\") return null;\n return { blockId: block.id };\n },\n};\n","import { isTitle, isSection } from \"@templatical/types\";\nimport type { Block, TitleBlock, TemplateContent } from \"@templatical/types\";\nimport type { Rule, RuleHit, RuleMeta } from \"../../types\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.heading-skip-level\",\n severity: \"error\",\n};\n\nfunction collectTitles(blocks: Block[], out: TitleBlock[]): void {\n for (const block of blocks) {\n if (isTitle(block)) {\n out.push(block);\n continue;\n }\n if (isSection(block)) {\n for (const column of block.children) {\n collectTitles(column, out);\n }\n }\n }\n}\n\nexport const headingSkipLevel: Rule = {\n meta,\n template(content: TemplateContent) {\n const titles: TitleBlock[] = [];\n collectTitles(content.blocks, titles);\n\n const hits: RuleHit[] = [];\n let lastLevel = 0;\n\n for (const title of titles) {\n if (lastLevel !== 0 && title.level > lastLevel + 1) {\n hits.push({\n blockId: title.id,\n params: { from: lastLevel, to: title.level },\n });\n }\n lastLevel = title.level;\n }\n\n return hits;\n },\n};\n","import { isTitle, isSection } from \"@templatical/types\";\nimport type { Block, TitleBlock, TemplateContent } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.heading-multiple-h1\",\n severity: \"warning\",\n};\n\nfunction collectTitles(blocks: Block[], out: TitleBlock[]): void {\n for (const block of blocks) {\n if (isTitle(block)) {\n out.push(block);\n continue;\n }\n if (isSection(block)) {\n for (const column of block.children) {\n collectTitles(column, out);\n }\n }\n }\n}\n\nexport const headingMultipleH1: Rule = {\n meta,\n template(content: TemplateContent) {\n const titles: TitleBlock[] = [];\n collectTitles(content.blocks, titles);\n const h1s = titles.filter((t) => t.level === 1);\n if (h1s.length <= 1) return [];\n return h1s.slice(1).map((title) => ({ blockId: title.id }));\n },\n};\n","import { isParagraph, isTitle } from \"@templatical/types\";\nimport type { Block } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\nimport { extractAnchors } from \"../../html-utils\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.link-empty\",\n severity: \"error\",\n};\n\nfunction getHtml(block: Block): string | null {\n if (isParagraph(block) || isTitle(block)) return block.content;\n return null;\n}\n\nexport const linkEmpty: Rule = {\n meta,\n block(block) {\n const html = getHtml(block);\n if (html === null) return null;\n\n const anchors = extractAnchors(html);\n const offender = anchors.find(\n (anchor) => anchor.text === \"\" && !anchor.hasImageWithAlt,\n );\n if (!offender) return null;\n\n return { blockId: block.id };\n },\n};\n","import { isParagraph, isTitle } from \"@templatical/types\";\nimport type { Block } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\nimport { extractAnchors } from \"../../html-utils\";\nimport { getDictionary, normalizeForMatch } from \"../dictionaries\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.link-vague-text\",\n severity: \"warning\",\n};\n\nfunction getHtml(block: Block): string | null {\n if (isParagraph(block) || isTitle(block)) return block.content;\n return null;\n}\n\nexport const linkVagueText: Rule = {\n meta,\n block(block, _ctx, opts) {\n const html = getHtml(block);\n if (html === null) return null;\n\n const phrases = getDictionary(opts.locale).vagueLinkText;\n const anchors = extractAnchors(html);\n const offender = anchors.find((a) => {\n const text = normalizeForMatch(a.text);\n return text !== \"\" && phrases.includes(text);\n });\n if (!offender) return null;\n\n return { blockId: block.id, params: { text: offender.text } };\n },\n};\n","import { isParagraph, isTitle } from \"@templatical/types\";\nimport type { Block } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\nimport { extractAnchors } from \"../../html-utils\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.link-href-empty\",\n severity: \"error\",\n};\n\nfunction getHtml(block: Block): string | null {\n if (isParagraph(block) || isTitle(block)) return block.content;\n return null;\n}\n\nexport const linkHrefEmpty: Rule = {\n meta,\n block(block) {\n const html = getHtml(block);\n if (html === null) return null;\n const anchors = extractAnchors(html);\n const offender = anchors.find((a) => {\n const href = a.href.trim();\n return href === \"\" || href === \"#\";\n });\n if (!offender) return null;\n return { blockId: block.id };\n },\n};\n","import { isParagraph, isTitle } from \"@templatical/types\";\nimport type { Block } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\nimport { extractAnchors } from \"../../html-utils\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.link-target-blank-no-rel\",\n severity: \"warning\",\n};\n\nfunction getHtml(block: Block): string | null {\n if (isParagraph(block) || isTitle(block)) return block.content;\n return null;\n}\n\nfunction hasSafeRel(rel: string | null): boolean {\n if (rel === null) return false;\n const tokens = rel.toLowerCase().split(/\\s+/);\n return tokens.includes(\"noopener\") || tokens.includes(\"noreferrer\");\n}\n\nexport const linkTargetBlankNoRel: Rule = {\n meta,\n block(block) {\n const html = getHtml(block);\n if (html === null) return null;\n const anchors = extractAnchors(html);\n const offender = anchors.find(\n (a) => a.target === \"_blank\" && !hasSafeRel(a.rel),\n );\n if (!offender) return null;\n\n return {\n blockId: block.id,\n fix: {\n description: 'Add rel=\"noopener\"',\n apply: (ctx) => {\n if (!isParagraph(block) && !isTitle(block)) return;\n const updated = addNoopenerToTargetBlank(block.content ?? \"\");\n ctx.updateBlock(block.id, { content: updated } as Partial<Block>);\n },\n },\n };\n },\n};\n\ninterface ParsedAttr {\n raw: string;\n name: string;\n value: string | null;\n /** Start offset of `raw` within the parent attrs string. */\n start: number;\n}\n\nconst ATTR_RE =\n /([^\\s\"'>/=]+)(?:\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s\"'=<>`]+)))?/g;\n\nfunction parseAttrs(attrs: string): ParsedAttr[] {\n const parsed: ParsedAttr[] = [];\n const re = new RegExp(ATTR_RE.source, ATTR_RE.flags);\n let match: RegExpExecArray | null;\n while ((match = re.exec(attrs)) !== null) {\n const value = match[2] ?? match[3] ?? match[4] ?? null;\n parsed.push({\n raw: match[0],\n name: match[1],\n value,\n start: match.index,\n });\n }\n return parsed;\n}\n\nfunction hasUnsafeTargetBlank(parsed: ParsedAttr[]): boolean {\n return parsed.some(\n (a) =>\n a.name.toLowerCase() === \"target\" &&\n a.value !== null &&\n a.value.toLowerCase() === \"_blank\",\n );\n}\n\nfunction addNoopenerToTargetBlank(html: string): string {\n return html.replace(/<a\\b([^>]*)>/gi, (match, attrs: string) => {\n const parsed = parseAttrs(attrs);\n if (!hasUnsafeTargetBlank(parsed)) return match;\n\n const relAttr = parsed.find((a) => a.name.toLowerCase() === \"rel\");\n if (relAttr) {\n const tokens = (relAttr.value ?? \"\").toLowerCase().split(/\\s+/);\n if (tokens.includes(\"noopener\") || tokens.includes(\"noreferrer\")) {\n return match;\n }\n const newRel = `${relAttr.value ?? \"\"} noopener`.trim();\n const before = attrs.slice(0, relAttr.start);\n const after = attrs.slice(relAttr.start + relAttr.raw.length);\n return `<a${before}rel=\"${newRel}\"${after}>`;\n }\n return `<a${attrs} rel=\"noopener\">`;\n });\n}\n","import { isParagraph, isTitle } from \"@templatical/types\";\nimport type { Block } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\nimport { hasNestedAnchors } from \"../../html-utils\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.link-nested-anchor\",\n severity: \"error\",\n};\n\nfunction getHtml(block: Block): string | null {\n if (isParagraph(block) || isTitle(block)) return block.content;\n return null;\n}\n\nexport const linkNestedAnchor: Rule = {\n meta,\n block(block) {\n const html = getHtml(block);\n if (html === null) return null;\n if (!hasNestedAnchors(html)) return null;\n return { blockId: block.id };\n },\n};\n","import { isParagraph, isTitle } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\nimport { extractText } from \"../../html-utils\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.text-all-caps\",\n severity: \"warning\",\n};\n\nexport const textAllCaps: Rule = {\n meta,\n block(block, _ctx, opts) {\n if (!isParagraph(block) && !isTitle(block)) return null;\n const text = extractText(block.content ?? \"\");\n const letters = text.replace(/[^\\p{L}]/gu, \"\");\n if (letters.length < opts.thresholds.allCapsMinLength) return null;\n if (letters !== letters.toLocaleUpperCase()) return null;\n return { blockId: block.id };\n },\n};\n","import { isTitle } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\nimport { getContrastRatio, isOpaqueHex } from \"../../contrast\";\nimport { HEADING_LEVEL_FONT_SIZE } from \"@templatical/types\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.text-low-contrast\",\n severity: \"error\",\n};\n\nexport const textLowContrast: Rule = {\n meta,\n block(block, ctx) {\n if (!isTitle(block)) return null;\n // Unset title color inherits the document text color, so check the\n // effective color against the background.\n const color = block.color ?? ctx.resolvedTextColor;\n if (!isOpaqueHex(color) || !isOpaqueHex(ctx.resolvedBackgroundColor)) {\n return null;\n }\n const fontSize = HEADING_LEVEL_FONT_SIZE[block.level];\n // WCAG large text = 18pt (~24px). Headings have no structured bold\n // flag in this codebase (TipTap stores it inline), so we conservatively\n // skip the 14pt-bold (~18.66px) relaxation and apply the px threshold.\n const required = fontSize >= 24 ? 3 : 4.5;\n const ratio = getContrastRatio(color, ctx.resolvedBackgroundColor);\n if (Number.isNaN(ratio) || ratio >= required) return null;\n return {\n blockId: block.id,\n params: { ratio: ratio.toFixed(2), required },\n };\n },\n};\n","import { isMenu, isTable } from \"@templatical/types\";\nimport type { Block } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.text-too-small\",\n severity: \"warning\",\n};\n\nfunction getFontSize(block: Block): number | null {\n if (isMenu(block) || isTable(block)) return block.fontSize;\n return null;\n}\n\nexport const textTooSmall: Rule = {\n meta,\n block(block, _ctx, opts) {\n const fontSize = getFontSize(block);\n if (fontSize === null) return null;\n if (fontSize >= opts.thresholds.minFontSize) return null;\n return {\n blockId: block.id,\n params: { size: fontSize, min: opts.thresholds.minFontSize },\n };\n },\n};\n","import { isButton } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\nimport { getDictionary, normalizeForMatch } from \"../dictionaries\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.button-vague-label\",\n severity: \"warning\",\n};\n\nexport const buttonVagueLabel: Rule = {\n meta,\n block(block, _ctx, opts) {\n if (!isButton(block)) return null;\n const text = normalizeForMatch(block.text ?? \"\");\n if (text === \"\") return null;\n const phrases = getDictionary(opts.locale).vagueButtonLabels;\n if (!phrases.includes(text)) return null;\n return { blockId: block.id, params: { text: block.text } };\n },\n};\n","import { isButton } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.button-touch-target\",\n severity: \"warning\",\n};\n\nexport const buttonTouchTarget: Rule = {\n meta,\n block(block, _ctx, opts) {\n if (!isButton(block)) return null;\n const padding = block.buttonPadding;\n if (!padding) return null;\n const estimatedHeight = block.fontSize * 1.4 + padding.top + padding.bottom;\n if (estimatedHeight >= opts.thresholds.minTouchTargetPx) return null;\n return {\n blockId: block.id,\n params: {\n height: Math.round(estimatedHeight),\n min: opts.thresholds.minTouchTargetPx,\n },\n };\n },\n};\n","import { isButton } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\nimport { getContrastRatio } from \"../../contrast\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.button-low-contrast\",\n severity: \"error\",\n};\n\nexport const buttonLowContrast: Rule = {\n meta,\n block(block) {\n if (!isButton(block)) return null;\n const ratio = getContrastRatio(block.textColor, block.backgroundColor);\n if (Number.isNaN(ratio)) return null;\n // WCAG large text = 18pt (~24px). Mirrors the heading rule's threshold.\n const required = block.fontSize >= 24 ? 3 : 4.5;\n if (ratio >= required) return null;\n return {\n blockId: block.id,\n params: { ratio: ratio.toFixed(2), required },\n };\n },\n};\n","import type { Rule, RuleMeta } from \"../../types\";\n\nexport const meta: RuleMeta = {\n id: \"a11y.missing-preheader\",\n severity: \"info\",\n};\n\nexport const missingPreheader: Rule = {\n meta,\n template(content) {\n const text = content.settings.preheaderText?.trim() ?? \"\";\n if (text !== \"\") return [];\n return [{ blockId: null }];\n },\n};\n","import type { TemplateContent } from \"@templatical/types\";\nimport type { LintIssue, LintOptions, Rule } from \"../types\";\nimport { resolveAccessibilityOptions, runRules } from \"../run-rules\";\nimport { formatMessage, type RuleMessageId } from \"./messages\";\nimport { imgMissingAlt } from \"./rules/img-missing-alt\";\nimport { imgAltIsFilename } from \"./rules/img-alt-is-filename\";\nimport { imgAltTooLong } from \"./rules/img-alt-too-long\";\nimport { imgDecorativeNeedsEmptyAlt } from \"./rules/img-decorative-needs-empty-alt\";\nimport { imgLinkedNoContext } from \"./rules/img-linked-no-context\";\nimport { headingEmpty } from \"./rules/heading-empty\";\nimport { headingSkipLevel } from \"./rules/heading-skip-level\";\nimport { headingMultipleH1 } from \"./rules/heading-multiple-h1\";\nimport { linkEmpty } from \"./rules/link-empty\";\nimport { linkVagueText } from \"./rules/link-vague-text\";\nimport { linkHrefEmpty } from \"./rules/link-href-empty\";\nimport { linkTargetBlankNoRel } from \"./rules/link-target-blank-no-rel\";\nimport { linkNestedAnchor } from \"./rules/link-nested-anchor\";\nimport { textAllCaps } from \"./rules/text-all-caps\";\nimport { textLowContrast } from \"./rules/text-low-contrast\";\nimport { textTooSmall } from \"./rules/text-too-small\";\nimport { buttonVagueLabel } from \"./rules/button-vague-label\";\nimport { buttonTouchTarget } from \"./rules/button-touch-target\";\nimport { buttonLowContrast } from \"./rules/button-low-contrast\";\nimport { missingPreheader } from \"./rules/missing-preheader\";\n\nexport const ACCESSIBILITY_RULES: Rule[] = [\n imgMissingAlt,\n imgAltIsFilename,\n imgAltTooLong,\n imgDecorativeNeedsEmptyAlt,\n imgLinkedNoContext,\n headingEmpty,\n headingSkipLevel,\n headingMultipleH1,\n linkEmpty,\n linkVagueText,\n linkHrefEmpty,\n linkTargetBlankNoRel,\n linkNestedAnchor,\n textAllCaps,\n textLowContrast,\n textTooSmall,\n buttonVagueLabel,\n buttonTouchTarget,\n buttonLowContrast,\n missingPreheader,\n];\n\nexport function lintAccessibility(\n content: TemplateContent,\n options: LintOptions = {},\n): LintIssue[] {\n if (options.disabled === true || options.accessibility === false) return [];\n const tool = options.accessibility ?? {};\n const resolved = resolveAccessibilityOptions(\n options.locale,\n tool,\n ACCESSIBILITY_RULES,\n );\n return runRules(\n content,\n ACCESSIBILITY_RULES,\n resolved,\n (locale, id, params) => formatMessage(locale, id as RuleMessageId, params),\n );\n}\n","import type en from \"./en\";\n\nconst de: typeof en = {\n \"structure.duplicate-block-id\":\n \"Block-ID erscheint {count}-mal im Baum. Jeder Block muss eine eindeutige ID haben.\",\n \"structure.section-column-mismatch\":\n 'Sektion verwendet Layout „{layout}\" (erwartet {expected} Spalten), hat aber {actual}. Deutet auf beschädigten Zustand hin.',\n \"structure.nested-section\":\n \"Sektion ist in einer anderen Sektion verschachtelt. Sektionen können nicht verschachtelt werden – der Renderer wird sich falsch verhalten.\",\n \"structure.empty-section\":\n \"Sektion enthält keine Blöcke. Entferne sie oder füge Inhalt hinzu.\",\n \"structure.empty-column\":\n \"Spalte {columnIndex} dieser Sektion ist leer. Füge Inhalt hinzu oder reduziere die Spaltenanzahl.\",\n};\n\nexport default de;\n","/**\n * English structure-rule messages. The source of truth — other locales\n * annotate themselves `typeof en` so missing or extra keys fail typecheck.\n *\n * Templates use `{name}` placeholders, interpolated by `formatMessage`.\n */\nconst en = {\n \"structure.duplicate-block-id\":\n \"Block id appears {count} times in the tree. Each block must have a unique id.\",\n \"structure.section-column-mismatch\":\n 'Section uses layout \"{layout}\" (expects {expected} columns) but has {actual}. Indicates corrupted state.',\n \"structure.nested-section\":\n \"Section is nested inside another section. Sections cannot nest — the renderer will misbehave.\",\n \"structure.empty-section\": \"Section has no blocks. Remove it or add content.\",\n \"structure.empty-column\":\n \"Column {columnIndex} of this section is empty. Add content or reduce the column count.\",\n};\n\nexport default en;\n","import en from \"./en\";\n\nexport type StructureMessageMap = typeof en;\nexport type StructureRuleMessageId = keyof StructureMessageMap;\n\nconst modules = import.meta.glob<{ default: StructureMessageMap }>(\"./*.ts\", {\n eager: true,\n});\n\nconst MESSAGES: Record<string, StructureMessageMap> = {};\nfor (const path in modules) {\n const match = /\\.\\/([^/]+)\\.ts$/.exec(path);\n if (!match) continue;\n const locale = match[1];\n if (locale === \"index\") continue;\n MESSAGES[locale] = modules[path].default;\n}\n\nexport const SUPPORTED_STRUCTURE_MESSAGE_LOCALES = Object.keys(MESSAGES);\n\nexport function getStructureMessages(locale: string): StructureMessageMap {\n const base = locale.split(\"-\")[0]?.toLowerCase() ?? \"en\";\n return MESSAGES[base] ?? MESSAGES.en ?? en;\n}\n\nexport function formatStructureMessage(\n locale: string,\n ruleId: StructureRuleMessageId,\n params?: Record<string, string | number>,\n): string {\n const map = getStructureMessages(locale);\n const template = map[ruleId] ?? en[ruleId];\n if (!params) return template;\n return template.replace(/\\{(\\w+)\\}/g, (_, key: string) => {\n const value = params[key];\n return value === undefined ? `{${key}}` : String(value);\n });\n}\n","import type { Block, SectionBlock, TemplateContent } from \"@templatical/types\";\nimport { isSection } from \"@templatical/types\";\nimport type { Rule, RuleHit, RuleMeta } from \"../../types\";\n\nexport const meta: RuleMeta = {\n id: \"structure.duplicate-block-id\",\n severity: \"error\",\n};\n\nfunction collectIds(blocks: Block[], counts: Map<string, number>): void {\n for (const block of blocks) {\n counts.set(block.id, (counts.get(block.id) ?? 0) + 1);\n if (isSection(block)) {\n for (const column of (block as SectionBlock).children) {\n collectIds(column, counts);\n }\n }\n }\n}\n\nexport const duplicateBlockId: Rule = {\n meta,\n template(content: TemplateContent): RuleHit[] {\n const counts = new Map<string, number>();\n collectIds(content.blocks, counts);\n\n const hits: RuleHit[] = [];\n for (const [id, count] of counts) {\n if (count > 1) {\n hits.push({ blockId: id, params: { count } });\n }\n }\n return hits;\n },\n};\n","import type { Block, SectionBlock, TemplateContent } from \"@templatical/types\";\nimport { isSection } from \"@templatical/types\";\nimport type { Rule, RuleHit, RuleMeta } from \"../../types\";\n\nexport const meta: RuleMeta = {\n id: \"structure.empty-column\",\n severity: \"warning\",\n};\n\nfunction findEmptyColumns(blocks: Block[], hits: RuleHit[]): void {\n for (const block of blocks) {\n if (!isSection(block)) continue;\n const section = block as SectionBlock;\n if (section.children.length > 1) {\n section.children.forEach((column, columnIndex) => {\n if (column.length === 0) {\n hits.push({\n blockId: section.id,\n params: { columnIndex: columnIndex + 1 },\n });\n }\n });\n }\n for (const column of section.children) {\n findEmptyColumns(column, hits);\n }\n }\n}\n\nexport const emptyColumn: Rule = {\n meta,\n template(content: TemplateContent): RuleHit[] {\n const hits: RuleHit[] = [];\n findEmptyColumns(content.blocks, hits);\n return hits;\n },\n};\n","import type { SectionBlock } from \"@templatical/types\";\nimport { isSection } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\n\nexport const meta: RuleMeta = {\n id: \"structure.empty-section\",\n severity: \"warning\",\n};\n\nfunction isSectionEmpty(section: SectionBlock): boolean {\n if (section.children.length === 0) return true;\n return section.children.every((column) => column.length === 0);\n}\n\nexport const emptySection: Rule = {\n meta,\n block(block) {\n if (!isSection(block)) return null;\n const section = block as SectionBlock;\n if (!isSectionEmpty(section)) return null;\n return {\n blockId: section.id,\n fix: {\n description: \"Remove the empty section\",\n apply: (ctx) => {\n ctx.removeBlock(section.id);\n },\n },\n };\n },\n};\n","import type { SectionBlock } from \"@templatical/types\";\nimport { isSection } from \"@templatical/types\";\nimport type { Rule, RuleMeta, WalkContext } from \"../../types\";\n\nexport const meta: RuleMeta = {\n id: \"structure.nested-section\",\n severity: \"error\",\n};\n\nexport const nestedSection: Rule = {\n meta,\n block(block, ctx: WalkContext) {\n if (!isSection(block)) return null;\n if (ctx.section === null) return null;\n const parentSection = ctx.section as SectionBlock;\n return {\n blockId: block.id,\n params: { parentId: parentSection.id },\n };\n },\n};\n","import type { ColumnLayout, SectionBlock } from \"@templatical/types\";\nimport { isSection } from \"@templatical/types\";\nimport type { Rule, RuleMeta } from \"../../types\";\n\nexport const meta: RuleMeta = {\n id: \"structure.section-column-mismatch\",\n severity: \"error\",\n};\n\nfunction expectedColumnCount(layout: ColumnLayout): number {\n if (layout === \"1\") return 1;\n if (layout === \"3\") return 3;\n return 2;\n}\n\nexport const sectionColumnMismatch: Rule = {\n meta,\n block(block) {\n if (!isSection(block)) return null;\n const section = block as SectionBlock;\n const expected = expectedColumnCount(section.columns);\n const actual = section.children.length;\n if (actual === expected) return null;\n return {\n blockId: section.id,\n params: { layout: section.columns, expected, actual },\n };\n },\n};\n","import type { TemplateContent } from \"@templatical/types\";\nimport type { LintIssue, LintOptions, Rule } from \"../types\";\nimport { resolveStructureOptions, runRules } from \"../run-rules\";\nimport {\n formatStructureMessage,\n type StructureRuleMessageId,\n} from \"./messages\";\nimport { duplicateBlockId } from \"./rules/duplicate-block-id\";\nimport { emptyColumn } from \"./rules/empty-column\";\nimport { emptySection } from \"./rules/empty-section\";\nimport { nestedSection } from \"./rules/nested-section\";\nimport { sectionColumnMismatch } from \"./rules/section-column-mismatch\";\n\nexport const STRUCTURE_RULES: Rule[] = [\n duplicateBlockId,\n emptySection,\n emptyColumn,\n nestedSection,\n sectionColumnMismatch,\n];\n\nexport function lintStructure(\n content: TemplateContent,\n options: LintOptions = {},\n): LintIssue[] {\n if (options.disabled === true || options.structure === false) return [];\n const tool = options.structure ?? {};\n const resolved = resolveStructureOptions(\n options.locale,\n tool,\n STRUCTURE_RULES,\n );\n return runRules(content, STRUCTURE_RULES, resolved, (locale, id, params) =>\n formatStructureMessage(locale, id as StructureRuleMessageId, params),\n );\n}\n","import type en from \"./en\";\n\nconst de: typeof en = {\n \"link.javascript-protocol\":\n 'Die URL verwendet das Protokoll „{protocol}:\", das beliebigen Skriptcode ausführen kann und aus Sicherheitsgründen beim Rendern entfernt wird. Ersetze sie durch eine echte URL oder entferne sie.',\n \"link.unsupported-protocol\":\n 'Die URL verwendet das Protokoll „{protocol}\", das von den meisten E-Mail-Clients nicht unterstützt wird. Verwende http, https, mailto, tel oder sms.',\n \"link.malformed-mailto\":\n \"Der mailto:-Link ist fehlerhaft. Erwartet wird eine einzelne Empfängeradresse vor einer eventuellen Querystring (z. B. mailto:hallo@example.com).\",\n \"link.malformed-tel\":\n \"Der tel:-Link enthält Zeichen, die keine Ziffern, +, Leerzeichen, Bindestriche, Klammern oder Punkte sind.\",\n \"link.localhost-or-staging\":\n 'Der URL-Host „{host}\" entspricht einem Nicht-Produktionsmuster. Ersetze ihn vor dem Versand durch die Produktions-URL.',\n};\n\nexport default de;\n","/**\n * English link-rule messages. The source of truth — other locales annotate\n * themselves `typeof en` so missing or extra keys fail typecheck.\n *\n * Templates use `{name}` placeholders, interpolated by `formatLinkMessage`.\n */\nconst en = {\n \"link.javascript-protocol\":\n 'URL uses the \"{protocol}:\" protocol, which can execute arbitrary script and is stripped at render time for safety. Replace it with a real link or remove the URL.',\n \"link.unsupported-protocol\":\n 'URL uses the \"{protocol}\" protocol, which most email clients do not support. Use http, https, mailto, tel, or sms.',\n \"link.malformed-mailto\":\n \"mailto: link is malformed. Expected a single recipient address before any query string (e.g. mailto:hello@example.com).\",\n \"link.malformed-tel\":\n \"tel: link contains characters that are not digits, +, spaces, dashes, parentheses, or dots.\",\n \"link.localhost-or-staging\":\n 'URL host \"{host}\" matches a non-production pattern. Replace with the production URL before sending.',\n};\n\nexport default en;\n","import en from \"./en\";\n\nexport type LinkMessageMap = typeof en;\nexport type LinkRuleMessageId = keyof LinkMessageMap;\n\nconst modules = import.meta.glob<{ default: LinkMessageMap }>(\"./*.ts\", {\n eager: true,\n});\n\nconst MESSAGES: Record<string, LinkMessageMap> = {};\nfor (const path in modules) {\n const match = /\\.\\/([^/]+)\\.ts$/.exec(path);\n if (!match) continue;\n const locale = match[1];\n if (locale === \"index\") continue;\n MESSAGES[locale] = modules[path].default;\n}\n\nexport const SUPPORTED_LINK_MESSAGE_LOCALES = Object.keys(MESSAGES);\n\nexport function getLinkMessages(locale: string): LinkMessageMap {\n const base = locale.split(\"-\")[0]?.toLowerCase() ?? \"en\";\n return MESSAGES[base] ?? MESSAGES.en ?? en;\n}\n\nexport function formatLinkMessage(\n locale: string,\n ruleId: LinkRuleMessageId,\n params?: Record<string, string | number>,\n): string {\n const map = getLinkMessages(locale);\n const template = map[ruleId] ?? en[ruleId];\n if (!params) return template;\n return template.replace(/\\{(\\w+)\\}/g, (_, key: string) => {\n const value = params[key];\n return value === undefined ? `{${key}}` : String(value);\n });\n}\n","import type { TemplateContent } from \"@templatical/types\";\nimport {\n isButton,\n isHtml,\n isImage,\n isMenu,\n isParagraph,\n isSocialIcons,\n isTitle,\n isVideo,\n} from \"@templatical/types\";\nimport { walkBlocks } from \"./walk\";\nimport { extractAnchors } from \"./html-utils\";\n\nexport type UrlSource =\n \"anchor\" | \"button\" | \"image-link\" | \"video\" | \"menu-item\" | \"social-icon\";\n\nexport interface UrlOccurrence {\n url: string;\n blockId: string;\n source: UrlSource;\n /** Anchor text or block-derived label, if applicable. */\n label?: string;\n}\n\n/**\n * Visit every URL-bearing field in the template tree.\n *\n * Sources covered:\n * - anchor — `<a href>` inside `title.content`, `paragraph.content`,\n * `html.content` (parsed via extractAnchors)\n * - button — `button.url`\n * - image-link — `image.linkUrl` (only when present + non-empty)\n * - video — `video.url`\n * - menu-item — `menu.items[i].url`\n * - social-icon — `social.icons[i].url`\n *\n * Each rule iterates this list once and decides per occurrence.\n */\nexport function walkUrls(content: TemplateContent): UrlOccurrence[] {\n const occurrences: UrlOccurrence[] = [];\n\n walkBlocks(content, (block) => {\n if (isTitle(block) || isParagraph(block) || isHtml(block)) {\n for (const anchor of extractAnchors(block.content)) {\n occurrences.push({\n url: anchor.href,\n blockId: block.id,\n source: \"anchor\",\n label: anchor.text,\n });\n }\n return;\n }\n\n if (isButton(block)) {\n occurrences.push({\n url: block.url,\n blockId: block.id,\n source: \"button\",\n label: block.text,\n });\n return;\n }\n\n if (isImage(block)) {\n if (block.linkUrl && block.linkUrl !== \"\") {\n occurrences.push({\n url: block.linkUrl,\n blockId: block.id,\n source: \"image-link\",\n label: block.alt || undefined,\n });\n }\n return;\n }\n\n if (isVideo(block)) {\n occurrences.push({\n url: block.url,\n blockId: block.id,\n source: \"video\",\n label: block.alt || undefined,\n });\n return;\n }\n\n if (isMenu(block)) {\n for (const item of block.items) {\n occurrences.push({\n url: item.url,\n blockId: block.id,\n source: \"menu-item\",\n label: item.text,\n });\n }\n return;\n }\n\n if (isSocialIcons(block)) {\n for (const icon of block.icons) {\n occurrences.push({\n url: icon.url,\n blockId: block.id,\n source: \"social-icon\",\n label: icon.platform,\n });\n }\n return;\n }\n });\n\n return occurrences;\n}\n","import type { Rule, RuleHit, RuleMeta } from \"../../types\";\nimport { walkUrls } from \"../../url-walker\";\n\nexport const meta: RuleMeta = {\n id: \"link.javascript-protocol\",\n severity: \"error\",\n};\n\n/**\n * The set of URL schemes that can encode executable script or arbitrary\n * payloads inside an `href`/`src` value. All three are in scope for this\n * rule because a sanitizer that strips `javascript:` but leaves `data:` or\n * `vbscript:` through is the textbook \"incomplete URL scheme check\" bug.\n *\n * Rule ID stays `link.javascript-protocol` for back-compat with consumer\n * severity overrides; the message is parameterized so users see the actual\n * matched protocol.\n */\nexport const DANGEROUS_SCRIPT_PROTOCOLS = [\n \"javascript\",\n \"data\",\n \"vbscript\",\n] as const;\n\ntype DangerousProtocol = (typeof DANGEROUS_SCRIPT_PROTOCOLS)[number];\n\n/**\n * Match dangerous-script schemes even when the value is whitespace-padded or\n * mixed-case. Mirrors what HTML attribute parsers see at insert time —\n * leading whitespace (spaces, tabs, newlines) is stripped before scheme\n * parsing, and unicode-percent-encoded whitespace inside the scheme is\n * rejected by browsers, so a literal-strip is sufficient.\n */\nfunction matchDangerousProtocol(url: string): DangerousProtocol | null {\n if (!url) return null;\n const stripped = url.replace(/\\s+/g, \"\");\n for (const proto of DANGEROUS_SCRIPT_PROTOCOLS) {\n if (new RegExp(`^${proto}:`, \"i\").test(stripped)) return proto;\n }\n return null;\n}\n\nexport const javascriptProtocol: Rule = {\n meta,\n template(content): RuleHit[] {\n const hits: RuleHit[] = [];\n for (const occ of walkUrls(content)) {\n const protocol = matchDangerousProtocol(occ.url);\n if (protocol !== null) {\n hits.push({ blockId: occ.blockId, params: { protocol } });\n }\n }\n return hits;\n },\n};\n","import type { Rule, RuleHit, RuleMeta } from \"../../types\";\nimport { walkUrls } from \"../../url-walker\";\nimport { DANGEROUS_SCRIPT_PROTOCOLS } from \"./javascript-protocol\";\n\nexport const meta: RuleMeta = {\n id: \"link.unsupported-protocol\",\n severity: \"warning\",\n};\n\nconst SUPPORTED = new Set([\"http\", \"https\", \"mailto\", \"tel\", \"sms\"]);\nconst DANGEROUS = new Set<string>(DANGEROUS_SCRIPT_PROTOCOLS);\n\n/**\n * Treat dangerous-script schemes (covered by `link.javascript-protocol`) and\n * bare/relative URLs as \"not unsupported\" — this rule fires only for\n * explicitly named schemes that email clients typically refuse.\n */\nfunction getProtocol(url: string): string | null {\n if (!url) return null;\n const trimmed = url.trim();\n const match = /^([a-z][a-z0-9+\\-.]*):/i.exec(trimmed);\n if (!match) return null;\n return match[1].toLowerCase();\n}\n\nexport const unsupportedProtocol: Rule = {\n meta,\n template(content): RuleHit[] {\n const hits: RuleHit[] = [];\n for (const occ of walkUrls(content)) {\n const protocol = getProtocol(occ.url);\n if (protocol === null) continue;\n if (DANGEROUS.has(protocol)) continue;\n if (SUPPORTED.has(protocol)) continue;\n hits.push({ blockId: occ.blockId, params: { protocol } });\n }\n return hits;\n },\n};\n","import type { Rule, RuleHit, RuleMeta } from \"../../types\";\nimport { walkUrls } from \"../../url-walker\";\n\nexport const meta: RuleMeta = {\n id: \"link.malformed-mailto\",\n severity: \"warning\",\n};\n\n/**\n * Pragmatic RFC-5321-ish sanity check, not a full validator. Splits on `?`,\n * requires the left side to contain exactly one `@` with a non-empty local\n * part and a domain that includes at least one dot.\n *\n * Multi-recipient `mailto:a@x.com,b@y.com` is accepted (commas pass through;\n * each recipient is validated individually).\n */\nfunction isMalformedMailto(url: string): boolean {\n const trimmed = url.trim();\n if (!/^mailto:/i.test(trimmed)) return false;\n const value = trimmed.slice(\"mailto:\".length);\n const [recipients] = value.split(\"?\", 2);\n if (recipients.trim() === \"\") return true;\n\n const list = recipients.split(\",\").map((r) => r.trim());\n for (const recipient of list) {\n if (recipient === \"\") return true;\n const at = recipient.split(\"@\");\n if (at.length !== 2) return true;\n const [local, domain] = at;\n if (local === \"\" || domain === \"\") return true;\n if (!domain.includes(\".\")) return true;\n }\n return false;\n}\n\nexport const malformedMailto: Rule = {\n meta,\n template(content): RuleHit[] {\n const hits: RuleHit[] = [];\n for (const occ of walkUrls(content)) {\n if (isMalformedMailto(occ.url)) {\n hits.push({ blockId: occ.blockId });\n }\n }\n return hits;\n },\n};\n","import type { Rule, RuleHit, RuleMeta } from \"../../types\";\nimport { walkUrls } from \"../../url-walker\";\n\nexport const meta: RuleMeta = {\n id: \"link.malformed-tel\",\n severity: \"warning\",\n};\n\nconst VALID_SUBSCRIBER_CHARS = /^[+0-9\\s().\\-]+$/;\n// RFC 3966 par = `;` pname [ \"=\" pvalue ]. pname is alphanum/`-`, pvalue is\n// 1+ paramchar. We accept anything non-empty on the right of `=` since email\n// clients don't validate it.\nconst VALID_PARAM = /^[A-Za-z0-9-]+(=[^;]+)?$/;\n\nfunction isMalformedTel(url: string): boolean {\n const trimmed = url.trim();\n if (!/^tel:/i.test(trimmed)) return false;\n const value = trimmed.slice(\"tel:\".length).trim();\n if (value === \"\") return true;\n const [subscriber, ...params] = value.split(\";\");\n if (!VALID_SUBSCRIBER_CHARS.test(subscriber)) return true;\n return params.some((p) => !VALID_PARAM.test(p));\n}\n\nexport const malformedTel: Rule = {\n meta,\n template(content): RuleHit[] {\n const hits: RuleHit[] = [];\n for (const occ of walkUrls(content)) {\n if (isMalformedTel(occ.url)) {\n hits.push({ blockId: occ.blockId });\n }\n }\n return hits;\n },\n};\n","import type { ResolvedOptions, Rule, RuleHit, RuleMeta } from \"../../types\";\nimport { walkUrls } from \"../../url-walker\";\n\nexport const meta: RuleMeta = {\n id: \"link.localhost-or-staging\",\n severity: \"warning\",\n};\n\n/**\n * Glob → RegExp for the `nonProductionHosts` pattern set. `*` is a wildcard\n * that matches any run of characters (including `.`) so `*.staging.*`\n * matches `app.staging.example.com` and `*.local` matches both `acme.local`\n * and `a.b.c.local`. Case-insensitive.\n */\nfunction globToRegex(pattern: string): RegExp {\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const expanded = escaped.replace(/\\*/g, \".*\");\n return new RegExp(`^${expanded}$`, \"i\");\n}\n\nfunction extractHost(url: string): string | null {\n if (!url) return null;\n const trimmed = url.trim();\n // mailto/tel/sms have no host concept worth matching.\n if (!/^(https?|ftps?):\\/\\//i.test(trimmed)) return null;\n try {\n return new URL(trimmed).hostname.toLowerCase();\n } catch {\n return null;\n }\n}\n\nexport const localhostOrStaging: Rule = {\n meta,\n template(content, opts: ResolvedOptions): RuleHit[] {\n const patterns = opts.links.nonProductionHosts;\n if (patterns.length === 0) return [];\n const regexes = patterns.map(globToRegex);\n const hits: RuleHit[] = [];\n\n for (const occ of walkUrls(content)) {\n const host = extractHost(occ.url);\n if (host === null) continue;\n if (regexes.some((re) => re.test(host))) {\n hits.push({ blockId: occ.blockId, params: { host } });\n }\n }\n return hits;\n },\n};\n","import type { TemplateContent } from \"@templatical/types\";\nimport type { LintIssue, LintOptions, Rule } from \"../types\";\nimport { resolveLinksOptions, runRules } from \"../run-rules\";\nimport { formatLinkMessage, type LinkRuleMessageId } from \"./messages\";\nimport { javascriptProtocol } from \"./rules/javascript-protocol\";\nimport { unsupportedProtocol } from \"./rules/unsupported-protocol\";\nimport { malformedMailto } from \"./rules/malformed-mailto\";\nimport { malformedTel } from \"./rules/malformed-tel\";\nimport { localhostOrStaging } from \"./rules/localhost-or-staging\";\n\nexport const LINK_RULES: Rule[] = [\n javascriptProtocol,\n unsupportedProtocol,\n malformedMailto,\n malformedTel,\n localhostOrStaging,\n];\n\nexport function lintLinks(\n content: TemplateContent,\n options: LintOptions = {},\n): LintIssue[] {\n if (options.disabled === true || options.links === false) return [];\n const tool = options.links ?? {};\n const resolved = resolveLinksOptions(options.locale, tool, LINK_RULES);\n return runRules(content, LINK_RULES, resolved, (locale, id, params) =>\n formatLinkMessage(locale, id as LinkRuleMessageId, params),\n );\n}\n","import type { LintOptions } from \"./types\";\n\n/**\n * `true` when no linter would run for the given options — either the\n * global `disabled` flag is set, or every per-tool key is `false`.\n *\n * The editor uses this to skip lazy-loading `@templatical/quality`, hide\n * the Issues sidebar tab, and suppress inline canvas badges. Headless\n * callers can use it to short-circuit before any linter call.\n */\nexport function isLintFullyDisabled(options: LintOptions | undefined): boolean {\n if (!options) return false;\n if (options.disabled === true) return true;\n return (\n options.accessibility === false &&\n options.structure === false &&\n options.links === false\n );\n}\n","import type { TemplateContent } from \"@templatical/types\";\nimport type { LintIssue, LintOptions } from \"./types\";\nimport { lintAccessibility } from \"./accessibility\";\nimport { lintStructure } from \"./structure\";\nimport { lintLinks } from \"./links\";\nimport { isLintFullyDisabled } from \"./util\";\n\n/**\n * Run every linter in the package — accessibility, structure, and links —\n * against `content` and return the merged issue list.\n *\n * This is the single entry point callers should prefer. CI guards, the\n * editor's live linter, and headless consumers all funnel through here, so\n * a new linter category is picked up everywhere by registering it in this\n * one fan-out — no consumer has to learn about the new function.\n *\n * Per-category options (`options.accessibility`, `options.structure`,\n * `options.links`) and the global `options.disabled` flag are forwarded\n * unchanged; each sub-linter already short-circuits when its category is\n * `false`, so the per-tool calls below are cheap no-ops when disabled.\n *\n * Issue order is stable: accessibility first, then structure, then links.\n */\nexport function lintTemplate(\n content: TemplateContent,\n options: LintOptions = {},\n): LintIssue[] {\n if (isLintFullyDisabled(options)) return [];\n return [\n ...lintAccessibility(content, options),\n ...lintStructure(content, options),\n ...lintLinks(content, options),\n ];\n}\n"],"mappings":"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"}
|