All files index.ts

98% Statements 49/50
81.48% Branches 22/27
100% Functions 9/9
98% Lines 49/50
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 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 1511x                 1x 1x 1x 1x     28x                                             1x 7x 7x 7x           7x                 7x         50x     50x   28x 28x 15x     28x 7x   21x     28x 28x       22x 21x 1x 1x     50x   50x         15x 15x 15x   15x 43x     15x       7x         21x         1x       74x 15x     59x 59x                 21x 21x 21x     21x 25x 25x       21x   21x    
import {
  ParseSourceSpan,
  splitNsName,
  Element,
  Comment,
  Text,
  Node
} from 'webparser'
 
let htmlSchema = require('property-information/html')
let svgSchema = require('property-information/svg')
let hastSvg = require('@starptech/prettyhtml-hastscript/svg')
let hast = require('@starptech/prettyhtml-hastscript')
 
function isFakeRoot(obj: Element): boolean {
  return obj.name === ':webparser:root'
}
 
type Options = {
  file?: string
  verbose?: boolean
  schema?: { space: string }
  documentMode?: boolean
}
 
type HastNode = {
  name?: string
  type: string
  tagName?: string
  properties?: Array<Object>
  children?: HastNode[]
  public?: string
  system?: string
  value?: string
  data?: { [name: string]: any }
}
 
/* Wrapper to normalise options. */
export default function(rootNodes: Node[], options: Options) {
  const sourceSpan = new ParseSourceSpan(null, null)
  const fakeRoot = new Element(':webparser:root', [], rootNodes, sourceSpan)
  const result = transform(fakeRoot, {
    schema: htmlSchema,
    file: options.file,
    verbose: options.verbose
  })
 
  Iif (options.documentMode === true) {
    result.children.unshift({
      type: 'doctype',
      name: 'html',
      public: null,
      system: null
    })
  }
 
  return result
}
 
/* Transform a node. */
function transform(ast: Node, config: Options): HastNode {
  let schema = config.schema
  let node: HastNode
 
  if (ast instanceof Element) {
    let children: HastNode[]
    config.schema = getNameAndNS(ast.name).ns === 'svg' ? svgSchema : htmlSchema
    if (ast.children && ast.children.length) {
      children = nodes(ast.children, config)
    }
 
    if (isFakeRoot(ast)) {
      node = root(ast, children)
    } else {
      node = element(ast, children, config)
    }
 
    node.data = node.data || {}
    node.data.selfClosing =
      ast.startSourceSpan === ast.endSourceSpan &&
      ast.startSourceSpan !== null &&
      ast.endSourceSpan !== null
  } else if (ast instanceof Text) {
    node = text(ast)
  } else Eif (ast instanceof Comment) {
    node = comment(ast)
  }
 
  config.schema = schema
 
  return node
}
 
/* Transform children. */
function nodes(children: Node[], config: Options): HastNode[] {
  let length = children.length
  let index = -1
  let result: HastNode[] = []
 
  while (++index < length) {
    result[index] = transform(children[index], config)
  }
 
  return result
}
 
function root(ast: Node, children: HastNode[]): HastNode {
  return { type: 'root', children, data: {} }
}
 
/* Transform a text. */
function text(ast: Text): HastNode {
  return { type: 'text', value: ast.value }
}
 
/* Transform a comment. */
function comment(ast: Comment): HastNode {
  return { type: 'comment', value: ast.value }
}
 
function getNameAndNS(name: string) {
  if (name[0] === ':') {
    return { ns: null, name: name }
  }
 
  const info = splitNsName(name)
  return { ns: info[0], name: info[1] }
}
 
/* Transform an element. */
function element(
  ast: Element,
  children: HastNode[],
  config: Options
): HastNode {
  let fn = config.schema.space === 'svg' ? hastSvg : hast
  let name = getNameAndNS(ast.name).name
  let props: { [name: string]: string } = {}
  let node
 
  for (const attr of ast.attrs) {
    const attrInfo = getNameAndNS(attr.name)
    props[attrInfo.ns ? attrInfo.ns + ':' + attrInfo.name : attrInfo.name] =
      attr.value
  }
 
  node = fn(name, props, children)
 
  return node
}