Merge branch 'master'

This commit is contained in:
Vasil Trifonov
2020-01-17 15:12:28 +02:00
parent 432a029499
commit b76893801d
3131 changed files with 418263 additions and 185769 deletions

View File

@@ -0,0 +1,85 @@
import { cssTreeParse } from "@nativescript/core/css/css-tree-parser";
import { parse as reworkCssParse } from "@nativescript/core/css";
import { assert } from "chai";
describe("css-tree parser compatible with rework ", () => {
it("basic selector", () => {
const testCase = ".test { color: red; }";
const reworkAST = reworkCssParse(testCase, { source: "file.css" });
const cssTreeAST = cssTreeParse(testCase, "file.css");
assert.deepEqual(cssTreeAST, reworkAST);
});
it("@keyframes", () => {
const testCase = ".test { animation-name: test; } @keyframes test { from { background-color: red; } to { background-color: blue; } } .test { color: red; }";
const reworkAST = reworkCssParse(testCase, { source: "file.css" });
const cssTreeAST = cssTreeParse(testCase, "file.css");
assert.deepEqual(cssTreeAST, reworkAST);
});
it("@media", () => {
const testCase = "@media screen and (max-width: 600px) { body { background-color: olive; } } .test { color: red; }";
const reworkAST = reworkCssParse(testCase, { source: "file.css" });
const cssTreeAST = cssTreeParse(testCase, "file.css");
assert.deepEqual(cssTreeAST, reworkAST);
});
it("@supports", () => {
const testCase = "@supports not (display: grid) { div { float: right; } } .test { color: red; }";
const reworkAST = reworkCssParse(testCase, { source: "file.css" });
const cssTreeAST = cssTreeParse(testCase, "file.css");
assert.deepEqual(cssTreeAST, reworkAST);
});
it("@page", () => {
const testCase = "@page :first { margin: 2cm; } .test { color: red; }";
const reworkAST = reworkCssParse(testCase, { source: "file.css" });
const cssTreeAST = cssTreeParse(testCase, "file.css");
assert.deepEqual(cssTreeAST, reworkAST);
});
it("@document", () => {
const testCase = "@document url(\"https://www.example.com/\") { h1 { color: green; } } .test { color: red; }";
const reworkAST = reworkCssParse(testCase, { source: "file.css" });
const cssTreeAST = cssTreeParse(testCase, "file.css");
assert.deepEqual(cssTreeAST, reworkAST);
});
it("@font-face", () => {
const testCase = "@font-face { font-family: \"Open Sans\"; src: url(\"/fonts/OpenSans-Regular-webfont.woff2\") format(\"woff2\"), url(\"/fonts/OpenSans-Regular-webfont.woff\") format(\"woff\"); } .test { color: red; }";
const reworkAST = reworkCssParse(testCase, { source: "file.css" });
const cssTreeAST = cssTreeParse(testCase, "file.css");
assert.deepEqual(cssTreeAST, reworkAST);
});
it("@import", () => {
const testCase = "@import url('landscape.css') screen and (orientation:landscape); @import url(\"fineprint.css\") print; .test { color: red; }";
const reworkAST = reworkCssParse(testCase, { source: "file.css" });
const cssTreeAST = cssTreeParse(testCase, "file.css");
assert.deepEqual(cssTreeAST, reworkAST);
});
it("@charset", () => {
const testCase = "@charset \"utf-8\"; .test { color: red; }";
const reworkAST = reworkCssParse(testCase, { source: "file.css" });
const cssTreeAST = cssTreeParse(testCase, "file.css");
assert.deepEqual(cssTreeAST, reworkAST);
});
it("@namespace", () => {
const testCase = "@namespace svg url(http://www.w3.org/2000/svg); .test { color: red; }";
const reworkAST = reworkCssParse(testCase, { source: "file.css" });
const cssTreeAST = cssTreeParse(testCase, "file.css");
assert.deepEqual(cssTreeAST, reworkAST);
});
});

View File

@@ -10,19 +10,16 @@ import {
CSS3Parser,
TokenObjectType,
CSSNativeScript,
} from "tns-core-modules/css/parser";
import {
parse
} from "tns-core-modules/css";
} from "@nativescript/core/css/parser";
import * as fs from "fs";
import * as shadyCss from 'shady-css-parser';
import * as reworkCss from 'css';
import * as shadyCss from "shady-css-parser";
import * as reworkCss from "css";
const parseCss: any = require('parse-css');
const gonzales: any = require('gonzales');
const parseCss: any = require("parse-css");
const gonzales: any = require("gonzales");
const parserlib: any = require("parserlib");
const csstree: any = require('css-tree');
const csstree: any = require("css-tree");
describe("css", () => {
describe("parser", () => {
@@ -45,7 +42,7 @@ describe("css", () => {
describe("values", () => {
describe("url", () => {
test(parseURL, "url('smiley.gif') ", { start: 0, end: 19, value: "smiley.gif" });
test(parseURL, ' url("frown.gif") ', { start: 0, end: 19, value: "frown.gif" });
test(parseURL, " url(\"frown.gif\") ", { start: 0, end: 19, value: "frown.gif" });
test(parseURL, " url(lucky.gif)", { start: 0, end: 16, value: "lucky.gif" });
test(parseURL, "url(lucky.gif) #FF0000", 15, null);
test(parseURL, "repeat url(lucky.gif) #FF0000", 6, { start: 6, end: 22, value: "lucky.gif" });
@@ -56,6 +53,8 @@ describe("css", () => {
test(parseColor, " #85456789 ", { start: 0, end: 12, value: 0x85456789 });
test(parseColor, " rgb(255, 8, 128) ", { start: 0, end: 18, value: 0xFFFF0880 });
test(parseColor, " rgba(255, 8, 128, 0.5) ", { start: 0, end: 24, value: 0x80FF0880 });
test(parseColor, " hsl(330.9, 100%, 51.6%) ", { start: 0, end: 25, value: 0xFFFF0880 });
test(parseColor, " hsla(330.9, 100%, 51.6%, 0.5) ", { start: 0, end: 31, value: 0x80FF0880 });
test(parseColor, "#FF0000 url(lucky.gif)", 8, null);
test(parseColor, "url(lucky.gif) #FF0000 repeat", 15, { start: 15, end: 23, value: 0xFFFF0000 });
});
@@ -90,8 +89,8 @@ describe("css", () => {
});
describe("background", () => {
test(parseBackground, " #996633 ", { start: 0, end: 12, value: { color: 0xFF996633 }});
test(parseBackground, ' #00ff00 url("smiley.gif") repeat-y ', { start: 0, end: 37, value: { color: 0xFF00FF00, image: "smiley.gif", repeat: "repeat-y" }});
test(parseBackground, ' url(smiley.gif) no-repeat top 50% left 100% #00ff00', { start: 0, end: 56, value: {
test(parseBackground, " #00ff00 url(\"smiley.gif\") repeat-y ", { start: 0, end: 37, value: { color: 0xFF00FF00, image: "smiley.gif", repeat: "repeat-y" }});
test(parseBackground, " url(smiley.gif) no-repeat top 50% left 100% #00ff00", { start: 0, end: 56, value: {
color: 0xFF00FF00,
image: "smiley.gif",
repeat: "no-repeat",
@@ -101,7 +100,7 @@ describe("css", () => {
y: { align: "top", offset: { value: 0.5, unit: "%" }}
}
}});
test(parseBackground, ' url(smiley.gif) no-repeat top 50% left 100% / 100px 100px #00ff00', { start: 0, end: 70, value: {
test(parseBackground, " url(smiley.gif) no-repeat top 50% left 100% / 100px 100px #00ff00", { start: 0, end: 70, value: {
color: 0xFF00FF00,
image: "smiley.gif",
repeat: "no-repeat",
@@ -112,24 +111,24 @@ describe("css", () => {
},
size: { x: { value: 100, unit: "px" }, y: { value: 100, unit: "px" }}
}});
test(parseBackground, ' linear-gradient(to right top) ', { start: 0, end: 32, value: {
test(parseBackground, " linear-gradient(to right top) ", { start: 0, end: 32, value: {
image: {
angle: Math.PI * 1/4,
angle: Math.PI * 1 / 4,
colors: []
}
}});
test(parseBackground, ' linear-gradient(45deg, #0000FF, #00FF00) ', { start: 0, end: 43, value: {
test(parseBackground, " linear-gradient(45deg, #0000FF, #00FF00) ", { start: 0, end: 43, value: {
image: {
angle: Math.PI * 1/4,
angle: Math.PI * 1 / 4,
colors: [
{ argb: 0xFF0000FF },
{ argb: 0xFF00FF00 }
]
}
}});
test(parseBackground, 'linear-gradient(0deg, blue, green 40%, red)', { start: 0, end: 43, value: {
test(parseBackground, "linear-gradient(0deg, blue, green 40%, red)", { start: 0, end: 43, value: {
image: {
angle: Math.PI * 0/4,
angle: Math.PI * 0 / 4,
colors: [
{ argb: 0xFF0000FF },
{ argb: 0xFF008000, offset: { value: 0.4, unit: "%" }},
@@ -175,11 +174,11 @@ describe("css", () => {
test(parseSelector, `[src ${attributeTest} "val"]`, { start: 0, end: 12 + attributeTest.length, value: [[[{ type: "[]", property: "src", test: attributeTest, value: "val"}], undefined]]});
});
test(parseSelector, "listview > .image", { start: 0, end: 17, value: [
[[{ type: "", identifier: "listview"}], ">"],
[[{ type: "", identifier: "listview"}], ">"],
[[{ type: ".", identifier: "image"}], undefined]
]});
test(parseSelector, "listview .image", { start: 0, end: 16, value: [
[[{ type: "", identifier: "listview"}], " "],
[[{ type: "", identifier: "listview"}], " "],
[[{ type: ".", identifier: "image"}], undefined]
]});
test(parseSelector, "button:hover", { start: 0, end: 12, value: [[[{ type: "", identifier: "button" }, { type: ":", identifier: "hover"}], undefined]]});
@@ -227,15 +226,23 @@ describe("css", () => {
let original = themeCoreLightIos.replace(/\/\*([^\/]|\/[^\*])*\*\//g, "").replace(/\n/g, " ");
let roundtrip = stylesheet.map(m => {
if (!m) return "";
if (typeof m === "string") return m;
if (!m) {
return "";
}
if (typeof m === "string") {
return m;
}
return m.text;
}).join("");
let lastIndex = Math.min(original.length, roundtrip.length);
for(var i = 0; i < lastIndex; i++)
if (original[i] != roundtrip[i])
for (var i = 0; i < lastIndex; i++) {
if (original[i] !== roundtrip[i]) {
assert.equal(roundtrip.substr(i, 50), original.substr(i, 50), "Round-tripped CSS string differ at index: " + i);
}
}
assert.equal(roundtrip.length, original.length, "Expected round-tripped string lengths to match.");
});
@@ -317,7 +324,7 @@ describe("css", () => {
const parser = new CSS3Parser(".btn-primary{border-color:rgba(255,0,0,0)}");
const stylesheet = parser.parseAStylesheet();
assert.deepEqual(stylesheet, {rules:[
assert.deepEqual(stylesheet, {rules: [
{
type: "qualified-rule",
prelude: [{ type: 2, text: "." }, { type: 6, text: "btn-primary" }],
@@ -368,6 +375,7 @@ describe("css", () => {
const [startSec, startMSec] = process.hrtime();
action();
const [endSec, endMSec] = process.hrtime();
return (endSec - startSec) * 1000 + (endMSec - startMSec) / 1000000;
}
const charCodeByCharCodeDuration = trapDuration(() => {
@@ -388,7 +396,7 @@ describe("css", () => {
let char;
let c = 0;
for (let i = 0; i < themeCoreLightIos.length; i++) {
const char = themeCoreLightIos[i];
char = themeCoreLightIos[i];
if ((char >= "a" && char <= "z") || (char >= "A" && char <= "Z") || char === "_") {
c++;
}
@@ -400,7 +408,7 @@ describe("css", () => {
let char;
let c = 0;
for (let i = 0; i < themeCoreLightIos.length; i++) {
const char = themeCoreLightIos[i];
char = themeCoreLightIos[i];
if (compareCharRegEx.test(char)) {
c++;
}

View File

@@ -1,4 +1,4 @@
import { Observable } from "tns-core-modules/data/observable";
import { Observable } from "@nativescript/core/data/observable";
import { assert } from "chai";
describe("observable", () => {

View File

@@ -3,19 +3,20 @@ import "tslib";
import * as moduleAlias from "module-alias";
import * as path from "path";
const tnsCoreModules = path.resolve(__dirname, "..", "tns-core-modules");
const tnsCoreModules = path.resolve(__dirname, "..", "nativescript-core");
moduleAlias.addPath(tnsCoreModules);
moduleAlias.addAliases({
// NOTE: require("tns-core-modules/platform") with these aliases will work in node but fail in Angular AoT
"tns-core-modules/platform": path.resolve(__dirname, "polyfills", "platform"),
"tns-core-modules/file-system/file-system-access": path.resolve(__dirname, "polyfills", "file-system-access"),
"tns-core-modules/utils/utils": path.resolve(tnsCoreModules, "utils/utils-common"),
// NOTE: require("@nativescript/core/platform") with these aliases will work in node but fail in Angular AoT
"@nativescript/core/platform": path.resolve(__dirname, "polyfills", "platform"),
"@nativescript/core/file-system/file-system-access": path.resolve(__dirname, "polyfills", "file-system-access"),
"@nativescript/core/utils/utils": path.resolve(tnsCoreModules, "utils/utils-common"),
"./layout-helper": path.resolve(tnsCoreModules, "utils/layout-helper/layout-helper-common"),
"./mainthread-helper": path.resolve(__dirname, "polyfills", "mainthread-helper"),
"tns-core-modules/color": path.resolve(tnsCoreModules, "color/color-common"),
"tns-core-modules/ui/styling/font": path.resolve(tnsCoreModules, "ui/styling/font-common"),
"tns-core-modules/ui/styling/background": path.resolve(tnsCoreModules, "ui/styling/background-common"),
"@nativescript/core/color": path.resolve(tnsCoreModules, "color/color-common"),
"@nativescript/core/ui/styling/font": path.resolve(tnsCoreModules, "ui/styling/font-common"),
"@nativescript/core/ui/styling/background": path.resolve(tnsCoreModules, "ui/styling/background-common"),
"tns-core-modules": tnsCoreModules,
"@nativescript/core": tnsCoreModules,
"~": __dirname
});

42
unit-tests/tsconfig.json Normal file
View File

@@ -0,0 +1,42 @@
{
"compilerOptions": {
"noEmitOnError": false,
"noEmitHelpers": true,
"target": "es5",
"module": "commonjs",
"noImplicitUseStrict": true,
"removeComments": true,
"experimentalDecorators": true,
"diagnostics": true,
"sourceMap": true,
"inlineSourceMap": false,
"lib": [
"es6",
"dom"
],
"types": [
"node",
"chai",
"mocha"
],
"baseUrl": ".",
"paths": {
"@nativescript/core/*": [
"../nativescript-core/*"
]
}
},
"include": [
"../nativescript-core/**/*.ts",
"./**/*.ts"
],
"exclude": [
"../nativescript-core/**/*.android.ts",
"../nativescript-core/**/*.android.d.ts",
"../nativescript-core/**/*.ios.ts",
"../nativescript-core/**/*.ios.d.ts",
"../nativescript-core/node-modules",
"../nativescript-core/references.d.ts",
"../nativescript-core/platforms"
]
}

View File

@@ -1,6 +1,6 @@
import { assert } from "chai";
import * as parser from "tns-core-modules/css";
import * as selector from "tns-core-modules/ui/styling/css-selector";
import * as parser from "@nativescript/core/css";
import * as selector from "@nativescript/core/ui/styling/css-selector";
describe("ui", () => {
describe("styling", () => {
@@ -22,12 +22,14 @@ describe("ui", () => {
let rulesAst = parse.stylesheet.rules.filter(n => n.type === "rule");
let rules = selector.fromAstNodes(rulesAst);
let map = new selector.SelectorsMap(rules);
return { rules, map };
}
function createOne(css: string, source: string = "css-selectors.ts@test"): selector.RuleSet {
let {rules} = create(css, source);
assert.equal(rules.length, 1);
return rules[0];
}
@@ -51,7 +53,7 @@ describe("ui", () => {
button { color: red; }
image { color: green; }
`);
let buttonQuerry = map.query({ cssType: "button" }).selectors;
assert.equal(buttonQuerry.length, 1);
assert.includeDeepMembers(buttonQuerry[0].ruleset.declarations, [
@@ -76,8 +78,8 @@ describe("ui", () => {
".class": (view) => view.cssClasses.has("class"),
":pseudo": (view) => view.cssPseudoClasses.has("pseudo"),
"[src1]": (view) => "src1" in view,
"[src2='src-value']": (view) => view['src2'] === 'src-value'
}
"[src2='src-value']": (view) => view["src2"] === "src-value"
};
let positivelyMatchingView = {
cssType: "type",
@@ -86,7 +88,7 @@ describe("ui", () => {
cssPseudoClasses: new Set(["pseudo"]),
"src1": "src",
"src2": "src-value"
}
};
let negativelyMatchingView = {
cssType: "nottype",
@@ -95,7 +97,7 @@ describe("ui", () => {
cssPseudoClasses: new Set(["notpseudo"]),
// Has no "src1"
"src2": "not-src-value"
}
};
it("simple selectors match", () => {
for (let sel in positiveMatches) {
@@ -191,7 +193,8 @@ describe("ui", () => {
}
}
}
}
};
assert.isTrue(sel.match(child));
});
@@ -215,7 +218,7 @@ describe("ui", () => {
toString
}
}
}
};
let match = map.query(button);
assert.equal(match.selectors.length, 1, "Expected match to have one selector.");

View File

@@ -1,5 +1,5 @@
import {assert} from "chai";
const xml = require("tns-core-modules/xml");
const xml = require("@nativescript/core/xml");
describe("angular xml parser", () => {
let last_element = null;

View File

@@ -1,5 +1,5 @@
import {assert} from "chai";
const xml = require("tns-core-modules/xml");
import { assert } from "chai";
const xml = require("@nativescript/core/xml");
describe("xml parser", () => {
let last_element = null;
@@ -27,7 +27,7 @@ describe("xml parser", () => {
assert.equal('TextField', last_element);
assert.equal('hello', last_attrs['text']);
});
it("resolves entities", () => {
parser.parse("<element>&lt;&gt;&quot;&amp;&apos;</element>");
assert.equal("<>\"&'", last_data);
@@ -44,8 +44,8 @@ describe("xml parser", () => {
});
it("resolves <> inside quotes", () => {
parser.parse("<element name='<&>' blah=\"b<a&>\"/>");
assert.equal("<&>", last_attrs.name);
assert.equal("b<a&>", last_attrs.blah);
parser.parse("<element name='<&>' blah=\"b<a&>\"/>");
assert.equal("<&>", last_attrs.name);
assert.equal("b<a&>", last_attrs.blah);
});
});