prosemirror-menu
Version:
Simple menu elements for ProseMirror
54 lines (49 loc) • 2.28 kB
text/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)
}