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 | 24x 24x 24x 24x 24x 24x 24x 24x 24x 67x 67x 67x 67x 67x 67x 67x 6x 61x 61x 61x 61x 61x 141x 141x 141x 75x 6x 6x 75x 75x 75x 10x 65x 9x 65x 66x 10x 56x 19x 66x 66x 61x 41x 61x 61x 61x 61x 202x 202x 124x 202x 202x 71x 202x 75x 75x 572x 75x 497x 75x | /**
* Marks the end of a string and the beginning of a value
*/
export const beginMarker = "_$bm_";
/**
* Marks the end of a value and the beginning of a string
*/
export const endMarker = "_$em_";
// Referenced to avoid converting the value of the attribute for templates
export const attributeMarkerPrefix = "_$attr:";
export const eventMarkerPrefix = "_$evt:";
export enum NodePatcherRuleTypes {
PATCH_NODE = 1, // Patches either a single node or a collection of nodes
PATCH_ATTRIBUTE,
PATCH_EVENT
}
export interface TemplateData {
templateString: string;
template: HTMLTemplateElement;
keyIndex: number;
}
export default function createTemplate(strings: TemplateStringsArray): TemplateData {
const template = document.createElement('template');
const {
templateString,
keyIndex
} = createTemplateString(strings);
template.innerHTML = templateString;
return {
templateString,
template,
keyIndex
};
}
function createTemplateString(strings: TemplateStringsArray): { templateString: string, keyIndex: number } {
let keyIndex: number = undefined; // The index of the key to get the value from the values array
const parts: string[] = [];
if (strings.length === 1) { // No values ... literal only
return {
templateString: strings[0],
keyIndex
};
}
const length = strings.length - 1; // Exclude the last one
let s: string = undefined;
// Flag to indicate state whether we are dealing with a value for an attribute or an event
let beginAttributeOrEvent: boolean = false;
// Flag when a begin marker has been emitted but we transitioned to an attribute so we need to emit the end marker as well
let beginMarkerSet: boolean = false;
for (let i = 0; i < length; ++i) {
s = strings[i];
s = trimNode(s);
if (s.endsWith('=')) { // It is an attribute or an event
if (beginMarkerSet === true) {
parts.push(`<!--${endMarker}-->`); // End the previous node
beginMarkerSet = false;
}
const name = getAttributeName(s);
beginAttributeOrEvent = true;
if (name[0] === 'o' && name[1] === 'n') { // It is an event handler
parts.push(`${s}"${eventMarkerPrefix}${name}"`);
}
else { // Not an event
if (name === 'key') {
keyIndex = i;
}
parts.push(`${s}"${attributeMarkerPrefix}${name}"`);
}
}
else { // It is the beginning of a text or element
if (beginAttributeOrEvent === true) {
beginAttributeOrEvent = false; // Clear the attribute flag
}
else if (i > 0) { // Ignore the first string
parts.push(`<!--${endMarker}-->`); // End the previous node
}
parts.push(`${s}<!--${beginMarker}-->`);
beginMarkerSet = true; // Flag that we set the begin marker
}
}
// Add the ending string
if (beginAttributeOrEvent === false) { // End of a text or element
parts.push(`<!--${endMarker}-->`);
}
s = strings[length];
s = trimNode(s);
parts.push(s);
return {
templateString: parts.join(''),
keyIndex
};
}
function trimNode(s: string): string {
const trimmedStart = s.trimStart();
if (trimmedStart.startsWith('<') ||
trimmedStart === '') {
s = trimmedStart; // Remove any empty text nodes at the start so there are not extra unnecessary children
}
const trimmedEnd = s.trimEnd();
if (trimmedEnd.endsWith('>')) {
s = trimmedEnd;
}
return s;
}
function getAttributeName(s: string): string {
let b: string[] = [];
for (let i = s.lastIndexOf('=') - 1; i >= 0; --i) {
if (s[i] === ' ') { // Finished with the name of the attribute
break;
}
b = [s[i], ...b]; // Prepend
}
return b.join('');
} |