Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | 4x 467064x 202548x 87458x 87458x 85534x 1924x 651x 1273x 1261x 12x 8x 4x 4188x 4188x 1037x 1037x 1037x 1037x 1037x 1037x 1037x 30536x 30536x 30536x 1037x 1037x 1037x 390x 647x 18522x 64748x 790x 790x 172x 27180x 27180x 10x 4752x 35882x 7066x 7066x 7066x 7066x 7066x 184x 184x 184x 53x 187x 53x 180x 75x 75x 74x 74x 74x 74x 24x 24x 24x 118x 118x 118x 92x 78x 78x 92x 1x 91x 91x 91x 91x 53x 53x 53x 138400x 6504x 6504x 6504x 12976x 2955x 12976x 6504x | import { XMLSerializer, type Attr as XmlAttr, type Document as XmlDocument, type Element as XmlElement, type Node as XmlNode } from '@xmldom/xmldom';
import { parseXmlDocument } from '../xmlParser';
import { ACTIVITI_NAMESPACE, BPMN_MODEL_NAMESPACE } from './constants';
export const serializer = new XMLSerializer();
export function getElementChildren(element: XmlElement): XmlElement[] {
return Array.from(element.childNodes).filter((node): node is XmlElement => node.nodeType === node.ELEMENT_NODE);
}
export function getLocalName(node: XmlNode): string {
return node.localName || node.nodeName.split(':').pop() || node.nodeName;
}
function matchesQualifiedNode(
node: Pick<XmlNode, 'nodeName' | 'namespaceURI' | 'localName'>,
localName: string,
namespaceUri?: string,
): boolean {
const nodeLocalName = node.localName || node.nodeName.split(':').pop() || node.nodeName;
if (nodeLocalName !== localName) {
return false;
}
if (!namespaceUri) {
return true;
}
if ((node.namespaceURI || '') === namespaceUri) {
return true;
}
if (!node.namespaceURI && namespaceUri === ACTIVITI_NAMESPACE) {
return node.nodeName === `activiti:${localName}`;
}
return false;
}
export function isElementNamed(node: XmlNode, localName: string, namespaceUri?: string): node is XmlElement {
return node.nodeType === node.ELEMENT_NODE && matchesQualifiedNode(node, localName, namespaceUri);
}
export function isActivitiElement(node: XmlNode, localName: string): node is XmlElement {
return isElementNamed(node, localName, ACTIVITI_NAMESPACE);
}
function getTraversalRoot(root: XmlDocument | XmlElement): XmlElement | undefined {
Eif ('documentElement' in root) {
return root.documentElement || undefined;
}
return root;
}
function collectDescendantElements(root: XmlDocument | XmlElement): XmlElement[] {
const traversalRoot = getTraversalRoot(root);
Iif (!traversalRoot) {
return [];
}
const elements: XmlElement[] = [];
const queue: XmlElement[] = [traversalRoot];
while (queue.length > 0) {
const [element] = queue.splice(0, 1);
elements.push(element);
queue.push(...getElementChildren(element));
}
return elements;
}
export function getElementsByLocalName(root: XmlDocument | XmlElement, localName: string, namespaceUri?: string): XmlElement[] {
const elements = collectDescendantElements(root);
if (localName === '*') {
return elements;
}
return elements.filter((node): node is XmlElement => {
return matchesQualifiedNode(node, localName, namespaceUri);
});
}
function findAttribute(element: XmlElement, localName: string, namespaceUri?: string): XmlAttr | undefined {
return Array.from(element.attributes).find((attribute) => matchesQualifiedNode(attribute, localName, namespaceUri));
}
export function getAttributeValue(element: XmlElement, localName: string, namespaceUri?: string): string {
return findAttribute(element, localName, namespaceUri)?.value || '';
}
export function getActivitiAttribute(element: XmlElement, localName: string): string {
return getAttributeValue(element, localName, ACTIVITI_NAMESPACE);
}
export function setActivitiAttribute(element: XmlElement, localName: string, value: string): void {
element.setAttributeNS(ACTIVITI_NAMESPACE, `activiti:${localName}`, value);
}
export function removeActivitiAttribute(element: XmlElement, localName: string): void {
const attribute = findAttribute(element, localName, ACTIVITI_NAMESPACE);
if (attribute) {
element.removeAttributeNode(attribute);
}
}
export function isSameElementType(left: XmlElement, right: XmlElement): boolean {
return getLocalName(left) === getLocalName(right) && (left.namespaceURI || '') === (right.namespaceURI || '');
}
function replaceAllPlain(value: string, search: string, replacement: string): string {
return value.split(search).join(replacement);
}
export function escapeXml(value: string): string {
let escapedValue = replaceAllPlain(value, '&', '&');
escapedValue = replaceAllPlain(escapedValue, '<', '<');
escapedValue = replaceAllPlain(escapedValue, '>', '>');
escapedValue = replaceAllPlain(escapedValue, '"', '"');
return replaceAllPlain(escapedValue, "'", ''');
}
export function escapeXmlText(value: string): string {
let escapedValue = replaceAllPlain(value, '&', '&');
escapedValue = replaceAllPlain(escapedValue, '<', '<');
return replaceAllPlain(escapedValue, '>', '>');
}
function buildNamespaceWrapper(namespaces: Record<string, string>): string {
const namespaceAttributes = Object.entries(namespaces)
.map(([prefix, uri]) => `xmlns:${prefix}="${escapeXml(uri)}"`)
.join(' ');
return `<root xmlns="${BPMN_MODEL_NAMESPACE}" ${namespaceAttributes}>`;
}
export function getNodeDocument(node: XmlNode): XmlDocument {
return (node.ownerDocument || node) as XmlDocument;
}
export function insertAfter(parent: XmlNode, newNode: XmlNode, referenceNode: XmlNode): void {
if (referenceNode.nextSibling) {
parent.insertBefore(newNode, referenceNode.nextSibling);
} else E{
parent.appendChild(newNode);
}
}
export function insertBeforeNode(parent: XmlNode, newNode: XmlNode, referenceNode: XmlNode): void {
const beforeCapableReference = referenceNode as XmlNode & { before?: (node: XmlNode) => void };
Iif (typeof beforeCapableReference.before === 'function') {
beforeCapableReference.before(newNode);
return;
}
const insertBefore = parent.insertBefore.bind(parent);
insertBefore(newNode, referenceNode);
}
export function replaceNode(targetNode: XmlNode, replacementNode: XmlNode): void {
const replaceCapableNode = targetNode as XmlNode & { replaceWith?: (node: XmlNode) => void };
Iif (typeof replaceCapableNode.replaceWith === 'function') {
replaceCapableNode.replaceWith(replacementNode);
return;
}
targetNode.parentNode?.replaceChild(replacementNode, targetNode);
}
export function detachNode(node: XmlNode): void {
Eif (node.parentNode) {
const removeChild = node.parentNode.removeChild.bind(node.parentNode);
removeChild(node);
}
}
export function setTextContentPreservingComments(element: XmlElement, value: string): void {
for (const child of Array.from(element.childNodes)) {
Eif (child.nodeType === child.TEXT_NODE || child.nodeType === child.CDATA_SECTION_NODE) {
detachNode(child);
}
}
if (!value) {
return;
}
const firstNonTextChild = Array.from(element.childNodes).find((child) => {
return child.nodeType !== child.TEXT_NODE && child.nodeType !== child.CDATA_SECTION_NODE;
});
const textNode = getNodeDocument(element).createTextNode(value);
Iif (firstNonTextChild) {
const insertBefore = element.insertBefore.bind(element);
insertBefore(textNode, firstNonTextChild);
} else {
element.appendChild(textNode);
}
}
export function parseXmlFragment(xml: string, namespaces: Record<string, string>): XmlElement[] {
const fragmentDocument = parseXmlDocument(`${buildNamespaceWrapper(namespaces)}${xml}</root>`);
Iif (!fragmentDocument.documentElement) {
return [];
}
return getElementChildren(fragmentDocument.documentElement);
}
export function findDirectChild(element: XmlElement, localName: string): XmlElement | undefined {
return getElementChildren(element).find((child) => getLocalName(child) === localName);
}
export function buildXmlIdentity(scope: string, element: XmlElement): string {
let index = 0;
let sibling = element.previousSibling;
while (sibling) {
if (sibling.nodeType === sibling.ELEMENT_NODE && isSameElementType(sibling as XmlElement, element)) {
index++;
}
sibling = sibling.previousSibling;
}
return `${scope}:${element.namespaceURI || ''}:${getLocalName(element)}:${index}`;
} |