@aswin.dev/editor 0.7.0 → 0.7.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/LICENSE +56 -0
- package/README.md +3 -3
- package/dist/{AccessibilityPanel-CvQGLdu6.js → AccessibilityPanel-EmQ19wiS.js} +37 -37
- package/dist/{AiChatSidebar-B3SJIKG_.js → AiChatSidebar-DeB0w_32.js} +67 -81
- package/dist/{AiFeatureMenu-BLLKoOos.js → AiFeatureMenu-DoLD5Cde.js} +22 -22
- package/dist/{BlockA11yBadge-CXDLqkcJ.js → BlockA11yBadge-DkNbDvJA.js} +12 -12
- package/dist/CloudEditor-zo9PjjvY.js +1214 -0
- package/dist/{CollaboratorBar-DuPYW5iF.js → CollaboratorBar-BsXMY-8e.js} +21 -21
- package/dist/CommentsSidebar-DIWIa4rS.js +436 -0
- package/dist/CountdownBlock-BCi7-DAM.js +92 -0
- package/dist/CountdownToolbar-BuS8p5ju.js +210 -0
- package/dist/{DesignReferenceSidebar-B8V_F2yF.js → DesignReferenceSidebar-RDlnhL-6.js} +58 -58
- package/dist/{LoadingTrack-B0CWFHXQ.js → LoadingTrack-BJ59h9ok.js} +2 -2
- package/dist/ModuleBrowserModal-b7HbpByz.js +206 -0
- package/dist/ModulePreviewCanvas-D__YlOLS.js +108 -0
- package/dist/{NumberWithSuffix-DkXUez9t.js → NumberWithSuffix-Ca3vNY84.js} +87 -87
- package/dist/{ParagraphEditor-D75wl3BX.js → ParagraphEditor-B1aYPO-6.js} +182 -182
- package/dist/{RichTextEditorContent-DYkIauIk.js → RichTextEditorContent-BmEVMrkJ.js} +38 -38
- package/dist/{SaveModuleDialog-FZ9lxY7_.js → SaveModuleDialog-ClovqI6h.js} +28 -28
- package/dist/{SnapshotHistory-BR3eV120.js → SnapshotHistory-DoqtH0cw.js} +45 -50
- package/dist/{TemplateScoringPanel-4GTNHej5.js → TemplateScoringPanel-DQv2ZAiL.js} +75 -75
- package/dist/{TestEmailModal--ue5w9fT.js → TestEmailModal-iIeYJYsj.js} +28 -28
- package/dist/{TitleEditor-fStSADI-.js → TitleEditor-CTDIwRF_.js} +68 -68
- package/dist/{TplModal-BwSfxIHf.js → TplModal-CBq1J1pG.js} +14 -14
- package/dist/{accessibility-e8JYu_zd.js → accessibility-BU09xZrQ.js} +1 -1
- package/dist/{blockTypeIcons-BcTrDjmH.js → blockTypeIcons-QkC6f5UE.js} +19 -5
- package/dist/bundle-stats.json +7 -7
- package/dist/cdn/chunks/{AccessibilityPanel-B6DOjojm.js → AccessibilityPanel-BeU8nz7A.js} +28 -28
- package/dist/cdn/chunks/{AccessibilityPanel-B6DOjojm.js.map → AccessibilityPanel-BeU8nz7A.js.map} +1 -1
- package/dist/cdn/chunks/{AiFeatureMenu-qEdB2fZJ.js → AiFeatureMenu-B2mhscyP.js} +21 -21
- package/dist/cdn/chunks/AiFeatureMenu-B2mhscyP.js.map +1 -0
- package/dist/cdn/chunks/{BlockA11yBadge-DcEZftf6.js → BlockA11yBadge-C4g77gF0.js} +11 -11
- package/dist/cdn/chunks/{BlockA11yBadge-DcEZftf6.js.map → BlockA11yBadge-C4g77gF0.js.map} +1 -1
- package/dist/{CloudEditor-BCz1ZTYC.js → cdn/chunks/CloudEditor-Btyr0b0_.js} +486 -475
- package/dist/cdn/chunks/CloudEditor-Btyr0b0_.js.map +1 -0
- package/dist/cdn/chunks/{CollaboratorBar--nO7TX6b.js → CollaboratorBar-YBiIjiRh.js} +15 -15
- package/dist/cdn/chunks/CollaboratorBar-YBiIjiRh.js.map +1 -0
- package/dist/cdn/chunks/CountdownBlock-B06UZoWe.js +93 -0
- package/dist/cdn/chunks/CountdownBlock-B06UZoWe.js.map +1 -0
- package/dist/cdn/chunks/CountdownToolbar-C9XZr33O.js +212 -0
- package/dist/cdn/chunks/CountdownToolbar-C9XZr33O.js.map +1 -0
- package/dist/{ModuleBrowserModal-DrUFMTDx.js → cdn/chunks/ModuleBrowserModal-C2CDWKW6.js} +51 -62
- package/dist/cdn/chunks/ModuleBrowserModal-C2CDWKW6.js.map +1 -0
- package/dist/cdn/chunks/ModulePreviewCanvas-Drt8Evai.js +109 -0
- package/dist/cdn/chunks/ModulePreviewCanvas-Drt8Evai.js.map +1 -0
- package/dist/cdn/chunks/{NumberWithSuffix-CE3NrZhH.js → NumberWithSuffix-Ty1bp9vB.js} +64 -64
- package/dist/cdn/chunks/{NumberWithSuffix-CE3NrZhH.js.map → NumberWithSuffix-Ty1bp9vB.js.map} +1 -1
- package/dist/cdn/chunks/{ParagraphEditor-B6Ygu-Mq.js → ParagraphEditor-BA1WbHI7.js} +188 -188
- package/dist/cdn/chunks/{ParagraphEditor-B6Ygu-Mq.js.map → ParagraphEditor-BA1WbHI7.js.map} +1 -1
- package/dist/cdn/chunks/{RichTextEditorContent-DL_y2SrR.js → RichTextEditorContent-BtWCA_Oc.js} +30 -30
- package/dist/cdn/chunks/{RichTextEditorContent-DL_y2SrR.js.map → RichTextEditorContent-BtWCA_Oc.js.map} +1 -1
- package/dist/cdn/chunks/{SaveModuleDialog-B0TnO_o9.js → SaveModuleDialog-AwL0tkCV.js} +21 -21
- package/dist/cdn/chunks/SaveModuleDialog-AwL0tkCV.js.map +1 -0
- package/dist/cdn/chunks/{TitleEditor-BHpfxvwy.js → TitleEditor-DbSyeixS.js} +65 -65
- package/dist/cdn/chunks/TitleEditor-DbSyeixS.js.map +1 -0
- package/dist/cdn/chunks/blockTypeIcons-pQIkxJzc.js +23 -0
- package/dist/cdn/chunks/blockTypeIcons-pQIkxJzc.js.map +1 -0
- package/dist/cdn/chunks/{de-D8CnZxV9.js → de-_tooy3Q8.js} +250 -2
- package/dist/cdn/chunks/de-_tooy3Q8.js.map +1 -0
- package/dist/cdn/chunks/{draggable-Bcb86AsV.js → draggable-C-1_gch3.js} +2 -2
- package/dist/cdn/chunks/{draggable-Bcb86AsV.js.map → draggable-C-1_gch3.js.map} +1 -1
- package/dist/cdn/chunks/{en-8FHaQv4V.js → en-CNqLoIm9.js} +250 -2
- package/dist/cdn/chunks/en-CNqLoIm9.js.map +1 -0
- package/dist/cdn/chunks/{extensions-DIxF31tA.js → extensions-BVKQw_sp.js} +107 -107
- package/dist/cdn/chunks/extensions-BVKQw_sp.js.map +1 -0
- package/dist/cdn/chunks/{features-DEMb13KS.js → features-DIBEo4xl.js} +3388 -2289
- package/dist/cdn/chunks/features-DIBEo4xl.js.map +1 -0
- package/dist/cdn/chunks/{icons-CsLTcirh.js → icons-C1Gg-ov-.js} +346 -54
- package/dist/cdn/chunks/icons-C1Gg-ov-.js.map +1 -0
- package/dist/cdn/chunks/{media-library-CVaNvhpM.js → media-library-BTF_Ko70.js} +985 -985
- package/dist/cdn/chunks/media-library-BTF_Ko70.js.map +1 -0
- package/dist/cdn/chunks/{quality-BaBfc54_.js → quality-C5AmotmP.js} +312 -312
- package/dist/cdn/chunks/quality-C5AmotmP.js.map +1 -0
- package/dist/cdn/chunks/{renderer-CUxvx7ro.js → renderer-D0L44Vlp.js} +236 -142
- package/dist/cdn/chunks/renderer-D0L44Vlp.js.map +1 -0
- package/dist/cdn/chunks/{src-CRaqN-p8.js → src-RKexlYjA.js} +161 -161
- package/dist/cdn/chunks/src-RKexlYjA.js.map +1 -0
- package/dist/cdn/chunks/styleConstants-PgmvNBzQ.js +57 -0
- package/dist/cdn/chunks/styleConstants-PgmvNBzQ.js.map +1 -0
- package/dist/cdn/chunks/styles-CQR6ed13.js +4976 -0
- package/dist/cdn/chunks/styles-CQR6ed13.js.map +1 -0
- package/dist/cdn/chunks/{tiptap-ZhwKyFp7.js → tiptap-CDzAbF2j.js} +43 -43
- package/dist/cdn/chunks/{tiptap-ZhwKyFp7.js.map → tiptap-CDzAbF2j.js.map} +1 -1
- package/dist/cdn/editor.css +1 -1
- package/dist/cdn/editor.js +211 -123
- package/dist/cdn/editor.js.map +1 -1
- package/dist/{check-Da05j8yl.js → check-DJrpDKO_.js} +1 -1
- package/dist/{chevron-down-R2uY34iD.js → chevron-down-C5oBUhT8.js} +1 -1
- package/dist/chevron-right-BqCptpdp.js +10 -0
- package/dist/{circle-alert-DZuGWPX-.js → circle-alert-ZQQc98HC.js} +1 -1
- package/dist/{clock-CRp2sIub.js → clock-ik2pRJKG.js} +1 -1
- package/dist/{cloud-DEk_b4CR.js → cloud-DJG4tb4_.js} +485 -427
- package/dist/{createLucideIcon-C3pa2siy.js → createLucideIcon-ClREiSx3.js} +6 -6
- package/dist/{de-Brqvgr43.js → de-2LEvILeZ.js} +249 -1
- package/dist/{dist-Cp0zXPAD.js → dist-BHAeXaUY.js} +1 -1
- package/dist/{dist-BaQIYPsn.js → dist-BSJvAvH3.js} +1 -1
- package/dist/{dist-wzMIGj-D.js → dist-BeFnymxK.js} +1 -1
- package/dist/dist-Bmir0gYb.js +1167 -0
- package/dist/{dist-DDJIWTRY.js → dist-BvPgo-UK.js} +1 -1
- package/dist/{dist-BFawx6IS.js → dist-CPVBKMmd.js} +51 -51
- package/dist/dist-CivF9P8b.js +382 -0
- package/dist/{dist-D6uC2xhi.js → dist-Df4ie7vZ.js} +1 -1
- package/dist/{dist-us-RpCWN.js → dist-DxOoemkW.js} +1 -1
- package/dist/{dist-KoBJjK1G.js → dist-HEQ52gTJ.js} +1 -1
- package/dist/{dist-DjviJBCi.js → dist-b-XUqAoF.js} +1 -1
- package/dist/{dist-D90y8dvT.js → dist-kZfaVUpW.js} +3 -3
- package/dist/{dist-aRzjfSRN.js → dist-wfAedlzi.js} +1 -1
- package/dist/{en-WDVp87TE.js → en-D2RU2Poj.js} +249 -1
- package/dist/{extensions-CUcl9Ok4.js → extensions-BQ1xXx3d.js} +103 -103
- package/dist/{image-up-MBZKKg9p.js → image-up-DT7gcJLN.js} +1 -1
- package/dist/index.d.ts +102 -14
- package/dist/{info-CJEC7piy.js → info-BSPGcsSM.js} +1 -1
- package/dist/keys-CvX8D-8C.js +10 -0
- package/dist/{loader-circle-DsY5Yg33.js → loader-circle-Balo8p3d.js} +1 -1
- package/dist/{message-circle-yElBbR2C.js → message-circle-B39qAHxs.js} +1 -1
- package/dist/pencil-BZJPNYWR.js +10 -0
- package/dist/{refresh-cw-CE_AGtn8.js → refresh-cw-DwDqGUM0.js} +1 -1
- package/dist/{scan-line-D0vcUekt.js → scan-line-DlghmhNf.js} +1 -1
- package/dist/{send-DH4oDQqC.js → send-DDdhIRj8.js} +1 -1
- package/dist/{shield-check-CfJgs2Hd.js → shield-check-OSQ-JVTX.js} +1 -1
- package/dist/{sparkles-CvRXGqFs.js → sparkles-BN4a-CoF.js} +1 -1
- package/dist/style.css +1 -1
- package/dist/styleConstants-wWRbcuEK.js +55 -0
- package/dist/styles-CavWjvol.js +5487 -0
- package/dist/templatical-editor.js +211 -119
- package/dist/{text-align-start-BT9VUDxK.js → text-align-start-D1weisjS.js} +1 -1
- package/dist/{trash-2-DbP2Y6t2.js → trash-2-CMWvQ5KX.js} +1 -1
- package/dist/{triangle-alert-aOXceTSe.js → triangle-alert-DyidRNX_.js} +1 -1
- package/dist/undo-2-Cg8I7obC.js +16 -0
- package/dist/{useCloudI18n-BuIwR6OE.js → useCloudI18n-BTTNBk5i.js} +2 -2
- package/dist/{useEditorCore-C6ost42Q.js → useEditorCore-BGnzcT7p.js} +2424 -2249
- package/dist/{useI18n-lb2DHDiu.js → useI18n-C2xQZ6K9.js} +2 -2
- package/dist/{useMergeTag-CBwKnnNB.js → useMergeTag-CfuZq2fF.js} +4 -4
- package/dist/{vue.runtime.esm-bundler-DpvJL-nX.js → vue.runtime.esm-bundler-CjauPXjj.js} +1 -1
- package/dist/{x-u2oVmjN_.js → x-CgIhNcT9.js} +1 -1
- package/package.json +15 -15
- package/dist/CommentsSidebar-B1pvJdqF.js +0 -441
- package/dist/CountdownBlock-BNSj1jvJ.js +0 -92
- package/dist/CountdownToolbar-ClJr2GzL.js +0 -210
- package/dist/ModulePreviewCanvas-CHdOwV_4.js +0 -106
- package/dist/cdn/chunks/AiFeatureMenu-qEdB2fZJ.js.map +0 -1
- package/dist/cdn/chunks/CloudEditor-D2GsEC_n.js +0 -1143
- package/dist/cdn/chunks/CloudEditor-D2GsEC_n.js.map +0 -1
- package/dist/cdn/chunks/CollaboratorBar--nO7TX6b.js.map +0 -1
- package/dist/cdn/chunks/CountdownBlock-5YdT1uUu.js +0 -93
- package/dist/cdn/chunks/CountdownBlock-5YdT1uUu.js.map +0 -1
- package/dist/cdn/chunks/CountdownToolbar-DXPXrbAA.js +0 -212
- package/dist/cdn/chunks/CountdownToolbar-DXPXrbAA.js.map +0 -1
- package/dist/cdn/chunks/ModuleBrowserModal-DxoPp81s.js +0 -195
- package/dist/cdn/chunks/ModuleBrowserModal-DxoPp81s.js.map +0 -1
- package/dist/cdn/chunks/ModulePreviewCanvas-CoLdb4ar.js +0 -107
- package/dist/cdn/chunks/ModulePreviewCanvas-CoLdb4ar.js.map +0 -1
- package/dist/cdn/chunks/SaveModuleDialog-B0TnO_o9.js.map +0 -1
- package/dist/cdn/chunks/TitleEditor-BHpfxvwy.js.map +0 -1
- package/dist/cdn/chunks/blockTypeIcons-BzzY9_kA.js +0 -22
- package/dist/cdn/chunks/blockTypeIcons-BzzY9_kA.js.map +0 -1
- package/dist/cdn/chunks/de-D8CnZxV9.js.map +0 -1
- package/dist/cdn/chunks/en-8FHaQv4V.js.map +0 -1
- package/dist/cdn/chunks/extensions-DIxF31tA.js.map +0 -1
- package/dist/cdn/chunks/features-DEMb13KS.js.map +0 -1
- package/dist/cdn/chunks/icons-CsLTcirh.js.map +0 -1
- package/dist/cdn/chunks/media-library-CVaNvhpM.js.map +0 -1
- package/dist/cdn/chunks/quality-BaBfc54_.js.map +0 -1
- package/dist/cdn/chunks/renderer-CUxvx7ro.js.map +0 -1
- package/dist/cdn/chunks/src-CRaqN-p8.js.map +0 -1
- package/dist/cdn/chunks/styleConstants-DP1VOca8.js +0 -57
- package/dist/cdn/chunks/styleConstants-DP1VOca8.js.map +0 -1
- package/dist/cdn/chunks/styles-BHJULjNR.js +0 -2947
- package/dist/cdn/chunks/styles-BHJULjNR.js.map +0 -1
- package/dist/dist-B1IR0bpH.js +0 -326
- package/dist/dist-DJmnUmW9.js +0 -362
- package/dist/keys-ciNfSSGj.js +0 -10
- package/dist/styleConstants-fWzlIIwN.js +0 -55
- package/dist/styles-DEXEkBvg.js +0 -3176
- /package/dist/{_plugin-vue_export-helper-B0hnzhyu.js → _plugin-vue_export-helper-Bwh4ceeO.js} +0 -0
- /package/dist/{de-DCaaCE5s.js → de-D2npYjrZ.js} +0 -0
- /package/dist/{dist-iLBdeBDR.js → dist-DvHLtWVP.js} +0 -0
- /package/dist/{emojiData-PQyVa4bU.js → emojiData-DvQBBzmO.js} +0 -0
- /package/dist/{en-DXCyK4-X.js → en-ib-4h3_o.js} +0 -0
- /package/dist/{formatRelativeTime-BOEf47hq.js → formatRelativeTime-CFDZnEIs.js} +0 -0
- /package/dist/{liquid.browser-CdMv1BTn.js → liquid.browser-7Rv0QDiO.js} +0 -0
- /package/dist/{readableTextColor-CY3SiRnt.js → readableTextColor-C_9OpzBw.js} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { _ as O, g as k, h as A, n as j, r as M, t as N, v as P, y as F } from "./tiptap-
|
|
1
|
+
import { A as e, C as t, G as n, I as r, P as i, T as a, W as o, _ as s, c, ct as l, d as u, dt as d, f, ft as p, g as m, h, m as g, r as _, tt as v, u as y, ut as b, v as x } from "./draggable-C-1_gch3.js";
|
|
2
|
+
import { Cn as S, Dn as C, En as w, Lt as T, Q as E, Tn as D } from "./features-DIBEo4xl.js";
|
|
3
|
+
import { _ as O, g as k, h as A, n as j, r as M, t as N, v as P, y as F } from "./tiptap-CDzAbF2j.js";
|
|
4
4
|
//#region src/extensions/FontSize.ts
|
|
5
5
|
var I = A.create({
|
|
6
6
|
name: "fontSize",
|
|
@@ -72,7 +72,7 @@ var I = A.create({
|
|
|
72
72
|
"aria-label",
|
|
73
73
|
"data-tooltip",
|
|
74
74
|
"onKeydown"
|
|
75
|
-
], te = ["aria-label", "onKeydown"], ne = ["aria-label"], z = /* @__PURE__ */
|
|
75
|
+
], te = ["aria-label", "onKeydown"], ne = ["aria-label"], z = /* @__PURE__ */ t({
|
|
76
76
|
__name: "LogicMergeTagNodeView",
|
|
77
77
|
props: {
|
|
78
78
|
node: {},
|
|
@@ -82,9 +82,9 @@ var I = A.create({
|
|
|
82
82
|
updateAttributes: { type: Function }
|
|
83
83
|
},
|
|
84
84
|
setup(t) {
|
|
85
|
-
let
|
|
85
|
+
let r = t, { syntax: a } = E(), { t: f } = T(), _ = g(() => C(r.node.attrs.value, a)), S = g(() => D(r.node.attrs.value, a)), w = v(!1), O = v(""), k = v(null), A = !1;
|
|
86
86
|
function M() {
|
|
87
|
-
O.value =
|
|
87
|
+
O.value = r.node.attrs.value, A = !1, w.value = !0, e(() => {
|
|
88
88
|
k.value?.focus(), k.value?.select();
|
|
89
89
|
});
|
|
90
90
|
}
|
|
@@ -93,56 +93,56 @@ var I = A.create({
|
|
|
93
93
|
A = !0;
|
|
94
94
|
let e = O.value.trim();
|
|
95
95
|
if (!e) {
|
|
96
|
-
|
|
96
|
+
w.value = !1;
|
|
97
97
|
return;
|
|
98
98
|
}
|
|
99
|
-
e !==
|
|
99
|
+
e !== r.node.attrs.value && r.updateAttributes({
|
|
100
100
|
value: e,
|
|
101
|
-
keyword:
|
|
102
|
-
}),
|
|
101
|
+
keyword: C(e, a) ? D(e, a) : ""
|
|
102
|
+
}), w.value = !1;
|
|
103
103
|
}
|
|
104
104
|
function P(e) {
|
|
105
|
-
e.key === "Enter" ? (e.preventDefault(), N()) : e.key === "Escape" && (
|
|
105
|
+
e.key === "Enter" ? (e.preventDefault(), N()) : e.key === "Escape" && (w.value = !1);
|
|
106
106
|
}
|
|
107
|
-
return (e,
|
|
107
|
+
return (e, r) => (i(), m(l(j), {
|
|
108
108
|
as: "span",
|
|
109
|
-
class:
|
|
110
|
-
style:
|
|
109
|
+
class: b(_.value ? "tpl-logic-merge-tag-node tpl:group tpl:mx-0.5 tpl:inline-flex tpl:items-center tpl:gap-1 tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.8em] tpl:font-bold tpl:tracking-wide tpl:uppercase tpl:select-none" : ""),
|
|
110
|
+
style: d(_.value ? "background-color: transparent; border: 1.5px solid color-mix(in srgb, var(--tpl-primary) 50%, transparent); color: var(--tpl-primary);" : ""),
|
|
111
111
|
contenteditable: "false"
|
|
112
112
|
}, {
|
|
113
|
-
default:
|
|
113
|
+
default: o(() => [w.value ? n((i(), x("input", {
|
|
114
114
|
key: 0,
|
|
115
115
|
ref_key: "inputRef",
|
|
116
116
|
ref: k,
|
|
117
|
-
"onUpdate:modelValue":
|
|
117
|
+
"onUpdate:modelValue": r[0] ||= (e) => O.value = e,
|
|
118
118
|
type: "text",
|
|
119
119
|
class: "tpl:w-40 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-0.5 tpl:py-0 tpl:text-[1em] tpl:font-medium tpl:normal-case tpl:outline-none tpl:text-[var(--tpl-primary)]",
|
|
120
120
|
onBlur: N,
|
|
121
121
|
onKeydown: P
|
|
122
|
-
}, null, 544)), [[
|
|
122
|
+
}, null, 544)), [[c, O.value]]) : _.value ? (i(), x("span", {
|
|
123
123
|
key: 1,
|
|
124
124
|
role: "button",
|
|
125
125
|
tabindex: "0",
|
|
126
|
-
"aria-label":
|
|
126
|
+
"aria-label": l(f).mergeTag.editValue,
|
|
127
127
|
class: "tpl-tooltip tpl:cursor-pointer",
|
|
128
128
|
"data-tooltip": t.node.attrs.value,
|
|
129
|
-
onClick:
|
|
130
|
-
onKeydown: [
|
|
131
|
-
},
|
|
129
|
+
onClick: u(M, ["stop"]),
|
|
130
|
+
onKeydown: [y(u(M, ["stop"]), ["enter"]), y(u(M, ["prevent", "stop"]), ["space"])]
|
|
131
|
+
}, p(S.value), 41, ee)) : (i(), x("span", {
|
|
132
132
|
key: 2,
|
|
133
133
|
role: "button",
|
|
134
134
|
tabindex: "0",
|
|
135
|
-
"aria-label":
|
|
136
|
-
onClick:
|
|
137
|
-
onKeydown: [
|
|
138
|
-
},
|
|
135
|
+
"aria-label": l(f).mergeTag.editValue,
|
|
136
|
+
onClick: u(M, ["stop"]),
|
|
137
|
+
onKeydown: [y(u(M, ["stop"]), ["enter"]), y(u(M, ["prevent", "stop"]), ["space"])]
|
|
138
|
+
}, p(t.node.attrs.value), 41, te)), _.value ? (i(), x("button", {
|
|
139
139
|
key: 3,
|
|
140
140
|
type: "button",
|
|
141
|
-
"aria-label":
|
|
141
|
+
"aria-label": l(f).mergeTag.deleteMergeTag,
|
|
142
142
|
class: "tpl-merge-tag-delete tpl:flex tpl:size-5 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:opacity-60 tpl:transition-all hover:tpl:opacity-100 tpl:text-[var(--tpl-primary)]",
|
|
143
143
|
contenteditable: "false",
|
|
144
|
-
onClick:
|
|
145
|
-
}, [...
|
|
144
|
+
onClick: r[1] ||= u((...e) => t.deleteNode && t.deleteNode(...e), ["stop", "prevent"])
|
|
145
|
+
}, [...r[2] ||= [h("svg", {
|
|
146
146
|
width: "10",
|
|
147
147
|
height: "10",
|
|
148
148
|
viewBox: "0 0 24 24",
|
|
@@ -160,7 +160,7 @@ var I = A.create({
|
|
|
160
160
|
y1: "6",
|
|
161
161
|
x2: "18",
|
|
162
162
|
y2: "18"
|
|
163
|
-
})], -1)]], 8, ne)) :
|
|
163
|
+
})], -1)]], 8, ne)) : s("", !0)]),
|
|
164
164
|
_: 1
|
|
165
165
|
}, 8, ["class", "style"]));
|
|
166
166
|
}
|
|
@@ -186,7 +186,7 @@ var H = O.create({
|
|
|
186
186
|
inline: !0,
|
|
187
187
|
atom: !0,
|
|
188
188
|
addOptions() {
|
|
189
|
-
return { syntax:
|
|
189
|
+
return { syntax: S.liquid };
|
|
190
190
|
},
|
|
191
191
|
addAttributes() {
|
|
192
192
|
return {
|
|
@@ -204,7 +204,7 @@ var H = O.create({
|
|
|
204
204
|
return [{ tag: "span[data-logic-merge-tag]" }];
|
|
205
205
|
},
|
|
206
206
|
renderHTML({ node: e, HTMLAttributes: t }) {
|
|
207
|
-
if (!
|
|
207
|
+
if (!C(e.attrs.value, this.options.syntax)) return [
|
|
208
208
|
"span",
|
|
209
209
|
{},
|
|
210
210
|
e.attrs.value
|
|
@@ -233,7 +233,7 @@ var H = O.create({
|
|
|
233
233
|
find: RegExp(this.options.syntax.logic.source + "$", ""),
|
|
234
234
|
handler: ({ state: e, range: t, match: n }) => {
|
|
235
235
|
let r = n[0];
|
|
236
|
-
if (!
|
|
236
|
+
if (!C(r, this.options.syntax)) return;
|
|
237
237
|
let i = D(r, this.options.syntax), a = this.type.create({
|
|
238
238
|
value: r,
|
|
239
239
|
keyword: i
|
|
@@ -247,7 +247,7 @@ var H = O.create({
|
|
|
247
247
|
find: new RegExp(this.options.syntax.logic.source, "g"),
|
|
248
248
|
handler: ({ state: e, range: t, match: n }) => {
|
|
249
249
|
let r = n[0];
|
|
250
|
-
if (!
|
|
250
|
+
if (!C(r, this.options.syntax)) return;
|
|
251
251
|
let i = D(r, this.options.syntax), a = this.type.create({
|
|
252
252
|
value: r,
|
|
253
253
|
keyword: i
|
|
@@ -260,7 +260,7 @@ var H = O.create({
|
|
|
260
260
|
"aria-label",
|
|
261
261
|
"data-tooltip",
|
|
262
262
|
"onKeydown"
|
|
263
|
-
], W = ["aria-label"], G = /* @__PURE__ */
|
|
263
|
+
], W = ["aria-label"], G = /* @__PURE__ */ t({
|
|
264
264
|
__name: "MergeTagNodeView",
|
|
265
265
|
props: {
|
|
266
266
|
node: {},
|
|
@@ -268,53 +268,53 @@ var H = O.create({
|
|
|
268
268
|
updateAttributes: { type: Function }
|
|
269
269
|
},
|
|
270
270
|
setup(t) {
|
|
271
|
-
let
|
|
272
|
-
function
|
|
273
|
-
|
|
274
|
-
|
|
271
|
+
let r = t, { getMergeTagLabel: a } = E(), { t: s } = T(), d = g(() => a(r.node.attrs.value)), f = v(!1), _ = v(""), b = v(null);
|
|
272
|
+
function S() {
|
|
273
|
+
_.value = r.node.attrs.value, f.value = !0, e(() => {
|
|
274
|
+
b.value?.focus(), b.value?.select();
|
|
275
275
|
});
|
|
276
276
|
}
|
|
277
|
-
function
|
|
278
|
-
let e =
|
|
279
|
-
e && e !==
|
|
277
|
+
function C() {
|
|
278
|
+
let e = _.value.trim();
|
|
279
|
+
e && e !== r.node.attrs.value && r.updateAttributes({
|
|
280
280
|
value: e,
|
|
281
|
-
label:
|
|
282
|
-
}),
|
|
281
|
+
label: a(e)
|
|
282
|
+
}), f.value = !1;
|
|
283
283
|
}
|
|
284
|
-
function
|
|
285
|
-
e.key === "Enter" ? (e.preventDefault(),
|
|
284
|
+
function w(e) {
|
|
285
|
+
e.key === "Enter" ? (e.preventDefault(), C()) : e.key === "Escape" && (f.value = !1);
|
|
286
286
|
}
|
|
287
|
-
return (e,
|
|
287
|
+
return (e, r) => (i(), m(l(j), {
|
|
288
288
|
as: "span",
|
|
289
289
|
class: "tpl-merge-tag-node tpl:group tpl:mx-0.5 tpl:inline-flex tpl:items-center tpl:gap-1 tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.9em] tpl:font-medium tpl:select-none tpl:text-[var(--tpl-primary)]",
|
|
290
290
|
style: { "background-color": "color-mix(in srgb, var(--tpl-primary) 20%, transparent)" },
|
|
291
291
|
contenteditable: "false"
|
|
292
292
|
}, {
|
|
293
|
-
default:
|
|
293
|
+
default: o(() => [f.value ? n((i(), x("input", {
|
|
294
294
|
key: 0,
|
|
295
295
|
ref_key: "inputRef",
|
|
296
|
-
ref:
|
|
297
|
-
"onUpdate:modelValue":
|
|
296
|
+
ref: b,
|
|
297
|
+
"onUpdate:modelValue": r[0] ||= (e) => _.value = e,
|
|
298
298
|
type: "text",
|
|
299
299
|
class: "tpl:w-32 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-0.5 tpl:py-0 tpl:text-[1em] tpl:font-medium tpl:outline-none tpl:text-[var(--tpl-primary)]",
|
|
300
|
-
onBlur:
|
|
301
|
-
onKeydown:
|
|
302
|
-
}, null, 544)), [[
|
|
300
|
+
onBlur: C,
|
|
301
|
+
onKeydown: w
|
|
302
|
+
}, null, 544)), [[c, _.value]]) : (i(), x("span", {
|
|
303
303
|
key: 1,
|
|
304
304
|
role: "button",
|
|
305
305
|
tabindex: "0",
|
|
306
|
-
"aria-label": s
|
|
306
|
+
"aria-label": l(s).mergeTag.editValue,
|
|
307
307
|
class: "tpl-tooltip tpl:cursor-pointer",
|
|
308
308
|
"data-tooltip": t.node.attrs.value,
|
|
309
|
-
onClick:
|
|
310
|
-
onKeydown: [
|
|
311
|
-
},
|
|
309
|
+
onClick: u(S, ["stop"]),
|
|
310
|
+
onKeydown: [y(u(S, ["stop"]), ["enter"]), y(u(S, ["prevent", "stop"]), ["space"])]
|
|
311
|
+
}, p(d.value), 41, U)), h("button", {
|
|
312
312
|
type: "button",
|
|
313
|
-
"aria-label": s
|
|
313
|
+
"aria-label": l(s).mergeTag.deleteMergeTag,
|
|
314
314
|
class: "tpl-merge-tag-delete tpl:flex tpl:size-5 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:opacity-60 tpl:transition-all hover:tpl:opacity-100 tpl:text-[var(--tpl-primary)]",
|
|
315
315
|
contenteditable: "false",
|
|
316
|
-
onClick:
|
|
317
|
-
}, [...
|
|
316
|
+
onClick: r[1] ||= u((...e) => t.deleteNode && t.deleteNode(...e), ["stop", "prevent"])
|
|
317
|
+
}, [...r[2] ||= [h("svg", {
|
|
318
318
|
width: "10",
|
|
319
319
|
height: "10",
|
|
320
320
|
viewBox: "0 0 24 24",
|
|
@@ -344,7 +344,7 @@ var H = O.create({
|
|
|
344
344
|
addOptions() {
|
|
345
345
|
return {
|
|
346
346
|
mergeTags: [],
|
|
347
|
-
syntax:
|
|
347
|
+
syntax: S.liquid
|
|
348
348
|
};
|
|
349
349
|
},
|
|
350
350
|
addAttributes() {
|
|
@@ -363,7 +363,7 @@ var H = O.create({
|
|
|
363
363
|
return [{ tag: "span[data-merge-tag]" }];
|
|
364
364
|
},
|
|
365
365
|
renderHTML({ node: e, HTMLAttributes: t }) {
|
|
366
|
-
let n =
|
|
366
|
+
let n = w(e.attrs.value, this.options.mergeTags);
|
|
367
367
|
return [
|
|
368
368
|
"span",
|
|
369
369
|
F(t, {
|
|
@@ -392,7 +392,7 @@ var H = O.create({
|
|
|
392
392
|
return [new k({
|
|
393
393
|
find: RegExp(this.options.syntax.value.source + "$", ""),
|
|
394
394
|
handler: ({ state: e, range: t, match: n }) => {
|
|
395
|
-
let r = n[0], i =
|
|
395
|
+
let r = n[0], i = w(r, this.options.mergeTags), a = this.type.create({
|
|
396
396
|
label: i,
|
|
397
397
|
value: r
|
|
398
398
|
});
|
|
@@ -404,7 +404,7 @@ var H = O.create({
|
|
|
404
404
|
return [new P({
|
|
405
405
|
find: new RegExp(this.options.syntax.value.source, "g"),
|
|
406
406
|
handler: ({ state: e, range: t, match: n }) => {
|
|
407
|
-
let r = n[0], i =
|
|
407
|
+
let r = n[0], i = w(r, this.options.mergeTags), a = this.type.create({
|
|
408
408
|
label: i,
|
|
409
409
|
value: r
|
|
410
410
|
});
|
|
@@ -423,7 +423,7 @@ var H = O.create({
|
|
|
423
423
|
"data-merge-tag-value",
|
|
424
424
|
"onMousedown",
|
|
425
425
|
"onMousemove"
|
|
426
|
-
], X = { class: "tpl:font-medium" }, re = { class: "tpl:text-[var(--tpl-text-dim)] tpl:font-mono" }, ie = /* @__PURE__ */
|
|
426
|
+
], X = { class: "tpl:font-medium" }, re = { class: "tpl:text-[var(--tpl-text-dim)] tpl:font-mono" }, ie = /* @__PURE__ */ t({
|
|
427
427
|
__name: "MergeTagSuggestionList",
|
|
428
428
|
props: {
|
|
429
429
|
items: {},
|
|
@@ -433,27 +433,27 @@ var H = O.create({
|
|
|
433
433
|
},
|
|
434
434
|
emits: ["select", "hover"],
|
|
435
435
|
setup(e) {
|
|
436
|
-
let
|
|
437
|
-
function
|
|
438
|
-
return
|
|
436
|
+
let t = e;
|
|
437
|
+
function n(e) {
|
|
438
|
+
return t.listId ? `${t.listId}-opt-${e}` : void 0;
|
|
439
439
|
}
|
|
440
|
-
return (
|
|
440
|
+
return (t, a) => (i(), x("div", {
|
|
441
441
|
id: e.listId,
|
|
442
442
|
class: "tpl:min-w-[200px] tpl:max-w-[320px] tpl:max-h-[50vh] tpl:overflow-y-auto tpl:rounded-[var(--tpl-radius)] tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)] tpl:py-1 tpl:shadow-lg",
|
|
443
443
|
role: "listbox",
|
|
444
444
|
"data-testid": "merge-tag-suggestion-list"
|
|
445
|
-
}, [e.items.length === 0 ? (
|
|
446
|
-
key:
|
|
447
|
-
id:
|
|
445
|
+
}, [e.items.length === 0 ? (i(), x("div", J, p(e.emptyText), 1)) : s("", !0), (i(!0), x(f, null, r(e.items, (r, a) => (i(), x("button", {
|
|
446
|
+
key: r.value,
|
|
447
|
+
id: n(a),
|
|
448
448
|
type: "button",
|
|
449
449
|
role: "option",
|
|
450
450
|
"aria-selected": a === e.selectedIndex,
|
|
451
451
|
"data-selected": a === e.selectedIndex ? "true" : "false",
|
|
452
|
-
"data-merge-tag-value":
|
|
453
|
-
class:
|
|
454
|
-
onMousedown:
|
|
455
|
-
onMousemove: (
|
|
456
|
-
}, [h("span", X,
|
|
452
|
+
"data-merge-tag-value": r.value,
|
|
453
|
+
class: b(["tpl:flex tpl:w-full tpl:flex-col tpl:items-start tpl:gap-0.5 tpl:px-3 tpl:py-1.5 tpl:text-left tpl:text-xs tpl:transition-colors", a === e.selectedIndex ? "tpl:bg-[var(--tpl-primary-light)] tpl:text-[var(--tpl-primary)]" : "tpl:text-[var(--tpl-text)] hover:tpl:bg-[var(--tpl-bg-hover)]"]),
|
|
454
|
+
onMousedown: u((e) => t.$emit("select", r), ["prevent", "stop"]),
|
|
455
|
+
onMousemove: (n) => a !== e.selectedIndex && t.$emit("hover", a)
|
|
456
|
+
}, [h("span", X, p(r.label), 1), h("span", re, p(r.value), 1)], 42, Y))), 128))], 8, q));
|
|
457
457
|
}
|
|
458
458
|
}), Z = 10, ae = 0;
|
|
459
459
|
function Q(e, t) {
|
|
@@ -476,12 +476,12 @@ var oe = A.create({
|
|
|
476
476
|
};
|
|
477
477
|
},
|
|
478
478
|
addProseMirrorPlugins() {
|
|
479
|
-
let
|
|
479
|
+
let e = this.options.mergeTags, t = this.options.emptyText, n = {
|
|
480
480
|
char: this.options.char,
|
|
481
481
|
allowSpaces: !1,
|
|
482
482
|
startOfLine: !1,
|
|
483
483
|
allowedPrefixes: null,
|
|
484
|
-
items: ({ query:
|
|
484
|
+
items: ({ query: t }) => Q(e, t),
|
|
485
485
|
command: ({ editor: e, range: t, props: n }) => {
|
|
486
486
|
e.chain().focus().insertContentAt(t, {
|
|
487
487
|
type: "mergeTagNode",
|
|
@@ -492,7 +492,7 @@ var oe = A.create({
|
|
|
492
492
|
}).run();
|
|
493
493
|
},
|
|
494
494
|
render: () => {
|
|
495
|
-
let
|
|
495
|
+
let e = null, n = null, r = null, i = v([]), o = v(0), s = null, c = `tpl-merge-tag-suggestion-${++ae}`, l = null, u = [];
|
|
496
496
|
function d() {
|
|
497
497
|
g(l?.() ?? null);
|
|
498
498
|
}
|
|
@@ -520,15 +520,15 @@ var oe = A.create({
|
|
|
520
520
|
window.removeEventListener("resize", d), u = [];
|
|
521
521
|
}
|
|
522
522
|
function g(e) {
|
|
523
|
-
if (!
|
|
524
|
-
|
|
525
|
-
let t =
|
|
523
|
+
if (!n || !e || e.bottom < 0 || e.top > window.innerHeight) return;
|
|
524
|
+
n.style.position = "fixed", n.style.left = `${e.left}px`, n.style.zIndex = "9999", n.style.top = `${e.bottom}px`;
|
|
525
|
+
let t = n.offsetHeight;
|
|
526
526
|
if (t !== 0 && window.innerHeight - e.bottom < t) {
|
|
527
|
-
let
|
|
528
|
-
|
|
527
|
+
let r = Math.max(0, e.top - t);
|
|
528
|
+
n.style.top = `${r}px`;
|
|
529
529
|
}
|
|
530
530
|
}
|
|
531
|
-
function
|
|
531
|
+
function y(e, t) {
|
|
532
532
|
let n = t?.closest("[data-tpl-theme]");
|
|
533
533
|
if (!n) return;
|
|
534
534
|
let r = n.getAttribute("data-tpl-theme");
|
|
@@ -540,59 +540,59 @@ var oe = A.create({
|
|
|
540
540
|
}
|
|
541
541
|
e.style.fontFamily = i.fontFamily, e.style.fontSize = i.fontSize, e.style.lineHeight = i.lineHeight;
|
|
542
542
|
}
|
|
543
|
-
function
|
|
544
|
-
|
|
543
|
+
function b(e) {
|
|
544
|
+
r && (e ? (r.setAttribute("role", "combobox"), r.setAttribute("aria-haspopup", "listbox"), r.setAttribute("aria-expanded", "true"), r.setAttribute("aria-controls", c)) : (r.removeAttribute("aria-expanded"), r.removeAttribute("aria-controls"), r.removeAttribute("aria-activedescendant"), r.removeAttribute("aria-haspopup"), r.removeAttribute("role")));
|
|
545
545
|
}
|
|
546
|
-
function
|
|
547
|
-
if (
|
|
548
|
-
if (
|
|
549
|
-
|
|
546
|
+
function x() {
|
|
547
|
+
if (r) {
|
|
548
|
+
if (i.value.length === 0) {
|
|
549
|
+
r.removeAttribute("aria-activedescendant");
|
|
550
550
|
return;
|
|
551
551
|
}
|
|
552
|
-
|
|
552
|
+
r.setAttribute("aria-activedescendant", `${c}-opt-${o.value}`);
|
|
553
553
|
}
|
|
554
554
|
}
|
|
555
555
|
function S(e) {
|
|
556
556
|
s?.(e);
|
|
557
557
|
}
|
|
558
558
|
return {
|
|
559
|
-
onStart: (
|
|
560
|
-
|
|
561
|
-
let
|
|
562
|
-
|
|
563
|
-
return
|
|
564
|
-
items:
|
|
559
|
+
onStart: (u) => {
|
|
560
|
+
i.value = u.items, o.value = 0, s = (e) => u.command(e), n = document.createElement("div"), n.setAttribute("data-testid", "merge-tag-suggestion-popup");
|
|
561
|
+
let d = u.editor.view?.dom;
|
|
562
|
+
r = d ?? null, y(n, d ?? null), document.body.appendChild(n), e = _({ render() {
|
|
563
|
+
return a(ie, {
|
|
564
|
+
items: i.value,
|
|
565
565
|
selectedIndex: o.value,
|
|
566
|
-
emptyText:
|
|
566
|
+
emptyText: t,
|
|
567
567
|
listId: c,
|
|
568
568
|
onSelect: (e) => S(e),
|
|
569
569
|
onHover: (e) => {
|
|
570
|
-
o.value = e,
|
|
570
|
+
o.value = e, x();
|
|
571
571
|
}
|
|
572
572
|
});
|
|
573
|
-
} }),
|
|
573
|
+
} }), e.mount(n), b(!0), x(), l = u.clientRect ?? null, f(), m(d ?? null);
|
|
574
574
|
},
|
|
575
575
|
onUpdate: (e) => {
|
|
576
|
-
|
|
576
|
+
i.value = e.items, o.value >= e.items.length && (o.value = 0), s = (t) => e.command(t), x(), l = e.clientRect ?? null, f();
|
|
577
577
|
},
|
|
578
578
|
onKeyDown: (e) => {
|
|
579
579
|
if (e.event.key === "Escape") return !0;
|
|
580
|
-
let t = $(e.event,
|
|
581
|
-
return t &&
|
|
580
|
+
let t = $(e.event, i.value, o, S);
|
|
581
|
+
return t && x(), t;
|
|
582
582
|
},
|
|
583
583
|
onExit: () => {
|
|
584
|
-
h(),
|
|
584
|
+
h(), b(!1), e?.unmount(), n?.remove(), e = null, n = null, r = null, s = null, l = null;
|
|
585
585
|
}
|
|
586
586
|
};
|
|
587
587
|
}
|
|
588
588
|
};
|
|
589
589
|
return [N({
|
|
590
590
|
editor: this.editor,
|
|
591
|
-
...
|
|
591
|
+
...n
|
|
592
592
|
})];
|
|
593
593
|
}
|
|
594
594
|
});
|
|
595
595
|
//#endregion
|
|
596
596
|
export { I as FontSize, L as LetterSpacing, R as LineHeight, H as LogicMergeTagNode, K as MergeTagNode, oe as MergeTagSuggestion, Q as filterMergeTags, $ as handleSuggestionKeyDown };
|
|
597
597
|
|
|
598
|
-
//# sourceMappingURL=extensions-
|
|
598
|
+
//# sourceMappingURL=extensions-BVKQw_sp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extensions-BVKQw_sp.js","names":["$emit"],"sources":["../../../src/extensions/FontSize.ts","../../../src/extensions/LetterSpacing.ts","../../../src/extensions/LineHeight.ts","../../../src/extensions/LogicMergeTagNodeView.vue","../../../src/extensions/LogicMergeTagNodeView.vue","../../../src/extensions/isNodeSelected.ts","../../../src/extensions/renderVueNodeView.ts","../../../src/extensions/LogicMergeTagNode.ts","../../../src/extensions/MergeTagNodeView.vue","../../../src/extensions/MergeTagNodeView.vue","../../../src/extensions/MergeTagNode.ts","../../../src/components/MergeTagSuggestionList.vue","../../../src/components/MergeTagSuggestionList.vue","../../../src/extensions/MergeTagSuggestion.ts"],"sourcesContent":["import { Extension } from \"@tiptap/core\";\n\nexport interface FontSizeOptions {\n types: string[];\n}\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n fontSize: {\n setFontSize: (size: string) => ReturnType;\n unsetFontSize: () => ReturnType;\n };\n }\n}\n\nexport const FontSize = Extension.create<FontSizeOptions>({\n name: \"fontSize\",\n\n addOptions() {\n return {\n types: [\"textStyle\"],\n };\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n fontSize: {\n default: null,\n parseHTML: (element) =>\n element.style.fontSize?.replace(/['\"]+/g, \"\") || null,\n renderHTML: (attributes) => {\n if (!attributes.fontSize) {\n return {};\n }\n return {\n style: `font-size: ${attributes.fontSize}`,\n };\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setFontSize:\n (size: string) =>\n ({ chain }) => {\n return chain().setMark(\"textStyle\", { fontSize: size }).run();\n },\n unsetFontSize:\n () =>\n ({ chain }) => {\n return chain()\n .setMark(\"textStyle\", { fontSize: null })\n .removeEmptyTextStyle()\n .run();\n },\n };\n },\n});\n","import { Extension } from \"@tiptap/core\";\n\nexport interface LetterSpacingOptions {\n types: string[];\n}\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n letterSpacing: {\n setLetterSpacing: (spacing: string) => ReturnType;\n unsetLetterSpacing: () => ReturnType;\n };\n }\n}\n\nexport const LetterSpacing = Extension.create<LetterSpacingOptions>({\n name: \"letterSpacing\",\n\n addOptions() {\n return {\n types: [\"textStyle\"],\n };\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n letterSpacing: {\n default: null,\n parseHTML: (element) =>\n element.style.letterSpacing?.replace(/['\"]+/g, \"\") || null,\n renderHTML: (attributes) => {\n if (!attributes.letterSpacing) {\n return {};\n }\n return {\n style: `letter-spacing: ${attributes.letterSpacing}`,\n };\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setLetterSpacing:\n (spacing: string) =>\n ({ chain }) => {\n return chain().setMark(\"textStyle\", { letterSpacing: spacing }).run();\n },\n unsetLetterSpacing:\n () =>\n ({ chain }) => {\n return chain()\n .setMark(\"textStyle\", { letterSpacing: null })\n .removeEmptyTextStyle()\n .run();\n },\n };\n },\n});\n","import { Extension } from \"@tiptap/core\";\n\nexport interface LineHeightOptions {\n types: string[];\n defaultLineHeight: string;\n}\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n lineHeight: {\n setLineHeight: (lineHeight: string) => ReturnType;\n unsetLineHeight: () => ReturnType;\n };\n }\n}\n\nexport const LineHeight = Extension.create<LineHeightOptions>({\n name: \"lineHeight\",\n\n addOptions() {\n return {\n types: [\"paragraph\"],\n defaultLineHeight: \"1.5\",\n };\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n lineHeight: {\n default: null,\n parseHTML: (element) => element.style.lineHeight || null,\n renderHTML: (attributes) => {\n if (!attributes.lineHeight) {\n return {};\n }\n return {\n style: `line-height: ${attributes.lineHeight}`,\n };\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setLineHeight:\n (lineHeight: string) =>\n ({ commands }) => {\n return this.options.types.every((type) =>\n commands.updateAttributes(type, { lineHeight }),\n );\n },\n unsetLineHeight:\n () =>\n ({ commands }) => {\n return this.options.types.every((type) =>\n commands.resetAttributes(type, \"lineHeight\"),\n );\n },\n };\n },\n});\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../composables/useI18n\";\nimport { useMergeTag } from \"../composables/useMergeTag\";\nimport {\n getLogicMergeTagKeyword,\n isLogicMergeTagValue,\n} from \"@aswin.dev/types\";\nimport type { Editor } from \"@tiptap/core\";\nimport { NodeViewWrapper } from \"@tiptap/vue-3\";\nimport { computed, nextTick, ref } from \"vue\";\n\nconst props = defineProps<{\n node: {\n attrs: {\n value: string;\n keyword: string;\n };\n };\n editor: Editor;\n getPos: () => number;\n deleteNode: () => void;\n updateAttributes: (attrs: Record<string, unknown>) => void;\n}>();\n\nconst { syntax } = useMergeTag();\nconst { t } = useI18n();\n\nconst isValid = computed(() =>\n isLogicMergeTagValue(props.node.attrs.value, syntax),\n);\nconst displayKeyword = computed(() =>\n getLogicMergeTagKeyword(props.node.attrs.value, syntax),\n);\n\nconst isEditing = ref(false);\nconst editValue = ref(\"\");\nconst inputRef = ref<HTMLInputElement | null>(null);\nlet handled = false;\n\nfunction startEditing(): void {\n editValue.value = props.node.attrs.value;\n handled = false;\n isEditing.value = true;\n nextTick(() => {\n inputRef.value?.focus();\n inputRef.value?.select();\n });\n}\n\nfunction finishEditing(): void {\n if (handled) {\n return;\n }\n handled = true;\n\n const newValue = editValue.value.trim();\n if (!newValue) {\n isEditing.value = false;\n return;\n }\n\n if (newValue !== props.node.attrs.value) {\n props.updateAttributes({\n value: newValue,\n keyword: isLogicMergeTagValue(newValue, syntax)\n ? getLogicMergeTagKeyword(newValue, syntax)\n : \"\",\n });\n }\n isEditing.value = false;\n}\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key === \"Enter\") {\n event.preventDefault();\n finishEditing();\n } else if (event.key === \"Escape\") {\n isEditing.value = false;\n }\n}\n</script>\n\n<template>\n <NodeViewWrapper\n as=\"span\"\n :class=\"\n isValid\n ? 'tpl-logic-merge-tag-node tpl:group tpl:mx-0.5 tpl:inline-flex tpl:items-center tpl:gap-1 tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.8em] tpl:font-bold tpl:tracking-wide tpl:uppercase tpl:select-none'\n : ''\n \"\n :style=\"\n isValid\n ? 'background-color: transparent; border: 1.5px solid color-mix(in srgb, var(--tpl-primary) 50%, transparent); color: var(--tpl-primary);'\n : ''\n \"\n contenteditable=\"false\"\n >\n <!-- Edit mode -->\n <input\n v-if=\"isEditing\"\n ref=\"inputRef\"\n v-model=\"editValue\"\n type=\"text\"\n class=\"tpl:w-40 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-0.5 tpl:py-0 tpl:text-[1em] tpl:font-medium tpl:normal-case tpl:outline-none tpl:text-[var(--tpl-primary)]\"\n @blur=\"finishEditing\"\n @keydown=\"handleKeydown\"\n />\n <!-- Display mode: valid merge tag -->\n <span\n v-else-if=\"isValid\"\n role=\"button\"\n tabindex=\"0\"\n :aria-label=\"t.mergeTag.editValue\"\n class=\"tpl-tooltip tpl:cursor-pointer\"\n :data-tooltip=\"node.attrs.value\"\n @click.stop=\"startEditing\"\n @keydown.enter.stop=\"startEditing\"\n @keydown.space.prevent.stop=\"startEditing\"\n >\n {{ displayKeyword }}\n </span>\n <!-- Display mode: invalid (plain text) -->\n <span\n v-else\n role=\"button\"\n tabindex=\"0\"\n :aria-label=\"t.mergeTag.editValue\"\n @click.stop=\"startEditing\"\n @keydown.enter.stop=\"startEditing\"\n @keydown.space.prevent.stop=\"startEditing\"\n >\n {{ node.attrs.value }}\n </span>\n <button\n v-if=\"isValid\"\n type=\"button\"\n :aria-label=\"t.mergeTag.deleteMergeTag\"\n class=\"tpl-merge-tag-delete tpl:flex tpl:size-5 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:opacity-60 tpl:transition-all hover:tpl:opacity-100 tpl:text-[var(--tpl-primary)]\"\n contenteditable=\"false\"\n @click.stop.prevent=\"deleteNode\"\n >\n <svg\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </NodeViewWrapper>\n</template>\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../composables/useI18n\";\nimport { useMergeTag } from \"../composables/useMergeTag\";\nimport {\n getLogicMergeTagKeyword,\n isLogicMergeTagValue,\n} from \"@aswin.dev/types\";\nimport type { Editor } from \"@tiptap/core\";\nimport { NodeViewWrapper } from \"@tiptap/vue-3\";\nimport { computed, nextTick, ref } from \"vue\";\n\nconst props = defineProps<{\n node: {\n attrs: {\n value: string;\n keyword: string;\n };\n };\n editor: Editor;\n getPos: () => number;\n deleteNode: () => void;\n updateAttributes: (attrs: Record<string, unknown>) => void;\n}>();\n\nconst { syntax } = useMergeTag();\nconst { t } = useI18n();\n\nconst isValid = computed(() =>\n isLogicMergeTagValue(props.node.attrs.value, syntax),\n);\nconst displayKeyword = computed(() =>\n getLogicMergeTagKeyword(props.node.attrs.value, syntax),\n);\n\nconst isEditing = ref(false);\nconst editValue = ref(\"\");\nconst inputRef = ref<HTMLInputElement | null>(null);\nlet handled = false;\n\nfunction startEditing(): void {\n editValue.value = props.node.attrs.value;\n handled = false;\n isEditing.value = true;\n nextTick(() => {\n inputRef.value?.focus();\n inputRef.value?.select();\n });\n}\n\nfunction finishEditing(): void {\n if (handled) {\n return;\n }\n handled = true;\n\n const newValue = editValue.value.trim();\n if (!newValue) {\n isEditing.value = false;\n return;\n }\n\n if (newValue !== props.node.attrs.value) {\n props.updateAttributes({\n value: newValue,\n keyword: isLogicMergeTagValue(newValue, syntax)\n ? getLogicMergeTagKeyword(newValue, syntax)\n : \"\",\n });\n }\n isEditing.value = false;\n}\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key === \"Enter\") {\n event.preventDefault();\n finishEditing();\n } else if (event.key === \"Escape\") {\n isEditing.value = false;\n }\n}\n</script>\n\n<template>\n <NodeViewWrapper\n as=\"span\"\n :class=\"\n isValid\n ? 'tpl-logic-merge-tag-node tpl:group tpl:mx-0.5 tpl:inline-flex tpl:items-center tpl:gap-1 tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.8em] tpl:font-bold tpl:tracking-wide tpl:uppercase tpl:select-none'\n : ''\n \"\n :style=\"\n isValid\n ? 'background-color: transparent; border: 1.5px solid color-mix(in srgb, var(--tpl-primary) 50%, transparent); color: var(--tpl-primary);'\n : ''\n \"\n contenteditable=\"false\"\n >\n <!-- Edit mode -->\n <input\n v-if=\"isEditing\"\n ref=\"inputRef\"\n v-model=\"editValue\"\n type=\"text\"\n class=\"tpl:w-40 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-0.5 tpl:py-0 tpl:text-[1em] tpl:font-medium tpl:normal-case tpl:outline-none tpl:text-[var(--tpl-primary)]\"\n @blur=\"finishEditing\"\n @keydown=\"handleKeydown\"\n />\n <!-- Display mode: valid merge tag -->\n <span\n v-else-if=\"isValid\"\n role=\"button\"\n tabindex=\"0\"\n :aria-label=\"t.mergeTag.editValue\"\n class=\"tpl-tooltip tpl:cursor-pointer\"\n :data-tooltip=\"node.attrs.value\"\n @click.stop=\"startEditing\"\n @keydown.enter.stop=\"startEditing\"\n @keydown.space.prevent.stop=\"startEditing\"\n >\n {{ displayKeyword }}\n </span>\n <!-- Display mode: invalid (plain text) -->\n <span\n v-else\n role=\"button\"\n tabindex=\"0\"\n :aria-label=\"t.mergeTag.editValue\"\n @click.stop=\"startEditing\"\n @keydown.enter.stop=\"startEditing\"\n @keydown.space.prevent.stop=\"startEditing\"\n >\n {{ node.attrs.value }}\n </span>\n <button\n v-if=\"isValid\"\n type=\"button\"\n :aria-label=\"t.mergeTag.deleteMergeTag\"\n class=\"tpl-merge-tag-delete tpl:flex tpl:size-5 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:opacity-60 tpl:transition-all hover:tpl:opacity-100 tpl:text-[var(--tpl-primary)]\"\n contenteditable=\"false\"\n @click.stop.prevent=\"deleteNode\"\n >\n <svg\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </NodeViewWrapper>\n</template>\n","import type { Editor } from \"@tiptap/core\";\n\n/**\n * Checks whether a TipTap node of the given type is selected, or if the cursor\n * is immediately adjacent to one (for Backspace/Delete handling).\n *\n * Shared by MergeTagNode and LogicMergeTagNode keyboard shortcuts.\n */\nexport function isNodeSelected(editor: Editor, nodeTypeName: string): boolean {\n const { selection } = editor.state;\n const { $from, $to } = selection;\n\n // Check if selection contains a node of this type\n let found = false;\n editor.state.doc.nodesBetween($from.pos, $to.pos, (node) => {\n if (node.type.name === nodeTypeName) {\n found = true;\n return false;\n }\n });\n\n if (found) {\n return true;\n }\n\n // Check if cursor is right after the node (for Backspace)\n if ($from.pos > 0 && $from.nodeBefore?.type.name === nodeTypeName) {\n return true;\n }\n\n // Check if cursor is right before the node (for Delete)\n if ($from.nodeAfter?.type.name === nodeTypeName) {\n return true;\n }\n\n return false;\n}\n","import type { Component } from \"vue\";\nimport { VueNodeViewRenderer } from \"@tiptap/vue-3\";\n\n/**\n * Typed wrapper for VueNodeViewRenderer that handles the known type mismatch\n * between Vue SFC default exports and TipTap's expected component type.\n */\nexport function renderVueNodeView(component: Component) {\n return VueNodeViewRenderer(\n component as Parameters<typeof VueNodeViewRenderer>[0],\n );\n}\n","import LogicMergeTagNodeView from \"./LogicMergeTagNodeView.vue\";\nimport type { SyntaxPreset } from \"@aswin.dev/types\";\nimport {\n getLogicMergeTagKeyword,\n isLogicMergeTagValue,\n SYNTAX_PRESETS,\n} from \"@aswin.dev/types\";\nimport { InputRule, mergeAttributes, Node, PasteRule } from \"@tiptap/core\";\nimport { isNodeSelected } from \"./isNodeSelected\";\nimport { renderVueNodeView } from \"./renderVueNodeView\";\n\nexport interface LogicMergeTagNodeOptions {\n syntax: SyntaxPreset;\n}\n\nexport const LogicMergeTagNode = Node.create<LogicMergeTagNodeOptions>({\n name: \"logicMergeTagNode\",\n\n group: \"inline\",\n\n inline: true,\n\n atom: true,\n\n addOptions() {\n return {\n syntax: SYNTAX_PRESETS.liquid,\n };\n },\n\n addAttributes() {\n return {\n value: {\n default: \"\",\n parseHTML: (element) =>\n element.getAttribute(\"data-logic-merge-tag\") || \"\",\n },\n keyword: {\n default: \"\",\n parseHTML: (element) =>\n element.getAttribute(\"data-keyword\") || element.textContent || \"\",\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"span[data-logic-merge-tag]\",\n },\n ];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n if (!isLogicMergeTagValue(node.attrs.value, this.options.syntax)) {\n return [\"span\", {}, node.attrs.value];\n }\n\n const keyword = getLogicMergeTagKeyword(\n node.attrs.value,\n this.options.syntax,\n );\n\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n \"data-logic-merge-tag\": node.attrs.value,\n \"data-keyword\": keyword,\n }),\n keyword,\n ];\n },\n\n addNodeView() {\n return renderVueNodeView(LogicMergeTagNodeView);\n },\n\n addKeyboardShortcuts() {\n return {\n Backspace: () => isNodeSelected(this.editor, this.name),\n Delete: () => isNodeSelected(this.editor, this.name),\n };\n },\n\n addInputRules() {\n const inputRegex = new RegExp(this.options.syntax.logic.source + \"$\", \"\");\n\n return [\n new InputRule({\n find: inputRegex,\n handler: ({ state, range, match }) => {\n const fullValue = match[0];\n if (!isLogicMergeTagValue(fullValue, this.options.syntax)) {\n return;\n }\n\n const keyword = getLogicMergeTagKeyword(\n fullValue,\n this.options.syntax,\n );\n\n const node = this.type.create({\n value: fullValue,\n keyword,\n });\n\n state.tr.replaceWith(range.from, range.to, node);\n },\n }),\n ];\n },\n\n addPasteRules() {\n const pasteRegex = new RegExp(this.options.syntax.logic.source, \"g\");\n\n return [\n new PasteRule({\n find: pasteRegex,\n handler: ({ state, range, match }) => {\n const fullValue = match[0];\n if (!isLogicMergeTagValue(fullValue, this.options.syntax)) {\n return;\n }\n\n const keyword = getLogicMergeTagKeyword(\n fullValue,\n this.options.syntax,\n );\n\n const node = this.type.create({\n value: fullValue,\n keyword,\n });\n\n state.tr.replaceWith(range.from, range.to, node);\n },\n }),\n ];\n },\n});\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../composables/useI18n\";\nimport { useMergeTag } from \"../composables/useMergeTag\";\nimport { NodeViewWrapper } from \"@tiptap/vue-3\";\nimport { computed, nextTick, ref } from \"vue\";\n\nconst props = defineProps<{\n node: {\n attrs: {\n label: string;\n value: string;\n };\n };\n deleteNode: () => void;\n updateAttributes: (attrs: Record<string, unknown>) => void;\n}>();\n\nconst { getMergeTagLabel } = useMergeTag();\nconst { t } = useI18n();\n\nconst displayLabel = computed(() => getMergeTagLabel(props.node.attrs.value));\n\nconst isEditing = ref(false);\nconst editValue = ref(\"\");\nconst inputRef = ref<HTMLInputElement | null>(null);\n\nfunction startEditing(): void {\n editValue.value = props.node.attrs.value;\n isEditing.value = true;\n nextTick(() => {\n inputRef.value?.focus();\n inputRef.value?.select();\n });\n}\n\nfunction finishEditing(): void {\n const newValue = editValue.value.trim();\n if (newValue && newValue !== props.node.attrs.value) {\n // Update with new value and derive label from it\n props.updateAttributes({\n value: newValue,\n label: getMergeTagLabel(newValue),\n });\n }\n isEditing.value = false;\n}\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key === \"Enter\") {\n event.preventDefault();\n finishEditing();\n } else if (event.key === \"Escape\") {\n isEditing.value = false;\n }\n}\n</script>\n\n<template>\n <NodeViewWrapper\n as=\"span\"\n class=\"tpl-merge-tag-node tpl:group tpl:mx-0.5 tpl:inline-flex tpl:items-center tpl:gap-1 tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.9em] tpl:font-medium tpl:select-none tpl:text-[var(--tpl-primary)]\"\n style=\"\n background-color: color-mix(in srgb, var(--tpl-primary) 20%, transparent);\n \"\n contenteditable=\"false\"\n >\n <!-- Edit mode -->\n <input\n v-if=\"isEditing\"\n ref=\"inputRef\"\n v-model=\"editValue\"\n type=\"text\"\n class=\"tpl:w-32 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-0.5 tpl:py-0 tpl:text-[1em] tpl:font-medium tpl:outline-none tpl:text-[var(--tpl-primary)]\"\n @blur=\"finishEditing\"\n @keydown=\"handleKeydown\"\n />\n <!-- Display mode -->\n <span\n v-else\n role=\"button\"\n tabindex=\"0\"\n :aria-label=\"t.mergeTag.editValue\"\n class=\"tpl-tooltip tpl:cursor-pointer\"\n :data-tooltip=\"node.attrs.value\"\n @click.stop=\"startEditing\"\n @keydown.enter.stop=\"startEditing\"\n @keydown.space.prevent.stop=\"startEditing\"\n >\n {{ displayLabel }}\n </span>\n <button\n type=\"button\"\n :aria-label=\"t.mergeTag.deleteMergeTag\"\n class=\"tpl-merge-tag-delete tpl:flex tpl:size-5 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:opacity-60 tpl:transition-all hover:tpl:opacity-100 tpl:text-[var(--tpl-primary)]\"\n contenteditable=\"false\"\n @click.stop.prevent=\"deleteNode\"\n >\n <svg\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </NodeViewWrapper>\n</template>\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../composables/useI18n\";\nimport { useMergeTag } from \"../composables/useMergeTag\";\nimport { NodeViewWrapper } from \"@tiptap/vue-3\";\nimport { computed, nextTick, ref } from \"vue\";\n\nconst props = defineProps<{\n node: {\n attrs: {\n label: string;\n value: string;\n };\n };\n deleteNode: () => void;\n updateAttributes: (attrs: Record<string, unknown>) => void;\n}>();\n\nconst { getMergeTagLabel } = useMergeTag();\nconst { t } = useI18n();\n\nconst displayLabel = computed(() => getMergeTagLabel(props.node.attrs.value));\n\nconst isEditing = ref(false);\nconst editValue = ref(\"\");\nconst inputRef = ref<HTMLInputElement | null>(null);\n\nfunction startEditing(): void {\n editValue.value = props.node.attrs.value;\n isEditing.value = true;\n nextTick(() => {\n inputRef.value?.focus();\n inputRef.value?.select();\n });\n}\n\nfunction finishEditing(): void {\n const newValue = editValue.value.trim();\n if (newValue && newValue !== props.node.attrs.value) {\n // Update with new value and derive label from it\n props.updateAttributes({\n value: newValue,\n label: getMergeTagLabel(newValue),\n });\n }\n isEditing.value = false;\n}\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key === \"Enter\") {\n event.preventDefault();\n finishEditing();\n } else if (event.key === \"Escape\") {\n isEditing.value = false;\n }\n}\n</script>\n\n<template>\n <NodeViewWrapper\n as=\"span\"\n class=\"tpl-merge-tag-node tpl:group tpl:mx-0.5 tpl:inline-flex tpl:items-center tpl:gap-1 tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.9em] tpl:font-medium tpl:select-none tpl:text-[var(--tpl-primary)]\"\n style=\"\n background-color: color-mix(in srgb, var(--tpl-primary) 20%, transparent);\n \"\n contenteditable=\"false\"\n >\n <!-- Edit mode -->\n <input\n v-if=\"isEditing\"\n ref=\"inputRef\"\n v-model=\"editValue\"\n type=\"text\"\n class=\"tpl:w-32 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-0.5 tpl:py-0 tpl:text-[1em] tpl:font-medium tpl:outline-none tpl:text-[var(--tpl-primary)]\"\n @blur=\"finishEditing\"\n @keydown=\"handleKeydown\"\n />\n <!-- Display mode -->\n <span\n v-else\n role=\"button\"\n tabindex=\"0\"\n :aria-label=\"t.mergeTag.editValue\"\n class=\"tpl-tooltip tpl:cursor-pointer\"\n :data-tooltip=\"node.attrs.value\"\n @click.stop=\"startEditing\"\n @keydown.enter.stop=\"startEditing\"\n @keydown.space.prevent.stop=\"startEditing\"\n >\n {{ displayLabel }}\n </span>\n <button\n type=\"button\"\n :aria-label=\"t.mergeTag.deleteMergeTag\"\n class=\"tpl-merge-tag-delete tpl:flex tpl:size-5 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:opacity-60 tpl:transition-all hover:tpl:opacity-100 tpl:text-[var(--tpl-primary)]\"\n contenteditable=\"false\"\n @click.stop.prevent=\"deleteNode\"\n >\n <svg\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </NodeViewWrapper>\n</template>\n","import MergeTagNodeView from \"./MergeTagNodeView.vue\";\nimport type { MergeTag, SyntaxPreset } from \"@aswin.dev/types\";\nimport { getMergeTagLabel, SYNTAX_PRESETS } from \"@aswin.dev/types\";\nimport { InputRule, mergeAttributes, Node, PasteRule } from \"@tiptap/core\";\nimport { isNodeSelected } from \"./isNodeSelected\";\nimport { renderVueNodeView } from \"./renderVueNodeView\";\n\nexport interface MergeTagNodeOptions {\n mergeTags: MergeTag[];\n syntax: SyntaxPreset;\n}\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n mergeTagNode: {\n insertMergeTag: (attrs: MergeTag) => ReturnType;\n };\n }\n}\n\nexport const MergeTagNode = Node.create<MergeTagNodeOptions>({\n name: \"mergeTagNode\",\n\n group: \"inline\",\n\n inline: true,\n\n atom: true,\n\n addOptions() {\n return {\n mergeTags: [],\n syntax: SYNTAX_PRESETS.liquid,\n };\n },\n\n addAttributes() {\n return {\n label: {\n default: \"\",\n parseHTML: (element) =>\n element.getAttribute(\"data-label\") || element.textContent || \"\",\n },\n value: {\n default: \"\",\n parseHTML: (element) => element.getAttribute(\"data-merge-tag\") || \"\",\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"span[data-merge-tag]\",\n },\n ];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const label = getMergeTagLabel(node.attrs.value, this.options.mergeTags);\n\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n \"data-merge-tag\": node.attrs.value,\n \"data-label\": label,\n }),\n label,\n ];\n },\n\n addNodeView() {\n return renderVueNodeView(MergeTagNodeView);\n },\n\n addCommands() {\n return {\n insertMergeTag:\n (attrs: MergeTag) =>\n ({ commands }) => {\n return commands.insertContent({\n type: this.name,\n attrs,\n });\n },\n };\n },\n\n addKeyboardShortcuts() {\n return {\n Backspace: () => isNodeSelected(this.editor, this.name),\n Delete: () => isNodeSelected(this.editor, this.name),\n };\n },\n\n addInputRules() {\n const inputRegex = new RegExp(this.options.syntax.value.source + \"$\", \"\");\n\n return [\n new InputRule({\n find: inputRegex,\n handler: ({ state, range, match }) => {\n const fullValue = match[0];\n const label = getMergeTagLabel(fullValue, this.options.mergeTags);\n\n const node = this.type.create({\n label,\n value: fullValue,\n });\n\n state.tr.replaceWith(range.from, range.to, node);\n },\n }),\n ];\n },\n\n addPasteRules() {\n const pasteRegex = new RegExp(this.options.syntax.value.source, \"g\");\n\n return [\n new PasteRule({\n find: pasteRegex,\n handler: ({ state, range, match }) => {\n const fullValue = match[0];\n const label = getMergeTagLabel(fullValue, this.options.mergeTags);\n\n const node = this.type.create({\n label,\n value: fullValue,\n });\n\n state.tr.replaceWith(range.from, range.to, node);\n },\n }),\n ];\n },\n});\n","<script setup lang=\"ts\">\nimport type { MergeTag } from \"@aswin.dev/types\";\n\nconst props = defineProps<{\n items: MergeTag[];\n selectedIndex: number;\n emptyText: string;\n /** Stable id used for aria-controls + per-option id derivation. */\n listId?: string;\n}>();\n\ndefineEmits<{\n (e: \"select\", item: MergeTag): void;\n (e: \"hover\", index: number): void;\n}>();\n\nfunction optionId(index: number): string | undefined {\n return props.listId ? `${props.listId}-opt-${index}` : undefined;\n}\n</script>\n\n<template>\n <div\n :id=\"listId\"\n class=\"tpl:min-w-[200px] tpl:max-w-[320px] tpl:max-h-[50vh] tpl:overflow-y-auto tpl:rounded-[var(--tpl-radius)] tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)] tpl:py-1 tpl:shadow-lg\"\n role=\"listbox\"\n data-testid=\"merge-tag-suggestion-list\"\n >\n <div\n v-if=\"items.length === 0\"\n class=\"tpl:px-3 tpl:py-2 tpl:text-xs tpl:text-[var(--tpl-text-dim)]\"\n data-testid=\"merge-tag-suggestion-empty\"\n >\n {{ emptyText }}\n </div>\n <button\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n :id=\"optionId(index)\"\n type=\"button\"\n role=\"option\"\n :aria-selected=\"index === selectedIndex\"\n :data-selected=\"index === selectedIndex ? 'true' : 'false'\"\n :data-merge-tag-value=\"item.value\"\n class=\"tpl:flex tpl:w-full tpl:flex-col tpl:items-start tpl:gap-0.5 tpl:px-3 tpl:py-1.5 tpl:text-left tpl:text-xs tpl:transition-colors\"\n :class=\"\n index === selectedIndex\n ? 'tpl:bg-[var(--tpl-primary-light)] tpl:text-[var(--tpl-primary)]'\n : 'tpl:text-[var(--tpl-text)] hover:tpl:bg-[var(--tpl-bg-hover)]'\n \"\n @mousedown.prevent.stop=\"$emit('select', item)\"\n @mousemove=\"index !== selectedIndex && $emit('hover', index)\"\n >\n <span class=\"tpl:font-medium\">{{ item.label }}</span>\n <span class=\"tpl:text-[var(--tpl-text-dim)] tpl:font-mono\">{{\n item.value\n }}</span>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport type { MergeTag } from \"@aswin.dev/types\";\n\nconst props = defineProps<{\n items: MergeTag[];\n selectedIndex: number;\n emptyText: string;\n /** Stable id used for aria-controls + per-option id derivation. */\n listId?: string;\n}>();\n\ndefineEmits<{\n (e: \"select\", item: MergeTag): void;\n (e: \"hover\", index: number): void;\n}>();\n\nfunction optionId(index: number): string | undefined {\n return props.listId ? `${props.listId}-opt-${index}` : undefined;\n}\n</script>\n\n<template>\n <div\n :id=\"listId\"\n class=\"tpl:min-w-[200px] tpl:max-w-[320px] tpl:max-h-[50vh] tpl:overflow-y-auto tpl:rounded-[var(--tpl-radius)] tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)] tpl:py-1 tpl:shadow-lg\"\n role=\"listbox\"\n data-testid=\"merge-tag-suggestion-list\"\n >\n <div\n v-if=\"items.length === 0\"\n class=\"tpl:px-3 tpl:py-2 tpl:text-xs tpl:text-[var(--tpl-text-dim)]\"\n data-testid=\"merge-tag-suggestion-empty\"\n >\n {{ emptyText }}\n </div>\n <button\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n :id=\"optionId(index)\"\n type=\"button\"\n role=\"option\"\n :aria-selected=\"index === selectedIndex\"\n :data-selected=\"index === selectedIndex ? 'true' : 'false'\"\n :data-merge-tag-value=\"item.value\"\n class=\"tpl:flex tpl:w-full tpl:flex-col tpl:items-start tpl:gap-0.5 tpl:px-3 tpl:py-1.5 tpl:text-left tpl:text-xs tpl:transition-colors\"\n :class=\"\n index === selectedIndex\n ? 'tpl:bg-[var(--tpl-primary-light)] tpl:text-[var(--tpl-primary)]'\n : 'tpl:text-[var(--tpl-text)] hover:tpl:bg-[var(--tpl-bg-hover)]'\n \"\n @mousedown.prevent.stop=\"$emit('select', item)\"\n @mousemove=\"index !== selectedIndex && $emit('hover', index)\"\n >\n <span class=\"tpl:font-medium\">{{ item.label }}</span>\n <span class=\"tpl:text-[var(--tpl-text-dim)] tpl:font-mono\">{{\n item.value\n }}</span>\n </button>\n </div>\n</template>\n","import type { MergeTag } from \"@aswin.dev/types\";\nimport { Extension } from \"@tiptap/core\";\nimport Suggestion, {\n type SuggestionOptions,\n type SuggestionProps,\n type SuggestionKeyDownProps,\n} from \"@tiptap/suggestion\";\nimport { type App, createApp, h, ref, type Ref } from \"vue\";\nimport MergeTagSuggestionList from \"../components/MergeTagSuggestionList.vue\";\n\nconst MAX_RESULTS = 10;\n\n// Monotonic counter for unique listbox IDs across multiple popup instances.\nlet POPUP_ID_SEQ = 0;\n\nexport interface MergeTagSuggestionOptions {\n /** Available merge tags */\n mergeTags: MergeTag[];\n /** Trigger string (e.g. \"{{\", \"*|\", \"%%=\") */\n char: string;\n /** Localized empty-state label */\n emptyText: string;\n}\n\n/**\n * Filter merge tags by query against label and value (case-insensitive).\n * Capped at MAX_RESULTS. Exported for testing.\n */\nexport function filterMergeTags(tags: MergeTag[], query: string): MergeTag[] {\n const trimmed = query.trim().toLowerCase();\n if (trimmed === \"\") {\n return tags.slice(0, MAX_RESULTS);\n }\n return tags\n .filter((tag) => {\n const label = tag.label.toLowerCase();\n const value = tag.value.toLowerCase();\n return label.includes(trimmed) || value.includes(trimmed);\n })\n .slice(0, MAX_RESULTS);\n}\n\n/**\n * Handle a keydown event against a list of items. Returns whether the\n * event was handled (so the suggestion plugin can stop propagation).\n * Exported for testing.\n */\nexport function handleSuggestionKeyDown(\n event: KeyboardEvent,\n items: MergeTag[],\n selectedIndex: Ref<number>,\n onSelect: (item: MergeTag) => void,\n): boolean {\n if (items.length === 0) {\n if (event.key === \"Enter\" || event.key === \"Tab\") return true;\n return false;\n }\n\n if (event.key === \"ArrowDown\") {\n selectedIndex.value = (selectedIndex.value + 1) % items.length;\n return true;\n }\n if (event.key === \"ArrowUp\") {\n selectedIndex.value =\n (selectedIndex.value - 1 + items.length) % items.length;\n return true;\n }\n if (event.key === \"Enter\" || event.key === \"Tab\") {\n onSelect(items[selectedIndex.value]);\n return true;\n }\n return false;\n}\n\nexport const MergeTagSuggestion = Extension.create<MergeTagSuggestionOptions>({\n name: \"mergeTagSuggestion\",\n\n addOptions() {\n return {\n mergeTags: [],\n char: \"{{\",\n emptyText: \"No matching merge tags\",\n };\n },\n\n addProseMirrorPlugins() {\n const tags = this.options.mergeTags;\n const emptyText = this.options.emptyText;\n\n const config: Omit<SuggestionOptions<MergeTag>, \"editor\"> = {\n char: this.options.char,\n allowSpaces: false,\n startOfLine: false,\n // Default is [\" \"] which requires whitespace/line-start before the\n // trigger char — so `.{{` would not fire. Allow any preceding char.\n allowedPrefixes: null,\n items: ({ query }: { query: string }) => filterMergeTags(tags, query),\n command: ({\n editor,\n range,\n props,\n }: {\n editor: SuggestionProps<MergeTag>[\"editor\"];\n range: { from: number; to: number };\n props: MergeTag;\n }) => {\n // Use insertContentAt for atomic replace (matches the canonical\n // @tiptap/suggestion + Mention pattern). Avoids edge cases where\n // chained deleteRange + insertMergeTag fails to insert when the\n // selection state shifts mid-chain.\n editor\n .chain()\n .focus()\n .insertContentAt(range, {\n type: \"mergeTagNode\",\n attrs: { label: props.label, value: props.value },\n })\n .run();\n },\n render: () => {\n let app: App | null = null;\n let container: HTMLElement | null = null;\n let editableEl: HTMLElement | null = null;\n const itemsRef = ref<MergeTag[]>([]);\n const selectedIndex = ref(0);\n let currentCommand: ((item: MergeTag) => void) | null = null;\n const listId = `tpl-merge-tag-suggestion-${++POPUP_ID_SEQ}`;\n let latestClientRect: (() => DOMRect | null) | null = null;\n let scrollTargets: Array<EventTarget> = [];\n\n function reposition(): void {\n position(latestClientRect?.() ?? null);\n }\n\n /**\n * Reposition immediately and on the next animation frame.\n * After a keystroke triggers the suggestion, TipTap may run its\n * own `scrollIntoView` to keep the caret visible. That scroll\n * lands AFTER the current task's `position()` call but BEFORE\n * the browser's next paint, so we re-measure on rAF to catch\n * the post-scroll caret rect. Without this, the popup pins to\n * the pre-scroll caret position and ends up offset on slower\n * runners.\n */\n function repositionAfterPaint(): void {\n reposition();\n requestAnimationFrame(reposition);\n }\n\n function collectScrollAncestors(el: HTMLElement | null): HTMLElement[] {\n // Walk up the DOM finding scrollable ancestors. ProseMirror's\n // scrollIntoView fires on whichever ancestor scrolls — listening\n // to all of them ensures we reposition regardless of which one\n // moves.\n const result: HTMLElement[] = [];\n let node: HTMLElement | null = el?.parentElement ?? null;\n while (\n node &&\n node !== document.body &&\n node !== document.documentElement\n ) {\n const style = window.getComputedStyle(node);\n const overflow = style.overflow + style.overflowX + style.overflowY;\n if (/(auto|scroll|overlay)/.test(overflow)) {\n result.push(node);\n }\n node = node.parentElement;\n }\n return result;\n }\n\n function attachScrollListeners(viewDom: HTMLElement | null): void {\n scrollTargets = [window, ...collectScrollAncestors(viewDom)];\n for (const target of scrollTargets) {\n target.addEventListener(\"scroll\", reposition, {\n passive: true,\n capture: true,\n });\n }\n window.addEventListener(\"resize\", reposition, { passive: true });\n }\n\n function detachScrollListeners(): void {\n for (const target of scrollTargets) {\n target.removeEventListener(\"scroll\", reposition, {\n capture: true,\n } as EventListenerOptions);\n }\n window.removeEventListener(\"resize\", reposition);\n scrollTargets = [];\n }\n\n function position(rect: DOMRect | null): void {\n if (!container || !rect) return;\n // If the caret has scrolled out of the viewport, freeze the\n // popup at its last on-screen position. Following the caret\n // off-screen produces an invisible popup the user can't reach,\n // and lets pathological scroll loops drag the popup further\n // each tick.\n if (rect.bottom < 0 || rect.top > window.innerHeight) return;\n container.style.position = \"fixed\";\n container.style.left = `${rect.left}px`;\n container.style.zIndex = \"9999\";\n // Place below caret first; offsetHeight is sync-readable after\n // the Vue app has mounted (or after onUpdate's reactive flush).\n container.style.top = `${rect.bottom}px`;\n const popupHeight = container.offsetHeight;\n if (popupHeight === 0) return;\n const spaceBelow = window.innerHeight - rect.bottom;\n if (spaceBelow < popupHeight) {\n // Not enough room below — flip above. Clamp to 0 so the\n // popup never positions off the top of the viewport.\n const flippedTop = Math.max(0, rect.top - popupHeight);\n container.style.top = `${flippedTop}px`;\n }\n }\n\n function applyThemeContext(\n target: HTMLElement,\n editorEl: HTMLElement | null | undefined,\n ): void {\n // The popup mounts to document.body so its `position: fixed`\n // resolves against the viewport — any transform/filter on a\n // consumer-page ancestor (route transitions, reveal animations,\n // dark canvas inversion) creates a containing block and moves\n // fixed descendants with it. Body ancestors don't transform.\n //\n // CSS vars (--tpl-bg-elevated, --tpl-border, etc.) are scoped to\n // `.tpl` and `.tpl[data-tpl-theme=\"dark\"]` in the editor's\n // stylesheet, so the popup wouldn't inherit them at body root.\n // Adding `class=\"tpl\"` would also pull base rules (min-height,\n // flex, full-page bg) we don't want on a popup. Instead, snapshot\n // every --tpl-* custom property from the editor's theme root and\n // re-emit them inline on the popup wrapper.\n const themeRoot = editorEl?.closest<HTMLElement>(\"[data-tpl-theme]\");\n if (!themeRoot) return;\n const themeValue = themeRoot.getAttribute(\"data-tpl-theme\");\n if (themeValue) target.setAttribute(\"data-tpl-theme\", themeValue);\n const computed = window.getComputedStyle(themeRoot);\n for (let i = 0; i < computed.length; i++) {\n const prop = computed[i];\n if (prop.startsWith(\"--tpl-\")) {\n target.style.setProperty(prop, computed.getPropertyValue(prop));\n }\n }\n // The popup no longer inherits font from the editor wrapper, so\n // its content would render in the page's default font and end up\n // at a different height — which changes the flip-above decision\n // and shifts the popup off the caret. Copy typography too.\n target.style.fontFamily = computed.fontFamily;\n target.style.fontSize = computed.fontSize;\n target.style.lineHeight = computed.lineHeight;\n }\n\n function setEditableAria(active: boolean): void {\n if (!editableEl) return;\n if (active) {\n editableEl.setAttribute(\"role\", \"combobox\");\n editableEl.setAttribute(\"aria-haspopup\", \"listbox\");\n editableEl.setAttribute(\"aria-expanded\", \"true\");\n editableEl.setAttribute(\"aria-controls\", listId);\n } else {\n editableEl.removeAttribute(\"aria-expanded\");\n editableEl.removeAttribute(\"aria-controls\");\n editableEl.removeAttribute(\"aria-activedescendant\");\n editableEl.removeAttribute(\"aria-haspopup\");\n editableEl.removeAttribute(\"role\");\n }\n }\n\n function setActiveDescendant(): void {\n if (!editableEl) return;\n if (itemsRef.value.length === 0) {\n editableEl.removeAttribute(\"aria-activedescendant\");\n return;\n }\n editableEl.setAttribute(\n \"aria-activedescendant\",\n `${listId}-opt-${selectedIndex.value}`,\n );\n }\n\n function select(item: MergeTag): void {\n currentCommand?.(item);\n }\n\n return {\n onStart: (props: SuggestionProps<MergeTag>) => {\n itemsRef.value = props.items;\n selectedIndex.value = 0;\n currentCommand = (item) => props.command(item);\n\n container = document.createElement(\"div\");\n container.setAttribute(\"data-testid\", \"merge-tag-suggestion-popup\");\n // Use view.dom (ProseMirror contenteditable, actually\n // attached to the DOM) rather than options.element, which may\n // be a detached div when no `element` is passed to the editor\n // constructor (as is the case with @tiptap/vue-3 EditorContent).\n const viewDom = props.editor.view?.dom as HTMLElement | undefined;\n editableEl = viewDom ?? null;\n applyThemeContext(container, viewDom ?? null);\n document.body.appendChild(container);\n\n app = createApp({\n render() {\n return h(MergeTagSuggestionList, {\n items: itemsRef.value,\n selectedIndex: selectedIndex.value,\n emptyText,\n listId,\n onSelect: (item: MergeTag) => select(item),\n onHover: (index: number) => {\n selectedIndex.value = index;\n setActiveDescendant();\n },\n });\n },\n });\n app.mount(container);\n setEditableAria(true);\n setActiveDescendant();\n latestClientRect = props.clientRect ?? null;\n repositionAfterPaint();\n attachScrollListeners(viewDom ?? null);\n },\n onUpdate: (props: SuggestionProps<MergeTag>) => {\n itemsRef.value = props.items;\n // Reset selection when item set changes (query changed).\n if (selectedIndex.value >= props.items.length) {\n selectedIndex.value = 0;\n }\n currentCommand = (item) => props.command(item);\n setActiveDescendant();\n latestClientRect = props.clientRect ?? null;\n repositionAfterPaint();\n },\n onKeyDown: (props: SuggestionKeyDownProps): boolean => {\n if (props.event.key === \"Escape\") {\n return true;\n }\n const handled = handleSuggestionKeyDown(\n props.event,\n itemsRef.value,\n selectedIndex,\n select,\n );\n if (handled) setActiveDescendant();\n return handled;\n },\n onExit: () => {\n detachScrollListeners();\n setEditableAria(false);\n app?.unmount();\n container?.remove();\n app = null;\n container = null;\n editableEl = null;\n currentCommand = null;\n latestClientRect = null;\n },\n };\n },\n };\n\n return [\n Suggestion({\n editor: this.editor,\n ...config,\n }),\n ];\n },\n});\n"],"mappings":"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"}
|