54 lines
2.2 KiB
TypeScript
54 lines
2.2 KiB
TypeScript
const SVG = "http://www.w3.org/2000/svg"
|
|
const XLINK = "http://www.w3.org/1999/xlink"
|
|
|
|
const prefix = "ProseMirror-icon"
|
|
|
|
function hashPath(path: string) {
|
|
let hash = 0
|
|
for (let i = 0; i < path.length; i++)
|
|
hash = (((hash << 5) - hash) + path.charCodeAt(i)) | 0
|
|
return hash
|
|
}
|
|
|
|
export function getIcon(
|
|
root: Document | ShadowRoot,
|
|
icon: {path: string, width: number, height: number} | {text: string, css?: string} | {dom: Node}
|
|
): HTMLElement {
|
|
let doc = (root.nodeType == 9 ? root as Document : root.ownerDocument) || document
|
|
let node = doc.createElement("div")
|
|
node.className = prefix
|
|
if ((icon as any).path) {
|
|
let {path, width, height} = icon as {path: string, width: number, height: number}
|
|
let name = "pm-icon-" + hashPath(path).toString(16)
|
|
if (!doc.getElementById(name)) buildSVG(root, name, icon as {path: string, width: number, height: number})
|
|
let svg = node.appendChild(doc.createElementNS(SVG, "svg"))
|
|
svg.style.width = (width / height) + "em"
|
|
let use = svg.appendChild(doc.createElementNS(SVG, "use"))
|
|
use.setAttributeNS(XLINK, "href", /([^#]*)/.exec(doc.location.toString())![1] + "#" + name)
|
|
} else if ((icon as any).dom) {
|
|
node.appendChild((icon as any).dom.cloneNode(true))
|
|
} else {
|
|
let {text, css} = icon as {text: string, css?: string}
|
|
node.appendChild(doc.createElement("span")).textContent = text || ''
|
|
if (css) (node.firstChild as HTMLElement).style.cssText = css
|
|
}
|
|
return node
|
|
}
|
|
|
|
function buildSVG(root: Document | ShadowRoot, name: string, data: {width: number, height: number, path: string}) {
|
|
let [doc, top] = root.nodeType == 9 ? [root as Document, (root as Document).body] : [root.ownerDocument || document, root]
|
|
let collection = doc.getElementById(prefix + "-collection") as Element
|
|
if (!collection) {
|
|
collection = doc.createElementNS(SVG, "svg")
|
|
collection.id = prefix + "-collection"
|
|
;(collection as HTMLElement).style.display = "none"
|
|
top.insertBefore(collection, top.firstChild)
|
|
}
|
|
let sym = doc.createElementNS(SVG, "symbol")
|
|
sym.id = name
|
|
sym.setAttribute("viewBox", "0 0 " + data.width + " " + data.height)
|
|
let path = sym.appendChild(doc.createElementNS(SVG, "path"))
|
|
path.setAttribute("d", data.path)
|
|
collection.appendChild(sym)
|
|
}
|