内容简介:执行这个脚本的作用是:读取PostCSS 是一个允许使用
build:file
脚本的执行目的是生成包括 icon
, 入口文件
, i18n 国际化
, version
在内的文件, 内容为:
node build/bin/iconInit.js & node build/bin/build-entry.js & node build/bin/i18n.js & node build/bin/version.js 复制代码
node build/bin/iconInit.js
执行这个脚本的作用是:读取 packages/theme-chalk/src/icon.scss
文件, 对文件中的所有类似于 el-icon-close
这样的图标类名进行正则匹配,把所有符合正则的图标类名组成一个图标数组,最后把图标数写入到 example/icon.json
前提知识点
postcss
PostCSS 是一个允许使用 JS
插件转换样式的工具。 PostCSS
接受一个 CSS
文件并提供了一个 API 来分析、修改它的规则(通过把 CSS
转换成一个 AST
抽象语法树的方式。 PostCSS 更多说明
, PostCSS API
)。
postcss.parse
解析一个 css
文件, 返回文件中所包含的 css
节点。
<!-- icon.scss --> .el-icon-info:before { content: "\e61a"; } 复制代码
const postcss = require('postcss') const fs = require('fs') const fontFile = fs.readFileSync('./testIcon.scss', 'utf-8') const nodes = postcss.parse(fontFile).nodes console.log(nodes) 复制代码
打印出来的结果为:
[ Rule { raws: { before: '\r\n\r\n', between: ' ', semicolon: true, after: '\r\n' }, type: 'rule', nodes:[...], parent: Root { raws: [Object], type: 'root', nodes: [Circular], source: [Object] }, source: { start: [Object], input: [Object], end: [Object] }, selector: '[class^="el-icon-"], [class*=" el-icon-"]' } ] 复制代码
对上面的前提知识了解后,开始看执行的脚本代码逻辑
iconInit.js 逻辑分析
var postcss = require('postcss'); var fs = require('fs'); var path = require('path'); var fontFile = fs.readFileSync(path.resolve(__dirname, '../../packages/theme-chalk/src/icon.scss'), 'utf8'); var nodes = postcss.parse(fontFile).nodes; var classList = []; nodes.forEach((node) => { var selector = node.selector || ''; var reg = new RegExp(/\.el-icon-([^:]+):before/); var arr = selector.match(reg); if (arr && arr[1]) { classList.push(arr[1]); } }); fs.writeFile(path.resolve(__dirname, '../../examples/icon.json'), JSON.stringify(classList), () => {}); 复制代码
循环中的逻辑:
-
使用
forEach
遍历取到的所有css
文件节点。 -
首先拿到节点的
选择器
属性(包含class
类、id
)selector
。 -
使用正则表达式
/\.el-icon-([^:]+):before/
匹配所有满足Element iocn
命名规则的selector
。 这里使用 字符串的match
方法。它将返回所有匹配项。 -
如果匹配结果为真(
match
匹配不到结果时返回null
),并且匹配的第一个结果也为真时。 为了避免重复 只将第一个匹配结果放在classList
数组中。
最后将 生成的 classList
以字符串的形式写入到 examples/icon.js
node build/bin/build-entry.js
执行这个文件的目的是自动生成 整个 Elemnet
框架的入口文件。 这个入口文件需要暴露 一个 默认对象, 这个对象上包括 install
方法, install
方法中需要在传入的 Vue
参数上添加 全部的组件、指令、全局挂载的方法。除了 install
方法外,为了支持单组件的使用, 还需要在这个默认对象上面添加 全部的组件作为该对象的属性。
前提知识
json-templater/String
一种模板语言实现。可以预先写一个字符串模板,在这个字符串模板中可以存在 以 {{var}}
包裹的变量, 使用该方法可以将字符串中的变量替换为其他值。
var render = require('json-templater/string'); let template = `A {{platform}} UI Library ` render(template, { platform: 'Desktop'}); 复制代码
uppercamelcase
将给定字符串转换成 驼峰写法
os.EOL
一个字符串常量,定义操作系统相关的行末标志:
- \n 在 POSIX 系统上
- \r\n 在 Windows系统上
依赖文件分析
components.json
以每一个组件名为对象的 key
, 以该组件的所在目录为 value
组成的对象。
"pagination": "./packages/pagination/index.js", "dialog": "./packages/dialog/index.js", "autocomplete": "./packages/autocomplete/index.js", "dropdown": "./packages/dropdown/index.js", "dropdown-menu": "./packages/dropdown-menu/index.js", ...... 复制代码
build-entry.js
// 组件-组件地址 json 对象 var Components = require('../../components.json'); var fs = require('fs'); // 替换 json 模板中的变量的方法 var render = require('json-templater/string'); // 字符串转换为 驼峰写法 var uppercamelcase = require('uppercamelcase'); var path = require('path'); // 当前操作系统的 换行符 var endOfLine = require('os').EOL; // 将字符串文件模板输出的文件地址, 这个地址就是项目的入口文件的地址 var OUTPUT_PATH = path.join(__dirname, '../../src/index.js'); // 文件模板头部的 import 引用 字符串模板 var IMPORT_TEMPLATE = 'import {{name}} from \'../packages/{{package}}/index.js\';'; // 文件模板中的 component 的字符串模板 var INSTALL_COMPONENT_TEMPLATE = ' {{name}}'; // 整个文件模板中 主体字符串模板 里面有四个替代变量,分别是 include、 install、version、list var MAIN_TEMPLATE = `......` delete Components.font; var ComponentNames = Object.keys(Components); // 替换 include 的变量数组 var includeComponentTemplate = []; // 替换 install 的变量数组 var installTemplate = []; // 替换 list 的变量数组 var listTemplate = []; // 循环 component.json 中的 key 组成的对象 ComponentNames.forEach(name => { // 组件名 转换为 驼峰写法 var componentName = uppercamelcase(name); // include 变量数组中添加 变量替换后的 IMPORT_TEMPLATE 字符串 includeComponentTemplate.push(render(IMPORT_TEMPLATE, { name: componentName, package: name })); // install 变量数组中添加 变量替换后的 INSTALL_COMPONENT_TEMPLATE 字符串 这里排除 'Loading', 'MessageBox', 'Notification', 'Message' 是因为这几个组件将会全局挂载到 Vue 的实例上。 if (['Loading', 'MessageBox', 'Notification', 'Message'].indexOf(componentName) === -1) { installTemplate.push(render(INSTALL_COMPONENT_TEMPLATE, { name: componentName, component: name })); } // list 的变量数组 中添加 组件的 key 的驼峰写法的字符串 if (componentName !== 'Loading') listTemplate.push(` ${componentName}`); }) // 最终将 MAIN_TEMPLATE 模板中的变量进行替换,生成最终的 框架入口文件的 字符串模板 var template = render(MAIN_TEMPLATE, { include: includeComponentTemplate.join(endOfLine), install: installTemplate.join(',' + endOfLine), version: process.env.VERSION || require('../../package.json').version, list: listTemplate.join(',' + endOfLine) }); // 将生成的 字符串模板写入到 框架入口文件 fs.writeFileSync(OUTPUT_PATH, template); 复制代码
关于 MAIN_TEMPLATE
字符串模板的写法分析,可以看Element UI 项目分析
node build/bin/i18n.js
这个 文件中是通过循环已经配置好的 i18n
形式的数据字典, 对每一个数据字典中语种对象都生成一个 语种目录,在每一个目录中, 根据 模板引擎 生成 不同语种对应的模板。 之后 根据数据字典中的 pages
属性里面的配置,替换掉模板中的变量。 最后写入到 example/pages/
这样每一个语种都有一套对应的 .vue
代码。
依赖文件
page.json
这个文件里面配置了 i18n
的数据字典数组。
[ { "lang": "zh-CN", "pages": { "index": { }, "component": {}, "changelog": {}, "design": {}, "guide": {}, "nav": {}, "resource": {} } } ... ] 复制代码
i18n.js
var fs = require('fs'); var path = require('path'); var langConfig = require('../../examples/i18n/page.json'); langConfig.forEach(lang => { // 在../../examples/pages 文件夹下 读取 与 `lang.lang` (指 zh-CN、 en-US、 es ) 对应的文件信息, 如果抛出异常,说明该文件夹下没有改文件,就新建一个对应 `lang.lang` 的文件 try { fs.statSync(path.resolve(__dirname, `../../examples/pages/${ lang.lang }`)); } catch (e) { fs.mkdirSync(path.resolve(__dirname, `../../examples/pages/${ lang.lang }`)); } // pages 里面包含 index component changelog design guide nav resource Object.keys(lang.pages).forEach(page => { // 模板地址 var templatePath = path.resolve(__dirname, `../../examples/pages/template/${ page }.tpl`); // 输出地址 var outputPath = path.resolve(__dirname, `../../examples/pages/${ lang.lang }/${ page }.vue`); var content = fs.readFileSync(templatePath, 'utf8'); var pairs = lang.pages[page]; // 就是本次循环里的 page // 将 page 再次遍历, 并将 与 page 变量相对应的 模板中的 变量 替换成 page 对象中的 value Object.keys(pairs).forEach(key => { content = content.replace(new RegExp(`<%=\\s*${ key }\\s*>`, 'g'), pairs[key]); }); // 最终将 替换后的 模板写入到 输入地址 fs.writeFileSync(outputPath, content); }); }); 复制代码
node build/bin/version.js
这个文件是根据 命令行参数 process.env.VERSION
或者 package.json
中的 version
的值, 来生成 框架的版本对象,并最终在 examples
下生成 version.json
文件
var fs = require('fs'); var path = require('path'); var version = process.env.VERSION || require('../../package.json').version; var content = { '1.4.13': '1.4', '2.0.11': '2.0', '2.1.0': '2.1', '2.2.2': '2.2', '2.3.9': '2.3' }; if (!content[version]) content[version] = '2.4'; fs.writeFileSync(path.resolve(__dirname, '../../examples/versions.json'), JSON.stringify(content)); 复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 使用动态分析技术分析 Java
- 使用动态分析技术分析 Java
- 案例分析:如何进行需求分析?
- 深度分析ConcurrentHashMap原理分析
- 如何分析“数据分析师”的岗位?
- EOS源码分析(3)案例分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Game Engine Architecture, Second Edition
Jason Gregory / A K Peters/CRC Press / 2014-8-15 / USD 69.95
A 2010 CHOICE outstanding academic title, this updated book covers the theory and practice of game engine software development. It explains practical concepts and techniques used by real game studios,......一起来看看 《Game Engine Architecture, Second Edition》 这本书的介绍吧!
URL 编码/解码
URL 编码/解码
html转js在线工具
html转js在线工具