• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import path from 'path'
17import fs from 'fs'
18import {
19  getRequireString,
20  jsonLoaders,
21  logWarn
22}
23from './util'
24import { parseFragment } from './parser'
25
26function loader(source) {
27  this.cacheable && this.cacheable()
28  const options = {
29    lang: {
30      sass:['sass-loader'],
31      scss:['sass-loader'],
32      less:['less-loader']
33    }
34  }
35  const customLang = options.lang || {}
36  const resourcePath = this.resourcePath
37  const fileName = resourcePath.replace(path.extname(resourcePath).toString(), '')
38  let output = '//card_start\n'
39  output += 'var card_template =' + getRequireString(this, jsonLoaders('template'), resourcePath)
40  const styleInfo = findStyleFile(fileName)
41  if (styleInfo.extStyle == true) {
42    output += 'var card_style =' +
43      getRequireString(this, jsonLoaders('style', customLang[styleInfo.type]), styleInfo.styleFileName)
44  }
45  output = addJson(this, output, fileName, '')
46
47  const frag = parseFragment(source)
48  const nameSet = new Set()
49  if (frag.element) {
50    frag.element.forEach(item => {
51      let customElementName
52      if (!item.src) {
53        logWarn(this, [{
54          reason: `ERROR: The attribute 'src' must be set in the custom element.`,
55          line: item.node.__location.line,
56          column: item.node.__location.col
57        }])
58        return
59      }
60      if (!item.src.match(/\.hml$/)) {
61        item.src = item.src.concat('.hml')
62      }
63      const compResourcepath = path.join(resourcePath, '..', item.src)
64      if (!fs.existsSync(compResourcepath)) {
65        logWarn(this, [{
66          reason: `ERROR: The custom element '${compResourcepath}' can not be found.`,
67          line: item.node.__location.line,
68          column: item.node.__location.col
69        }])
70        return
71      }
72      if (!item.name) {
73        customElementName = path.parse(item.src).name.toLowerCase()
74      } else {
75        customElementName = item.name.toLowerCase()
76      }
77      if (nameSet.has(customElementName)) {
78        logWarn(this, [{
79          reason: `ERROR: The custom elements cannot have the same attribute 'name' or file name (case insensitive).`,
80          line: item.node.__location.line,
81          column: item.node.__location.col
82        }])
83        return
84      } else {
85        nameSet.add(customElementName)
86      }
87      const compFileName = compResourcepath.replace(path.extname(compResourcepath).toString(), '')
88      const elementLastName = path.basename(compResourcepath).replace(path.extname(compResourcepath).toString(), '')
89      output += `var card_element_template_${elementLastName} =` + getRequireString(this, jsonLoaders('template'),
90        compResourcepath + `?${customElementName}#${fileName}`)
91      const compStyleInfo = findStyleFile(compFileName)
92      if (compStyleInfo.extStyle == true) {
93        output += `var card_element_style_${elementLastName} =` +
94          getRequireString(this, jsonLoaders('style', customLang[compStyleInfo.type]),
95          compStyleInfo.styleFileName + `?${customElementName}#${fileName}`)
96      }
97      output = addJson(this, output, compFileName, `?${customElementName}#${fileName}`, elementLastName)
98    })
99  }
100  output = output + '\n//card_end'
101  return output
102}
103
104function findStyleFile (fileName) {
105  let extStyle = false
106  let styleFileName = fileName + '.css'
107  let type = 'css'
108  if (fs.existsSync(styleFileName)) {
109    extStyle = true
110    type = 'css'
111  } else {
112    styleFileName = fileName + '.less'
113    if (fs.existsSync(styleFileName)) {
114      extStyle = true
115      type = 'less'
116    } else {
117      styleFileName = fileName + '.sass'
118      if (fs.existsSync(styleFileName)) {
119        extStyle = true
120        type = 'sass'
121      } else {
122        styleFileName = fileName + '.scss'
123        if (fs.existsSync(styleFileName)) {
124          extStyle = true
125          type = 'sass'
126        } else {
127          extStyle = false
128        }
129      }
130    }
131  }
132  return {extStyle: extStyle, styleFileName: styleFileName, type: type}
133}
134
135function addJson(_this, output, fileName, query, elementLastName) {
136  const content = `${elementLastName ? 'var card_element_json_' + elementLastName : 'var card_json'} =`
137  if (fs.existsSync(fileName + '.json') && !fs.existsSync(fileName + '.js')) {
138    output += content + getRequireString(_this, jsonLoaders('json'), fileName + '.json' + query)
139  } else if (fs.existsSync(fileName + '.js') && !fs.existsSync(fileName + '.json')) {
140    logWarn(_this, [{
141      reason: `WARNING: The JS file '${fileName}.js' will be discarded in future version, ` +
142        `use the JSON file '${fileName}.json' instead.`,
143    }])
144    output += content + getRequireString(_this, jsonLoaders('json'), fileName + '.js' + query)
145  } else if (fs.existsSync(fileName + '.json') && fs.existsSync(fileName + '.js')) {
146    logWarn(_this, [{
147      reason: `WARNING: '${fileName}' cannot have the same name files '.json' and '.js', otherwise '.json' in default.`,
148    }])
149    output += content + getRequireString(_this, jsonLoaders('json'), fileName + '.json' + query)
150  }
151  return output
152}
153
154module.exports = loader