Precise DOM morphing
morphing typescript dom

Rename `preserveModified` to `preserveChanges`

+42 -44
+10 -12
src/morphlex.ts
··· 19 19 * This prevents user-entered data from being overwritten. 20 20 * @default false 21 21 */ 22 - preserveModified?: boolean 22 + preserveChanges?: boolean 23 23 24 24 /** 25 25 * Called before a node is visited during morphing. ··· 107 107 * @param options Optional configuration for the morphing behavior. 108 108 * @example 109 109 * ```ts 110 - * morphDocument(document, "<html>...</html>", { preserveModified: true }) 110 + * morphDocument(document, "<html>...</html>", { preserveChanges: true }) 111 111 * ``` 112 112 */ 113 113 export function morphDocument(from: Document, to: Document | string, options?: Options): void { ··· 375 375 for (const { name, value } of to.attributes) { 376 376 if (name === "value") { 377 377 if (isInputElement(from) && from.value !== value) { 378 - if (!this.#options.preserveModified || from.value === from.defaultValue) { 378 + if (!this.#options.preserveChanges || from.value === from.defaultValue) { 379 379 from.value = value 380 380 } 381 381 } ··· 383 383 384 384 if (name === "selected") { 385 385 if (isOptionElement(from) && !from.selected) { 386 - if (!this.#options.preserveModified || from.selected === from.defaultSelected) { 386 + if (!this.#options.preserveChanges || from.selected === from.defaultSelected) { 387 387 from.selected = true 388 388 } 389 389 } ··· 391 391 392 392 if (name === "checked") { 393 393 if (isInputElement(from) && !from.checked) { 394 - if (!this.#options.preserveModified || from.checked === from.defaultChecked) { 394 + if (!this.#options.preserveChanges || from.checked === from.defaultChecked) { 395 395 from.checked = true 396 396 } 397 397 } ··· 414 414 if (!to.hasAttribute(name)) { 415 415 if (name === "selected") { 416 416 if (isOptionElement(from) && from.selected) { 417 - if (!this.#options.preserveModified || from.selected === from.defaultSelected) { 417 + if (!this.#options.preserveChanges || from.selected === from.defaultSelected) { 418 418 from.selected = false 419 419 } 420 420 } ··· 422 422 423 423 if (name === "checked") { 424 424 if (isInputElement(from) && from.checked) { 425 - if (!this.#options.preserveModified || from.checked === from.defaultChecked) { 425 + if (!this.#options.preserveChanges || from.checked === from.defaultChecked) { 426 426 from.checked = false 427 427 } 428 428 } ··· 445 445 from.textContent = newTextContent 446 446 } 447 447 448 - if (this.#options.preserveModified && isModified) return 448 + if (this.#options.preserveChanges && isModified) return 449 449 450 450 from.value = from.defaultValue 451 451 } ··· 640 640 // Find LIS - these nodes don't need to move 641 641 const lisIndices = this.#longestIncreasingSubsequence(sequence) 642 642 const shouldNotMove = new Set<number>() 643 - for (const idx of lisIndices) { 644 - shouldNotMove.add(sequence[idx]!) 643 + for (const i of lisIndices) { 644 + shouldNotMove.add(sequence[i]!) 645 645 } 646 646 647 - // Process nodes in forward order to maintain proper positioning 648 647 let insertionPoint: ChildNode | null = parent.firstChild 649 648 for (let i = 0; i < toChildNodes.length; i++) { 650 649 const node = toChildNodes[i]! 651 650 const match = matches[i] 652 651 if (match) { 653 652 const matchIndex = fromIndex.get(match)! 654 - // Only move if not in LIS 655 653 if (!shouldNotMove.has(matchIndex)) { 656 654 moveBefore(parent, match, insertionPoint) 657 655 }
+32 -32
test/new/inputs.browser.test.ts
··· 3 3 import { dom } from "./utils" 4 4 5 5 describe("text input", () => { 6 - test("morphing a modified value with preserveModified enabled", () => { 6 + test("morphing a modified value with preserveChanges enabled", () => { 7 7 const a = dom(`<input type="text" value="a">`) as HTMLInputElement 8 8 const b = dom(`<input type="text" value="b">`) as HTMLInputElement 9 9 10 10 a.value = "c" 11 - morph(a, b, { preserveModified: true }) 11 + morph(a, b, { preserveChanges: true }) 12 12 13 13 expect(a.outerHTML).toBe(`<input type="text" value="b">`) 14 14 expect(a.value).toBe("c") 15 15 }) 16 16 17 - test("morphing a modified value preserveModified disabled", () => { 17 + test("morphing a modified value preserveChanges disabled", () => { 18 18 const a = dom(`<input type="text" value="a">`) as HTMLInputElement 19 19 const b = dom(`<input type="text" value="b">`) as HTMLInputElement 20 20 21 21 a.value = "c" 22 - morph(a, b, { preserveModified: false }) 22 + morph(a, b, { preserveChanges: false }) 23 23 24 24 expect(a.outerHTML).toBe(`<input type="text" value="b">`) 25 25 expect(a.value).toBe("b") 26 26 }) 27 27 28 - test("morphing an unmodified value with preserveModified enabled", () => { 28 + test("morphing an unmodified value with preserveChanges enabled", () => { 29 29 const a = dom(`<input type="text" value="a">`) as HTMLInputElement 30 30 const b = dom(`<input type="text" value="b">`) as HTMLInputElement 31 31 32 - morph(a, b, { preserveModified: true }) 32 + morph(a, b, { preserveChanges: true }) 33 33 34 34 expect(a.outerHTML).toBe(`<input type="text" value="b">`) 35 35 expect(a.value).toBe("b") ··· 37 37 }) 38 38 39 39 describe("checkbox", () => { 40 - test("morphing a modified checkbox checked with preserveModified enabled", () => { 40 + test("morphing a modified checkbox checked with preserveChanges enabled", () => { 41 41 const a = dom(`<input type="checkbox">`) as HTMLInputElement 42 42 const b = dom(`<input type="checkbox" checked>`) as HTMLInputElement 43 43 44 44 a.checked = true 45 - morph(a, b, { preserveModified: true }) 45 + morph(a, b, { preserveChanges: true }) 46 46 47 47 expect(a.hasAttribute("checked")).toBe(true) 48 48 expect(a.checked).toBe(true) 49 49 }) 50 50 51 - test("morphing a modified checkbox checked with preserveModified disabled", () => { 51 + test("morphing a modified checkbox checked with preserveChanges disabled", () => { 52 52 const a = dom(`<input type="checkbox">`) as HTMLInputElement 53 53 const b = dom(`<input type="checkbox" checked>`) as HTMLInputElement 54 54 55 55 a.checked = true 56 - morph(a, b, { preserveModified: false }) 56 + morph(a, b, { preserveChanges: false }) 57 57 58 58 expect(a.hasAttribute("checked")).toBe(true) 59 59 expect(a.checked).toBe(true) 60 60 }) 61 61 62 - test("morphing an unmodified checkbox with preserveModified enabled", () => { 62 + test("morphing an unmodified checkbox with preserveChanges enabled", () => { 63 63 const a = dom(`<input type="checkbox">`) as HTMLInputElement 64 64 const b = dom(`<input type="checkbox" checked>`) as HTMLInputElement 65 65 66 - morph(a, b, { preserveModified: true }) 66 + morph(a, b, { preserveChanges: true }) 67 67 68 68 expect(a.hasAttribute("checked")).toBe(true) 69 69 expect(a.checked).toBe(true) 70 70 }) 71 71 72 - test("morphing a modified checkbox unchecked with preserveModified enabled", () => { 72 + test("morphing a modified checkbox unchecked with preserveChanges enabled", () => { 73 73 const a = dom(`<input type="checkbox" checked>`) as HTMLInputElement 74 74 const b = dom(`<input type="checkbox">`) as HTMLInputElement 75 75 76 76 a.checked = false 77 - morph(a, b, { preserveModified: true }) 77 + morph(a, b, { preserveChanges: true }) 78 78 79 79 expect(a.hasAttribute("checked")).toBe(false) 80 80 expect(a.checked).toBe(false) 81 81 }) 82 82 83 - test("morphing a modified checkbox unchecked with preserveModified disabled", () => { 83 + test("morphing a modified checkbox unchecked with preserveChanges disabled", () => { 84 84 const a = dom(`<input type="checkbox" checked>`) as HTMLInputElement 85 85 const b = dom(`<input type="checkbox">`) as HTMLInputElement 86 86 87 87 a.checked = false 88 - morph(a, b, { preserveModified: false }) 88 + morph(a, b, { preserveChanges: false }) 89 89 90 90 expect(a.hasAttribute("checked")).toBe(false) 91 91 expect(a.checked).toBe(false) ··· 93 93 }) 94 94 95 95 describe("select", () => { 96 - test("morphing a modified select option with preserveModified enabled", () => { 96 + test("morphing a modified select option with preserveChanges enabled", () => { 97 97 const a = dom(`<select><option value="a">A</option><option value="b">B</option></select>`) as HTMLSelectElement 98 98 const b = dom(`<select><option value="a">A</option><option value="b" selected>B</option></select>`) as HTMLSelectElement 99 99 100 100 a.value = "b" 101 - morph(a, b, { preserveModified: true }) 101 + morph(a, b, { preserveChanges: true }) 102 102 103 103 expect(a.options[1].hasAttribute("selected")).toBe(true) 104 104 expect(a.value).toBe("b") 105 105 expect(a.options[1].selected).toBe(true) 106 106 }) 107 107 108 - test("morphing a modified select option with preserveModified disabled", () => { 108 + test("morphing a modified select option with preserveChanges disabled", () => { 109 109 const a = dom(`<select><option value="a">A</option><option value="b">B</option></select>`) as HTMLSelectElement 110 110 const b = dom(`<select><option value="a">A</option><option value="b" selected>B</option></select>`) as HTMLSelectElement 111 111 112 112 a.value = "b" 113 - morph(a, b, { preserveModified: false }) 113 + morph(a, b, { preserveChanges: false }) 114 114 115 115 expect(a.options[1].hasAttribute("selected")).toBe(true) 116 116 expect(a.value).toBe("b") 117 117 expect(a.options[1].selected).toBe(true) 118 118 }) 119 119 120 - test("morphing an unmodified select option with preserveModified enabled", () => { 120 + test("morphing an unmodified select option with preserveChanges enabled", () => { 121 121 const a = dom(`<select><option value="a">A</option><option value="b">B</option></select>`) as HTMLSelectElement 122 122 const b = dom(`<select><option value="a">A</option><option value="b" selected>B</option></select>`) as HTMLSelectElement 123 123 124 - morph(a, b, { preserveModified: true }) 124 + morph(a, b, { preserveChanges: true }) 125 125 126 126 expect(a.options[1].hasAttribute("selected")).toBe(true) 127 127 expect(a.value).toBe("b") 128 128 expect(a.options[1].selected).toBe(true) 129 129 }) 130 130 131 - test("morphing a modified select option back to default with preserveModified enabled", () => { 131 + test("morphing a modified select option back to default with preserveChanges enabled", () => { 132 132 const a = dom(`<select><option value="a">A</option><option value="b" selected>B</option></select>`) as HTMLSelectElement 133 133 const b = dom(`<select><option value="a">A</option><option value="b">B</option></select>`) as HTMLSelectElement 134 134 135 135 a.value = "a" 136 - morph(a, b, { preserveModified: true }) 136 + morph(a, b, { preserveChanges: true }) 137 137 138 138 expect(a.options[1].hasAttribute("selected")).toBe(false) 139 139 expect(a.value).toBe("a") 140 140 expect(a.options[0].selected).toBe(true) 141 141 }) 142 142 143 - test("morphing a modified select option back to default with preserveModified disabled", () => { 143 + test("morphing a modified select option back to default with preserveChanges disabled", () => { 144 144 const a = dom(`<select><option value="a">A</option><option value="b" selected>B</option></select>`) as HTMLSelectElement 145 145 const b = dom(`<select><option value="a">A</option><option value="b">B</option></select>`) as HTMLSelectElement 146 146 147 147 a.value = "a" 148 - morph(a, b, { preserveModified: false }) 148 + morph(a, b, { preserveChanges: false }) 149 149 150 150 expect(a.options[1].hasAttribute("selected")).toBe(false) 151 151 expect(a.value).toBe("a") ··· 154 154 }) 155 155 156 156 describe("textarea", () => { 157 - test("morphing a modified textarea value with preserveModified enabled", () => { 157 + test("morphing a modified textarea value with preserveChanges enabled", () => { 158 158 const a = dom(`<textarea>a</textarea>`) as HTMLTextAreaElement 159 159 const b = dom(`<textarea>b</textarea>`) as HTMLTextAreaElement 160 160 161 161 a.value = "c" 162 - morph(a, b, { preserveModified: true }) 162 + morph(a, b, { preserveChanges: true }) 163 163 164 164 expect(a.textContent).toBe("b") 165 165 expect(a.value).toBe("c") 166 166 }) 167 167 168 - test("morphing a modified textarea value with preserveModified disabled", () => { 168 + test("morphing a modified textarea value with preserveChanges disabled", () => { 169 169 const a = dom(`<textarea>a</textarea>`) as HTMLTextAreaElement 170 170 const b = dom(`<textarea>b</textarea>`) as HTMLTextAreaElement 171 171 172 172 a.value = "c" 173 - morph(a, b, { preserveModified: false }) 173 + morph(a, b, { preserveChanges: false }) 174 174 175 175 expect(a.textContent).toBe("b") 176 176 expect(a.value).toBe("b") 177 177 }) 178 178 179 - test("morphing an unmodified textarea value with preserveModified enabled", () => { 179 + test("morphing an unmodified textarea value with preserveChanges enabled", () => { 180 180 const a = dom(`<textarea>a</textarea>`) as HTMLTextAreaElement 181 181 const b = dom(`<textarea>b</textarea>`) as HTMLTextAreaElement 182 182 183 - morph(a, b, { preserveModified: true }) 183 + morph(a, b, { preserveChanges: true }) 184 184 185 185 expect(a.textContent).toBe("b") 186 186 expect(a.value).toBe("b")