@broberg/cms-inline-edit 0.7.2 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +30 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +29 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -183,6 +183,19 @@ declare function disconnect(options: InlineEditOptions): void;
|
|
|
183
183
|
* MPA consumers (broberg: full reload per navigation re-runs init) never need it.
|
|
184
184
|
*/
|
|
185
185
|
declare function rescanFields(): void;
|
|
186
|
+
/**
|
|
187
|
+
* A plain field's value, with its line breaks intact.
|
|
188
|
+
*
|
|
189
|
+
* `textContent` drops <br> entirely — a two-paragraph value read through it
|
|
190
|
+
* comes back as one run of text, and saving then DESTROYS the break that was
|
|
191
|
+
* already stored. So this is not only how a new break gets in; it is what stops
|
|
192
|
+
* an existing one being silently flattened the next time anyone edits the field.
|
|
193
|
+
*
|
|
194
|
+
* Deliberately narrow: <br> becomes "\n" and text nodes come through verbatim.
|
|
195
|
+
* A plain field is a string, not a document — anything richer belongs in a
|
|
196
|
+
* richtext field, which has its own serializer.
|
|
197
|
+
*/
|
|
198
|
+
declare function plainTextWithBreaks(el: HTMLElement): string;
|
|
186
199
|
interface LinkablePage {
|
|
187
200
|
collection: string;
|
|
188
201
|
slug: string;
|
|
@@ -253,4 +266,4 @@ declare function setLinkTarget(el: HTMLElement, newTab: boolean): void;
|
|
|
253
266
|
*/
|
|
254
267
|
declare function htmlToMarkdown(html: string): string;
|
|
255
268
|
|
|
256
|
-
export { type InlineEditLabels, type InlineEditOptions, applyFieldSlice, buildConnectUrl, disconnect, extractLinkTargets, getConnectedToken, htmlToMarkdown, initInlineEdit, isBareEmail, isDangerousUrl, isExternalHost, isSchemeless, positionPopover, renderCurrentRefLine, rescanFields, resolveExistingRef, setLinkTarget, withHttps };
|
|
269
|
+
export { type InlineEditLabels, type InlineEditOptions, applyFieldSlice, buildConnectUrl, disconnect, extractLinkTargets, getConnectedToken, htmlToMarkdown, initInlineEdit, isBareEmail, isDangerousUrl, isExternalHost, isSchemeless, plainTextWithBreaks, positionPopover, renderCurrentRefLine, rescanFields, resolveExistingRef, setLinkTarget, withHttps };
|
package/dist/index.d.ts
CHANGED
|
@@ -183,6 +183,19 @@ declare function disconnect(options: InlineEditOptions): void;
|
|
|
183
183
|
* MPA consumers (broberg: full reload per navigation re-runs init) never need it.
|
|
184
184
|
*/
|
|
185
185
|
declare function rescanFields(): void;
|
|
186
|
+
/**
|
|
187
|
+
* A plain field's value, with its line breaks intact.
|
|
188
|
+
*
|
|
189
|
+
* `textContent` drops <br> entirely — a two-paragraph value read through it
|
|
190
|
+
* comes back as one run of text, and saving then DESTROYS the break that was
|
|
191
|
+
* already stored. So this is not only how a new break gets in; it is what stops
|
|
192
|
+
* an existing one being silently flattened the next time anyone edits the field.
|
|
193
|
+
*
|
|
194
|
+
* Deliberately narrow: <br> becomes "\n" and text nodes come through verbatim.
|
|
195
|
+
* A plain field is a string, not a document — anything richer belongs in a
|
|
196
|
+
* richtext field, which has its own serializer.
|
|
197
|
+
*/
|
|
198
|
+
declare function plainTextWithBreaks(el: HTMLElement): string;
|
|
186
199
|
interface LinkablePage {
|
|
187
200
|
collection: string;
|
|
188
201
|
slug: string;
|
|
@@ -253,4 +266,4 @@ declare function setLinkTarget(el: HTMLElement, newTab: boolean): void;
|
|
|
253
266
|
*/
|
|
254
267
|
declare function htmlToMarkdown(html: string): string;
|
|
255
268
|
|
|
256
|
-
export { type InlineEditLabels, type InlineEditOptions, applyFieldSlice, buildConnectUrl, disconnect, extractLinkTargets, getConnectedToken, htmlToMarkdown, initInlineEdit, isBareEmail, isDangerousUrl, isExternalHost, isSchemeless, positionPopover, renderCurrentRefLine, rescanFields, resolveExistingRef, setLinkTarget, withHttps };
|
|
269
|
+
export { type InlineEditLabels, type InlineEditOptions, applyFieldSlice, buildConnectUrl, disconnect, extractLinkTargets, getConnectedToken, htmlToMarkdown, initInlineEdit, isBareEmail, isDangerousUrl, isExternalHost, isSchemeless, plainTextWithBreaks, positionPopover, renderCurrentRefLine, rescanFields, resolveExistingRef, setLinkTarget, withHttps };
|
package/dist/index.js
CHANGED
|
@@ -397,7 +397,7 @@ function wireField(el, token, options) {
|
|
|
397
397
|
e.preventDefault();
|
|
398
398
|
e.stopPropagation();
|
|
399
399
|
const tokenSafe = hasTokenChips(el);
|
|
400
|
-
el.dataset.cmsOriginalValue = tokenSafe ? serializeTokenSafe(el) : el
|
|
400
|
+
el.dataset.cmsOriginalValue = tokenSafe ? serializeTokenSafe(el) : plainTextWithBreaks(el);
|
|
401
401
|
el.setAttribute("contenteditable", "true");
|
|
402
402
|
if (tokenSafe) lockTokenChips(el);
|
|
403
403
|
el.focus();
|
|
@@ -405,7 +405,7 @@ function wireField(el, token, options) {
|
|
|
405
405
|
el.addEventListener("blur", () => {
|
|
406
406
|
el.removeAttribute("contenteditable");
|
|
407
407
|
const original = el.dataset.cmsOriginalValue ?? "";
|
|
408
|
-
const current = hasTokenChips(el) ? serializeTokenSafe(el) : el
|
|
408
|
+
const current = hasTokenChips(el) ? serializeTokenSafe(el) : plainTextWithBreaks(el);
|
|
409
409
|
if (current.trim() === original.trim()) return;
|
|
410
410
|
void saveField(el, current.trim(), token, options);
|
|
411
411
|
});
|
|
@@ -415,12 +415,35 @@ function wireField(el, token, options) {
|
|
|
415
415
|
document.execCommand("insertText", false, text);
|
|
416
416
|
});
|
|
417
417
|
el.addEventListener("keydown", (e) => {
|
|
418
|
-
if (e.key
|
|
419
|
-
|
|
420
|
-
|
|
418
|
+
if (e.key !== "Enter") return;
|
|
419
|
+
e.preventDefault();
|
|
420
|
+
if (e.shiftKey) {
|
|
421
|
+
document.execCommand("insertLineBreak");
|
|
422
|
+
return;
|
|
421
423
|
}
|
|
424
|
+
el.blur();
|
|
422
425
|
});
|
|
423
426
|
}
|
|
427
|
+
function plainTextWithBreaks(el) {
|
|
428
|
+
let out = "";
|
|
429
|
+
const walk = (node) => {
|
|
430
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
431
|
+
out += node.textContent ?? "";
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
if (node.nodeType !== Node.ELEMENT_NODE) return;
|
|
435
|
+
const tag = node.tagName.toLowerCase();
|
|
436
|
+
if (tag === "br") {
|
|
437
|
+
out += "\n";
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
const blocky = tag === "div" || tag === "p";
|
|
441
|
+
if (blocky && out !== "" && !out.endsWith("\n")) out += "\n";
|
|
442
|
+
node.childNodes.forEach(walk);
|
|
443
|
+
};
|
|
444
|
+
el.childNodes.forEach(walk);
|
|
445
|
+
return out;
|
|
446
|
+
}
|
|
424
447
|
var richCtx = null;
|
|
425
448
|
var richToolbar = null;
|
|
426
449
|
function wireRichField(el, token, options, mode) {
|
|
@@ -1532,6 +1555,7 @@ export {
|
|
|
1532
1555
|
isDangerousUrl,
|
|
1533
1556
|
isExternalHost,
|
|
1534
1557
|
isSchemeless,
|
|
1558
|
+
plainTextWithBreaks,
|
|
1535
1559
|
positionPopover,
|
|
1536
1560
|
renderCurrentRefLine,
|
|
1537
1561
|
rescanFields,
|