-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: integrate EditV1 types and oscd-edit event
- Loading branch information
1 parent
a86c1dc
commit bcd6086
Showing
7 changed files
with
274 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import { expect } from "@open-wc/testing"; | ||
|
||
import { Insert, Remove, Update } from "./edit-event.js"; | ||
|
||
import { convertEdit } from "./convertEditToEditV2.js"; | ||
import { | ||
isInsert as isInsertV2, | ||
isRemove as isRemoveV2, | ||
isSetAttributes, | ||
SetAttributes, | ||
} from "./handleEdit.js"; | ||
|
||
const doc = new DOMParser().parseFromString( | ||
'<SCL><Substation name="AA1"></Substation></SCL>', | ||
"application/xml" | ||
); | ||
|
||
const subSt = doc.querySelector("Substation")!; | ||
|
||
const removeV1: Remove = { node: subSt }; | ||
|
||
const insertV1: Insert = { | ||
parent: subSt, | ||
node: doc.createAttribute("VoltageLevel"), | ||
reference: null, | ||
}; | ||
|
||
const update: Update = { | ||
element: subSt, | ||
attributes: { | ||
name: "A2", | ||
desc: null, | ||
["__proto__"]: "a string", | ||
"myns:attr": { | ||
value: "value1", | ||
namespaceURI: "http://example.org/myns", | ||
}, | ||
"myns:attr2": { | ||
value: "value1", | ||
namespaceURI: "http://example.org/myns", | ||
}, | ||
attr: { | ||
value: "value2", | ||
namespaceURI: "http://example.org/myns2", | ||
}, | ||
attr2: { | ||
value: "value2", | ||
namespaceURI: "http://example.org/myns2", | ||
}, | ||
attr3: { | ||
value: "value3", | ||
namespaceURI: null, | ||
}, | ||
}, | ||
}; | ||
|
||
const setAttributes: SetAttributes = { | ||
element: subSt, | ||
attributes: { | ||
name: "A2", | ||
desc: null, | ||
}, | ||
attributesNS: { | ||
"http://example.org/myns": { | ||
"myns:attr": "value1", | ||
"myns:attr2": "value1", | ||
}, | ||
"http://example.org/myns2": { | ||
attr: "value2", | ||
attr2: "value2", | ||
}, | ||
}, | ||
}; | ||
|
||
const invalidEdit = { someWrongKey: "someValue" } as unknown as Update; | ||
|
||
describe("convertEditToEditV2", () => { | ||
it("passes through a Remove edit", () => | ||
expect(convertEdit(removeV1)).to.deep.equal(removeV1)); | ||
|
||
it("passes through a Insert edit", () => | ||
expect(convertEdit(insertV1)).to.deep.equal(insertV1)); | ||
|
||
it("converts Update to SetAttributes", () => | ||
expect(convertEdit(update)).to.deep.equal(setAttributes)); | ||
|
||
it("converts complex edits", () => { | ||
const editsV1 = [removeV1, insertV1, update]; | ||
|
||
const editsV2 = convertEdit(editsV1); | ||
|
||
const [removeV2, insertV2, updateV2] = Array.from( | ||
editsV2 as Array<Remove | Insert | SetAttributes> | ||
); | ||
|
||
expect(removeV1).to.deep.equal(removeV2); | ||
expect(insertV1).to.deep.equal(insertV2); | ||
expect(updateV2).to.deep.equal(setAttributes); | ||
}); | ||
|
||
it("return empty array for invalid edit", () => { | ||
expect(convertEdit(invalidEdit)).to.be.an("array").that.is.empty; | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { | ||
Edit, | ||
isComplex, | ||
isInsert, | ||
isNamespaced, | ||
isUpdate, | ||
isRemove, | ||
Update, | ||
} from "./edit-event.js"; | ||
|
||
import { EditV2 } from "./handleEdit.js"; | ||
|
||
function convertUpdate(edit: Update): EditV2 { | ||
const attributes: Partial<Record<string, string | null>> = {}; | ||
const attributesNS: Partial< | ||
Record<string, Partial<Record<string, string | null>>> | ||
> = {}; | ||
|
||
Object.entries(edit.attributes).forEach(([key, value]) => { | ||
if (isNamespaced(value!)) { | ||
const ns = value.namespaceURI; | ||
if (!ns) return; | ||
|
||
if (!attributesNS[ns]) { | ||
attributesNS[ns] = {}; | ||
} | ||
attributesNS[ns][key] = value.value; | ||
} else attributes[key] = value; | ||
}); | ||
|
||
return { element: edit.element, attributes, attributesNS }; | ||
} | ||
|
||
export function convertEdit(edit: Edit): EditV2 { | ||
if (isRemove(edit)) return edit as EditV2; | ||
if (isInsert(edit)) return edit as EditV2; | ||
if (isUpdate(edit)) return convertUpdate(edit); | ||
if (isComplex(edit)) return edit.map(convertEdit); | ||
|
||
return []; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { EditV2 } from "./handleEdit.js"; | ||
|
||
export type EditDetailV2<E extends EditV2 = EditV2> = { | ||
edit: E; | ||
title?: string; | ||
squash?: boolean; | ||
}; | ||
|
||
export type EditEventV2<E extends EditV2 = EditV2> = CustomEvent< | ||
EditDetailV2<E> | ||
>; | ||
|
||
export type EditEventOptions = { | ||
title?: string; | ||
squash?: boolean; | ||
}; | ||
|
||
export function newEditEventV2<E extends EditV2>( | ||
edit: E, | ||
options?: EditEventOptions | ||
): EditEventV2<E> { | ||
return new CustomEvent<EditDetailV2<E>>("oscd-edit-v2", { | ||
composed: true, | ||
bubbles: true, | ||
detail: { ...options, edit }, | ||
}); | ||
} | ||
|
||
declare global { | ||
interface ElementEventMap { | ||
["oscd-edit-v2"]: EditEventV2; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,65 @@ | ||
import { EditV2 } from "./handleEdit.js"; | ||
|
||
export type EditDetailV2<E extends EditV2 = EditV2> = { | ||
edit: E; | ||
title?: string; | ||
squash?: boolean; | ||
/** Intent to `parent.insertBefore(node, reference)` */ | ||
export type Insert = { | ||
parent: Node; | ||
node: Node; | ||
reference: Node | null; | ||
}; | ||
|
||
export type EditEventV2<E extends EditV2 = EditV2> = CustomEvent< | ||
EditDetailV2<E> | ||
>; | ||
export type NamespacedAttributeValue = { | ||
value: string | null; | ||
namespaceURI: string | null; | ||
}; | ||
export type AttributeValue = string | null | NamespacedAttributeValue; | ||
/** Intent to set or remove (if null) attributes on element */ | ||
export type Update = { | ||
element: Element; | ||
attributes: Partial<Record<string, AttributeValue>>; | ||
}; | ||
|
||
export type EditEventOptions = { | ||
title?: string; | ||
squash?: boolean; | ||
/** Intent to remove a node from its ownerDocument */ | ||
export type Remove = { | ||
node: Node; | ||
}; | ||
|
||
export function newEditEventV2<E extends EditV2>( | ||
edit: E, | ||
options?: EditEventOptions | ||
): EditEventV2<E> { | ||
return new CustomEvent<EditDetailV2<E>>("oscd-edit-v2", { | ||
/** Represents the user's intent to change an XMLDocument */ | ||
export type Edit = Insert | Update | Remove | Edit[]; | ||
|
||
export function isComplex(edit: Edit): edit is Edit[] { | ||
return edit instanceof Array; | ||
} | ||
|
||
export function isInsert(edit: Edit): edit is Insert { | ||
return (edit as Insert).parent !== undefined; | ||
} | ||
|
||
export function isNamespaced( | ||
value: AttributeValue | ||
): value is NamespacedAttributeValue { | ||
return value !== null && typeof value !== "string"; | ||
} | ||
|
||
export function isUpdate(edit: Edit): edit is Update { | ||
return (edit as Update).element !== undefined; | ||
} | ||
|
||
export function isRemove(edit: Edit): edit is Remove { | ||
return ( | ||
(edit as Insert).parent === undefined && (edit as Remove).node !== undefined | ||
); | ||
} | ||
|
||
export type EditEvent<E extends Edit = Edit> = CustomEvent<E>; | ||
|
||
export function newEditEvent<E extends Edit>(edit: E): EditEvent<E> { | ||
return new CustomEvent<E>("oscd-edit", { | ||
composed: true, | ||
bubbles: true, | ||
detail: { ...options, edit }, | ||
detail: edit, | ||
}); | ||
} | ||
|
||
declare global { | ||
interface ElementEventMap { | ||
["oscd-edit-v2"]: EditEventV2; | ||
["oscd-edit"]: EditEvent; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters