nativescript-web-adapter 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +220 -168
- package/core/components/AbsoluteLayout.vue +11 -0
- package/core/components/ActionBar.vue +11 -0
- package/core/components/ActionItem.vue +11 -0
- package/core/components/ActivityIndicator.vue +15 -0
- package/core/components/Button.vue +41 -0
- package/core/components/DatePicker.vue +27 -0
- package/core/components/DockLayout.vue +23 -0
- package/core/components/FlexboxLayout.vue +11 -0
- package/core/components/Frame.vue +11 -0
- package/core/components/GridLayout.vue +85 -0
- package/core/components/HtmlView.vue +13 -0
- package/core/components/Image.vue +12 -0
- package/core/components/ImageCacheIt.vue +12 -0
- package/core/components/Label.vue +15 -0
- package/core/components/ListPicker.vue +21 -0
- package/core/components/ListView.vue +12 -0
- package/core/components/NavigationButton.vue +28 -0
- package/core/components/Page.vue +18 -0
- package/core/components/Placeholder.vue +11 -0
- package/core/components/Progress.vue +12 -0
- package/core/components/RootLayout.vue +11 -0
- package/core/components/ScrollView.vue +11 -0
- package/core/components/SearchBar.vue +22 -0
- package/core/components/SegmentedBar.vue +50 -0
- package/core/components/SegmentedBarItem.vue +21 -0
- package/core/components/Slider.vue +18 -0
- package/core/components/StackLayout.vue +11 -0
- package/core/components/Switch.vue +26 -0
- package/core/components/TabView.vue +48 -0
- package/core/components/TabViewItem.vue +27 -0
- package/core/components/TextField.vue +15 -0
- package/core/components/TextView.vue +18 -0
- package/core/components/TimePicker.vue +21 -0
- package/core/components/WebView.vue +13 -0
- package/core/components/WrapLayout.vue +11 -0
- package/core/components/index.js +3 -0
- package/core/components/index.ts +35 -0
- package/core/composables/dialogs.ts +31 -0
- package/core/composables/index.js +3 -0
- package/core/composables/index.ts +4 -0
- package/core/composables/useActionBar.js +7 -0
- package/core/composables/useActionBar.ts +19 -0
- package/core/composables/useFrame.js +8 -0
- package/core/composables/useFrame.ts +25 -0
- package/core/composables/usePage.js +8 -0
- package/core/composables/usePage.ts +25 -0
- package/core/env.d.ts +7 -0
- package/core/index.js +4 -0
- package/core/index.ts +85 -0
- package/core/types.ts +12 -0
- package/dist/nativescript-web-adapter.es.js +83 -0
- package/dist/nativescript-web-adapter.umd.js +1 -0
- package/dist/style.css +1 -0
- package/package.json +34 -46
- package/tools/cli.cjs +45 -0
- package/tools/create-web-platform.cjs +76 -0
- package/tools/create-web-platform.js +196 -0
- package/tools/modules/appPatch.cjs +27 -0
- package/tools/modules/copy.cjs +84 -0
- package/tools/modules/router.cjs +46 -0
- package/tools/modules/templates.cjs +130 -0
- package/tools/modules/transform.cjs +93 -0
- package/dist/core.cjs +0 -3
- package/dist/core.cjs.map +0 -1
- package/dist/core.js +0 -2
- package/dist/core.js.map +0 -1
- package/dist/index.cjs +0 -240
- package/dist/index.cjs.map +0 -1
- package/dist/index.js +0 -229
- package/dist/index.js.map +0 -1
- package/dist/types/core/index.d.ts +0 -8
- package/dist/types/index.d.ts +0 -1
- package/dist/types/vue/components/ActionBar.d.ts +0 -5
- package/dist/types/vue/components/Button.d.ts +0 -26
- package/dist/types/vue/components/FlexboxLayout.d.ts +0 -35
- package/dist/types/vue/components/Frame.d.ts +0 -3
- package/dist/types/vue/components/GridLayout.d.ts +0 -27
- package/dist/types/vue/components/ImageCacheIt.d.ts +0 -23
- package/dist/types/vue/components/Label.d.ts +0 -26
- package/dist/types/vue/components/Page.d.ts +0 -5
- package/dist/types/vue/components/StackLayout.d.ts +0 -5
- package/dist/types/vue/index.d.ts +0 -12
- package/dist/types/vue.d.ts +0 -169
- package/dist/vue.cjs +0 -240
- package/dist/vue.cjs.map +0 -1
- package/dist/vue.js +0 -229
- package/dist/vue.js.map +0 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Ref, ref } from 'vue';
|
|
2
|
+
|
|
3
|
+
export interface FrameState {
|
|
4
|
+
stack: Ref<any[]>;
|
|
5
|
+
push: (page: any) => void;
|
|
6
|
+
pop: () => any;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function useFrame(): FrameState {
|
|
10
|
+
const stack = ref<any[]>([]);
|
|
11
|
+
|
|
12
|
+
function push(page: any) {
|
|
13
|
+
stack.value.push(page);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function pop() {
|
|
17
|
+
return stack.value.pop();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
stack,
|
|
22
|
+
push,
|
|
23
|
+
pop
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Ref, ref } from 'vue';
|
|
2
|
+
|
|
3
|
+
export interface PageState {
|
|
4
|
+
isVisible: Ref<boolean>;
|
|
5
|
+
show: () => void;
|
|
6
|
+
hide: () => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function usePage(): PageState {
|
|
10
|
+
const isVisible = ref(true);
|
|
11
|
+
|
|
12
|
+
function show() {
|
|
13
|
+
isVisible.value = true;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function hide() {
|
|
17
|
+
isVisible.value = false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
isVisible,
|
|
22
|
+
show,
|
|
23
|
+
hide
|
|
24
|
+
};
|
|
25
|
+
}
|
package/core/env.d.ts
ADDED
package/core/index.js
ADDED
package/core/index.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Explicitly collect components and composables into objects so consumers
|
|
2
|
+
// can reference `core.components` and `core.composables` at runtime.
|
|
3
|
+
import ActionBar from './components/ActionBar.vue';
|
|
4
|
+
import Page from './components/Page.vue';
|
|
5
|
+
import Frame from './components/Frame.vue';
|
|
6
|
+
import StackLayout from './components/StackLayout.vue';
|
|
7
|
+
import GridLayout from './components/GridLayout.vue';
|
|
8
|
+
import FlexboxLayout from './components/FlexboxLayout.vue';
|
|
9
|
+
import WrapLayout from './components/WrapLayout.vue';
|
|
10
|
+
import ScrollView from './components/ScrollView.vue';
|
|
11
|
+
import Label from './components/Label.vue';
|
|
12
|
+
import Button from './components/Button.vue';
|
|
13
|
+
import Image from './components/Image.vue';
|
|
14
|
+
import HtmlView from './components/HtmlView.vue';
|
|
15
|
+
import ImageCacheIt from './components/ImageCacheIt.vue';
|
|
16
|
+
import TabView from './components/TabView.vue';
|
|
17
|
+
import TabViewItem from './components/TabViewItem.vue';
|
|
18
|
+
import RootLayout from './components/RootLayout.vue';
|
|
19
|
+
import DockLayout from './components/DockLayout.vue';
|
|
20
|
+
import AbsoluteLayout from './components/AbsoluteLayout.vue';
|
|
21
|
+
import ActionItem from './components/ActionItem.vue';
|
|
22
|
+
import NavigationButton from './components/NavigationButton.vue';
|
|
23
|
+
import ActivityIndicator from './components/ActivityIndicator.vue';
|
|
24
|
+
import DatePicker from './components/DatePicker.vue';
|
|
25
|
+
import TimePicker from './components/TimePicker.vue';
|
|
26
|
+
import ListPicker from './components/ListPicker.vue';
|
|
27
|
+
import ListView from './components/ListView.vue';
|
|
28
|
+
import Placeholder from './components/Placeholder.vue';
|
|
29
|
+
import Progress from './components/Progress.vue';
|
|
30
|
+
import SearchBar from './components/SearchBar.vue';
|
|
31
|
+
import SegmentedBar from './components/SegmentedBar.vue';
|
|
32
|
+
import SegmentedBarItem from './components/SegmentedBarItem.vue';
|
|
33
|
+
import Slider from './components/Slider.vue';
|
|
34
|
+
import SwitchComp from './components/Switch.vue';
|
|
35
|
+
import TextField from './components/TextField.vue';
|
|
36
|
+
import TextView from './components/TextView.vue';
|
|
37
|
+
import WebView from './components/WebView.vue';
|
|
38
|
+
|
|
39
|
+
export const components = {
|
|
40
|
+
ActionBar,
|
|
41
|
+
Page,
|
|
42
|
+
Frame,
|
|
43
|
+
StackLayout,
|
|
44
|
+
GridLayout,
|
|
45
|
+
FlexboxLayout,
|
|
46
|
+
WrapLayout,
|
|
47
|
+
ScrollView,
|
|
48
|
+
Label,
|
|
49
|
+
Button,
|
|
50
|
+
Image,
|
|
51
|
+
HtmlView,
|
|
52
|
+
ImageCacheIt,
|
|
53
|
+
TabView,
|
|
54
|
+
TabViewItem,
|
|
55
|
+
RootLayout,
|
|
56
|
+
DockLayout,
|
|
57
|
+
AbsoluteLayout,
|
|
58
|
+
ActionItem,
|
|
59
|
+
NavigationButton,
|
|
60
|
+
ActivityIndicator,
|
|
61
|
+
DatePicker,
|
|
62
|
+
TimePicker,
|
|
63
|
+
ListPicker,
|
|
64
|
+
ListView,
|
|
65
|
+
Placeholder,
|
|
66
|
+
Progress,
|
|
67
|
+
SearchBar,
|
|
68
|
+
SegmentedBar,
|
|
69
|
+
SegmentedBarItem,
|
|
70
|
+
Slider,
|
|
71
|
+
Switch: SwitchComp,
|
|
72
|
+
TextField,
|
|
73
|
+
TextView,
|
|
74
|
+
WebView,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
import * as composablesNS from './composables';
|
|
78
|
+
export const composables = composablesNS;
|
|
79
|
+
|
|
80
|
+
// Re-export types for convenience
|
|
81
|
+
export * from './types';
|
|
82
|
+
|
|
83
|
+
// Also provide the original named exports for compatibility
|
|
84
|
+
export { ActionBar, Page, Frame, StackLayout, GridLayout, FlexboxLayout, WrapLayout, ScrollView, Label, Button, Image, HtmlView, ImageCacheIt, TabView, TabViewItem };
|
|
85
|
+
export { RootLayout, DockLayout, AbsoluteLayout, ActionItem, NavigationButton, ActivityIndicator, DatePicker, TimePicker, ListPicker, ListView, Placeholder, Progress, SearchBar, SegmentedBar, SegmentedBarItem, Slider, SwitchComp as Switch, TextField, TextView, WebView };
|
package/core/types.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { DefineComponent } from 'vue';
|
|
2
|
+
import type { FrameState } from './composables/useFrame';
|
|
3
|
+
import type { PageState } from './composables/usePage';
|
|
4
|
+
import type { ActionBarState } from './composables/useActionBar';
|
|
5
|
+
|
|
6
|
+
// 重新导出Vue组件类型
|
|
7
|
+
export type ActionBarComponent = DefineComponent;
|
|
8
|
+
export type PageComponent = DefineComponent;
|
|
9
|
+
export type FrameComponent = DefineComponent;
|
|
10
|
+
|
|
11
|
+
// 重新导出composables类型
|
|
12
|
+
export type { FrameState, PageState, ActionBarState };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { defineComponent as r, createElementBlock as s, openBlock as c, renderSlot as a, ref as u } from "vue";
|
|
2
|
+
const f = { class: "ns-actionbar" }, p = /* @__PURE__ */ r({
|
|
3
|
+
name: "ActionBar",
|
|
4
|
+
__name: "ActionBar",
|
|
5
|
+
setup(e) {
|
|
6
|
+
return (t, o) => (c(), s("header", f, [
|
|
7
|
+
a(t.$slots, "default", {}, void 0, !0)
|
|
8
|
+
]));
|
|
9
|
+
}
|
|
10
|
+
}), _ = (e, t) => {
|
|
11
|
+
const o = e.__vccOpts || e;
|
|
12
|
+
for (const [n, d] of t)
|
|
13
|
+
o[n] = d;
|
|
14
|
+
return o;
|
|
15
|
+
}, m = /* @__PURE__ */ _(p, [["__scopeId", "data-v-f29dfd84"]]), v = { class: "ns-page" }, b = /* @__PURE__ */ r({
|
|
16
|
+
name: "Page",
|
|
17
|
+
__name: "Page",
|
|
18
|
+
setup(e) {
|
|
19
|
+
return (t, o) => (c(), s("div", v, [
|
|
20
|
+
a(t.$slots, "default", {}, void 0, !0)
|
|
21
|
+
]));
|
|
22
|
+
}
|
|
23
|
+
}), g = /* @__PURE__ */ _(b, [["__scopeId", "data-v-87719fa5"]]), h = { class: "ns-frame" }, $ = /* @__PURE__ */ r({
|
|
24
|
+
name: "Frame",
|
|
25
|
+
__name: "Frame",
|
|
26
|
+
setup(e) {
|
|
27
|
+
return (t, o) => (c(), s("div", h, [
|
|
28
|
+
a(t.$slots, "default", {}, void 0, !0)
|
|
29
|
+
]));
|
|
30
|
+
}
|
|
31
|
+
}), O = /* @__PURE__ */ _($, [["__scopeId", "data-v-a66356e7"]]), i = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
32
|
+
__proto__: null,
|
|
33
|
+
ActionBar: m,
|
|
34
|
+
Frame: O,
|
|
35
|
+
Page: g
|
|
36
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
37
|
+
function P() {
|
|
38
|
+
const e = u("");
|
|
39
|
+
function t(o) {
|
|
40
|
+
e.value = o;
|
|
41
|
+
}
|
|
42
|
+
return { title: e, setTitle: t };
|
|
43
|
+
}
|
|
44
|
+
function j() {
|
|
45
|
+
const e = u(!0);
|
|
46
|
+
function t() {
|
|
47
|
+
e.value = !0;
|
|
48
|
+
}
|
|
49
|
+
function o() {
|
|
50
|
+
e.value = !1;
|
|
51
|
+
}
|
|
52
|
+
return { isVisible: e, show: t, hide: o };
|
|
53
|
+
}
|
|
54
|
+
function y() {
|
|
55
|
+
const e = u([]);
|
|
56
|
+
function t(n) {
|
|
57
|
+
e.value.push(n);
|
|
58
|
+
}
|
|
59
|
+
function o() {
|
|
60
|
+
return e.value.pop();
|
|
61
|
+
}
|
|
62
|
+
return { stack: e, push: t, pop: o };
|
|
63
|
+
}
|
|
64
|
+
const l = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
65
|
+
__proto__: null,
|
|
66
|
+
useActionBar: P,
|
|
67
|
+
useFrame: y,
|
|
68
|
+
usePage: j
|
|
69
|
+
}, Symbol.toStringTag, { value: "Module" })), x = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
70
|
+
__proto__: null,
|
|
71
|
+
components: i,
|
|
72
|
+
composables: l
|
|
73
|
+
}, Symbol.toStringTag, { value: "Module" })), B = {
|
|
74
|
+
install(e) {
|
|
75
|
+
Object.entries(i || {}).forEach(([t, o]) => {
|
|
76
|
+
e.component(t, o);
|
|
77
|
+
}), e.config.globalProperties.$ns = l || {};
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
export {
|
|
81
|
+
x as core,
|
|
82
|
+
B as default
|
|
83
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(r,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(r=typeof globalThis<"u"?globalThis:r||self,e(r.NativeScriptWebAdapter={},r.Vue))})(this,function(r,e){"use strict";const l={class:"ns-actionbar"},_=e.defineComponent({name:"ActionBar",__name:"ActionBar",setup(t){return(n,o)=>(e.openBlock(),e.createElementBlock("header",l,[e.renderSlot(n.$slots,"default",{},void 0,!0)]))}}),c=(t,n)=>{const o=t.__vccOpts||t;for(const[s,$]of n)o[s]=$;return o},u=c(_,[["__scopeId","data-v-f29dfd84"]]),d={class:"ns-page"},f=c(e.defineComponent({name:"Page",__name:"Page",setup(t){return(n,o)=>(e.openBlock(),e.createElementBlock("div",d,[e.renderSlot(n.$slots,"default",{},void 0,!0)]))}}),[["__scopeId","data-v-87719fa5"]]),p={class:"ns-frame"},a=Object.freeze(Object.defineProperty({__proto__:null,ActionBar:u,Frame:c(e.defineComponent({name:"Frame",__name:"Frame",setup(t){return(n,o)=>(e.openBlock(),e.createElementBlock("div",p,[e.renderSlot(n.$slots,"default",{},void 0,!0)]))}}),[["__scopeId","data-v-a66356e7"]]),Page:f},Symbol.toStringTag,{value:"Module"}));function m(){const t=e.ref("");function n(o){t.value=o}return{title:t,setTitle:n}}function b(){const t=e.ref(!0);function n(){t.value=!0}function o(){t.value=!1}return{isVisible:t,show:n,hide:o}}function g(){const t=e.ref([]);function n(s){t.value.push(s)}function o(){return t.value.pop()}return{stack:t,push:n,pop:o}}const i=Object.freeze(Object.defineProperty({__proto__:null,useActionBar:m,useFrame:g,usePage:b},Symbol.toStringTag,{value:"Module"})),h=Object.freeze(Object.defineProperty({__proto__:null,components:a,composables:i},Symbol.toStringTag,{value:"Module"})),S={install(t){Object.entries(a||{}).forEach(([n,o])=>{t.component(n,o)}),t.config.globalProperties.$ns=i||{}}};r.core=h,r.default=S,Object.defineProperties(r,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.ns-actionbar[data-v-f29dfd84]{background:#1f1140;color:#fff;padding:12px}.ns-page[data-v-87719fa5]{top:0;left:0;position:absolute;width:100%;min-height:100%;padding:0}
|
package/package.json
CHANGED
|
@@ -1,59 +1,47 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nativescript-web-adapter",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"
|
|
5
|
-
"type": "git",
|
|
6
|
-
"url": "https://github.com/ponzS/NativeScript-for-web.git"
|
|
7
|
-
},
|
|
8
|
-
"bugs": {
|
|
9
|
-
"url": "https://github.com/ponzS/NativeScript-for-web/issues"
|
|
10
|
-
},
|
|
11
|
-
"homepage": "https://github.com/ponzS/NativeScript-for-web#readme",
|
|
12
|
-
"files": [
|
|
13
|
-
"dist",
|
|
14
|
-
"README.md"
|
|
15
|
-
],
|
|
16
|
-
"description": "Web adapter for NativeScript UI components (Vue 3)",
|
|
17
|
-
"license": "MIT",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "Web adapter for NativeScript applications",
|
|
18
5
|
"type": "module",
|
|
19
|
-
"main": "dist/
|
|
20
|
-
"module": "dist/
|
|
21
|
-
"types": "dist/
|
|
6
|
+
"main": "./dist/nativescript-web-adapter.umd.js",
|
|
7
|
+
"module": "./dist/nativescript-web-adapter.es.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
22
9
|
"exports": {
|
|
23
10
|
".": {
|
|
24
|
-
"import": "./dist/
|
|
25
|
-
"require": "./dist/
|
|
26
|
-
"types": "./dist/
|
|
27
|
-
},
|
|
28
|
-
"./vue": {
|
|
29
|
-
"import": "./dist/vue.js",
|
|
30
|
-
"require": "./dist/vue.cjs",
|
|
31
|
-
"types": "./dist/types/vue.d.ts"
|
|
32
|
-
},
|
|
33
|
-
"./core": {
|
|
34
|
-
"import": "./dist/core.js",
|
|
35
|
-
"require": "./dist/core.cjs",
|
|
36
|
-
"types": "./dist/types/core/index.d.ts"
|
|
11
|
+
"import": "./dist/nativescript-web-adapter.es.js",
|
|
12
|
+
"require": "./dist/nativescript-web-adapter.umd.js",
|
|
13
|
+
"types": "./dist/index.d.ts"
|
|
37
14
|
}
|
|
38
15
|
},
|
|
39
16
|
"scripts": {
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"prepublishOnly": "npm run build
|
|
17
|
+
"create:web": "node tools/create-web-platform.cjs",
|
|
18
|
+
"dev": "vite",
|
|
19
|
+
"build": "vite build",
|
|
20
|
+
"preview": "vite preview",
|
|
21
|
+
"type-check": "vue-tsc --noEmit",
|
|
22
|
+
"prepublishOnly": "npm run build"
|
|
46
23
|
},
|
|
47
|
-
"
|
|
48
|
-
"
|
|
24
|
+
"bin": {
|
|
25
|
+
"ns-web": "./tools/cli.cjs"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist",
|
|
29
|
+
"tools",
|
|
30
|
+
"templates",
|
|
31
|
+
"core"
|
|
32
|
+
],
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"vue": "^3.4.0",
|
|
35
|
+
"commander": "^11.0.0"
|
|
49
36
|
},
|
|
50
37
|
"devDependencies": {
|
|
51
|
-
"@
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
|
|
57
|
-
|
|
38
|
+
"@types/node": "^20.0.0",
|
|
39
|
+
"typescript": "^5.0.0",
|
|
40
|
+
"@vitejs/plugin-vue": "^5.0.0",
|
|
41
|
+
"vite": "^5.0.0",
|
|
42
|
+
"vue-tsc": "^1.8.0"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"vue": "^3.0.0"
|
|
58
46
|
}
|
|
59
47
|
}
|
package/tools/cli.cjs
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { program } = require('commander');
|
|
3
|
+
const { createWebPlatform } = require('./create-web-platform.cjs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { execSync } = require('child_process');
|
|
6
|
+
|
|
7
|
+
program
|
|
8
|
+
.name('ns-web')
|
|
9
|
+
.description('CLI工具用于创建和管理NativeScript应用的web平台')
|
|
10
|
+
.version('1.0.0');
|
|
11
|
+
|
|
12
|
+
program
|
|
13
|
+
.command('init')
|
|
14
|
+
.description('为NativeScript项目初始化web平台支持')
|
|
15
|
+
.action(async () => {
|
|
16
|
+
await createWebPlatform();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
program
|
|
20
|
+
.command('build')
|
|
21
|
+
.description('生成web平台并在 platforms/web 内构建')
|
|
22
|
+
.option('--skip-install', '跳过依赖安装')
|
|
23
|
+
.action(async (opts) => {
|
|
24
|
+
await createWebPlatform();
|
|
25
|
+
const webDir = path.join(process.cwd(), 'platforms', 'web');
|
|
26
|
+
if (!opts.skipInstall) {
|
|
27
|
+
execSync('npm install', { stdio: 'inherit', cwd: webDir });
|
|
28
|
+
}
|
|
29
|
+
execSync('npm run build', { stdio: 'inherit', cwd: webDir });
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
program
|
|
33
|
+
.command('dev')
|
|
34
|
+
.description('生成web平台并在 platforms/web 内启动开发服务器')
|
|
35
|
+
.option('--skip-install', '跳过依赖安装')
|
|
36
|
+
.action(async (opts) => {
|
|
37
|
+
await createWebPlatform();
|
|
38
|
+
const webDir = path.join(process.cwd(), 'platforms', 'web');
|
|
39
|
+
if (!opts.skipInstall) {
|
|
40
|
+
execSync('npm install', { stdio: 'inherit', cwd: webDir });
|
|
41
|
+
}
|
|
42
|
+
execSync('npm run dev', { stdio: 'inherit', cwd: webDir });
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
program.parse();
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
console.log('[web-adapter] create-web-platform.cjs 脚本已启动');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
// 模块入口(全部实现下沉到 modules/*)
|
|
6
|
+
const copy = require('./modules/copy.cjs');
|
|
7
|
+
const transform = require('./modules/transform.cjs');
|
|
8
|
+
const routerGen = require('./modules/router.cjs');
|
|
9
|
+
const appPatch = require('./modules/appPatch.cjs');
|
|
10
|
+
const templates = require('./modules/templates.cjs');
|
|
11
|
+
|
|
12
|
+
function createWebPlatform(options = {}) {
|
|
13
|
+
const adapterDir = path.resolve(__dirname, '..');
|
|
14
|
+
// 当作为 node_modules 使用时,项目根应为当前工作目录
|
|
15
|
+
const projectRoot = options.projectRoot ? path.resolve(options.projectRoot) : process.cwd();
|
|
16
|
+
const platformsDir = path.join(projectRoot, 'platforms');
|
|
17
|
+
const webDir = path.join(platformsDir, 'web');
|
|
18
|
+
const srcDir = path.join(projectRoot, 'src');
|
|
19
|
+
|
|
20
|
+
console.log('[web-adapter] 项目根目录:', projectRoot);
|
|
21
|
+
console.log('[web-adapter] platforms 目录:', platformsDir);
|
|
22
|
+
console.log('[web-adapter] web 目录:', webDir);
|
|
23
|
+
console.log('[web-adapter] src 目录:', srcDir);
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
if (!fs.existsSync(webDir)) {
|
|
27
|
+
fs.mkdirSync(webDir, { recursive: true });
|
|
28
|
+
console.log('[web-adapter] 已创建 web 目录');
|
|
29
|
+
} else {
|
|
30
|
+
console.log('[web-adapter] web 目录已存在');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// 1) 复制源码(仅脚本层转换,保留模板标签)
|
|
34
|
+
copy.copySourceFiles(srcDir, path.join(webDir, 'src'), transform.transformContent);
|
|
35
|
+
console.log('[web-adapter] 已复制 src 源代码');
|
|
36
|
+
|
|
37
|
+
// 2) 复制适配器 web 组件与 composables
|
|
38
|
+
const adapterComponentsDir = path.join(adapterDir, 'core', 'components');
|
|
39
|
+
const targetComponentsDir = path.join(webDir, 'src', 'components', 'websfc');
|
|
40
|
+
copy.copyAdapterComponents(adapterComponentsDir, targetComponentsDir);
|
|
41
|
+
console.log('[web-adapter] 已复制适配器组件到 websfc');
|
|
42
|
+
|
|
43
|
+
const adapterComposablesDir = path.join(adapterDir, 'core', 'composables');
|
|
44
|
+
const targetComposablesDir = path.join(webDir, 'src', 'composables', 'websfc');
|
|
45
|
+
copy.copyAdapterComposables(adapterComposablesDir, targetComposablesDir);
|
|
46
|
+
console.log('[web-adapter] 已复制适配器 composables 到 websfc');
|
|
47
|
+
|
|
48
|
+
// 3) 写入 web 项目模板(index.html、package.json、vite.config、postcss、tailwind、App.vue)
|
|
49
|
+
templates.createWebPlatformFiles(webDir);
|
|
50
|
+
console.log('[web-adapter] 已生成 web 平台模板与配置');
|
|
51
|
+
|
|
52
|
+
// 4) 生成路由(根据 pages 目录)
|
|
53
|
+
const routerDirPath = path.join(webDir, 'src', 'router');
|
|
54
|
+
if (!fs.existsSync(routerDirPath)) {
|
|
55
|
+
fs.mkdirSync(routerDirPath, { recursive: true });
|
|
56
|
+
}
|
|
57
|
+
const routerContent = routerGen.buildRouterFromPages(webDir);
|
|
58
|
+
fs.writeFileSync(path.join(routerDirPath, 'index.ts'), routerContent, 'utf8');
|
|
59
|
+
console.log('[web-adapter] 已创建路由配置');
|
|
60
|
+
|
|
61
|
+
// 5) 修补 app.ts:注册所有 Web 适配组件并挂载应用
|
|
62
|
+
appPatch.patchAppForWeb(webDir);
|
|
63
|
+
console.log('[web-adapter] 正在安装依赖项...');
|
|
64
|
+
|
|
65
|
+
// 如需安装依赖,可在此调用(默认跳过以加快生成速度)
|
|
66
|
+
// installDependencies(webDir);
|
|
67
|
+
} catch (err) {
|
|
68
|
+
console.error('[web-adapter] 生成 web 平台时出错:', err);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = { createWebPlatform };
|
|
73
|
+
|
|
74
|
+
if (require.main === module) {
|
|
75
|
+
createWebPlatform();
|
|
76
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
// 文件扩展名应为 .cjs 以兼容 CommonJS require
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
// CommonJS export will be set at the end of the file
|
|
7
|
+
function createWebPlatform(options = {}) {
|
|
8
|
+
const cwd = process.cwd();
|
|
9
|
+
const platformsDir = path.join(cwd, 'platforms');
|
|
10
|
+
const webDir = path.join(platformsDir, 'web');
|
|
11
|
+
const srcDir = path.join(cwd, 'src');
|
|
12
|
+
|
|
13
|
+
// 确保platforms/web目录存在
|
|
14
|
+
if (!fs.existsSync(webDir)) {
|
|
15
|
+
fs.mkdirSync(webDir, { recursive: true });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// 复制源代码到web平台
|
|
19
|
+
copySourceFiles(srcDir, path.join(webDir, 'src'));
|
|
20
|
+
// 复制适配器的 composables 到 web 项目的 src/composables/websfc
|
|
21
|
+
try {
|
|
22
|
+
const adapterComposablesDir = path.join(__dirname, '..', 'core', 'composables');
|
|
23
|
+
const targetComposablesDir = path.join(webDir, 'src', 'composables', 'websfc');
|
|
24
|
+
copyAdapterDir(adapterComposablesDir, targetComposablesDir);
|
|
25
|
+
} catch (err) {
|
|
26
|
+
console.warn('[web-adapter] 复制适配器 composables 失败:', err);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// 创建web平台特定的文件
|
|
30
|
+
createWebPlatformFiles(webDir);
|
|
31
|
+
|
|
32
|
+
// 安装依赖
|
|
33
|
+
installDependencies(webDir);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function copyAdapterDir(srcDir, destDir) {
|
|
37
|
+
if (!fs.existsSync(srcDir)) {
|
|
38
|
+
// no composables to copy
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (!fs.existsSync(destDir)) {
|
|
42
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
43
|
+
}
|
|
44
|
+
const entries = fs.readdirSync(srcDir, { withFileTypes: true });
|
|
45
|
+
for (const entry of entries) {
|
|
46
|
+
const srcPath = path.join(srcDir, entry.name);
|
|
47
|
+
const destPath = path.join(destDir, entry.name);
|
|
48
|
+
if (entry.isDirectory()) {
|
|
49
|
+
copyAdapterDir(srcPath, destPath);
|
|
50
|
+
} else {
|
|
51
|
+
try {
|
|
52
|
+
fs.copyFileSync(srcPath, destPath);
|
|
53
|
+
} catch (err) {
|
|
54
|
+
console.error('[web-adapter] 复制文件失败:', srcPath, err);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function copySourceFiles(src, dest) {
|
|
61
|
+
if (!fs.existsSync(dest)) {
|
|
62
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
66
|
+
|
|
67
|
+
for (const entry of entries) {
|
|
68
|
+
const srcPath = path.join(src, entry.name);
|
|
69
|
+
const destPath = path.join(dest, entry.name);
|
|
70
|
+
|
|
71
|
+
if (entry.isDirectory()) {
|
|
72
|
+
copySourceFiles(srcPath, destPath);
|
|
73
|
+
} else {
|
|
74
|
+
// 转换并复制文件
|
|
75
|
+
let content = fs.readFileSync(srcPath, 'utf8');
|
|
76
|
+
content = transformContent(content);
|
|
77
|
+
fs.writeFileSync(destPath, content);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function transformContent(content) {
|
|
83
|
+
// 将nativescript特定的导入替换为web版本
|
|
84
|
+
content = content.replace(/from\s+['"](nativescript-vue)['"]/g, "from 'vue'");
|
|
85
|
+
content = content.replace(/from\s+['"]([@]nativescript\/core)['"]/g, "from 'nativescript-web-adapter'");
|
|
86
|
+
|
|
87
|
+
// 移除registerElement调用
|
|
88
|
+
content = content.replace(/registerElement\([^)]+\);?\n?/g, '// registerElement removed for web\n');
|
|
89
|
+
|
|
90
|
+
// 移除平台特定代码
|
|
91
|
+
if (content.includes('__ANDROID__') || content.includes('Application.launchEvent')) {
|
|
92
|
+
content = content.replace(/Application\.on[\s\S]*?}\);/g, '');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return content;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function createWebPlatformFiles(webDir) {
|
|
99
|
+
// 创建index.html
|
|
100
|
+
const indexHtml = `<!DOCTYPE html>
|
|
101
|
+
<html lang="en">
|
|
102
|
+
<head>
|
|
103
|
+
<meta charset="UTF-8" />
|
|
104
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
105
|
+
<title>NS Vue Web</title>
|
|
106
|
+
</head>
|
|
107
|
+
<body>
|
|
108
|
+
<div id="app"></div>
|
|
109
|
+
<script type="module" src="/src/app.ts"></script>
|
|
110
|
+
</body>
|
|
111
|
+
</html>`;
|
|
112
|
+
|
|
113
|
+
fs.writeFileSync(path.join(webDir, 'index.html'), indexHtml);
|
|
114
|
+
|
|
115
|
+
// 创建web平台的package.json
|
|
116
|
+
const packageJson = {
|
|
117
|
+
name: "ns-vue-web-platform",
|
|
118
|
+
private: true,
|
|
119
|
+
scripts: {
|
|
120
|
+
dev: "vite",
|
|
121
|
+
build: "vite build"
|
|
122
|
+
},
|
|
123
|
+
dependencies: {
|
|
124
|
+
"vue": "^3.4.0",
|
|
125
|
+
"nativescript-web-adapter": "file:../../nativescript-web-adapter"
|
|
126
|
+
},
|
|
127
|
+
devDependencies: {
|
|
128
|
+
"@vitejs/plugin-vue": "^5.0.0",
|
|
129
|
+
"typescript": "^5.0.0",
|
|
130
|
+
"vite": "^5.0.0",
|
|
131
|
+
"autoprefixer": "^10.4.16",
|
|
132
|
+
"postcss": "^8.4.31",
|
|
133
|
+
"tailwindcss": "^3.4.0"
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
fs.writeFileSync(
|
|
138
|
+
path.join(webDir, 'package.json'),
|
|
139
|
+
JSON.stringify(packageJson, null, 2)
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
// 创建vite.config.ts(设置 dev server 端口为 3005,避免冲突)
|
|
143
|
+
const viteConfig = `import { defineConfig } from 'vite';
|
|
144
|
+
import vue from '@vitejs/plugin-vue';
|
|
145
|
+
import path from 'path';
|
|
146
|
+
|
|
147
|
+
export default defineConfig({
|
|
148
|
+
plugins: [vue()],
|
|
149
|
+
resolve: {
|
|
150
|
+
alias: {
|
|
151
|
+
'@': path.resolve(__dirname, './src'),
|
|
152
|
+
'@nativescript/core': 'nativescript-web-adapter'
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
server: {
|
|
156
|
+
port: 3005,
|
|
157
|
+
strictPort: true
|
|
158
|
+
}
|
|
159
|
+
});`;
|
|
160
|
+
|
|
161
|
+
fs.writeFileSync(path.join(webDir, 'vite.config.ts'), viteConfig);
|
|
162
|
+
|
|
163
|
+
// 创建postcss.config.js
|
|
164
|
+
const postcssConfig = `module.exports = {
|
|
165
|
+
plugins: {
|
|
166
|
+
tailwindcss: {},
|
|
167
|
+
autoprefixer: {},
|
|
168
|
+
},
|
|
169
|
+
};`;
|
|
170
|
+
|
|
171
|
+
fs.writeFileSync(path.join(webDir, 'postcss.config.js'), postcssConfig);
|
|
172
|
+
|
|
173
|
+
// 创建tailwind.config.js
|
|
174
|
+
const tailwindConfig = `/** @type {import('tailwindcss').Config} */
|
|
175
|
+
module.exports = {
|
|
176
|
+
content: [
|
|
177
|
+
"./index.html",
|
|
178
|
+
"./src/**/*.{vue,js,ts,jsx,tsx}",
|
|
179
|
+
],
|
|
180
|
+
theme: {
|
|
181
|
+
extend: {},
|
|
182
|
+
},
|
|
183
|
+
plugins: [],
|
|
184
|
+
};`;
|
|
185
|
+
|
|
186
|
+
fs.writeFileSync(path.join(webDir, 'tailwind.config.js'), tailwindConfig);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function installDependencies(webDir) {
|
|
190
|
+
const { execSync } = require('child_process');
|
|
191
|
+
execSync('npm install', { cwd: webDir, stdio: 'inherit' });
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
module.exports = {
|
|
195
|
+
createWebPlatform
|
|
196
|
+
};
|