├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .prettierrc.js
├── README.md
├── app
├── app.js
├── app.json
├── app.scss
├── components
│ ├── one-component
│ │ ├── one-component.js
│ │ ├── one-component.json
│ │ ├── one-component.scss
│ │ └── one-component.wxml
│ ├── three-component
│ │ ├── three-component.js
│ │ ├── three-component.json
│ │ ├── three-component.scss
│ │ └── three-component.wxml
│ └── two-component
│ │ ├── two-component.js
│ │ ├── two-component.json
│ │ ├── two-component.scss
│ │ └── two-component.wxml
├── coverage
│ ├── clover.xml
│ ├── coverage-final.json
│ ├── lcov-report
│ │ ├── block-navigation.js
│ │ ├── favicon.png
│ │ ├── index.html
│ │ ├── prettify.js
│ │ ├── sort-arrow-sprite.png
│ │ ├── sorter.js
│ │ └── util.js.html
│ └── lcov.info
├── pages
│ ├── index
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.scss
│ │ └── index.wxml
│ └── one
│ │ ├── one.js
│ │ ├── one.json
│ │ ├── one.scss
│ │ └── one.wxml
├── project.config.json
├── sitemap.json
├── tests
│ └── index.test.js
└── utils
│ └── util.js
├── babel.config.js
├── cli
├── index.js
└── template
│ ├── components
│ ├── components.js
│ ├── components.json
│ ├── components.scss
│ └── components.wxml
│ └── pages
│ ├── pages.js
│ ├── pages.json
│ ├── pages.scss
│ └── pages.wxml
├── img
└── github.png
├── jest.config.js
├── package-lock.json
├── package.json
├── webpack.compress.js
├── webpack.config.js
└── yarn.lock
/.eslintignore:
--------------------------------------------------------------------------------
1 | !.eslintrc.js
2 | !.prettierrc.js
3 | !package.json
4 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | browser: true,
4 | es6: true
5 | },
6 | extends: 'eslint:recommended',
7 | parser: 'babel-eslint',
8 | parserOptions: {
9 | ecmaVersion: 6,
10 | sourceType: 'module'
11 | },
12 | rules: {
13 | 'no-undef': 0,
14 | 'no-unused-vars': 0
15 | }
16 | };
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.map
2 | .DS_Store
3 | .vscode/
4 | .idea/
5 | *.css
6 | *.wxss
7 | node_modules
8 | /app/assets/img
9 | /app/analyzer
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | eslintIntegration: true,
3 | // 一行最多 100 字符
4 | printWidth: 100,
5 | // 使用 4 个空格缩进
6 | tabWidth: 4,
7 | // 不使用缩进符,而使用空格
8 | useTabs: true,
9 | // 行尾需要有分号
10 | semi: true,
11 | // 使用单引号
12 | singleQuote: true,
13 | // 对象的 key 仅在必要时用引号
14 | quoteProps: 'as-needed',
15 | // jsx 不使用单引号,而使用双引号
16 | jsxSingleQuote: false,
17 | // 末尾不需要逗号
18 | trailingComma: 'none',
19 | // 大括号内的首尾需要空格
20 | bracketSpacing: true,
21 | // jsx 标签的反尖括号需要换行
22 | jsxBracketSameLine: false,
23 | // 箭头函数,只有一个参数的时候,也需要括号
24 | arrowParens: 'always',
25 | // 每个文件格式化的范围是文件的全部内容
26 | rangeStart: 0,
27 | rangeEnd: Infinity,
28 | // 不需要写文件开头的 @prettier
29 | requirePragma: false,
30 | // 不需要自动在文件开头插入 @prettier
31 | insertPragma: false,
32 | // 使用默认的折行标准
33 | proseWrap: 'preserve',
34 | // 根据显示样式决定 html 要不要折行
35 | htmlWhitespaceSensitivity: 'css',
36 | // 换行符使用 lf
37 | endOfLine: 'lf'
38 | };
39 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## 小程序开发现状:
2 |
3 | 1. 开发工具不好使用(无法热更新,编译缓慢);
4 | 2. 无法使用css预处理语言(Sass、Less),有些IDE的插件可以监听编译,但不同编辑器需要额外安装;
5 | 3. 无法使用工程化(图片自动压缩,文件监听编译等);
6 | 4.编码繁琐(创建一个页面,需要新建4个文件(.wxml、.js、.json、.wxss),每次新建都需要新建4次或者复制文件比较浪费时间);
7 | 5.团队多人协作,代码风格、使用的编辑器不一致;
8 |
9 | ## 技术选型:
10 |
11 | 在进行小程序项目启动,进行技术选型的时候,对市场上多个小程序框架进行了考虑:
12 |
13 | uni-app、mpVue、wepy、taro、 kbone
14 |
15 | 团队成员mpvue、wepy、uni-app都有实际的项目经验,且根据Github上的star数还有issue,最后决定回到到使用原生开发。
16 |
17 | ### 原因:
18 | 虽然框架有些很成熟,有工程化和跨端的解决方案,也有实际的上线项目,但考虑到后续一些支撑性的问题(维护,文档,坑等),在github上看了issue,有些已经没在维护了。
19 |
20 | 想着让项目持续迭代,不受第三方框架限制,保持稳健,最后决定使用原生,跟着官方的迭代升级,自己维护,引入前端工程化的思想,提高繁琐的流程以及开发效率。
21 |
22 | ## 引入工程化
23 |
24 | 基于Webpack4.x,自定义Webpack配置
25 |
26 | 1. scss编译为wxss:定义全局变量,使用公共的样式文件,提高css开发效率和可维护性;
27 |
28 | 2. 自动压缩图片资源 : 小程序对包大小有限制,压缩图片大小可以减少空间,加快页面加载;普通的图片压缩需要将图片上传到在线图片压缩网站,压缩完再保存下来,效率比较低。现在执行命令就可以自动压缩图片。
29 |
30 | ## 代码规范
31 |
32 | 1. eslint: 能在js运行前就识别一些基础的语法错误,减少不必要的小问题,提高调试效率;
33 |
34 | 2. husky、line-staged、prettier: 统一团队代码规范: 当执行代码提交到git仓库时,会将已改动文件的代码格式化统一规范的代码风格;
35 |
36 |
37 | ## 命令行创建页面和组件模板
38 |
39 | 1. 小程序每次新建页面或者组件,需要依赖4个文件(.wxml,.js,.wxss,.json)。只需要执行npm run create命令,会提示选择创建页面还是组件,选择完成输入页面或者组件的名字,会自动生成4个模板文件(.wxml,.js,json,.scss)到对应的目录
40 |
41 | ## 引入jest单元测试
42 |
43 | 1. 生成测试覆盖率
44 |
45 | ## 项目结构
46 |
47 | app -> 小程序程序的入口,使用微信开发者工具制定app目录
48 | cli -> 生pages和components的模板脚手架
49 | img -> 图片资源原文件
50 | .eslintignore
51 | .eslintrc.js
52 | .gitignore(忽略wxss的提交,多人和做改动,容易有冲突,将scss文件传到服务器就好了)
53 | .prettierrc.js(代码格式化风格配置)
54 | babel.config.js
55 | jest.config.js(单元测试配置文件)
56 | webpack.compress.js(指定入口图片资源文件,将图片压缩编译到小程序的资源目录)
57 | webpack.config.js -> (工程化入口文件,指定入口scss文件,监听文件变化,自动将scss编译为wxss)
58 | 项目使用的包文件
59 | webpack、babel、eslint: 转换、规范js
60 | chalk: console.log打印彩色颜色
61 | scss、css-loader: 编译scss
62 | figlet: 控制台显示字体样式
63 | husky,line-staged,prettier: 代码格式化相关
64 | jest、miniprogram-simulate: 单元测试
65 |
66 | ## 项目运行
67 |
68 | . 安装依赖
69 |
70 | npm install 或 yarn install
71 |
72 | . 编译scss
73 |
74 | npm run dev
75 |
76 | . 压缩图片
77 |
78 | npm run img
79 |
80 | . 单元测试
81 |
82 | npm run test(生成测试报告)
83 | npm run test:watch(监听测试文件改动--开发环境下使用)
84 |
85 |
86 |
87 | ## 其他思考
88 |
89 | 工程化的初衷就是为了减少重复性的操作,提高编码的效率和乐趣。
90 |
91 | JavaScript是弱类型语言,好处是灵活,坏处是太灵活(多人协作,维护别人写的代码就是很痛苦了)。
92 |
93 | 项目最主要的是稳健,可高度自定义拓展,不拘束于版本和地上那方,特别多人协作的团队,工程化能给团队带来更多的收益,后续也会考虑将TypeScript、Docker等其他好的方案引入项目。
94 |
--------------------------------------------------------------------------------
/app/app.js:
--------------------------------------------------------------------------------
1 | //app.js
2 | App({
3 | onLaunch: function () {
4 | // 展示本地存储能力
5 | var logs = wx.getStorageSync('logs') || [];
6 | logs.unshift(Date.now());
7 | wx.setStorageSync('logs', logs);
8 |
9 | // 登录
10 | wx.login({
11 | success: (res) => {
12 | // 发送 res.code 到后台换取 openId, sessionKey, unionId
13 | }
14 | });
15 | // 获取用户信息
16 | wx.getSetting({
17 | success: (res) => {
18 | if (res.authSetting['scope.userInfo']) {
19 | // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
20 | wx.getUserInfo({
21 | success: (res) => {
22 | // 可以将 res 发送给后台解码出 unionId
23 | this.globalData.userInfo = res.userInfo;
24 |
25 | // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
26 | // 所以此处加入 callback 以防止这种情况
27 | if (this.userInfoReadyCallback) {
28 | this.userInfoReadyCallback(res);
29 | }
30 | }
31 | });
32 | }
33 | }
34 | });
35 | },
36 | globalData: {
37 | userInfo: null
38 | }
39 | });
40 |
--------------------------------------------------------------------------------
/app/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages":[
3 | "pages/index/index"
4 | ],
5 | "window":{
6 | "backgroundTextStyle":"light",
7 | "navigationBarBackgroundColor": "#fff",
8 | "navigationBarTitleText": "Weixin",
9 | "navigationBarTextStyle":"black"
10 | },
11 | "style": "v2",
12 | "sitemapLocation": "sitemap.json"
13 | }
14 |
--------------------------------------------------------------------------------
/app/app.scss:
--------------------------------------------------------------------------------
1 | .container {
2 | height: 100%;
3 | display: flex;
4 | flex-direction: column;
5 | align-items: center;
6 | justify-content: space-between;
7 | padding: 200rpx 0;
8 | box-sizing: border-box;
9 | }
10 | .one{
11 | color:red;
12 | .two{
13 | color:blue;
14 | }
15 | }
--------------------------------------------------------------------------------
/app/components/one-component/one-component.js:
--------------------------------------------------------------------------------
1 | Component({
2 | // 组件的属性列表
3 | properties: {},
4 |
5 | // 组件的初始数据
6 | data: {},
7 |
8 | // 组件的生命周期
9 | lifetimes: {
10 | // 在组件实例刚刚被创建时执行
11 | created() {},
12 | // 在组件实例进入页面节点树时执行
13 | attached() {},
14 | // 在组件在视图层布局完成后执行
15 | ready() {},
16 | // 在组件实例被从页面节点树移除时执行
17 | detached() {}
18 | },
19 |
20 | // 组件的方法列表
21 | methods: {}
22 | });
23 |
--------------------------------------------------------------------------------
/app/components/one-component/one-component.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/app/components/one-component/one-component.scss:
--------------------------------------------------------------------------------
1 | .container{
2 |
3 | }
--------------------------------------------------------------------------------
/app/components/one-component/one-component.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/components/three-component/three-component.js:
--------------------------------------------------------------------------------
1 | Component({
2 | // 组件的属性列表
3 | properties: {},
4 |
5 | // 组件的初始数据
6 | data: {},
7 |
8 | // 组件的生命周期
9 | lifetimes: {
10 | // 在组件实例刚刚被创建时执行
11 | created() {},
12 | // 在组件实例进入页面节点树时执行
13 | attached() {},
14 | // 在组件在视图层布局完成后执行
15 | ready() {},
16 | // 在组件实例被从页面节点树移除时执行
17 | detached() {}
18 | },
19 |
20 | // 组件的方法列表
21 | methods: {}
22 | });
23 |
--------------------------------------------------------------------------------
/app/components/three-component/three-component.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/app/components/three-component/three-component.scss:
--------------------------------------------------------------------------------
1 | .container{
2 |
3 | }
--------------------------------------------------------------------------------
/app/components/three-component/three-component.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/components/two-component/two-component.js:
--------------------------------------------------------------------------------
1 | Component({
2 | // 组件的属性列表
3 | properties: {},
4 |
5 | // 组件的初始数据
6 | data: {},
7 |
8 | // 组件的生命周期
9 | lifetimes: {
10 | // 在组件实例刚刚被创建时执行
11 | created() {},
12 | // 在组件实例进入页面节点树时执行
13 | attached() {},
14 | // 在组件在视图层布局完成后执行
15 | ready() {},
16 | // 在组件实例被从页面节点树移除时执行
17 | detached() {}
18 | },
19 |
20 | // 组件的方法列表
21 | methods: {}
22 | });
23 |
--------------------------------------------------------------------------------
/app/components/two-component/two-component.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/app/components/two-component/two-component.scss:
--------------------------------------------------------------------------------
1 | .container{
2 |
3 | }
--------------------------------------------------------------------------------
/app/components/two-component/two-component.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/coverage/clover.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/coverage/coverage-final.json:
--------------------------------------------------------------------------------
1 | {"/Users/mac/Documents/github/miniprogram-cli/app/utils/util.js": {"path":"/Users/mac/Documents/github/miniprogram-cli/app/utils/util.js","statementMap":{"0":{"start":{"line":1,"column":12},"end":{"line":3,"column":1}},"1":{"start":{"line":2,"column":1},"end":{"line":2,"column":19}},"2":{"start":{"line":4,"column":0},"end":{"line":6,"column":2}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":1,"column":12},"end":{"line":1,"column":13}},"loc":{"start":{"line":1,"column":27},"end":{"line":3,"column":1}},"line":1}},"branchMap":{},"s":{"0":1,"1":2,"2":1},"f":{"0":2},"b":{},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"81008584390709ec51a22f155f55044ed3f431f2"}
2 | }
3 |
--------------------------------------------------------------------------------
/app/coverage/lcov-report/block-navigation.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | var jumpToCode = (function init() {
3 | // Classes of code we would like to highlight in the file view
4 | var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no'];
5 |
6 | // Elements to highlight in the file listing view
7 | var fileListingElements = ['td.pct.low'];
8 |
9 | // We don't want to select elements that are direct descendants of another match
10 | var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > `
11 |
12 | // Selecter that finds elements on the page to which we can jump
13 | var selector =
14 | fileListingElements.join(', ') +
15 | ', ' +
16 | notSelector +
17 | missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b`
18 |
19 | // The NodeList of matching elements
20 | var missingCoverageElements = document.querySelectorAll(selector);
21 |
22 | var currentIndex;
23 |
24 | function toggleClass(index) {
25 | missingCoverageElements.item(currentIndex).classList.remove('highlighted');
26 | missingCoverageElements.item(index).classList.add('highlighted');
27 | }
28 |
29 | function makeCurrent(index) {
30 | toggleClass(index);
31 | currentIndex = index;
32 | missingCoverageElements.item(index).scrollIntoView({
33 | behavior: 'smooth',
34 | block: 'center',
35 | inline: 'center'
36 | });
37 | }
38 |
39 | function goToPrevious() {
40 | var nextIndex = 0;
41 | if (typeof currentIndex !== 'number' || currentIndex === 0) {
42 | nextIndex = missingCoverageElements.length - 1;
43 | } else if (missingCoverageElements.length > 1) {
44 | nextIndex = currentIndex - 1;
45 | }
46 |
47 | makeCurrent(nextIndex);
48 | }
49 |
50 | function goToNext() {
51 | var nextIndex = 0;
52 |
53 | if (typeof currentIndex === 'number' && currentIndex < missingCoverageElements.length - 1) {
54 | nextIndex = currentIndex + 1;
55 | }
56 |
57 | makeCurrent(nextIndex);
58 | }
59 |
60 | return function jump(event) {
61 | switch (event.which) {
62 | case 78: // n
63 | case 74: // j
64 | goToNext();
65 | break;
66 | case 66: // b
67 | case 75: // k
68 | case 80: // p
69 | goToPrevious();
70 | break;
71 | }
72 | };
73 | })();
74 | window.addEventListener('keydown', jumpToCode);
75 |
--------------------------------------------------------------------------------
/app/coverage/lcov-report/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/czero1995/miniprogram-cli/e8fe5a7e82f87f0f21f87cb08b91b25833ad43a7/app/coverage/lcov-report/favicon.png
--------------------------------------------------------------------------------
/app/coverage/lcov-report/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Code coverage report for All files
7 |
8 |
9 |
10 |
11 |
12 |
17 |
18 |
19 |
20 |
21 |
22 |
All files
23 |
24 |
25 |
26 | 100%
27 | Statements
28 | 3/3
29 |
30 |
31 |
32 |
33 | 100%
34 | Branches
35 | 0/0
36 |
37 |
38 |
39 |
40 | 100%
41 | Functions
42 | 1/1
43 |
44 |
45 |
46 |
47 | 100%
48 | Lines
49 | 3/3
50 |
51 |
52 |
53 |
54 |
55 | Press n or j to go to the next uncovered block, b, p or k for the previous block.
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | File |
64 | |
65 | Statements |
66 | |
67 | Branches |
68 | |
69 | Functions |
70 | |
71 | Lines |
72 | |
73 |
74 |
75 |
76 | util.js |
77 |
78 |
79 | |
80 | 100% |
81 | 3/3 |
82 | 100% |
83 | 0/0 |
84 | 100% |
85 | 1/1 |
86 | 100% |
87 | 3/3 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
100 |
101 |
102 |
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/app/coverage/lcov-report/prettify.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | window.PR_SHOULD_USE_CONTINUATION = true;
3 | (function () {
4 | var h = ['break,continue,do,else,for,if,return,while'];
5 | var u = [
6 | h,
7 | 'auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile'
8 | ];
9 | var p = [
10 | u,
11 | 'catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof'
12 | ];
13 | var l = [
14 | p,
15 | 'alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where'
16 | ];
17 | var x = [
18 | p,
19 | 'abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient'
20 | ];
21 | var R = [
22 | x,
23 | 'as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var'
24 | ];
25 | var r =
26 | 'all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes';
27 | var w = [p, 'debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN'];
28 | var s =
29 | 'caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END';
30 | var I = [
31 | h,
32 | 'and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None'
33 | ];
34 | var f = [
35 | h,
36 | 'alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END'
37 | ];
38 | var H = [h, 'case,done,elif,esac,eval,fi,function,in,local,set,then,until'];
39 | var A = [l, R, w, s + I, f, H];
40 | var e = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;
41 | var C = 'str';
42 | var z = 'kwd';
43 | var j = 'com';
44 | var O = 'typ';
45 | var G = 'lit';
46 | var L = 'pun';
47 | var F = 'pln';
48 | var m = 'tag';
49 | var E = 'dec';
50 | var J = 'src';
51 | var P = 'atn';
52 | var n = 'atv';
53 | var N = 'nocode';
54 | var M =
55 | '(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*';
56 | function k(Z) {
57 | var ad = 0;
58 | var S = false;
59 | var ac = false;
60 | for (var V = 0, U = Z.length; V < U; ++V) {
61 | var ae = Z[V];
62 | if (ae.ignoreCase) {
63 | ac = true;
64 | } else {
65 | if (
66 | /[a-z]/i.test(ae.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi, ''))
67 | ) {
68 | S = true;
69 | ac = false;
70 | break;
71 | }
72 | }
73 | }
74 | var Y = { b: 8, t: 9, n: 10, v: 11, f: 12, r: 13 };
75 | function ab(ah) {
76 | var ag = ah.charCodeAt(0);
77 | if (ag !== 92) {
78 | return ag;
79 | }
80 | var af = ah.charAt(1);
81 | ag = Y[af];
82 | if (ag) {
83 | return ag;
84 | } else {
85 | if ('0' <= af && af <= '7') {
86 | return parseInt(ah.substring(1), 8);
87 | } else {
88 | if (af === 'u' || af === 'x') {
89 | return parseInt(ah.substring(2), 16);
90 | } else {
91 | return ah.charCodeAt(1);
92 | }
93 | }
94 | }
95 | }
96 | function T(af) {
97 | if (af < 32) {
98 | return (af < 16 ? '\\x0' : '\\x') + af.toString(16);
99 | }
100 | var ag = String.fromCharCode(af);
101 | if (ag === '\\' || ag === '-' || ag === '[' || ag === ']') {
102 | ag = '\\' + ag;
103 | }
104 | return ag;
105 | }
106 | function X(am) {
107 | var aq = am
108 | .substring(1, am.length - 1)
109 | .match(
110 | new RegExp(
111 | '\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]',
112 | 'g'
113 | )
114 | );
115 | var ak = [];
116 | var af = [];
117 | var ao = aq[0] === '^';
118 | for (var ar = ao ? 1 : 0, aj = aq.length; ar < aj; ++ar) {
119 | var ah = aq[ar];
120 | if (/\\[bdsw]/i.test(ah)) {
121 | ak.push(ah);
122 | } else {
123 | var ag = ab(ah);
124 | var al;
125 | if (ar + 2 < aj && '-' === aq[ar + 1]) {
126 | al = ab(aq[ar + 2]);
127 | ar += 2;
128 | } else {
129 | al = ag;
130 | }
131 | af.push([ag, al]);
132 | if (!(al < 65 || ag > 122)) {
133 | if (!(al < 65 || ag > 90)) {
134 | af.push([Math.max(65, ag) | 32, Math.min(al, 90) | 32]);
135 | }
136 | if (!(al < 97 || ag > 122)) {
137 | af.push([Math.max(97, ag) & ~32, Math.min(al, 122) & ~32]);
138 | }
139 | }
140 | }
141 | }
142 | af.sort(function (av, au) {
143 | return av[0] - au[0] || au[1] - av[1];
144 | });
145 | var ai = [];
146 | var ap = [NaN, NaN];
147 | for (var ar = 0; ar < af.length; ++ar) {
148 | var at = af[ar];
149 | if (at[0] <= ap[1] + 1) {
150 | ap[1] = Math.max(ap[1], at[1]);
151 | } else {
152 | ai.push((ap = at));
153 | }
154 | }
155 | var an = ['['];
156 | if (ao) {
157 | an.push('^');
158 | }
159 | an.push.apply(an, ak);
160 | for (var ar = 0; ar < ai.length; ++ar) {
161 | var at = ai[ar];
162 | an.push(T(at[0]));
163 | if (at[1] > at[0]) {
164 | if (at[1] + 1 > at[0]) {
165 | an.push('-');
166 | }
167 | an.push(T(at[1]));
168 | }
169 | }
170 | an.push(']');
171 | return an.join('');
172 | }
173 | function W(al) {
174 | var aj = al.source.match(
175 | new RegExp(
176 | '(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)',
177 | 'g'
178 | )
179 | );
180 | var ah = aj.length;
181 | var an = [];
182 | for (var ak = 0, am = 0; ak < ah; ++ak) {
183 | var ag = aj[ak];
184 | if (ag === '(') {
185 | ++am;
186 | } else {
187 | if ('\\' === ag.charAt(0)) {
188 | var af = +ag.substring(1);
189 | if (af && af <= am) {
190 | an[af] = -1;
191 | }
192 | }
193 | }
194 | }
195 | for (var ak = 1; ak < an.length; ++ak) {
196 | if (-1 === an[ak]) {
197 | an[ak] = ++ad;
198 | }
199 | }
200 | for (var ak = 0, am = 0; ak < ah; ++ak) {
201 | var ag = aj[ak];
202 | if (ag === '(') {
203 | ++am;
204 | if (an[am] === undefined) {
205 | aj[ak] = '(?:';
206 | }
207 | } else {
208 | if ('\\' === ag.charAt(0)) {
209 | var af = +ag.substring(1);
210 | if (af && af <= am) {
211 | aj[ak] = '\\' + an[am];
212 | }
213 | }
214 | }
215 | }
216 | for (var ak = 0, am = 0; ak < ah; ++ak) {
217 | if ('^' === aj[ak] && '^' !== aj[ak + 1]) {
218 | aj[ak] = '';
219 | }
220 | }
221 | if (al.ignoreCase && S) {
222 | for (var ak = 0; ak < ah; ++ak) {
223 | var ag = aj[ak];
224 | var ai = ag.charAt(0);
225 | if (ag.length >= 2 && ai === '[') {
226 | aj[ak] = X(ag);
227 | } else {
228 | if (ai !== '\\') {
229 | aj[ak] = ag.replace(/[a-zA-Z]/g, function (ao) {
230 | var ap = ao.charCodeAt(0);
231 | return '[' + String.fromCharCode(ap & ~32, ap | 32) + ']';
232 | });
233 | }
234 | }
235 | }
236 | }
237 | return aj.join('');
238 | }
239 | var aa = [];
240 | for (var V = 0, U = Z.length; V < U; ++V) {
241 | var ae = Z[V];
242 | if (ae.global || ae.multiline) {
243 | throw new Error('' + ae);
244 | }
245 | aa.push('(?:' + W(ae) + ')');
246 | }
247 | return new RegExp(aa.join('|'), ac ? 'gi' : 'g');
248 | }
249 | function a(V) {
250 | var U = /(?:^|\s)nocode(?:\s|$)/;
251 | var X = [];
252 | var T = 0;
253 | var Z = [];
254 | var W = 0;
255 | var S;
256 | if (V.currentStyle) {
257 | S = V.currentStyle.whiteSpace;
258 | } else {
259 | if (window.getComputedStyle) {
260 | S = document.defaultView.getComputedStyle(V, null).getPropertyValue('white-space');
261 | }
262 | }
263 | var Y = S && 'pre' === S.substring(0, 3);
264 | function aa(ab) {
265 | switch (ab.nodeType) {
266 | case 1:
267 | if (U.test(ab.className)) {
268 | return;
269 | }
270 | for (var ae = ab.firstChild; ae; ae = ae.nextSibling) {
271 | aa(ae);
272 | }
273 | var ad = ab.nodeName;
274 | if ('BR' === ad || 'LI' === ad) {
275 | X[W] = '\n';
276 | Z[W << 1] = T++;
277 | Z[(W++ << 1) | 1] = ab;
278 | }
279 | break;
280 | case 3:
281 | case 4:
282 | var ac = ab.nodeValue;
283 | if (ac.length) {
284 | if (!Y) {
285 | ac = ac.replace(/[ \t\r\n]+/g, ' ');
286 | } else {
287 | ac = ac.replace(/\r\n?/g, '\n');
288 | }
289 | X[W] = ac;
290 | Z[W << 1] = T;
291 | T += ac.length;
292 | Z[(W++ << 1) | 1] = ab;
293 | }
294 | break;
295 | }
296 | }
297 | aa(V);
298 | return { sourceCode: X.join('').replace(/\n$/, ''), spans: Z };
299 | }
300 | function B(S, U, W, T) {
301 | if (!U) {
302 | return;
303 | }
304 | var V = { sourceCode: U, basePos: S };
305 | W(V);
306 | T.push.apply(T, V.decorations);
307 | }
308 | var v = /\S/;
309 | function o(S) {
310 | var V = undefined;
311 | for (var U = S.firstChild; U; U = U.nextSibling) {
312 | var T = U.nodeType;
313 | V = T === 1 ? (V ? S : U) : T === 3 ? (v.test(U.nodeValue) ? S : V) : V;
314 | }
315 | return V === S ? undefined : V;
316 | }
317 | function g(U, T) {
318 | var S = {};
319 | var V;
320 | (function () {
321 | var ad = U.concat(T);
322 | var ah = [];
323 | var ag = {};
324 | for (var ab = 0, Z = ad.length; ab < Z; ++ab) {
325 | var Y = ad[ab];
326 | var ac = Y[3];
327 | if (ac) {
328 | for (var ae = ac.length; --ae >= 0; ) {
329 | S[ac.charAt(ae)] = Y;
330 | }
331 | }
332 | var af = Y[1];
333 | var aa = '' + af;
334 | if (!ag.hasOwnProperty(aa)) {
335 | ah.push(af);
336 | ag[aa] = null;
337 | }
338 | }
339 | ah.push(/[\0-\uffff]/);
340 | V = k(ah);
341 | })();
342 | var X = T.length;
343 | var W = function (ah) {
344 | var Z = ah.sourceCode,
345 | Y = ah.basePos;
346 | var ad = [Y, F];
347 | var af = 0;
348 | var an = Z.match(V) || [];
349 | var aj = {};
350 | for (var ae = 0, aq = an.length; ae < aq; ++ae) {
351 | var ag = an[ae];
352 | var ap = aj[ag];
353 | var ai = void 0;
354 | var am;
355 | if (typeof ap === 'string') {
356 | am = false;
357 | } else {
358 | var aa = S[ag.charAt(0)];
359 | if (aa) {
360 | ai = ag.match(aa[1]);
361 | ap = aa[0];
362 | } else {
363 | for (var ao = 0; ao < X; ++ao) {
364 | aa = T[ao];
365 | ai = ag.match(aa[1]);
366 | if (ai) {
367 | ap = aa[0];
368 | break;
369 | }
370 | }
371 | if (!ai) {
372 | ap = F;
373 | }
374 | }
375 | am = ap.length >= 5 && 'lang-' === ap.substring(0, 5);
376 | if (am && !(ai && typeof ai[1] === 'string')) {
377 | am = false;
378 | ap = J;
379 | }
380 | if (!am) {
381 | aj[ag] = ap;
382 | }
383 | }
384 | var ab = af;
385 | af += ag.length;
386 | if (!am) {
387 | ad.push(Y + ab, ap);
388 | } else {
389 | var al = ai[1];
390 | var ak = ag.indexOf(al);
391 | var ac = ak + al.length;
392 | if (ai[2]) {
393 | ac = ag.length - ai[2].length;
394 | ak = ac - al.length;
395 | }
396 | var ar = ap.substring(5);
397 | B(Y + ab, ag.substring(0, ak), W, ad);
398 | B(Y + ab + ak, al, q(ar, al), ad);
399 | B(Y + ab + ac, ag.substring(ac), W, ad);
400 | }
401 | }
402 | ah.decorations = ad;
403 | };
404 | return W;
405 | }
406 | function i(T) {
407 | var W = [],
408 | S = [];
409 | if (T.tripleQuotedStrings) {
410 | W.push([
411 | C,
412 | /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
413 | null,
414 | '\'"'
415 | ]);
416 | } else {
417 | if (T.multiLineStrings) {
418 | W.push([
419 | C,
420 | /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,
421 | null,
422 | '\'"`'
423 | ]);
424 | } else {
425 | W.push([
426 | C,
427 | /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,
428 | null,
429 | '"\''
430 | ]);
431 | }
432 | }
433 | if (T.verbatimStrings) {
434 | S.push([C, /^@\"(?:[^\"]|\"\")*(?:\"|$)/, null]);
435 | }
436 | var Y = T.hashComments;
437 | if (Y) {
438 | if (T.cStyleComments) {
439 | if (Y > 1) {
440 | W.push([j, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);
441 | } else {
442 | W.push([
443 | j,
444 | /^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,
445 | null,
446 | '#'
447 | ]);
448 | }
449 | S.push([
450 | C,
451 | /^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,
452 | null
453 | ]);
454 | } else {
455 | W.push([j, /^#[^\r\n]*/, null, '#']);
456 | }
457 | }
458 | if (T.cStyleComments) {
459 | S.push([j, /^\/\/[^\r\n]*/, null]);
460 | S.push([j, /^\/\*[\s\S]*?(?:\*\/|$)/, null]);
461 | }
462 | if (T.regexLiterals) {
463 | var X =
464 | '/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/';
465 | S.push(['lang-regex', new RegExp('^' + M + '(' + X + ')')]);
466 | }
467 | var V = T.types;
468 | if (V) {
469 | S.push([O, V]);
470 | }
471 | var U = ('' + T.keywords).replace(/^ | $/g, '');
472 | if (U.length) {
473 | S.push([z, new RegExp('^(?:' + U.replace(/[\s,]+/g, '|') + ')\\b'), null]);
474 | }
475 | W.push([F, /^\s+/, null, ' \r\n\t\xA0']);
476 | S.push(
477 | [G, /^@[a-z_$][a-z_$@0-9]*/i, null],
478 | [O, /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/, null],
479 | [F, /^[a-z_$][a-z_$@0-9]*/i, null],
480 | [
481 | G,
482 | new RegExp(
483 | '^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*',
484 | 'i'
485 | ),
486 | null,
487 | '0123456789'
488 | ],
489 | [F, /^\\[\s\S]?/, null],
490 | [L, /^.[^\s\w\.$@\'\"\`\/\#\\]*/, null]
491 | );
492 | return g(W, S);
493 | }
494 | var K = i({
495 | keywords: A,
496 | hashComments: true,
497 | cStyleComments: true,
498 | multiLineStrings: true,
499 | regexLiterals: true
500 | });
501 | function Q(V, ag) {
502 | var U = /(?:^|\s)nocode(?:\s|$)/;
503 | var ab = /\r\n?|\n/;
504 | var ac = V.ownerDocument;
505 | var S;
506 | if (V.currentStyle) {
507 | S = V.currentStyle.whiteSpace;
508 | } else {
509 | if (window.getComputedStyle) {
510 | S = ac.defaultView.getComputedStyle(V, null).getPropertyValue('white-space');
511 | }
512 | }
513 | var Z = S && 'pre' === S.substring(0, 3);
514 | var af = ac.createElement('LI');
515 | while (V.firstChild) {
516 | af.appendChild(V.firstChild);
517 | }
518 | var W = [af];
519 | function ae(al) {
520 | switch (al.nodeType) {
521 | case 1:
522 | if (U.test(al.className)) {
523 | break;
524 | }
525 | if ('BR' === al.nodeName) {
526 | ad(al);
527 | if (al.parentNode) {
528 | al.parentNode.removeChild(al);
529 | }
530 | } else {
531 | for (var an = al.firstChild; an; an = an.nextSibling) {
532 | ae(an);
533 | }
534 | }
535 | break;
536 | case 3:
537 | case 4:
538 | if (Z) {
539 | var am = al.nodeValue;
540 | var aj = am.match(ab);
541 | if (aj) {
542 | var ai = am.substring(0, aj.index);
543 | al.nodeValue = ai;
544 | var ah = am.substring(aj.index + aj[0].length);
545 | if (ah) {
546 | var ak = al.parentNode;
547 | ak.insertBefore(ac.createTextNode(ah), al.nextSibling);
548 | }
549 | ad(al);
550 | if (!ai) {
551 | al.parentNode.removeChild(al);
552 | }
553 | }
554 | }
555 | break;
556 | }
557 | }
558 | function ad(ak) {
559 | while (!ak.nextSibling) {
560 | ak = ak.parentNode;
561 | if (!ak) {
562 | return;
563 | }
564 | }
565 | function ai(al, ar) {
566 | var aq = ar ? al.cloneNode(false) : al;
567 | var ao = al.parentNode;
568 | if (ao) {
569 | var ap = ai(ao, 1);
570 | var an = al.nextSibling;
571 | ap.appendChild(aq);
572 | for (var am = an; am; am = an) {
573 | an = am.nextSibling;
574 | ap.appendChild(am);
575 | }
576 | }
577 | return aq;
578 | }
579 | var ah = ai(ak.nextSibling, 0);
580 | for (var aj; (aj = ah.parentNode) && aj.nodeType === 1; ) {
581 | ah = aj;
582 | }
583 | W.push(ah);
584 | }
585 | for (var Y = 0; Y < W.length; ++Y) {
586 | ae(W[Y]);
587 | }
588 | if (ag === (ag | 0)) {
589 | W[0].setAttribute('value', ag);
590 | }
591 | var aa = ac.createElement('OL');
592 | aa.className = 'linenums';
593 | var X = Math.max(0, (ag - 1) | 0) || 0;
594 | for (var Y = 0, T = W.length; Y < T; ++Y) {
595 | af = W[Y];
596 | af.className = 'L' + ((Y + X) % 10);
597 | if (!af.firstChild) {
598 | af.appendChild(ac.createTextNode('\xA0'));
599 | }
600 | aa.appendChild(af);
601 | }
602 | V.appendChild(aa);
603 | }
604 | function D(ac) {
605 | var aj = /\bMSIE\b/.test(navigator.userAgent);
606 | var am = /\n/g;
607 | var al = ac.sourceCode;
608 | var an = al.length;
609 | var V = 0;
610 | var aa = ac.spans;
611 | var T = aa.length;
612 | var ah = 0;
613 | var X = ac.decorations;
614 | var Y = X.length;
615 | var Z = 0;
616 | X[Y] = an;
617 | var ar, aq;
618 | for (aq = ar = 0; aq < Y; ) {
619 | if (X[aq] !== X[aq + 2]) {
620 | X[ar++] = X[aq++];
621 | X[ar++] = X[aq++];
622 | } else {
623 | aq += 2;
624 | }
625 | }
626 | Y = ar;
627 | for (aq = ar = 0; aq < Y; ) {
628 | var at = X[aq];
629 | var ab = X[aq + 1];
630 | var W = aq + 2;
631 | while (W + 2 <= Y && X[W + 1] === ab) {
632 | W += 2;
633 | }
634 | X[ar++] = at;
635 | X[ar++] = ab;
636 | aq = W;
637 | }
638 | Y = X.length = ar;
639 | var ae = null;
640 | while (ah < T) {
641 | var af = aa[ah];
642 | var S = aa[ah + 2] || an;
643 | var ag = X[Z];
644 | var ap = X[Z + 2] || an;
645 | var W = Math.min(S, ap);
646 | var ak = aa[ah + 1];
647 | var U;
648 | if (ak.nodeType !== 1 && (U = al.substring(V, W))) {
649 | if (aj) {
650 | U = U.replace(am, '\r');
651 | }
652 | ak.nodeValue = U;
653 | var ai = ak.ownerDocument;
654 | var ao = ai.createElement('SPAN');
655 | ao.className = X[Z + 1];
656 | var ad = ak.parentNode;
657 | ad.replaceChild(ao, ak);
658 | ao.appendChild(ak);
659 | if (V < S) {
660 | aa[ah + 1] = ak = ai.createTextNode(al.substring(W, S));
661 | ad.insertBefore(ak, ao.nextSibling);
662 | }
663 | }
664 | V = W;
665 | if (V >= S) {
666 | ah += 2;
667 | }
668 | if (V >= ap) {
669 | Z += 2;
670 | }
671 | }
672 | }
673 | var t = {};
674 | function c(U, V) {
675 | for (var S = V.length; --S >= 0; ) {
676 | var T = V[S];
677 | if (!t.hasOwnProperty(T)) {
678 | t[T] = U;
679 | } else {
680 | if (window.console) {
681 | console.warn('cannot override language handler %s', T);
682 | }
683 | }
684 | }
685 | }
686 | function q(T, S) {
687 | if (!(T && t.hasOwnProperty(T))) {
688 | T = /^\s*]*(?:>|$)/],
699 | [j, /^<\!--[\s\S]*?(?:-\->|$)/],
700 | ['lang-', /^<\?([\s\S]+?)(?:\?>|$)/],
701 | ['lang-', /^<%([\s\S]+?)(?:%>|$)/],
702 | [L, /^(?:<[%?]|[%?]>)/],
703 | ['lang-', /^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],
704 | ['lang-js', /^
89 |
94 |
95 |
96 |