mirror of
https://github.com/penpot/penpot.git
synced 2025-05-09 05:55:53 +02:00
102 lines
2.8 KiB
JavaScript
102 lines
2.8 KiB
JavaScript
/**
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* Copyright (c) KALEIDOS INC
|
|
*/
|
|
|
|
import { createInline } from "./Inline.js";
|
|
import {
|
|
createEmptyParagraph,
|
|
createParagraph,
|
|
isLikeParagraph,
|
|
} from "./Paragraph.js";
|
|
import { isDisplayBlock, normalizeStyles } from "./Style.js";
|
|
|
|
/**
|
|
* Maps any HTML into a valid content DOM element.
|
|
*
|
|
* @param {Document} document
|
|
* @param {HTMLElement} root
|
|
* @param {CSSStyleDeclaration} [styleDefaults]
|
|
* @returns {DocumentFragment}
|
|
*/
|
|
export function mapContentFragmentFromDocument(document, root, styleDefaults) {
|
|
const nodeIterator = document.createNodeIterator(
|
|
root,
|
|
NodeFilter.SHOW_TEXT
|
|
);
|
|
const fragment = document.createDocumentFragment();
|
|
|
|
let currentParagraph = null;
|
|
let currentNode = nodeIterator.nextNode();
|
|
while (currentNode) {
|
|
// We cannot call document.defaultView because it is `null`.
|
|
const currentStyle = normalizeStyles(currentNode, styleDefaults);
|
|
if (
|
|
isDisplayBlock(currentNode.parentElement.style) ||
|
|
isDisplayBlock(currentStyle) ||
|
|
isLikeParagraph(currentNode.parentElement)
|
|
) {
|
|
if (currentParagraph) {
|
|
fragment.appendChild(currentParagraph);
|
|
}
|
|
currentParagraph = createParagraph(undefined, currentStyle);
|
|
} else {
|
|
if (currentParagraph === null) {
|
|
currentParagraph = createParagraph(undefined, currentStyle);
|
|
}
|
|
}
|
|
|
|
currentParagraph.appendChild(
|
|
createInline(new Text(currentNode.nodeValue), currentStyle)
|
|
);
|
|
|
|
currentNode = nodeIterator.nextNode();
|
|
}
|
|
|
|
fragment.appendChild(currentParagraph);
|
|
return fragment;
|
|
}
|
|
|
|
/**
|
|
* Maps any HTML into a valid content DOM element.
|
|
*
|
|
* @param {string} html
|
|
* @param {CSSStyleDeclaration} [styleDefaults]
|
|
* @returns {DocumentFragment}
|
|
*/
|
|
export function mapContentFragmentFromHTML(html, styleDefaults) {
|
|
const parser = new DOMParser();
|
|
const htmlDocument = parser.parseFromString(html, "text/html");
|
|
return mapContentFragmentFromDocument(
|
|
htmlDocument,
|
|
htmlDocument.documentElement,
|
|
styleDefaults
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Maps a plain text into a valid content DOM element.
|
|
*
|
|
* @param {string} string
|
|
* @param {CSSStyleDeclaration} [styleDefaults]
|
|
* @returns {DocumentFragment}
|
|
*/
|
|
export function mapContentFragmentFromString(string, styleDefaults) {
|
|
const lines = string.replace(/\r/g, "").split("\n");
|
|
const fragment = document.createDocumentFragment();
|
|
for (const line of lines) {
|
|
if (line === "") {
|
|
fragment.appendChild(createEmptyParagraph(styleDefaults));
|
|
} else {
|
|
fragment.appendChild(
|
|
createParagraph([
|
|
createInline(new Text(line), styleDefaults)
|
|
], styleDefaults)
|
|
);
|
|
}
|
|
}
|
|
return fragment;
|
|
}
|