mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
Merge remote-tracking branch 'origin' into merge-release-in-master
This commit is contained in:
@@ -4,11 +4,12 @@ Development Workflow
|
||||
## Project Structure
|
||||
|
||||
The repository contains several packages and apps:
|
||||
- `tns-core-modules` - The core NativeScript TypeScript modules used to develop NativeScript apps.
|
||||
- `apps` - UI app used for manual testing and automation.
|
||||
- `e2e` - applications and *e2e* tests.
|
||||
- `tests` - Unit tests app for the `tns-core-modules`.
|
||||
- `tns-platform-declarations` - TypeScript definitions for Android and iOS native APIs.
|
||||
- `tns-core-modules` - The core NativeScript TypeScript modules used to develop NativeScript apps
|
||||
- `tns-core-modules-widgets` - The native widgets (Java and Objective-C) used by the core NativeScript modules
|
||||
- `e2e/ui-tests-app` - UI app used for manual testing and automation
|
||||
- `e2e` - applications and *e2e* tests
|
||||
- `tests` - Unit tests app for the `tns-core-modules`
|
||||
- `tns-platform-declarations` - TypeScript definitions for Android and iOS native APIs
|
||||
|
||||
Working with the repo is organized with npm scripts,
|
||||
go and read through the `scripts` section in the [package.json](./package.json).
|
||||
@@ -16,7 +17,7 @@ go and read through the `scripts` section in the [package.json](./package.json).
|
||||
Managing dependencies:
|
||||
- `tns-core-modules` depends on:
|
||||
- `tns-platform-declarations`
|
||||
- `apps` depends on:
|
||||
- `e2e/ui-tests-app` depends on:
|
||||
- `tns-platform-declarations`
|
||||
- `tns-core-modules`
|
||||
- `e2e` depends on:
|
||||
@@ -26,89 +27,60 @@ Managing dependencies:
|
||||
- `tns-core-modules`
|
||||
|
||||
> NOTE: `tns-core-modules` depends on `tns-core-modules-widgets`,
|
||||
this dependency contains native code and is rarely modified so for now it remains outside this repo.
|
||||
|
||||
## Initial Setup
|
||||
|
||||
Clone (or fork/clone) the repo:
|
||||
|
||||
```bash
|
||||
``` bash
|
||||
git clone https://github.com/NativeScript/NativeScript.git
|
||||
```
|
||||
|
||||
Install devDependencies:
|
||||
Install dependencies:
|
||||
|
||||
```bash
|
||||
``` bash
|
||||
npm install
|
||||
```
|
||||
|
||||
<!---
|
||||
## TypeScript
|
||||
|
||||
The following commands are commonly used to compile the `tns-core-modules`:
|
||||
```bash
|
||||
# Full tsc with type checking ~22.2s.
|
||||
tsc
|
||||
|
||||
# Fast tsc ~11.2s.
|
||||
tsc --skipLibCheck
|
||||
|
||||
# Fast watcher, ~4s. on save
|
||||
tsc --skipLibCheck -w
|
||||
```
|
||||
|
||||
NOTE: transpile `tns-core-modules` only.
|
||||
|
||||
The modules have `typescript` as a devDependency so you should also be able to use the locally installed TypeScript compiler from node_modules:
|
||||
|
||||
```bash
|
||||
./node_modules/.bin/tsc
|
||||
```
|
||||
|
||||
You can compile the TypeScript files in the `tns-core-modules` and `tns-platform-declarations` at once at the root of the repo:
|
||||
|
||||
```bash
|
||||
npm run tsc
|
||||
```
|
||||
--->
|
||||
|
||||
## Running Unit Tests
|
||||
|
||||
```
|
||||
cd ./tests
|
||||
tns run android| ios
|
||||
``` bash
|
||||
cd tests
|
||||
tns run android | ios
|
||||
```
|
||||
|
||||
## Running the Test App
|
||||
## Running the UI Test App
|
||||
|
||||
The test app is an ordinary NativeScript app that logs the test results as it go.
|
||||
The UI test app is an ordinary NativeScript app that logs the test results on the go.
|
||||
After the [initial setup](#initial-setup) you can run the tests with:
|
||||
|
||||
```
|
||||
# Make sure TypeScript is transpiled
|
||||
tsc
|
||||
``` bash
|
||||
cd e2e/ui-tests-app
|
||||
|
||||
# Run the Android app
|
||||
tns platform add android@next # NOTE: do not commit this change to package.json
|
||||
tns run android
|
||||
|
||||
# Run the iOS app
|
||||
tns platform add ios@next # NOTE: do not commit this change to package.json
|
||||
tns run ios
|
||||
|
||||
# Run the app
|
||||
tns run ios --path apps
|
||||
tns run android --path apps
|
||||
```
|
||||
|
||||
## Running Another App
|
||||
|
||||
The [initial setup](#initial-setup) will `npm-link` the `tns-core-modules` globally. You can use it in any local project:
|
||||
|
||||
1. Open the app, where you will use the module from the repository in the console.
|
||||
2. Add the `tns-core-modules` in the application via:
|
||||
```bash
|
||||
npm install --save <path to tns-core-modules>
|
||||
# Example: npm install --save ../NativeScript/tns-core-modules
|
||||
```
|
||||
3. Run the app
|
||||
```bash
|
||||
# Run once: Link tns-core-modules in your project
|
||||
npm link tns-core-modules
|
||||
|
||||
# Run the app
|
||||
tns run ios
|
||||
tns run android
|
||||
```
|
||||
|
||||
> Note: You still have to rebuild the TypeScript if you have made changes in the code of the core-modules.
|
||||
|
||||
|
||||
## Platform declarations
|
||||
To update the platform declarations (the ios.d.ts-es) you can run:
|
||||
|
||||
|
||||
@@ -54,16 +54,16 @@ Below is a common NativeScript architecture diagram. In more detail, read the [H
|
||||
The NativeScript framework consists of a number of components, all of which are open source and on GitHub. Here are the major ones:
|
||||
|
||||
- **[Cross-platform modules](//github.com/NativeScript/NativeScript/)**
|
||||
[](https://www.npmjs.com/package/tns-core-modules) [](https://waffle.io/NativeScript/NativeScript)
|
||||
[](https://www.npmjs.com/package/tns-core-modules)
|
||||
- This repo contains the [NativeScript cross-platform modules](http://docs.nativescript.org/core-concepts/modules), which abstract iOS and Android APIs into JavaScript APIs—e.g. `camera.takePicture()`. The modules are written in TypeScript.
|
||||
- **[iOS runtime](//github.com/NativeScript/ios-runtime/)**
|
||||
[](https://www.npmjs.com/package/tns-ios) [](https://waffle.io/NativeScript/ios-runtime)
|
||||
[](https://www.npmjs.com/package/tns-ios)
|
||||
- This repo contains the NativeScript iOS runtime—the code that hosts NativeScript iOS apps, and allows JavaScript code to be executed on iOS devices. The iOS runtime is written in a fun mix of C++, Objective-C, and more.
|
||||
- **[Android runtime](//github.com/NativeScript/android-runtime)**
|
||||
[](https://www.npmjs.com/package/tns-android) [](https://waffle.io/NativeScript/android-runtime)
|
||||
[](https://www.npmjs.com/package/tns-android)
|
||||
- This repo contains the NativeScript Android—the code that hosts NativeScript Android apps, and allows JavaScript code to be executed on Android devices. The Android runtime is written in a fun mix of C++ and Java.
|
||||
- **[CLI](//github.com/NativeScript/nativescript-cli)**
|
||||
[](https://www.npmjs.com/package/nativescript) [](https://waffle.io/NativeScript/nativescript-cli)
|
||||
[](https://www.npmjs.com/package/nativescript)
|
||||
- This repo contains the NativeScript command-line interface, which lets you create, build, and run apps using the NativeScript framework. The CLI is written in TypeScript.
|
||||
- **[Docs](//github.com/NativeScript/docs)**
|
||||
- This repo contains the NativeScript framework documentation, which is available at <http://docs.nativescript.org/>. The docs are written in Markdown.
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
"dev-tsc-tests": "npm run tsc -- -p tests",
|
||||
"dev-tsc-apps": "npm run tsc -- -p apps",
|
||||
"dev-tsc-e2e": "npm run tsc -- -p e2e",
|
||||
"dev-tsc-all": "npm run dev-tsc-tns-platform-declarations && npm run tsc && npm run dev-tsc-tests && npm run dev-tsc-apps && && npm run dev-tsc-e2e",
|
||||
"dev-tsc-all": "npm run dev-tsc-tns-platform-declarations && npm run tsc && npm run dev-tsc-tests && npm run dev-tsc-apps && npm run dev-tsc-e2e",
|
||||
"dev-link-tns-core-modules-widgets": "(cd tns-core-modules-widgets/dist/package && npm link) && (cd tns-core-modules && npm i ../tns-core-modules-widgets/dist/package --save)",
|
||||
"dev-declarations": "rm -rf tns-platform-declarations/ios/objc* && TNS_TYPESCRIPT_DECLARATIONS_PATH=$PWD/tns-platform-declarations/ios/objc tns build ios --path tests",
|
||||
"test": "npm run test-android && npm run test-ios",
|
||||
|
||||
@@ -41,7 +41,7 @@ export function testAndroidApplicationInitialized() {
|
||||
TKUnit.assert(app.android, "Android application not initialized.");
|
||||
TKUnit.assert(app.android.context, "Android context not initialized.");
|
||||
TKUnit.assert(app.android.foregroundActivity, "Android foregroundActivity not initialized.");
|
||||
TKUnit.assert(app.android.foregroundActivity.isNativeScriptActivity, "Andorid foregroundActivity.isNativeScriptActivity is false.");
|
||||
TKUnit.assert(app.android.foregroundActivity.isNativeScriptActivity, "Android foregroundActivity.isNativeScriptActivity is false.");
|
||||
TKUnit.assert(app.android.startActivity, "Android startActivity not initialized.");
|
||||
TKUnit.assert(app.android.nativeApp, "Android nativeApp not initialized.");
|
||||
TKUnit.assert(app.android.orientation, "Android orientation not initialized.");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tns-core-modules-widgets",
|
||||
"version": "6.1.0",
|
||||
"version": "6.2.0",
|
||||
"description": "Native widgets used in the NativeScript framework.",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
@@ -17,8 +17,8 @@
|
||||
"homepage": "https://github.com/NativeScript/NativeScript/blob/master/tns-core-modules-widgets#readme",
|
||||
"nativescript": {
|
||||
"platforms": {
|
||||
"ios": "5.0.0",
|
||||
"android": "5.0.0"
|
||||
"ios": "6.0.0",
|
||||
"android": "6.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,10 +85,13 @@ export function clear(): void {
|
||||
}
|
||||
|
||||
export function flush(): boolean {
|
||||
ensureSharedPreferences();
|
||||
|
||||
return sharedPreferences.edit().commit();
|
||||
}
|
||||
|
||||
export function getAllKeys(): Array<string> {
|
||||
ensureSharedPreferences();
|
||||
const mappedPreferences = sharedPreferences.getAll();
|
||||
const iterator = mappedPreferences.keySet().iterator();
|
||||
const result = [];
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as definition from ".";
|
||||
import * as definition from ".";
|
||||
import * as types from "../utils/types";
|
||||
import * as knownColors from "./known-colors";
|
||||
import { convertHSLToRGBColor } from "tns-core-modules/css/parser";
|
||||
|
||||
const SHARP = "#";
|
||||
const HEX_REGEX = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)|(^#[0-9A-F]{8}$)/i;
|
||||
@@ -18,6 +19,8 @@ export class Color implements definition.Color {
|
||||
if (types.isString(arg)) {
|
||||
if (isRgbOrRgba(arg)) {
|
||||
this._argb = argbFromRgbOrRgba(arg);
|
||||
} else if (isHslOrHsla(arg)) {
|
||||
this._argb = argbFromHslOrHsla(arg);
|
||||
} else if (knownColors.isKnownName(arg)) {
|
||||
// The parameter is a known color name
|
||||
const hex = knownColors.getKnownColor(arg);
|
||||
@@ -127,7 +130,7 @@ export class Color implements definition.Color {
|
||||
return true;
|
||||
}
|
||||
|
||||
return HEX_REGEX.test(value) || isRgbOrRgba(value);
|
||||
return HEX_REGEX.test(value) || isRgbOrRgba(value) || isHslOrHsla(value);
|
||||
}
|
||||
|
||||
private _componentToHex(component: number): string {
|
||||
@@ -162,33 +165,58 @@ function isRgbOrRgba(value: string): boolean {
|
||||
return (toLower.indexOf("rgb(") === 0 || toLower.indexOf("rgba(") === 0) && toLower.indexOf(")") === (toLower.length - 1);
|
||||
}
|
||||
|
||||
function argbFromRgbOrRgba(value: string): number {
|
||||
function isHslOrHsla(value: string): boolean {
|
||||
const toLower = value.toLowerCase();
|
||||
const parts = toLower.replace("rgba(", "").replace("rgb(", "").replace(")", "").trim().split(",");
|
||||
|
||||
let r = 255;
|
||||
let g = 255;
|
||||
let b = 255;
|
||||
return (toLower.indexOf("hsl(") === 0 || toLower.indexOf("hsla(") === 0) && toLower.indexOf(")") === (toLower.length - 1);
|
||||
}
|
||||
|
||||
function parseColorWithAlpha(value: string): any {
|
||||
const toLower = value.toLowerCase();
|
||||
const parts = toLower.replace(/(rgb|hsl)a?\(/, "")
|
||||
.replace(")", "")
|
||||
.trim().split(",");
|
||||
|
||||
let f = 255;
|
||||
let s = 255;
|
||||
let t = 255;
|
||||
let a = 255;
|
||||
|
||||
if (parts[0]) {
|
||||
r = parseInt(parts[0].trim());
|
||||
f = parseInt(parts[0].trim());
|
||||
}
|
||||
|
||||
if (parts[1]) {
|
||||
g = parseInt(parts[1].trim());
|
||||
s = parseInt(parts[1].trim());
|
||||
}
|
||||
|
||||
if (parts[2]) {
|
||||
b = parseInt(parts[2].trim());
|
||||
t = parseInt(parts[2].trim());
|
||||
}
|
||||
|
||||
if (parts[3]) {
|
||||
a = Math.round(parseFloat(parts[3].trim()) * 255);
|
||||
}
|
||||
|
||||
return { f, s, t, a };
|
||||
}
|
||||
|
||||
function argbFromRgbOrRgba(value: string): number {
|
||||
const { f: r, s: g, t: b, a } = parseColorWithAlpha(value);
|
||||
|
||||
return (a & 0xFF) * 0x01000000
|
||||
+ (r & 0xFF) * 0x00010000
|
||||
+ (g & 0xFF) * 0x00000100
|
||||
+ (b & 0xFF) * 0x00000001;
|
||||
+ (b & 0xFF);
|
||||
}
|
||||
|
||||
function argbFromHslOrHsla(value: string): number {
|
||||
const { f: h, s: s, t: l, a } = parseColorWithAlpha(value);
|
||||
|
||||
const { r, g, b } = convertHSLToRGBColor(h, s, l);
|
||||
|
||||
return (a & 0xFF) * 0x01000000
|
||||
+ (r & 0xFF) * 0x00010000
|
||||
+ (g & 0xFF) * 0x00000100
|
||||
+ (b & 0xFF);
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ export function parseHexColor(text: string, start: number = 0): Parsed<ARGB> {
|
||||
|
||||
function rgbaToArgbNumber(r: number, g: number, b: number, a: number = 1): number | undefined {
|
||||
if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255 && a >= 0 && a <= 1) {
|
||||
return (Math.round(a * 0xFF) * 0x01000000) + (r * 0x010000) + (g * 0x000100) + (b * 0x000001);
|
||||
return (Math.round(a * 0xFF) * 0x01000000) + (r * 0x010000) + (g * 0x000100) + b;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@@ -116,6 +116,67 @@ export function parseRGBAColor(text: string, start: number = 0): Parsed<ARGB> {
|
||||
return { start, end, value };
|
||||
}
|
||||
|
||||
export function convertHSLToRGBColor(hue: number, saturation: number, lightness: number): { r: number; g: number; b: number; } {
|
||||
// Per formula it will be easier if hue is divided to 60° and saturation to 100 beforehand
|
||||
// https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_RGB
|
||||
hue /= 60;
|
||||
lightness /= 100;
|
||||
|
||||
let chroma = (1 - Math.abs(2 * lightness - 1)) * saturation / 100,
|
||||
X = chroma * (1 - Math.abs(hue % 2 - 1)),
|
||||
// Add lightness match to all RGB components beforehand
|
||||
{ m: r, m: g, m: b } = { m: lightness - chroma / 2 };
|
||||
|
||||
if (0 <= hue && hue < 1) { r += chroma; g += X; }
|
||||
else if (hue < 2) { r += X; g += chroma; }
|
||||
else if (hue < 3) { g += chroma; b += X; }
|
||||
else if (hue < 4) { g += X; b += chroma; }
|
||||
else if (hue < 5) { r += X; b += chroma; }
|
||||
else if (hue < 6) { r += chroma; b += X; }
|
||||
|
||||
return {
|
||||
r: Math.round(r * 0xFF),
|
||||
g: Math.round(g * 0xFF),
|
||||
b: Math.round(b * 0xFF)
|
||||
};
|
||||
}
|
||||
|
||||
function hslaToArgbNumber(h: number, s: number, l: number, a: number = 1): number | undefined {
|
||||
let { r, g, b } = convertHSLToRGBColor(h, s, l);
|
||||
|
||||
if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255 && a >= 0 && a <= 1) {
|
||||
return (Math.round(a * 0xFF) * 0x01000000) + (r * 0x010000) + (g * 0x000100) + b;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const hslColorRegEx = /\s*(hsl\(\s*([\d.]*)\s*,\s*([\d.]*)%\s*,\s*([\d.]*)%\s*\))/gy;
|
||||
export function parseHSLColor(text: string, start: number = 0): Parsed<ARGB> {
|
||||
hslColorRegEx.lastIndex = start;
|
||||
const result = hslColorRegEx.exec(text);
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
const end = hslColorRegEx.lastIndex;
|
||||
const value = result[1] && hslaToArgbNumber(parseFloat(result[2]), parseFloat(result[3]), parseFloat(result[4]));
|
||||
|
||||
return { start, end, value };
|
||||
}
|
||||
|
||||
const hslaColorRegEx = /\s*(hsla\(\s*([\d.]*)\s*,\s*([\d.]*)%\s*,\s*([\d.]*)%\s*,\s*([01]?\.?\d*)\s*\))/gy;
|
||||
export function parseHSLAColor(text: string, start: number = 0): Parsed<ARGB> {
|
||||
hslaColorRegEx.lastIndex = start;
|
||||
const result = hslaColorRegEx.exec(text);
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
const end = hslaColorRegEx.lastIndex;
|
||||
const value = hslaToArgbNumber(parseFloat(result[2]), parseFloat(result[3]), parseFloat(result[4]), parseFloat(result[5]));
|
||||
|
||||
return { start, end, value };
|
||||
}
|
||||
|
||||
export enum colors {
|
||||
transparent = 0x00000000,
|
||||
aliceblue = 0xFFF0F8FF,
|
||||
@@ -280,7 +341,12 @@ export function parseColorKeyword(value, start: number, keyword = parseKeyword(v
|
||||
}
|
||||
|
||||
export function parseColor(value: string, start: number = 0, keyword = parseKeyword(value, start)): Parsed<ARGB> {
|
||||
return parseHexColor(value, start) || parseColorKeyword(value, start, keyword) || parseRGBColor(value, start) || parseRGBAColor(value, start);
|
||||
return parseHexColor(value, start) ||
|
||||
parseColorKeyword(value, start, keyword) ||
|
||||
parseRGBColor(value, start) ||
|
||||
parseRGBAColor(value, start) ||
|
||||
parseHSLColor(value, start) ||
|
||||
parseHSLAColor(value, start);
|
||||
}
|
||||
|
||||
const keywordRegEx = /\s*([a-z][\w\-]*)\s*/giy;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "tns-core-modules",
|
||||
"description": "Telerik NativeScript Core Modules",
|
||||
"version": "6.1.1",
|
||||
"version": "6.2.0",
|
||||
"homepage": "https://www.nativescript.org",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -39,8 +39,8 @@
|
||||
},
|
||||
"nativescript": {
|
||||
"platforms": {
|
||||
"ios": "5.0.0",
|
||||
"android": "5.0.0"
|
||||
"ios": "6.0.0",
|
||||
"android": "6.0.0"
|
||||
}
|
||||
},
|
||||
"snapshot": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tns-platform-declarations",
|
||||
"version": "6.1.1",
|
||||
"version": "6.2.0",
|
||||
"description": "Platform-specific TypeScript declarations for NativeScript for accessing native objects",
|
||||
"main": "",
|
||||
"scripts": {
|
||||
|
||||
@@ -56,6 +56,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 });
|
||||
});
|
||||
@@ -175,11 +177,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]]});
|
||||
|
||||
Reference in New Issue
Block a user