| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- import { warn } from '@vue/runtime-core'
- import type { RendererOptions } from '@vue/runtime-core'
- import type {
- TrustedHTML,
- TrustedTypePolicy,
- TrustedTypesWindow,
- } from 'trusted-types/lib'
- let policy: Pick<TrustedTypePolicy, 'name' | 'createHTML'> | undefined =
- undefined
- const tt =
- typeof window !== 'undefined' &&
- (window as unknown as TrustedTypesWindow).trustedTypes
- if (tt) {
- try {
- policy = /*@__PURE__*/ tt.createPolicy('vue', {
- createHTML: val => val,
- })
- } catch (e: unknown) {
- // `createPolicy` throws a TypeError if the name is a duplicate
- // and the CSP trusted-types directive is not using `allow-duplicates`.
- // So we have to catch that error.
- __DEV__ && warn(`Error creating trusted types policy: ${e}`)
- }
- }
- // __UNSAFE__
- // Reason: potentially setting innerHTML.
- // This function merely perform a type-level trusted type conversion
- // for use in `innerHTML` assignment, etc.
- // Be careful of whatever value passed to this function.
- export const unsafeToTrustedHTML: (value: string) => TrustedHTML | string =
- policy ? val => policy.createHTML(val) : val => val
- export const svgNS = 'http://www.w3.org/2000/svg'
- export const mathmlNS = 'http://www.w3.org/1998/Math/MathML'
- const doc = (typeof document !== 'undefined' ? document : null) as Document
- const templateContainer = doc && /*@__PURE__*/ doc.createElement('template')
- export const nodeOps: Omit<RendererOptions<Node, Element>, 'patchProp'> = {
- insert: (child, parent, anchor) => {
- parent.insertBefore(child, anchor || null)
- },
- remove: child => {
- const parent = child.parentNode
- if (parent) {
- parent.removeChild(child)
- }
- },
- createElement: (tag, namespace, is, props): Element => {
- const el =
- namespace === 'svg'
- ? doc.createElementNS(svgNS, tag)
- : namespace === 'mathml'
- ? doc.createElementNS(mathmlNS, tag)
- : is
- ? doc.createElement(tag, { is })
- : doc.createElement(tag)
- if (tag === 'select' && props && props.multiple != null) {
- ;(el as HTMLSelectElement).setAttribute('multiple', props.multiple)
- }
- return el
- },
- createText: text => doc.createTextNode(text),
- createComment: text => doc.createComment(text),
- setText: (node, text) => {
- node.nodeValue = text
- },
- setElementText: (el, text) => {
- el.textContent = text
- },
- parentNode: node => node.parentNode as Element | null,
- nextSibling: node => node.nextSibling,
- querySelector: selector => doc.querySelector(selector),
- setScopeId(el, id) {
- el.setAttribute(id, '')
- },
- // __UNSAFE__
- // Reason: innerHTML.
- // Static content here can only come from compiled templates.
- // As long as the user only uses trusted templates, this is safe.
- insertStaticContent(content, parent, anchor, namespace, start, end) {
- // <parent> before | first ... last | anchor </parent>
- const before = anchor ? anchor.previousSibling : parent.lastChild
- // #5308 can only take cached path if:
- // - has a single root node
- // - nextSibling info is still available
- if (start && (start === end || start.nextSibling)) {
- // cached
- while (true) {
- parent.insertBefore(start!.cloneNode(true), anchor)
- if (start === end || !(start = start!.nextSibling)) break
- }
- } else {
- // fresh insert
- templateContainer.innerHTML = unsafeToTrustedHTML(
- namespace === 'svg'
- ? `<svg>${content}</svg>`
- : namespace === 'mathml'
- ? `<math>${content}</math>`
- : content,
- ) as string
- const template = templateContainer.content
- if (namespace === 'svg' || namespace === 'mathml') {
- // remove outer svg/math wrapper
- const wrapper = template.firstChild!
- while (wrapper.firstChild) {
- template.appendChild(wrapper.firstChild)
- }
- template.removeChild(wrapper)
- }
- parent.insertBefore(template, anchor)
- }
- return [
- // first
- before ? before.nextSibling! : parent.firstChild!,
- // last
- anchor ? anchor.previousSibling! : parent.lastChild!,
- ]
- },
- }
|