🚀. Socket Launch Week Day 3:Socket Firewall Now Blocks Malicious VS Code and Open VSX Extensions.Learn more
Sign In

@datocms/content-link

Package Overview
Dependencies
Maintainers
7
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@datocms/content-link - npm Package Compare versions

Comparing version
0.3.14
to
0.3.15
+1
-1
package.json
{
"name": "@datocms/content-link",
"version": "0.3.14",
"version": "0.3.15",
"description": "DatoCMS visual editing overlays without Vercel dependencies.",

@@ -5,0 +5,0 @@ "type": "module",

@@ -77,3 +77,3 @@ # DatoCMS Content Link

- `root?: ParentNode`: Limit scanning to a specific container (default: `document`)
- `stripStega?: boolean`: Whether to strip stega-encoded invisible characters from text content after stamping (default: `false`)
- `stripStega?: boolean`: Whether to strip stega-encoded invisible characters from text content after stamping (default: `false`). Stega embeds invisible, zero-width UTF-8 characters into text content to encode editing metadata.
- When `false` (default): Stega encoding remains in the DOM, allowing controllers to be disposed and recreated on the same page. The invisible characters don't affect display but preserve the source of truth.

@@ -372,2 +372,3 @@ - When `true`: Stega encoding is permanently removed from text nodes, providing clean `textContent` for programmatic access. However, recreating a controller on the same page won't detect elements since the encoding is lost.

- **Controller recreation issues**: If you dispose and recreate a controller on the same page, the second controller will only find elements if `stripStega: false` (the default). If you previously used `stripStega: true`, the stega encoding was permanently removed and cannot be recovered. In this case, you'll need to reload the page or re-fetch the content.
- **Layout issues caused by stega encoding**: The invisible zero-width characters can cause unexpected letter-spacing or text breaking out of containers. To fix this, either use `stripStega: true`, or use CSS: `[data-datocms-contains-stega] { letter-spacing: 0 !important; }`. This attribute is automatically added to elements with stega-encoded content when `stripStega: false` (the default).

@@ -374,0 +375,0 @@ ## License

@@ -18,4 +18,4 @@ /**

import {
AUTOMATIC_STAMP_ATTRIBUTE,
MANUAL_STAMP_ATTRIBUTE,
AUTOMATIC_TARGET_STAMP_ATTRIBUTE,
MANUAL_TARGET_STAMP_ATTRIBUTE,
STAMPED_ELEMENTS_SELECTOR,

@@ -220,4 +220,4 @@ } from './domStamping/constants.js';

const url =
element.getAttribute(MANUAL_STAMP_ATTRIBUTE) ||
element.getAttribute(AUTOMATIC_STAMP_ATTRIBUTE);
element.getAttribute(MANUAL_TARGET_STAMP_ATTRIBUTE) ||
element.getAttribute(AUTOMATIC_TARGET_STAMP_ATTRIBUTE);
if (url) {

@@ -224,0 +224,0 @@ editUrls.add(url);

@@ -6,5 +6,5 @@ /**

import {
AUTOMATIC_STAMP_ATTRIBUTE,
MANUAL_STAMP_ATTRIBUTE,
STAMPED_ELEMENTS_SELECTOR
AUTOMATIC_TARGET_STAMP_ATTRIBUTE,
MANUAL_TARGET_STAMP_ATTRIBUTE,
STAMPED_ELEMENTS_SELECTOR,
} from '../domStamping/constants.js';

@@ -17,3 +17,5 @@

export function findEditableTarget(from: EventTarget | Element | null): EditableTarget | null {
export function findEditableTarget(
from: EventTarget | Element | null,
): EditableTarget | null {
if (!from || !(from instanceof Element)) {

@@ -28,3 +30,5 @@ return null;

const url = el.getAttribute(MANUAL_STAMP_ATTRIBUTE) || el.getAttribute(AUTOMATIC_STAMP_ATTRIBUTE);
const url =
el.getAttribute(MANUAL_TARGET_STAMP_ATTRIBUTE) ||
el.getAttribute(AUTOMATIC_TARGET_STAMP_ATTRIBUTE);

@@ -31,0 +35,0 @@ if (!url) {

@@ -6,4 +6,6 @@ /**

*/
export const AUTOMATIC_STAMP_ATTRIBUTE = 'data-datocms-stega';
export const MANUAL_STAMP_ATTRIBUTE = 'data-datocms-content-link-url';
export const AUTOMATIC_TARGET_STAMP_ATTRIBUTE =
'data-datocms-auto-content-link-url';
export const AUTOMATIC_STEGA_STAMP_ATTRIBUTE = 'data-datocms-contains-stega';
export const MANUAL_TARGET_STAMP_ATTRIBUTE = 'data-datocms-content-link-url';
export const GROUP_ATTRIBUTE = 'data-datocms-content-link-group';

@@ -13,2 +15,2 @@ export const GROUP_BOUNDARY_ATTRIBUTE = 'data-datocms-content-link-boundary';

export const STAMPED_ELEMENTS_SELECTOR = `[${MANUAL_STAMP_ATTRIBUTE}], [${AUTOMATIC_STAMP_ATTRIBUTE}]`;
export const STAMPED_ELEMENTS_SELECTOR = `[${MANUAL_TARGET_STAMP_ATTRIBUTE}], [${AUTOMATIC_TARGET_STAMP_ATTRIBUTE}]`;

@@ -12,6 +12,7 @@ /**

import {
AUTOMATIC_STAMP_ATTRIBUTE,
AUTOMATIC_STEGA_STAMP_ATTRIBUTE,
AUTOMATIC_TARGET_STAMP_ATTRIBUTE,
GROUP_ATTRIBUTE,
GROUP_BOUNDARY_ATTRIBUTE,
SOURCE_STAMP_ATTRIBUTE
SOURCE_STAMP_ATTRIBUTE,
} from './constants.js';

@@ -22,3 +23,5 @@

private readonly pendingElementsToStamp = new Set<ParentNode>();
private readonly scheduleStamping = createScheduler(() => this.instantStampPendingElements());
private readonly scheduleStamping = createScheduler(() =>
this.instantStampPendingElements(),
);

@@ -28,5 +31,7 @@ constructor(

private readonly onStamp: (summary: StampSummary) => void,
private readonly stripStega: boolean = false
private readonly stripStega: boolean = false,
) {
this.observer = new MutationObserver((mutations) => this.handleMutations(mutations));
this.observer = new MutationObserver((mutations) =>
this.handleMutations(mutations),
);

@@ -38,3 +43,3 @@ this.observer.observe(this.root, {

attributes: true,
attributeFilter: ['alt', SOURCE_STAMP_ATTRIBUTE]
attributeFilter: ['alt', SOURCE_STAMP_ATTRIBUTE],
});

@@ -49,6 +54,8 @@

const nodes = this.root.querySelectorAll<HTMLElement>(`[${AUTOMATIC_STAMP_ATTRIBUTE}]`);
const nodes = this.root.querySelectorAll<HTMLElement>(
`[${AUTOMATIC_TARGET_STAMP_ATTRIBUTE}]`,
);
for (const el of nodes) {
el.removeAttribute(AUTOMATIC_STAMP_ATTRIBUTE);
el.removeAttribute(AUTOMATIC_TARGET_STAMP_ATTRIBUTE);
}

@@ -63,12 +70,24 @@ }

const node = mutation.target as Node;
const parent = (node.parentElement ?? node.parentNode ?? this.root) as ParentNode;
const parent = (node.parentElement ??
node.parentNode ??
this.root) as ParentNode;
this.pendingElementsToStamp.add(parent);
hasChanges = true;
} else if (mutation.type === 'attributes' && mutation.attributeName === 'alt') {
} else if (
mutation.type === 'attributes' &&
mutation.attributeName === 'alt'
) {
const element = mutation.target as Element;
this.pendingElementsToStamp.add((element.parentElement ?? this.root) as ParentNode);
this.pendingElementsToStamp.add(
(element.parentElement ?? this.root) as ParentNode,
);
hasChanges = true;
} else if (mutation.type === 'attributes' && mutation.attributeName === SOURCE_STAMP_ATTRIBUTE) {
} else if (
mutation.type === 'attributes' &&
mutation.attributeName === SOURCE_STAMP_ATTRIBUTE
) {
const element = mutation.target as Element;
this.pendingElementsToStamp.add((element.parentElement ?? this.root) as ParentNode);
this.pendingElementsToStamp.add(
(element.parentElement ?? this.root) as ParentNode,
);
hasChanges = true;

@@ -119,3 +138,3 @@ } else if (mutation.type === 'childList') {

}, new Map<Element, string>()),
scope: this.root
scope: this.root,
};

@@ -145,3 +164,3 @@

appliedStamps: new Map(),
scope: element
scope: element,
};

@@ -174,3 +193,3 @@ }

parent,
appliedStamps
appliedStamps,
);

@@ -192,3 +211,3 @@

img,
appliedStamps
appliedStamps,
);

@@ -202,3 +221,5 @@

// Third pass: inspect elements with data-datocms-content-link-source attribute
for (const el of element.querySelectorAll<HTMLElement>(`[${SOURCE_STAMP_ATTRIBUTE}]`)) {
for (const el of element.querySelectorAll<HTMLElement>(
`[${SOURCE_STAMP_ATTRIBUTE}]`,
)) {
const sourceValue = el.getAttribute(SOURCE_STAMP_ATTRIBUTE);

@@ -209,3 +230,3 @@

el,
appliedStamps
appliedStamps,
);

@@ -221,3 +242,3 @@

appliedStamps: appliedStamps,
scope: element
scope: element,
};

@@ -231,3 +252,3 @@

elementWithStega: Element | null,
appliedStamps: Map<Element, string>
appliedStamps: Map<Element, string>,
): string | undefined {

@@ -273,9 +294,16 @@ if (!value || !elementWithStega) {

// Stamp the attribute if it changed
const existingEditUrl = target.getAttribute(AUTOMATIC_STAMP_ATTRIBUTE);
const existingEditUrl = target.getAttribute(
AUTOMATIC_TARGET_STAMP_ATTRIBUTE,
);
if (existingEditUrl !== decoded.href) {
target.setAttribute(AUTOMATIC_STAMP_ATTRIBUTE, decoded.href);
target.setAttribute(AUTOMATIC_TARGET_STAMP_ATTRIBUTE, decoded.href);
appliedStamps.set(target, decoded.href);
}
// When not stripping stega, mark the element that directly contains the stega data
if (!this.stripStega) {
elementWithStega.setAttribute(AUTOMATIC_STEGA_STAMP_ATTRIBUTE, '');
}
return split.cleaned;

@@ -289,3 +317,3 @@ }

incomingEl: Element,
incomingUrl: string
incomingUrl: string,
) {

@@ -292,0 +320,0 @@ const message = `[@datocms/content-link] Multiple stega-encoded payloads resolved to the same DOM element. Previous URL: ${originalUrl}. Incoming URL: ${incomingUrl}. Wrap each encoded block in its own element (for example by adding ${GROUP_ATTRIBUTE}).`;

import { HighlightOverlay } from '../../utils/HighlightOverlay.js';
import { maybeScrollToNearestTarget, sleep, waitTwoRafs } from '../../utils/dom.js';
import {
maybeScrollToNearestTarget,
sleep,
waitTwoRafs,
} from '../../utils/dom.js';
import { extractInfo } from '../../utils/editUrl.js';
import {
AUTOMATIC_STAMP_ATTRIBUTE,
MANUAL_STAMP_ATTRIBUTE,
STAMPED_ELEMENTS_SELECTOR
AUTOMATIC_TARGET_STAMP_ATTRIBUTE,
MANUAL_TARGET_STAMP_ATTRIBUTE,
STAMPED_ELEMENTS_SELECTOR,
} from '../domStamping/constants.js';

@@ -19,3 +23,3 @@ import { STAGGER_DELAY } from './FlashAllManager.js';

private readonly itemId: string,
private readonly editUrlRegExp: RegExp
private readonly editUrlRegExp: RegExp,
) {}

@@ -33,4 +37,5 @@

if (this.disposed) return;
const stampedElements =
this.wrapperElement.querySelectorAll<HTMLElement>(STAMPED_ELEMENTS_SELECTOR);
const stampedElements = this.wrapperElement.querySelectorAll<HTMLElement>(
STAMPED_ELEMENTS_SELECTOR,
);

@@ -40,4 +45,4 @@ const targetsSet = new Set<HTMLElement>();

const editUrl =
element.getAttribute(MANUAL_STAMP_ATTRIBUTE) ||
element.getAttribute(AUTOMATIC_STAMP_ATTRIBUTE);
element.getAttribute(MANUAL_TARGET_STAMP_ATTRIBUTE) ||
element.getAttribute(AUTOMATIC_TARGET_STAMP_ATTRIBUTE);
if (editUrl) {

@@ -88,4 +93,4 @@ // Filter by itemId - parse editUrl to extract itemId

this.overlays.map((overlay, index) =>
overlay.disposeWithFadeOut(index * STAGGER_DELAY, abortController)
)
overlay.disposeWithFadeOut(index * STAGGER_DELAY, abortController),
),
);

@@ -92,0 +97,0 @@

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display