mirror of
https://gitee.com/openharmony/third_party_weex-loader
synced 2024-11-22 23:10:17 +00:00
Signed-off-by: zhongjianfei <zhongjianfei@huawei.com>
This commit is contained in:
parent
159b76f8b0
commit
1957db76ec
13
CHANGELOG.md
Normal file
13
CHANGELOG.md
Normal file
@ -0,0 +1,13 @@
|
||||
# change logs
|
||||
|
||||
## v0.3.2/v0.3.3
|
||||
|
||||
- Fix the path of babel-plugins
|
||||
|
||||
## v0.3.1
|
||||
|
||||
- Fix defined a component repeatly.
|
||||
|
||||
## v0.3.0
|
||||
|
||||
- A new loader for weex! The features are amazing!
|
201
LICENSE
Normal file
201
LICENSE
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2019 Apache Incubator-Weex
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
5
NOTICE
Normal file
5
NOTICE
Normal file
@ -0,0 +1,5 @@
|
||||
Apache Weex (Incubating)
|
||||
Copyright 2019 The Apache Software Foundation
|
||||
|
||||
This product includes software developed at
|
||||
The Apache Software Foundation (http://www.apache.org/).
|
11
README.OpenSource
Normal file
11
README.OpenSource
Normal file
@ -0,0 +1,11 @@
|
||||
[
|
||||
{
|
||||
"Name": "weex-loader",
|
||||
"License": "Apache-2.0",
|
||||
"License File": "NOTICE",
|
||||
"Version Number": " 0.7.12",
|
||||
"Owner": "sunbingxin@huawei.com",
|
||||
"Upstream URL": "https://github.com/apache/weex-loader.git",
|
||||
"Description": "a webpack loader for weex."
|
||||
}
|
||||
]
|
7
circle.yml
Normal file
7
circle.yml
Normal file
@ -0,0 +1,7 @@
|
||||
machine:
|
||||
node:
|
||||
version: 4
|
||||
|
||||
test:
|
||||
override:
|
||||
- npm run build
|
3
deps/weex-scripter/.gitignore
vendored
Normal file
3
deps/weex-scripter/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
node_modules
|
||||
coverage
|
||||
.DS_Store
|
31
deps/weex-scripter/.jscsrc
vendored
Normal file
31
deps/weex-scripter/.jscsrc
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"preset": "node-style-guide",
|
||||
|
||||
"disallowKeywordsOnNewLine": [],
|
||||
"disallowMultipleVarDecl": {"allExcept": ["undefined"]},
|
||||
"disallowSemicolons": true,
|
||||
"requireCapitalizedComments": null,
|
||||
|
||||
"requireCurlyBraces": [
|
||||
"if",
|
||||
"else",
|
||||
"for",
|
||||
"while",
|
||||
"do",
|
||||
"try",
|
||||
"catch"
|
||||
],
|
||||
|
||||
"disallowSpacesInFunction": null,
|
||||
"disallowSpacesInNamedFunctionExpression": {
|
||||
"beforeOpeningRoundBrace": true
|
||||
},
|
||||
"requireSpacesInAnonymousFunctionExpression": {
|
||||
"beforeOpeningRoundBrace": true
|
||||
},
|
||||
|
||||
"disallowSpaceBeforeComma": true,
|
||||
"requireCommaBeforeLineBreak": true,
|
||||
"disallowTrailingComma": true,
|
||||
"requireTrailingComma": null
|
||||
}
|
21
deps/weex-scripter/LICENSE
vendored
Normal file
21
deps/weex-scripter/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2015-present, Weex Team
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
7
deps/weex-scripter/NOTICE
vendored
Normal file
7
deps/weex-scripter/NOTICE
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
Weex
|
||||
Copyright 2016 Alibaba Group
|
||||
|
||||
This product includes software developed at Alibaba Group. (http://www.alibabagroup.com)
|
||||
|
||||
This product contains software (https://github.com/marcuswestin/require) developed
|
||||
by Marcus Westin, licensed under the MIT License.
|
21
deps/weex-scripter/README.md
vendored
Normal file
21
deps/weex-scripter/README.md
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# Weex `<script>` Transformer
|
||||
|
||||
[![NPM version][npm-image]][npm-url]
|
||||
[![Build status][circle-image]][circle-url]
|
||||
[![Downloads][downloads-image]][downloads-url]
|
||||
|
||||
[npm-image]: https://img.shields.io/npm/v/weex-scripter.svg?style=flat-square
|
||||
[npm-url]: https://npmjs.org/package/weex-scripter
|
||||
[circle-image]: https://circleci.com/gh/weexteam/weex-scripter.svg?style=svg
|
||||
[circle-url]: https://circleci.com/gh/weexteam/weex-scripter/tree/master
|
||||
[downloads-image]: https://img.shields.io/npm/dm/weex-scripter.svg?style=flat-square
|
||||
[downloads-url]: https://npmjs.org/package/weex-scripter
|
||||
|
||||
transform JavaScript
|
||||
|
||||
## API
|
||||
|
||||
- `fix(code)`: automatically add `data: {function () {return {...}}}` to init component data from `data: {...}`
|
||||
- `parseAndReplaceRequire(code)`: parse third party js required in `<script>`, return the modified code and collect requires
|
||||
* note that `require` is automatically changed to `browserifyRequire` because of the built-in `require` in `js-framework`
|
||||
- `getBundle(requires)`: bundle all the third party js required in `<script>` by using `browserify`
|
3
deps/weex-scripter/circle.yml
vendored
Normal file
3
deps/weex-scripter/circle.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
machine:
|
||||
node:
|
||||
version: 4.2.1
|
25
deps/weex-scripter/gulpfile.js
vendored
Normal file
25
deps/weex-scripter/gulpfile.js
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
var gulp = require('gulp')
|
||||
var jscs = require('gulp-jscs')
|
||||
var mocha = require('gulp-mocha')
|
||||
|
||||
gulp.task('default', ['test'], function() {
|
||||
console.log('done')
|
||||
})
|
||||
|
||||
gulp.task('watch', function () {
|
||||
return gulp.watch('**/*.js', ['test'])
|
||||
})
|
||||
|
||||
gulp.task('test', ['jscs', 'mocha'], function () {
|
||||
console.log('test done')
|
||||
})
|
||||
|
||||
gulp.task('mocha', function () {
|
||||
return gulp.src([
|
||||
'test/*.js'
|
||||
]).pipe(mocha())
|
||||
})
|
||||
|
||||
gulp.task('jscs', function () {
|
||||
return gulp.src('**/*.js').pipe(jscs())
|
||||
})
|
8
deps/weex-scripter/index.js
vendored
Normal file
8
deps/weex-scripter/index.js
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
var fixer = require('./lib/fix')
|
||||
var requireParse = require('./lib/require-parse')
|
||||
var requireBundle = require('./lib/require-bundle')
|
||||
|
||||
exports.fix = fixer.fix
|
||||
exports.formatWhenFix = fixer.formatWhenFix
|
||||
exports.parseAndReplaceRequire = requireParse.parseAndReplaceRequire
|
||||
exports.getBundle = requireBundle.getBundle
|
19
deps/weex-scripter/lib/LICENSE
vendored
Normal file
19
deps/weex-scripter/lib/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2011 Marcus Westin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
174
deps/weex-scripter/lib/fix.js
vendored
Normal file
174
deps/weex-scripter/lib/fix.js
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
var esprima = require('esprima')
|
||||
var escodegen = require('escodegen')
|
||||
|
||||
// code sample of hacking old script
|
||||
;({
|
||||
"type": "Program",
|
||||
"body": [
|
||||
{
|
||||
"type": "ExpressionStatement",
|
||||
"expression": {
|
||||
"type": "AssignmentExpression",
|
||||
"operator": "=",
|
||||
"left": {
|
||||
"type": "MemberExpression",
|
||||
"computed": false,
|
||||
"object": {
|
||||
"type": "Identifier",
|
||||
"name": "module"
|
||||
},
|
||||
"property": {
|
||||
"type": "Identifier",
|
||||
"name": "exports"
|
||||
}
|
||||
},
|
||||
"right": {
|
||||
"type": "ObjectExpression",
|
||||
"properties": [
|
||||
{
|
||||
"type": "Property",
|
||||
"key": {
|
||||
"type": "Identifier",
|
||||
"name": "data"
|
||||
},
|
||||
"computed": false,
|
||||
"value": {
|
||||
// "type": "FunctionExpression",
|
||||
// "id": null,
|
||||
// "params": [],
|
||||
// "defaults": [],
|
||||
// "body": {
|
||||
// "type": "BlockStatement",
|
||||
// "body": [
|
||||
// {
|
||||
// "type": "ReturnStatement",
|
||||
// "argument": {
|
||||
"type": "ObjectExpression",
|
||||
"properties": []
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// "generator": false,
|
||||
// "expression": false
|
||||
},
|
||||
"kind": "init",
|
||||
"method": false,
|
||||
"shorthand": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"sourceType": "script"
|
||||
})
|
||||
|
||||
var LEFT_MODULE_EXPORTS_AST = {
|
||||
"type": "MemberExpression",
|
||||
"computed": false,
|
||||
"object": {
|
||||
"type": "Identifier",
|
||||
"name": "module"
|
||||
},
|
||||
"property": {
|
||||
"type": "Identifier",
|
||||
"name": "exports"
|
||||
}
|
||||
}
|
||||
|
||||
function removeAllLoc(ast) {
|
||||
ast = JSON.parse(JSON.stringify(ast))
|
||||
function remove(o) {
|
||||
if (Array.isArray(o)) {
|
||||
o.forEach(remove)
|
||||
}
|
||||
else if (typeof o === 'object') {
|
||||
for (var i in o) {
|
||||
if (i === 'loc') {
|
||||
delete o[i]
|
||||
}
|
||||
if (i === 'range') {
|
||||
delete o[i]
|
||||
}
|
||||
else {
|
||||
if (typeof o[i] === 'object') {
|
||||
remove(o[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
remove(ast)
|
||||
return ast
|
||||
}
|
||||
|
||||
function findDataValue(ast) {
|
||||
var exp, left, right, dataValue
|
||||
if (ast && ast.body && ast.body.length) {
|
||||
ast.body.forEach(function (bodyItem) {
|
||||
if (bodyItem.type === 'ExpressionStatement') {
|
||||
exp = bodyItem.expression
|
||||
if (exp.type === 'AssignmentExpression' && exp.operator === '=') {
|
||||
left = removeAllLoc(exp.left || {})
|
||||
if (JSON.stringify(left) === JSON.stringify(LEFT_MODULE_EXPORTS_AST)) {
|
||||
right = exp.right
|
||||
if (right.type === 'ObjectExpression') {
|
||||
right.properties.some(function (prop) {
|
||||
if (prop.type === 'Property' && prop.key && prop.key.name === 'data') {
|
||||
if (prop.value && prop.value.type === 'ObjectExpression') {
|
||||
dataValue = prop
|
||||
return true
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return dataValue
|
||||
}
|
||||
|
||||
function convertValueAst(value) {
|
||||
var data = {
|
||||
type: "FunctionExpression",
|
||||
id: null,
|
||||
params: [],
|
||||
defaults: [],
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
body: [
|
||||
{
|
||||
type: "ReturnStatement",
|
||||
argument: value
|
||||
}
|
||||
]
|
||||
},
|
||||
generator: false,
|
||||
expression: false
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
function format(code, needCodegen) {
|
||||
var ast = esprima.parse(code)
|
||||
var prop = findDataValue(ast)
|
||||
|
||||
if (prop) {
|
||||
prop.value = convertValueAst(prop.value)
|
||||
needCodegen = true
|
||||
}
|
||||
|
||||
return needCodegen ? escodegen.generate(ast) : code
|
||||
}
|
||||
|
||||
function formatBetter(code) {
|
||||
esprima.parse(code, {range: true})
|
||||
|
||||
return code
|
||||
}
|
||||
|
||||
exports.fix = formatBetter
|
||||
exports.formatWhenFix = format
|
28
deps/weex-scripter/lib/require-bundle.js
vendored
Normal file
28
deps/weex-scripter/lib/require-bundle.js
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
var path = require('path')
|
||||
var execSync = require('child_process').execSync
|
||||
var resolveBin = require('resolve-bin')
|
||||
|
||||
function replaceRequire(code) {
|
||||
var count = 0
|
||||
var hasRequire = false
|
||||
code = code.replace(/require/g, function ($0) {
|
||||
hasRequire = true
|
||||
return count++ < 5 ? 'browserifyRequire' : $0
|
||||
})
|
||||
if (hasRequire) {
|
||||
code = 'var ' + code
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
function getBundle(requires) {
|
||||
var cmd = '"' + resolveBin.sync('browserify') + '"'
|
||||
Object.keys(requires).forEach(function (key) {
|
||||
cmd += ' -r ' + '"' + requires[key] + ':' + key + '"'
|
||||
})
|
||||
var bundleCode = execSync(cmd)
|
||||
bundleCode = replaceRequire(bundleCode.toString())
|
||||
return bundleCode
|
||||
}
|
||||
|
||||
exports.getBundle = getBundle
|
98
deps/weex-scripter/lib/require-parse.js
vendored
Normal file
98
deps/weex-scripter/lib/require-parse.js
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
var path = require('path')
|
||||
var fs = require('fs')
|
||||
var md5 = require('md5')
|
||||
var existsSync = fs.existsSync || path.existsSync
|
||||
|
||||
var nodePaths = process.env.NODE_PATH ? process.env.NODE_PATH.split(':') : []
|
||||
var cwd = process.cwd()
|
||||
nodePaths.push(cwd)
|
||||
|
||||
function resolvePath(searchPath, pathBase) {
|
||||
if (searchPath[0] === '.') {
|
||||
// relative path, e.g. require("./foo")
|
||||
return findModuleMain(path.resolve(pathBase, searchPath))
|
||||
}
|
||||
|
||||
// npm-style path, e.g. require("npm").
|
||||
// Climb parent directories in search for "node_modules"
|
||||
var modulePath = findModuleMain(path.resolve(pathBase, 'node_modules', searchPath))
|
||||
if (modulePath) {
|
||||
return modulePath
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
function resolveRequire(rawPath, currentPath) {
|
||||
var resolvedPath = resolvePath(rawPath, path.dirname(currentPath))
|
||||
|
||||
if (!resolvedPath && rawPath[0] !== '.' && rawPath[0] !== '/') {
|
||||
for (var i = 0; i < nodePaths.length; i++) {
|
||||
resolvedPath = findModuleMain(path.resolve(nodePaths[i], rawPath))
|
||||
/* istanbul ignore if */
|
||||
if (resolvedPath) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resolvedPath
|
||||
}
|
||||
|
||||
function findModuleMain(absModulePath) {
|
||||
var foundPath = ''
|
||||
function attempt(aPath) {
|
||||
if (foundPath) {
|
||||
return
|
||||
}
|
||||
if (existsSync(aPath)) {
|
||||
foundPath = aPath
|
||||
}
|
||||
}
|
||||
if (path.extname(absModulePath) === '.js') {
|
||||
absModulePath = absModulePath.replace(/\..+/, '')
|
||||
}
|
||||
|
||||
attempt(absModulePath + '.js')
|
||||
try {
|
||||
var pkg = JSON.parse(fs.readFileSync(absModulePath + '/package.json').toString())
|
||||
attempt(path.resolve(absModulePath, pkg.main + '.js'))
|
||||
attempt(path.resolve(absModulePath, pkg.main))
|
||||
} catch (e) {}
|
||||
attempt(absModulePath + '/index.js')
|
||||
|
||||
return foundPath
|
||||
}
|
||||
|
||||
var REQUIRE_REGEXP = /require\s*\(['"]([\w\/\.-]*)['"]\)/g // do not contain `@weex-module` and `@weex-component`
|
||||
|
||||
function parseAndReplaceRequire(code, curPath) {
|
||||
curPath = curPath || '.'
|
||||
var requires = {}
|
||||
var log = []
|
||||
code = code.replace(REQUIRE_REGEXP, function ($0, $1) {
|
||||
var subModulePath
|
||||
|
||||
subModulePath = resolveRequire(path.resolve(cwd, curPath, $1), '.')
|
||||
if (!subModulePath) {
|
||||
subModulePath = resolveRequire($1, '.')
|
||||
}
|
||||
|
||||
if (!subModulePath) {
|
||||
log.push({reason: 'ERROR: Cannot find required module "' + $1 + '"'})
|
||||
return $0
|
||||
}
|
||||
else {
|
||||
var md5Path = md5(subModulePath)
|
||||
requires[md5Path] = subModulePath
|
||||
return 'browserifyRequire("' + md5Path + '")'
|
||||
}
|
||||
})
|
||||
return {
|
||||
code: code,
|
||||
requires: requires,
|
||||
log: log
|
||||
}
|
||||
}
|
||||
|
||||
exports.parseAndReplaceRequire = parseAndReplaceRequire
|
35
deps/weex-scripter/package.json
vendored
Normal file
35
deps/weex-scripter/package.json
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "weex-scripter",
|
||||
"version": "0.1.6",
|
||||
"description": "Weex <script> transformer",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "gulp test && npm run cover",
|
||||
"cover": "node node_modules/isparta/bin/isparta cover node_modules/gulp-mocha/node_modules/.bin/_mocha -- --reporter dot"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/weexteam/weex-scripter.git"
|
||||
},
|
||||
"keywords": [
|
||||
"weex"
|
||||
],
|
||||
"author": "songsiqi <songsiqi2006@126.com>",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"browserify": "~13.0.0",
|
||||
"escodegen": "~1.7.1",
|
||||
"esprima": "~2.7.0",
|
||||
"md5": "~2.1.0",
|
||||
"resolve-bin": "^0.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "~3.4.1",
|
||||
"gulp": "~3.9.0",
|
||||
"gulp-jscs": "~3.0.2",
|
||||
"gulp-mocha": "~2.2.0",
|
||||
"sinon": "~1.17.2",
|
||||
"sinon-chai": "~2.8.0",
|
||||
"isparta": "~4.0.0"
|
||||
}
|
||||
}
|
5
deps/weex-scripter/test/bundle/a.js
vendored
Normal file
5
deps/weex-scripter/test/bundle/a.js
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
var b = require('./b')
|
||||
|
||||
exports.getA = function () {
|
||||
return 'a' + b.getB()
|
||||
}
|
3
deps/weex-scripter/test/bundle/b.js
vendored
Normal file
3
deps/weex-scripter/test/bundle/b.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
exports.getB = function () {
|
||||
return 'b'
|
||||
}
|
4
deps/weex-scripter/test/bundle/c.js
vendored
Normal file
4
deps/weex-scripter/test/bundle/c.js
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
var c = ' require'
|
||||
exports.getC = function () {
|
||||
return 'c' + c
|
||||
}
|
33
deps/weex-scripter/test/fix.js
vendored
Normal file
33
deps/weex-scripter/test/fix.js
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
var chai = require('chai')
|
||||
var sinon = require('sinon')
|
||||
var sinonChai = require('sinon-chai')
|
||||
var expect = chai.expect
|
||||
chai.use(sinonChai)
|
||||
|
||||
var fixer = require('../lib/fix')
|
||||
|
||||
describe('fix', function () {
|
||||
it('old fix method: ast hack and re-generate', function () {
|
||||
expect(fixer.formatWhenFix('module.exports = {data: {a: 1}}')).
|
||||
eql('module.exports = {\n data: function () {\n return { a: 1 };\n }\n};')
|
||||
expect(fixer.formatWhenFix('module.exports = {data: function () {return {a: 1}}}')).
|
||||
eql('module.exports = {data: function () {return {a: 1}}}')
|
||||
})
|
||||
|
||||
it('new fix method: loc-based hack', function () {
|
||||
expect(fixer.fix('module.exports = {data: {a: 1}}')).
|
||||
eql('module.exports = {data: function () {return {a: 1}}}')
|
||||
expect(fixer.fix('module.exports = {data: function () {return {a: 1}}}')).
|
||||
eql('module.exports = {data: function () {return {a: 1}}}')
|
||||
})
|
||||
|
||||
it('fix code with multi lines', function () {
|
||||
var result = fixer.fix('module.exports = {\n data: {a: 1}}')
|
||||
expect(result).eql('module.exports = {\n data: function () {return {a: 1}}}')
|
||||
})
|
||||
|
||||
it('fix code with other declarations', function () {
|
||||
var result = fixer.fix('require("./b.wx")\n\nvar c = require("./lib/c")\n\nmodule.exports = {\n data: {\n text: "hello " + c.name\n }\n};')
|
||||
expect(result).eql('require("./b.wx")\n\nvar c = require("./lib/c")\n\nmodule.exports = {\n data: function () {return {\n text: "hello " + c.name\n }}\n};')
|
||||
})
|
||||
})
|
40
deps/weex-scripter/test/require-bundle.js
vendored
Normal file
40
deps/weex-scripter/test/require-bundle.js
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
var chai = require('chai')
|
||||
var sinon = require('sinon')
|
||||
var sinonChai = require('sinon-chai')
|
||||
var expect = chai.expect
|
||||
chai.use(sinonChai)
|
||||
|
||||
var md5 = require('md5')
|
||||
var getBundle = require('../lib/require-bundle').getBundle
|
||||
|
||||
|
||||
describe('bundle of 3rd party js', function () {
|
||||
it('one entry file', function () {
|
||||
var requiresObj = {}
|
||||
var absolutePath = path.join(__dirname, 'bundle/a.js')
|
||||
var md5Path = md5(absolutePath)
|
||||
requiresObj[md5Path] = absolutePath
|
||||
|
||||
var outputBundleCode = getBundle(requiresObj)
|
||||
var evalCode = outputBundleCode + '; var aModule = browserifyRequire("' + md5Path + '"); aModule.getA();'
|
||||
expect(eval(evalCode)).eql('ab')
|
||||
})
|
||||
|
||||
it('multiple entry file', function () {
|
||||
var requiresObj = {}
|
||||
var absolutePathA = path.join(__dirname, 'bundle/a.js')
|
||||
var md5PathA = md5(absolutePathA)
|
||||
requiresObj[md5PathA] = absolutePathA
|
||||
var absolutePathC = path.join(__dirname, 'bundle/c.js')
|
||||
var md5PathC = md5(absolutePathC)
|
||||
requiresObj[md5PathC] = absolutePathC
|
||||
|
||||
var outputBundleCode = getBundle(requiresObj)
|
||||
var evalCodeA = outputBundleCode + '; var aModule = browserifyRequire("' + md5PathA + '"); aModule.getA();'
|
||||
var evalCodeC = outputBundleCode + '; var cModule = browserifyRequire("' + md5PathC + '"); cModule.getC();'
|
||||
expect(eval(evalCodeA)).eql('ab')
|
||||
expect(eval(evalCodeC)).eql('c require')
|
||||
})
|
||||
})
|
136
deps/weex-scripter/test/require-parse.js
vendored
Normal file
136
deps/weex-scripter/test/require-parse.js
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
var path = require('path')
|
||||
var chai = require('chai')
|
||||
var sinon = require('sinon')
|
||||
var sinonChai = require('sinon-chai')
|
||||
var expect = chai.expect
|
||||
chai.use(sinonChai)
|
||||
|
||||
var md5 = require('md5')
|
||||
var parseAndReplaceRequire = require('../lib/require-parse').parseAndReplaceRequire
|
||||
|
||||
|
||||
describe('parse and replace require 3rd party js', function () {
|
||||
it('implicit node_modules', function () {
|
||||
var code = 'var a = require("md5");'
|
||||
var absolutePath = path.join(__dirname, '../node_modules/md5/md5.js')
|
||||
var md5Path = md5(absolutePath)
|
||||
var expected = {
|
||||
code: 'var a = browserifyRequire("' + md5Path + '");',
|
||||
requires: {},
|
||||
log: []
|
||||
}
|
||||
expected.requires[md5Path] = absolutePath
|
||||
expect(parseAndReplaceRequire(code)).eql(expected)
|
||||
})
|
||||
|
||||
it('explicit node_modules', function () {
|
||||
var code = 'var a = require("./node_modules/md5");'
|
||||
var absolutePath = path.join(__dirname, '../node_modules/md5/md5.js')
|
||||
var md5Path = md5(absolutePath)
|
||||
var expected = {
|
||||
code: 'var a = browserifyRequire("' + md5Path + '");',
|
||||
requires: {},
|
||||
log: []
|
||||
}
|
||||
expected.requires[md5Path] = absolutePath
|
||||
expect(parseAndReplaceRequire(code)).eql(expected)
|
||||
})
|
||||
|
||||
it('current directory with no extname', function () {
|
||||
var code = 'var a = require("./lib/fix");'
|
||||
var absolutePath = path.join(__dirname, '../lib/fix.js')
|
||||
var md5Path = md5(absolutePath)
|
||||
var expected = {
|
||||
code: 'var a = browserifyRequire("' + md5Path + '");',
|
||||
requires: {},
|
||||
log: []
|
||||
}
|
||||
expected.requires[md5Path] = absolutePath
|
||||
expect(parseAndReplaceRequire(code)).eql(expected)
|
||||
})
|
||||
|
||||
it('current directory with extname', function () {
|
||||
var code = 'var a = require("./lib/fix.js");'
|
||||
var absolutePath = path.join(__dirname, '../lib/fix.js')
|
||||
var md5Path = md5(absolutePath)
|
||||
var expected = {
|
||||
code: 'var a = browserifyRequire("' + md5Path + '");',
|
||||
requires: {},
|
||||
log: []
|
||||
}
|
||||
expected.requires[md5Path] = absolutePath
|
||||
expect(parseAndReplaceRequire(code)).eql(expected)
|
||||
})
|
||||
|
||||
it('parent directory with no extname', function () {
|
||||
var code = 'var a = require("./test/fix");'
|
||||
var absolutePath = path.join(__dirname, '../test/fix.js')
|
||||
var md5Path = md5(absolutePath)
|
||||
var expected = {
|
||||
code: 'var a = browserifyRequire("' + md5Path + '");',
|
||||
requires: {},
|
||||
log: []
|
||||
}
|
||||
expected.requires[md5Path] = absolutePath
|
||||
expect(parseAndReplaceRequire(code)).eql(expected)
|
||||
})
|
||||
|
||||
it('parent directory with extname', function () {
|
||||
var code = 'var a = require("./test/fix.js");'
|
||||
var absolutePath = path.join(__dirname, '../test/fix.js')
|
||||
var md5Path = md5(absolutePath)
|
||||
var expected = {
|
||||
code: 'var a = browserifyRequire("' + md5Path + '");',
|
||||
requires: {},
|
||||
log: []
|
||||
}
|
||||
expected.requires[md5Path] = absolutePath
|
||||
expect(parseAndReplaceRequire(code)).eql(expected)
|
||||
})
|
||||
|
||||
it('require @weex-module', function () {
|
||||
var code = 'var a = require("@weex-module/xxx");'
|
||||
var expected = {
|
||||
code: 'var a = require("@weex-module/xxx");',
|
||||
requires: {},
|
||||
log: []
|
||||
}
|
||||
expect(parseAndReplaceRequire(code)).eql(expected)
|
||||
})
|
||||
|
||||
it('require @weex-component', function () {
|
||||
var code = 'var a = require("@weex-component/xxx");'
|
||||
var expected = {
|
||||
code: 'var a = require("@weex-component/xxx");',
|
||||
requires: {},
|
||||
log: []
|
||||
}
|
||||
expect(parseAndReplaceRequire(code)).eql(expected)
|
||||
})
|
||||
|
||||
it('multiple requires', function () {
|
||||
var code = 'var a = require("md5"); var b = require("test/fix"); var c = require("@weex-component/xxx");'
|
||||
var absolutePathA = path.join(__dirname, '../node_modules/md5/md5.js')
|
||||
var md5PathA = md5(absolutePathA)
|
||||
var absolutePathB = path.join(__dirname, '../test/fix.js')
|
||||
var md5PathB = md5(absolutePathB)
|
||||
var expected = {
|
||||
code: 'var a = browserifyRequire("' + md5PathA + '"); var b = browserifyRequire("' + md5PathB + '"); var c = require("@weex-component/xxx");',
|
||||
requires: {},
|
||||
log: []
|
||||
}
|
||||
expected.requires[md5PathA] = absolutePathA
|
||||
expected.requires[md5PathB] = absolutePathB
|
||||
expect(parseAndReplaceRequire(code)).eql(expected)
|
||||
})
|
||||
|
||||
it('cannot find required module', function () {
|
||||
var code = 'var a = require("underscore")'
|
||||
var expected = {
|
||||
code: 'var a = require("underscore")',
|
||||
requires: {},
|
||||
log: [{reason: 'ERROR: Cannot find required module "underscore"'}]
|
||||
}
|
||||
expect(parseAndReplaceRequire(code)).eql(expected)
|
||||
})
|
||||
})
|
4
deps/weex-styler/.gitignore
vendored
Normal file
4
deps/weex-styler/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
node_modules
|
||||
coverage
|
||||
.DS_Store
|
||||
.idea
|
31
deps/weex-styler/.jscsrc
vendored
Normal file
31
deps/weex-styler/.jscsrc
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"preset": "node-style-guide",
|
||||
|
||||
"disallowKeywordsOnNewLine": [],
|
||||
"disallowMultipleVarDecl": {"allExcept": ["undefined"]},
|
||||
"disallowSemicolons": true,
|
||||
"requireCapitalizedComments": null,
|
||||
|
||||
"requireCurlyBraces": [
|
||||
"if",
|
||||
"else",
|
||||
"for",
|
||||
"while",
|
||||
"do",
|
||||
"try",
|
||||
"catch"
|
||||
],
|
||||
|
||||
"disallowSpacesInFunction": null,
|
||||
"disallowSpacesInNamedFunctionExpression": {
|
||||
"beforeOpeningRoundBrace": true
|
||||
},
|
||||
"requireSpacesInAnonymousFunctionExpression": {
|
||||
"beforeOpeningRoundBrace": true
|
||||
},
|
||||
|
||||
"disallowSpaceBeforeComma": true,
|
||||
"requireCommaBeforeLineBreak": true,
|
||||
"disallowTrailingComma": true,
|
||||
"requireTrailingComma": null
|
||||
}
|
21
deps/weex-styler/LICENSE
vendored
Normal file
21
deps/weex-styler/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-present, songsiqi
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
124
deps/weex-styler/README.md
vendored
Normal file
124
deps/weex-styler/README.md
vendored
Normal file
@ -0,0 +1,124 @@
|
||||
# Weex `<style>` Transformer
|
||||
|
||||
[![NPM version][npm-image]][npm-url]
|
||||
[![Build status][circle-image]][circle-url]
|
||||
[![Downloads][downloads-image]][downloads-url]
|
||||
|
||||
[npm-image]: https://img.shields.io/npm/v/weex-styler.svg?style=flat-square
|
||||
[npm-url]: https://npmjs.org/package/weex-styler
|
||||
[circle-image]: https://circleci.com/gh/alibaba/weex_toolchain.svg?style=svg
|
||||
[circle-url]: https://circleci.com/gh/alibaba/weex_toolchain/tree/master
|
||||
[downloads-image]: https://img.shields.io/npm/dm/weex-styler.svg?style=flat-square
|
||||
[downloads-url]: https://npmjs.org/package/weex-styler
|
||||
|
||||
## Features
|
||||
|
||||
- convert a `<style>` element to JSON format
|
||||
- autofix common mistakes
|
||||
- friendly warnings
|
||||
|
||||
## API
|
||||
|
||||
- `parse(code, done)`
|
||||
- `validate(json, done)`
|
||||
- `validateItem(name, value)`
|
||||
|
||||
### util api
|
||||
|
||||
- `util.hyphenedToCamelCase(value)`
|
||||
- `util.camelCaseToHyphened(value)`
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* Parse `<style>` code to a JSON Object and log errors & warnings
|
||||
*
|
||||
* @param {string} code
|
||||
* @param {function} done
|
||||
*/
|
||||
function parse(code, done) {}
|
||||
|
||||
/**
|
||||
* Validate a JSON Object and log errors & warnings
|
||||
*
|
||||
* @param {object} json
|
||||
* @param {function} done
|
||||
*/
|
||||
function validate(json, done) {}
|
||||
|
||||
/**
|
||||
* Result callback
|
||||
*
|
||||
* data
|
||||
* - jsonStyle{}: `classname.propname.value`-like object
|
||||
* - log[{line, column, reason}]
|
||||
*
|
||||
* @param {Error} err
|
||||
* @param {object} data
|
||||
*/
|
||||
function done(err, data) {}
|
||||
|
||||
/**
|
||||
* Validate a single name-value pair
|
||||
*
|
||||
* @param {string} name camel cased
|
||||
* @param {string} value
|
||||
* @return {object}
|
||||
* - value
|
||||
* - log{reason}
|
||||
*/
|
||||
function validateItem(name, value) {}
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
- rule check: only common rule type supported, othres will be ignored
|
||||
- selector check: only single-classname selector is supported, others will be ignored
|
||||
- prop name check: out-of-defined prop name will be warned but preserved
|
||||
- prop value check: common prop value mistakes will be autofixed or ignored
|
||||
+ color type: keywords, `#xxx` -> warning: `#xxxxxx`
|
||||
+ color type: `transparent` -> error: not supported
|
||||
+ length type: `100px` -> warning: `100`
|
||||
|
||||
## Demo
|
||||
|
||||
```javascript
|
||||
var styler = require('weex-styler')
|
||||
|
||||
var code = 'html {color: #000000;} .foo {color: red; -webkit-transform: rotate(90deg); width: 200px;}'
|
||||
|
||||
styler.parse(code, function (err, data) {
|
||||
// syntax error
|
||||
// format: {line, column, reason, ...}
|
||||
err
|
||||
// result
|
||||
// {foo: {color: '#ff0000', webkitTransform: 'rotate(90deg)', width: 200}}
|
||||
data.jsonStyle
|
||||
// format: {line, column, reason}
|
||||
// - Error: Selector `html` is not supported. Weex only support single-classname selector
|
||||
// - Warning: prop value `red` is autofixed to `#ff0000`
|
||||
// - Warning: prop name `-webkit-transform` is not supported
|
||||
// - Warning: prop value `200px` is autofixed to `200`
|
||||
data.log[]
|
||||
})
|
||||
|
||||
var jsonStyle = {
|
||||
foo: {
|
||||
color: 'red',
|
||||
webkitTransform: 'rotate(90deg)',
|
||||
width: '200px'
|
||||
}
|
||||
}
|
||||
|
||||
styler.validate(json, function (err, data) {
|
||||
// syntax error
|
||||
err
|
||||
// result
|
||||
// {foo: {color: '#ff0000', webkitTransform: 'rotate(90deg)', width: 200}}
|
||||
data.jsonStyle
|
||||
// format: {reason}
|
||||
// - Warning: prop value `red` is autofixed to `#ff0000`
|
||||
// - Warning: prop name `-webkit-transform` is not supported
|
||||
// - Warning: prop value `200px` is autofixed to `200`
|
||||
data.log[]
|
||||
})
|
||||
```
|
3
deps/weex-styler/circle.yml
vendored
Normal file
3
deps/weex-styler/circle.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
machine:
|
||||
node:
|
||||
version: 4.2.1
|
25
deps/weex-styler/gulpfile.js
vendored
Normal file
25
deps/weex-styler/gulpfile.js
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
var gulp = require('gulp')
|
||||
var jscs = require('gulp-jscs')
|
||||
var mocha = require('gulp-mocha')
|
||||
|
||||
gulp.task('default', ['test'], function() {
|
||||
console.log('done')
|
||||
})
|
||||
|
||||
gulp.task('watch', function () {
|
||||
return gulp.watch('**/*.js', ['test'])
|
||||
})
|
||||
|
||||
gulp.task('test', ['jscs', 'mocha'], function () {
|
||||
console.log('test done')
|
||||
})
|
||||
|
||||
gulp.task('mocha', function () {
|
||||
return gulp.src([
|
||||
'test/*.js'
|
||||
]).pipe(mocha())
|
||||
})
|
||||
|
||||
gulp.task('jscs', function () {
|
||||
return gulp.src('**/*.js').pipe(jscs())
|
||||
})
|
600
deps/weex-styler/index.js
vendored
Normal file
600
deps/weex-styler/index.js
vendored
Normal file
@ -0,0 +1,600 @@
|
||||
'use strict'
|
||||
|
||||
var css = require('css')
|
||||
var util = require('./lib/util')
|
||||
var validateItem = require('./lib/validator').validate
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
|
||||
var SELECTOR_MATCHER = /^[\.#]?[A-Za-z0-9_\-:]+$/
|
||||
var DESCENDANT_SELECTOR_MATCHER = /^([.#]?[A-Za-z0-9_-]+(\s+|\s*>\s*))+([.#]?[A-Za-z0-9_\-:]+)$/
|
||||
var IMPORT_MATCHER = /(['"]([^()]+?)['"])|(['"]([^()]+?)['"]\s+(only|not)?\s?(screen)?\s?((and|or|,|not|landscape)?\s?[(]([^()])+[)]\s*)+)/g
|
||||
var LENGTH_REGEXP = /^[-+]?\d*\.?\d+(\S*)$/
|
||||
const CARD_SELECTOR = /^[\.#][A-Za-z0-9_\-]+$/
|
||||
const card = process.env.DEVICE_LEVEL === 'card'
|
||||
|
||||
/**
|
||||
* expand margin、padding、border、borderWidth、borderColor、borderStyle properties、animation
|
||||
*
|
||||
* @param {object} subResult
|
||||
* @param {String} camelCasedName
|
||||
* @param {object} ruleResult
|
||||
*/
|
||||
function expand (subResult, camelCasedName, ruleResult) {
|
||||
if (camelCasedName === 'border') {
|
||||
subResult.value.forEach(function (item) {
|
||||
if (item.type === 'Width' || item.type === 'Color' || item.type === 'Style') {
|
||||
const spliceName = [camelCasedName + 'Top' + item.type, camelCasedName + 'Right' + item.type, camelCasedName +
|
||||
'Bottom' + item.type, camelCasedName + 'Left' + item.type]
|
||||
util.splitAttr(ruleResult, item.value, spliceName)
|
||||
}
|
||||
else {
|
||||
ruleResult[camelCasedName + item.type] = item.value
|
||||
}
|
||||
})
|
||||
}
|
||||
else if (['borderTop', 'borderRight', 'borderBottom', 'borderLeft'].includes(camelCasedName)) {
|
||||
subResult.value.forEach(function (item) {
|
||||
ruleResult[camelCasedName + item.type] = item.value
|
||||
})
|
||||
}
|
||||
else if (camelCasedName === 'margin' || camelCasedName === 'padding') {
|
||||
const spliceName = [camelCasedName + 'Top', camelCasedName + 'Right', camelCasedName + 'Bottom', camelCasedName + 'Left']
|
||||
util.splitAttr(ruleResult, subResult.value, spliceName)
|
||||
}
|
||||
else if (camelCasedName === 'borderWidth') {
|
||||
util.splitAttr(ruleResult, subResult.value, ['borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth'])
|
||||
}
|
||||
else if (camelCasedName === 'borderColor') {
|
||||
util.splitAttr(ruleResult, subResult.value, ['borderTopColor', 'borderRightColor', 'borderBottomColor', 'borderLeftColor'])
|
||||
}
|
||||
else if (camelCasedName === 'borderStyle') {
|
||||
util.splitAttr(ruleResult, subResult.value, ['borderTopStyle', 'borderRightStyle', 'borderBottomStyle', 'borderLeftStyle'])
|
||||
}
|
||||
else if (camelCasedName === 'borderRadius') {
|
||||
util.splitAttr(ruleResult, subResult.value, ['borderBottomLeftRadius', 'borderBottomRightRadius', 'borderTopLeftRadius', 'borderTopRightRadius'])
|
||||
}
|
||||
else if (camelCasedName === 'gridGap') {
|
||||
util.splitAttr(ruleResult, subResult.value, ['gridRowsGap', 'gridColumnsGap'])
|
||||
}
|
||||
else if (camelCasedName === 'boxShadow') {
|
||||
subResult.value.forEach(function (item) {
|
||||
if (item.type === 'H' || item.type === 'V' || item.type === 'Blur' || item.type === 'Spread' ||
|
||||
item.type === 'Color') {
|
||||
util.splitAttr(ruleResult, item.value, [camelCasedName + item.type])
|
||||
}
|
||||
})
|
||||
}
|
||||
else if (camelCasedName === 'animation') {
|
||||
Object.assign(ruleResult, subResult.value);
|
||||
}
|
||||
else {
|
||||
// never to do
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* expand flex style
|
||||
*
|
||||
* @param {object} rule
|
||||
* @param {Array} ruleLog
|
||||
*/
|
||||
function flexExpand(rule, ruleLog) {
|
||||
for (let i = 0; i < rule.declarations.length; i++) {
|
||||
let declaration = rule.declarations[i]
|
||||
if (declaration.property === 'flex') {
|
||||
let values = declaration.value.split(/\s+/)
|
||||
rule.declarations.splice(i, 1)
|
||||
if (values.length === 1) {
|
||||
checkFlexOne(rule, ruleLog, declaration, values, i)
|
||||
} else if (values.length === 2) {
|
||||
checkFlexTwo(rule, ruleLog, declaration, values, i)
|
||||
} else if (values.length === 3) {
|
||||
checkFlexThree(rule, ruleLog, declaration, values, i)
|
||||
} else {
|
||||
ruleLog.push({
|
||||
line: declaration.position.start.line,
|
||||
column: declaration.position.start.column,
|
||||
reason: 'ERROR: Value `' + declaration.value + '` of the `' + declaration.property + '` attribute is incorrect.'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getUnit(value) {
|
||||
value = value.toString().trim()
|
||||
let match = value.match(LENGTH_REGEXP)
|
||||
if (match) {
|
||||
let unit = match[1]
|
||||
if (unit) {
|
||||
if (unit === 'px') {
|
||||
return "px"
|
||||
}
|
||||
} else {
|
||||
return "none"
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function checkFlexOne(rule, ruleLog, declaration, values, i) {
|
||||
const array = ['none', 'auto', 'initial']
|
||||
if (array.includes(values[0])) {
|
||||
rule.declarations.splice(i, 0, {type: 'declaration', property: 'flex', value: values[0], position: declaration.position})
|
||||
} else if (getUnit(values[0]) === 'px') {
|
||||
rule.declarations.splice(i, 0, {type: 'declaration', property: 'flex-basis', value: values[0], position: declaration.position})
|
||||
} else if (getUnit(values[0]) === 'none') {
|
||||
rule.declarations.splice(i, 0, {type: 'declaration', property: 'flex-grow', value: values[0], position: declaration.position})
|
||||
} else {
|
||||
ruleLog.push({
|
||||
line: declaration.position.start.line,
|
||||
column: declaration.position.start.column,
|
||||
reason: 'ERROR: Value `' + declaration.value + '` of the `' + declaration.property + '` attribute is incorrect.' +
|
||||
'It must be a number, a number with unit `' + 'px`' + ', none, auto, or initial.'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function checkFlexTwo(rule, ruleLog, declaration, values, i) {
|
||||
if (getUnit(values[0]) === 'none') {
|
||||
rule.declarations.splice(i, 0, {type: 'declaration', property: 'flex-grow', value: values[0], position: declaration.position})
|
||||
if (getUnit(values[1]) === 'px') {
|
||||
rule.declarations.splice(i, 0, {type: 'declaration', property: 'flex-basis', value: values[1], position: declaration.position})
|
||||
} else if (getUnit(values[1]) === 'none') {
|
||||
rule.declarations.splice(i, 0, {type: 'declaration', property: 'flex-shrink', value: values[1], position: declaration.position})
|
||||
} else {
|
||||
ruleLog.push({
|
||||
line: declaration.position.start.line,
|
||||
column: declaration.position.start.column,
|
||||
reason: 'ERROR: Value `' + declaration.value + '` of the `' + declaration.property + '` attribute is incorrect. Value `' +
|
||||
values[1] + '` must be a number or a number with unit `' + 'px`.'
|
||||
})
|
||||
}
|
||||
} else {
|
||||
ruleLog.push({
|
||||
line: declaration.position.start.line,
|
||||
column: declaration.position.start.column,
|
||||
reason: 'ERROR: Value `' + declaration.value + '` of the `' + declaration.property + '` attribute is incorrect. Value `' +
|
||||
values[0] + '` must be a number.'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function checkFlexThree(rule, ruleLog, declaration, values, i) {
|
||||
if (getUnit(values[0]) === 'none' && getUnit(values[1]) === 'none' && getUnit(values[2]) === 'px') {
|
||||
rule.declarations.splice(i, 0, {type: 'declaration', property: 'flex-grow', value: values[0], position: declaration.position})
|
||||
rule.declarations.splice(i, 0, {type: 'declaration', property: 'flex-shrink', value: values[1], position: declaration.position})
|
||||
rule.declarations.splice(i, 0, {type: 'declaration', property: 'flex-basis', value: values[2], position: declaration.position})
|
||||
} else {
|
||||
ruleLog.push({
|
||||
line: declaration.position.start.line,
|
||||
column: declaration.position.start.column,
|
||||
reason: 'ERROR: Value `' + declaration.value + '` of the `' + declaration.property +
|
||||
'` attribute is incorrect. It must be in the format of (1, 1, 1px).'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse `<style>` code to a JSON Object and log errors & warnings
|
||||
*
|
||||
* @param {string} code
|
||||
* @param {function} done which will be called with
|
||||
* - err:Error
|
||||
* - data.jsonStyle{}: `classname.propname.value`-like object
|
||||
* - data.log[{line, column, reason}]
|
||||
*/
|
||||
function parse(code, done, resourcePath) {
|
||||
var ast, err, jsonStyle = {}, log = []
|
||||
|
||||
// css parse
|
||||
ast = css.parse(code, {silent: true})
|
||||
|
||||
// catch syntax error
|
||||
if (ast.stylesheet.parsingErrors && ast.stylesheet.parsingErrors.length) {
|
||||
err = ast.stylesheet.parsingErrors
|
||||
err.forEach(function (error) {
|
||||
log.push({line: error.line, column: error.column, reason: error.toString().replace('Error', 'ERROR')})
|
||||
})
|
||||
}
|
||||
|
||||
// walk all
|
||||
/* istanbul ignore else */
|
||||
if (ast && ast.type === 'stylesheet' && ast.stylesheet &&
|
||||
ast.stylesheet.rules && ast.stylesheet.rules.length) {
|
||||
ast.stylesheet.rules.forEach(function (rule) {
|
||||
var type = rule.type
|
||||
var ruleResult = {}
|
||||
var ruleLog = []
|
||||
|
||||
if (type === 'rule') {
|
||||
if (rule.declarations && rule.declarations.length) {
|
||||
flexExpand(rule, ruleLog)
|
||||
|
||||
rule.declarations.forEach(function (declaration) {
|
||||
var subType = declaration.type
|
||||
var name, value, line, column, subResult, camelCasedName
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (subType !== 'declaration') {
|
||||
return
|
||||
}
|
||||
|
||||
name = declaration.property
|
||||
value = declaration.value
|
||||
|
||||
// validate declarations and collect them to result
|
||||
camelCasedName = util.hyphenedToCamelCase(name)
|
||||
subResult = validateItem(camelCasedName, value)
|
||||
|
||||
// expand margin、padding、border、borderWidth、borderColor、borderStyle properties、animation
|
||||
if (subResult.value && Object.values(util.SPLECIAL_ATTR).indexOf(camelCasedName) !== -1) {
|
||||
expand(subResult, camelCasedName, ruleResult)
|
||||
}
|
||||
|
||||
/* istanbul ignore else */
|
||||
if ((typeof subResult.value === 'number' || typeof subResult.value === 'string')
|
||||
&& !Object.values(util.SPLECIAL_ATTR).includes(camelCasedName)) {
|
||||
ruleResult[camelCasedName] = subResult.value
|
||||
}
|
||||
if (subResult.log) {
|
||||
subResult.log.line = declaration.position.start.line
|
||||
subResult.log.column = declaration.position.start.column
|
||||
ruleLog.push(subResult.log)
|
||||
}
|
||||
})
|
||||
|
||||
if (card && rule.selectors.length > 1) {
|
||||
log.push({
|
||||
line: rule.position.start.line,
|
||||
column: rule.position.start.column,
|
||||
reason: 'ERROR: The `' + rule.selectors.join(', ') + '` selector is not supported.'
|
||||
})
|
||||
} else {
|
||||
rule.selectors.forEach(function (selector) {
|
||||
const flag = card ? selector.match(CARD_SELECTOR) :
|
||||
selector.match(SELECTOR_MATCHER) || selector.match(DESCENDANT_SELECTOR_MATCHER)
|
||||
if (flag) {
|
||||
var className = selector
|
||||
|
||||
// handle pseudo class
|
||||
var pseudoIndex = className.indexOf(':')
|
||||
if (pseudoIndex > -1) {
|
||||
var pseudoCls = className.slice(pseudoIndex)
|
||||
className = className.slice(0, pseudoIndex)
|
||||
var pseudoRuleResult = {}
|
||||
Object.keys(ruleResult).forEach(function (prop) {
|
||||
pseudoRuleResult[prop + pseudoCls] = ruleResult[prop]
|
||||
})
|
||||
ruleResult = pseudoRuleResult
|
||||
}
|
||||
|
||||
// merge style
|
||||
Object.keys(ruleResult).forEach(function (prop) {
|
||||
// handle transition
|
||||
if (prop.indexOf('transition') === 0 && prop !== 'transition') {
|
||||
var realProp = prop.replace('transition', '')
|
||||
realProp = realProp[0].toLowerCase() + realProp.slice(1)
|
||||
jsonStyle['@TRANSITION'] = jsonStyle['@TRANSITION'] || {}
|
||||
jsonStyle['@TRANSITION'][className] = jsonStyle['@TRANSITION'][className] || {}
|
||||
jsonStyle['@TRANSITION'][className][realProp] = ruleResult[prop]
|
||||
}
|
||||
|
||||
jsonStyle[className] = jsonStyle[className] || {}
|
||||
jsonStyle[className][prop] = ruleResult[prop]
|
||||
})
|
||||
} else {
|
||||
log.push({
|
||||
line: rule.position.start.line,
|
||||
column: rule.position.start.column,
|
||||
reason: 'ERROR: The `' + selector + '` selector is not supported.'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
log = log.concat(ruleLog)
|
||||
}
|
||||
}
|
||||
/* istanbul ignore else */
|
||||
else if (type === 'font-face') {
|
||||
/* istanbul ignore else */
|
||||
if (rule.declarations && rule.declarations.length) {
|
||||
rule.declarations.forEach(function (declaration) {
|
||||
/* istanbul ignore if */
|
||||
if (declaration.type !== 'declaration') {
|
||||
return
|
||||
}
|
||||
var name = util.hyphenedToCamelCase(declaration.property)
|
||||
var value = declaration.value
|
||||
if (name === 'fontFamily' && '\"\''.indexOf(value[0]) > -1) { // FIXME: delete leading and trailing quotes
|
||||
value = value.slice(1, value.length - 1)
|
||||
}
|
||||
ruleResult[name] = value
|
||||
})
|
||||
if (!jsonStyle['@FONT-FACE']) {
|
||||
jsonStyle['@FONT-FACE'] = []
|
||||
}
|
||||
jsonStyle['@FONT-FACE'].push(ruleResult)
|
||||
}
|
||||
}
|
||||
else if (type === 'import') {
|
||||
parseImport(resourcePath, rule, jsonStyle, log)
|
||||
}
|
||||
else if (type === 'keyframes' && !card) {
|
||||
if (!jsonStyle['@KEYFRAMES']) {
|
||||
jsonStyle['@KEYFRAMES'] = {}
|
||||
}
|
||||
var keyName = rule.name
|
||||
jsonStyle['@KEYFRAMES'][keyName] = []
|
||||
if (rule.keyframes && rule.keyframes.length) {
|
||||
if (card) {
|
||||
log.push({
|
||||
line: rule.position.start.line,
|
||||
column: rule.position.start.column,
|
||||
reason: 'ERROR: The keyframes is not supported!'
|
||||
})
|
||||
} else {
|
||||
rule.keyframes.forEach(function (keyframe) {
|
||||
|
||||
var keyframeType = keyframe.type
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (keyframeType !== 'keyframe') {
|
||||
return
|
||||
}
|
||||
|
||||
if (keyframe.declarations && keyframe.declarations.length) {
|
||||
keyframe.declarations.forEach(function (declaration) {
|
||||
var subType = declaration.type
|
||||
var name, value, line, column, subResult, camelCasedName
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (subType !== 'declaration') {
|
||||
return
|
||||
}
|
||||
|
||||
name = declaration.property
|
||||
value = declaration.value
|
||||
|
||||
// validate declarations and collect them to result
|
||||
camelCasedName = util.hyphenedToCamelCase(name)
|
||||
subResult = validateItem(camelCasedName, value)
|
||||
|
||||
// expand margin、padding、border、borderWidth、borderColor、borderStyle properties
|
||||
if (subResult.value && Object.values(util.SPLECIAL_ATTR).indexOf(camelCasedName) !== -1) {
|
||||
expand(subResult, camelCasedName, ruleResult)
|
||||
}
|
||||
/* istanbul ignore else */
|
||||
if ((typeof subResult.value === 'number' || typeof subResult.value === 'string')
|
||||
&& !Object.values(util.SPLECIAL_ATTR).includes(camelCasedName)) {
|
||||
ruleResult[camelCasedName] = subResult.value
|
||||
}
|
||||
if (subResult.log) {
|
||||
subResult.log.line = declaration.position.start.line
|
||||
subResult.log.column = declaration.position.start.column
|
||||
ruleLog.push(subResult.log)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (keyframe.values[0] === 'from') {
|
||||
var keyframeResult = {}
|
||||
Object.keys(ruleResult).forEach(function (prop) {
|
||||
keyframeResult[prop] = ruleResult[prop]
|
||||
})
|
||||
keyframeResult['time'] = 0
|
||||
jsonStyle['@KEYFRAMES'][keyName].push(keyframeResult)
|
||||
}
|
||||
if (keyframe.values[0] === 'to') {
|
||||
var keyframeResult = {}
|
||||
Object.keys(ruleResult).forEach(function (prop) {
|
||||
keyframeResult[prop] = ruleResult[prop]
|
||||
})
|
||||
keyframeResult['time'] = 100
|
||||
jsonStyle['@KEYFRAMES'][keyName].push(keyframeResult)
|
||||
}
|
||||
var patt = new RegExp(/^(100|[1-9]?\d)%$/)
|
||||
if (patt.test(keyframe.values[0])) {
|
||||
var keyframeResult = {}
|
||||
Object.keys(ruleResult).forEach(function (prop) {
|
||||
keyframeResult[prop] = ruleResult[prop]
|
||||
})
|
||||
keyframeResult['time'] = keyframe.values[0].replace("%", "")
|
||||
jsonStyle['@KEYFRAMES'][keyName].push(keyframeResult)
|
||||
}
|
||||
})
|
||||
log = log.concat(ruleLog)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type === 'media') {
|
||||
if (!jsonStyle['@MEDIA']) {
|
||||
jsonStyle['@MEDIA'] = []
|
||||
}
|
||||
var condition = rule.media
|
||||
var mediaObj = {}
|
||||
mediaObj['condition'] = condition
|
||||
|
||||
if (rule.rules && rule.rules.length) {
|
||||
rule.rules.forEach(function(rule) {
|
||||
ruleResult = {}
|
||||
if (rule.type === 'import') {
|
||||
parseImport(resourcePath, rule, mediaObj, log)
|
||||
}
|
||||
if (rule.declarations && rule.declarations.length) {
|
||||
flexExpand(rule, ruleLog)
|
||||
rule.declarations.forEach(function (declaration) {
|
||||
var subType = declaration.type
|
||||
var name, value, line, column, subResult, camelCasedName
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (subType !== 'declaration') {
|
||||
return
|
||||
}
|
||||
|
||||
name = declaration.property
|
||||
value = declaration.value
|
||||
|
||||
// validate declarations and collect them to result
|
||||
camelCasedName = util.hyphenedToCamelCase(name)
|
||||
subResult = validateItem(camelCasedName, value)
|
||||
// expand margin、padding、border、borderWidth、borderColor、borderStyle properties
|
||||
if (subResult.value && Object.values(util.SPLECIAL_ATTR).indexOf(camelCasedName) !== -1) {
|
||||
expand(subResult, camelCasedName, ruleResult)
|
||||
}
|
||||
|
||||
/* istanbul ignore else */
|
||||
if ((typeof subResult.value === 'number' || typeof subResult.value === 'string')
|
||||
&& !Object.values(util.SPLECIAL_ATTR).includes(camelCasedName)) {
|
||||
ruleResult[camelCasedName] = subResult.value
|
||||
}
|
||||
if (subResult.log) {
|
||||
subResult.log.line = declaration.position.start.line
|
||||
subResult.log.column = declaration.position.start.column
|
||||
ruleLog.push(subResult.log)
|
||||
}
|
||||
})
|
||||
rule.selectors.forEach(function (selector) {
|
||||
if (selector.match(SELECTOR_MATCHER) || selector.match(DESCENDANT_SELECTOR_MATCHER)) {
|
||||
var className = selector
|
||||
|
||||
// handle pseudo class
|
||||
var pseudoIndex = className.indexOf(':')
|
||||
if (pseudoIndex > -1) {
|
||||
var pseudoCls = className.slice(pseudoIndex)
|
||||
className = className.slice(0, pseudoIndex)
|
||||
var pseudoRuleResult = {}
|
||||
Object.keys(ruleResult).forEach(function (prop) {
|
||||
pseudoRuleResult[prop + pseudoCls] = ruleResult[prop]
|
||||
})
|
||||
ruleResult = pseudoRuleResult
|
||||
}
|
||||
// merge style
|
||||
Object.keys(ruleResult).forEach(function (prop) {
|
||||
// handle transition
|
||||
if (prop.indexOf('transition') === 0 && prop !== 'transition') {
|
||||
var realProp = prop.replace('transition', '')
|
||||
realProp = realProp[0].toLowerCase() + realProp.slice(1)
|
||||
mediaObj['@TRANSITION'] = mediaObj['@TRANSITION'] || {}
|
||||
mediaObj['@TRANSITION'][className] = mediaObj['@TRANSITION'][className] || {}
|
||||
mediaObj['@TRANSITION'][className][realProp] = ruleResult[prop]
|
||||
}
|
||||
mediaObj[className] = mediaObj[className] || {}
|
||||
mediaObj[className][prop] = ruleResult[prop]
|
||||
})
|
||||
} else {
|
||||
log.push({
|
||||
line: rule.position.start.line,
|
||||
column: rule.position.start.column,
|
||||
reason: 'ERROR: The `' + selector + '` selector is not supported.'
|
||||
})
|
||||
}
|
||||
})
|
||||
log = log.concat(ruleLog)
|
||||
}
|
||||
})
|
||||
}
|
||||
jsonStyle['@MEDIA'].push(mediaObj)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
done(err, {jsonStyle: jsonStyle, log: log})
|
||||
}
|
||||
|
||||
function parseImport(resourcePath, rule, jsonStyle, log) {
|
||||
if(!resourcePath) {
|
||||
return
|
||||
}
|
||||
let importString = rule.import
|
||||
let importPath
|
||||
let mediaString = ''
|
||||
let source = ''
|
||||
if (importString.match(IMPORT_MATCHER)) {
|
||||
let filePath = importString.match(/['"]([^()]+?)['"]/)
|
||||
importPath = filePath[1]
|
||||
mediaString = importString.replace(importPath, '').replace(/['"]/g, '')
|
||||
}
|
||||
if(/^(\.)|(\.\.)\//.test(importPath)) {
|
||||
resourcePath = resourcePath.substring(0, resourcePath.lastIndexOf(path.sep) + 1);
|
||||
importPath = path.resolve(resourcePath, importPath)
|
||||
}
|
||||
if (fs.existsSync(importPath)) {
|
||||
source = fs.readFileSync(importPath).toString()
|
||||
} else {
|
||||
log.push({
|
||||
line: rule.position.start.line,
|
||||
column: rule.position.start.column,
|
||||
reason: 'ERROR: no such file or directory, open ' + importPath
|
||||
})
|
||||
return
|
||||
}
|
||||
if (mediaString.length !== 0) {
|
||||
source = '@media ' + mediaString + '{\n' + source + '\n}'
|
||||
}
|
||||
parse(source, (err, obj) => {
|
||||
if (err) {
|
||||
throw(err)
|
||||
} else {
|
||||
jsonStyle = Object.assign(jsonStyle, obj.jsonStyle)
|
||||
}
|
||||
}, importPath)
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a JSON Object and log errors & warnings
|
||||
*
|
||||
* @param {object} json
|
||||
* @param {function} done which will be called with
|
||||
* - err:Error
|
||||
* - data.jsonStyle{}: `classname.propname.value`-like object
|
||||
* - data.log[{reason}]
|
||||
*/
|
||||
function validate(json, done) {
|
||||
var log = []
|
||||
var err
|
||||
|
||||
try {
|
||||
json = JSON.parse(JSON.stringify(json))
|
||||
}
|
||||
catch (e) {
|
||||
err = e
|
||||
json = {}
|
||||
}
|
||||
|
||||
Object.keys(json).forEach(function (selector) {
|
||||
var declarations = json[selector]
|
||||
|
||||
Object.keys(declarations).forEach(function (name) {
|
||||
var value = declarations[name]
|
||||
var result = validateItem(name, value)
|
||||
|
||||
if (typeof result.value === 'number' || typeof result.value === 'string') {
|
||||
declarations[name] = result.value
|
||||
}
|
||||
else {
|
||||
delete declarations[name]
|
||||
}
|
||||
|
||||
if (result.log) {
|
||||
log.push(result.log)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
done(err, {
|
||||
jsonStyle: json,
|
||||
log: log
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
parse: parse,
|
||||
validate: validate,
|
||||
validateItem: validateItem,
|
||||
util: util,
|
||||
expand: expand,
|
||||
getUnit: getUnit,
|
||||
}
|
||||
|
60
deps/weex-styler/lib/shorthand-parser.js
vendored
Normal file
60
deps/weex-styler/lib/shorthand-parser.js
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
function generateDeclaration (property, value, position) {
|
||||
return {
|
||||
type: 'declaration',
|
||||
property,
|
||||
value,
|
||||
position
|
||||
}
|
||||
}
|
||||
function transition (declaration) {
|
||||
var CHUNK_REGEXP = /^(\S*)?\s*(\d*\.?\d+(?:ms|s)?)?\s*(\S*)?\s*(\d*\.?\d+(?:ms|s)?)?$/
|
||||
var match = declaration.value.match(CHUNK_REGEXP)
|
||||
var result = []
|
||||
var position = declaration.position
|
||||
match[1] && result.push(generateDeclaration('transition-property', match[1], position))
|
||||
match[2] && result.push(generateDeclaration('transition-duration', match[2], position))
|
||||
match[3] && result.push(generateDeclaration('transition-timing-function', match[3], position))
|
||||
match[4] && result.push(generateDeclaration('transition-delay', match[4], position))
|
||||
return result
|
||||
}
|
||||
|
||||
function margin (declaration) {
|
||||
var position = declaration.position
|
||||
var splitResult = declaration.value.split(/\s+/)
|
||||
var result = []
|
||||
switch (splitResult.length) {
|
||||
case 1:
|
||||
splitResult.push(splitResult[0], splitResult[0], splitResult[0])
|
||||
break
|
||||
case 2:
|
||||
splitResult.push(splitResult[0], splitResult[1])
|
||||
break
|
||||
case 3:
|
||||
splitResult.push(splitResult[1])
|
||||
break
|
||||
}
|
||||
result.push(
|
||||
generateDeclaration('margin-top', splitResult[0], position),
|
||||
generateDeclaration('margin-right', splitResult[1], position),
|
||||
generateDeclaration('margin-bottom', splitResult[2], position),
|
||||
generateDeclaration('margin-left', splitResult[3], position)
|
||||
)
|
||||
return result
|
||||
}
|
||||
|
||||
var parserCollection = {
|
||||
transition,
|
||||
margin
|
||||
}
|
||||
|
||||
module.exports = function (declarations) {
|
||||
return declarations.reduce((result, declaration) => {
|
||||
var parser = parserCollection[declaration.property]
|
||||
if (parser) {
|
||||
return result.concat(parser(declaration))
|
||||
} else {
|
||||
result.push(declaration)
|
||||
return result
|
||||
}
|
||||
}, [])
|
||||
}
|
102
deps/weex-styler/lib/util.js
vendored
Normal file
102
deps/weex-styler/lib/util.js
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
const { DEVICE_LEVEL } = require('../../lite/lite-enum')
|
||||
|
||||
/**
|
||||
* rules:
|
||||
* - abc-def -> abcDef
|
||||
* - -abc-def -> AbcDef
|
||||
*
|
||||
* @param {string} value
|
||||
* @return {string}
|
||||
*/
|
||||
exports.hyphenedToCamelCase = function hyphenedToCamelCase(value) {
|
||||
return value.replace(/-([a-z])/g, function(s, m) {
|
||||
return m.toUpperCase()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* rules:
|
||||
* - abcDef -> abc-def
|
||||
* - AbcDef -> -abc-def
|
||||
*
|
||||
* @param {string} value
|
||||
* @return {string}
|
||||
*/
|
||||
exports.camelCaseToHyphened = function camelCaseToHyphened(value) {
|
||||
return value.replace(/([A-Z])/g, function(s, m) {
|
||||
if (typeof m === 'string') {
|
||||
return '-' + m.toLowerCase()
|
||||
}
|
||||
return m
|
||||
})
|
||||
}
|
||||
|
||||
exports.isValidValue = function isValidValue(value) {
|
||||
return "number" == typeof value || "string" == typeof value
|
||||
}
|
||||
|
||||
/**
|
||||
* rules:
|
||||
* assign abbreviated values to expanded attributes
|
||||
* margin:1px 2px -> marginTop:1px;marginRight:2px;marginBottom:1px;marginLeft:2px;
|
||||
*
|
||||
* @param {obejct} object
|
||||
* @param {string} value
|
||||
* @param {obejct} spliceName
|
||||
*/
|
||||
exports.splitAttr = function (object, value, spliceName) {
|
||||
const values = value.toString().trim().split(/\s+/)
|
||||
if (values) {
|
||||
switch (values.length) {
|
||||
case 1:
|
||||
spliceName.forEach(function (item) {
|
||||
object[item] = values[0]
|
||||
})
|
||||
break
|
||||
case 2:
|
||||
spliceName.forEach(function (item, index) {
|
||||
object[item] = index % 2 ? values[1] : values[0]
|
||||
})
|
||||
break
|
||||
case 3:
|
||||
spliceName.forEach(function (item, index) {
|
||||
object[item] = index % 2 ? values[1] : values[index]
|
||||
})
|
||||
break
|
||||
default:
|
||||
spliceName.forEach(function (item, index) {
|
||||
object[item] = values[index]
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const RICH_SPLECIAL_ATTR = {
|
||||
MARGIN: 'margin',
|
||||
PADDING: 'padding',
|
||||
BORDER: 'border',
|
||||
BORDER_WIDTH: 'borderWidth',
|
||||
BORDER_COLOR: 'borderColor',
|
||||
BORDER_STYLE: 'borderStyle',
|
||||
BORDER_RADIUS: 'borderRadius',
|
||||
BORDER_BOTTOM: 'borderBottom',
|
||||
BORDER_RIGHT: 'borderRight',
|
||||
BORDER_LEFT: 'borderLeft',
|
||||
BORDER_TOP: 'borderTop',
|
||||
GRID_GAP: 'gridGap',
|
||||
BOX_SHADOW: 'boxShadow',
|
||||
ANIMATION: 'animation'
|
||||
}
|
||||
|
||||
const LITE_SPLECIAL_ATTR = {
|
||||
MARGIN: 'margin',
|
||||
PADDING: 'padding',
|
||||
BORDER_WIDTH: 'borderWidth',
|
||||
BORDER_COLOR: 'borderColor'
|
||||
}
|
||||
|
||||
/**
|
||||
* Special style attributes that need to be expanded
|
||||
*
|
||||
*/
|
||||
exports.SPLECIAL_ATTR = process.env.DEVICE_LEVEL === DEVICE_LEVEL.LITE ? LITE_SPLECIAL_ATTR : RICH_SPLECIAL_ATTR
|
2995
deps/weex-styler/lib/validator.js
vendored
Normal file
2995
deps/weex-styler/lib/validator.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3074
deps/weex-styler/package-lock.json
generated
vendored
Normal file
3074
deps/weex-styler/package-lock.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
31
deps/weex-styler/package.json
vendored
Normal file
31
deps/weex-styler/package.json
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "weex-styler",
|
||||
"version": "0.3.0",
|
||||
"description": "Weex <style> transformer",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "gulp test && npm run cover",
|
||||
"cover": "node node_modules/isparta/bin/isparta cover node_modules/gulp-mocha/node_modules/.bin/_mocha -- --reporter dot"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/weexteam/weex-styler.git"
|
||||
},
|
||||
"keywords": [
|
||||
"weex"
|
||||
],
|
||||
"author": "songsiqi <songsiqi2006@126.com>",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"css": "~2.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "~3.4.1",
|
||||
"gulp": "~3.9.0",
|
||||
"gulp-jscs": "~3.0.2",
|
||||
"gulp-mocha": "~2.2.0",
|
||||
"sinon": "~1.17.2",
|
||||
"sinon-chai": "~2.8.0",
|
||||
"isparta": "~4.0.0"
|
||||
}
|
||||
}
|
289
deps/weex-styler/test/parse.js
vendored
Normal file
289
deps/weex-styler/test/parse.js
vendored
Normal file
@ -0,0 +1,289 @@
|
||||
var chai = require('chai')
|
||||
var sinon = require('sinon')
|
||||
var sinonChai = require('sinon-chai')
|
||||
var expect = chai.expect
|
||||
chai.use(sinonChai)
|
||||
|
||||
var styler = require('../')
|
||||
|
||||
describe('parse', function () {
|
||||
|
||||
it('parse normal style code', function (done) {
|
||||
var code = 'html {color: #000000;}\n\n.foo {color: red; background-color: rgba(255,255,255,0.6); -webkit-transform: rotate(90deg); width: 200px; left: 0; right: 0px; border-width: 1pt; font-weight: 100}\n\n.bar {background: red}'
|
||||
styler.parse(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle).eql({foo: {color: '#FF0000', backgroundColor: 'rgba(255,255,255,0.6)', WebkitTransform: 'rotate(90deg)', width: '200px', left: 0, right: '0px', borderWidth: '1pt', fontWeight: '100'}, bar: {background: 'red'}})
|
||||
expect(data.log).eql([
|
||||
{line: 1, column: 1, reason: 'ERROR: Selector `html` is not supported. Weex only support single-classname selector'},
|
||||
{line: 3, column: 7, reason: 'NOTE: property value `red` is autofixed to `#FF0000`'},
|
||||
{line: 3, column: 60, reason: 'WARNING: `-webkit-transform` is not a standard property name (may not be supported)'},
|
||||
{line: 5, column: 7, reason: 'WARNING: `background` is not a standard property name (may not be supported), suggest `background-color`'}
|
||||
])
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('parse and fix prop value', function (done) {
|
||||
var code = '.foo {font-size: 200px;}'
|
||||
styler.parse(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle).eql({foo: {fontSize: '200px'}})
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('parse and ensure number type value', function (done) {
|
||||
var code = '.foo {line-height: 40;}\n\n .bar {line-height: 20px;}'
|
||||
styler.parse(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle).eql({foo: {lineHeight: 40}, bar: {lineHeight: '20px'}})
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('handle complex class definition', function (done) {
|
||||
var code = '.foo, .bar {font-size: 20;}\n\n .foo {color: #ff5000;}\n\n .bar {color: #000000;}'
|
||||
styler.parse(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle).eql({
|
||||
foo: {fontSize: 20, color: '#ff5000'},
|
||||
bar: {fontSize: 20, color: '#000000'}
|
||||
})
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('handle more complex class definition', function (done) {
|
||||
var code = '.foo, .bar {font-size: 20; color: #000000}\n\n .foo, .bar, .baz {color: #ff5000; height: 30;}'
|
||||
styler.parse(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle).eql({
|
||||
foo: {fontSize: 20, color: '#ff5000', height: 30},
|
||||
bar: {fontSize: 20, color: '#ff5000', height: 30},
|
||||
baz: {color: '#ff5000', height: 30}
|
||||
})
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('parse transition', function (done) {
|
||||
var code = '.foo {transition-property: margin-top; transition-duration: 300ms; transition-delay: 0.2s; transition-timing-function: ease-in;}'
|
||||
styler.parse(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle['@TRANSITION']).eql({foo: {property: 'marginTop', duration: 300, delay: 200, timingFunction: 'ease-in'}})
|
||||
expect(data.jsonStyle.foo).eql({
|
||||
transitionDelay: 200,
|
||||
transitionDuration: 300,
|
||||
transitionProperty: "marginTop",
|
||||
transitionTimingFunction: "ease-in"
|
||||
})
|
||||
expect(data.log).eql([
|
||||
{line: 1, column: 40, reason: 'NOTE: property value `300ms` is autofixed to `300`'},
|
||||
{line: 1, column: 68, reason: 'NOTE: property value `0.2s` is autofixed to `200`'}
|
||||
])
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('parse transition transform', function (done) {
|
||||
var code = '.foo {transition-property: transform; transition-duration: 300ms; transition-delay: 0.2s; transition-timing-function: ease-in-out;}'
|
||||
styler.parse(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle['@TRANSITION']).eql({foo: {property: 'transform', duration: 300, delay: 200, timingFunction: 'ease-in-out'}})
|
||||
expect(data.jsonStyle.foo).eql({
|
||||
transitionDelay: 200,
|
||||
transitionDuration: 300,
|
||||
transitionProperty: "transform",
|
||||
transitionTimingFunction: "ease-in-out"
|
||||
})
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('parse multi transition properties', function (done) {
|
||||
var code = '.foo {transition-property: margin-top, height; transition-duration: 300ms; transition-delay: 0.2s; transition-timing-function: ease-in-out;}'
|
||||
styler.parse(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle['@TRANSITION']).eql({foo: {property: 'marginTop,height', duration: 300, delay: 200, timingFunction: 'ease-in-out'}})
|
||||
expect(data.jsonStyle.foo).eql({
|
||||
transitionDelay: 200,
|
||||
transitionDuration: 300,
|
||||
transitionProperty: "marginTop,height",
|
||||
transitionTimingFunction: "ease-in-out"
|
||||
})
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('parse complex transition', function (done) {
|
||||
var code = '.foo {font-size: 20; color: #000000}\n\n .foo, .bar {color: #ff5000; height: 30; transition-property: margin-top; transition-duration: 300ms; transition-delay: 0.2s; transition-timing-function: ease-in;}'
|
||||
styler.parse(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle['@TRANSITION']).eql({
|
||||
foo: {property: 'marginTop', duration: 300, delay: 200, timingFunction: 'ease-in'},
|
||||
bar: {property: 'marginTop', duration: 300, delay: 200, timingFunction: 'ease-in'}
|
||||
})
|
||||
expect(data.jsonStyle.foo).eql({
|
||||
fontSize: 20, color: '#ff5000', height: 30,
|
||||
transitionDelay: 200,
|
||||
transitionDuration: 300,
|
||||
transitionProperty: "marginTop",
|
||||
transitionTimingFunction: "ease-in"
|
||||
})
|
||||
expect(data.jsonStyle.bar).eql({
|
||||
color: '#ff5000', height: 30,
|
||||
transitionDelay: 200,
|
||||
transitionDuration: 300,
|
||||
transitionProperty: "marginTop",
|
||||
transitionTimingFunction: "ease-in"
|
||||
})
|
||||
expect(data.log).eql([
|
||||
{line: 3, column: 75, reason: 'NOTE: property value `300ms` is autofixed to `300`'},
|
||||
{line: 3, column: 103, reason: 'NOTE: property value `0.2s` is autofixed to `200`'}
|
||||
])
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('parse transition shorthand', function (done) {
|
||||
var code = '.foo {font-size: 20; transition: margin-top 500ms ease-in-out 1s}'
|
||||
styler.parse(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle['@TRANSITION']).eql({foo: {property: 'marginTop', duration: 500, delay: 1000, timingFunction: 'ease-in-out' }})
|
||||
expect(data.jsonStyle.foo).eql({
|
||||
fontSize: 20,
|
||||
transitionDelay: 1000,
|
||||
transitionDuration: 500,
|
||||
transitionProperty: "marginTop",
|
||||
transitionTimingFunction: "ease-in-out"
|
||||
})
|
||||
expect(data.log).eql([
|
||||
{line: 1, column: 22, reason: 'NOTE: property value `500ms` is autofixed to `500`'},
|
||||
{line: 1, column: 22, reason: 'NOTE: property value `1s` is autofixed to `1000`'}
|
||||
])
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it.skip('override transition shorthand', function (done) {
|
||||
var code = '.foo {font-size: 32px; transition: margin-top 500ms ease-in-out 1s; transition-duration: 300ms}'
|
||||
styler.parse(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle['@TRANSITION']).eql({foo: {property: 'marginTop', duration: 300, delay: 1000, timingFunction: 'ease-in-out' }})
|
||||
expect(data.jsonStyle.foo).eql({
|
||||
fontSize: 32,
|
||||
transitionDelay: 1000,
|
||||
transitionDuration: 300,
|
||||
transitionProperty: "marginTop",
|
||||
transitionTimingFunction: "ease-in-out"
|
||||
})
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('parse padding & margin shorthand', function (done) {
|
||||
var code = '.foo { padding: 20px; margin: 30px 40; } .bar { margin: 10px 20 30; padding: 10 20px 30px 40;}'
|
||||
styler.parse(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle.foo).eql({
|
||||
paddingTop: '20px',
|
||||
paddingRight: '20px',
|
||||
paddingBottom: '20px',
|
||||
paddingLeft: '20px',
|
||||
marginTop: '30px',
|
||||
marginRight: 40,
|
||||
marginBottom: '30px',
|
||||
marginLeft: 40
|
||||
})
|
||||
expect(data.jsonStyle.bar).eql({
|
||||
paddingTop: 10,
|
||||
paddingRight: '20px',
|
||||
paddingBottom: '30px',
|
||||
paddingLeft: 40,
|
||||
marginTop: '10px',
|
||||
marginRight: 20,
|
||||
marginBottom: 30,
|
||||
marginLeft: 20
|
||||
})
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('override padding & margin shorthand', function (done) {
|
||||
var code = '.foo { padding: 20px; padding-left: 30px; } .bar { margin: 10px 20; margin-bottom: 30px;}'
|
||||
styler.parse(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle.foo).eql({
|
||||
paddingTop: '20px',
|
||||
paddingRight: '20px',
|
||||
paddingBottom: '20px',
|
||||
paddingLeft: '30px'
|
||||
})
|
||||
expect(data.jsonStyle.bar).eql({
|
||||
marginTop: '10px',
|
||||
marginRight: 20,
|
||||
marginBottom: '30px',
|
||||
marginLeft: 20
|
||||
})
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('handle pseudo class', function (done) {
|
||||
var code = '.class-a {color: #0000ff;} .class-a:last-child:focus {color: #ff0000;}'
|
||||
styler.parse(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle).eql({
|
||||
'class-a': {
|
||||
color: '#0000ff',
|
||||
'color:last-child:focus': '#ff0000'
|
||||
}
|
||||
})
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('handle iconfont', function (done) {
|
||||
var code = '@font-face {font-family: "font-family-name-1"; src: url("font file url 1-1") format("truetype");} @font-face {font-family: "font-family-name-2"; src: url("font file url 2-1") format("truetype"), url("font file url 2-2") format("woff");}'
|
||||
styler.parse(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle).eql({
|
||||
'@FONT-FACE': [
|
||||
{fontFamily: 'font-family-name-1', src: 'url("font file url 1-1") format("truetype")'},
|
||||
{fontFamily: 'font-family-name-2', src: 'url("font file url 2-1") format("truetype"), url("font file url 2-2") format("woff")'}
|
||||
]
|
||||
})
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('handle syntax error', function (done) {
|
||||
var code = 'asdf'
|
||||
styler.parse(code, function (err, data) {
|
||||
expect(err).is.an.array
|
||||
expect(err[0].toString()).eql('Error: undefined:1:5: missing \'{\'')
|
||||
expect(err[0].reason).eql('missing \'{\'')
|
||||
expect(err[0].filename).eql(undefined)
|
||||
expect(err[0].line).eql(1)
|
||||
expect(err[0].column).eql(5)
|
||||
expect(err[0].source).eql('')
|
||||
expect(data.log).eql([{line: 1, column: 5, reason: 'ERROR: undefined:1:5: missing \'{\''}])
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
178
deps/weex-styler/test/shorthand-parser.spec.js
vendored
Normal file
178
deps/weex-styler/test/shorthand-parser.spec.js
vendored
Normal file
@ -0,0 +1,178 @@
|
||||
var chai = require('chai')
|
||||
var sinon = require('sinon')
|
||||
var sinonChai = require('sinon-chai')
|
||||
var expect = chai.expect
|
||||
chai.use(sinonChai)
|
||||
|
||||
var shorthandParser = require('../lib/shorthand-parser')
|
||||
|
||||
describe('shorthand-parser', function () {
|
||||
it('parse transition', function () {
|
||||
var declarations = [
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'transition',
|
||||
value: 'margin-top 500ms ease-in-out 1s',
|
||||
position: {}
|
||||
}
|
||||
]
|
||||
var result = shorthandParser(declarations)
|
||||
expect(result).eql([
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'transition-property',
|
||||
value: 'margin-top',
|
||||
position: {}
|
||||
},
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'transition-duration',
|
||||
value: '500ms',
|
||||
position: {}
|
||||
},
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'transition-timing-function',
|
||||
value: 'ease-in-out',
|
||||
position: {}
|
||||
},
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'transition-delay',
|
||||
value: '1s',
|
||||
position: {}
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
it('parse margin', function () {
|
||||
var declarations = [
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin',
|
||||
value: '1px',
|
||||
position: {}
|
||||
},
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin',
|
||||
value: '21px 22px',
|
||||
position: {}
|
||||
},
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin',
|
||||
value: '31px 32px 33px',
|
||||
position: {}
|
||||
},
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin',
|
||||
value: '41px 42px 43px 44px',
|
||||
position: {}
|
||||
}
|
||||
]
|
||||
var result = shorthandParser(declarations)
|
||||
expect(result).eql([
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin-top',
|
||||
value: '1px',
|
||||
position: {}
|
||||
},
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin-right',
|
||||
value: '1px',
|
||||
position: {}
|
||||
},
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin-bottom',
|
||||
value: '1px',
|
||||
position: {}
|
||||
},
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin-left',
|
||||
value: '1px',
|
||||
position: {}
|
||||
},
|
||||
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin-top',
|
||||
value: '21px',
|
||||
position: {}
|
||||
},
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin-right',
|
||||
value: '22px',
|
||||
position: {}
|
||||
},
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin-bottom',
|
||||
value: '21px',
|
||||
position: {}
|
||||
},
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin-left',
|
||||
value: '22px',
|
||||
position: {}
|
||||
},
|
||||
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin-top',
|
||||
value: '31px',
|
||||
position: {}
|
||||
},
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin-right',
|
||||
value: '32px',
|
||||
position: {}
|
||||
},
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin-bottom',
|
||||
value: '33px',
|
||||
position: {}
|
||||
},
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin-left',
|
||||
value: '32px',
|
||||
position: {}
|
||||
},
|
||||
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin-top',
|
||||
value: '41px',
|
||||
position: {}
|
||||
},
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin-right',
|
||||
value: '42px',
|
||||
position: {}
|
||||
},
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin-bottom',
|
||||
value: '43px',
|
||||
position: {}
|
||||
},
|
||||
{
|
||||
type: 'declaration',
|
||||
property: 'margin-left',
|
||||
value: '44px',
|
||||
position: {}
|
||||
}
|
||||
])
|
||||
})
|
||||
})
|
445
deps/weex-styler/test/validate.js
vendored
Normal file
445
deps/weex-styler/test/validate.js
vendored
Normal file
@ -0,0 +1,445 @@
|
||||
var chai = require('chai')
|
||||
var sinon = require('sinon')
|
||||
var sinonChai = require('sinon-chai')
|
||||
var expect = chai.expect
|
||||
chai.use(sinonChai)
|
||||
|
||||
var styler = require('../')
|
||||
|
||||
describe('validate', function () {
|
||||
|
||||
it('parse normal style code', function (done) {
|
||||
var code = {
|
||||
foo: {
|
||||
color: '#FF0000',
|
||||
width: '200',
|
||||
position: 'sticky',
|
||||
zIndex: 4
|
||||
}
|
||||
}
|
||||
styler.validate(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle).eql({foo: {color: '#FF0000', width: 200, position: 'sticky', zIndex: 4}})
|
||||
expect(data.log).eql([])
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('parse length', function (done) {
|
||||
var code = {
|
||||
foo: {
|
||||
width: '200px',
|
||||
paddingLeft: '300',
|
||||
borderWidth: '1pt',
|
||||
left: '0',
|
||||
right: '0px',
|
||||
marginRight: 'asdf'
|
||||
}
|
||||
}
|
||||
styler.validate(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle).eql({foo: {
|
||||
width: '200px',
|
||||
paddingLeft: 300,
|
||||
borderWidth: '1pt',
|
||||
left: 0,
|
||||
right: '0px'
|
||||
}})
|
||||
expect(data.log).eql([
|
||||
{reason: 'ERROR: property value `asdf` is not supported for `margin-right` (only number and pixel values are supported)'}
|
||||
])
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('parse number', function (done) {
|
||||
var code = {
|
||||
foo: {
|
||||
opacity: '1'
|
||||
},
|
||||
bar: {
|
||||
opacity: '0.5'
|
||||
},
|
||||
baz: {
|
||||
opacity: 'a'
|
||||
},
|
||||
boo: {
|
||||
opacity: '0.5a'
|
||||
},
|
||||
zero: {
|
||||
opacity: '0'
|
||||
}
|
||||
}
|
||||
styler.validate(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle).eql({
|
||||
foo: {
|
||||
opacity: 1
|
||||
},
|
||||
bar: {
|
||||
opacity: 0.5
|
||||
},
|
||||
baz: {},
|
||||
boo: {},
|
||||
zero: {
|
||||
opacity: 0
|
||||
}
|
||||
})
|
||||
expect(data.log).eql([
|
||||
{reason: 'ERROR: property value `a` is not supported for `opacity` (only number is supported)'},
|
||||
{reason: 'ERROR: property value `0.5a` is not supported for `opacity` (only number is supported)'}
|
||||
])
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('parse integer', function (done) {
|
||||
var code = {
|
||||
foo: {
|
||||
zIndex: '1'
|
||||
},
|
||||
bar: {
|
||||
zIndex: '0.5'
|
||||
},
|
||||
baz: {
|
||||
zIndex: 'a'
|
||||
},
|
||||
boo: {
|
||||
zIndex: '0.5a'
|
||||
},
|
||||
zero: {
|
||||
zIndex: '0'
|
||||
}
|
||||
}
|
||||
styler.validate(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle).eql({
|
||||
foo: {
|
||||
zIndex: 1
|
||||
},
|
||||
bar: {},
|
||||
baz: {},
|
||||
boo: {},
|
||||
zero: {
|
||||
zIndex: 0
|
||||
}
|
||||
})
|
||||
expect(data.log).eql([
|
||||
{reason: 'ERROR: property value `0.5` is not supported for `z-index` (only integer is supported)'},
|
||||
{reason: 'ERROR: property value `a` is not supported for `z-index` (only integer is supported)'},
|
||||
{reason: 'ERROR: property value `0.5a` is not supported for `z-index` (only integer is supported)'}
|
||||
])
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('parse color', function (done) {
|
||||
var code = {
|
||||
foo: {
|
||||
color: '#FF0000',
|
||||
backgroundColor: '#ff0000'
|
||||
},
|
||||
bar: {
|
||||
color: '#F00',
|
||||
backgroundColor: '#f00'
|
||||
},
|
||||
baz: {
|
||||
color: 'red',
|
||||
backgroundColor: 'lightpink'
|
||||
},
|
||||
rgba: {
|
||||
color: 'rgb(23, 0, 255)',
|
||||
backgroundColor: 'rgba(234, 45, 99, .4)'
|
||||
},
|
||||
transparent: {
|
||||
color: 'transparent',
|
||||
backgroundColor: 'asdf'
|
||||
},
|
||||
errRgba: {
|
||||
color: 'rgb(266,0,255)',
|
||||
backgroundColor: 'rgba(234,45,99,1.3)'
|
||||
}
|
||||
}
|
||||
styler.validate(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle).eql({
|
||||
foo: {
|
||||
color: '#FF0000',
|
||||
backgroundColor: '#ff0000'
|
||||
},
|
||||
bar: {
|
||||
color: '#FF0000',
|
||||
backgroundColor: '#ff0000'
|
||||
},
|
||||
baz: {
|
||||
color: '#FF0000',
|
||||
backgroundColor: '#FFB6C1'
|
||||
},
|
||||
rgba: {
|
||||
color: 'rgb(23,0,255)',
|
||||
backgroundColor: 'rgba(234,45,99,0.4)'
|
||||
},
|
||||
transparent: {
|
||||
color: 'rgba(0,0,0,0)'
|
||||
},
|
||||
errRgba: {}
|
||||
})
|
||||
expect(data.log).eql([
|
||||
{reason: 'NOTE: property value `#F00` is autofixed to `#FF0000`'},
|
||||
{reason: 'NOTE: property value `#f00` is autofixed to `#ff0000`'},
|
||||
{reason: 'NOTE: property value `red` is autofixed to `#FF0000`'},
|
||||
{reason: 'NOTE: property value `lightpink` is autofixed to `#FFB6C1`'},
|
||||
{reason: 'ERROR: property value `asdf` is not valid for `background-color`'},
|
||||
{reason: 'ERROR: property value `rgb(266,0,255)` is not valid for `color`'},
|
||||
{reason: 'ERROR: property value `rgba(234,45,99,1.3)` is not valid for `background-color`'}
|
||||
])
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('parse color', function (done) {
|
||||
var code = {
|
||||
foo: {
|
||||
color: '#FF0000',
|
||||
backgroundColor: '#ff0000'
|
||||
},
|
||||
bar: {
|
||||
color: '#F00',
|
||||
backgroundColor: '#f00'
|
||||
},
|
||||
baz: {
|
||||
color: 'red',
|
||||
backgroundColor: 'lightpink'
|
||||
},
|
||||
rgba: {
|
||||
color: 'rgb(23, 0, 255)',
|
||||
backgroundColor: 'rgba(234, 45, 99, .4)'
|
||||
},
|
||||
transparent: {
|
||||
color: 'transparent',
|
||||
backgroundColor: 'asdf'
|
||||
},
|
||||
errRgba: {
|
||||
color: 'rgb(266,0,255)',
|
||||
backgroundColor: 'rgba(234,45,99,1.3)'
|
||||
}
|
||||
}
|
||||
styler.validate(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle).eql({
|
||||
foo: {
|
||||
color: '#FF0000',
|
||||
backgroundColor: '#ff0000'
|
||||
},
|
||||
bar: {
|
||||
color: '#FF0000',
|
||||
backgroundColor: '#ff0000'
|
||||
},
|
||||
baz: {
|
||||
color: '#FF0000',
|
||||
backgroundColor: '#FFB6C1'
|
||||
},
|
||||
rgba: {
|
||||
color: 'rgb(23,0,255)',
|
||||
backgroundColor: 'rgba(234,45,99,0.4)'
|
||||
},
|
||||
transparent: {
|
||||
color: 'rgba(0,0,0,0)'
|
||||
},
|
||||
errRgba: {}
|
||||
})
|
||||
expect(data.log).eql([
|
||||
{reason: 'NOTE: property value `#F00` is autofixed to `#FF0000`'},
|
||||
{reason: 'NOTE: property value `#f00` is autofixed to `#ff0000`'},
|
||||
{reason: 'NOTE: property value `red` is autofixed to `#FF0000`'},
|
||||
{reason: 'NOTE: property value `lightpink` is autofixed to `#FFB6C1`'},
|
||||
{reason: 'ERROR: property value `asdf` is not valid for `background-color`'},
|
||||
{reason: 'ERROR: property value `rgb(266,0,255)` is not valid for `color`'},
|
||||
{reason: 'ERROR: property value `rgba(234,45,99,1.3)` is not valid for `background-color`'}
|
||||
])
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('parse flex-wrap', function (done) {
|
||||
var code = {
|
||||
foo: { flexWrap: 'nowrap' },
|
||||
bar: { flexWrap: 'wrap' }
|
||||
}
|
||||
styler.validate(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle).eql({
|
||||
foo: { flexWrap: 'nowrap' },
|
||||
bar: { flexWrap: 'wrap' }
|
||||
})
|
||||
expect(data.log).eql([
|
||||
{reason: 'NOTE: property value `nowrap` is the DEFAULT value for `flex-wrap` (could be removed)'},
|
||||
{reason: 'NOTE: the flex-wrap property may have compatibility problem on native'},
|
||||
])
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('parse transition-property', function (done) {
|
||||
var code = {
|
||||
foo: {
|
||||
transitionProperty: 'margin-top'
|
||||
},
|
||||
bar: {
|
||||
transitionProperty: 'height'
|
||||
},
|
||||
foobar: {
|
||||
transitionProperty: 'margin-top, height'
|
||||
},
|
||||
baz: {
|
||||
transitionProperty: 'abc'
|
||||
}
|
||||
}
|
||||
styler.validate(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle).eql({
|
||||
foo: {
|
||||
transitionProperty: 'marginTop'
|
||||
},
|
||||
bar: {
|
||||
transitionProperty: 'height'
|
||||
},
|
||||
foobar: {
|
||||
transitionProperty: 'marginTop,height'
|
||||
},
|
||||
baz: {}
|
||||
})
|
||||
expect(data.log).eql([
|
||||
{reason: 'ERROR: property value `abc` is not supported for `transition-property` (only css property is valid)'}
|
||||
])
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('parse transition-duration & transition-delay', function (done) {
|
||||
var code = {
|
||||
foo: {
|
||||
transitionDuration: '200ms',
|
||||
transitionDelay: '0.5s'
|
||||
},
|
||||
bar: {
|
||||
transitionDuration: '200',
|
||||
transitionDelay: 'abc'
|
||||
}
|
||||
}
|
||||
styler.validate(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle).eql({
|
||||
foo: {
|
||||
transitionDuration: 200,
|
||||
transitionDelay: 500
|
||||
},
|
||||
bar: {
|
||||
transitionDuration: 200
|
||||
}
|
||||
})
|
||||
expect(data.log).eql([
|
||||
{reason: 'NOTE: property value `200ms` is autofixed to `200`'},
|
||||
{reason: 'NOTE: property value `0.5s` is autofixed to `500`'},
|
||||
{reason: 'ERROR: property value `abc` is not supported for `transition-delay` (only number of seconds and milliseconds is valid)'}
|
||||
])
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('parse transition-timing-function', function (done) {
|
||||
var code = {
|
||||
foo: {
|
||||
transitionTimingFunction: 'ease-in-out'
|
||||
},
|
||||
bar: {
|
||||
transitionTimingFunction: 'cubic-bezier(.88, 1.0, -0.67, 1.37)'
|
||||
},
|
||||
baz: {
|
||||
transitionTimingFunction: 'abc'
|
||||
}
|
||||
}
|
||||
styler.validate(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle).eql({
|
||||
foo: {
|
||||
transitionTimingFunction: 'ease-in-out'
|
||||
},
|
||||
bar: {
|
||||
transitionTimingFunction: 'cubic-bezier(0.88,1,-0.67,1.37)'
|
||||
},
|
||||
baz: {}
|
||||
})
|
||||
expect(data.log).eql([
|
||||
{reason: 'ERROR: property value `abc` is not supported for `transition-timing-function` (supported values are: `linear`|`ease`|`ease-in`|`ease-out`|`ease-in-out`|`cubic-bezier(n,n,n,n)`)'}
|
||||
])
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('parse unknown', function (done) {
|
||||
var code = {
|
||||
foo: {
|
||||
background: '#ff0000',
|
||||
abc: '123',
|
||||
def: '456px',
|
||||
ghi: '789pt',
|
||||
AbcDef: '456',
|
||||
abcDef: 'abc'
|
||||
}
|
||||
}
|
||||
styler.validate(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle).eql({
|
||||
foo: {
|
||||
background: '#ff0000',
|
||||
abc: 123,
|
||||
def: '456px',
|
||||
ghi: '789pt',
|
||||
AbcDef: 456,
|
||||
abcDef: 'abc'
|
||||
}
|
||||
})
|
||||
expect(data.log).eql([
|
||||
{reason: 'WARNING: `background` is not a standard property name (may not be supported), suggest `background-color`'},
|
||||
{reason: 'WARNING: `abc` is not a standard property name (may not be supported)'},
|
||||
{reason: 'WARNING: `def` is not a standard property name (may not be supported)'},
|
||||
{reason: 'WARNING: `ghi` is not a standard property name (may not be supported)'},
|
||||
{reason: 'WARNING: `-abc-def` is not a standard property name (may not be supported)'},
|
||||
{reason: 'WARNING: `abc-def` is not a standard property name (may not be supported)'}
|
||||
])
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('parse complex style code', function (done) {
|
||||
var code = {
|
||||
foo: {
|
||||
color: 'red',
|
||||
WebkitTransform: 'rotate(90deg)',
|
||||
width: '200px'
|
||||
}
|
||||
}
|
||||
styler.validate(code, function (err, data) {
|
||||
expect(err).is.undefined
|
||||
expect(data).is.an.object
|
||||
expect(data.jsonStyle).eql({foo: {color: '#FF0000', WebkitTransform: 'rotate(90deg)', width: '200px'}})
|
||||
expect(data.log).eql([
|
||||
{reason: 'NOTE: property value `red` is autofixed to `#FF0000`'},
|
||||
{reason: 'WARNING: `-webkit-transform` is not a standard property name (may not be supported)'}
|
||||
])
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
20
index.js
Normal file
20
index.js
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
module.exports = require('./lib/loader')
|
8356
package-lock.json
generated
Normal file
8356
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
72
package.json
Normal file
72
package.json
Normal file
@ -0,0 +1,72 @@
|
||||
{
|
||||
"name": "weex-loader",
|
||||
"version": "0.7.12",
|
||||
"description": "a webpack loader for weex",
|
||||
"main": "index.js",
|
||||
"author": "terrykingcha <terrykingcha@gmail.com>",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/weexteam/weex-loader.git"
|
||||
},
|
||||
"licenses": "Apache-2.0",
|
||||
"keywords": [
|
||||
"weex",
|
||||
"loader",
|
||||
"webpack",
|
||||
"transformer"
|
||||
],
|
||||
"scripts": {
|
||||
"clear": " ",
|
||||
"lint": "eslint --fix src",
|
||||
"dev": "gazeer -p \"src/*.js\" -c \"npm run build\"",
|
||||
"build": "node node_modules/babel-cli/bin/babel.js src --out-dir lib",
|
||||
"test:build": "cd test && webpack --config ./webpack.config.js",
|
||||
"test": "npm run test:build",
|
||||
"rich:build": "cd sample && webpack --config ../webpack.rich.config.js",
|
||||
"rich": "npm run lint && npm run build && npm run rich:build",
|
||||
"lite:build": "cd sample && webpack --config ../webpack.lite.config.js",
|
||||
"lite": "npm run lint && npm run build && npm run lite:build",
|
||||
"ace:build": "webpack --config ./webpack.config.js",
|
||||
"ace": "npm run lint && npm run build && npm run ace:build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.10.1",
|
||||
"babel-core": "^6.10.4",
|
||||
"chai": "^3.5.0",
|
||||
"coffee-loader": "^0.7.2",
|
||||
"coffee-script": "^1.10.0",
|
||||
"eslint": "^2.13.1",
|
||||
"gazeer": "^0.1.1",
|
||||
"jade": "^1.11.0",
|
||||
"jade-html-loader": "0.0.3",
|
||||
"js-base64": "^2.1.9",
|
||||
"mocha": "^2.4.5",
|
||||
"postcss-cssnext": "^2.7.0",
|
||||
"postcss-loader": "^0.9.1",
|
||||
"sinon": "^1.17.3",
|
||||
"sinon-chai": "^2.8.0",
|
||||
"webpack": "~1.13.0",
|
||||
"weex-components": "^0.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-loader": "^6.2.4",
|
||||
"babel-plugin-transform-runtime": "^6.9.0",
|
||||
"babel-preset-es2015": "^6.9.0",
|
||||
"babel-runtime": "^6.9.2",
|
||||
"hash-sum": "^1.0.2",
|
||||
"loader-utils": "^1.1.0",
|
||||
"md5": "^2.1.0",
|
||||
"parse5": "^2.1.5",
|
||||
"source-map": "^0.5.6",
|
||||
"weex-scripter": "^0.1.6",
|
||||
"weex-styler": "^0.3.1",
|
||||
"weex-templater": "^0.3.5",
|
||||
"weex-transformer": "^0.4.6",
|
||||
"weex-vue-loader": "^0.7.0"
|
||||
},
|
||||
"babel": {
|
||||
"presets": [
|
||||
"es2015"
|
||||
]
|
||||
}
|
||||
}
|
53
src/element.js
Normal file
53
src/element.js
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import loaderUtils from 'loader-utils'
|
||||
|
||||
import {
|
||||
extractBlocks
|
||||
} from './parser'
|
||||
|
||||
module.exports = function (source) {
|
||||
this.cacheable && this.cacheable()
|
||||
|
||||
const callback = this.async()
|
||||
const loaderQuery = loaderUtils.getOptions(this) || {}
|
||||
const resourceQuery = loaderUtils.parseQuery(this.resourceQuery) || {}
|
||||
const name = resourceQuery.name
|
||||
|
||||
let contentPromise
|
||||
|
||||
if (loaderQuery.extract) {
|
||||
contentPromise =
|
||||
extractBlocks(source, 'elements')
|
||||
}
|
||||
else {
|
||||
contentPromise = Promise.resolve({ content: source })
|
||||
}
|
||||
|
||||
contentPromise.then(elements => {
|
||||
if (loaderQuery.raw) {
|
||||
return elements[name].content
|
||||
}
|
||||
}).then(result => {
|
||||
callback(null, result)
|
||||
}).catch(e => {
|
||||
callback(e, '')
|
||||
})
|
||||
}
|
200
src/json.js
Normal file
200
src/json.js
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
const path = require('path')
|
||||
|
||||
const cardJsonPlugin = require('./cardJson-plugin')
|
||||
const transCardArray = require('./templater/bind').transCardArray
|
||||
const ResourceReferenceParsing = require('./resource-reference-script')
|
||||
import { logWarn } from './util'
|
||||
|
||||
const REG_EVENT_STRING = /("\s*\$event\..+")|('\s*\$event\..+')/g
|
||||
const REG_EVENT = /\$event\.[\w]+/g
|
||||
const REG_THIS = /this\..*/g
|
||||
|
||||
module.exports = function (source) {
|
||||
this.cacheable && this.cacheable()
|
||||
|
||||
if (process.env.DEVICE_LEVEL === 'card') {
|
||||
try {
|
||||
source = parseCard(this, source)
|
||||
}
|
||||
catch (e) {
|
||||
logWarn(this, [{
|
||||
reason: 'ERROR: Failed to parse the file : ' + this.resourcePath + `\n${e}`
|
||||
}])
|
||||
return '{}'
|
||||
}
|
||||
return '{}'
|
||||
}
|
||||
return `module.exports = ${source}`
|
||||
}
|
||||
|
||||
function parseCard(_this, source) {
|
||||
source = source.replace(/\/\*((\n|\r|.)*?)\*\//mg,"")
|
||||
source = source.replace(/(\s|\;|^|\{|\})\/\/.*$/mg,"$1")
|
||||
if (source.trim().indexOf('export default') === 0) {
|
||||
source = source.replace('export default', '')
|
||||
}
|
||||
const extName = path.extname(_this.resourcePath)
|
||||
if (extName === '.json' || extName === '.js') {
|
||||
source = ResourceReferenceParsing(source)
|
||||
source = source.replace(REG_EVENT_STRING, item => {
|
||||
return item.slice(1, -1)
|
||||
})
|
||||
source = source.replace(REG_EVENT, item => {
|
||||
return '"' + item + '"'
|
||||
})
|
||||
source = source.replace(REG_THIS, item => {
|
||||
if (item.charAt(item.length - 1) !== '\"' && item.charAt(item.length - 1) !== '\'' &&
|
||||
item.slice(-2) !== '\"\,' && item.slice(-2) !== '\'\,') {
|
||||
if (item.charAt(item.length - 1) === ',') {
|
||||
item = `"{{${transCardArray(item.slice(0, -1))}}}",`.replace(/this\./g, '')
|
||||
} else {
|
||||
item = `"{{${transCardArray(item)}}}"`.replace(/this\./g, '')
|
||||
}
|
||||
}
|
||||
return item
|
||||
})
|
||||
}
|
||||
source = JSON.stringify(eval('(' + source + ')'))
|
||||
const jsonPaths = mkJsonFiles(_this)
|
||||
cardJsonPlugin.compileJson(_this._compiler, 'init', jsonPaths.indexJson)
|
||||
if (jsonPaths.element) {
|
||||
if (extName === '.json' || extName === '.js') {
|
||||
cardJsonPlugin.compileJson(_this._compiler, jsonPaths.element, jsonPaths.indexJson,
|
||||
processActions(JSON.parse(source).actions, _this), jsonPaths.element, 'actions')
|
||||
cardJsonPlugin.compileJson(_this._compiler, jsonPaths.element, jsonPaths.indexJson,
|
||||
validateData(JSON.parse(source).data, _this), jsonPaths.element, 'data')
|
||||
cardJsonPlugin.compileJson(_this._compiler, jsonPaths.element, jsonPaths.indexJson,
|
||||
validateData(JSON.parse(source).apiVersion, _this), jsonPaths.element, 'apiVersion')
|
||||
cardJsonPlugin.compileJson(_this._compiler, jsonPaths.element, jsonPaths.indexJson,
|
||||
replacePropsArray(JSON.parse(source).props, _this), jsonPaths.element, 'props')
|
||||
} else if (extName === '.css' || extName === '.less' || extName === '.sass' || extName === '.scss') {
|
||||
cardJsonPlugin.compileJson(_this._compiler, jsonPaths.element, jsonPaths.indexJson, JSON.parse(source),
|
||||
jsonPaths.element, 'styles')
|
||||
} else if (extName === '.hml') {
|
||||
cardJsonPlugin.compileJson(_this._compiler, jsonPaths.element, jsonPaths.indexJson, JSON.parse(source),
|
||||
jsonPaths.element, 'template')
|
||||
}
|
||||
} else {
|
||||
if (extName === '.json' || extName === '.js') {
|
||||
cardJsonPlugin.compileJson(_this._compiler, 'actions', jsonPaths.indexJson,
|
||||
processActions(JSON.parse(source).actions, _this), 'actions')
|
||||
cardJsonPlugin.compileJson(_this._compiler, 'data', jsonPaths.indexJson,
|
||||
validateData(JSON.parse(source).data, _this), 'data')
|
||||
cardJsonPlugin.compileJson(_this._compiler, 'apiVersion', jsonPaths.indexJson,
|
||||
validateData(JSON.parse(source).apiVersion, _this), 'apiVersion')
|
||||
} else if (extName === '.css' || extName === '.less' || extName === '.sass' || extName === '.scss') {
|
||||
cardJsonPlugin.compileJson(_this._compiler, 'styles', jsonPaths.indexJson, JSON.parse(source), 'styles')
|
||||
} else if (extName === '.hml') {
|
||||
cardJsonPlugin.compileJson(_this._compiler, 'template', jsonPaths.indexJson, JSON.parse(source), 'template')
|
||||
}
|
||||
}
|
||||
return source
|
||||
}
|
||||
|
||||
function mkJsonFiles(_this) {
|
||||
let indexJson = ''
|
||||
let element
|
||||
const resourceQuery = _this.resourceQuery.split('#');
|
||||
const entrys = _this._compiler.options.entry
|
||||
const resourcePath = _this.resourcePath
|
||||
Object.keys(entrys).forEach(function (key) {
|
||||
if (path.dirname(path.resolve(entrys[key]['import'][0])) === path.dirname(resourcePath)) {
|
||||
indexJson = key + '.json'
|
||||
} else {
|
||||
indexJson = key + '.json'
|
||||
element = resourceQuery[0].slice(1)
|
||||
}
|
||||
})
|
||||
indexJson = path.resolve(_this._compiler.options.output.path, indexJson)
|
||||
return { indexJson: indexJson, element: element }
|
||||
}
|
||||
|
||||
function replacePropsArray(propsValue, _this) {
|
||||
if (!propsValue) {
|
||||
return propsValue
|
||||
}
|
||||
if (Array.isArray(propsValue)) {
|
||||
const propsObject = {}
|
||||
propsValue.forEach(item => {
|
||||
if (typeof(item) !== 'string') {
|
||||
logWarn(_this, [{
|
||||
reason: `WARNING: The props value type should be 'string', not '${typeof(item)}' in props array in custom elements.`
|
||||
}])
|
||||
}
|
||||
propsObject[item] = { 'default': '' }
|
||||
})
|
||||
propsValue = propsObject
|
||||
} else if (Object.prototype.toString.call(propsValue) === '[object Object]') {
|
||||
Object.keys(propsValue).forEach(item => {
|
||||
if (Object.prototype.toString.call(propsValue[item]) !== '[object Object]') {
|
||||
logWarn(_this, [{
|
||||
reason: 'WARNING: The props default value type can only be Object in custom elements.'
|
||||
}])
|
||||
}
|
||||
if (!propsValue[item].hasOwnProperty('default')) {
|
||||
propsValue[item] = { 'default': '' }
|
||||
}
|
||||
})
|
||||
} else {
|
||||
logWarn(_this, [{
|
||||
reason: 'WARNING: The props type can only be Array or Object in custom elements.'
|
||||
}])
|
||||
}
|
||||
return propsValue
|
||||
}
|
||||
|
||||
function processActions(actionsValue, _this) {
|
||||
if (Object.prototype.toString.call(actionsValue) === '[object Object]') {
|
||||
Object.keys(actionsValue).forEach(item => {
|
||||
if (actionsValue[item].method) {
|
||||
if (typeof(actionsValue[item].method) === 'string') {
|
||||
if (actionsValue[item].method.toLowerCase() !== actionsValue[item].method) {
|
||||
logWarn(_this, [{
|
||||
reason: `WARNING: The key method '${actionsValue[item].method}' in the actions don't support uppercase letters.`
|
||||
}])
|
||||
actionsValue[item].method = actionsValue[item].method.toLowerCase()
|
||||
}
|
||||
} else {
|
||||
logWarn(_this, [{
|
||||
reason: `WARNING: The key method type in the actions should be 'string', not '${typeof(actionsValue[item].method)}'.`
|
||||
}])
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
if (actionsValue) {
|
||||
logWarn(_this, [{
|
||||
reason: 'WARNING: The actions value type can only be Object.'
|
||||
}])
|
||||
}
|
||||
}
|
||||
return actionsValue
|
||||
}
|
||||
|
||||
function validateData(dataValue, _this) {
|
||||
if (dataValue && Object.prototype.toString.call(dataValue) !== '[object Object]') {
|
||||
logWarn(_this, [{
|
||||
reason: 'WARNING: The data value type can only be Object.'
|
||||
}])
|
||||
}
|
||||
return dataValue
|
||||
}
|
32
src/legacy.js
Normal file
32
src/legacy.js
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export function useScripter () {
|
||||
warn('useScripter()')
|
||||
}
|
||||
export function useStyler () {
|
||||
warn('useStyler()')
|
||||
}
|
||||
export function useTemplater () {
|
||||
warn('useTemplater()')
|
||||
}
|
||||
|
||||
function warn (method) {
|
||||
console.warn(`\u001b[1;32m[Warn]\u001b[0m: method ${method} in weex-loader is no more necessary`)
|
||||
}
|
452
src/loader.js
Normal file
452
src/loader.js
Normal file
@ -0,0 +1,452 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import loaderUtils from 'loader-utils'
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
|
||||
import * as legacy from './legacy'
|
||||
import {
|
||||
parseFragment
|
||||
}
|
||||
from './parser'
|
||||
import {
|
||||
getNameByPath,
|
||||
getRequireString,
|
||||
stringifyLoaders,
|
||||
logWarn,
|
||||
loadBabelModule
|
||||
}
|
||||
from './util'
|
||||
import { isReservedTag } from './templater/component_validator'
|
||||
|
||||
const { DEVICE_LEVEL } = require('./lite/lite-enum')
|
||||
const loaderPath = __dirname
|
||||
const defaultLoaders = {
|
||||
none: '',
|
||||
main: path.resolve(loaderPath, 'loader.js'),
|
||||
template: path.resolve(loaderPath, 'template.js'),
|
||||
style: path.resolve(loaderPath, 'style.js'),
|
||||
script: path.resolve(loaderPath, 'script.js'),
|
||||
json: path.resolve(loaderPath, 'json.js'),
|
||||
babel: loadBabelModule('babel-loader'),
|
||||
manifest: path.resolve(loaderPath, 'manifest-loader.js'),
|
||||
resourceReferenceScript: path.resolve(loaderPath, 'resource-reference-script.js')
|
||||
}
|
||||
|
||||
function getLoaderString (type, config) {
|
||||
config = config || {}
|
||||
const customLoader = loadCustomLoader(config)
|
||||
let loaders
|
||||
switch (type) {
|
||||
case 'main':
|
||||
return mainLoaderString(loaders)
|
||||
case 'element':
|
||||
return elementLoaderString(loaders, config)
|
||||
case 'template':
|
||||
return templateLoaderString(loaders, config, customLoader)
|
||||
case 'style':
|
||||
return styleLoaderString(loaders, config, customLoader)
|
||||
case 'script':
|
||||
return scriptLoaderString(loaders, config, customLoader)
|
||||
case 'config':
|
||||
return configLoaderString(loaders, config)
|
||||
case 'data':
|
||||
return dataLoaderString(loaders, config)
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
function loadCustomLoader (config) {
|
||||
if (config.lang && config.customLang[config.lang]) {
|
||||
return loadBabelModule(config.customLang[config.lang][0])
|
||||
}
|
||||
}
|
||||
|
||||
function mainLoaderString (loaders) {
|
||||
loaders = [{
|
||||
name: defaultLoaders.main
|
||||
}]
|
||||
return stringifyLoaders(loaders)
|
||||
}
|
||||
|
||||
function elementLoaderString (loaders, config) {
|
||||
loaders = [{
|
||||
name: defaultLoaders.main,
|
||||
query: {
|
||||
element: config.source ? undefined : true
|
||||
}
|
||||
}]
|
||||
return stringifyLoaders(loaders)
|
||||
}
|
||||
|
||||
function templateLoaderString (loaders, config, customLoader) {
|
||||
loaders = [{
|
||||
name: defaultLoaders.json
|
||||
}, {
|
||||
name: defaultLoaders.template
|
||||
}]
|
||||
if (customLoader) {
|
||||
loaders = loaders.concat(customLoader)
|
||||
}
|
||||
return stringifyLoaders(loaders)
|
||||
}
|
||||
|
||||
function styleLoaderString (loaders, config, customLoader) {
|
||||
loaders = [{
|
||||
name: defaultLoaders.json
|
||||
}, {
|
||||
name: defaultLoaders.style
|
||||
}]
|
||||
if (customLoader) {
|
||||
loaders = loaders.concat(customLoader)
|
||||
}
|
||||
return stringifyLoaders(loaders)
|
||||
}
|
||||
|
||||
function scriptLoaderString (loaders, config, customLoader) {
|
||||
loaders = [{
|
||||
name: defaultLoaders.script
|
||||
}]
|
||||
if (customLoader) {
|
||||
loaders = loaders.concat(customLoader)
|
||||
}
|
||||
else {
|
||||
loaders.push({
|
||||
name: defaultLoaders.babel,
|
||||
query: {
|
||||
presets: [loadBabelModule('@babel/preset-env')],
|
||||
plugins: [loadBabelModule('@babel/plugin-transform-modules-commonjs')],
|
||||
comments: 'false'
|
||||
}
|
||||
})
|
||||
loaders.push({
|
||||
name: defaultLoaders.resourceReferenceScript
|
||||
})
|
||||
}
|
||||
if (config.app) {
|
||||
loaders.push({
|
||||
name: defaultLoaders.manifest,
|
||||
query: {
|
||||
path: config.source
|
||||
}
|
||||
})
|
||||
}
|
||||
return stringifyLoaders(loaders)
|
||||
}
|
||||
|
||||
function configLoaderString (loaders, config) {
|
||||
loaders = [{
|
||||
name: defaultLoaders.json
|
||||
}]
|
||||
return stringifyLoaders(loaders)
|
||||
}
|
||||
|
||||
function dataLoaderString (loaders, config) {
|
||||
loaders = [{
|
||||
name: defaultLoaders.json
|
||||
}]
|
||||
return stringifyLoaders(loaders)
|
||||
}
|
||||
|
||||
function loader (source) {
|
||||
this.cacheable && this.cacheable()
|
||||
|
||||
const options = {
|
||||
lang: {
|
||||
sass:['sass-loader'],
|
||||
scss:['sass-loader'],
|
||||
less:['less-loader']
|
||||
}
|
||||
}
|
||||
const customLang = options.lang || {}
|
||||
const resourceQuery = this.resourceQuery && loaderUtils.parseQuery(this.resourceQuery) || {}
|
||||
const isEntry = resourceQuery.entry
|
||||
const dirName = path.parse(this.resourcePath)
|
||||
const name = isEntry ? dirName.name : resourceQuery.name || getNameByPath(this.resourcePath)
|
||||
if (isReservedTag(name)) {
|
||||
logWarn(this, [{
|
||||
reason: 'ERROR: The file name cannot contain reserved tag name: ' + name
|
||||
}])
|
||||
return ''
|
||||
}
|
||||
let output = ''
|
||||
// import app.js
|
||||
output += loadApp(this, name, isEntry, customLang)
|
||||
output += loadPage(this, name, isEntry, customLang, source)
|
||||
return output
|
||||
}
|
||||
|
||||
function loadApp (_this, name, isEntry, customLang) {
|
||||
let output = ''
|
||||
let extcss = false
|
||||
if (_this.resourcePath.indexOf('app.js') > 0) {
|
||||
const filename = _this.resourcePath.replace(path.extname(_this.resourcePath).toString(), '')
|
||||
// find css
|
||||
const cssFileName = filename + '.css'
|
||||
if (!fs.existsSync(cssFileName)) {
|
||||
extcss = false
|
||||
}
|
||||
else {
|
||||
extcss = true
|
||||
output += 'var $app_style$ = ' + getRequireString(_this, getLoaderString('style', {
|
||||
customLang,
|
||||
lang: undefined,
|
||||
element: undefined,
|
||||
elementName: undefined,
|
||||
source: cssFileName
|
||||
}), cssFileName)
|
||||
}
|
||||
output += 'var $app_script$ = ' + getRequireString(_this, getLoaderString('script', {
|
||||
customLang,
|
||||
lang: undefined,
|
||||
element: undefined,
|
||||
elementName: undefined,
|
||||
source: _this.resourcePath,
|
||||
app: true
|
||||
}), _this.resourcePath)
|
||||
|
||||
if (process.env.DEVICE_LEVEL === DEVICE_LEVEL.RICH) {
|
||||
output += `
|
||||
$app_define$('@app-application/${name}', [], function($app_require$, $app_exports$, $app_module$) {
|
||||
` + `
|
||||
$app_script$($app_module$, $app_exports$, $app_require$)
|
||||
if ($app_exports$.__esModule && $app_exports$.default) {
|
||||
$app_module$.exports = $app_exports$.default
|
||||
}
|
||||
` + (extcss ? `
|
||||
$app_module$.exports.style = $app_style$
|
||||
` : '')
|
||||
+ `
|
||||
})
|
||||
`
|
||||
if (isEntry) {
|
||||
output += `$app_bootstrap$('@app-application/${name}'` + ',undefined' + ',undefined' + `)`
|
||||
}
|
||||
}
|
||||
if (process.env.DEVICE_LEVEL === DEVICE_LEVEL.LITE) {
|
||||
output += `var options=$app_script$\n if ($app_script$.__esModule) {\n
|
||||
options = $app_script$.default;\n }\n` +
|
||||
(extcss ? `options.styleSheet=$app_style$\n` : ``) +
|
||||
`module.exports=new ViewModel(options);`
|
||||
}
|
||||
return output
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
function loadPage (_this, name, isEntry, customLang, source) {
|
||||
let output = ''
|
||||
if (path.extname(_this.resourcePath).match(/\.hml/)) {
|
||||
const filename = _this.resourcePath.replace(path.extname(_this.resourcePath).toString(), '')
|
||||
const resourcePath = _this.resourcePath
|
||||
const loaderQuery = loaderUtils.getOptions(_this) || {}
|
||||
const isElement = loaderQuery.element
|
||||
const frag = parseFragment(source)
|
||||
const elementNames = []
|
||||
const elementLength = frag.element.length
|
||||
output += loadPageCheckElementLength(_this, elementLength, frag, elementNames, resourcePath, customLang)
|
||||
|
||||
output += 'var $app_template$ = ' + getRequireString(_this, getLoaderString('template', {
|
||||
customLang,
|
||||
lang: undefined,
|
||||
element: isElement,
|
||||
elementName: isElement ? name : undefined,
|
||||
source: _this.resourcePath
|
||||
}), _this.resourcePath)
|
||||
|
||||
// find css
|
||||
const cssContent = loadPageFindCss(_this, filename, customLang)
|
||||
const extcss = cssContent.extcss
|
||||
output += cssContent.output
|
||||
|
||||
// find js
|
||||
const scriptContent = loadPageFindJs(_this, filename, customLang)
|
||||
const extscript = scriptContent.extscript
|
||||
output += scriptContent.output
|
||||
|
||||
output += process.env.DEVICE_LEVEL === DEVICE_LEVEL.RICH ? loadPageCheckRich(name, extscript, extcss, isEntry) :
|
||||
loadPageCheckLite(extscript, extcss)
|
||||
return output
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
function loadPageCheckElementLength (_this, elementLength, frag, elementNames, resourcePath, customLang) {
|
||||
let output = ''
|
||||
if (elementLength) {
|
||||
for (let i = 0; i < elementLength; i++) {
|
||||
const element = frag.element[i]
|
||||
let src = resourcePath
|
||||
if (element.src) {
|
||||
src = element.src
|
||||
if (!src.match(/\.hml$/)) {
|
||||
src = src.concat('.hml')
|
||||
}
|
||||
const filePath = path.join(path.dirname(resourcePath), src)
|
||||
if (!fs.existsSync(filePath) && src.match(/^(\/|\.)/)) {
|
||||
logWarn(_this, [{
|
||||
reason: 'ERROR: The file path of custom element does not exist, src: ' + src
|
||||
}])
|
||||
return ''
|
||||
}
|
||||
if (!element.name) {
|
||||
element.name = path.parse(src).name
|
||||
}
|
||||
}
|
||||
else {
|
||||
logWarn(_this, [{
|
||||
reason: 'ERROR: src attributes must be set for custom elements.'
|
||||
}])
|
||||
return ''
|
||||
}
|
||||
elementNames.push(element.name)
|
||||
output += getRequireString(_this, getLoaderString('element', {
|
||||
customLang,
|
||||
name: element.name,
|
||||
source: src
|
||||
}), `${src}?name=${element.name.toLowerCase()}`)
|
||||
}
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
function loadPageFindCss (_this, filename, customLang) {
|
||||
let output = ''
|
||||
let extcss = false
|
||||
const cssFileName = filename + '.css'
|
||||
if (fs.existsSync(cssFileName)) {
|
||||
extcss = true
|
||||
output = 'var $app_style$ = ' + getRequireString(_this, getLoaderString('style', {
|
||||
customLang,
|
||||
lang: undefined,
|
||||
element: undefined,
|
||||
elementName: undefined,
|
||||
source: cssFileName
|
||||
}), cssFileName)
|
||||
}
|
||||
else {
|
||||
// find less
|
||||
const lessFileName = filename + '.less'
|
||||
if (fs.existsSync(lessFileName)) {
|
||||
extcss = true
|
||||
output = 'var $app_style$ = ' + getRequireString(_this, getLoaderString('style', {
|
||||
customLang,
|
||||
lang: 'less',
|
||||
element: undefined,
|
||||
elementName: undefined,
|
||||
source: lessFileName
|
||||
}), lessFileName)
|
||||
}
|
||||
else {
|
||||
// find scss
|
||||
const scssFileName = filename + '.scss'
|
||||
if (fs.existsSync(scssFileName)) {
|
||||
extcss = true
|
||||
output = 'var $app_style$ = ' + getRequireString(_this, getLoaderString('style', {
|
||||
customLang,
|
||||
lang: 'scss',
|
||||
element: undefined,
|
||||
elementName: undefined,
|
||||
source: scssFileName
|
||||
}), scssFileName)
|
||||
}
|
||||
else {
|
||||
// find sass
|
||||
const sassFileName = filename + '.sass'
|
||||
if (fs.existsSync(sassFileName)) {
|
||||
extcss = true
|
||||
output = 'var $app_style$ = ' + getRequireString(_this, getLoaderString('style', {
|
||||
customLang,
|
||||
lang: 'sass',
|
||||
element: undefined,
|
||||
elementName: undefined,
|
||||
source: sassFileName
|
||||
}), sassFileName)
|
||||
}
|
||||
else {
|
||||
extcss = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
extcss: extcss,
|
||||
output: output
|
||||
}
|
||||
}
|
||||
|
||||
function loadPageFindJs (_this, filename, customLang) {
|
||||
let output = ''
|
||||
let extscript = false
|
||||
const jsFileName = filename + '.js'
|
||||
if (!fs.existsSync(jsFileName)) {
|
||||
extscript = false
|
||||
console.log('missing ' + jsFileName)
|
||||
}
|
||||
else {
|
||||
extscript = true
|
||||
output = 'var $app_script$ = ' + getRequireString(_this, getLoaderString('script', {
|
||||
customLang,
|
||||
lang: undefined,
|
||||
element: undefined,
|
||||
elementName: undefined,
|
||||
source: jsFileName
|
||||
}), jsFileName)
|
||||
}
|
||||
return {
|
||||
extscript: extscript,
|
||||
output: output
|
||||
}
|
||||
}
|
||||
|
||||
function loadPageCheckRich (name, extscript, extcss, isEntry) {
|
||||
let output = ''
|
||||
output += `
|
||||
$app_define$('@app-component/${name}', [], function($app_require$, $app_exports$, $app_module$) {
|
||||
` + (extscript ? `
|
||||
$app_script$($app_module$, $app_exports$, $app_require$)
|
||||
if ($app_exports$.__esModule && $app_exports$.default) {
|
||||
$app_module$.exports = $app_exports$.default
|
||||
}
|
||||
` : '') + `
|
||||
$app_module$.exports.template = $app_template$
|
||||
` + (extcss ? `
|
||||
$app_module$.exports.style = $app_style$
|
||||
` : '') + `
|
||||
})
|
||||
`
|
||||
if (isEntry) {
|
||||
output += `$app_bootstrap$('@app-component/${name}'` + ',undefined' + ',undefined' + `)`
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
function loadPageCheckLite (extscript, extcss) {
|
||||
return (extscript ? `var options=$app_script$\n if ($app_script$.__esModule) {\n
|
||||
options = $app_script$.default;\n }\n` : `var options={}\n`) +
|
||||
(extcss ? `options.styleSheet=$app_style$\n` : ``) +
|
||||
`options.render=$app_template$;\nmodule.exports=new ViewModel(options);`
|
||||
}
|
||||
|
||||
for (const key in legacy) {
|
||||
loader[key] = legacy[key]
|
||||
}
|
||||
module.exports = loader
|
150
src/parser.js
Normal file
150
src/parser.js
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import parse5 from 'parse5'
|
||||
import templater from './templater'
|
||||
import styler from './styler'
|
||||
import scripter from './scripter'
|
||||
import { checkTagName } from './templater/component_validator'
|
||||
|
||||
import {
|
||||
FUNC_START_REG,
|
||||
FUNC_END_REG,
|
||||
stringifyFunction
|
||||
} from './util'
|
||||
|
||||
function getAttribute (node, name) {
|
||||
if (node.attrs) {
|
||||
let i = node.attrs.length
|
||||
let attr
|
||||
while (i--) {
|
||||
attr = node.attrs[i]
|
||||
if (attr.name === name) {
|
||||
return attr.value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function extractDependencies (node, deps) {
|
||||
if (node.childNodes) {
|
||||
node.childNodes.forEach(child => {
|
||||
checkTagName(child, {
|
||||
result: {},
|
||||
deps,
|
||||
log: []
|
||||
})
|
||||
extractDependencies(child, deps)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function parseFragment (source) {
|
||||
const fragment = parse5.parseFragment(source, {
|
||||
locationInfo: true
|
||||
})
|
||||
|
||||
const output = {
|
||||
deps: [],
|
||||
element: [],
|
||||
template: [],
|
||||
style: [],
|
||||
script: [],
|
||||
data: [],
|
||||
config: []
|
||||
}
|
||||
|
||||
fragment.childNodes.forEach(node => {
|
||||
let type
|
||||
|
||||
if (node.tagName === 'script') {
|
||||
type = getAttribute(node, 'type')
|
||||
if (type !== 'data' && type !== 'config') {
|
||||
type = 'script'
|
||||
}
|
||||
}
|
||||
else {
|
||||
type = node.tagName
|
||||
}
|
||||
if (type === 'we-element') {
|
||||
console.warn(`<we-element name="${getAttribute(node, 'name')}"> is deprecated, please use <element> instead.`)
|
||||
type = 'element'
|
||||
}
|
||||
|
||||
if (!output[type]) {
|
||||
return
|
||||
}
|
||||
|
||||
const name = getAttribute(node, 'name')
|
||||
const src = getAttribute(node, 'src')
|
||||
const lang = getAttribute(node, 'lang')
|
||||
|
||||
output[type].push({
|
||||
name,
|
||||
src,
|
||||
lang,
|
||||
node
|
||||
})
|
||||
|
||||
if (type === 'template') {
|
||||
const deps = []
|
||||
extractDependencies(node.content, deps)
|
||||
output.deps = deps
|
||||
}
|
||||
})
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
export function parseTemplate (source, resourcePath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
templater.parse(source, (err, obj) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
}
|
||||
else {
|
||||
// parse json to string and treat function specially
|
||||
let parsed = JSON.stringify(obj.jsonTemplate, stringifyFunction, ' ')
|
||||
parsed = parsed.replace(FUNC_START_REG, '').replace(FUNC_END_REG, '')
|
||||
resolve({ parsed, log: obj.log })
|
||||
}
|
||||
}, resourcePath)
|
||||
})
|
||||
}
|
||||
|
||||
export function parseStyle (source, resourcePath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
styler.parse(source, (err, obj) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
}
|
||||
else {
|
||||
const parsed = JSON.stringify(obj.jsonStyle, null, 2)
|
||||
resolve({ parsed, log: obj.log })
|
||||
}
|
||||
}, resourcePath)
|
||||
})
|
||||
}
|
||||
|
||||
export function parseScript (source) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const parsed = scripter.fix(source)
|
||||
resolve({ parsed })
|
||||
})
|
||||
}
|
75
src/script.js
Normal file
75
src/script.js
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import path from 'path'
|
||||
|
||||
import {
|
||||
logWarn,
|
||||
parseRequireModule
|
||||
} from './util'
|
||||
import {
|
||||
parseScript
|
||||
} from './parser'
|
||||
|
||||
const { DEVICE_LEVEL } = require('./lite/lite-enum')
|
||||
|
||||
module.exports = function (source, map) {
|
||||
this.cacheable && this.cacheable()
|
||||
const callback = this.async()
|
||||
|
||||
parseScript(source, this.resourcePath)
|
||||
.then(({
|
||||
parsed, log
|
||||
}) => {
|
||||
if (log && log.length) {
|
||||
logWarn(this, log)
|
||||
}
|
||||
parsed = parseRequireModule(parsed)
|
||||
if (process.env.DEVICE_LEVEL === DEVICE_LEVEL.RICH) {
|
||||
if (path.basename(this.resourcePath) !== 'app.js') {
|
||||
parsed += `\nvar moduleOwn = exports.default || module.exports;\nvar accessors = ['public', 'protected', 'private'];
|
||||
if (moduleOwn.data && accessors.some(function (acc) {
|
||||
return moduleOwn[acc];
|
||||
})) {\n throw new Error('For VM objects, attribute data must not coexist with public, protected, or private. Please replace data with public.');
|
||||
} else if (!moduleOwn.data) {
|
||||
moduleOwn.data = {};\n moduleOwn._descriptor = {};\n accessors.forEach(function(acc) {
|
||||
var accType = typeof moduleOwn[acc];
|
||||
if (accType === 'object') {
|
||||
moduleOwn.data = Object.assign(moduleOwn.data, moduleOwn[acc]);
|
||||
for (var name in moduleOwn[acc]) {
|
||||
moduleOwn._descriptor[name] = {access : acc};
|
||||
}
|
||||
} else if (accType === 'function') {
|
||||
console.warn('For VM objects, attribute ' + acc + ' value must not be a function. Change the value to an object.');
|
||||
}\n });\n}`
|
||||
}
|
||||
let result = `module.exports = function(module, exports, $app_require$){${parsed}}`
|
||||
result += '\n/* generated by ace-loader */\n'
|
||||
callback(null, result, map)
|
||||
}
|
||||
if (process.env.DEVICE_LEVEL === DEVICE_LEVEL.LITE) {
|
||||
callback(null, parsed, map)
|
||||
}
|
||||
}).catch(e => {
|
||||
logWarn(this, [{
|
||||
reason: 'ERROR: Failed to parse the JS file. ' + e
|
||||
}])
|
||||
callback('')
|
||||
})
|
||||
}
|
49
src/style.js
Normal file
49
src/style.js
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
logWarn
|
||||
} from './util'
|
||||
|
||||
import {
|
||||
parseStyle
|
||||
} from './parser'
|
||||
const compileStyle = require('./lite/lite-transform-style')
|
||||
const { DEVICE_LEVEL } = require('./lite/lite-enum')
|
||||
module.exports = function (source) {
|
||||
this.cacheable && this.cacheable()
|
||||
|
||||
const callback = this.async()
|
||||
|
||||
parseStyle(source, this.resourcePath)
|
||||
.then(({ parsed, log }) => {
|
||||
if (log && log.length) {
|
||||
logWarn(this, log)
|
||||
}
|
||||
if (process.env.DEVICE_LEVEL === DEVICE_LEVEL.LITE) {
|
||||
parsed = compileStyle.transformStyle(parsed)
|
||||
}
|
||||
callback(null, parsed)
|
||||
}).catch(e => {
|
||||
logWarn(this, [{
|
||||
reason: 'ERROR: Failed to parse the CSS file. ' + e
|
||||
}])
|
||||
callback('')
|
||||
})
|
||||
}
|
60
src/template.js
Normal file
60
src/template.js
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
logWarn
|
||||
} from './util'
|
||||
|
||||
import {
|
||||
parseTemplate
|
||||
} from './parser'
|
||||
const compiler = require('./lite/lite-transform-template')
|
||||
const { DEVICE_LEVEL } = require('./lite/lite-enum')
|
||||
module.exports = function (source) {
|
||||
if (process.env.DEVICE_LEVEL !== DEVICE_LEVEL.RICH && source.lastIndexOf('</element>') > 0) {
|
||||
const count = source.lastIndexOf('</element>')
|
||||
source = source.substr(count + 10, source.length)
|
||||
}
|
||||
this.cacheable && this.cacheable()
|
||||
|
||||
const callback = this.async()
|
||||
|
||||
let hasError = false
|
||||
parseTemplate(source, this.resourcePath)
|
||||
.then(({ parsed, log }) => {
|
||||
if (log && log.length) {
|
||||
hasError = logWarn(this, log)
|
||||
}
|
||||
// If there is an error during compilation, an empty object is returned
|
||||
if (process.env.DEVICE_LEVEL === DEVICE_LEVEL.LITE) {
|
||||
if (hasError) {
|
||||
parsed = `function () { return {} }`
|
||||
}
|
||||
else {
|
||||
parsed = compiler.transformTemplate(parsed)
|
||||
}
|
||||
}
|
||||
callback(null, parsed)
|
||||
}).catch(e => {
|
||||
logWarn(this, [{
|
||||
reason: 'ERROR: Failed to parse the HML file. ' + e
|
||||
}])
|
||||
callback('')
|
||||
})
|
||||
}
|
322
src/util.js
Normal file
322
src/util.js
Normal file
@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import path from 'path'
|
||||
import loaderUtils from 'loader-utils'
|
||||
import hash from 'hash-sum'
|
||||
import {
|
||||
SourceMapGenerator,
|
||||
SourceMapConsumer
|
||||
} from 'source-map'
|
||||
|
||||
const { DEVICE_LEVEL } = require('./lite/lite-enum')
|
||||
|
||||
export function getNameByPath (resourcePath) {
|
||||
return path.basename(resourcePath).replace(/\..*$/, '')
|
||||
}
|
||||
|
||||
export function getFileNameWithHash (resourcePath, content) {
|
||||
const filename = path.relative('.', resourcePath)
|
||||
const cacheKey = hash(filename + content)
|
||||
return `./${filename}?${cacheKey}`
|
||||
}
|
||||
|
||||
export function getFilenameByPath (filepath) {
|
||||
return path.relative('.', filepath)
|
||||
}
|
||||
|
||||
export const FUNC_START = '#####FUN_S#####'
|
||||
export const FUNC_START_REG = new RegExp('["\']' + FUNC_START, 'g')
|
||||
export const FUNC_END = '#####FUN_E#####'
|
||||
export const FUNC_END_REG = new RegExp(FUNC_END + '["\']', 'g')
|
||||
|
||||
export function stringifyFunction (key, value) {
|
||||
if (typeof value === 'function') {
|
||||
return FUNC_START + value.toString() + FUNC_END
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
export function logWarn (loader, logs) {
|
||||
// add flag to determine if there is an error log
|
||||
let flag = false
|
||||
if (process.env.logLevel > 0) {
|
||||
if (logs && logs.length) {
|
||||
logs.forEach(log => {
|
||||
if (log.reason.startsWith('NOTE') && parseInt(process.env.logLevel) <= 1) {
|
||||
if (log.line && log.column) {
|
||||
loader.emitWarning('noteStartNOTE File:' + loader.resourcePath + ':' +
|
||||
log.line + ':' + log.column + '\n ' + log.reason.replace('NOTE: ', '') + 'noteEnd')
|
||||
} else {
|
||||
loader.emitWarning('noteStartNOTE File:' + loader.resourcePath +
|
||||
'\n ' + log.reason.replace('NOTE: ', '') + 'noteEnd')
|
||||
}
|
||||
} else if (log.reason.startsWith('WARN') && parseInt(process.env.logLevel) <= 2) {
|
||||
if (log.line && log.column) {
|
||||
loader.emitWarning('warnStartWARNING File:' + loader.resourcePath + ':' +
|
||||
log.line + ':' + log.column + '\n ' + log.reason.replace('WARNING: ', '') + 'warnEnd')
|
||||
} else {
|
||||
loader.emitWarning('warnStartWARNING File:' + loader.resourcePath +
|
||||
'\n ' + log.reason.replace('WARNING: ', '') + 'warnEnd')
|
||||
}
|
||||
} else if (log.reason.startsWith('ERROR') && parseInt(process.env.logLevel) <= 3) {
|
||||
flag = true
|
||||
if (log.line && log.column) {
|
||||
loader.emitError('errorStartERROR File:' + loader.resourcePath + ':' +
|
||||
log.line + ':' + log.column + '\n ' + log.reason.replace('ERROR: ', '') + 'errorEnd')
|
||||
} else {
|
||||
loader.emitError('errorStartERROR File:' + loader.resourcePath +
|
||||
'\n ' + log.reason.replace('ERROR: ', '') + 'errorEnd')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
return flag
|
||||
}
|
||||
|
||||
export function getRequireString (loaderContext, loader, filepath) {
|
||||
return 'require(' +
|
||||
loaderUtils.stringifyRequest(
|
||||
loaderContext,
|
||||
loader ?
|
||||
`!!${loader}!${filepath}` :
|
||||
`${filepath}`
|
||||
) +
|
||||
')\n'
|
||||
}
|
||||
|
||||
export function stringifyLoaders (loaders) {
|
||||
return loaders.map(loader => {
|
||||
if (typeof loader === 'string') {
|
||||
return loader
|
||||
}
|
||||
else {
|
||||
const name = loader.name
|
||||
const query = []
|
||||
if (loader.query) {
|
||||
for (const k in loader.query) {
|
||||
const v = loader.query[k]
|
||||
if (v != null) {
|
||||
if (v === true) {
|
||||
query.push(k)
|
||||
}
|
||||
else if (v instanceof Array) {
|
||||
query.push(`${k}[]=${v.join(',')}`)
|
||||
}
|
||||
else {
|
||||
query.push(`${k}=${v}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return `${name}${query.length ? ('?' + query.join('&')) : ''}`
|
||||
}
|
||||
}).join('!')
|
||||
}
|
||||
|
||||
export function generateMap (loader, source, iterator) {
|
||||
const filePath = loader.resourcePath
|
||||
|
||||
const fileNameWithHash = getFileNameWithHash(filePath)
|
||||
const sourceRoot = path.resolve('.')
|
||||
|
||||
const map = new SourceMapGenerator({
|
||||
sourceRoot,
|
||||
skipValidation: true
|
||||
})
|
||||
map.setSourceContent(fileNameWithHash, source)
|
||||
|
||||
for (const { original, generated } of iterator) {
|
||||
map.addMapping({
|
||||
source: fileNameWithHash,
|
||||
original,
|
||||
generated
|
||||
})
|
||||
}
|
||||
|
||||
return map
|
||||
}
|
||||
|
||||
export function consumeMap (loader, target, map) {
|
||||
const smc = new SourceMapConsumer(map)
|
||||
let source
|
||||
const original = []
|
||||
const generated = []
|
||||
const mapping = {}
|
||||
|
||||
splitSourceLine(target)
|
||||
.forEach((input, line) => {
|
||||
const column = 0
|
||||
line = line + 1
|
||||
|
||||
const pos = smc.originalPositionFor({
|
||||
line,
|
||||
column
|
||||
})
|
||||
|
||||
if (pos.source) {
|
||||
source = pos.source
|
||||
original.push({
|
||||
line: pos.line,
|
||||
column: pos.column
|
||||
})
|
||||
generated.push({
|
||||
line,
|
||||
column
|
||||
})
|
||||
mapping[`line-${line}-column-${column}`] = {
|
||||
line: pos.line,
|
||||
column: pos.column
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
source,
|
||||
original,
|
||||
generated,
|
||||
mapping,
|
||||
sourcesContent: smc.sourcesContent
|
||||
}
|
||||
}
|
||||
|
||||
const LINE_REG = /\r?\n/g
|
||||
export function splitSourceLine (source) {
|
||||
return source.split(LINE_REG)
|
||||
}
|
||||
|
||||
export function printSourceWithLine (source) {
|
||||
console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
|
||||
source = splitSourceLine(source)
|
||||
.map((input, line) => {
|
||||
console.log(line + 1 + ':', input)
|
||||
})
|
||||
console.log('<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<')
|
||||
}
|
||||
|
||||
export function loadBabelModule (moduleName) {
|
||||
try {
|
||||
const filePath = require.resolve(moduleName)
|
||||
return filePath.slice(0, filePath.indexOf(moduleName.replace(/\//g, path.sep)) + moduleName.length)
|
||||
}
|
||||
catch (e) {
|
||||
return moduleName
|
||||
}
|
||||
}
|
||||
|
||||
export function parseRequireModule (source) {
|
||||
const requireMethod = process.env.DEVICE_LEVEL === DEVICE_LEVEL.LITE ?
|
||||
`
|
||||
function requireModule(moduleName) {
|
||||
return requireNative(moduleName.slice(1));
|
||||
}
|
||||
` :
|
||||
`
|
||||
function requireModule(moduleName) {
|
||||
const systemList = ['system.router', 'system.app', 'system.prompt', 'system.configuration',
|
||||
'system.image', 'system.device', 'system.mediaquery', 'ohos.animator', 'system.grid', 'system.resource']
|
||||
var target = ''
|
||||
if (systemList.includes(moduleName.replace('@', ''))) {
|
||||
target = $app_require$('@app-module/' + moduleName.substring(1));
|
||||
return target;
|
||||
}
|
||||
var shortName = moduleName.replace(/@[^.]+\.([^.]+)/, '$1');
|
||||
if (typeof ohosplugin !== 'undefined' && /@ohos/.test(moduleName)) {
|
||||
target = ohosplugin;
|
||||
for (let key of shortName.split('.')) {
|
||||
target = target[key];
|
||||
if(!target) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (typeof target !== 'undefined') {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
if (typeof systemplugin !== 'undefined') {
|
||||
target = systemplugin;
|
||||
for (let key of shortName.split('.')) {
|
||||
target = target[key];
|
||||
if(!target) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (typeof target !== 'undefined') {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
target = requireNapi(shortName);
|
||||
return target;
|
||||
}
|
||||
`
|
||||
|
||||
source = `${source}\n${requireMethod}`
|
||||
const requireReg = /require\(['"]([^()]+)['"]\)/g
|
||||
const libReg = /^lib(.+)\.so$/
|
||||
let requireStatements = source.match(requireReg)
|
||||
if (requireStatements && requireStatements.length) {
|
||||
for (let requireStatement of requireStatements) {
|
||||
if (requireStatement.indexOf('@system') > 0 || requireStatement.indexOf('@ohos') > 0) {
|
||||
source = source.replace(requireStatement, requireStatement.replace('require', 'requireModule'))
|
||||
}
|
||||
}
|
||||
}
|
||||
source = source.replace(requireReg, (item, item1) => {
|
||||
if (libReg.test(item1)) {
|
||||
item = `requireNapi("${item1.replace(libReg, '$1')}", true)`
|
||||
}
|
||||
return item
|
||||
})
|
||||
return source
|
||||
}
|
||||
|
||||
export function jsonLoaders (type, customLoader) {
|
||||
let loaders = []
|
||||
switch (type) {
|
||||
case "template":
|
||||
loaders = [{
|
||||
name: path.resolve(__dirname, 'json.js')
|
||||
}, {
|
||||
name: path.resolve(__dirname, 'template.js')
|
||||
}]
|
||||
break
|
||||
case "style":
|
||||
loaders = [{
|
||||
name: path.resolve(__dirname, 'json.js')
|
||||
}, {
|
||||
name: path.resolve(__dirname, 'style.js')
|
||||
}]
|
||||
break
|
||||
case "json":
|
||||
loaders = [{
|
||||
name: path.resolve(__dirname, 'json.js')
|
||||
}]
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if (customLoader) {
|
||||
loaders.push({
|
||||
name: path.resolve(__dirname, `../node_modules/${customLoader}`)
|
||||
})
|
||||
}
|
||||
return stringifyLoaders(loaders)
|
||||
}
|
0
test/actual/.gitkeeper
Normal file
0
test/actual/.gitkeeper
Normal file
15
test/expect/a.js
Normal file
15
test/expect/a.js
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"@weex-component/f7f03a1f8fba3f0ef22eb87969da4ac2": {
|
||||
"template": {
|
||||
"type": "div",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"attr": {
|
||||
"value": "Hello Weex"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
24
test/expect/b.js
Normal file
24
test/expect/b.js
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"@weex-component/efeeed2d981d974f413e0eb80df99deb": {
|
||||
"template": {
|
||||
"type": "div",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"hi"
|
||||
],
|
||||
"attr": {
|
||||
"value": "Hello Weex"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"hi": {
|
||||
"fontSize": 26,
|
||||
"color": "#FF0000"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
25
test/expect/c.js
Normal file
25
test/expect/c.js
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"@weex-component/192c464938a57dbd89308b3f2aaa0b18": {
|
||||
"data": "function data() {\n\t return {\n\t name: 'Weex'\n\t };\n\t}",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"hello"
|
||||
],
|
||||
"attr": {
|
||||
"value": "function () {return 'Hello ' + (this.name)}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"hello": {
|
||||
"fontSize": 26,
|
||||
"color": "#FF0000"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
57
test/expect/d.js
Normal file
57
test/expect/d.js
Normal file
@ -0,0 +1,57 @@
|
||||
{
|
||||
"@weex-component/name": {
|
||||
"data": "function data() {\n\t return {\n\t name: ''\n\t };\n\t }",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"name"
|
||||
],
|
||||
"attr": {
|
||||
"value": "function () {return this.name}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"name": {
|
||||
"fontSize": 26,
|
||||
"color": "#FF0000"
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/efd01076a5d363118b9fa68bbab98216": {
|
||||
"data": "function data() {\n\t return {\n\t name: 'Weex'\n\t };\n\t}",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"style": {
|
||||
"flexDirection": "row"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"hello"
|
||||
],
|
||||
"attr": {
|
||||
"value": "Hello"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "name",
|
||||
"attr": {
|
||||
"name": "function () {return this.name}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"hello": {
|
||||
"fontSize": 26,
|
||||
"color": "#008000"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
71
test/expect/e.js
Normal file
71
test/expect/e.js
Normal file
@ -0,0 +1,71 @@
|
||||
{
|
||||
"@weex-component/hi": {
|
||||
"data": "function data() {\n\t return {\n\t hi: ''\n\t };\n\t }",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"hi"
|
||||
],
|
||||
"attr": {
|
||||
"value": "function () {return this.hi}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"hi": {
|
||||
"fontSize": 26,
|
||||
"color": "#008000"
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/name": {
|
||||
"data": "function data() {\n\t return {\n\t name: ''\n\t };\n\t }",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"name"
|
||||
],
|
||||
"attr": {
|
||||
"value": "function () {return this.name}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"name": {
|
||||
"fontSize": 26,
|
||||
"color": "#FF0000"
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/3f7bb5c2b95329dedd5cb4556f4df361": {
|
||||
"data": "function data() {\n\t return {\n\t hi: 'Hello',\n\t name: 'Weex'\n\t };\n\t}",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"style": {
|
||||
"flexDirection": "row"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "hi",
|
||||
"attr": {
|
||||
"hi": "function () {return this.hi}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "name",
|
||||
"attr": {
|
||||
"name": "function () {return this.name}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
76
test/expect/f.js
Normal file
76
test/expect/f.js
Normal file
@ -0,0 +1,76 @@
|
||||
{
|
||||
"@weex-component/hi": {
|
||||
"data": "function data() {\n\t return {\n\t hi: ''\n\t };\n\t }",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"hi"
|
||||
],
|
||||
"attr": {
|
||||
"value": "function () {return this.hi}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"hi": {
|
||||
"fontSize": 26,
|
||||
"color": "#008000"
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/name": {
|
||||
"data": "function data() {\n\t console.log('Name Component Comment');\n\t return {\n\t name: ''\n\t };\n\t }",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"name"
|
||||
],
|
||||
"attr": {
|
||||
"value": "function () {return this.name}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"name": {
|
||||
"fontSize": 26,
|
||||
"color": "#FF0000"
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/ce75098d1d76e52a00b0d2b2613d990c": {
|
||||
"data": "function data() {\n\t return {\n\t hi: 'Hello',\n\t name: 'Weex'\n\t };\n\t}",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"classList": [
|
||||
"wrap"
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "hi",
|
||||
"attr": {
|
||||
"hi": "function () {return this.hi}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "name",
|
||||
"attr": {
|
||||
"name": "function () {return this.name}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"wrap": {
|
||||
"flexDirection": "row"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
76
test/expect/g.js
Normal file
76
test/expect/g.js
Normal file
@ -0,0 +1,76 @@
|
||||
{
|
||||
"@weex-component/name1": {
|
||||
"data": "function data() {\n\t console.log('Name Component Comment');\n\t return {\n\t name: ''\n\t };\n\t }",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"name"
|
||||
],
|
||||
"attr": {
|
||||
"value": "function () {return this.name}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"name": {
|
||||
"fontSize": 26,
|
||||
"color": "#FF0000"
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/hi1": {
|
||||
"data": "function data() {\n\t return {\n\t hi: ''\n\t };\n\t }",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"hi"
|
||||
],
|
||||
"attr": {
|
||||
"value": "function () {return this.hi}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"hi": {
|
||||
"fontSize": 26,
|
||||
"color": "#008000"
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/ce13b953688b3be076ebafcfb5807052": {
|
||||
"data": "function data() {\n\t return {\n\t hi: 'Hello',\n\t name: 'Weex'\n\t };\n\t }",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"classList": [
|
||||
"wrap"
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "hi1",
|
||||
"attr": {
|
||||
"hi": "function () {return this.hi}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "name1",
|
||||
"attr": {
|
||||
"name": "function () {return this.name}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"wrap": {
|
||||
"flexDirection": "row"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
76
test/expect/h.js
Normal file
76
test/expect/h.js
Normal file
@ -0,0 +1,76 @@
|
||||
{
|
||||
"@weex-component/hi": {
|
||||
"data": "function data() {\n\t return {\n\t hi: ''\n\t };\n\t }",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"hi"
|
||||
],
|
||||
"attr": {
|
||||
"value": "function () {return this.hi}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"hi": {
|
||||
"fontSize": 26,
|
||||
"color": "#008000"
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/name": {
|
||||
"data": "function data() {\n\t console.log('Name Component Comment');\n\t return {\n\t name: ''\n\t };\n\t }",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"name"
|
||||
],
|
||||
"attr": {
|
||||
"value": "function () {return this.name}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"name": {
|
||||
"fontSize": 26,
|
||||
"color": "#FF0000"
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/a3294f0702f2a9d0b48c66c00c4429af": {
|
||||
"data": "function data() {\n\t return {\n\t hi: 'Hello',\n\t name: 'Weex'\n\t };\n\t }",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"classList": [
|
||||
"wrap"
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "hi",
|
||||
"attr": {
|
||||
"hi": "function () {return this.hi}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "name",
|
||||
"attr": {
|
||||
"name": "function () {return this.name}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"wrap": {
|
||||
"flexDirection": "row"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
24
test/expect/i.js
Normal file
24
test/expect/i.js
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"@weex-component/a0ca0f35aa865d928da5cb31115674de": {
|
||||
"template": {
|
||||
"type": "div",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"hello"
|
||||
],
|
||||
"attr": {
|
||||
"value": "function () {return 'Hello ' + (this.name)}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"hello": {
|
||||
"fontSize": 26,
|
||||
"color": "#FF0000"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
31
test/expect/j.js
Normal file
31
test/expect/j.js
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"@weex-component/75ade3685ace094b4dd3622093f2ac3e": {
|
||||
"ready": "function ready() {\n\t _modal2.default.toast({ 'message': 'ready' });\n\t }",
|
||||
"data": "function data() {\n\t return {\n\t hi: 'Hello',\n\t name: 'Weex'\n\t };\n\t }",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"classList": [
|
||||
"wrap"
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"attr": {
|
||||
"value": "function () {return this.hi}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"attr": {
|
||||
"value": "function () {return this.name}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"wrap": {
|
||||
"flexDirection": "row"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
45
test/expect/k.js
Normal file
45
test/expect/k.js
Normal file
@ -0,0 +1,45 @@
|
||||
{
|
||||
"@weex-component/6461408a6e72015716c3e75aedb3f4f8": {
|
||||
"ready": "function () {\n\t return modal.toast({\n\t 'message': 'ready'\n\t });\n\t }",
|
||||
"data": "function () {\n\t return {\n\t hi: 'Hello',\n\t name: 'Weex'\n\t };\n\t }",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"classList": [
|
||||
"wrap"
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"text-hi"
|
||||
],
|
||||
"attr": {
|
||||
"value": "function () {return this.hi}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"text-name"
|
||||
],
|
||||
"attr": {
|
||||
"value": "function () {return this.name}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"wrap": {
|
||||
"flexDirection": "row"
|
||||
},
|
||||
"text-hi": {
|
||||
"color": "#FF0000",
|
||||
"fontSize": 26
|
||||
},
|
||||
"text-name": {
|
||||
"color": "#008000",
|
||||
"fontSize": 26
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
26
test/expect/l.js
Normal file
26
test/expect/l.js
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"@weex-component/b88790ebbe39cc44c23e81e6ef2a07e2": {
|
||||
"ready": "function ready() {\n\t _modal2.default.toast({ message: this.name });\n\t}",
|
||||
"data": "function data() {\n\t return {\n\t name: (0, _getName2.default)()\n\t };\n\t}",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"hello"
|
||||
],
|
||||
"attr": {
|
||||
"value": "function () {return 'Hello ' + (this.name)}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"hello": {
|
||||
"fontSize": 26,
|
||||
"color": "#FF0000"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
27
test/expect/m.js
Normal file
27
test/expect/m.js
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"@weex-component/toast": {},
|
||||
"@weex-component/27bd9f030aa3c2c01f3168b3f623e61e": {
|
||||
"ready": "function ready() {\n\t (0, _toast2.default)(this.name);\n\t }",
|
||||
"data": "function data() {\n\t return {\n\t name: 'Weex'\n\t };\n\t }",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"hello"
|
||||
],
|
||||
"attr": {
|
||||
"value": "function () {return 'Hello ' + (this.name)}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"hello": {
|
||||
"fontSize": 26,
|
||||
"color": "#FF0000"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
76
test/expect/n.js
Normal file
76
test/expect/n.js
Normal file
@ -0,0 +1,76 @@
|
||||
{
|
||||
"@weex-component/hi": {
|
||||
"data": "function data() {\n\t console.log('Hi Component Comment');\n\t return {\n\t hi: ''\n\t };\n\t }",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"hi"
|
||||
],
|
||||
"attr": {
|
||||
"value": "function () {return this.hi}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"hi": {
|
||||
"fontSize": 26,
|
||||
"color": "#008000"
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/name": {
|
||||
"data": "function data() {\n\t console.log('Name Component Comment');\n\t return {\n\t name: ''\n\t };\n\t }",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"name"
|
||||
],
|
||||
"attr": {
|
||||
"value": "function () {return this.name}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"name": {
|
||||
"fontSize": 26,
|
||||
"color": "#FF0000"
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/57a447a57bba51ef8a7697040ca71e75": {
|
||||
"data": "function data() {\n\t console.log('N comment');\n\t return {\n\t hi: 'Hello',\n\t name: 'Weex'\n\t };\n\t}",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"classList": [
|
||||
"wrap"
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "hi",
|
||||
"attr": {
|
||||
"hi": "function () {return this.hi}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "name",
|
||||
"attr": {
|
||||
"name": "function () {return this.name}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"wrap": {
|
||||
"flexDirection": "row"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
830
test/expect/o.js
Normal file
830
test/expect/o.js
Normal file
@ -0,0 +1,830 @@
|
||||
{
|
||||
"@weex-component/wxc-button": {
|
||||
"data": "function () {return {\n\t type: 'default',\n\t size: 'large',\n\t value: ''\n\t }}",
|
||||
"methods": {},
|
||||
"template": {
|
||||
"type": "div",
|
||||
"classList": "function () {return ['btn', 'btn-' + (this.type), 'btn-sz-' + (this.size)]}",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": "function () {return ['btn-txt', 'btn-txt-' + (this.type), 'btn-txt-sz-' + (this.size)]}",
|
||||
"attr": {
|
||||
"value": "function () {return this.value}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"btn": {
|
||||
"marginBottom": 0,
|
||||
"alignItems": "center",
|
||||
"justifyContent": "center",
|
||||
"borderWidth": 1,
|
||||
"borderStyle": "solid",
|
||||
"borderColor": "#333333"
|
||||
},
|
||||
"btn-default": {
|
||||
"color": "rgb(51,51,51)"
|
||||
},
|
||||
"btn-primary": {
|
||||
"backgroundColor": "rgb(40,96,144)",
|
||||
"borderColor": "rgb(40,96,144)"
|
||||
},
|
||||
"btn-success": {
|
||||
"backgroundColor": "rgb(92,184,92)",
|
||||
"borderColor": "rgb(76,174,76)"
|
||||
},
|
||||
"btn-info": {
|
||||
"backgroundColor": "rgb(91,192,222)",
|
||||
"borderColor": "rgb(70,184,218)"
|
||||
},
|
||||
"btn-warning": {
|
||||
"backgroundColor": "rgb(240,173,78)",
|
||||
"borderColor": "rgb(238,162,54)"
|
||||
},
|
||||
"btn-danger": {
|
||||
"backgroundColor": "rgb(217,83,79)",
|
||||
"borderColor": "rgb(212,63,58)"
|
||||
},
|
||||
"btn-link": {
|
||||
"borderColor": "rgba(0,0,0,0)",
|
||||
"borderRadius": 0
|
||||
},
|
||||
"btn-txt-default": {
|
||||
"color": "rgb(51,51,51)"
|
||||
},
|
||||
"btn-txt-primary": {
|
||||
"color": "rgb(255,255,255)"
|
||||
},
|
||||
"btn-txt-success": {
|
||||
"color": "rgb(255,255,255)"
|
||||
},
|
||||
"btn-txt-info": {
|
||||
"color": "rgb(255,255,255)"
|
||||
},
|
||||
"btn-txt-warning": {
|
||||
"color": "rgb(255,255,255)"
|
||||
},
|
||||
"btn-txt-danger": {
|
||||
"color": "rgb(255,255,255)"
|
||||
},
|
||||
"btn-txt-link": {
|
||||
"color": "rgb(51,122,183)"
|
||||
},
|
||||
"btn-sz-large": {
|
||||
"width": 300,
|
||||
"height": 100,
|
||||
"paddingTop": 25,
|
||||
"paddingBottom": 25,
|
||||
"paddingLeft": 40,
|
||||
"paddingRight": 40,
|
||||
"borderRadius": 15
|
||||
},
|
||||
"btn-sz-middle": {
|
||||
"width": 240,
|
||||
"height": 80,
|
||||
"paddingTop": 15,
|
||||
"paddingBottom": 15,
|
||||
"paddingLeft": 30,
|
||||
"paddingRight": 30,
|
||||
"borderRadius": 10
|
||||
},
|
||||
"btn-sz-small": {
|
||||
"width": 170,
|
||||
"height": 60,
|
||||
"paddingTop": 12,
|
||||
"paddingBottom": 12,
|
||||
"paddingLeft": 25,
|
||||
"paddingRight": 25,
|
||||
"borderRadius": 7
|
||||
},
|
||||
"btn-txt-sz-large": {
|
||||
"fontSize": 45
|
||||
},
|
||||
"btn-txt-sz-middle": {
|
||||
"fontSize": 35
|
||||
},
|
||||
"btn-txt-sz-small": {
|
||||
"fontSize": 30
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/wxc-hn": {
|
||||
"data": "function () {return {\n\t level: 1,\n\t value: ''\n\t }}",
|
||||
"methods": {},
|
||||
"template": {
|
||||
"type": "div",
|
||||
"classList": "function () {return ['h' + (this.level)]}",
|
||||
"style": {
|
||||
"justifyContent": "center"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": "function () {return ['txt-h' + (this.level)]}",
|
||||
"attr": {
|
||||
"value": "function () {return this.value}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"h1": {
|
||||
"height": 110,
|
||||
"paddingTop": 20,
|
||||
"paddingBottom": 20
|
||||
},
|
||||
"h2": {
|
||||
"height": 110,
|
||||
"paddingTop": 20,
|
||||
"paddingBottom": 20
|
||||
},
|
||||
"h3": {
|
||||
"height": 110,
|
||||
"paddingTop": 20,
|
||||
"paddingBottom": 20
|
||||
},
|
||||
"txt-h1": {
|
||||
"fontSize": 70
|
||||
},
|
||||
"txt-h2": {
|
||||
"fontSize": 52
|
||||
},
|
||||
"txt-h3": {
|
||||
"fontSize": 42
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/wxc-list-item": {
|
||||
"data": "function () {return {\n\t bgColor: '#ffffff'\n\t }}",
|
||||
"methods": {
|
||||
"touchstart": "function touchstart() {}",
|
||||
"touchend": "function touchend() {}"
|
||||
},
|
||||
"template": {
|
||||
"type": "div",
|
||||
"classList": [
|
||||
"item"
|
||||
],
|
||||
"events": {
|
||||
"touchstart": "touchstart",
|
||||
"touchend": "touchend"
|
||||
},
|
||||
"style": {
|
||||
"backgroundColor": "function () {return this.bgColor}"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "content"
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"item": {
|
||||
"paddingTop": 25,
|
||||
"paddingBottom": 25,
|
||||
"paddingLeft": 35,
|
||||
"paddingRight": 35,
|
||||
"height": 160,
|
||||
"justifyContent": "center",
|
||||
"borderBottomWidth": 1,
|
||||
"borderColor": "#dddddd"
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/wxc-panel": {
|
||||
"data": "function () {return {\n\t type: 'default',\n\t title: '',\n\t paddingBody: 20,\n\t paddingHead: 20,\n\t dataClass: '',\n\t border: 0\n\t }}",
|
||||
"ready": "function ready() {}",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"classList": "function () {return ['panel', 'panel-' + (this.type)]}",
|
||||
"style": {
|
||||
"borderWidth": "function () {return this.border}"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": "function () {return ['panel-header', 'panel-header-' + (this.type)]}",
|
||||
"style": {
|
||||
"paddingTop": "function () {return this.paddingHead}",
|
||||
"paddingBottom": "function () {return this.paddingHead}",
|
||||
"paddingLeft": "function () {return this.paddingHead*1.5}",
|
||||
"paddingRight": "function () {return this.paddingHead*1.5}"
|
||||
},
|
||||
"attr": {
|
||||
"value": "function () {return this.title}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "div",
|
||||
"classList": "function () {return ['panel-body', 'panel-body-' + (this.type)]}",
|
||||
"style": {
|
||||
"paddingTop": "function () {return this.paddingBody}",
|
||||
"paddingBottom": "function () {return this.paddingBody}",
|
||||
"paddingLeft": "function () {return this.paddingBody*1.5}",
|
||||
"paddingRight": "function () {return this.paddingBody*1.5}"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "content"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"panel": {
|
||||
"marginBottom": 20,
|
||||
"backgroundColor": "#ffffff",
|
||||
"borderColor": "#dddddd",
|
||||
"borderWidth": 1
|
||||
},
|
||||
"panel-primary": {
|
||||
"borderColor": "rgb(40,96,144)"
|
||||
},
|
||||
"panel-success": {
|
||||
"borderColor": "rgb(76,174,76)"
|
||||
},
|
||||
"panel-info": {
|
||||
"borderColor": "rgb(70,184,218)"
|
||||
},
|
||||
"panel-warning": {
|
||||
"borderColor": "rgb(238,162,54)"
|
||||
},
|
||||
"panel-danger": {
|
||||
"borderColor": "rgb(212,63,58)"
|
||||
},
|
||||
"panel-header": {
|
||||
"backgroundColor": "#f5f5f5",
|
||||
"fontSize": 40,
|
||||
"color": "#333333"
|
||||
},
|
||||
"panel-header-primary": {
|
||||
"backgroundColor": "rgb(40,96,144)",
|
||||
"color": "#ffffff"
|
||||
},
|
||||
"panel-header-success": {
|
||||
"backgroundColor": "rgb(92,184,92)",
|
||||
"color": "#ffffff"
|
||||
},
|
||||
"panel-header-info": {
|
||||
"backgroundColor": "rgb(91,192,222)",
|
||||
"color": "#ffffff"
|
||||
},
|
||||
"panel-header-warning": {
|
||||
"backgroundColor": "rgb(240,173,78)",
|
||||
"color": "#ffffff"
|
||||
},
|
||||
"panel-header-danger": {
|
||||
"backgroundColor": "rgb(217,83,79)",
|
||||
"color": "#ffffff"
|
||||
},
|
||||
"panel-body": {}
|
||||
}
|
||||
},
|
||||
"@weex-component/wxc-tip": {
|
||||
"data": "function () {return {\n\t type: 'success',\n\t value: ''\n\t }}",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"classList": "function () {return ['tip', 'tip-' + (this.type)]}",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": "function () {return ['tip-txt', 'tip-txt-' + (this.type)]}",
|
||||
"attr": {
|
||||
"value": "function () {return this.value}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"tip": {
|
||||
"paddingLeft": 36,
|
||||
"paddingRight": 36,
|
||||
"paddingTop": 36,
|
||||
"paddingBottom": 36,
|
||||
"borderRadius": 10
|
||||
},
|
||||
"tip-txt": {
|
||||
"fontSize": 28
|
||||
},
|
||||
"tip-success": {
|
||||
"backgroundColor": "#dff0d8",
|
||||
"borderColor": "#d6e9c6"
|
||||
},
|
||||
"tip-txt-success": {
|
||||
"color": "#3c763d"
|
||||
},
|
||||
"tip-info": {
|
||||
"backgroundColor": "#d9edf7",
|
||||
"borderColor": "#bce8f1"
|
||||
},
|
||||
"tip-txt-info": {
|
||||
"color": "#31708f"
|
||||
},
|
||||
"tip-warning": {
|
||||
"backgroundColor": "#fcf8e3",
|
||||
"borderColor": "#faebcc"
|
||||
},
|
||||
"tip-txt-warning": {
|
||||
"color": "#8a6d3b"
|
||||
},
|
||||
"tip-danger": {
|
||||
"backgroundColor": "#f2dede",
|
||||
"borderColor": "#ebccd1"
|
||||
},
|
||||
"tip-txt-danger": {
|
||||
"color": "#a94442"
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/wxc-countdown": {
|
||||
"data": "function () {return {\n\t now: 0,\n\t remain: 0,\n\t time: {\n\t elapse: 0,\n\t D: '0',\n\t DD: '0',\n\t h: '0',\n\t hh: '00',\n\t H: '0',\n\t HH: '0',\n\t m: '0',\n\t mm: '00',\n\t M: '0',\n\t MM: '0',\n\t s: '0',\n\t ss: '00',\n\t S: '0',\n\t SS: '0'\n\t },\n\t outofview: false\n\t }}",
|
||||
"ready": "function ready() {\n\t if (this.remain <= 0) {\n\t return;\n\t }\n\t\n\t this.now = Date.now();\n\t this.nextTick();\n\t }",
|
||||
"methods": {
|
||||
"nextTick": "function nextTick() {\n\t if (this.outofview) {\n\t setTimeout(this.nextTick.bind(this), 1000);\n\t } else {\n\t this.time.elapse = parseInt((Date.now() - this.now) / 1000);\n\t\n\t if (this.calc()) {\n\t this.$emit('tick', (0, _assign2.default)({}, this.time));\n\t setTimeout(this.nextTick.bind(this), 1000);\n\t } else {\n\t this.$emit('alarm', (0, _assign2.default)({}, this.time));\n\t }\n\t this._app.updateActions();\n\t }\n\t }",
|
||||
"format": "function format(str) {\n\t if (str.length >= 2) {\n\t return str;\n\t } else {\n\t return '0' + str;\n\t }\n\t }",
|
||||
"calc": "function calc() {\n\t var remain = this.remain - this.time.elapse;\n\t if (remain < 0) {\n\t remain = 0;\n\t }\n\t this.time.D = String(parseInt(remain / 86400));\n\t this.time.DD = this.format(this.time.D);\n\t this.time.h = String(parseInt((remain - parseInt(this.time.D) * 86400) / 3600));\n\t this.time.hh = this.format(this.time.h);\n\t this.time.H = String(parseInt(remain / 3600));\n\t this.time.HH = this.format(this.time.H);\n\t this.time.m = String(parseInt((remain - parseInt(this.time.H) * 3600) / 60));\n\t this.time.mm = this.format(this.time.m);\n\t this.time.M = String(parseInt(remain / 60));\n\t this.time.MM = this.format(this.time.M);\n\t this.time.s = String(remain - parseInt(this.time.M) * 60);\n\t this.time.ss = this.format(this.time.s);\n\t this.time.S = String(remain);\n\t this.time.SS = this.format(this.time.S);\n\t\n\t return remain > 0;\n\t }",
|
||||
"appeared": "function appeared() {\n\t this.outofview = false;\n\t }",
|
||||
"disappeared": "function disappeared() {\n\t this.outofview = true;\n\t }"
|
||||
},
|
||||
"template": {
|
||||
"type": "div",
|
||||
"style": {
|
||||
"overflow": "hidden",
|
||||
"flexDirection": "row"
|
||||
},
|
||||
"events": {
|
||||
"appear": "appeared",
|
||||
"disappear": "disappeared"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "content"
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"wrap": {
|
||||
"overflow": "hidden"
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/wxc-marquee": {
|
||||
"data": "function () {return {\n\t step: 0,\n\t count: 0,\n\t index: 1,\n\t duration: 0,\n\t interval: 0,\n\t outofview: false\n\t }}",
|
||||
"ready": "function ready() {\n\t if (this.interval > 0 && this.step > 0 && this.duration > 0) {\n\t this.nextTick();\n\t }\n\t }",
|
||||
"methods": {
|
||||
"nextTick": "function nextTick() {\n\t var self = this;\n\t if (this.outofview) {\n\t setTimeout(self.nextTick.bind(self), self.interval);\n\t } else {\n\t setTimeout(function () {\n\t self.animation(self.nextTick.bind(self));\n\t }, self.interval);\n\t }\n\t }",
|
||||
"animation": "function animation(cb) {\n\t var self = this;\n\t var offset = -self.step * self.index;\n\t var $animation = __weex_require__('@weex-module/animation');\n\t $animation.transition(this.$el('anim'), {\n\t styles: {\n\t transform: 'translateY(' + String(offset) + 'px) translateZ(0)'\n\t },\n\t timingFunction: 'ease',\n\t duration: self.duration\n\t }, function () {\n\t self.index = (self.index + 1) % self.count;\n\t self.$emit('change', {\n\t index: self.index,\n\t count: self.count\n\t });\n\t cb && cb();\n\t });\n\t }",
|
||||
"appeared": "function appeared() {\n\t this.outofview = false;\n\t }",
|
||||
"disappeared": "function disappeared() {\n\t this.outofview = true;\n\t }"
|
||||
},
|
||||
"template": {
|
||||
"type": "div",
|
||||
"classList": [
|
||||
"wrap"
|
||||
],
|
||||
"events": {
|
||||
"appear": "appeared",
|
||||
"disappear": "disappeared"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "div",
|
||||
"id": "anim",
|
||||
"classList": [
|
||||
"anim"
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "content"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"wrap": {
|
||||
"overflow": "hidden",
|
||||
"position": "relative"
|
||||
},
|
||||
"anim": {
|
||||
"flexDirection": "column",
|
||||
"position": "absolute",
|
||||
"transform": "translateY(0) translateZ(0)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/wxc-navbar": {
|
||||
"data": "function () {return {\n\t dataRole: 'navbar',\n\t\n\t backgroundColor: 'black',\n\t\n\t height: 88,\n\t\n\t title: \"\",\n\t\n\t titleColor: 'black',\n\t\n\t rightItemSrc: '',\n\t\n\t rightItemTitle: '',\n\t\n\t rightItemColor: 'black',\n\t\n\t leftItemSrc: '',\n\t\n\t leftItemTitle: '',\n\t\n\t leftItemColor: 'black'\n\t }}",
|
||||
"methods": {
|
||||
"onclickrightitem": "function onclickrightitem(e) {\n\t this.$dispatch('naviBar.rightItem.click', {});\n\t }",
|
||||
"onclickleftitem": "function onclickleftitem(e) {\n\t this.$dispatch('naviBar.leftItem.click', {});\n\t }"
|
||||
},
|
||||
"template": {
|
||||
"type": "div",
|
||||
"classList": [
|
||||
"container"
|
||||
],
|
||||
"style": {
|
||||
"height": "function () {return this.height}",
|
||||
"backgroundColor": "function () {return this.backgroundColor}"
|
||||
},
|
||||
"attr": {
|
||||
"dataRole": "function () {return this.dataRole}"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"right-text"
|
||||
],
|
||||
"style": {
|
||||
"color": "function () {return this.rightItemColor}"
|
||||
},
|
||||
"attr": {
|
||||
"naviItemPosition": "right",
|
||||
"value": "function () {return this.rightItemTitle}"
|
||||
},
|
||||
"shown": "function () {return !this.rightItemSrc}",
|
||||
"events": {
|
||||
"click": "onclickrightitem"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"classList": [
|
||||
"right-image"
|
||||
],
|
||||
"attr": {
|
||||
"naviItemPosition": "right",
|
||||
"src": "function () {return this.rightItemSrc}"
|
||||
},
|
||||
"shown": "function () {return this.rightItemSrc}",
|
||||
"events": {
|
||||
"click": "onclickrightitem"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"left-text"
|
||||
],
|
||||
"style": {
|
||||
"color": "function () {return this.leftItemColor}"
|
||||
},
|
||||
"attr": {
|
||||
"naviItemPosition": "left",
|
||||
"value": "function () {return this.leftItemTitle}"
|
||||
},
|
||||
"shown": "function () {return !this.leftItemSrc}",
|
||||
"events": {
|
||||
"click": "onclickleftitem"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"classList": [
|
||||
"left-image"
|
||||
],
|
||||
"attr": {
|
||||
"naviItemPosition": "left",
|
||||
"src": "function () {return this.leftItemSrc}"
|
||||
},
|
||||
"shown": "function () {return this.leftItemSrc}",
|
||||
"events": {
|
||||
"click": "onclickleftitem"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"center-text"
|
||||
],
|
||||
"style": {
|
||||
"color": "function () {return this.titleColor}"
|
||||
},
|
||||
"attr": {
|
||||
"naviItemPosition": "center",
|
||||
"value": "function () {return this.title}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"container": {
|
||||
"flexDirection": "row",
|
||||
"position": "fixed",
|
||||
"top": 0,
|
||||
"left": 0,
|
||||
"right": 0,
|
||||
"width": 750
|
||||
},
|
||||
"right-text": {
|
||||
"position": "absolute",
|
||||
"bottom": 28,
|
||||
"right": 32,
|
||||
"textAlign": "right",
|
||||
"fontSize": 32,
|
||||
"fontFamily": "'Open Sans', sans-serif"
|
||||
},
|
||||
"left-text": {
|
||||
"position": "absolute",
|
||||
"bottom": 28,
|
||||
"left": 32,
|
||||
"textAlign": "left",
|
||||
"fontSize": 32,
|
||||
"fontFamily": "'Open Sans', sans-serif"
|
||||
},
|
||||
"center-text": {
|
||||
"position": "absolute",
|
||||
"bottom": 25,
|
||||
"left": 172,
|
||||
"right": 172,
|
||||
"textAlign": "center",
|
||||
"fontSize": 36,
|
||||
"fontWeight": "bold"
|
||||
},
|
||||
"left-image": {
|
||||
"position": "absolute",
|
||||
"bottom": 20,
|
||||
"left": 28,
|
||||
"width": 50,
|
||||
"height": 50
|
||||
},
|
||||
"right-image": {
|
||||
"position": "absolute",
|
||||
"bottom": 20,
|
||||
"right": 28,
|
||||
"width": 50,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/wxc-navpage": {
|
||||
"data": "function () {return {\n\t dataRole: 'navbar',\n\t backgroundColor: 'black',\n\t height: 88,\n\t title: \"\",\n\t titleColor: 'black',\n\t rightItemSrc: '',\n\t rightItemTitle: '',\n\t rightItemColor: 'black',\n\t leftItemSrc: '',\n\t leftItemTitle: '',\n\t leftItemColor: 'black'\n\t }}",
|
||||
"template": {
|
||||
"type": "div",
|
||||
"classList": [
|
||||
"wrapper"
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "wxc-navbar",
|
||||
"attr": {
|
||||
"dataRole": "function () {return this.dataRole}",
|
||||
"height": "function () {return this.height}",
|
||||
"backgroundColor": "function () {return this.backgroundColor}",
|
||||
"title": "function () {return this.title}",
|
||||
"titleColor": "function () {return this.titleColor}",
|
||||
"leftItemSrc": "function () {return this.leftItemSrc}",
|
||||
"leftItemTitle": "function () {return this.leftItemTitle}",
|
||||
"leftItemColor": "function () {return this.leftItemColor}",
|
||||
"rightItemSrc": "function () {return this.rightItemSrc}",
|
||||
"rightItemTitle": "function () {return this.rightItemTitle}",
|
||||
"rightItemColor": "function () {return this.rightItemColor}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "div",
|
||||
"classList": [
|
||||
"wrapper"
|
||||
],
|
||||
"style": {
|
||||
"marginTop": "function () {return this.height}"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "content"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"wrapper": {
|
||||
"position": "absolute",
|
||||
"top": 0,
|
||||
"left": 0,
|
||||
"right": 0,
|
||||
"bottom": 0,
|
||||
"width": 750
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/wxc-tabitem": {
|
||||
"data": "function () {return {\n\t index: 0,\n\t title: '',\n\t titleColor: '#000000',\n\t icon: '',\n\t backgroundColor: '#ffffff'\n\t }}",
|
||||
"methods": {
|
||||
"onclickitem": "function onclickitem(e) {\n\t var vm = this;\n\t var params = {\n\t index: vm.index\n\t };\n\t vm.$dispatch('tabItem.onClick', params);\n\t }"
|
||||
},
|
||||
"template": {
|
||||
"type": "div",
|
||||
"classList": [
|
||||
"container"
|
||||
],
|
||||
"style": {
|
||||
"backgroundColor": "function () {return this.backgroundColor}"
|
||||
},
|
||||
"events": {
|
||||
"click": "onclickitem"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "image",
|
||||
"classList": [
|
||||
"top-line"
|
||||
],
|
||||
"attr": {
|
||||
"src": "http://gtms03.alicdn.com/tps/i3/TB1mdsiMpXXXXXpXXXXNw4JIXXX-640-4.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"classList": [
|
||||
"tab-icon"
|
||||
],
|
||||
"attr": {
|
||||
"src": "function () {return this.icon}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"tab-text"
|
||||
],
|
||||
"style": {
|
||||
"color": "function () {return this.titleColor}"
|
||||
},
|
||||
"attr": {
|
||||
"value": "function () {return this.title}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"container": {
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
"alignItems": "center",
|
||||
"justifyContent": "center",
|
||||
"height": 88
|
||||
},
|
||||
"top-line": {
|
||||
"position": "absolute",
|
||||
"top": 0,
|
||||
"left": 0,
|
||||
"right": 0,
|
||||
"height": 2
|
||||
},
|
||||
"tab-icon": {
|
||||
"marginTop": 5,
|
||||
"width": 40,
|
||||
"height": 40
|
||||
},
|
||||
"tab-text": {
|
||||
"marginTop": 5,
|
||||
"textAlign": "center",
|
||||
"fontSize": 20
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/wxc-tabbar": {
|
||||
"data": "function () {return {\n\t tabItems: [],\n\t selectedIndex: 0,\n\t selectedColor: '#ff0000',\n\t unselectedColor: '#000000'\n\t }}",
|
||||
"created": "function created() {\n\t this.selected(this.selectedIndex);\n\t\n\t this.$on('tabItem.onClick', function (e) {\n\t var detail = e.detail;\n\t this.selectedIndex = detail.index;\n\t this.selected(detail.index);\n\t\n\t var params = {\n\t index: detail.index\n\t };\n\t this.$dispatch('tabBar.onClick', params);\n\t });\n\t }",
|
||||
"methods": {
|
||||
"selected": "function selected(index) {\n\t for (var i = 0; i < this.tabItems.length; i++) {\n\t var tabItem = this.tabItems[i];\n\t if (i == index) {\n\t tabItem.icon = tabItem.selectedImage;\n\t tabItem.titleColor = this.selectedColor;\n\t tabItem.visibility = 'visible';\n\t } else {\n\t tabItem.icon = tabItem.image;\n\t tabItem.titleColor = this.unselectedColor;\n\t tabItem.visibility = 'hidden';\n\t }\n\t }\n\t }"
|
||||
},
|
||||
"template": {
|
||||
"type": "div",
|
||||
"classList": [
|
||||
"wrapper"
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "embed",
|
||||
"classList": [
|
||||
"content"
|
||||
],
|
||||
"style": {
|
||||
"visibility": "function () {return this.visibility}"
|
||||
},
|
||||
"repeat": "function () {return this.tabItems}",
|
||||
"attr": {
|
||||
"src": "function () {return this.src}",
|
||||
"type": "weex"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "div",
|
||||
"classList": [
|
||||
"tabbar"
|
||||
],
|
||||
"append": "tree",
|
||||
"children": [
|
||||
{
|
||||
"type": "wxc-tabitem",
|
||||
"repeat": "function () {return this.tabItems}",
|
||||
"attr": {
|
||||
"index": "function () {return this.index}",
|
||||
"icon": "function () {return this.icon}",
|
||||
"title": "function () {return this.title}",
|
||||
"titleColor": "function () {return this.titleColor}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"wrapper": {
|
||||
"width": 750,
|
||||
"position": "absolute",
|
||||
"top": 0,
|
||||
"left": 0,
|
||||
"right": 0,
|
||||
"bottom": 0
|
||||
},
|
||||
"content": {
|
||||
"position": "absolute",
|
||||
"top": 0,
|
||||
"left": 0,
|
||||
"right": 0,
|
||||
"bottom": 0,
|
||||
"marginTop": 0,
|
||||
"marginBottom": 88
|
||||
},
|
||||
"tabbar": {
|
||||
"flexDirection": "row",
|
||||
"position": "fixed",
|
||||
"bottom": 0,
|
||||
"left": 0,
|
||||
"right": 0,
|
||||
"height": 88
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/example-list-item": {
|
||||
"data": "function () {return {\n\t title: '',\n\t url: ''\n\t }}",
|
||||
"methods": {
|
||||
"redirect": "function redirect() {\n\t this.$openURL(this.url);\n\t }"
|
||||
},
|
||||
"template": {
|
||||
"type": "wxc-list-item",
|
||||
"events": {
|
||||
"click": "redirect"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"classList": [
|
||||
"item-txt"
|
||||
],
|
||||
"attr": {
|
||||
"value": "function () {return this.title}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {
|
||||
"item-txt": {
|
||||
"fontSize": 48,
|
||||
"color": "#555555"
|
||||
}
|
||||
}
|
||||
},
|
||||
"@weex-component/example-list": {
|
||||
"data": "function () {return {\n\t root: '',\n\t items: [{ name: 'hello', title: 'Hello World', url: '' }]\n\t }}",
|
||||
"created": "function created() {\n\t var bundleUrl = this.$getConfig().bundleUrl;\n\t console.log('hit', bundleUrl);\n\t var dirs = this.root.split('/');\n\t dirs.forEach(function (dir, index) {\n\t if (!dir) dirs.splice(index, 1);\n\t });\n\t var root = dirs.length > 0 ? dirs[0] : '';\n\t var subRoot = dirs.length > 1 ? dirs.slice(1).join('/') + '/' : '';\n\t\n\t var nativeBase;\n\t var isAndroidAssets = bundleUrl.indexOf('your_current_IP') >= 0 || bundleUrl.indexOf('file://assets/') >= 0;\n\t var isiOSAssets = bundleUrl.indexOf('file:///') >= 0 && bundleUrl.indexOf('WeexDemo.app') > 0;\n\t if (isAndroidAssets) {\n\t nativeBase = 'file://assets/';\n\t } else if (isiOSAssets) {\n\t nativeBase = bundleUrl.substring(0, bundleUrl.lastIndexOf('/') + 1);\n\t } else {\n\t var host = 'localhost:12580';\n\t var matches = /\\/\\/([^\\/]+?)\\//.exec(this.$getConfig().bundleUrl);\n\t if (matches && matches.length >= 2) {\n\t host = matches[1];\n\t }\n\t nativeBase = '//' + host + '/' + root + '/build/' + subRoot;\n\t }\n\t var h5Base = './index.html?page=./' + root + '/build/' + subRoot;\n\t\n\t var base = nativeBase;\n\t if ((typeof window === 'undefined' ? 'undefined' : (0, _typeof3.default)(window)) === 'object') {\n\t base = h5Base;\n\t }\n\t\n\t for (var i in this.items) {\n\t var item = this.items[i];\n\t if (!item.url) {\n\t item.url = base + item.name + '.js';\n\t }\n\t }\n\t\n\t if (this.items.length) console.log('hit', this.items[0].url);\n\t }",
|
||||
"template": {
|
||||
"type": "list",
|
||||
"children": [
|
||||
{
|
||||
"type": "cell",
|
||||
"append": "tree",
|
||||
"repeat": "function () {return this.items}",
|
||||
"children": [
|
||||
{
|
||||
"type": "example-list-item",
|
||||
"attr": {
|
||||
"title": "function () {return this.title}",
|
||||
"url": "function () {return this.url}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"style": {}
|
||||
},
|
||||
"@weex-component/ff1b948d57ece2a9e61ad75680c9e80e": {
|
||||
"data": "function () {return {\n\t root: 'examples',\n\t items: [{ name: 'hello', title: 'Hello World' }, { name: 'syntax/index', title: 'More Syntax' }, { name: 'style/index', title: 'Common Style' }, { name: 'animation', title: 'Animation' }, { name: 'component/text-demo', title: 'Text' }, { name: 'component/image-demo', title: 'Image' }, { name: 'component/input-demo', title: 'Input' }, { name: 'component/scroller-demo', title: 'Scroller' }, { name: 'component/list/list-basic', title: 'List (Basic)' }, { name: 'component/list/list-demo', title: 'List (Advanced)' }, { name: 'component/slider/index', title: 'Slider' }, { name: 'component/a-demo', title: 'A' }, { name: 'component/video-demo', title: 'Video' }, { name: 'component/countdown-demo', title: 'Countdown' }, { name: 'component/marquee-demo', title: 'Marquee' }, { name: 'component/web-demo', title: 'Web' }, { name: 'component/navigator-demo', title: 'Navigator' }, { name: 'component/tabbar/tabbar-demo', title: 'Tabbar' }, { name: 'component/process-bar-demo', title: 'ProcessBar' }, { name: 'module/instance-api', title: 'Instance API' }, { name: 'module/modal', title: 'Modal' }, { name: 'module/stream-demo', title: 'Stream' }, { name: 'module/storage-demo', title: 'Storage' }, { name: 'showcase/new-fashion/index', title: 'Activity' }, { name: 'showcase/calculator', title: 'Calculator' }, { name: 'showcase/minesweeper', title: 'Minesweeper' }, { name: 'showcase/ui', title: 'UI Gallery' }, { name: 'showcase/dropdown/dropdown-demo', title: 'Dropdown' }]\n\t }}",
|
||||
"template": {
|
||||
"type": "example-list",
|
||||
"attr": {
|
||||
"items": "function () {return this.items}",
|
||||
"root": "function () {return this.root}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
3
test/spec/a.we
Normal file
3
test/spec/a.we
Normal file
@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<div><text>Hello Weex</text></div>
|
||||
</template>
|
10
test/spec/b.we
Normal file
10
test/spec/b.we
Normal file
@ -0,0 +1,10 @@
|
||||
<template>
|
||||
<div><text class="hi">Hello Weex</text></div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.hi {
|
||||
font-size: 26px;
|
||||
color: red;
|
||||
}
|
||||
</style>
|
22
test/spec/c.we
Normal file
22
test/spec/c.we
Normal file
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<div>
|
||||
<text class="hello">Hello {{name}}</text>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style>
|
||||
.hello {
|
||||
font-size: 26px;
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<script>
|
||||
export function data() {
|
||||
return {
|
||||
name: 'Weex'
|
||||
}
|
||||
}
|
||||
</script>
|
46
test/spec/d.we
Normal file
46
test/spec/d.we
Normal file
@ -0,0 +1,46 @@
|
||||
<element name="name">
|
||||
<template>
|
||||
<div><text class="name">{{name}}</text></div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.name {
|
||||
font-size: 26px;
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
module.exports = {
|
||||
data: function() {
|
||||
return {
|
||||
name: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</element>
|
||||
|
||||
<template>
|
||||
<div style="flex-direction: row;">
|
||||
<text class="hello">Hello</text>
|
||||
<name name="{{name}}"></name>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style>
|
||||
.hello {
|
||||
font-size: 26px;
|
||||
color: green;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<script>
|
||||
export function data() {
|
||||
return {
|
||||
name: 'Weex'
|
||||
}
|
||||
}
|
||||
</script>
|
3
test/spec/data.json
Normal file
3
test/spec/data.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"name": "Weex"
|
||||
}
|
61
test/spec/e.we
Normal file
61
test/spec/e.we
Normal file
@ -0,0 +1,61 @@
|
||||
<element name="hi">
|
||||
<template>
|
||||
<div><text class="hi">{{hi}}</text></div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.hi {
|
||||
font-size: 26px;
|
||||
color: green;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
module.exports = {
|
||||
data: function() {
|
||||
return {
|
||||
hi: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</element>
|
||||
|
||||
<we-element name="name">
|
||||
<template>
|
||||
<div><text class="name">{{name}}</text></div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.name {
|
||||
font-size: 26px;
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
module.exports = {
|
||||
data: function() {
|
||||
return {
|
||||
name: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</we-element>
|
||||
|
||||
<template>
|
||||
<div style="flex-direction: row;">
|
||||
<hi hi="{{hi}}"></hi>
|
||||
<name name="{{name}}"></name>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export function data() {
|
||||
return {
|
||||
hi: 'Hello',
|
||||
name: 'Weex'
|
||||
}
|
||||
}
|
||||
</script>
|
27
test/spec/example-list-item.we
Normal file
27
test/spec/example-list-item.we
Normal file
@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<wxc-list-item onclick="{{redirect}}">
|
||||
<text class="item-txt">{{ title }}</text>
|
||||
</wxc-list-item>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.item-txt {
|
||||
font-size: 48px;
|
||||
color: #555;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
require('weex-components');
|
||||
module.exports = {
|
||||
data: {
|
||||
title: '',
|
||||
url: ''
|
||||
},
|
||||
methods: {
|
||||
redirect: function() {
|
||||
this.$openURL(this.url);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
68
test/spec/example-list.we
Normal file
68
test/spec/example-list.we
Normal file
@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<list>
|
||||
<cell repeat="{{items}}">
|
||||
<example-list-item title="{{title}}" url="{{url}}"></example-list-item>
|
||||
</cell>
|
||||
</list>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
require('weex-components');
|
||||
module.exports = {
|
||||
data: {
|
||||
root: '', // examples, examples/syntax, test ...
|
||||
items: [
|
||||
{name: 'hello', title: 'Hello World', url: ''}
|
||||
]
|
||||
},
|
||||
created: function() {
|
||||
var bundleUrl = this.$getConfig().bundleUrl;
|
||||
console.log('hit', bundleUrl);
|
||||
var dirs = this.root.split('/');
|
||||
dirs.forEach(function(dir, index) {
|
||||
if (!dir) dirs.splice(index, 1);
|
||||
});
|
||||
var root = dirs.length > 0 ? dirs[0] : '';
|
||||
var subRoot = dirs.length > 1 ? dirs.slice(1).join('/') + '/' : '';
|
||||
|
||||
var nativeBase;
|
||||
var isAndroidAssets = bundleUrl.indexOf('your_current_IP') >= 0 || bundleUrl.indexOf('file://assets/')>=0;
|
||||
var isiOSAssets = bundleUrl.indexOf('file:///') >= 0 && bundleUrl.indexOf('WeexDemo.app') > 0;
|
||||
if (isAndroidAssets) {
|
||||
nativeBase = 'file://assets/';
|
||||
}
|
||||
else if (isiOSAssets) {
|
||||
// file:///var/mobile/Containers/Bundle/Application/{id}/WeexDemo.app/
|
||||
// file:///Users/{user}/Library/Developer/CoreSimulator/Devices/{id}/data/Containers/Bundle/Application/{id}/WeexDemo.app/
|
||||
nativeBase = bundleUrl.substring(0, bundleUrl.lastIndexOf('/') + 1);
|
||||
}
|
||||
else {
|
||||
var host = 'localhost:12580';
|
||||
var matches = /\/\/([^\/]+?)\//.exec(this.$getConfig().bundleUrl);
|
||||
if (matches && matches.length >= 2) {
|
||||
host = matches[1];
|
||||
}
|
||||
nativeBase = '//' + host + '/' + root + '/build/' + subRoot;
|
||||
}
|
||||
var h5Base = './index.html?page=./' + root + '/build/' + subRoot;
|
||||
// in Native
|
||||
var base = nativeBase;
|
||||
if (typeof window === 'object') {
|
||||
// in Browser or WebView
|
||||
base = h5Base;
|
||||
}
|
||||
|
||||
for (var i in this.items) {
|
||||
var item = this.items[i];
|
||||
if (!item.url) {
|
||||
item.url = base + item.name + '.js';
|
||||
}
|
||||
}
|
||||
// see log in Android Logcat
|
||||
if (this.items.length) console.log('hit', this.items[0].url);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
3
test/spec/f.css
Normal file
3
test/spec/f.css
Normal file
@ -0,0 +1,3 @@
|
||||
.wrap {
|
||||
flex-direction: row;
|
||||
}
|
4
test/spec/f.html
Normal file
4
test/spec/f.html
Normal file
@ -0,0 +1,4 @@
|
||||
<div class="wrap">
|
||||
<hi hi="{{hi}}"></hi>
|
||||
<name name="{{name}}"></name>
|
||||
</div>
|
6
test/spec/f.js
Normal file
6
test/spec/f.js
Normal file
@ -0,0 +1,6 @@
|
||||
export function data() {
|
||||
return {
|
||||
hi: 'Hello',
|
||||
name: 'Weex'
|
||||
}
|
||||
}
|
5
test/spec/f.we
Normal file
5
test/spec/f.we
Normal file
@ -0,0 +1,5 @@
|
||||
<element name="hi" src="./hi.we"></element>
|
||||
<element name="name" src="./name.we"></element>
|
||||
<template src="./f.html"></template>
|
||||
<style src="./f.css"></style>
|
||||
<script src="./f.js"></script>
|
27
test/spec/g.we
Normal file
27
test/spec/g.we
Normal file
@ -0,0 +1,27 @@
|
||||
<element name="name1" src="./name.we"></element>
|
||||
|
||||
<template>
|
||||
<div class="wrap">
|
||||
<hi1 hi="{{hi}}"></hi1>
|
||||
<name1 name="{{name}}"></name1>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.wrap {
|
||||
flex-direction: row;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import './hi.we?name=hi1'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
hi: 'Hello',
|
||||
name: 'Weex'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
1
test/spec/getName.js
Normal file
1
test/spec/getName.js
Normal file
@ -0,0 +1 @@
|
||||
export default () => 'Weex'
|
25
test/spec/h.we
Normal file
25
test/spec/h.we
Normal file
@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<div class="wrap">
|
||||
<hi hi="{{hi}}"></hi>
|
||||
<name name="{{name}}"></name>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.wrap {
|
||||
flex-direction: row;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import './hi.we';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
hi: 'Hello',
|
||||
name: 'Weex'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
20
test/spec/hi.we
Normal file
20
test/spec/hi.we
Normal file
@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<div><text class="hi">{{hi}}</text></div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.hi {
|
||||
font-size: 26px;
|
||||
color: green;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
hi: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
22
test/spec/i.we
Normal file
22
test/spec/i.we
Normal file
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<div>
|
||||
<text class="hello">Hello {{name}}</text>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style>
|
||||
.hello {
|
||||
font-size: 26px;
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<script type="config">
|
||||
{
|
||||
downgrade: true
|
||||
}
|
||||
</script>
|
||||
|
||||
<script type="data" src="./data.json"></script>
|
28
test/spec/j.we
Normal file
28
test/spec/j.we
Normal file
@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<div class="wrap">
|
||||
<text>{{hi}}</text>
|
||||
<text>{{name}}</text>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.wrap {
|
||||
flex-direction: row;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import modal from '@weex-module/modal'
|
||||
|
||||
export default {
|
||||
ready() {
|
||||
modal.toast({'message': 'ready'})
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
hi: 'Hello',
|
||||
name: 'Weex'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
43
test/spec/k.we
Normal file
43
test/spec/k.we
Normal file
@ -0,0 +1,43 @@
|
||||
<template lang="jade">
|
||||
.wrap
|
||||
text.text-hi {{hi}}
|
||||
text.text-name {{name}}
|
||||
</template>
|
||||
|
||||
<style lang="cssnext">
|
||||
:root {
|
||||
--mainColor: red;
|
||||
--subColor: green;
|
||||
--normalFont: {
|
||||
font-size: 26px;
|
||||
};
|
||||
}
|
||||
|
||||
.wrap {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.text-hi {
|
||||
color: var(--mainColor);
|
||||
@apply --normalFont;
|
||||
}
|
||||
|
||||
.text-name {
|
||||
color: var(--subColor);
|
||||
@apply --normalFont;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script lang="coffee">
|
||||
modal = require '@weex-module/modal'
|
||||
|
||||
module.exports =
|
||||
ready: () ->
|
||||
modal.toast({'message': 'ready'})
|
||||
|
||||
data: () ->
|
||||
return {
|
||||
hi: 'Hello',
|
||||
name: 'Weex'
|
||||
}
|
||||
</script>
|
29
test/spec/l.we
Normal file
29
test/spec/l.we
Normal file
@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<div>
|
||||
<text class="hello">Hello {{name}}</text>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style>
|
||||
.hello {
|
||||
font-size: 26px;
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<script>
|
||||
import modal from '@weex-module/modal'
|
||||
import getName from './getName.js'
|
||||
|
||||
export function ready() {
|
||||
modal.toast({message: this.name})
|
||||
}
|
||||
|
||||
export function data() {
|
||||
return {
|
||||
name: getName()
|
||||
}
|
||||
}
|
||||
</script>
|
29
test/spec/m.we
Normal file
29
test/spec/m.we
Normal file
@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<div>
|
||||
<text class="hello">Hello {{name}}</text>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style>
|
||||
.hello {
|
||||
font-size: 26px;
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<script>
|
||||
import toast from './toast.js'
|
||||
|
||||
export default {
|
||||
ready() {
|
||||
toast(this.name)
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
name: 'Weex'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
37
test/spec/n.we
Normal file
37
test/spec/n.we
Normal file
@ -0,0 +1,37 @@
|
||||
<element name="hi">
|
||||
<template>
|
||||
<div><text class="hi">{{hi}}</text></div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.hi {
|
||||
font-size: 26px;
|
||||
color: green;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
console.log('Hi Component Comment')
|
||||
return {
|
||||
hi: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</element>
|
||||
|
||||
<element name="name" src="./name.we"></element>
|
||||
|
||||
<template src="./f.html"></template>
|
||||
<style src="./f.css"></style>
|
||||
<script>
|
||||
export function data() {
|
||||
console.log('N comment')
|
||||
return {
|
||||
hi: 'Hello',
|
||||
name: 'Weex'
|
||||
}
|
||||
}
|
||||
</script>
|
4
test/spec/name.css
Normal file
4
test/spec/name.css
Normal file
@ -0,0 +1,4 @@
|
||||
.name {
|
||||
font-size: 26px;
|
||||
color: red;
|
||||
}
|
1
test/spec/name.html
Normal file
1
test/spec/name.html
Normal file
@ -0,0 +1 @@
|
||||
<div><text class="name">{{name}}</text></div>
|
8
test/spec/name.js
Normal file
8
test/spec/name.js
Normal file
@ -0,0 +1,8 @@
|
||||
export default {
|
||||
data() {
|
||||
console.log('Name Component Comment')
|
||||
return {
|
||||
name: ''
|
||||
}
|
||||
}
|
||||
}
|
3
test/spec/name.we
Normal file
3
test/spec/name.we
Normal file
@ -0,0 +1,3 @@
|
||||
<template src="./name.html"></template>
|
||||
<style src="./name.css"></style>
|
||||
<script src="./name.js"></script>
|
54
test/spec/o.we
Normal file
54
test/spec/o.we
Normal file
@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<example-list items="{{items}}" root="{{root}}"></example-list>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
require('./example-list.we');
|
||||
module.exports = {
|
||||
data: {
|
||||
root: 'examples',
|
||||
items: [
|
||||
// FORMAT:
|
||||
// `name` key is the example filename without '.we'
|
||||
// Support sub directory, e.g. 'new-fashion/index'
|
||||
|
||||
// common
|
||||
{name: 'hello', title: 'Hello World'},
|
||||
{name: 'syntax/index', title: 'More Syntax'},
|
||||
{name: 'style/index', title: 'Common Style'},
|
||||
{name: 'animation', title: 'Animation'},
|
||||
|
||||
// component
|
||||
{name: 'component/text-demo', title: 'Text'},
|
||||
{name: 'component/image-demo', title: 'Image'},
|
||||
{name: 'component/input-demo', title: 'Input'},
|
||||
{name: 'component/scroller-demo', title: 'Scroller'},
|
||||
{name: 'component/list/list-basic', title: 'List (Basic)'},
|
||||
{name: 'component/list/list-demo', title: 'List (Advanced)'},
|
||||
{name: 'component/slider/index', title: 'Slider'},
|
||||
{name: 'component/a-demo', title: 'A'},
|
||||
{name: 'component/video-demo', title: 'Video'},
|
||||
{name: 'component/countdown-demo', title: 'Countdown'},
|
||||
{name: 'component/marquee-demo', title: 'Marquee'},
|
||||
{name: 'component/web-demo', title: 'Web'},
|
||||
{name: 'component/navigator-demo', title: 'Navigator'},
|
||||
{name: 'component/tabbar/tabbar-demo', title: 'Tabbar'},
|
||||
{name: 'component/process-bar-demo', title: 'ProcessBar'},
|
||||
|
||||
// module
|
||||
{name: 'module/instance-api', title: 'Instance API'},
|
||||
{name: 'module/modal', title: 'Modal'},
|
||||
{name: 'module/stream-demo', title: 'Stream'},
|
||||
{name: 'module/storage-demo',title:'Storage'},
|
||||
// {name: 'module/clipboard', title: 'Clipboard'}, // 0.8 , developing
|
||||
|
||||
// showcase
|
||||
{name: 'showcase/new-fashion/index', title: 'Activity'},
|
||||
{name: 'showcase/calculator', title: 'Calculator'},
|
||||
{name: 'showcase/minesweeper', title: 'Minesweeper'},
|
||||
{name: 'showcase/ui', title: 'UI Gallery'},
|
||||
{name: 'showcase/dropdown/dropdown-demo', title: 'Dropdown'}
|
||||
]
|
||||
}
|
||||
}
|
||||
</script>
|
8
test/spec/toast.js
Normal file
8
test/spec/toast.js
Normal file
@ -0,0 +1,8 @@
|
||||
var modal
|
||||
__weex_define__('@weex-component/toast', [], function(__weex_require__) {
|
||||
modal = __weex_require__('@weex-module/modal')
|
||||
})
|
||||
|
||||
module.exports = function(msg) {
|
||||
modal.toast({message: msg})
|
||||
}
|
189
test/test.js
Normal file
189
test/test.js
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path =require('path');
|
||||
|
||||
const chai = require('chai');
|
||||
const sinon = require('sinon');
|
||||
const sinonChai = require('sinon-chai');
|
||||
const expect = chai.expect;
|
||||
chai.use(sinonChai);
|
||||
|
||||
const Base64 = require('js-base64').Base64;
|
||||
const SourceMap = require('source-map');
|
||||
|
||||
function getActualString(name) {
|
||||
const filepath = path.resolve(__dirname, 'actual', `${name}.js`);
|
||||
const result = fs.readFileSync(filepath, 'utf-8');
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
function getExpectJSON(name) {
|
||||
const filepath = path.resolve(__dirname, 'expect', `${name}.js`);
|
||||
const result = fs.readFileSync(filepath, 'utf-8');
|
||||
return JSON.parse(result.toString());
|
||||
}
|
||||
|
||||
function stringifyActual(json) {
|
||||
return JSON.stringify(json, function(key, value) {
|
||||
if (typeof value === 'function') {
|
||||
value = value.toString();
|
||||
}
|
||||
return value;
|
||||
}, ' ');
|
||||
}
|
||||
|
||||
function extractMap(actualStr) {
|
||||
const mapStr = actualStr.match(/\/\/\# sourceMappingURL=data:application\/json;charset=utf-8;base64,([0-9a-zA-Z=+\/]+)/)
|
||||
if (mapStr) {
|
||||
return JSON.parse(Base64.decode(mapStr[1]));
|
||||
}
|
||||
}
|
||||
|
||||
describe('build', () => {
|
||||
let __weex_define__;
|
||||
let __weex_bootstrap__;
|
||||
let components;
|
||||
let requireStub;
|
||||
let bootstrapStub;
|
||||
|
||||
function expectActual(name) {
|
||||
const actualStr = getActualString(name);
|
||||
const fn = new Function('__weex_define__', '__weex_bootstrap__', actualStr);
|
||||
fn(__weex_define__, __weex_bootstrap__);
|
||||
|
||||
// const filepath = path.resolve(__dirname, 'expect', `${name}.js`);
|
||||
// fs.writeFileSync(filepath, stringifyActual(components), 'utf-8');
|
||||
|
||||
const expectJSON = getExpectJSON(name);
|
||||
expect(JSON.parse(stringifyActual(components))).eql(expectJSON);
|
||||
expect(components).to.include.keys(__weex_bootstrap__.firstCall.args[0]);
|
||||
|
||||
return actualStr;
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
components = {};
|
||||
requireStub = sinon.stub();
|
||||
bootstrapStub = sinon.stub();
|
||||
|
||||
__weex_define__ = function(componentName, deps, factory) {
|
||||
if (components[componentName]) {
|
||||
throw new Error(`${componentName} is defined repeatly`);
|
||||
}
|
||||
|
||||
var __weex_require__ = requireStub;
|
||||
var __weex_exports__ = {};
|
||||
var __weex_module__ = {exports : __weex_exports__}
|
||||
|
||||
factory(__weex_require__, __weex_exports__, __weex_module__)
|
||||
components[componentName] = __weex_module__.exports
|
||||
}
|
||||
|
||||
__weex_bootstrap__ = bootstrapStub;
|
||||
|
||||
});
|
||||
|
||||
it('single template', () => {
|
||||
expectActual('a');
|
||||
});
|
||||
|
||||
it('template with style', () => {
|
||||
expectActual('b');
|
||||
});
|
||||
|
||||
it('template with style and script', () => {
|
||||
expectActual('c');
|
||||
});
|
||||
|
||||
it('template with single inline element', () => {
|
||||
expectActual('d');
|
||||
});
|
||||
|
||||
it('template with multiple inline elements', () => {
|
||||
expectActual('e');
|
||||
});
|
||||
|
||||
it('parted files specifed in src', () => {
|
||||
expectActual('f');
|
||||
});
|
||||
|
||||
it('component by requiring src and specifing alias', () => {
|
||||
expectActual('g');
|
||||
expect(requireStub.callCount).eql(0);
|
||||
});
|
||||
|
||||
it('component under same folder', () => {
|
||||
expectActual('h');
|
||||
});
|
||||
|
||||
it('template with config and data', () => {
|
||||
expectActual('i');
|
||||
expect(bootstrapStub.firstCall.args[1]).is.not.undefined;
|
||||
expect(bootstrapStub.firstCall.args[2]).is.not.undefined;
|
||||
});
|
||||
|
||||
it('template and use weex module', () => {
|
||||
expectActual('j');
|
||||
expect(requireStub.callCount).eql(1);
|
||||
expect(requireStub.firstCall.args).eql(['@weex-module/modal']);
|
||||
});
|
||||
|
||||
it('template by using custom language', () => {
|
||||
expectActual('k');
|
||||
expect(requireStub.callCount).eql(1);
|
||||
expect(requireStub.firstCall.args).eql(['@weex-module/modal']);
|
||||
});
|
||||
|
||||
it('template and require commonjs module', () => {
|
||||
expectActual('l');
|
||||
expect(requireStub.callCount).eql(1);
|
||||
expect(requireStub.firstCall.args).eql(['@weex-module/modal']);
|
||||
});
|
||||
|
||||
it('template and use weex module in commonjs module', () => {
|
||||
expectActual('m');
|
||||
expect(requireStub.callCount).eql(1);
|
||||
expect(requireStub.firstCall.args).eql(['@weex-module/modal']);
|
||||
});
|
||||
|
||||
it.skip('template with sourcemap', () => {
|
||||
const actualStr = expectActual('n');
|
||||
const map = extractMap(actualStr);
|
||||
const smc = new SourceMap.SourceMapConsumer(map);
|
||||
|
||||
// new Array(276).fill(0).forEach((n, i) => {
|
||||
// i = i + 1
|
||||
// const original = smc.originalPositionFor({
|
||||
// line: i,
|
||||
// column: 0
|
||||
// })
|
||||
// if (original.source) {
|
||||
// console.log(i, original.line, original.source)
|
||||
// }
|
||||
// })
|
||||
});
|
||||
|
||||
it('weex examples', () => {
|
||||
expectActual('o');
|
||||
});
|
||||
});
|
50
test/webpack.config.js
Normal file
50
test/webpack.config.js
Normal file
@ -0,0 +1,50 @@
|
||||
var path = require('path')
|
||||
var cssnext = require('postcss-cssnext')
|
||||
|
||||
var entry = {}
|
||||
var start = 'a'
|
||||
var end = 'o'
|
||||
var count = end.charCodeAt(0) - start.charCodeAt(0)
|
||||
|
||||
new Array(count + 1).fill(0)
|
||||
.forEach((n, i) => {
|
||||
var name = String.fromCharCode(i + start.charCodeAt(0))
|
||||
entry[name] = path.resolve(__dirname, 'spec', name + '.we?entry')
|
||||
})
|
||||
|
||||
module.exports = {
|
||||
entry: entry,
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'actual'),
|
||||
filename: '[name].js'
|
||||
},
|
||||
devtool: 'source-map',
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
test: /\.we(\?[^?]+)?$/,
|
||||
loaders: [path.resolve(__dirname, '..', 'index.js')]
|
||||
},
|
||||
{
|
||||
test: /\.js/,
|
||||
loaders: ['babel?presets[]=es2015']
|
||||
}
|
||||
]
|
||||
},
|
||||
devtool: 'inline-source-map',
|
||||
resolveLoader: {
|
||||
modulesDirectories: ['./node_modules']
|
||||
},
|
||||
postcss: function() {
|
||||
return [cssnext({
|
||||
browsers: ['last 1 version']
|
||||
})]
|
||||
},
|
||||
weex: {
|
||||
lang: {
|
||||
cssnext: ['postcss'],
|
||||
jade: ['jade-html'],
|
||||
coffee: ['coffee']
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user