Merge branch 'h5_master' into combine
This commit is contained in:
commit
c951ce39a7
5
doric-h5/.gitignore
vendored
Normal file
5
doric-h5/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
node_modules/
|
||||||
|
build/
|
||||||
|
bundle/
|
||||||
|
demo/
|
||||||
|
.DS_Store
|
201
doric-h5/LICENCE
Normal file
201
doric-h5/LICENCE
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] [Doric.Pub]
|
||||||
|
|
||||||
|
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.
|
140
doric-h5/dist/Counter.js
vendored
Normal file
140
doric-h5/dist/Counter.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4665
doric-h5/dist/index.js
vendored
Normal file
4665
doric-h5/dist/index.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
doric-h5/dist/index.js.map
vendored
Normal file
1
doric-h5/dist/index.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
37
doric-h5/index.html
Normal file
37
doric-h5/index.html
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
|
<title>Doric Playground</title>
|
||||||
|
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<noscript>
|
||||||
|
<strong>We're sorry but This doesn't work properly without JavaScript enabled. Please enable it to
|
||||||
|
continue.</strong>
|
||||||
|
</noscript>
|
||||||
|
<div id="app">
|
||||||
|
<doric-div src="./dist/Counter.js" alias="test">
|
||||||
|
</doric-div>
|
||||||
|
</div>
|
||||||
|
<script type="text/javascript" src="./dist/index.js"></script>
|
||||||
|
</body>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
#app {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</html>
|
3
doric-h5/index.ts
Normal file
3
doric-h5/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { DoricElement } from './src/DoricElement'
|
||||||
|
|
||||||
|
window.customElements.define('doric-div', DoricElement);
|
174
doric-h5/package-lock.json
generated
Normal file
174
doric-h5/package-lock.json
generated
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
{
|
||||||
|
"name": "doric-h5",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": {
|
||||||
|
"version": "12.12.20",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.20.tgz",
|
||||||
|
"integrity": "sha512-VAe+DiwpnC/g448uN+/3gRl4th0BTdrR9gSLIOHA+SUQskaYZQDOHG7xmjiE7JUhjbXnbXytf6Ih+/pA6CtMFQ=="
|
||||||
|
},
|
||||||
|
"@types/resolve": {
|
||||||
|
"version": "0.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz",
|
||||||
|
"integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==",
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"axios": {
|
||||||
|
"version": "0.19.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz",
|
||||||
|
"integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==",
|
||||||
|
"requires": {
|
||||||
|
"follow-redirects": "1.5.10",
|
||||||
|
"is-buffer": "^2.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"builtin-modules": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw=="
|
||||||
|
},
|
||||||
|
"debug": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"doric": {
|
||||||
|
"version": "file:../doric/doric-js",
|
||||||
|
"requires": {
|
||||||
|
"@types/ws": "^6.0.4",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rollup": "^1.27.12",
|
||||||
|
"rollup-plugin-node-resolve": "^5.2.0",
|
||||||
|
"tslib": "^1.10.0",
|
||||||
|
"typescript": "^3.7.3",
|
||||||
|
"ws": "^7.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"estree-walker": {
|
||||||
|
"version": "0.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
|
||||||
|
"integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w=="
|
||||||
|
},
|
||||||
|
"follow-redirects": {
|
||||||
|
"version": "1.5.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
|
||||||
|
"integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
|
||||||
|
"requires": {
|
||||||
|
"debug": "=3.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"is-buffer": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A=="
|
||||||
|
},
|
||||||
|
"is-module": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE="
|
||||||
|
},
|
||||||
|
"is-reference": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-uJA/CDPO3Tao3GTrxYn6AwkM4nUPJiGGYu5+cB8qbC7WGFlrKZbiRo7SFKxUAEpFUfiHofWCXBUNhvYJMh+6zw==",
|
||||||
|
"requires": {
|
||||||
|
"@types/estree": "0.0.39"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/estree": {
|
||||||
|
"version": "0.0.39",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
|
||||||
|
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"magic-string": {
|
||||||
|
"version": "0.25.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.4.tgz",
|
||||||
|
"integrity": "sha512-oycWO9nEVAP2RVPbIoDoA4Y7LFIJ3xRYov93gAyJhZkET1tNuB0u7uWkZS2LpBWTJUWnmau/To8ECWRC+jKNfw==",
|
||||||
|
"requires": {
|
||||||
|
"sourcemap-codec": "^1.4.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||||
|
},
|
||||||
|
"path-parse": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
|
||||||
|
},
|
||||||
|
"resolve": {
|
||||||
|
"version": "1.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.0.tgz",
|
||||||
|
"integrity": "sha512-uviWSi5N67j3t3UKFxej1loCH0VZn5XuqdNxoLShPcYPw6cUZn74K1VRj+9myynRX03bxIBEkwlkob/ujLsJVw==",
|
||||||
|
"requires": {
|
||||||
|
"path-parse": "^1.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rollup-plugin-commonjs": {
|
||||||
|
"version": "10.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz",
|
||||||
|
"integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==",
|
||||||
|
"requires": {
|
||||||
|
"estree-walker": "^0.6.1",
|
||||||
|
"is-reference": "^1.1.2",
|
||||||
|
"magic-string": "^0.25.2",
|
||||||
|
"resolve": "^1.11.0",
|
||||||
|
"rollup-pluginutils": "^2.8.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rollup-plugin-json": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow==",
|
||||||
|
"requires": {
|
||||||
|
"rollup-pluginutils": "^2.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rollup-plugin-node-resolve": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==",
|
||||||
|
"requires": {
|
||||||
|
"@types/resolve": "0.0.8",
|
||||||
|
"builtin-modules": "^3.1.0",
|
||||||
|
"is-module": "^1.0.0",
|
||||||
|
"resolve": "^1.11.1",
|
||||||
|
"rollup-pluginutils": "^2.8.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rollup-pluginutils": {
|
||||||
|
"version": "2.8.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
|
||||||
|
"integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==",
|
||||||
|
"requires": {
|
||||||
|
"estree-walker": "^0.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourcemap-codec": {
|
||||||
|
"version": "1.4.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz",
|
||||||
|
"integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg=="
|
||||||
|
},
|
||||||
|
"tsc": {
|
||||||
|
"version": "1.20150623.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tsc/-/tsc-1.20150623.0.tgz",
|
||||||
|
"integrity": "sha1-Trw8d04WkUjLx2inNCUz8ILHpuU="
|
||||||
|
},
|
||||||
|
"typescript": {
|
||||||
|
"version": "3.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz",
|
||||||
|
"integrity": "sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
doric-h5/package.json
Normal file
29
doric-h5/package.json
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"name": "doric-h5",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Doric library for html",
|
||||||
|
"main": "build/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"build": "tsc -p .&& rollup -c"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/doric-pub/doric-h5.git"
|
||||||
|
},
|
||||||
|
"author": "pengfeizhou",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/doric-pub/doric-h5/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/doric-pub/doric-h5#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^0.19.0",
|
||||||
|
"doric": "file:../doric/doric-js",
|
||||||
|
"rollup-plugin-commonjs": "^10.1.0",
|
||||||
|
"rollup-plugin-json": "^4.0.0",
|
||||||
|
"rollup-plugin-node-resolve": "^5.2.0",
|
||||||
|
"tsc": "^1.20150623.0",
|
||||||
|
"typescript": "^3.7.3"
|
||||||
|
}
|
||||||
|
}
|
48
doric-h5/rollup.config.js
Normal file
48
doric-h5/rollup.config.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import resolve from 'rollup-plugin-node-resolve'
|
||||||
|
import commonjs from 'rollup-plugin-commonjs'
|
||||||
|
import jsonPlugin from 'rollup-plugin-json'
|
||||||
|
import fs from 'fs'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
const sandboxBundle = fs.readFileSync(path.resolve("./node_modules/doric/bundle/doric-sandbox.js"), 'utf-8')
|
||||||
|
|
||||||
|
const doricLibBundle = fs.readFileSync(path.resolve("./node_modules/doric/bundle/doric-lib.js"), 'utf-8')
|
||||||
|
|
||||||
|
const builtinScript = `
|
||||||
|
/**++++++++SandBox++++++++*/
|
||||||
|
${sandboxBundle}
|
||||||
|
/**--------SandBox--------*/
|
||||||
|
|
||||||
|
/**++++++++Lib++++++++*/
|
||||||
|
Reflect.apply(doric.jsRegisterModule,this,["doric",Reflect.apply(function(__module){(function(module,exports,require){
|
||||||
|
${doricLibBundle}
|
||||||
|
})(__module,__module.exports,doric.__require__);
|
||||||
|
return __module.exports;
|
||||||
|
},this,[{exports:{}}])]);
|
||||||
|
/**--------Lib--------*/
|
||||||
|
`
|
||||||
|
|
||||||
|
export default {
|
||||||
|
input: `build/index.js`,
|
||||||
|
output: {
|
||||||
|
format: "iife",
|
||||||
|
name: "index",
|
||||||
|
file: `dist/index.js`,
|
||||||
|
sourcemap: true,
|
||||||
|
banner: builtinScript,
|
||||||
|
globals: {
|
||||||
|
doric: "doric_lib",
|
||||||
|
'doric/src/runtime/sandbox': 'doric',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
resolve({ mainFields: ["jsnext"] }),
|
||||||
|
commonjs(),
|
||||||
|
jsonPlugin(),
|
||||||
|
],
|
||||||
|
external: ['axios', 'reflect-metadata', 'doric'],
|
||||||
|
onwarn: function (warning) {
|
||||||
|
if (warning.code === 'THIS_IS_UNDEFINED') { return; }
|
||||||
|
console.warn(warning.message);
|
||||||
|
},
|
||||||
|
}
|
46
doric-h5/src/DoricContext.ts
Normal file
46
doric-h5/src/DoricContext.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { jsObtainContext, jsCallEntityMethod } from 'doric/src/runtime/sandbox'
|
||||||
|
import { Panel } from 'doric'
|
||||||
|
import { DoricPlugin } from "./DoricPlugin"
|
||||||
|
import { createContext } from "./DoricDriver"
|
||||||
|
import { DoricStackNode } from './shader/DoricStackNode'
|
||||||
|
const doricContexts: Map<string, DoricContext> = new Map
|
||||||
|
|
||||||
|
let __contextId__ = 0
|
||||||
|
function getContextId() {
|
||||||
|
return `context_${__contextId__++}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDoricContext(contextId: string) {
|
||||||
|
return doricContexts.get(contextId)
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DoricContext {
|
||||||
|
contextId = getContextId()
|
||||||
|
pluginInstances: Map<string, DoricPlugin> = new Map
|
||||||
|
rootNode: DoricStackNode
|
||||||
|
constructor(content: string) {
|
||||||
|
createContext(this.contextId, content)
|
||||||
|
doricContexts.set(this.contextId, this)
|
||||||
|
this.rootNode = new DoricStackNode(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
get panel() {
|
||||||
|
return jsObtainContext(this.contextId)?.entity as Panel
|
||||||
|
}
|
||||||
|
|
||||||
|
invokeEntityMethod(method: string, ...otherArgs: any) {
|
||||||
|
const argumentsList: any = [this.contextId]
|
||||||
|
for (let i = 0; i < arguments.length; i++) {
|
||||||
|
argumentsList.push(arguments[i])
|
||||||
|
}
|
||||||
|
Reflect.apply(jsCallEntityMethod, this.panel, argumentsList)
|
||||||
|
}
|
||||||
|
|
||||||
|
init(frame: {
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
}, extra?: object) {
|
||||||
|
this.invokeEntityMethod("__init__", frame, extra ? JSON.stringify(extra) : undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
137
doric-h5/src/DoricDriver.ts
Normal file
137
doric-h5/src/DoricDriver.ts
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
import { jsCallResolve, jsCallReject, jsCallbackTimer } from 'doric/src/runtime/sandbox'
|
||||||
|
import { acquireJSBundle, acquirePlugin } from './DoricRegistry'
|
||||||
|
import { getDoricContext } from './DoricContext'
|
||||||
|
import { DoricPlugin } from './DoricPlugin'
|
||||||
|
|
||||||
|
let __scriptId__ = 0
|
||||||
|
function getScriptId() {
|
||||||
|
return `script_${__scriptId__++}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const originSetTimeout = window.setTimeout
|
||||||
|
const originClearTimeout = window.clearTimeout
|
||||||
|
const originSetInterval = window.setInterval
|
||||||
|
const originClearInterval = window.clearInterval
|
||||||
|
|
||||||
|
const timers: Map<number, { handleId: number, repeat: boolean }> = new Map
|
||||||
|
|
||||||
|
export function injectGlobalObject(name: string, value: any) {
|
||||||
|
Reflect.set(window, name, value, window)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loadJS(script: string) {
|
||||||
|
const scriptElement = document.createElement('script')
|
||||||
|
scriptElement.text = script
|
||||||
|
scriptElement.id = getScriptId()
|
||||||
|
document.body.appendChild(scriptElement)
|
||||||
|
}
|
||||||
|
|
||||||
|
function packageModuleScript(name: string, content: string) {
|
||||||
|
return `Reflect.apply(doric.jsRegisterModule,this,[${name},Reflect.apply(function(__module){(function(module,exports,require,setTimeout,setInterval,clearTimeout,clearInterval){
|
||||||
|
${content}
|
||||||
|
})(__module,__module.exports,doric.__require__,doricSetTimeout,doricSetInterval,doricClearTimeout,doricClearInterval);
|
||||||
|
return __module.exports;},this,[{exports:{}}])])`
|
||||||
|
}
|
||||||
|
|
||||||
|
function packageCreateContext(contextId: string, content: string) {
|
||||||
|
return `Reflect.apply(function(doric,context,Entry,require,exports,setTimeout,setInterval,clearTimeout,clearInterval){
|
||||||
|
${content}
|
||||||
|
},doric.jsObtainContext("${contextId}"),[undefined,doric.jsObtainContext("${contextId}"),doric.jsObtainEntry("${contextId}"),doric.__require__,{},doricSetTimeout,doricSetInterval,doricClearTimeout,doricClearInterval])`
|
||||||
|
}
|
||||||
|
|
||||||
|
function initDoric() {
|
||||||
|
injectGlobalObject("nativeEmpty", () => undefined)
|
||||||
|
|
||||||
|
injectGlobalObject('nativeLog', (type: 'd' | 'w' | 'e', message: string) => {
|
||||||
|
switch (type) {
|
||||||
|
case 'd':
|
||||||
|
console.log(message)
|
||||||
|
break
|
||||||
|
case 'w':
|
||||||
|
console.warn(message)
|
||||||
|
break
|
||||||
|
case 'e':
|
||||||
|
console.error(message)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
injectGlobalObject('nativeRequire', (moduleName: string) => {
|
||||||
|
const bundle = acquireJSBundle(moduleName)
|
||||||
|
if (bundle === undefined || bundle.length === 0) {
|
||||||
|
console.log(`Cannot require JS Bundle :${moduleName}`)
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
loadJS(packageModuleScript(moduleName, packageModuleScript(name, bundle)))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
injectGlobalObject('nativeBridge', (contextId: string, namespace: string, method: string, callbackId: string, args?: any) => {
|
||||||
|
const pluginClass = acquirePlugin(namespace)
|
||||||
|
const doricContext = getDoricContext(contextId)
|
||||||
|
if (pluginClass === undefined) {
|
||||||
|
console.error(`Cannot find Plugin:${namespace}`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (doricContext === undefined) {
|
||||||
|
console.error(`Cannot find Doric Context:${contextId}`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
let plugin = doricContext.pluginInstances.get(namespace)
|
||||||
|
if (plugin === undefined) {
|
||||||
|
plugin = new pluginClass(doricContext) as DoricPlugin
|
||||||
|
doricContext.pluginInstances.set(namespace, plugin)
|
||||||
|
}
|
||||||
|
if (!Reflect.has(plugin, method)) {
|
||||||
|
console.error(`Cannot find Method:${method} in plugin ${namespace}`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const pluginMethod = Reflect.get(plugin, method, plugin)
|
||||||
|
if (typeof pluginMethod !== 'function') {
|
||||||
|
console.error(`Plugin ${namespace}'s property ${method}'s type is ${typeof pluginMethod} not function,`)
|
||||||
|
}
|
||||||
|
const ret = Reflect.apply(pluginMethod, plugin, [args])
|
||||||
|
if (ret instanceof Promise) {
|
||||||
|
ret.then(
|
||||||
|
e => {
|
||||||
|
jsCallResolve(contextId, callbackId, e)
|
||||||
|
},
|
||||||
|
e => {
|
||||||
|
jsCallReject(contextId, callbackId, e)
|
||||||
|
})
|
||||||
|
} else if (ret !== undefined) {
|
||||||
|
jsCallResolve(contextId, callbackId, ret)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
injectGlobalObject('nativeSetTimer', (timerId: number, time: number, repeat: boolean) => {
|
||||||
|
if (repeat) {
|
||||||
|
const handleId = originSetInterval(() => {
|
||||||
|
jsCallbackTimer(timerId)
|
||||||
|
}, time)
|
||||||
|
timers.set(timerId, { handleId, repeat })
|
||||||
|
} else {
|
||||||
|
const handleId = originSetTimeout(() => {
|
||||||
|
jsCallbackTimer(timerId)
|
||||||
|
}, time)
|
||||||
|
timers.set(timerId, { handleId, repeat })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
injectGlobalObject('nativeClearTimer', (timerId: number) => {
|
||||||
|
const timerInfo = timers.get(timerId)
|
||||||
|
if (timerInfo) {
|
||||||
|
if (timerInfo.repeat) {
|
||||||
|
originClearInterval(timerInfo.handleId)
|
||||||
|
} else {
|
||||||
|
originClearTimeout(timerInfo.handleId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createContext(contextId: string, content: string) {
|
||||||
|
loadJS(packageCreateContext(contextId, content))
|
||||||
|
}
|
||||||
|
|
||||||
|
initDoric()
|
30
doric-h5/src/DoricElement.ts
Normal file
30
doric-h5/src/DoricElement.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import axios from 'axios'
|
||||||
|
import { DoricContext } from './DoricContext'
|
||||||
|
|
||||||
|
|
||||||
|
export class DoricElement extends HTMLElement {
|
||||||
|
source: string
|
||||||
|
alias: string
|
||||||
|
context?: DoricContext
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
this.source = this.getAttribute('src') || ""
|
||||||
|
this.alias = this.getAttribute('alias') || this.source
|
||||||
|
axios.get<string>(this.source).then(result => {
|
||||||
|
this.load(result.data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
load(content: string) {
|
||||||
|
this.context = new DoricContext(content)
|
||||||
|
|
||||||
|
const divElement = document.createElement('div')
|
||||||
|
divElement.style.height = '100%'
|
||||||
|
this.append(divElement)
|
||||||
|
this.context.rootNode.view = divElement
|
||||||
|
this.context.init({
|
||||||
|
width: divElement.offsetWidth,
|
||||||
|
height: divElement.offsetHeight,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
9
doric-h5/src/DoricPlugin.ts
Normal file
9
doric-h5/src/DoricPlugin.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { DoricContext } from "./DoricContext"
|
||||||
|
|
||||||
|
export type DoricPluginClass = { new(...args: any[]): {} }
|
||||||
|
export class DoricPlugin {
|
||||||
|
context: DoricContext
|
||||||
|
constructor(context: DoricContext) {
|
||||||
|
this.context = context
|
||||||
|
}
|
||||||
|
}
|
51
doric-h5/src/DoricRegistry.ts
Normal file
51
doric-h5/src/DoricRegistry.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { DoricPluginClass } from "./DoricPlugin"
|
||||||
|
import { ShaderPlugin } from "./plugins/ShaderPlugin"
|
||||||
|
import { DoricViewNodeClass } from "./shader/DoricViewNode"
|
||||||
|
import { DoricStackNode } from "./shader/DoricStackNode"
|
||||||
|
import { DoricVLayoutNode } from './shader/DoricVLayoutNode'
|
||||||
|
import { DoricHLayoutNode } from './shader/DoricHLayoutNode'
|
||||||
|
import { DoricTextNode } from "./shader/DoricTextNode"
|
||||||
|
import { DoricImageNode } from "./shader/DoricImageNode"
|
||||||
|
import { DoricScrollerNode } from "./shader/DoricScrollerNode"
|
||||||
|
import { ModalPlugin } from './plugins/ModalPlugin'
|
||||||
|
|
||||||
|
const bundles: Map<string, string> = new Map
|
||||||
|
|
||||||
|
const plugins: Map<string, DoricPluginClass> = new Map
|
||||||
|
|
||||||
|
const nodes: Map<string, DoricViewNodeClass> = new Map
|
||||||
|
|
||||||
|
|
||||||
|
export function acquireJSBundle(name: string) {
|
||||||
|
return bundles.get(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function registerJSBundle(name: string, bundle: string) {
|
||||||
|
bundles.set(name, bundle)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function registerPlugin(name: string, plugin: DoricPluginClass) {
|
||||||
|
plugins.set(name, plugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function acquirePlugin(name: string) {
|
||||||
|
return plugins.get(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function registerViewNode(name: string, node: DoricViewNodeClass) {
|
||||||
|
nodes.set(name, node)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function acquireViewNode(name: string) {
|
||||||
|
return nodes.get(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
registerPlugin('shader', ShaderPlugin)
|
||||||
|
registerPlugin('modal', ModalPlugin)
|
||||||
|
|
||||||
|
registerViewNode('Stack', DoricStackNode)
|
||||||
|
registerViewNode('VLayout', DoricVLayoutNode)
|
||||||
|
registerViewNode('HLayout', DoricHLayoutNode)
|
||||||
|
registerViewNode('Text', DoricTextNode)
|
||||||
|
registerViewNode('Image', DoricImageNode)
|
||||||
|
registerViewNode('Scroller', DoricScrollerNode)
|
72
doric-h5/src/plugins/ModalPlugin.ts
Normal file
72
doric-h5/src/plugins/ModalPlugin.ts
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import { DoricPlugin } from '../DoricPlugin'
|
||||||
|
import { TOP, CENTER_Y, BOTTOM, toPixelString } from '../shader/DoricViewNode'
|
||||||
|
|
||||||
|
export class ModalPlugin extends DoricPlugin {
|
||||||
|
toast(args: {
|
||||||
|
msg?: string,
|
||||||
|
gravity?: number
|
||||||
|
}) {
|
||||||
|
const toastElement = document.createElement('div')
|
||||||
|
toastElement.style.position = "absolute"
|
||||||
|
toastElement.style.textAlign = "center"
|
||||||
|
toastElement.style.width = "100%"
|
||||||
|
|
||||||
|
const textElement = document.createElement('span')
|
||||||
|
textElement.innerText = args.msg || ""
|
||||||
|
textElement.style.backgroundColor = "#777777"
|
||||||
|
textElement.style.color = "white"
|
||||||
|
textElement.style.paddingLeft = '20px'
|
||||||
|
textElement.style.paddingRight = '20px'
|
||||||
|
textElement.style.paddingTop = '10px'
|
||||||
|
textElement.style.paddingBottom = '10px'
|
||||||
|
toastElement.appendChild(textElement)
|
||||||
|
document.body.appendChild(toastElement)
|
||||||
|
const gravity = args.gravity || BOTTOM
|
||||||
|
if ((gravity & TOP) == TOP) {
|
||||||
|
toastElement.style.top = toPixelString(30)
|
||||||
|
} else if ((gravity & BOTTOM) == BOTTOM) {
|
||||||
|
toastElement.style.bottom = toPixelString(30)
|
||||||
|
} else if ((gravity & CENTER_Y) == CENTER_Y) {
|
||||||
|
toastElement.style.top = toPixelString(document.body.offsetHeight / 2 - toastElement.offsetHeight / 2)
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
document.body.removeChild(toastElement)
|
||||||
|
}, 2000)
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
alert(args: {
|
||||||
|
title?: string,
|
||||||
|
msg?: string,
|
||||||
|
okLabel?: string,
|
||||||
|
}) {
|
||||||
|
window.alert(args.msg || "")
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
confirm(args: {
|
||||||
|
title?: string,
|
||||||
|
msg?: string,
|
||||||
|
okLabel?: string,
|
||||||
|
cancelLabel?: string,
|
||||||
|
}) {
|
||||||
|
if (window.confirm(args.msg || "")) {
|
||||||
|
return Promise.resolve()
|
||||||
|
} else {
|
||||||
|
return Promise.reject()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prompt(args: {
|
||||||
|
title?: string,
|
||||||
|
msg?: string,
|
||||||
|
okLabel?: string,
|
||||||
|
cancelLabel?: string,
|
||||||
|
defaultText?: string
|
||||||
|
text?: string
|
||||||
|
}) {
|
||||||
|
const result = window.prompt(args.msg || "", args.defaultText)
|
||||||
|
if (result) {
|
||||||
|
return Promise.resolve(result)
|
||||||
|
} else {
|
||||||
|
return Promise.reject(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
doric-h5/src/plugins/ShaderPlugin.ts
Normal file
9
doric-h5/src/plugins/ShaderPlugin.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { DoricPlugin } from "../DoricPlugin";
|
||||||
|
import { DVModel } from "../shader/DoricViewNode";
|
||||||
|
|
||||||
|
export class ShaderPlugin extends DoricPlugin {
|
||||||
|
render(ret: DVModel) {
|
||||||
|
this.context.rootNode.viewId = ret.id
|
||||||
|
this.context.rootNode.blend(ret.props)
|
||||||
|
}
|
||||||
|
}
|
53
doric-h5/src/shader/DoricHLayoutNode.ts
Normal file
53
doric-h5/src/shader/DoricHLayoutNode.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { DoricGroupViewNode, LEFT, RIGHT, CENTER_X, CENTER_Y, TOP, BOTTOM, toPixelString } from "./DoricViewNode";
|
||||||
|
|
||||||
|
export class DoricHLayoutNode extends DoricGroupViewNode {
|
||||||
|
space = 0
|
||||||
|
gravity = 0
|
||||||
|
build() {
|
||||||
|
const ret = document.createElement('div')
|
||||||
|
ret.style.display = "flex"
|
||||||
|
ret.style.flexDirection = "row"
|
||||||
|
ret.style.flexWrap = "nowrap"
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
blendProps(v: HTMLElement, propName: string, prop: any) {
|
||||||
|
if (propName === 'space') {
|
||||||
|
this.space = prop
|
||||||
|
} else if (propName === 'gravity') {
|
||||||
|
this.gravity = prop
|
||||||
|
this.gravity = prop
|
||||||
|
if ((this.gravity & LEFT) === LEFT) {
|
||||||
|
this.view.style.justifyContent = "flex-start"
|
||||||
|
} else if ((this.gravity & RIGHT) === RIGHT) {
|
||||||
|
this.view.style.justifyContent = "flex-end"
|
||||||
|
} else if ((this.gravity & CENTER_X) === CENTER_X) {
|
||||||
|
this.view.style.justifyContent = "center"
|
||||||
|
}
|
||||||
|
if ((this.gravity & TOP) === TOP) {
|
||||||
|
this.view.style.alignItems = "flex-start"
|
||||||
|
} else if ((this.gravity & BOTTOM) === BOTTOM) {
|
||||||
|
this.view.style.alignItems = "flex-end"
|
||||||
|
} else if ((this.gravity & CENTER_Y) === CENTER_Y) {
|
||||||
|
this.view.style.alignItems = "center"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super.blendProps(v, propName, prop)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
layout() {
|
||||||
|
super.layout()
|
||||||
|
this.childNodes.forEach((e, idx) => {
|
||||||
|
e.view.style.flexShrink = "0"
|
||||||
|
if (e.layoutConfig?.weight) {
|
||||||
|
e.view.style.flex = `${e.layoutConfig?.weight}`
|
||||||
|
}
|
||||||
|
e.view.style.marginLeft = toPixelString(e.layoutConfig?.margin?.left || 0)
|
||||||
|
e.view.style.marginRight = toPixelString(
|
||||||
|
(idx === this.childNodes.length - 1) ? 0 : this.space
|
||||||
|
+ (e.layoutConfig?.margin?.right || 0))
|
||||||
|
e.view.style.marginTop = toPixelString(e.layoutConfig?.margin?.top || 0)
|
||||||
|
e.view.style.marginBottom = toPixelString(e.layoutConfig?.margin?.bottom || 0)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
59
doric-h5/src/shader/DoricImageNode.ts
Normal file
59
doric-h5/src/shader/DoricImageNode.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { DoricViewNode, LEFT, RIGHT, CENTER_X, CENTER_Y, TOP, BOTTOM, toPixelString, toRGBAString } from "./DoricViewNode";
|
||||||
|
|
||||||
|
enum ScaleType {
|
||||||
|
ScaleToFill = 0,
|
||||||
|
ScaleAspectFit,
|
||||||
|
ScaleAspectFill,
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DoricImageNode extends DoricViewNode {
|
||||||
|
|
||||||
|
build(): HTMLElement {
|
||||||
|
const ret = document.createElement('img')
|
||||||
|
ret.style.objectFit = "fill"
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
blendProps(v: HTMLImageElement, propName: string, prop: any) {
|
||||||
|
switch (propName) {
|
||||||
|
case 'imageUrl':
|
||||||
|
v.setAttribute('src', prop)
|
||||||
|
break
|
||||||
|
case 'imageBase64':
|
||||||
|
v.setAttribute('src', prop)
|
||||||
|
break
|
||||||
|
case 'loadCallback':
|
||||||
|
v.onload = () => {
|
||||||
|
this.callJSResponse(prop, {
|
||||||
|
width: v.width,
|
||||||
|
height: v.height
|
||||||
|
})
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'scaleType':
|
||||||
|
switch (prop) {
|
||||||
|
case ScaleType.ScaleToFill:
|
||||||
|
v.style.objectFit = "fill"
|
||||||
|
break
|
||||||
|
case ScaleType.ScaleAspectFit:
|
||||||
|
v.style.objectFit = "contain"
|
||||||
|
break
|
||||||
|
case ScaleType.ScaleAspectFill:
|
||||||
|
v.style.objectFit = "cover"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'isBlur':
|
||||||
|
if (prop) {
|
||||||
|
v.style.filter = 'blur(8px)'
|
||||||
|
} else {
|
||||||
|
v.style.filter = ''
|
||||||
|
}
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
super.blendProps(v, propName, prop)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
69
doric-h5/src/shader/DoricScrollerNode.ts
Normal file
69
doric-h5/src/shader/DoricScrollerNode.ts
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import { LEFT, RIGHT, CENTER_X, CENTER_Y, TOP, BOTTOM, toPixelString, DoricSuperViewNode, DVModel, DoricViewNode } from "./DoricViewNode";
|
||||||
|
|
||||||
|
export class DoricScrollerNode extends DoricSuperViewNode {
|
||||||
|
|
||||||
|
|
||||||
|
childViewId: string = ""
|
||||||
|
childNode?: DoricViewNode
|
||||||
|
build() {
|
||||||
|
const ret = document.createElement('div')
|
||||||
|
ret.style.overflow = "scroll"
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
blendProps(v: HTMLElement, propName: string, prop: any) {
|
||||||
|
if (propName === 'content') {
|
||||||
|
this.childViewId = prop
|
||||||
|
} else {
|
||||||
|
super.blendProps(v, propName, prop)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
blendSubNode(model: DVModel): void {
|
||||||
|
this.childNode?.blend(model.props)
|
||||||
|
}
|
||||||
|
getSubNodeById(viewId: string) {
|
||||||
|
return viewId === this.childViewId ? this.childNode : undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
onBlended() {
|
||||||
|
super.onBlended()
|
||||||
|
const model = this.getSubModel(this.childViewId)
|
||||||
|
if (model === undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this.childNode) {
|
||||||
|
if (this.childNode.viewId === this.childViewId) {
|
||||||
|
///skip
|
||||||
|
} else {
|
||||||
|
if (this.reusable && this.childNode.viewType === model.type) {
|
||||||
|
this.childNode.viewId = model.id
|
||||||
|
this.childNode.blend(model.props)
|
||||||
|
} else {
|
||||||
|
this.view.removeChild(this.childNode.view)
|
||||||
|
const childNode = DoricViewNode.create(this.context, model.type)
|
||||||
|
if (childNode === undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
childNode.viewId = model.id
|
||||||
|
childNode.init(this)
|
||||||
|
childNode.blend(model.props)
|
||||||
|
this.view.appendChild(childNode.view)
|
||||||
|
this.childNode = childNode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const childNode = DoricViewNode.create(this.context, model.type)
|
||||||
|
if (childNode === undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
childNode.viewId = model.id
|
||||||
|
childNode.init(this)
|
||||||
|
childNode.blend(model.props)
|
||||||
|
this.view.appendChild(childNode.view)
|
||||||
|
this.childNode = childNode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
layout() {
|
||||||
|
super.layout()
|
||||||
|
}
|
||||||
|
}
|
38
doric-h5/src/shader/DoricStackNode.ts
Normal file
38
doric-h5/src/shader/DoricStackNode.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import { DoricGroupViewNode, LayoutSpec, FrameSize, LEFT, RIGHT, CENTER_X, CENTER_Y, TOP, BOTTOM, toPixelString } from "./DoricViewNode";
|
||||||
|
|
||||||
|
export class DoricStackNode extends DoricGroupViewNode {
|
||||||
|
|
||||||
|
build() {
|
||||||
|
const ret = document.createElement('div')
|
||||||
|
ret.style.position = "relative"
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
layout() {
|
||||||
|
super.layout()
|
||||||
|
this.configOffset()
|
||||||
|
}
|
||||||
|
|
||||||
|
configOffset() {
|
||||||
|
this.childNodes.forEach(e => {
|
||||||
|
e.view.style.position = "absolute"
|
||||||
|
e.view.style.left = toPixelString(e.offsetX + this.paddingLeft)
|
||||||
|
e.view.style.top = toPixelString(e.offsetY + this.paddingTop)
|
||||||
|
const gravity = e.layoutConfig.alignment
|
||||||
|
if ((gravity & LEFT) === LEFT) {
|
||||||
|
e.view.style.left = toPixelString(0)
|
||||||
|
} else if ((gravity & RIGHT) === RIGHT) {
|
||||||
|
e.view.style.left = toPixelString(this.view.offsetWidth - e.view.offsetWidth)
|
||||||
|
} else if ((gravity & CENTER_X) === CENTER_X) {
|
||||||
|
e.view.style.left = toPixelString(this.view.offsetWidth / 2 - e.view.offsetWidth / 2)
|
||||||
|
}
|
||||||
|
if ((gravity & TOP) === TOP) {
|
||||||
|
e.view.style.top = toPixelString(0)
|
||||||
|
} else if ((gravity & BOTTOM) === BOTTOM) {
|
||||||
|
e.view.style.top = toPixelString(this.view.offsetHeight - e.view.offsetHeight)
|
||||||
|
} else if ((gravity & CENTER_Y) === CENTER_Y) {
|
||||||
|
e.view.style.top = toPixelString(this.view.offsetHeight / 2 - e.view.offsetHeight / 2)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
49
doric-h5/src/shader/DoricTextNode.ts
Normal file
49
doric-h5/src/shader/DoricTextNode.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { DoricViewNode, LEFT, RIGHT, CENTER_X, CENTER_Y, TOP, BOTTOM, toPixelString, toRGBAString } from "./DoricViewNode";
|
||||||
|
|
||||||
|
export class DoricTextNode extends DoricViewNode {
|
||||||
|
textElement!: HTMLElement
|
||||||
|
build(): HTMLElement {
|
||||||
|
const div = document.createElement('div')
|
||||||
|
div.style.display = "flex"
|
||||||
|
this.textElement = document.createElement('span')
|
||||||
|
div.appendChild(this.textElement)
|
||||||
|
div.style.justifyContent = "center"
|
||||||
|
div.style.alignItems = "center"
|
||||||
|
return div
|
||||||
|
}
|
||||||
|
|
||||||
|
blendProps(v: HTMLParagraphElement, propName: string, prop: any) {
|
||||||
|
switch (propName) {
|
||||||
|
case 'text':
|
||||||
|
this.textElement.innerText = prop
|
||||||
|
break
|
||||||
|
case 'textSize':
|
||||||
|
v.style.fontSize = toPixelString(prop)
|
||||||
|
break
|
||||||
|
case 'textColor':
|
||||||
|
v.style.color = toRGBAString(prop)
|
||||||
|
break
|
||||||
|
case 'textAlignment':
|
||||||
|
const gravity: number = prop
|
||||||
|
if ((gravity & LEFT) === LEFT) {
|
||||||
|
v.style.justifyContent = "flex-start"
|
||||||
|
} else if ((gravity & RIGHT) === RIGHT) {
|
||||||
|
v.style.justifyContent = "flex-end"
|
||||||
|
} else if ((gravity & CENTER_X) === CENTER_X) {
|
||||||
|
v.style.justifyContent = "center"
|
||||||
|
}
|
||||||
|
if ((gravity & TOP) === TOP) {
|
||||||
|
v.style.alignItems = "flex-start"
|
||||||
|
} else if ((gravity & BOTTOM) === BOTTOM) {
|
||||||
|
v.style.alignItems = "flex-end"
|
||||||
|
} else if ((gravity & CENTER_Y) === CENTER_Y) {
|
||||||
|
v.style.alignItems = "center"
|
||||||
|
}
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
super.blendProps(v, propName, prop)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
53
doric-h5/src/shader/DoricVLayoutNode.ts
Normal file
53
doric-h5/src/shader/DoricVLayoutNode.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { DoricGroupViewNode, LEFT, RIGHT, CENTER_X, CENTER_Y, TOP, BOTTOM, toPixelString } from "./DoricViewNode";
|
||||||
|
|
||||||
|
export class DoricVLayoutNode extends DoricGroupViewNode {
|
||||||
|
space = 0
|
||||||
|
gravity = 0
|
||||||
|
|
||||||
|
build() {
|
||||||
|
const ret = document.createElement('div')
|
||||||
|
ret.style.display = "flex"
|
||||||
|
ret.style.flexDirection = "column"
|
||||||
|
ret.style.flexWrap = "nowrap"
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
blendProps(v: HTMLElement, propName: string, prop: any) {
|
||||||
|
if (propName === 'space') {
|
||||||
|
this.space = prop
|
||||||
|
} else if (propName === 'gravity') {
|
||||||
|
this.gravity = prop
|
||||||
|
if ((this.gravity & LEFT) === LEFT) {
|
||||||
|
this.view.style.alignItems = "flex-start"
|
||||||
|
} else if ((this.gravity & RIGHT) === RIGHT) {
|
||||||
|
this.view.style.alignItems = "flex-end"
|
||||||
|
} else if ((this.gravity & CENTER_X) === CENTER_X) {
|
||||||
|
this.view.style.alignItems = "center"
|
||||||
|
}
|
||||||
|
if ((this.gravity & TOP) === TOP) {
|
||||||
|
this.view.style.justifyContent = "flex-start"
|
||||||
|
} else if ((this.gravity & BOTTOM) === BOTTOM) {
|
||||||
|
this.view.style.justifyContent = "flex-end"
|
||||||
|
} else if ((this.gravity & CENTER_Y) === CENTER_Y) {
|
||||||
|
this.view.style.justifyContent = "center"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super.blendProps(v, propName, prop)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
layout() {
|
||||||
|
super.layout()
|
||||||
|
this.childNodes.forEach((e, idx) => {
|
||||||
|
e.view.style.flexShrink = "0"
|
||||||
|
if (e.layoutConfig?.weight) {
|
||||||
|
e.view.style.flex = `${e.layoutConfig?.weight}`
|
||||||
|
}
|
||||||
|
e.view.style.marginTop = toPixelString(e.layoutConfig?.margin?.top || 0)
|
||||||
|
e.view.style.marginBottom = toPixelString(
|
||||||
|
(idx === this.childNodes.length - 1) ? 0 : this.space
|
||||||
|
+ (e.layoutConfig?.margin?.bottom || 0))
|
||||||
|
e.view.style.marginLeft = toPixelString(e.layoutConfig?.margin?.left || 0)
|
||||||
|
e.view.style.marginRight = toPixelString(e.layoutConfig?.margin?.right || 0)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
481
doric-h5/src/shader/DoricViewNode.ts
Normal file
481
doric-h5/src/shader/DoricViewNode.ts
Normal file
@ -0,0 +1,481 @@
|
|||||||
|
import { DoricContext } from "../DoricContext";
|
||||||
|
import { acquireViewNode } from "../DoricRegistry";
|
||||||
|
|
||||||
|
export enum LayoutSpec {
|
||||||
|
EXACTLY = 0,
|
||||||
|
WRAP_CONTENT = 1,
|
||||||
|
AT_MOST = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
const SPECIFIED = 1
|
||||||
|
const START = 1 << 1
|
||||||
|
const END = 1 << 2
|
||||||
|
|
||||||
|
const SHIFT_X = 0
|
||||||
|
const SHIFT_Y = 4
|
||||||
|
|
||||||
|
export const LEFT = (START | SPECIFIED) << SHIFT_X
|
||||||
|
export const RIGHT = (END | SPECIFIED) << SHIFT_X
|
||||||
|
|
||||||
|
export const TOP = (START | SPECIFIED) << SHIFT_Y
|
||||||
|
export const BOTTOM = (END | SPECIFIED) << SHIFT_Y
|
||||||
|
|
||||||
|
export const CENTER_X = SPECIFIED << SHIFT_X
|
||||||
|
export const CENTER_Y = SPECIFIED << SHIFT_Y
|
||||||
|
|
||||||
|
export const CENTER = CENTER_X | CENTER_Y
|
||||||
|
|
||||||
|
export type FrameSize = {
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
}
|
||||||
|
export function toPixelString(v: number) {
|
||||||
|
return `${v}px`
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toRGBAString(color: number) {
|
||||||
|
let strs = []
|
||||||
|
for (let i = 0; i < 32; i += 8) {
|
||||||
|
|
||||||
|
strs.push(((color >> i) & 0xff).toString(16))
|
||||||
|
}
|
||||||
|
strs = strs.map(e => {
|
||||||
|
if (e.length === 1) {
|
||||||
|
return '0' + e
|
||||||
|
}
|
||||||
|
return e
|
||||||
|
}).reverse()
|
||||||
|
/// RGBA
|
||||||
|
return `#${strs[1]}${strs[2]}${strs[3]}${strs[0]}`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type DoricViewNodeClass = { new(...args: any[]): {} }
|
||||||
|
|
||||||
|
export interface DVModel {
|
||||||
|
id: string,
|
||||||
|
type: string,
|
||||||
|
props: {
|
||||||
|
[index: string]: any
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class DoricViewNode {
|
||||||
|
viewId = ""
|
||||||
|
viewType = "View"
|
||||||
|
context: DoricContext
|
||||||
|
superNode?: DoricSuperViewNode
|
||||||
|
layoutConfig = {
|
||||||
|
widthSpec: LayoutSpec.EXACTLY,
|
||||||
|
heightSpec: LayoutSpec.EXACTLY,
|
||||||
|
alignment: 0,
|
||||||
|
weight: 0,
|
||||||
|
margin: {
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
top: 0,
|
||||||
|
bottom: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
padding = {
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
top: 0,
|
||||||
|
bottom: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
border?: {
|
||||||
|
width: number,
|
||||||
|
color: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
frameWidth = 0
|
||||||
|
|
||||||
|
frameHeight = 0
|
||||||
|
|
||||||
|
offsetX = 0
|
||||||
|
|
||||||
|
offsetY = 0
|
||||||
|
|
||||||
|
view!: HTMLElement
|
||||||
|
|
||||||
|
|
||||||
|
constructor(context: DoricContext) {
|
||||||
|
this.context = context
|
||||||
|
}
|
||||||
|
|
||||||
|
init(superNode: DoricSuperViewNode) {
|
||||||
|
this.superNode = superNode
|
||||||
|
if (this instanceof DoricSuperViewNode) {
|
||||||
|
this.reusable = superNode.reusable
|
||||||
|
}
|
||||||
|
this.view = this.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract build(): HTMLElement
|
||||||
|
|
||||||
|
get paddingLeft() {
|
||||||
|
return this.padding.left || 0
|
||||||
|
}
|
||||||
|
|
||||||
|
get paddingRight() {
|
||||||
|
return this.padding.right || 0
|
||||||
|
}
|
||||||
|
|
||||||
|
get paddingTop() {
|
||||||
|
return this.padding.top || 0
|
||||||
|
}
|
||||||
|
|
||||||
|
get paddingBottom() {
|
||||||
|
return this.padding.bottom || 0
|
||||||
|
}
|
||||||
|
|
||||||
|
get borderWidth() {
|
||||||
|
return this.border?.width || 0
|
||||||
|
}
|
||||||
|
|
||||||
|
blend(props: { [index: string]: any }) {
|
||||||
|
for (let key in props) {
|
||||||
|
this.blendProps(this.view, key, props[key])
|
||||||
|
}
|
||||||
|
this.onBlended()
|
||||||
|
this.layout()
|
||||||
|
}
|
||||||
|
onBlended() {
|
||||||
|
|
||||||
|
}
|
||||||
|
configBorder() {
|
||||||
|
if (this.border) {
|
||||||
|
this.view.style.borderStyle = "solid"
|
||||||
|
this.view.style.borderWidth = toPixelString(this.border.width)
|
||||||
|
this.view.style.borderColor = toRGBAString(this.border.color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configWidth() {
|
||||||
|
switch (this.layoutConfig.widthSpec) {
|
||||||
|
case LayoutSpec.WRAP_CONTENT:
|
||||||
|
this.view.style.width = "fit-content"
|
||||||
|
break
|
||||||
|
|
||||||
|
case LayoutSpec.AT_MOST:
|
||||||
|
this.view.style.width = "100%"
|
||||||
|
break
|
||||||
|
|
||||||
|
case LayoutSpec.EXACTLY:
|
||||||
|
default:
|
||||||
|
this.view.style.width = toPixelString(this.frameWidth
|
||||||
|
- this.paddingLeft - this.paddingRight
|
||||||
|
- this.borderWidth * 2)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
configHeight() {
|
||||||
|
switch (this.layoutConfig.heightSpec) {
|
||||||
|
case LayoutSpec.WRAP_CONTENT:
|
||||||
|
this.view.style.height = "fit-content"
|
||||||
|
break
|
||||||
|
|
||||||
|
case LayoutSpec.AT_MOST:
|
||||||
|
this.view.style.height = "100%"
|
||||||
|
break
|
||||||
|
|
||||||
|
case LayoutSpec.EXACTLY:
|
||||||
|
default:
|
||||||
|
this.view.style.height = toPixelString(this.frameHeight
|
||||||
|
- this.paddingTop - this.paddingBottom
|
||||||
|
- this.borderWidth * 2)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configMargin() {
|
||||||
|
if (this.layoutConfig.margin) {
|
||||||
|
this.view.style.marginLeft = toPixelString(this.layoutConfig.margin.left || 0)
|
||||||
|
this.view.style.marginRight = toPixelString(this.layoutConfig.margin.right || 0)
|
||||||
|
this.view.style.marginTop = toPixelString(this.layoutConfig.margin.top || 0)
|
||||||
|
this.view.style.marginBottom = toPixelString(this.layoutConfig.margin.bottom || 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configPadding() {
|
||||||
|
if (this.padding) {
|
||||||
|
this.view.style.paddingLeft = toPixelString(this.paddingLeft)
|
||||||
|
this.view.style.paddingRight = toPixelString(this.paddingRight)
|
||||||
|
this.view.style.paddingTop = toPixelString(this.paddingTop)
|
||||||
|
this.view.style.paddingBottom = toPixelString(this.paddingBottom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
layout() {
|
||||||
|
this.configMargin()
|
||||||
|
this.configBorder()
|
||||||
|
this.configPadding()
|
||||||
|
this.configWidth()
|
||||||
|
this.configHeight()
|
||||||
|
}
|
||||||
|
|
||||||
|
blendProps(v: HTMLElement, propName: string, prop: any) {
|
||||||
|
switch (propName) {
|
||||||
|
case "border":
|
||||||
|
this.border = prop
|
||||||
|
break
|
||||||
|
case "padding":
|
||||||
|
this.padding = prop
|
||||||
|
break
|
||||||
|
case 'width':
|
||||||
|
this.frameWidth = prop as number
|
||||||
|
break
|
||||||
|
case 'height':
|
||||||
|
this.frameHeight = prop as number
|
||||||
|
break
|
||||||
|
case 'backgroundColor':
|
||||||
|
this.backgroundColor = prop as number
|
||||||
|
break
|
||||||
|
case 'layoutConfig':
|
||||||
|
const layoutConfig = prop
|
||||||
|
for (let key in layoutConfig) {
|
||||||
|
Reflect.set(this.layoutConfig, key, Reflect.get(layoutConfig, key, layoutConfig))
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'x':
|
||||||
|
this.offsetX = prop as number
|
||||||
|
break
|
||||||
|
case 'y':
|
||||||
|
this.offsetY = prop as number
|
||||||
|
break
|
||||||
|
case 'onClick':
|
||||||
|
this.view.onclick = () => {
|
||||||
|
this.callJSResponse(prop as string)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'corners':
|
||||||
|
if (typeof prop === 'object') {
|
||||||
|
this.view.style.borderTopLeftRadius = toPixelString(prop.leftTop)
|
||||||
|
this.view.style.borderTopRightRadius = toPixelString(prop.rightTop)
|
||||||
|
this.view.style.borderBottomRightRadius = toPixelString(prop.rightBottom)
|
||||||
|
this.view.style.borderBottomLeftRadius = toPixelString(prop.leftBottom)
|
||||||
|
} else {
|
||||||
|
this.view.style.borderRadius = toPixelString(prop)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'shadow':
|
||||||
|
const opacity = prop.opacity || 0
|
||||||
|
if (opacity > 0) {
|
||||||
|
const offsetX = prop.offsetX || 0
|
||||||
|
const offsetY = prop.offsetY || 0
|
||||||
|
const shadowColor = prop.color || 0xff000000
|
||||||
|
const shadowRadius = prop.radius
|
||||||
|
const alpha = opacity * 255
|
||||||
|
this.view.style.boxShadow = `${toPixelString(offsetX)} ${toPixelString(offsetY)} ${toPixelString(shadowRadius)} ${toRGBAString((shadowColor & 0xffffff) | ((alpha & 0xff) << 24))} `
|
||||||
|
} else {
|
||||||
|
this.view.style.boxShadow = ""
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set backgroundColor(v: number) {
|
||||||
|
this.view.style.backgroundColor = toRGBAString(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
static create(context: DoricContext, type: string) {
|
||||||
|
const viewNodeClass = acquireViewNode(type)
|
||||||
|
if (viewNodeClass === undefined) {
|
||||||
|
console.error(`Cannot find ViewNode for ${type}`)
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
const ret = new viewNodeClass(context) as DoricViewNode
|
||||||
|
ret.viewType = type
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
getIdList() {
|
||||||
|
const ids: string[] = []
|
||||||
|
let viewNode: DoricViewNode | undefined = this
|
||||||
|
do {
|
||||||
|
ids.push(viewNode.viewId)
|
||||||
|
viewNode = viewNode.superNode
|
||||||
|
} while (viewNode)
|
||||||
|
return ids.reverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
callJSResponse(funcId: string, ...args: any) {
|
||||||
|
const argumentsList: any = ['__response__', this.getIdList(), funcId]
|
||||||
|
for (let i = 1; i < arguments.length; i++) {
|
||||||
|
argumentsList.push(arguments[i])
|
||||||
|
}
|
||||||
|
Reflect.apply(this.context.invokeEntityMethod, this.context, argumentsList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export abstract class DoricSuperViewNode extends DoricViewNode {
|
||||||
|
reusable = false
|
||||||
|
|
||||||
|
subModels: Map<String, DVModel> = new Map
|
||||||
|
|
||||||
|
blendProps(v: HTMLElement, propName: string, prop: any) {
|
||||||
|
if (propName === 'subviews') {
|
||||||
|
if (prop instanceof Array) {
|
||||||
|
prop.forEach((e: DVModel) => {
|
||||||
|
this.mixinSubModel(e)
|
||||||
|
this.blendSubNode(e)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super.blendProps(v, propName, prop)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mixinSubModel(subNode: DVModel) {
|
||||||
|
const oldValue = this.getSubModel(subNode.id)
|
||||||
|
if (oldValue) {
|
||||||
|
this.mixin(subNode, oldValue)
|
||||||
|
} else {
|
||||||
|
this.subModels.set(subNode.id, subNode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getSubModel(id: string) {
|
||||||
|
return this.subModels.get(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin(src: DVModel, target: DVModel) {
|
||||||
|
for (let key in src.props) {
|
||||||
|
if (key === "subviews") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
Reflect.set(target.props, key, Reflect.get(src.props, key))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clearSubModels() {
|
||||||
|
this.subModels.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
removeSubModel(id: string) {
|
||||||
|
this.subModels.delete(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract blendSubNode(model: DVModel): void
|
||||||
|
|
||||||
|
abstract getSubNodeById(viewId: string): DoricViewNode | undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class DoricGroupViewNode extends DoricSuperViewNode {
|
||||||
|
childNodes: DoricViewNode[] = []
|
||||||
|
childViewIds: string[] = []
|
||||||
|
|
||||||
|
blendProps(v: HTMLElement, propName: string, prop: any) {
|
||||||
|
if (propName === 'children') {
|
||||||
|
if (prop instanceof Array) {
|
||||||
|
this.childViewIds = prop
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super.blendProps(v, propName, prop)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blend(props: { [index: string]: any }) {
|
||||||
|
super.blend(props)
|
||||||
|
}
|
||||||
|
onBlended() {
|
||||||
|
super.onBlended()
|
||||||
|
this.configChildNode()
|
||||||
|
}
|
||||||
|
configChildNode() {
|
||||||
|
this.childViewIds.forEach((childViewId, index) => {
|
||||||
|
const model = this.getSubModel(childViewId)
|
||||||
|
if (model === undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (index < this.childNodes.length) {
|
||||||
|
const oldNode = this.childNodes[index]
|
||||||
|
if (oldNode.viewId === childViewId) {
|
||||||
|
//The same,skip
|
||||||
|
} else {
|
||||||
|
if (this.reusable) {
|
||||||
|
if (oldNode.viewType === model.type) {
|
||||||
|
//Same type,can be reused
|
||||||
|
oldNode.viewId = childViewId
|
||||||
|
oldNode.blend(model.props)
|
||||||
|
} else {
|
||||||
|
//Replace this view
|
||||||
|
this.view.removeChild(oldNode.view)
|
||||||
|
const newNode = DoricViewNode.create(this.context, model.type)
|
||||||
|
if (newNode === undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
newNode.viewId = childViewId
|
||||||
|
newNode.init(this)
|
||||||
|
newNode.blend(model.props)
|
||||||
|
this.childNodes[index] = newNode
|
||||||
|
this.view.replaceChild(newNode.view, oldNode.view)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Find in remain nodes
|
||||||
|
let position = -1
|
||||||
|
for (let start = index + 1; start < this.childNodes.length; start++) {
|
||||||
|
if (childViewId === this.childNodes[start].viewId) {
|
||||||
|
//Found
|
||||||
|
position = start
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (position >= 0) {
|
||||||
|
//Found swap idx,position
|
||||||
|
const reused = this.childNodes[position]
|
||||||
|
const abandoned = this.childNodes[index]
|
||||||
|
this.childNodes[index] = reused
|
||||||
|
this.childNodes[position] = abandoned
|
||||||
|
this.view.removeChild(reused.view)
|
||||||
|
this.view.insertBefore(reused.view, abandoned.view)
|
||||||
|
this.view.removeChild(abandoned.view)
|
||||||
|
if (position === this.view.childElementCount - 1) {
|
||||||
|
this.view.appendChild(abandoned.view)
|
||||||
|
} else {
|
||||||
|
this.view.insertBefore(abandoned.view, this.view.children[position])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Not found,insert
|
||||||
|
const newNode = DoricViewNode.create(this.context, model.type)
|
||||||
|
if (newNode === undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
newNode.viewId = childViewId
|
||||||
|
newNode.init(this)
|
||||||
|
newNode.blend(model.props)
|
||||||
|
this.childNodes[index] = newNode
|
||||||
|
this.view.insertBefore(newNode.view, this.view.children[index])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Insert
|
||||||
|
const newNode = DoricViewNode.create(this.context, model.type)
|
||||||
|
if (newNode === undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
newNode.viewId = childViewId
|
||||||
|
newNode.init(this)
|
||||||
|
newNode.blend(model.props)
|
||||||
|
this.childNodes.push(newNode)
|
||||||
|
this.view.appendChild(newNode.view)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
let size = this.childNodes.length
|
||||||
|
for (let idx = this.childViewIds.length; idx < size; idx++) {
|
||||||
|
this.view.removeChild(this.childNodes[idx].view)
|
||||||
|
}
|
||||||
|
this.childNodes = this.childNodes.slice(0, this.childViewIds.length)
|
||||||
|
}
|
||||||
|
|
||||||
|
blendSubNode(model: DVModel) {
|
||||||
|
this.getSubNodeById(model.id)?.blend(model.props)
|
||||||
|
}
|
||||||
|
|
||||||
|
getSubNodeById(viewId: string) {
|
||||||
|
return this.childNodes.filter(e => e.viewId === viewId)[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
64
doric-h5/tsconfig.json
Normal file
64
doric-h5/tsconfig.json
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
/* Basic Options */
|
||||||
|
// "incremental": true, /* Enable incremental compilation */
|
||||||
|
"target": "ES2015", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
||||||
|
"module": "es2015", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||||
|
"lib": [
|
||||||
|
"DOM"
|
||||||
|
], /* Specify library files to be included in the compilation. */
|
||||||
|
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||||
|
// "checkJs": true, /* Report errors in .js files. */
|
||||||
|
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||||
|
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||||
|
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||||
|
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||||
|
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||||
|
"outDir": "build/", /* Redirect output structure to the directory. */
|
||||||
|
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||||
|
// "composite": true, /* Enable project compilation */
|
||||||
|
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||||
|
// "removeComments": true, /* Do not emit comments to output. */
|
||||||
|
// "noEmit": true, /* Do not emit outputs. */
|
||||||
|
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||||
|
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||||
|
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||||
|
/* Strict Type-Checking Options */
|
||||||
|
"strict": true, /* Enable all strict type-checking options. */
|
||||||
|
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||||
|
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||||
|
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||||
|
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||||
|
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||||
|
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||||
|
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||||
|
/* Additional Checks */
|
||||||
|
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||||
|
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||||
|
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||||
|
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||||
|
/* Module Resolution Options */
|
||||||
|
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||||
|
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||||
|
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||||
|
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||||
|
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||||
|
// "types": [], /* Type declaration files to be included in compilation. */
|
||||||
|
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||||
|
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||||
|
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||||
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
|
/* Source Map Options */
|
||||||
|
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||||
|
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||||
|
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||||
|
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||||
|
/* Experimental Options */
|
||||||
|
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||||
|
"emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"**/*.ts",
|
||||||
|
]
|
||||||
|
}
|
Reference in New Issue
Block a user