Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] feat: support harmony #2261

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/driver-harmony/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## Changelog

### v1.0.0
28 changes: 28 additions & 0 deletions packages/driver-harmony/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# driver-harmony

> Harmony OS driver for Rax.

## Install

```bash
$ npm install --save driver-harmony
```

## Use

```jsx
import {createElement, render} from 'rax';
import DriverHarmony from 'driver-harmony';

function Example() {
return (
<div>
<image width="560" height="560" src="https://img.alicdn.com/tps/TB1z.55OFXXXXcLXXXXXXXXXXXX-560-560.jpg" />
</div>
);
}

render(<Example />, null, {
driver: DriverHarmony
});
```
22 changes: 22 additions & 0 deletions packages/driver-harmony/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "driver-harmony",
"version": "1.0.0-beta.0",
"description": "Harmony driver for Rax",
"license": "BSD-3-Clause",
"main": "lib/index.js",
"module": "es/index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/alibaba/rax.git"
},
"bugs": {
"url": "https://github.com/alibaba/rax/issues"
},
"homepage": "https://github.com/alibaba/rax#readme",
"dependencies": {
"style-unit": "^3.0.0"
},
"devDependencies": {
"rax": "^1.0.0"
}
}
20 changes: 20 additions & 0 deletions packages/driver-harmony/src/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Driver spec: https://github.com/alibaba/rax/blob/master/docs/en-US/driver-spec.md
declare namespace Driver {
function createBody(): void;
function createEmpty(component: any): void;
function createText(): void;
function updateText(node: any, text: any)
function createElement(type: any, props: any, component: any)
function appendChild(node: any, parent: any)
function removeChild(node: any, parent: any)
function replaceChild(newChild: any, oldChild: any, parent: any)
function insertAfter(node: any, after: any, parent: any)
function insertBefore(node: any, before: any, parent: any)
function addEventListener(node: any, eventName: any, eventHandler: any)
function removeEventListener(node: any, eventName: any, eventHandler: any)
function setAttribute(node: any, propKey: any, propValue: any)
function removeAttribute(node: any, propKey: any)
function setStyle(node: any, styleObject: any)
}

export default Driver;
200 changes: 200 additions & 0 deletions packages/driver-harmony/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
import { convertUnit, setTargetPlatform } from 'style-unit';

/**
* Server driver
**/
const ID = 'id';
const STYLE = 'style';
const CHILDREN = 'children';
const EVENT_PREFIX_REGEXP = /^on[A-Z]/;
const REF = 'ref';

const TEXT = 'text';
const EMPTY = '';

setTargetPlatform('harmony');

const Driver = {
// Internal state
nodeMaps: {},

getElementById(id) {
return this.nodeMaps[id];
},

createBody() {
return document.body;
},

createComment() {
// Use block element as comment node, because harmony not support append comment node
const node = this.createElement('block');
node.__type = 'comment';
return node;
},

createEmpty() {
return this.createComment(EMPTY);
},

createText(text) {
// Use comment node type mock text node
const node = this.createComment(EMPTY);
node.value = text;
return node;
},

updateText(node, text) {
node.value = text;
this.updateTextValue(node.parentNode);
},

updateTextValue(node) {
const value = node.children.map(function(child) {
// Comment node type
return child.__type === 'comment' ? child.value : EMPTY;
}).join(EMPTY);

node.setAttr('value', value);
},

createElement(type, props) {
props = props || {};
const style = {};
const originStyle = props.style;
if (originStyle) {
for (let prop in originStyle) {
style[prop] = convertUnit(originStyle[prop], prop);
}
}

const node = document.createElement(type, {
style,
});

this.setNativeProps(node, props, true);

return node;
},

appendChild(node, parent) {
parent.appendChild(node);

if (parent.type === TEXT) {
this.updateTextValue(parent);
}
},

aceAppendChildren(node, parent) {
this.aceAppendChild(node, parent);
},

removeChild(node, parent) {
parent = parent || node.parentNode;
let id = node.attr && node.attr[ID];
if (id != null) {
this.nodeMaps[id] = null;
}

parent.removeChild(node);

if (parent.type === TEXT) {
this.updateTextValue(parent);
}
},

replaceChild(newChild, oldChild, parent) {
parent = parent || oldChild.parentNode;

let previousSibling;
let nextSibling;

previousSibling = oldChild.previousSibling;
nextSibling = oldChild.nextSibling;
this.removeChild(oldChild, parent);

if (previousSibling) {
this.insertAfter(newChild, previousSibling, parent);
} else if (nextSibling) {
this.insertBefore(newChild, nextSibling, parent);
} else {
this.appendChild(newChild, parent);
}
},

insertAfter(node, after, parent) {
parent = parent || after.parentNode;
parent.insertAfter(node, after);


if (parent.type === TEXT) {
this.updateTextValue(parent);
}
},

insertBefore(node, before, parent) {
parent = parent || before.parentNode;
parent.insertBefore(node, before);

if (parent.type === TEXT) {
this.updateTextValue(parent);
}
},

addEventListener(node, eventName, eventHandler) {
node.addEvent(eventName, eventHandler);
},

removeEventListener(node, eventName, eventHandler) {
node.removeEvent(eventName, eventHandler);
},

removeAttribute(node, propKey, propValue) {
if (propKey === ID) {
this.nodeMaps[propValue] = null;
}
return node.setAttr(propKey, undefined, false);
},

setAttribute(node, propKey, propValue) {
if (propKey === ID) {
this.nodeMaps[propValue] = node;
}
// ref is harmony node internal key
if (propKey === REF) return;
return node.setAttr(propKey, propValue);
},

setStyle(node, style) {
for (let prop in style) {
// Translate `rpx` to weex `px`
style[prop] = convertUnit(style[prop], prop);
}
node.setStyles(style);
},

setNativeProps(node, props, shouldIgnoreStyleProp) {
for (let prop in props) {
let value = props[prop];
if (prop === CHILDREN) {
continue;
}

if (value != null) {
if (prop === STYLE) {
if (shouldIgnoreStyleProp) {
continue;
}
this.setStyle(node, value);
} else if (EVENT_PREFIX_REGEXP.test(prop)) {
let eventName = prop.slice(2).toLowerCase();
this.addEventListener(node, eventName, value);
} else {
this.setAttribute(node, prop, value);
}
}
}
}
};

export default Driver;
4 changes: 3 additions & 1 deletion packages/driver-universal/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "driver-universal",
"version": "3.3.1",
"version": "3.4.0-beta.1",
"description": "Driver for Universal App.",
"license": "BSD-3-Clause",
"main": "lib/index.js",
Expand All @@ -15,6 +15,7 @@
"bytedance-microapp": "./es/miniapp.js",
"baidu-smartprogram": "./es/miniapp.js",
"kuaishou-miniprogram": "./es/miniapp.js",
"harmony": "./es/harmony.js",
"default": "./es/index.js"
},
"./*": "./*"
Expand All @@ -36,6 +37,7 @@
"driver-kraken": "^0.2.0",
"driver-miniapp": "^0.1.0",
"driver-weex": "^2.0.0",
"driver-harmony": "^1.0.0-beta.0",
"universal-env": "^3.0.0"
}
}
3 changes: 3 additions & 0 deletions packages/driver-universal/src/harmony.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import HarmonyDriver from 'driver-harmony';

export default HarmonyDriver;
4 changes: 3 additions & 1 deletion packages/driver-universal/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import {
} from 'universal-env';

let currentDriver;
if (isWeex) {
if (typeof ace !== 'undefined') {
currentDriver = require('./harmony').default;
} else if (isWeex) {
currentDriver = require('./weex').default;
} else if (isWeb) {
currentDriver = require('./web').default;
Expand Down
2 changes: 1 addition & 1 deletion packages/style-unit/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export function calcRpx(str) {
// In Web convert rpx to 'vw', same as driver-dom and driver-universal
// '375rpx' => '50vw'
return str.replace(RPX_REG, decimalVWTransformer);
} else if (targetPlatform === 'weex') {
} else if (targetPlatform === 'weex' || targetPlatform === 'harmony') {
// In Weex convert rpx to 'px'
// '375rpx' => 375 * px
return str.replace(RPX_REG, decimalPixelTransformer);
Expand Down
4 changes: 4 additions & 0 deletions scripts/dist-core.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ buildCorePackages({
packageName: 'driver-weex',
name: 'DriverKraken'
});
buildCorePackages({
packageName: 'driver-harmony',
name: 'DriverHarmony'
});

// Build rax compat react version to rax/lib/compat/index.js
// It needs external ../../index, which won't bundle rax into lib/compat/index.js
Expand Down