@sap-ux/preview-middleware 0.4.5 → 0.5.0

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 CHANGED
@@ -11,10 +11,15 @@ It hosts a local Fiori launchpad based on your configuration as well as offers a
11
11
  | `flp.intent` | | | Optional intent to be used for the application |
12
12
  | `flp.intent.object` | `string` | `app` | Optional intent object |
13
13
  | `flp.intent.action` | `string` | `preview` | Optional intent action |
14
- | `flp.apps` | `array` | `[]` | Optional additional local apps that are available in local Fiori launchpad |
15
- | `flp.libs` | `boolean` | `undefined` | Optional flag to add a generic script fetching the paths of used libraries not available in UI5. To disable set it to `false`, if not set, then the project is checked for a `load-reuse-libs` script and if available the libraries are fetched as well. |
14
+ | `flp.apps` | `array` | `undefined` | Optional additional local apps that are available in local Fiori launchpad |
15
+ | `flp.libs` | `boolean` | `undefined` | Optional flag to add a generic script fetching the paths of used libraries not available in UI5. To disable set it to `false`, if not set, then the project is checked for a `load-reuse-libs` script and if available the libraries are fetched as well. |
16
16
  | `adp.target` | | | Required configuration for adaptation projects defining the connected backend |
17
17
  | `adp.ignoreCertErrors` | `boolean` | `false` | Optional setting to ignore certification validation errors when working with e.g. development systems with self signed certificates |
18
+ | `rta` | | | Optional configuration allowing to add mount points for runtime adaptation |
19
+ | `rta.layer` | `string` | `(calculated)` | Optional property for defining the runtime adaptation layer for changes (default is `CUSTOMER_BASE` or read from the project for adaptation projects) |
20
+ | `rta.editors` | `array` | `undefined` | Optional list of mount points for editing |
21
+
22
+
18
23
  | `debug` | `boolean` | `false` | Enables debug output |
19
24
 
20
25
  ### `flp.apps`
@@ -35,6 +40,13 @@ Array of additional application configurations:
35
40
  | `client` | `string` optional | sap-client parameter |
36
41
  | `scp` | `boolean` optional | If set to true the proxy will execute the required OAuth routine for the ABAP environment on SAP BTP |
37
42
 
43
+ ### `rta.editors`
44
+ | Option | Type | Description |
45
+ | --------------- | -------------------| -----------------------------------------------------------------------------------------------|
46
+ | `path` | `string` mandatory | The mount point to be used for the editor. |
47
+ | `developerMode` | `boolean` optional | Enables/disables the runtime adaptation developer mode (only supported for adaptation projects |
48
+
49
+
38
50
  ## Usage
39
51
  The middleware can be used without configuration. However, since the middleware intercepts a few requests that might otherwise be handled by a different middleware, it is strongly recommended to run other file serving middlewares after the `preview-middleware` e.g. `backend-proxy-middleware` and `ui5-proxy-middleware` (and the corresponding middlewares in the `@sap/ux-ui5-tooling`).
40
52
  Example: [./test/fixtures/simple-app/ui5.yaml](./test/fixtures/simple-app/ui5.yaml)
@@ -75,8 +87,23 @@ server:
75
87
  target: /apps/other-app
76
88
  ```
77
89
 
90
+ ### Runtime Adaptation Support
91
+ If you want to create variants as part of your application, then you can create an additional mount point allowing to created and edit variants.
92
+ ```Yaml
93
+ server:
94
+ customMiddleware:
95
+ - name: preview-middleware
96
+ afterMiddleware: compression
97
+ configuration:
98
+ rta:
99
+ layer: CUSTOMER_BASE
100
+ editors:
101
+ - path: /local/variant-editor.html
102
+ ```
103
+
104
+
78
105
  ### Adaptation Project
79
- If you want to use the middleware in an adaption project, the additional `adp` object needs to be configured. This example would preview a local adaptation project merged with its reference application from the target system at `http://sap.example` and it will ignore certification validation errors.
106
+ If you want to use the middleware in an adaption project, the additional `adp` object needs to be configured. This example would preview a local adaptation project merged with its reference application from the target system at `http://sap.example` and it will ignore certification validation errors. For adaptation projects, it is also recommended to add the `rta` configuration allowing to edit the project.
80
107
  ```Yaml
81
108
  server:
82
109
  customMiddleware:
@@ -87,11 +114,16 @@ server:
87
114
  target:
88
115
  url: http://sap.example
89
116
  ignoreCertErrors: true
117
+ rta:
118
+ editors:
119
+ - path: /adp/editor.html
120
+ developerMode: true
90
121
  ```
122
+
91
123
  ### Programmatic Usage
92
124
  Alternatively you can use the underlying middleware fuction programmatically, e.g. for the case when you want to incorporate the `preview-middleware` functionality in your own middleware.
93
125
 
94
- ```
126
+ ```typescript
95
127
  import { FlpSandbox } from '@sap-ux/preview-middleware';
96
128
  const flp = new FlpSandbox(flpConfig, rootProject, middlewareUtil, logger);
97
129
  const files = await resources.rootProject.byGlob('/manifest.json');
@@ -99,7 +131,7 @@ flp.init(JSON.parse(await files[0].getString()));
99
131
 
100
132
  return flp.router
101
133
  ```
102
- - `flpConfig` - the FLP configuration
134
+ - `flpConfig` - the middleware configuration
103
135
  - `rootProject` - [Reader](https://sap.github.io/ui5-tooling/stable/api/@ui5_fs_AbstractReader.html) to access resources of the root project
104
136
  - `middlewareUtil` - [MiddlewareUtil](https://sap.github.io/ui5-tooling/v3/api/@ui5_server_middleware_MiddlewareUtil.html) of the UI5 server
105
- - `logger` - Logger instance for use in the middleware.
137
+ - `logger` - Logger instance for use in the middleware.
@@ -1,6 +1,6 @@
1
1
  import type { ReaderCollection } from '@ui5/fs';
2
2
  import type { Router } from 'express';
3
- import type { App, FlpConfig } from '../types';
3
+ import type { App, FlpConfig, MiddlewareConfig, RtaConfig } from '../types';
4
4
  import type { Logger } from '@sap-ux/logger';
5
5
  import type { MiddlewareUtils } from '@ui5/server';
6
6
  import type { Manifest, UI5FlexLayer } from '@sap-ux/project-access';
@@ -33,8 +33,10 @@ export interface TemplateConfig {
33
33
  resources: Record<string, string>;
34
34
  };
35
35
  flex?: {
36
+ [key: string]: unknown;
36
37
  layer: UI5FlexLayer;
37
38
  developerMode: boolean;
39
+ pluginScript?: string;
38
40
  };
39
41
  locateReuseLibsScript?: boolean;
40
42
  }
@@ -47,6 +49,7 @@ export declare class FlpSandbox {
47
49
  private readonly logger;
48
50
  protected templateConfig: TemplateConfig;
49
51
  readonly config: FlpConfig;
52
+ readonly rta?: RtaConfig;
50
53
  readonly router: EnhancedRouter;
51
54
  /**
52
55
  * Constructor setting defaults and keeping reference to workspace resources.
@@ -56,7 +59,7 @@ export declare class FlpSandbox {
56
59
  * @param utils middleware utilities provided by the UI5 CLI
57
60
  * @param logger logger instance
58
61
  */
59
- constructor(config: Partial<FlpConfig>, project: ReaderCollection, utils: MiddlewareUtils, logger: Logger);
62
+ constructor(config: Partial<MiddlewareConfig>, project: ReaderCollection, utils: MiddlewareUtils, logger: Logger);
60
63
  /**
61
64
  * Initialize the FLP sandbox router.
62
65
  *
@@ -65,6 +68,12 @@ export declare class FlpSandbox {
65
68
  * @param resources optional additional resource mappings
66
69
  */
67
70
  init(manifest: Manifest, componentId?: string, resources?: Record<string, string>): Promise<void>;
71
+ /**
72
+ * Add additional routes for configured editors.
73
+ *
74
+ * @param rta runtime authoring configuration
75
+ */
76
+ private addEditorRoutes;
68
77
  /**
69
78
  * Add routes for html and scripts required for a local FLP.
70
79
  */
package/dist/base/flp.js CHANGED
@@ -54,21 +54,21 @@ class FlpSandbox {
54
54
  * @param logger logger instance
55
55
  */
56
56
  constructor(config, project, utils, logger) {
57
- var _a, _b, _c;
57
+ var _a, _b, _c, _d, _e, _f, _g;
58
58
  this.project = project;
59
59
  this.utils = utils;
60
60
  this.logger = logger;
61
61
  this.config = {
62
- path: (_a = config.path) !== null && _a !== void 0 ? _a : DEFAULT_PATH,
63
- intent: (_b = config.intent) !== null && _b !== void 0 ? _b : DEFAULT_INTENT,
64
- apps: (_c = config.apps) !== null && _c !== void 0 ? _c : [],
65
- rta: config.rta,
66
- libs: config.libs
62
+ path: (_b = (_a = config.flp) === null || _a === void 0 ? void 0 : _a.path) !== null && _b !== void 0 ? _b : DEFAULT_PATH,
63
+ intent: (_d = (_c = config.flp) === null || _c === void 0 ? void 0 : _c.intent) !== null && _d !== void 0 ? _d : DEFAULT_INTENT,
64
+ apps: (_f = (_e = config.flp) === null || _e === void 0 ? void 0 : _e.apps) !== null && _f !== void 0 ? _f : [],
65
+ libs: (_g = config.flp) === null || _g === void 0 ? void 0 : _g.libs
67
66
  };
68
67
  if (!this.config.path.startsWith('/')) {
69
68
  this.config.path = `/${this.config.path}`;
70
69
  }
71
- logger.debug(`Config: ${JSON.stringify(this.config)}`);
70
+ this.rta = config.rta;
71
+ logger.debug(`Config: ${JSON.stringify({ flp: this.config, rta: this.rta })}`);
72
72
  this.router = (0, express_1.Router)();
73
73
  }
74
74
  /**
@@ -79,7 +79,8 @@ class FlpSandbox {
79
79
  * @param resources optional additional resource mappings
80
80
  */
81
81
  init(manifest, componentId, resources = {}) {
82
- var _a, _b, _c, _d, _e, _f, _g, _h;
82
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
83
+ var _k;
83
84
  return __awaiter(this, void 0, void 0, function* () {
84
85
  const flex = this.createFlexHandler();
85
86
  const supportedThemes = (_b = (_a = manifest['sap.ui5']) === null || _a === void 0 ? void 0 : _a.supportedThemes) !== null && _b !== void 0 ? _b : [DEFAULT_THEME];
@@ -101,11 +102,45 @@ class FlpSandbox {
101
102
  intent: this.config.intent
102
103
  });
103
104
  this.addStandardRoutes();
105
+ if (this.rta) {
106
+ (_j = (_k = this.rta).options) !== null && _j !== void 0 ? _j : (_k.options = {});
107
+ this.rta.options.baseId = componentId !== null && componentId !== void 0 ? componentId : manifest['sap.app'].id;
108
+ this.addEditorRoutes(this.rta);
109
+ }
104
110
  this.addRoutesForAdditionalApps();
105
111
  this.logger.info(`Initialized for app ${manifest['sap.app'].id}`);
106
112
  this.logger.debug(`Configured apps: ${JSON.stringify(this.templateConfig.apps)}`);
107
113
  });
108
114
  }
115
+ /**
116
+ * Add additional routes for configured editors.
117
+ *
118
+ * @param rta runtime authoring configuration
119
+ */
120
+ addEditorRoutes(rta) {
121
+ var _a;
122
+ for (const editor of rta.editors) {
123
+ let previewUrl = editor.path;
124
+ if (editor.developerMode) {
125
+ previewUrl = `${previewUrl}.inner.html`;
126
+ (_a = editor.pluginScript) !== null && _a !== void 0 ? _a : (editor.pluginScript = 'open/ux/preview/client/cpe/init');
127
+ this.router.get(editor.path, ((_req, res) => __awaiter(this, void 0, void 0, function* () {
128
+ const template = (0, fs_1.readFileSync)((0, path_1.join)(__dirname, '../../templates/flp/editor.html'), 'utf-8');
129
+ const html = (0, ejs_1.render)(template, {
130
+ previewUrl: `${previewUrl}?sap-ui-xx-viewCache=false&fiori-tools-rta-mode=forAdaptation&sap-ui-rta-skip-flex-validation=true&sap-ui-xx-condense-changes=true#${this.config.intent.object}-${this.config.intent.action}`
131
+ });
132
+ res.status(200).contentType('html').send(html);
133
+ })));
134
+ }
135
+ this.router.get(previewUrl, ((_req, res) => __awaiter(this, void 0, void 0, function* () {
136
+ const config = Object.assign({}, this.templateConfig);
137
+ config.flex = Object.assign(Object.assign({ layer: rta.layer }, rta.options), { developerMode: editor.developerMode === true, pluginScript: editor.pluginScript });
138
+ const template = (0, fs_1.readFileSync)((0, path_1.join)(__dirname, '../../templates/flp/sandbox.html'), 'utf-8');
139
+ const html = (0, ejs_1.render)(template, config);
140
+ res.status(200).contentType('html').send(html);
141
+ })));
142
+ }
143
+ }
109
144
  /**
110
145
  * Add routes for html and scripts required for a local FLP.
111
146
  */
@@ -114,27 +149,13 @@ class FlpSandbox {
114
149
  this.router.use(PREVIEW_URL.client.url, (0, express_1.static)(PREVIEW_URL.client.local));
115
150
  // add route for the sandbox.html
116
151
  this.router.get(this.config.path, ((req, res) => __awaiter(this, void 0, void 0, function* () {
117
- var _a, _b;
118
- const config = Object.assign({}, this.templateConfig);
119
- const fioriToolsRtaMode = req.query['fiori-tools-rta-mode'];
120
- if (fioriToolsRtaMode) {
121
- if ((_a = this.config.rta) === null || _a === void 0 ? void 0 : _a.layer) {
122
- config.flex = {
123
- layer: (_b = this.config.rta) === null || _b === void 0 ? void 0 : _b.layer,
124
- developerMode: fioriToolsRtaMode === 'forAdaptation'
125
- };
126
- }
127
- else {
128
- this.logger.error('Fiori tools RTA mode could not be started because the RTA layer is missing.');
129
- }
130
- }
131
152
  // warn the user if a file with the same name exists in the filesystem
132
153
  const file = yield this.project.byPath(this.config.path);
133
154
  if (file) {
134
155
  this.logger.warn(`HTML file returned at ${this.config.path} is NOT loaded from the file system.`);
135
156
  }
136
157
  const template = (0, fs_1.readFileSync)((0, path_1.join)(__dirname, '../../templates/flp/sandbox.html'), 'utf-8');
137
- const html = (0, ejs_1.render)(template, config);
158
+ const html = (0, ejs_1.render)(template, this.templateConfig);
138
159
  // if livereload is enabled, don't send it but let other middleware modify the content
139
160
  if (res._livereload) {
140
161
  res.write(html);
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+
3
+ sap.ui.define(["../cpe/init", "sap/base/Log"], function (__init, log) {
4
+ "use strict";
5
+
6
+ function _interopRequireDefault(obj) {
7
+ return obj && obj.__esModule && typeof obj.default !== "undefined" ? obj.default : obj;
8
+ }
9
+ const init = _interopRequireDefault(__init);
10
+ var __exports = function (rta) {
11
+ // custom adaptation project plugin code goes here
12
+ log.debug('ADP init executed.');
13
+ // also initialize the editor
14
+ init(rta);
15
+ };
16
+ return __exports;
17
+ });
18
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1,10 @@
1
+ import type RuntimeAuthoring from 'sap/ui/rta/RuntimeAuthoring';
2
+ import init from '../cpe/init';
3
+ import log from 'sap/base/Log';
4
+
5
+ export default function(rta: RuntimeAuthoring) {
6
+ // custom adaptation project plugin code goes here
7
+ log.debug('ADP init executed.');
8
+ // also initialize the editor
9
+ init(rta);
10
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ sap.ui.define(["sap/base/Log"], function (log) {
4
+ "use strict";
5
+
6
+ var __exports = function (rta) {
7
+ // custom rta plugin code goes here
8
+ log.debug(`Editor start with following settings: ${rta.getFlexSettings()}}`);
9
+ };
10
+ return __exports;
11
+ });
12
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1,7 @@
1
+ import log from 'sap/base/Log';
2
+ import type RuntimeAuthoring from 'sap/ui/rta/RuntimeAuthoring';
3
+
4
+ export default function(rta: RuntimeAuthoring) {
5
+ // custom rta plugin code goes here
6
+ log.debug(`Editor start with following settings: ${rta.getFlexSettings()}}`);
7
+ }
@@ -164,13 +164,19 @@ sap.ui.define(["sap/base/Log", "sap/ui/core/IconPool", "sap/base/i18n/ResourceBu
164
164
  return Promise.resolve(sap.ushell.Container.getServiceAsync('AppLifeCycle')).then(function (serviceInstance) {
165
165
  serviceInstance.attachAppLoaded(event => {
166
166
  const oView = event.getParameter('componentInstance');
167
- sap.ui.require(['sap/ui/rta/api/startAdaptation'], function (startAdaptation) {
167
+ const requiredLibs = ['sap/ui/rta/api/startAdaptation'];
168
+ const flexSettings = JSON.parse(flex);
169
+ if (flexSettings.pluginScript) {
170
+ requiredLibs.push(flexSettings.pluginScript);
171
+ delete flexSettings.pluginScript;
172
+ }
173
+ sap.ui.require(requiredLibs, function (startAdaptation, pluginScript) {
168
174
  const options = {
169
175
  rootControl: oView,
170
176
  validateAppVersion: false,
171
- flexSettings: JSON.parse(flex)
177
+ flexSettings
172
178
  };
173
- startAdaptation(options);
179
+ startAdaptation(options, pluginScript);
174
180
  });
175
181
  });
176
182
  });
@@ -1,5 +1,6 @@
1
1
  import Log from 'sap/base/Log';
2
2
  import type AppLifeCycle from 'sap/ushell/services/AppLifeCycle';
3
+ import type { RTAPlugin, StartAdaptation } from 'sap/ui/rta/api/startAdaptation';
3
4
  import IconPool from 'sap/ui/core/IconPool';
4
5
  import ResourceBundle from 'sap/base/i18n/ResourceBundle';
5
6
  import UriParameters from 'sap/base/util/UriParameters';
@@ -184,13 +185,19 @@ export function configure({ appUrls, flex }: { appUrls?: string | null; flex?: s
184
185
  const serviceInstance = await sap.ushell.Container.getServiceAsync<AppLifeCycle>('AppLifeCycle');
185
186
  serviceInstance.attachAppLoaded(event => {
186
187
  const oView = event.getParameter('componentInstance');
187
- sap.ui.require(['sap/ui/rta/api/startAdaptation'], function (startAdaptation: (opts: object) => void) {
188
+ const requiredLibs = ['sap/ui/rta/api/startAdaptation'];
189
+ const flexSettings = JSON.parse(flex);
190
+ if (flexSettings.pluginScript) {
191
+ requiredLibs.push(flexSettings.pluginScript);
192
+ delete flexSettings.pluginScript;
193
+ }
194
+ sap.ui.require(requiredLibs, function (startAdaptation: StartAdaptation, pluginScript?: RTAPlugin) {
188
195
  const options = {
189
196
  rootControl: oView,
190
197
  validateAppVersion: false,
191
- flexSettings: JSON.parse(flex)
198
+ flexSettings
192
199
  };
193
- startAdaptation(options);
200
+ startAdaptation(options, pluginScript);
194
201
  });
195
202
  });
196
203
  });
@@ -19,15 +19,23 @@ export interface App {
19
19
  componentId?: string;
20
20
  intent?: Intent;
21
21
  }
22
+ export interface RtaConfig {
23
+ layer: UI5FlexLayer;
24
+ options?: {
25
+ [key: string]: unknown;
26
+ };
27
+ editors: {
28
+ path: string;
29
+ developerMode?: boolean;
30
+ pluginScript?: string;
31
+ }[];
32
+ }
22
33
  /**
23
34
  * FLP preview configuration.
24
35
  */
25
36
  export interface FlpConfig {
26
37
  path: string;
27
38
  intent: Intent;
28
- rta?: {
29
- layer?: UI5FlexLayer;
30
- };
31
39
  /**
32
40
  * Optional: if set to true then a locate-reuse-libs script will be attached to the html
33
41
  */
@@ -37,8 +45,9 @@ export interface FlpConfig {
37
45
  /**
38
46
  * Middleware configuration.
39
47
  */
40
- export interface Config {
48
+ export interface MiddlewareConfig {
41
49
  flp?: Partial<FlpConfig>;
50
+ rta?: RtaConfig;
42
51
  adp?: AdpPreviewConfig;
43
52
  debug?: boolean;
44
53
  }
@@ -21,12 +21,23 @@ const adp_tooling_1 = require("@sap-ux/adp-tooling");
21
21
  * @param logger logger instance
22
22
  */
23
23
  function initAdp(rootProject, config, flp, logger) {
24
+ var _a;
24
25
  return __awaiter(this, void 0, void 0, function* () {
25
26
  const appVariant = yield rootProject.byPath('/manifest.appdescr_variant');
26
27
  if (appVariant) {
27
28
  const adp = new adp_tooling_1.AdpPreview(config, rootProject, logger);
28
- const layer = yield adp.init(JSON.parse(yield appVariant.getString()));
29
- flp.config.rta = { layer };
29
+ const variant = JSON.parse(yield appVariant.getString());
30
+ const layer = yield adp.init(variant);
31
+ logger.warn(variant);
32
+ if (flp.rta) {
33
+ flp.rta.layer = layer;
34
+ flp.rta.options = {
35
+ projectId: variant.id
36
+ };
37
+ for (const editor of flp.rta.editors) {
38
+ (_a = editor.pluginScript) !== null && _a !== void 0 ? _a : (editor.pluginScript = 'open/ux/preview/client/adp/init');
39
+ }
40
+ }
30
41
  yield flp.init(adp.descriptor.manifest, adp.descriptor.name, adp.resources);
31
42
  flp.router.use(adp.descriptor.url, adp.proxy.bind(adp));
32
43
  }
@@ -52,7 +63,7 @@ function createRouter({ resources, options, middlewareUtil }, logger) {
52
63
  const config = (_a = options.configuration) !== null && _a !== void 0 ? _a : {};
53
64
  (_b = config.flp) !== null && _b !== void 0 ? _b : (config.flp = {});
54
65
  // configure the FLP sandbox based on information from the manifest
55
- const flp = new flp_1.FlpSandbox(config.flp, resources.rootProject, middlewareUtil, logger);
66
+ const flp = new flp_1.FlpSandbox(config, resources.rootProject, middlewareUtil, logger);
56
67
  if (config.adp) {
57
68
  yield initAdp(resources.rootProject, config.adp, flp, logger);
58
69
  }
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "bugs": {
10
10
  "url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Apreview-middleware"
11
11
  },
12
- "version": "0.4.5",
12
+ "version": "0.5.0",
13
13
  "license": "Apache-2.0",
14
14
  "author": "@SAP/ux-tools-team",
15
15
  "main": "dist/index.js",
@@ -24,7 +24,7 @@
24
24
  "dependencies": {
25
25
  "ejs": "3.1.7",
26
26
  "@sap-ux/logger": "0.3.7",
27
- "@sap-ux/adp-tooling": "0.1.8"
27
+ "@sap-ux/adp-tooling": "0.2.0"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/ejs": "3.1.0",
@@ -51,7 +51,7 @@
51
51
  "start:fixture": "ui5 serve --config test/fixtures/simple-app/ui5.yaml",
52
52
  "build": "npm-run-all -l -p build:middleware build:client",
53
53
  "build:middleware": "tsc --build",
54
- "build:client": "copyfiles --exclude **/*-dbg.js --up 4 \"./node_modules/@private/preview-middleware-client/dist/**/*\" \"./dist/client\"",
54
+ "build:client": "pnpm -C ../preview-middleware-client run build && copyfiles --exclude **/*-dbg.js --up 4 \"./node_modules/@private/preview-middleware-client/dist/**/*\" \"./dist/client\"",
55
55
  "watch": "tsc --watch",
56
56
  "clean": "rimraf dist test/test-output coverage *.tsbuildinfo",
57
57
  "format": "prettier --write '**/*.{js,json,ts,yaml,yml}' --ignore-path ../../.prettierignore",
@@ -0,0 +1,28 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <meta name="theme-color" content="#000000" />
7
+ <meta name="description" content="Web page for rendering Open UX Tools Control Property Editor" />
8
+ <link rel="shortcut icon" type="image/x-icon" href="./editor/favicon.ico" />
9
+ <link rel="stylesheet" type="text/css" href="./editor/app.css" />
10
+ <title>Control Property Editor</title>
11
+ <style>
12
+ body, html {
13
+ margin: 0;
14
+ padding: 0;
15
+ height: 100%;
16
+ overflow: hidden;
17
+ }
18
+ iframe {
19
+ width: 100%;
20
+ height: 100%;
21
+ border: none;
22
+ }
23
+ </style>
24
+ </head>
25
+ <body>
26
+ <iframe src="<%- previewUrl %>"></iframe>
27
+ </body>
28
+ </html>