All files / utils loadCss.ts

92.86% Statements 13/14
88.89% Branches 8/9
100% Functions 5/5
92.86% Lines 13/14

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61          23x                                                 4x           1x   1x 1x 1x 1x         1x 1x     4x 4x     2x 2x          
import { isBlobUrl } from './isBlobUrl'
import { isDataUrl } from './isDataUrl'
import { isUrl } from './isUrl'
import { loadResource, LoadResourceUrlType } from './loadResource'
 
const cache: Record<string, HTMLStyleElement> = Object.create(null)
 
export interface LoadCssResult {
  /**
   * 样式元素。
   */
  el: HTMLStyleElement
 
  /**
   * 销毁函数。
   */
  destroy: () => void
}
 
/**
 * 加载 CSS 样式,支持链接和内容。
 *
 * @param urlOrContent 链接或内容
 * @example
 * ```typescript
 * loadCss('https://foo.bar/global.css')
 * loadCss(`body { font-size: 20px; }`)
 * ```
 */
export function loadCss(urlOrContent: string): Promise<LoadCssResult> {
  return (urlOrContent in cache
    ? Promise.resolve(cache[urlOrContent])
    : isUrl(urlOrContent) || isDataUrl(urlOrContent) || isBlobUrl(urlOrContent)
    ? loadResource({
        type: LoadResourceUrlType.css,
        path: urlOrContent,
      }).then<HTMLStyleElement>(res => res[0] as any)
    : new Promise<HTMLStyleElement>(resolve => {
        const el = document.createElement('style')
        el.setAttribute('type', 'text/css')
        if ('textContent' in el) {
          el.textContent = urlOrContent
        } else E{
          // @ts-ignore
          el.styleSheet.cssText = urlOrContent
        }
        document.getElementsByTagName('head')[0].appendChild(el)
        resolve(el)
      })
  ).then<LoadCssResult>(el => {
    cache[urlOrContent] = el
    return {
      el: el,
      destroy: () => {
        delete cache[urlOrContent]
        el.parentNode!.removeChild(el)
      },
    }
  })
}