188c88e8eSopenharmony_ci/*
288c88e8eSopenharmony_ci * Licensed to the Apache Software Foundation (ASF) under one
388c88e8eSopenharmony_ci * or more contributor license agreements.  See the NOTICE file
488c88e8eSopenharmony_ci * distributed with this work for additional information
588c88e8eSopenharmony_ci * regarding copyright ownership.  The ASF licenses this file
688c88e8eSopenharmony_ci * to you under the Apache License, Version 2.0 (the
788c88e8eSopenharmony_ci * "License"); you may not use this file except in compliance
888c88e8eSopenharmony_ci * with the License.  You may obtain a copy of the License at
988c88e8eSopenharmony_ci *
1088c88e8eSopenharmony_ci *   http://www.apache.org/licenses/LICENSE-2.0
1188c88e8eSopenharmony_ci *
1288c88e8eSopenharmony_ci * Unless required by applicable law or agreed to in writing,
1388c88e8eSopenharmony_ci * software distributed under the License is distributed on an
1488c88e8eSopenharmony_ci * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1588c88e8eSopenharmony_ci * KIND, either express or implied.  See the License for the
1688c88e8eSopenharmony_ci * specific language governing permissions and limitations
1788c88e8eSopenharmony_ci * under the License.
1888c88e8eSopenharmony_ci */
1988c88e8eSopenharmony_ci
2088c88e8eSopenharmony_ciimport * as parse5 from 'parse5'
2188c88e8eSopenharmony_ciimport templater from './templater'
2288c88e8eSopenharmony_ciimport styler from './styler'
2388c88e8eSopenharmony_ciimport scripter from './scripter'
2488c88e8eSopenharmony_ciimport { checkTagName } from './templater/component_validator'
2588c88e8eSopenharmony_ci
2688c88e8eSopenharmony_ciimport {
2788c88e8eSopenharmony_ci  FUNC_START_REG,
2888c88e8eSopenharmony_ci  FUNC_END_REG,
2988c88e8eSopenharmony_ci  stringifyFunction
3088c88e8eSopenharmony_ci} from './util'
3188c88e8eSopenharmony_ci
3288c88e8eSopenharmony_cifunction getAttribute (node, name) {
3388c88e8eSopenharmony_ci  if (node.attrs) {
3488c88e8eSopenharmony_ci    let i = node.attrs.length
3588c88e8eSopenharmony_ci    let attr
3688c88e8eSopenharmony_ci    while (i--) {
3788c88e8eSopenharmony_ci      attr = node.attrs[i]
3888c88e8eSopenharmony_ci      if (attr.name === name) {
3988c88e8eSopenharmony_ci        return attr.value
4088c88e8eSopenharmony_ci      }
4188c88e8eSopenharmony_ci    }
4288c88e8eSopenharmony_ci  }
4388c88e8eSopenharmony_ci}
4488c88e8eSopenharmony_ci
4588c88e8eSopenharmony_cifunction extractDependencies (node, deps) {
4688c88e8eSopenharmony_ci  if (node.childNodes) {
4788c88e8eSopenharmony_ci    node.childNodes.forEach(child => {
4888c88e8eSopenharmony_ci      checkTagName(child, {
4988c88e8eSopenharmony_ci        result: {},
5088c88e8eSopenharmony_ci        deps,
5188c88e8eSopenharmony_ci        log: []
5288c88e8eSopenharmony_ci      })
5388c88e8eSopenharmony_ci      extractDependencies(child, deps)
5488c88e8eSopenharmony_ci    })
5588c88e8eSopenharmony_ci  }
5688c88e8eSopenharmony_ci}
5788c88e8eSopenharmony_ci
5888c88e8eSopenharmony_ciexport function parseFragment (source) {
5988c88e8eSopenharmony_ci  const fragment = parse5.parseFragment(source, {
6088c88e8eSopenharmony_ci    locationInfo: true
6188c88e8eSopenharmony_ci  })
6288c88e8eSopenharmony_ci
6388c88e8eSopenharmony_ci  const output = {
6488c88e8eSopenharmony_ci    deps: [],
6588c88e8eSopenharmony_ci    element: [],
6688c88e8eSopenharmony_ci    template: [],
6788c88e8eSopenharmony_ci    style: [],
6888c88e8eSopenharmony_ci    script: [],
6988c88e8eSopenharmony_ci    data: [],
7088c88e8eSopenharmony_ci    config: []
7188c88e8eSopenharmony_ci  }
7288c88e8eSopenharmony_ci
7388c88e8eSopenharmony_ci  fragment.childNodes.forEach(node => {
7488c88e8eSopenharmony_ci    let type
7588c88e8eSopenharmony_ci
7688c88e8eSopenharmony_ci    if (node.tagName === 'script') {
7788c88e8eSopenharmony_ci      type = getAttribute(node, 'type')
7888c88e8eSopenharmony_ci      if (type !== 'data' && type !== 'config') {
7988c88e8eSopenharmony_ci        type = 'script'
8088c88e8eSopenharmony_ci      }
8188c88e8eSopenharmony_ci    }
8288c88e8eSopenharmony_ci    else {
8388c88e8eSopenharmony_ci      type = node.tagName
8488c88e8eSopenharmony_ci    }
8588c88e8eSopenharmony_ci    if (type === 'we-element') {
8688c88e8eSopenharmony_ci      console.warn(`<we-element name="${getAttribute(node, 'name')}"> is deprecated, please use <element> instead.`)
8788c88e8eSopenharmony_ci      type = 'element'
8888c88e8eSopenharmony_ci    }
8988c88e8eSopenharmony_ci
9088c88e8eSopenharmony_ci    if (!output[type]) {
9188c88e8eSopenharmony_ci      return
9288c88e8eSopenharmony_ci    }
9388c88e8eSopenharmony_ci
9488c88e8eSopenharmony_ci    const name = getAttribute(node, 'name')
9588c88e8eSopenharmony_ci    const src = getAttribute(node, 'src')
9688c88e8eSopenharmony_ci    const lang = getAttribute(node, 'lang')
9788c88e8eSopenharmony_ci
9888c88e8eSopenharmony_ci    output[type].push({
9988c88e8eSopenharmony_ci      name,
10088c88e8eSopenharmony_ci      src,
10188c88e8eSopenharmony_ci      lang,
10288c88e8eSopenharmony_ci      node
10388c88e8eSopenharmony_ci    })
10488c88e8eSopenharmony_ci
10588c88e8eSopenharmony_ci    if (type === 'template') {
10688c88e8eSopenharmony_ci      const deps = []
10788c88e8eSopenharmony_ci      extractDependencies(node.content, deps)
10888c88e8eSopenharmony_ci      output.deps = deps
10988c88e8eSopenharmony_ci    }
11088c88e8eSopenharmony_ci  })
11188c88e8eSopenharmony_ci
11288c88e8eSopenharmony_ci  return output
11388c88e8eSopenharmony_ci}
11488c88e8eSopenharmony_ci
11588c88e8eSopenharmony_ciexport function parseTemplate (source, resourcePath) {
11688c88e8eSopenharmony_ci  return new Promise((resolve, reject) => {
11788c88e8eSopenharmony_ci    templater.parse(source, (err, obj) => {
11888c88e8eSopenharmony_ci      if (err) {
11988c88e8eSopenharmony_ci        reject(err)
12088c88e8eSopenharmony_ci      }
12188c88e8eSopenharmony_ci      else {
12288c88e8eSopenharmony_ci        // parse json to string and treat function specially
12388c88e8eSopenharmony_ci        let parsed = JSON.stringify(obj.jsonTemplate, stringifyFunction, '  ')
12488c88e8eSopenharmony_ci        parsed = parsed.replace(FUNC_START_REG, '').replace(FUNC_END_REG, '')
12588c88e8eSopenharmony_ci        resolve({ parsed, log: obj.log })
12688c88e8eSopenharmony_ci      }
12788c88e8eSopenharmony_ci    }, resourcePath)
12888c88e8eSopenharmony_ci  })
12988c88e8eSopenharmony_ci}
13088c88e8eSopenharmony_ci
13188c88e8eSopenharmony_ciexport function parseStyle (source, resourcePath) {
13288c88e8eSopenharmony_ci  return new Promise((resolve, reject) => {
13388c88e8eSopenharmony_ci    styler.parse(source, (err, obj) => {
13488c88e8eSopenharmony_ci      if (err) {
13588c88e8eSopenharmony_ci        reject(err)
13688c88e8eSopenharmony_ci      }
13788c88e8eSopenharmony_ci      else {
13888c88e8eSopenharmony_ci        const parsed = JSON.stringify(obj.jsonStyle, null, 2)
13988c88e8eSopenharmony_ci        resolve({ parsed, log: obj.log })
14088c88e8eSopenharmony_ci      }
14188c88e8eSopenharmony_ci    }, resourcePath)
14288c88e8eSopenharmony_ci  })
14388c88e8eSopenharmony_ci}
14488c88e8eSopenharmony_ci
14588c88e8eSopenharmony_ciexport function parseScript (source) {
14688c88e8eSopenharmony_ci  return new Promise((resolve, reject) => {
14788c88e8eSopenharmony_ci    const parsed = scripter.fix(source)
14888c88e8eSopenharmony_ci    resolve({ parsed })
14988c88e8eSopenharmony_ci  })
15088c88e8eSopenharmony_ci}
151