@soleil-se/app-util 4.2.0 → 5.0.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/CHANGELOG.md +19 -1
- package/MIGRATION.md +101 -108
- package/README.md +26 -34
- package/client/svelte/index.js +10 -8
- package/common/index.js +28 -82
- package/docs/1.svelte.md +115 -0
- package/docs/2.vue.md +57 -0
- package/package.json +9 -4
- package/server/svelte/index.js +8 -31
- package/client/utils/getCurrentScript.js +0 -56
- package/client/utils/index.js +0 -27
- package/client/vue/index.js +0 -33
- package/common/legacy/getRouteUri.js +0 -19
- package/common/legacy/getViewUri.js +0 -21
- package/docs/1.render.md +0 -58
- package/docs/2.svelte.md +0 -103
- package/docs/3.vue.md +0 -38
- package/docs/4.underscore.md +0 -57
- package/server/index.js +0 -83
package/CHANGELOG.md
CHANGED
|
@@ -5,7 +5,25 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [
|
|
8
|
+
## [5.0.0] - 2021-xx-xx
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Using WebApps 2 for rendering apps.
|
|
13
|
+
|
|
14
|
+
### Removed
|
|
15
|
+
|
|
16
|
+
- `getAppData`, use `getAppProps` instead.
|
|
17
|
+
- `server/render`, use `res.agnosticRender` for framework agnostic rendering.
|
|
18
|
+
- `server/renderTemplate`, used for rendering underscore templates.
|
|
19
|
+
|
|
20
|
+
## [4.2.1] - 2021-09-06
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- Underscore is misspelled in `renderTemplate`.
|
|
25
|
+
|
|
26
|
+
## [4.2.0] - 2021-08-20
|
|
9
27
|
|
|
10
28
|
### Added
|
|
11
29
|
|
package/MIGRATION.md
CHANGED
|
@@ -1,156 +1,149 @@
|
|
|
1
1
|
# Migration
|
|
2
2
|
|
|
3
|
-
Migration from version
|
|
3
|
+
Migration from version 4 to 5.
|
|
4
4
|
|
|
5
5
|
<!-- TOC -->
|
|
6
6
|
|
|
7
|
-
- [
|
|
8
|
-
|
|
9
|
-
- [
|
|
10
|
-
- [
|
|
11
|
-
- [
|
|
12
|
-
- [
|
|
13
|
-
- [Get data](#get-data)
|
|
14
|
-
- [Standard values](#standard-values)
|
|
15
|
-
- [Svelte](#svelte)
|
|
16
|
-
- [Server](#server)
|
|
17
|
-
- [Client](#client)
|
|
18
|
-
- [Vue](#vue)
|
|
7
|
+
- [Manifest](#manifest)
|
|
8
|
+
- [index.js](#indexjs)
|
|
9
|
+
- [Universal app](#universal-app)
|
|
10
|
+
- [SSR app](#ssr-app)
|
|
11
|
+
- [CSR app](#csr-app)
|
|
12
|
+
- [main.js](#mainjs)
|
|
19
13
|
|
|
20
14
|
<!-- /TOC -->
|
|
21
15
|
|
|
22
|
-
##
|
|
23
|
-
### Export
|
|
24
|
-
Export moved and renamed.
|
|
16
|
+
## Manifest
|
|
25
17
|
|
|
26
|
-
|
|
27
|
-
```js
|
|
28
|
-
import { renderApp } from '@soleil-api/webapp-util';
|
|
29
|
-
```
|
|
30
|
-
New:
|
|
31
|
-
```js
|
|
32
|
-
import { render } from '@soleil-api/webapp-util/server';
|
|
33
|
-
```
|
|
18
|
+
Add `"bundled": true` to the app manifest file.
|
|
34
19
|
|
|
35
|
-
|
|
36
|
-
|
|
20
|
+
manifest.json
|
|
21
|
+
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"id": "se.soleil.myApp",
|
|
25
|
+
"version": "1.0.0",
|
|
26
|
+
"name": "My app",
|
|
27
|
+
"author": "Soleil AB",
|
|
28
|
+
"description": "",
|
|
29
|
+
"helpUrl": "https://soleil.se/support",
|
|
30
|
+
"type": "WebApp",
|
|
31
|
+
"bundled": true
|
|
32
|
+
}
|
|
37
33
|
|
|
38
|
-
Old (index.js):
|
|
39
|
-
```js
|
|
40
|
-
res.send(renderApp(data, { selector: '#mount_app_here' }));
|
|
41
34
|
```
|
|
42
35
|
|
|
43
|
-
|
|
44
|
-
```js
|
|
45
|
-
import { render } from '@soleil-api/webapp-util/client/vue';
|
|
46
|
-
import App from './App.vue';
|
|
36
|
+
## index.js
|
|
47
37
|
|
|
48
|
-
|
|
49
|
-
```
|
|
38
|
+
Rendering is now using Webapps 2 render functions.
|
|
50
39
|
|
|
51
|
-
|
|
52
|
-
Export moved.
|
|
40
|
+
### Universal app
|
|
53
41
|
|
|
54
|
-
Old
|
|
55
|
-
```js
|
|
56
|
-
import { renderTemplate } from '@soleil-api/webapp-util';
|
|
57
|
-
```
|
|
58
|
-
New:
|
|
59
|
-
```js
|
|
60
|
-
import { renderTemplate } from '@soleil-api/webapp-util/server';
|
|
61
|
-
```
|
|
62
|
-
## getRouteUri
|
|
63
|
-
URIs for routes was previously passed as props when rendering an application. This is no longer needed.
|
|
64
|
-
Now you can use `getRouteUri` in a client context as well.
|
|
42
|
+
Old
|
|
65
43
|
|
|
66
|
-
Old:
|
|
67
44
|
```js
|
|
68
|
-
import
|
|
45
|
+
import router from '@sitevision/api/common/router';
|
|
46
|
+
import { render } from '@soleil-api/webapp-util/server/svelte';
|
|
69
47
|
|
|
70
|
-
|
|
71
|
-
return fetch(AppData.itemsRoute)
|
|
72
|
-
.then((res) => res.json());
|
|
73
|
-
};
|
|
74
|
-
```
|
|
75
|
-
New:
|
|
76
|
-
```js
|
|
77
|
-
import { getRouteUri } from '@soleil-api/webapp-util';
|
|
48
|
+
import App from './App.svelte';
|
|
78
49
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
};
|
|
50
|
+
router.get('/', (req, res) => {
|
|
51
|
+
const props = { foo: 'bar' };
|
|
52
|
+
res.send(render(App, props));
|
|
53
|
+
});
|
|
83
54
|
```
|
|
84
|
-
## AppData
|
|
85
55
|
|
|
86
|
-
|
|
87
|
-
The default export as object and `@soleil-api/webapp-util/app-data` import is removed.
|
|
56
|
+
New
|
|
88
57
|
|
|
89
|
-
Old:
|
|
90
58
|
```js
|
|
91
|
-
import
|
|
59
|
+
import router from '@sitevision/api/common/router';
|
|
60
|
+
import { render } from '@soleil-api/webapp-util/server/svelte';
|
|
92
61
|
|
|
93
|
-
|
|
94
|
-
```
|
|
95
|
-
New:
|
|
96
|
-
```js
|
|
97
|
-
import { getAppData } from '@soleil-api/webapp-util';
|
|
62
|
+
import App from './App.svelte';
|
|
98
63
|
|
|
99
|
-
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
64
|
+
router.get('/', (req, res) => {
|
|
65
|
+
const props = { foo: 'bar' };
|
|
66
|
+
const html = render(App, props);
|
|
67
|
+
res.agnosticRender(html, props);
|
|
68
|
+
});
|
|
103
69
|
```
|
|
104
|
-
### Standard values
|
|
105
|
-
Values that was set as sandard are now moved.
|
|
106
70
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
71
|
+
### SSR app
|
|
72
|
+
|
|
73
|
+
Old
|
|
110
74
|
|
|
111
|
-
const { isOnline, isOffline, uniqueId } = AppData;
|
|
112
|
-
```
|
|
113
|
-
New:
|
|
114
75
|
```js
|
|
115
|
-
import
|
|
76
|
+
import router from '@sitevision/api/common/router';
|
|
77
|
+
import { renderServer } from '@soleil-api/webapp-util/server/svelte';
|
|
116
78
|
|
|
117
|
-
|
|
79
|
+
import App from './App.svelte';
|
|
80
|
+
|
|
81
|
+
router.get('/', (req, res) => {
|
|
82
|
+
const props = { foo: 'bar' };
|
|
83
|
+
res.send(renderServer(App, props));
|
|
84
|
+
});
|
|
118
85
|
```
|
|
119
86
|
|
|
120
|
-
|
|
121
|
-
### Server
|
|
122
|
-
Export moved.
|
|
123
|
-
Export `renderClient` is removed, use `render` from `'@soleil-api/webapp-util/server`
|
|
87
|
+
New
|
|
124
88
|
|
|
125
|
-
Old:
|
|
126
|
-
```js
|
|
127
|
-
import { render } from '@soleil-api/webapp-util/svelte-server';
|
|
128
|
-
```
|
|
129
|
-
New:
|
|
130
89
|
```js
|
|
90
|
+
import router from '@sitevision/api/common/router';
|
|
131
91
|
import { render } from '@soleil-api/webapp-util/server/svelte';
|
|
92
|
+
|
|
93
|
+
import App from './App.svelte';
|
|
94
|
+
|
|
95
|
+
router.get('/', (req, res) => {
|
|
96
|
+
const props = { foo: 'bar' };
|
|
97
|
+
const html = render(App, props);
|
|
98
|
+
res.send(html);
|
|
99
|
+
});
|
|
132
100
|
```
|
|
133
|
-
### Client
|
|
134
|
-
Export moved.
|
|
135
101
|
|
|
136
|
-
|
|
102
|
+
### CSR app
|
|
103
|
+
|
|
104
|
+
Old
|
|
105
|
+
|
|
137
106
|
```js
|
|
138
|
-
import
|
|
107
|
+
import router from '@sitevision/api/common/router';
|
|
108
|
+
import { render } from '@soleil-api/webapp-util/server';
|
|
109
|
+
|
|
110
|
+
router.get('/', (req, res) => {
|
|
111
|
+
const props = { foo: 'bar' };
|
|
112
|
+
res.send(render(props));
|
|
113
|
+
});
|
|
139
114
|
```
|
|
140
|
-
|
|
115
|
+
|
|
116
|
+
New
|
|
117
|
+
|
|
141
118
|
```js
|
|
142
|
-
import
|
|
119
|
+
import router from '@sitevision/api/common/router';
|
|
120
|
+
|
|
121
|
+
router.get('/', (req, res) => {
|
|
122
|
+
const props = { foo: 'bar' };
|
|
123
|
+
res.agnosticRender('', props)
|
|
124
|
+
});
|
|
143
125
|
```
|
|
144
126
|
|
|
145
|
-
##
|
|
146
|
-
|
|
127
|
+
## main.js
|
|
128
|
+
|
|
129
|
+
Is now expecting a default export containing a function
|
|
130
|
+
|
|
131
|
+
Old
|
|
147
132
|
|
|
148
|
-
Old:
|
|
149
133
|
```js
|
|
150
|
-
import render from '@soleil-api/webapp-util/
|
|
134
|
+
import { render } from '@soleil-api/webapp-util/client/svelte';
|
|
135
|
+
import App from './App.svelte';
|
|
136
|
+
|
|
137
|
+
render(App);
|
|
151
138
|
```
|
|
152
|
-
|
|
139
|
+
|
|
140
|
+
New
|
|
141
|
+
|
|
153
142
|
```js
|
|
154
|
-
import { render } from '@soleil-api/webapp-util/client/
|
|
155
|
-
|
|
143
|
+
import { render } from '@soleil-api/webapp-util/client/svelte';
|
|
144
|
+
import App from './App.svelte';
|
|
156
145
|
|
|
146
|
+
export default (props, target) => {
|
|
147
|
+
render(App, { props, target });
|
|
148
|
+
};
|
|
149
|
+
```
|
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
|
-
# `@soleil-se/webapp-util@^
|
|
2
|
+
# `@soleil-se/webapp-util@^5.0.0`
|
|
3
3
|
|
|
4
|
-
Utility functions for
|
|
4
|
+
Utility functions for WebApps.
|
|
5
5
|
|
|
6
6
|
[GitHub](https://github.com/soleilit/server-monorepo/tree/master/packages/webapp-util)
|
|
7
7
|
[NPM](https://www.npmjs.com/package/@soleil-se/webapp-util)
|
|
@@ -10,7 +10,27 @@ Utility functions for Webapps.
|
|
|
10
10
|
|
|
11
11
|
## Requirements
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
* Sitevision 9.1.0 or later.
|
|
14
|
+
* `@soleil-se/sv-app-build` 1.0.0 or later.
|
|
15
|
+
* WebApps 2 enabled app.
|
|
16
|
+
|
|
17
|
+
### Manifest
|
|
18
|
+
|
|
19
|
+
`bundled` needs to be enabled in [WebApp manifest](https://developer.sitevision.se/docs/webapps/webapps-2/manifest) for WebApps 2.
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"id": "se.soleil.myApp",
|
|
24
|
+
"version": "1.0.0",
|
|
25
|
+
"name": "My app",
|
|
26
|
+
"author": "Soleil AB",
|
|
27
|
+
"description": "",
|
|
28
|
+
"helpUrl": "https://soleil.se/support",
|
|
29
|
+
"type": "WebApp",
|
|
30
|
+
"bundled": true
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
```
|
|
14
34
|
|
|
15
35
|
## Install
|
|
16
36
|
|
|
@@ -18,7 +38,7 @@ Utility functions for Webapps.
|
|
|
18
38
|
|
|
19
39
|
## Migration
|
|
20
40
|
|
|
21
|
-
Migrating from version
|
|
41
|
+
Migrating from version 4?
|
|
22
42
|
See [MIGRATION](./MIGRATION.md).
|
|
23
43
|
|
|
24
44
|
## API
|
|
@@ -57,9 +77,6 @@ All imports from base package are available both on the server and client.
|
|
|
57
77
|
<dt><a href="#getAppProps">getAppProps([key])</a> ⇒ <code>*</code> | <code>Object</code></dt>
|
|
58
78
|
<dd><p>Get props that are passed to app when rendering.</p>
|
|
59
79
|
</dd>
|
|
60
|
-
<dt><del><a href="#getAppData">getAppData([key])</a> ⇒ <code>*</code> | <code>Object</code></del></dt>
|
|
61
|
-
<dd><p>Get props that are passed to app when rendering.</p>
|
|
62
|
-
</dd>
|
|
63
80
|
</dl>
|
|
64
81
|
|
|
65
82
|
<a name="appId"></a>
|
|
@@ -200,32 +217,7 @@ const myValue = getAppProps('myValue');
|
|
|
200
217
|
const { myValue } = getAppProps();
|
|
201
218
|
```
|
|
202
219
|
|
|
203
|
-
<a name="getAppData"></a>
|
|
204
|
-
|
|
205
|
-
### getAppData([key]) ⇒ `*` | `Object` (DEPRECATED)
|
|
206
|
-
|
|
207
|
-
Use [getAppProps](#getAppProps) instead.
|
|
208
|
-
|
|
209
|
-
Get props that are passed to app when rendering.
|
|
210
|
-
|
|
211
|
-
**Returns**: `*` | `Object` - Value or object.
|
|
212
|
-
|
|
213
|
-
| Param | Type | Description |
|
|
214
|
-
| --- | --- | --- |
|
|
215
|
-
| [key] | `String` | Key for value. |
|
|
216
|
-
|
|
217
|
-
```js
|
|
218
|
-
import { getAppData } from '@soleil-se/webapp-util';
|
|
219
|
-
|
|
220
|
-
// Get value with key
|
|
221
|
-
const myValue = getAppData('myValue');
|
|
222
|
-
// Or with destructuring
|
|
223
|
-
const { myValue } = getAppData();
|
|
224
|
-
```
|
|
225
|
-
|
|
226
220
|
## Rendering
|
|
227
221
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
- [Vue](./docs/3.vue.md)
|
|
231
|
-
- [Underscore](./docs/4.underscore.md)
|
|
222
|
+
* [Svelte](./docs/1.svelte.md)
|
|
223
|
+
* [Vue (DEPRECATED)](./docs/2.vue.md)
|
package/client/svelte/index.js
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
import { appId, getAppProps } from '../../common';
|
|
1
|
+
import { setAppProps } from '../../common';
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* Renders a client side Svelte application.
|
|
6
5
|
* @param {*} App Svelte app root component.
|
|
7
|
-
* @param {
|
|
8
|
-
* @param {
|
|
9
|
-
* @param {
|
|
6
|
+
* @param {object} [settings={}] Settings object.
|
|
7
|
+
* @param {string} [settings.target] Target where app should be mounted.
|
|
8
|
+
* @param {string} [settings.props] Root component props.
|
|
9
|
+
* @param {string} [settings.intro=false] If true, will play transitions on initial render,
|
|
10
10
|
* rather than waiting for subsequent state changes.
|
|
11
11
|
* @return {*} Initialized Svelte component.
|
|
12
12
|
*/
|
|
13
13
|
export function render(App, {
|
|
14
|
-
|
|
14
|
+
target,
|
|
15
|
+
props,
|
|
15
16
|
intro = false,
|
|
16
17
|
} = {}) {
|
|
17
|
-
|
|
18
|
+
setAppProps(props);
|
|
19
|
+
|
|
18
20
|
const hydrate = target.childElementCount > 0;
|
|
19
|
-
|
|
21
|
+
|
|
20
22
|
return new App({
|
|
21
23
|
hydrate,
|
|
22
24
|
target,
|
package/common/index.js
CHANGED
|
@@ -1,24 +1,14 @@
|
|
|
1
|
+
/* global document */
|
|
1
2
|
/* eslint-disable global-require */
|
|
2
|
-
import { parseJson } from '../client/utils';
|
|
3
|
-
import getLegacyRouteUri from './legacy/getRouteUri';
|
|
4
|
-
import getLegacyViewUri from './legacy/getViewUri';
|
|
5
3
|
|
|
6
|
-
|
|
4
|
+
import router from '@sitevision/api/common/router';
|
|
5
|
+
import app from '@sitevision/api/common/app';
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Get an ID for the app.
|
|
10
9
|
* @return {String} ID
|
|
11
10
|
*/
|
|
12
|
-
const getAppId = () =>
|
|
13
|
-
const PortletContextUtil = require('PortletContextUtil');
|
|
14
|
-
const id = (PortletContextUtil.getPortletNamespace('') || 'ADDON_PREVIEW').replace('.', '_');
|
|
15
|
-
const decoratedNode = PortletContextUtil.getCurrentDecoratedNode();
|
|
16
|
-
|
|
17
|
-
if (decoratedNode) {
|
|
18
|
-
return `${decoratedNode.getIdentifier().replace('.', '_')}_${id}`;
|
|
19
|
-
}
|
|
20
|
-
return id;
|
|
21
|
-
};
|
|
11
|
+
const getAppId = () => app.portletId.replace('.', '_');
|
|
22
12
|
|
|
23
13
|
/**
|
|
24
14
|
* Regex for selecting leading slashes
|
|
@@ -34,21 +24,21 @@ const trailingSlashes = /(\/)*$/g;
|
|
|
34
24
|
|
|
35
25
|
/**
|
|
36
26
|
* DOM friendly unique identifier for the WebApp.
|
|
37
|
-
* @constant {
|
|
27
|
+
* @constant {string}
|
|
38
28
|
*/
|
|
39
|
-
export const appId =
|
|
29
|
+
export const appId = getAppId();
|
|
40
30
|
|
|
41
31
|
/**
|
|
42
32
|
* If the WebApp is running in offline mode or not.
|
|
43
|
-
* @constant {
|
|
33
|
+
* @constant {boolean}
|
|
44
34
|
*/
|
|
45
35
|
export const isOffline = process.server
|
|
46
36
|
? require('VersionUtil').getCurrentVersion() === require('VersionUtil').OFFLINE_VERSION
|
|
47
|
-
:
|
|
37
|
+
: document.documentElement.classList.contains('sv-edit-mode');
|
|
48
38
|
|
|
49
39
|
/**
|
|
50
40
|
* If the WebApp is running in online mode or not.
|
|
51
|
-
* @constant {
|
|
41
|
+
* @constant {boolean}
|
|
52
42
|
*/
|
|
53
43
|
export const isOnline = !isOffline;
|
|
54
44
|
|
|
@@ -62,92 +52,48 @@ export function getNamespace(prefix = 'app') {
|
|
|
62
52
|
}
|
|
63
53
|
|
|
64
54
|
/**
|
|
65
|
-
* Get URI for a route.
|
|
66
|
-
* @param {
|
|
67
|
-
* @
|
|
55
|
+
* Get URI for a route, same as `getStandaloneUrl` in Sitevision router.
|
|
56
|
+
* @param {string} route A route.
|
|
57
|
+
* @param {object} query Query parameters.
|
|
58
|
+
* @returns {string} URI for route.
|
|
68
59
|
*/
|
|
69
|
-
export function getRouteUri(route = '') {
|
|
60
|
+
export function getRouteUri(route = '', query) {
|
|
70
61
|
const path = route.replace(leadingSlashes, '');
|
|
71
|
-
|
|
72
|
-
const router = require('router');
|
|
73
|
-
if (router.getStandaloneUrl) {
|
|
74
|
-
return router
|
|
75
|
-
.getStandaloneUrl(path !== '' ? `/${path}` : path)
|
|
76
|
-
.replace(trailingSlashes, '');
|
|
77
|
-
}
|
|
78
|
-
// If Sitevision 7 or older.
|
|
79
|
-
return getLegacyRouteUri(path);
|
|
80
|
-
}
|
|
81
|
-
return `${appMetadata.baseRouteUri}/${path}`;
|
|
62
|
+
return router.getStandaloneUrl(path !== '' ? `/${path}` : path, query).replace(trailingSlashes, '');
|
|
82
63
|
}
|
|
83
64
|
|
|
84
65
|
/**
|
|
85
|
-
* Get URI for a view.
|
|
86
|
-
* @param {
|
|
87
|
-
* @returns {
|
|
66
|
+
* Get URI for a view, same as `getUrl` in Sitevision router.
|
|
67
|
+
* @param {string} route A route.
|
|
68
|
+
* @returns {string} URI for view.
|
|
88
69
|
*/
|
|
89
70
|
export function getViewUri(route = '') {
|
|
90
|
-
|
|
91
|
-
const router = require('router');
|
|
92
|
-
if (router.getUrl) {
|
|
93
|
-
return router.getUrl(route);
|
|
94
|
-
}
|
|
95
|
-
// If Sitevision 7 or older.
|
|
96
|
-
return getLegacyViewUri(route, { isOffline });
|
|
97
|
-
}
|
|
98
|
-
return appMetadata.baseViewUri + route;
|
|
71
|
+
return router.getUrl(route);
|
|
99
72
|
}
|
|
100
73
|
|
|
101
74
|
/**
|
|
102
75
|
* Get URI for a resource.
|
|
103
|
-
* @param {
|
|
104
|
-
* @returns {
|
|
76
|
+
* @param {string} resource A resource.
|
|
77
|
+
* @returns {string} URI for a resource.
|
|
105
78
|
*/
|
|
106
79
|
export function getResourceUri(resource = '') {
|
|
80
|
+
const { webAppId, webAppVersion } = app;
|
|
107
81
|
const path = resource.replace(leadingSlashes, '');
|
|
108
|
-
|
|
109
|
-
const appInfo = require('appInfo');
|
|
110
|
-
return `/webapp-files/${appInfo.appIdentifier}/${appInfo.appVersion}/${path}`
|
|
111
|
-
.replace(trailingSlashes, '');
|
|
112
|
-
}
|
|
113
|
-
return `${appMetadata.baseResourceUri}/${path}`;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export function getAppMetadata() {
|
|
117
|
-
return {
|
|
118
|
-
id: appId,
|
|
119
|
-
isOffline,
|
|
120
|
-
isOnline,
|
|
121
|
-
baseRouteUri: getRouteUri(),
|
|
122
|
-
baseViewUri: getViewUri(),
|
|
123
|
-
baseResourceUri: getResourceUri(),
|
|
124
|
-
};
|
|
82
|
+
return `/webapp-files/${webAppId}/${webAppVersion}/${path}`;
|
|
125
83
|
}
|
|
126
84
|
|
|
127
|
-
let appProps =
|
|
85
|
+
let appProps = {};
|
|
128
86
|
|
|
129
87
|
export function setAppProps(data) {
|
|
130
88
|
appProps = data;
|
|
131
89
|
}
|
|
132
90
|
|
|
133
91
|
/**
|
|
134
|
-
* Get
|
|
135
|
-
* @
|
|
136
|
-
* @
|
|
92
|
+
* Get appData value or object that is passed to app when rendering.
|
|
93
|
+
* @export
|
|
94
|
+
* @param {string} [key] - Key for value.
|
|
95
|
+
* @return {*|object} - Value or object.
|
|
137
96
|
*/
|
|
138
97
|
export function getAppProps(key) {
|
|
139
|
-
if (process.browser && !appProps) {
|
|
140
|
-
setAppProps(parseJson('app_props'));
|
|
141
|
-
}
|
|
142
98
|
return key ? appProps[key] : appProps;
|
|
143
99
|
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Get props that are passed to app when rendering.
|
|
147
|
-
* @deprecated Use `getAppProps` instead.
|
|
148
|
-
* @param {String} [key] - Key for value.
|
|
149
|
-
* @return {*|Object} Value or object.
|
|
150
|
-
*/
|
|
151
|
-
export function getAppData(key) {
|
|
152
|
-
return getAppProps(key);
|
|
153
|
-
}
|
package/docs/1.svelte.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Svelte
|
|
2
|
+
|
|
3
|
+
Sitevision supports both server and client side rendering with Svelte.
|
|
4
|
+
|
|
5
|
+
## index.js
|
|
6
|
+
|
|
7
|
+
For rendering a client side only app use the framework agnostic [client renderer](./1.render.md).
|
|
8
|
+
|
|
9
|
+
### `render(App, [props])`
|
|
10
|
+
|
|
11
|
+
`@soleil-api/webapp-util/server/svelte`
|
|
12
|
+
|
|
13
|
+
Get a HTML string for rendering a universal Svelte application.
|
|
14
|
+
If a client bundle is available the server rendered HTML will be hydrated and not completely re-rendered.
|
|
15
|
+
|
|
16
|
+
**Returns**: <code>String</code> - HTML for rendering a Svelte application.
|
|
17
|
+
|
|
18
|
+
| Param | Type | Default | Description |
|
|
19
|
+
| --- | --- | --- | --- |
|
|
20
|
+
| [App] | <code>Svelte</code> | | Svelte app to be rendered. |
|
|
21
|
+
| [props] | <code>Object</code> | <code>{}</code> | Props that will be passed to the app. |
|
|
22
|
+
|
|
23
|
+
### Universal
|
|
24
|
+
|
|
25
|
+
Render an app with both server and client code.
|
|
26
|
+
|
|
27
|
+
`index.js`
|
|
28
|
+
|
|
29
|
+
```javascript
|
|
30
|
+
import router from '@sitevision/api/common/router';
|
|
31
|
+
import { render } from '@soleil-api/webapp-util/server/svelte';
|
|
32
|
+
|
|
33
|
+
import App from './App.svelte';
|
|
34
|
+
|
|
35
|
+
router.get('/', (req, res) => {
|
|
36
|
+
const props = { foo: 'bar' };
|
|
37
|
+
const html = render(App, props);
|
|
38
|
+
res.agnosticRender(html, props);
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### SSR
|
|
43
|
+
|
|
44
|
+
Render an app with only server side code.
|
|
45
|
+
|
|
46
|
+
`index.js`
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
import router from '@sitevision/api/common/router';
|
|
50
|
+
import { render } from '@soleil-api/webapp-util/server/svelte';
|
|
51
|
+
|
|
52
|
+
import App from './App.svelte';
|
|
53
|
+
|
|
54
|
+
router.get('/', (req, res) => {
|
|
55
|
+
const props = { foo: 'bar' };
|
|
56
|
+
const html = render(App, props);
|
|
57
|
+
res.send(html);
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### CSR
|
|
62
|
+
|
|
63
|
+
Render an app with only client side code.
|
|
64
|
+
|
|
65
|
+
`index.js`
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
import router from '@sitevision/api/common/router';
|
|
69
|
+
|
|
70
|
+
router.get('/', (req, res) => {
|
|
71
|
+
const props = { foo: 'bar' };
|
|
72
|
+
res.agnosticRender('', props)
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## main.js
|
|
77
|
+
|
|
78
|
+
### `render(App, { target, props })`
|
|
79
|
+
|
|
80
|
+
`@soleil-api/webapp-util/client/svelte`
|
|
81
|
+
|
|
82
|
+
Renders a client side Svelte application.
|
|
83
|
+
|
|
84
|
+
**Returns**: <code>\*</code> - Initialized Svelte component.
|
|
85
|
+
|
|
86
|
+
| Param | Type | Default | Description |
|
|
87
|
+
| --- | --- | --- | --- |
|
|
88
|
+
| App | <code>\*</code> | | Svelte app root component. |
|
|
89
|
+
| [settings] | <code>Object</code> | <code>{}</code> | Settings object. |
|
|
90
|
+
| [settings.target] | <code>Element</code> | | Target where app should be mounted. |
|
|
91
|
+
| [settings.props] | <code>Object</code> | | Root component props. |
|
|
92
|
+
| [settings.intro] | <code>String</code> | <code>false</code> | If true, will play transitions on initial render, rather than waiting for subsequent state changes. |
|
|
93
|
+
|
|
94
|
+
`main.js`
|
|
95
|
+
|
|
96
|
+
```javascript
|
|
97
|
+
import { render } from '@soleil-api/webapp-util/client/svelte';
|
|
98
|
+
import App from './App.svelte';
|
|
99
|
+
|
|
100
|
+
export default (props, target) => {
|
|
101
|
+
render(App, { props, target });
|
|
102
|
+
};
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Mount the app in another element:
|
|
106
|
+
`main.js`
|
|
107
|
+
|
|
108
|
+
```javascript
|
|
109
|
+
import { render } from '@soleil-api/webapp-util/client/svelte';
|
|
110
|
+
import App from './App.svelte';
|
|
111
|
+
|
|
112
|
+
export default (props) => {
|
|
113
|
+
render(App, { props, target: document.querySelector('#mount_app_here') });
|
|
114
|
+
};
|
|
115
|
+
```
|
package/docs/2.vue.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Vue (DEPRECATED)
|
|
2
|
+
|
|
3
|
+
Sitevision only supports client side rendering with Vue.
|
|
4
|
+
|
|
5
|
+
## index.js
|
|
6
|
+
|
|
7
|
+
Render an app with only client code.
|
|
8
|
+
`index.js`
|
|
9
|
+
|
|
10
|
+
```javascript
|
|
11
|
+
import router from '@sitevision/api/common/router';
|
|
12
|
+
|
|
13
|
+
router.get('/', (req, res) => {
|
|
14
|
+
const props = { foo: 'bar' };
|
|
15
|
+
res.agnosticRender('', props)
|
|
16
|
+
});
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## main.js
|
|
20
|
+
|
|
21
|
+
### `render(App, { target, props })`
|
|
22
|
+
|
|
23
|
+
`@soleil-api/webapp-util/client/vue`
|
|
24
|
+
|
|
25
|
+
Renders a client side Vue application.
|
|
26
|
+
|
|
27
|
+
**Returns**: <code>\*</code> - Initialized Vue app.
|
|
28
|
+
|
|
29
|
+
| Param | Type | Default | Description |
|
|
30
|
+
| --- | --- | --- | --- |
|
|
31
|
+
| App | <code>\*</code> | | Svelte app root component. |
|
|
32
|
+
| [settings] | <code>Object</code> | <code>{}</code> | Settings object. |
|
|
33
|
+
| [settings.target] | <code>Element</code> | | Target where app should be mounted. |
|
|
34
|
+
| [settings.props] | <code>Object</code> | | Root component props. |
|
|
35
|
+
|
|
36
|
+
`main.js`
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
import { render } from '@soleil-api/webapp-util/client/vue';
|
|
40
|
+
import App from './App.vue';
|
|
41
|
+
|
|
42
|
+
export default (props, target) => {
|
|
43
|
+
render(App, { props, target });
|
|
44
|
+
};
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Mount the app in another element:
|
|
48
|
+
`main.js`
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
import { render } from '@soleil-api/webapp-util/client/vue';
|
|
52
|
+
import App from './App.vue';
|
|
53
|
+
|
|
54
|
+
export default (props) => {
|
|
55
|
+
render(App, { props, target: document.querySelector('#mount_app_here') });
|
|
56
|
+
};
|
|
57
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soleil-se/app-util",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "Utility and rendering functions for WebApps.",
|
|
5
5
|
"main": "./common/index.js",
|
|
6
6
|
"author": "Soleil AB",
|
|
@@ -11,7 +11,12 @@
|
|
|
11
11
|
"license": "UNLICENSED",
|
|
12
12
|
"private": false,
|
|
13
13
|
"homepage": "https://docs.soleilit.se/03.packages/@soleil-api&app-util",
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@sitevision/api": "^1.0.10",
|
|
16
|
+
"svelte": "^3.44.1"
|
|
17
|
+
},
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"@sitevision/api": "^1.0.10"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {}
|
|
17
22
|
}
|
package/server/svelte/index.js
CHANGED
|
@@ -1,36 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { appId, setAppProps } from '../../common';
|
|
3
|
-
import { render as renderClient } from '../index';
|
|
4
|
-
|
|
5
|
-
const initSSR = (App, props) => {
|
|
6
|
-
setAppProps(props);
|
|
7
|
-
return App.render(props).html;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* SSR Svelte App.
|
|
12
|
-
* @export
|
|
13
|
-
* @param {SvelteComponent} App - Svelte component that is root of app.
|
|
14
|
-
* @param {Object} [props] - Props available on root component. Also avaliable with getAppProps.
|
|
15
|
-
* @return {String} - HTML for rendering a Svelte application.
|
|
16
|
-
*/
|
|
17
|
-
export function renderServer(App, props = {}) {
|
|
18
|
-
const html = initSSR(App, props);
|
|
19
|
-
return `<div id="app_mount_${appId}">${html}</div>`;
|
|
20
|
-
}
|
|
1
|
+
import { setAppProps } from '../../common';
|
|
21
2
|
|
|
22
3
|
/**
|
|
23
|
-
*
|
|
24
|
-
* @export
|
|
4
|
+
* Returns HTML for a server rendered Svelte app.
|
|
25
5
|
* @param {SvelteComponent} App - Svelte component that is root of app.
|
|
26
|
-
* @param {
|
|
27
|
-
* @
|
|
28
|
-
* @return {String} - HTML for rendering a Svelte application.
|
|
6
|
+
* @param {object} props - Props passed to root component.
|
|
7
|
+
* @return {string} - HTML for the server rendered app.
|
|
29
8
|
*/
|
|
30
|
-
export function render(App, props
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
return `<div id="app_mount_${appId}">${html}</div>`;
|
|
9
|
+
export function render(App, props) {
|
|
10
|
+
setAppProps(props);
|
|
11
|
+
const { html } = App.render(props);
|
|
12
|
+
return html;
|
|
36
13
|
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
/* Scoped version of https://github.com/amiller-gh/currentScript-polyfill */
|
|
2
|
-
// document.currentScript polyfill by Adam Miller
|
|
3
|
-
// MIT license
|
|
4
|
-
|
|
5
|
-
export default function getCurrentScript() {
|
|
6
|
-
if (!('currentScript' in document)) {
|
|
7
|
-
// IE 8-10 support script readyState
|
|
8
|
-
// IE 11+ support stack trace
|
|
9
|
-
try {
|
|
10
|
-
throw new Error();
|
|
11
|
-
} catch (err) {
|
|
12
|
-
// Find the second match for the "at" string to get file src url from stack.
|
|
13
|
-
// Specifically works with the format of stack traces in IE.
|
|
14
|
-
let i = 0;
|
|
15
|
-
const stackDetails = (/.*at [^(]*\((.*):(.+):(.+)\)$/ig).exec(err.stack);
|
|
16
|
-
const scriptLocation = (stackDetails && stackDetails[1]) || false;
|
|
17
|
-
const line = (stackDetails && stackDetails[2]) || false;
|
|
18
|
-
const currentLocation = document.location.href.replace(document.location.hash, '');
|
|
19
|
-
let pageSource;
|
|
20
|
-
let inlineScriptSourceRegExp;
|
|
21
|
-
let inlineScriptSource;
|
|
22
|
-
const scripts = document.getElementsByTagName('script'); // Live NodeList collection
|
|
23
|
-
|
|
24
|
-
if (scriptLocation === currentLocation) {
|
|
25
|
-
pageSource = document.documentElement.outerHTML;
|
|
26
|
-
inlineScriptSourceRegExp = new RegExp(`(?:[^\\n]+?\\n){0,${line - 2}}[^<]*<script>([\\d\\D]*?)<\\/script>[\\d\\D]*`, 'i');
|
|
27
|
-
inlineScriptSource = pageSource.replace(inlineScriptSourceRegExp, '$1').trim();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
for (; i < scripts.length; i += 1) {
|
|
31
|
-
// If ready state is interactive, return the script tag
|
|
32
|
-
if (scripts[i].readyState === 'interactive') {
|
|
33
|
-
return scripts[i];
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// If src matches, return the script tag
|
|
37
|
-
if (scripts[i].src === scriptLocation) {
|
|
38
|
-
return scripts[i];
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// If inline source matches, return the script tag
|
|
42
|
-
if (
|
|
43
|
-
scriptLocation === currentLocation
|
|
44
|
-
&& scripts[i].innerHTML
|
|
45
|
-
&& scripts[i].innerHTML.trim() === inlineScriptSource
|
|
46
|
-
) {
|
|
47
|
-
return scripts[i];
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// If no match, return null
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return document.currentScript;
|
|
56
|
-
}
|
package/client/utils/index.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import getCurrentScript from './getCurrentScript';
|
|
2
|
-
|
|
3
|
-
const unescapeTags = (unsafe) => unsafe
|
|
4
|
-
.replace(/</g, '<')
|
|
5
|
-
.replace(/>/g, '>');
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* JSON decode an attribute on the currentScript element.
|
|
9
|
-
* Use if attribute contains a JSON-object.
|
|
10
|
-
* @param {String} attribute Attribute to decode.
|
|
11
|
-
* @returns {Object} Decoded JSON object.
|
|
12
|
-
*/
|
|
13
|
-
export const getAttribute = (attribute) => {
|
|
14
|
-
const currentScript = getCurrentScript();
|
|
15
|
-
const encoded = currentScript.getAttribute(attribute);
|
|
16
|
-
if (encoded) {
|
|
17
|
-
return decodeURIComponent(encoded);
|
|
18
|
-
}
|
|
19
|
-
return undefined;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export const parseJson = (type) => {
|
|
23
|
-
const id = getAttribute('data-app-id');
|
|
24
|
-
let json = document.querySelector(`[data-id="${type}_${id}"]`)?.textContent || '{}';
|
|
25
|
-
json = unescapeTags(json);
|
|
26
|
-
return JSON.parse(json);
|
|
27
|
-
};
|
package/client/vue/index.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/* eslint-disable import/prefer-default-export */
|
|
2
|
-
/* eslint-disable-next-line import/no-unresolved, import/no-extraneous-dependencies */
|
|
3
|
-
import Vue from 'vue';
|
|
4
|
-
|
|
5
|
-
import { appId, getAppProps, isOffline } from '../../common';
|
|
6
|
-
|
|
7
|
-
const offlineModeMixin = {
|
|
8
|
-
mounted() {
|
|
9
|
-
const $anchors = this.$el.querySelectorAll('a');
|
|
10
|
-
$anchors.forEach(($anchor) => {
|
|
11
|
-
$anchor.addEventListener('click', (e) => {
|
|
12
|
-
e.preventDefault();
|
|
13
|
-
window.$svjq($anchor).trigger('click');
|
|
14
|
-
}, false);
|
|
15
|
-
});
|
|
16
|
-
},
|
|
17
|
-
};
|
|
18
|
-
/**
|
|
19
|
-
* Renders a client side Vue application.
|
|
20
|
-
* @param {*} App Vue app root component.
|
|
21
|
-
* @param {Object} [settings={}] Settings object.
|
|
22
|
-
* @param {String} [settings.selector=`#app_mount_${appId}`] Query selector for mount element.
|
|
23
|
-
*/
|
|
24
|
-
export function render(App, { selector = `#app_mount_${appId}` } = {}) {
|
|
25
|
-
const options = getAppProps();
|
|
26
|
-
|
|
27
|
-
Object.assign(App, options, {
|
|
28
|
-
propsData: options,
|
|
29
|
-
mixins: isOffline ? [offlineModeMixin] : [],
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
new Vue(App).$mount(selector);
|
|
33
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/* eslint-disable global-require */
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Regex for selecting trailing slashes
|
|
5
|
-
* @constant {Regex}
|
|
6
|
-
*/
|
|
7
|
-
const trailingSlashes = /(\/)*$/g;
|
|
8
|
-
|
|
9
|
-
export default function getRouteUri(route) {
|
|
10
|
-
const PortletContextUtil = require('PortletContextUtil');
|
|
11
|
-
const currentPage = PortletContextUtil.getCurrentPage();
|
|
12
|
-
const currentPortlet = PortletContextUtil.getCurrentPortlet();
|
|
13
|
-
if (currentPage && currentPortlet) {
|
|
14
|
-
const currentPageId = currentPage.getIdentifier().replace('_sitePage', '');
|
|
15
|
-
const currentPortletId = currentPortlet.getIdentifier();
|
|
16
|
-
return `/appresource/${currentPageId}/${currentPortletId}/${route}`.replace(trailingSlashes, '');
|
|
17
|
-
}
|
|
18
|
-
return '/';
|
|
19
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/* eslint-disable global-require */
|
|
2
|
-
|
|
3
|
-
export default function getViewUri(route, { isOffline }) {
|
|
4
|
-
const PortletContextUtil = require('PortletContextUtil');
|
|
5
|
-
const PropertyUtil = require('PropertyUtil');
|
|
6
|
-
const appInfo = require('appInfo');
|
|
7
|
-
const currentPage = PortletContextUtil.getCurrentPage();
|
|
8
|
-
const currentPortlet = PortletContextUtil.getCurrentPortlet();
|
|
9
|
-
|
|
10
|
-
if (currentPage && currentPortlet) {
|
|
11
|
-
const currentPageId = currentPage.getIdentifier().replace('_sitePage', '');
|
|
12
|
-
const currentPageUri = PropertyUtil.getString(currentPage, 'URI');
|
|
13
|
-
const currentPortletId = PortletContextUtil.getCurrentPortlet().getIdentifier();
|
|
14
|
-
if (isOffline) {
|
|
15
|
-
return `/edit-offline/${currentPageId}?sv.target=${currentPortletId}&sv.${currentPortletId}.route=${encodeURI(route)}`;
|
|
16
|
-
}
|
|
17
|
-
return `${currentPageUri}?sv.target=${currentPortletId}&sv.${currentPortletId}.route=${encodeURI(route)}`;
|
|
18
|
-
}
|
|
19
|
-
const addonId = appInfo['jcr:uuid'];
|
|
20
|
-
return `/edit-web-app-offline/${addonId}?sv.target=${addonId}&sv.${addonId}.route=${encodeURI(route)}`;
|
|
21
|
-
}
|
package/docs/1.render.md
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# Render
|
|
2
|
-
|
|
3
|
-
Returns HTML for a script tag with the possibility to pass data from the server.
|
|
4
|
-
Framework agnostic.
|
|
5
|
-
|
|
6
|
-
Server data is embedded as JSON in script tags.
|
|
7
|
-
<https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#embedding_data_in_html>
|
|
8
|
-
|
|
9
|
-
## index.js
|
|
10
|
-
|
|
11
|
-
### render([props], [settings]) ⇒ <code>String</code>
|
|
12
|
-
|
|
13
|
-
`@soleil-api/webapp-util/server`
|
|
14
|
-
|
|
15
|
-
Get a HTML string for rendering an application.
|
|
16
|
-
|
|
17
|
-
**Returns**: <code>String</code> - HTML for rendering an application.
|
|
18
|
-
|
|
19
|
-
| Param | Type | Default | Description |
|
|
20
|
-
| --- | --- | --- | --- |
|
|
21
|
-
| [props] | <code>Object</code> | <code>{}</code> | Props that will be passed to the app |
|
|
22
|
-
| [settings] | <code>Object</code> | <code>{}</code> | Settings object. |
|
|
23
|
-
| [settings.html] | <code>String</code> | <code>''</code> | HTML that will be rendered inside mount element. |
|
|
24
|
-
| [settings.async] | <code>Boolean</code> | <code>false</code> | If the app script should be loaded asynchronously. |
|
|
25
|
-
| [settings.defer] | <code>Boolean</code> | <code>true</code> | If the app script should be loaded after DOM is ready. |
|
|
26
|
-
| [settings.req] | <code>Object</code> | | The req object from Sitevision, pass this to optimize browser specific script loading if you have multiple instances of the app. |
|
|
27
|
-
|
|
28
|
-
[Read more about async and defer.](https://flaviocopes.com/javascript-async-defer/)
|
|
29
|
-
|
|
30
|
-
### Example
|
|
31
|
-
|
|
32
|
-
```js
|
|
33
|
-
import router from '@Sitevision/api/common/router';
|
|
34
|
-
import { render } from '@soleil-api/webapp-util/server';
|
|
35
|
-
|
|
36
|
-
router.get('/', (req, res) => {
|
|
37
|
-
const props = { foo: 'bar' };
|
|
38
|
-
res.send(render(props));
|
|
39
|
-
};
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
**All settings**
|
|
43
|
-
|
|
44
|
-
```js
|
|
45
|
-
import router from '@Sitevision/api/common/router';
|
|
46
|
-
import { render } from '@soleil-api/webapp-util/server';
|
|
47
|
-
|
|
48
|
-
router.get('/', (req, res) => {
|
|
49
|
-
const props = { foo: 'bar' };
|
|
50
|
-
const settings = {
|
|
51
|
-
html: '<noscript>You can put a noscript message here for example!</noscript>',
|
|
52
|
-
async: false,
|
|
53
|
-
defer: true,
|
|
54
|
-
req,
|
|
55
|
-
}
|
|
56
|
-
res.send(render(props, settings));
|
|
57
|
-
};
|
|
58
|
-
```
|
package/docs/2.svelte.md
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
# Svelte
|
|
2
|
-
|
|
3
|
-
Sitevision supports both server and client side rendering with Svelte.
|
|
4
|
-
|
|
5
|
-
## index.js
|
|
6
|
-
|
|
7
|
-
For rendering a client side only app use the framework agnostic [client renderer](./1.render.md).
|
|
8
|
-
|
|
9
|
-
### `render(App, [props], [settings])`
|
|
10
|
-
|
|
11
|
-
`@soleil-api/webapp-util/server/svelte`
|
|
12
|
-
|
|
13
|
-
Get a HTML string for rendering a universal Svelte application.
|
|
14
|
-
If a client bundle is available the server rendered HTML will be hydrated and not completely re-rendered.
|
|
15
|
-
|
|
16
|
-
**Returns**: <code>String</code> - HTML for rendering a Svelte application.
|
|
17
|
-
|
|
18
|
-
| Param | Type | Default | Description |
|
|
19
|
-
| --- | --- | --- | --- |
|
|
20
|
-
| [App] | <code>Svelte</code> | | Svelte app to be rendered. |
|
|
21
|
-
| [props] | <code>Object</code> | <code>{}</code> | Props that will be passed to the app. |
|
|
22
|
-
| [settings] | <code>Object</code> | <code>{}</code> | Settings object. Forwarded to |
|
|
23
|
-
| [settings.async] | <code>Boolean</code> | <code>false</code> | If the app script should be loaded asynchronously. |
|
|
24
|
-
| [settings.defer] | <code>Boolean</code> | <code>true</code> | If the app script should be loaded after DOM is ready. |
|
|
25
|
-
| [settings.req] | <code>Object</code> | | The req object from Sitevision, pass this to optimize browser specific script loading if you have multiple instances of the app. |
|
|
26
|
-
|
|
27
|
-
[Read more about async and defer.](https://flaviocopes.com/javascript-async-defer/)
|
|
28
|
-
|
|
29
|
-
In `app_src/index.js` or `app_src/server/index.js`.
|
|
30
|
-
|
|
31
|
-
```javascript
|
|
32
|
-
import router from '@Sitevision/api/common/router';
|
|
33
|
-
import { render } from '@soleil-api/webapp-util/server/svelte';
|
|
34
|
-
|
|
35
|
-
import App from './App.svelte';
|
|
36
|
-
|
|
37
|
-
router.get('/', (req, res) => {
|
|
38
|
-
const props = { foo: 'bar' };
|
|
39
|
-
res.send(render(App, props));
|
|
40
|
-
});
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### `renderServer(App, [props])`
|
|
44
|
-
|
|
45
|
-
`@soleil-api/webapp-util/server/svelte`
|
|
46
|
-
|
|
47
|
-
Get a HTML string for rendering a server side Svelte application.
|
|
48
|
-
|
|
49
|
-
**Returns**: <code>String</code> - HTML for rendering a Svelte application.
|
|
50
|
-
|
|
51
|
-
| Param | Type | Default | Description |
|
|
52
|
-
| --- | --- | --- | --- |
|
|
53
|
-
| [App] | <code>Svelte</code> | | Svelte app to be rendered. |
|
|
54
|
-
| [props] | <code>Object</code> | <code>{}</code> | Server data that will be available as props and as app data. |
|
|
55
|
-
|
|
56
|
-
In `app_src/index.js` or `app_src/server/index.js`.
|
|
57
|
-
|
|
58
|
-
```javascript
|
|
59
|
-
import router from '@Sitevision/api/common/router';
|
|
60
|
-
import { renderServer } from '@soleil-api/webapp-util/server/svelte';
|
|
61
|
-
|
|
62
|
-
import App from './App.svelte';
|
|
63
|
-
|
|
64
|
-
router.get('/', (req, res) => {
|
|
65
|
-
const props = { foo: 'bar' };
|
|
66
|
-
res.send(render(App, props));
|
|
67
|
-
});
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
## main.js
|
|
71
|
-
|
|
72
|
-
### `render(App, [settings])`
|
|
73
|
-
|
|
74
|
-
`@soleil-api/webapp-util/client/svelte`
|
|
75
|
-
|
|
76
|
-
Renders a client side Svelte application.
|
|
77
|
-
|
|
78
|
-
**Returns**: <code>\*</code> - Initialized Svelte component.
|
|
79
|
-
|
|
80
|
-
| Param | Type | Default | Description |
|
|
81
|
-
| --- | --- | --- | --- |
|
|
82
|
-
| App | <code>\*</code> | | Svelte app root component. |
|
|
83
|
-
| [settings] | <code>Object</code> | <code>{}</code> | Settings object. |
|
|
84
|
-
| [settings.selector] | <code>String</code> | <code>`#app_mount_${appId}`</code> | Query selector for mount element. |
|
|
85
|
-
| [settings.intro] | <code>String</code> | <code>false</code> | If true, will play transitions on initial render, rather than waiting for subsequent state changes. |
|
|
86
|
-
|
|
87
|
-
In `app_src/main.js` or `app_src/client/index.js`.
|
|
88
|
-
|
|
89
|
-
```javascript
|
|
90
|
-
import { render } from '@soleil-api/webapp-util/client/svelte';
|
|
91
|
-
import App from './App.svelte';
|
|
92
|
-
|
|
93
|
-
render(App);
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
Mount the app in another element:
|
|
97
|
-
|
|
98
|
-
```javascript
|
|
99
|
-
import { render } from '@soleil-api/webapp-util/client/svelte';
|
|
100
|
-
import App from './App.svelte';
|
|
101
|
-
|
|
102
|
-
render(App, { selector: '#mount_app_here' });
|
|
103
|
-
```
|
package/docs/3.vue.md
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# Vue
|
|
2
|
-
|
|
3
|
-
Sitevision supports client side rendering with Vue.
|
|
4
|
-
|
|
5
|
-
## index.js
|
|
6
|
-
|
|
7
|
-
For rendering a client side only app use the framework agnostic [client renderer](./1.render.md).
|
|
8
|
-
|
|
9
|
-
## main.js
|
|
10
|
-
|
|
11
|
-
### `render(App, [settings])`
|
|
12
|
-
|
|
13
|
-
`@soleil-api/webapp-util/client/vue`
|
|
14
|
-
Renders a client side Vue application.
|
|
15
|
-
|
|
16
|
-
| Param | Type | Default | Description |
|
|
17
|
-
| --- | --- | --- | --- |
|
|
18
|
-
| App | <code>\*</code> | | Vue app root component. |
|
|
19
|
-
| [settings] | <code>Object</code> | <code>{}</code> | Settings object. |
|
|
20
|
-
| [settings.selector] | <code>String</code> | <code>`#app_mount_${appId}`</code> | Query selector for mount element. |
|
|
21
|
-
|
|
22
|
-
In `app_src/main.js` or `app_src/client/index.js`.
|
|
23
|
-
|
|
24
|
-
```javascript
|
|
25
|
-
import { render } from '@soleil-api/webapp-util/client/vue';
|
|
26
|
-
import App from './App.vue';
|
|
27
|
-
|
|
28
|
-
render(App);
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
Mount the app in another element:
|
|
32
|
-
|
|
33
|
-
```javascript
|
|
34
|
-
import { render } from '@soleil-api/webapp-util/client/vue';
|
|
35
|
-
import App from './App.vue';
|
|
36
|
-
|
|
37
|
-
render(App, { selector: '#mount_app_here' });
|
|
38
|
-
```
|
package/docs/4.underscore.md
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# Underscore
|
|
2
|
-
|
|
3
|
-
Render a Underscore template.
|
|
4
|
-
|
|
5
|
-
## `renderTemplate(template, [values])` ⇒ `String`
|
|
6
|
-
|
|
7
|
-
Renders a Underscore template and returns a string.
|
|
8
|
-
This function is also available inside the template.
|
|
9
|
-
|
|
10
|
-
**Returns**: `String` - Rendered template
|
|
11
|
-
|
|
12
|
-
| Param | Type | Default | Description |
|
|
13
|
-
| --- | --- | --- | --- |
|
|
14
|
-
| template | `String` | | Underscore template. |
|
|
15
|
-
| [values] | `Object` | `{}` | Values. |
|
|
16
|
-
|
|
17
|
-
### Examples
|
|
18
|
-
|
|
19
|
-
**Simple example**
|
|
20
|
-
|
|
21
|
-
```javascript
|
|
22
|
-
import { renderTemplate } from '@soleil-api/webapp-util/server';
|
|
23
|
-
|
|
24
|
-
const string = renderTemplate('<div><%= foo %></div>', {
|
|
25
|
-
foo: 'bar',
|
|
26
|
-
});
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
**Multiple templates**
|
|
30
|
-
|
|
31
|
-
```html
|
|
32
|
-
/* views/item.html */
|
|
33
|
-
<li>
|
|
34
|
-
<%- name %>
|
|
35
|
-
</li>
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
```html
|
|
39
|
-
/* views/main.html */
|
|
40
|
-
<ul>
|
|
41
|
-
<% items.forEach(function(item) { %>
|
|
42
|
-
<%= renderTemplate(itemTemplate, item) %>
|
|
43
|
-
<% }); %>
|
|
44
|
-
</ul>
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
```javascript
|
|
48
|
-
import { renderTemplate } from '@soleil-api/webapp-util/server';
|
|
49
|
-
import mainTemplate from './views/main.html';
|
|
50
|
-
import itemTemplate from './views/item.html';
|
|
51
|
-
|
|
52
|
-
const items = [{ name: 'Foo' }, { name: 'Bar' }, { name: 'Baz' }];
|
|
53
|
-
const string = renderTemplate(mainTemplate, { items, itemTemplate });
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
> **NOTE**
|
|
57
|
-
> Remember that the second argument must be an object and that objects properties are accessed directly in any child templates!
|
package/server/index.js
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { appImportDate } from 'appInfo';
|
|
2
|
-
import {
|
|
3
|
-
appId, isOffline, getResourceUri, getAppMetadata,
|
|
4
|
-
} from '../common';
|
|
5
|
-
|
|
6
|
-
const isIE = (req) => {
|
|
7
|
-
if (!req) return true;
|
|
8
|
-
const userAgent = req.header('user-agent');
|
|
9
|
-
return /Trident\/|MSIE/.test(userAgent);
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
const escapeTags = (unsafe) => unsafe
|
|
13
|
-
.replace(/</g, '<')
|
|
14
|
-
.replace(/>/g, '>');
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Get a HTML string for rendering an application.
|
|
18
|
-
* @param {Object} [props={}] Props that will be passed to the app.
|
|
19
|
-
* @param {Object} [settings={}] Settings object.
|
|
20
|
-
* @param {String} [settings.html=''] HTML that will be rendered inside mount element.
|
|
21
|
-
* where the app should be mounted.
|
|
22
|
-
* @param {Boolean} [settings.async=false] If the app script should be loaded asynchronously.
|
|
23
|
-
* [Read more about async and defer.](https://flaviocopes.com/javascript-async-defer/)
|
|
24
|
-
* @param {Boolean} [settings.defer=true] If the app script should be loaded after DOM is ready.
|
|
25
|
-
* [Read more about async and defer.](https://flaviocopes.com/javascript-async-defer/)
|
|
26
|
-
* @param {Object} [settings.req] The req object from Sitevision, pass this to optimize browser
|
|
27
|
-
* specific script loading if you have multiple instances of the app.
|
|
28
|
-
* @returns {String} HTML for rendering an application.
|
|
29
|
-
*/
|
|
30
|
-
export function render(props, {
|
|
31
|
-
html = '',
|
|
32
|
-
async = false,
|
|
33
|
-
defer = true,
|
|
34
|
-
req,
|
|
35
|
-
} = {}) {
|
|
36
|
-
const appMetadata = getAppMetadata();
|
|
37
|
-
|
|
38
|
-
const mountElement = `<div id="app_mount_${appId}">${html}</div>`;
|
|
39
|
-
const metaScriptTag = `<script data-id="app_meta_${appId}" type="application/json">${JSON.stringify(appMetadata)}</script>`;
|
|
40
|
-
const propsScriptTag = props ? `<script data-id="app_props_${appId}" type="application/json">${escapeTags(JSON.stringify(props))}</script>` : '';
|
|
41
|
-
|
|
42
|
-
if (isOffline) {
|
|
43
|
-
return `
|
|
44
|
-
${mountElement}
|
|
45
|
-
${metaScriptTag}
|
|
46
|
-
${propsScriptTag}
|
|
47
|
-
<script>
|
|
48
|
-
window.svDocReady(function() {
|
|
49
|
-
var targetElement = document.getElementById('app_mount_${appId}');
|
|
50
|
-
var script = document.createElement("script");
|
|
51
|
-
script.src = "${getResourceUri('client/index.js')}?${appImportDate}${appId}";
|
|
52
|
-
script.setAttribute("data-app-id", "${appId}");
|
|
53
|
-
targetElement.parentNode.insertBefore(script, targetElement.nextSibling);
|
|
54
|
-
});
|
|
55
|
-
</script>`;
|
|
56
|
-
}
|
|
57
|
-
return `
|
|
58
|
-
${mountElement}
|
|
59
|
-
${metaScriptTag}
|
|
60
|
-
${propsScriptTag}
|
|
61
|
-
<script
|
|
62
|
-
src="${getResourceUri('client/index.js')}?${appImportDate}${isIE(req) ? appId : ''}"
|
|
63
|
-
data-app-id="${appId}"
|
|
64
|
-
${async && !defer ? 'async' : ''}
|
|
65
|
-
${defer ? 'defer' : ''}>
|
|
66
|
-
</script>`;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Renders a Underscore template and returns a string.
|
|
71
|
-
* @param {String} template Underscore template.
|
|
72
|
-
* @param {Object} [values={}] Values.
|
|
73
|
-
* @returns {String} Rendered template
|
|
74
|
-
*/
|
|
75
|
-
export function renderTemplate(template, values = {}) {
|
|
76
|
-
// Import undercore dynamically in the rare case this function is still used.
|
|
77
|
-
// eslint-disable-next-line global-require
|
|
78
|
-
const _ = require('undercore');
|
|
79
|
-
if (typeof template === 'function') {
|
|
80
|
-
return template({ ...values, renderTemplate });
|
|
81
|
-
}
|
|
82
|
-
return _.template(template)(({ ...values, renderTemplate }));
|
|
83
|
-
}
|