marko 5.22.2 → 5.22.4
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +86 -86
- package/dist/core-tags/core/await/index.marko +13 -0
- package/docs/rollup.md +266 -114
- package/docs/troubleshooting-streaming.md +8 -2
- package/index.d.ts +317 -0
- package/package.json +6 -4
- package/src/core-tags/core/await/index.marko +13 -0
package/README.md
CHANGED
@@ -1,84 +1,75 @@
|
|
1
|
-
<
|
2
|
-
<a href="https://markojs.com/"><img src="https://raw.githubusercontent.com/marko-js/branding/master/marko-logo-medium-cropped.png" alt="Marko" width="250" /></a>
|
3
|
-
</h1>
|
1
|
+
<div align="center">
|
4
2
|
|
5
|
-
<
|
6
|
-
<strong>A declarative, HTML-based language that makes building web apps fun 🔥</strong>
|
7
|
-
</p>
|
3
|
+
# [<img alt="Marko" src="https://raw.githubusercontent.com/marko-js/branding/master/marko-logo-medium-cropped.png" width="250">](https://markojs.com/)
|
8
4
|
|
9
|
-
|
10
|
-
<a href="https://www.npmjs.com/package/marko"><img alt="NPM" src="https://img.shields.io/npm/v/marko.svg"/></a>
|
11
|
-
<a href="https://discord.gg/RFGxYGs"><img alt="Discord" src="https://img.shields.io/badge/discord-chat-7188da.svg"/></a>
|
12
|
-
<a href="https://github.com/marko-js/marko/actions/workflows/ci.yml">
|
13
|
-
<img src="https://github.com/marko-js/marko/actions/workflows/ci.yml/badge.svg" alt="Build status"/>
|
14
|
-
</a>
|
15
|
-
<a href="https://codecov.io/gh/marko-js/marko"><img alt="Coverage Status" src="https://codecov.io/gh/marko-js/marko/branch/master/graph/badge.svg"/></a>
|
16
|
-
<a href="http://npm-stat.com/charts.html?package=marko"><img alt="Downloads" src="https://img.shields.io/npm/dm/marko.svg"/></a>
|
17
|
-
</p>
|
5
|
+
**A declarative, HTML-based language that makes building web apps fun 🔥**
|
18
6
|
|
19
|
-
|
20
|
-
|
21
|
-
|
7
|
+
[![NPM](https://img.shields.io/npm/v/marko.svg)](https://www.npmjs.com/package/marko)
|
8
|
+
[![Discord Chat](https://img.shields.io/badge/discord-chat-7188da.svg)](https://discord.gg/RFGxYGs)
|
9
|
+
[![Continuous Integration status](https://github.com/marko-js/marko/actions/workflows/ci.yml/badge.svg)](https://github.com/marko-js/marko/actions/workflows/ci.yml)
|
10
|
+
[![Code coverage %](https://codecov.io/gh/marko-js/marko/branch/master/graph/badge.svg)](https://codecov.io/gh/marko-js/marko)
|
11
|
+
[![# of monthly downloads](https://img.shields.io/npm/dm/marko.svg)](https://npm-stat.com/charts.html?package=marko)
|
22
12
|
|
23
|
-
#
|
13
|
+
[Docs](https://markojs.com/docs/getting-started/) ∙ [Try Online](https://markojs.com/try-online/) ∙ [Contribute](#contributors) ∙ [Get Support](#community--support)
|
24
14
|
|
25
|
-
|
26
|
-
|
27
|
-
|
15
|
+
</div>
|
16
|
+
|
17
|
+
## Intro
|
28
18
|
|
29
|
-
Among these extensions are [conditionals
|
30
|
-
Marko supports both single-file components and components broken into separate files.
|
19
|
+
Marko is HTML _reimagined_ as a language for building dynamic and reactive user interfaces. Almost any valid HTML is valid Marko, and Marko extends HTML for building modern applications more declaratively. Among these extensions are [conditionals and lists](https://markojs.com/docs/conditionals-and-lists/), [state](https://markojs.com/docs/state/), and [components](https://markojs.com/docs/class-components/).
|
31
20
|
|
32
|
-
|
21
|
+
Marko supports both single-file components and components across separate files.
|
33
22
|
|
34
|
-
|
35
|
-
|
23
|
+
### Single-file component
|
24
|
+
|
25
|
+
The following renders a button and a counter of how many times the button has been pressed:
|
36
26
|
|
37
27
|
**click-count.marko**
|
38
28
|
|
39
29
|
```marko
|
40
30
|
class {
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
31
|
+
onCreate() {
|
32
|
+
this.state = { count: 0 };
|
33
|
+
}
|
34
|
+
increment() {
|
35
|
+
this.state.count++;
|
36
|
+
}
|
47
37
|
}
|
48
38
|
|
49
39
|
style {
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
}
|
40
|
+
.count {
|
41
|
+
color: #09c;
|
42
|
+
font-size: 3em;
|
43
|
+
}
|
44
|
+
.press-me {
|
45
|
+
padding: 0.5em;
|
46
|
+
}
|
58
47
|
}
|
59
48
|
|
60
|
-
<
|
61
|
-
|
62
|
-
</
|
63
|
-
<button.
|
64
|
-
|
49
|
+
<output.count>
|
50
|
+
${state.count}
|
51
|
+
</output>
|
52
|
+
<button.press-me on-click('increment')>
|
53
|
+
Press me!
|
65
54
|
</button>
|
66
55
|
```
|
67
56
|
|
68
|
-
|
57
|
+
### Multi-file component
|
58
|
+
|
59
|
+
The same component as above, but split into:
|
69
60
|
|
70
|
-
|
71
|
-
`component.js`
|
72
|
-
component
|
61
|
+
- `index.marko` template file
|
62
|
+
- `component.js` component JS logic file
|
63
|
+
- `style.css` component styles file
|
73
64
|
|
74
65
|
**index.marko**
|
75
66
|
|
76
67
|
```marko
|
77
|
-
<
|
78
|
-
|
79
|
-
</
|
80
|
-
<button.
|
81
|
-
|
68
|
+
<output.count>
|
69
|
+
${state.count}
|
70
|
+
</output>
|
71
|
+
<button.press-me on-click('increment')>
|
72
|
+
Press me!
|
82
73
|
</button>
|
83
74
|
```
|
84
75
|
|
@@ -102,59 +93,68 @@ export default {
|
|
102
93
|
color: #09c;
|
103
94
|
font-size: 3em;
|
104
95
|
}
|
105
|
-
.
|
106
|
-
font-size: 1em;
|
96
|
+
.press-me {
|
107
97
|
padding: 0.5em;
|
108
98
|
}
|
109
99
|
```
|
110
100
|
|
111
101
|
## Concise Syntax
|
112
102
|
|
113
|
-
Marko also supports a beautifully concise syntax as an alternative to its HTML
|
114
|
-
|
103
|
+
Marko also supports [a beautifully concise syntax as an alternative](https://markojs.com/docs/concise/) to its HTML syntax:
|
104
|
+
|
105
|
+
<table><thead><tr><th>Concise syntax<th>HTML syntax
|
106
|
+
<tbody><tr>
|
107
|
+
<td>
|
115
108
|
|
116
109
|
```marko
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
<li>${color}</li>
|
121
|
-
</for>
|
122
|
-
</ul>
|
110
|
+
ul.example-list
|
111
|
+
for|color| of=[a, b, c]
|
112
|
+
li -- ${color}
|
123
113
|
```
|
124
114
|
|
115
|
+
<td>
|
116
|
+
|
125
117
|
```marko
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
118
|
+
<ul class="example-list">
|
119
|
+
<for|color| of=[a, b, c]>
|
120
|
+
<li>${color}</li>
|
121
|
+
</for>
|
122
|
+
</ul>
|
130
123
|
```
|
131
124
|
|
132
|
-
|
125
|
+
</table>
|
126
|
+
|
127
|
+
## Getting Started
|
133
128
|
|
134
129
|
1. `npm install marko`
|
135
130
|
2. Read the [docs](https://markojs.com/docs/getting-started/)
|
136
131
|
|
137
|
-
|
132
|
+
## Community & Support
|
138
133
|
|
139
|
-
|
140
|
-
|
141
|
-
|
134
|
+
<table>
|
135
|
+
<thead><tr>
|
136
|
+
<th><img alt="Stack Overflow" src="https://user-images.githubusercontent.com/1958812/56055468-619b3e00-5d0e-11e9-92ae-200c212cafb8.png" width="205">
|
137
|
+
<th><img alt="Discord" src="https://user-images.githubusercontent.com/4985201/89313514-6edbea80-d62d-11ea-8447-ca2fd8983661.png" width="162">
|
138
|
+
<th><img alt="Twitter" src="https://user-images.githubusercontent.com/1958812/56055707-07e74380-5d0f-11e9-8a59-d529fbb5a81e.png" width="53">
|
139
|
+
<tbody><tr><td>
|
140
|
+
|
141
|
+
Ask and answer [StackOverflow questions with the `#marko` tag](https://stackoverflow.com/questions/tagged/marko)<td>
|
142
142
|
|
143
|
-
|
143
|
+
Come [hang out in our Discord chat](https://discord.gg/RFGxYGs), ask questions, and discuss project direction<td>
|
144
144
|
|
145
|
-
|
145
|
+
[Tweet to `@MarkoDevTeam`](https://twitter.com/MarkoDevTeam), or with the [`#markojs` hashtag](https://twitter.com/search?q=%23markojs&f=live)
|
146
146
|
|
147
|
-
|
148
|
-
<img src="https://opencollective.com/marko-js/contributors.svg?width=890&button=false"/>
|
149
|
-
</a>
|
147
|
+
</table>
|
150
148
|
|
151
|
-
|
149
|
+
### Contributors
|
152
150
|
|
153
|
-
|
154
|
-
|
155
|
-
-
|
156
|
-
- By participating in this project you agree to abide by its [Code of Conduct](https://ebay.github.io/codeofconduct).
|
151
|
+
Marko would not be what it is without all those who have contributed ✨
|
152
|
+
|
153
|
+
[![All marko-js/marko GitHub contributors](https://opencollective.com/marko-js/contributors.svg?width=890&button=false)](https://github.com/marko-js/marko/graphs/contributors)
|
157
154
|
|
158
|
-
|
155
|
+
### Get Involved!
|
159
156
|
|
160
|
-
|
157
|
+
- Pull requests are welcome!
|
158
|
+
- Submit [GitHub issues](https://github.com/marko-js/marko/issues) for any feature enhancements, bugs, or documentation problems
|
159
|
+
- [Read the Contribution Tips and Guidelines](.github/CONTRIBUTING.md)
|
160
|
+
- Participants in this project agree to abide by [its Code of Conduct](https://github.com/eBay/.github/blob/main/CODE_OF_CONDUCT.md)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/**
|
2
|
+
* @template T
|
3
|
+
* @typedef {{
|
4
|
+
* value?: T;
|
5
|
+
* then?: Marko.Body<[Awaited<T>], void>;
|
6
|
+
* catch?: Marko.Body<[unknown], void>;
|
7
|
+
* placeholder?: Marko.Body<[], void>;
|
8
|
+
* client-reorder?: boolean;
|
9
|
+
* name?: string;
|
10
|
+
* timeout?: number;
|
11
|
+
* show-after?: string;
|
12
|
+
* }} Input
|
13
|
+
*/
|
package/docs/rollup.md
CHANGED
@@ -1,155 +1,309 @@
|
|
1
1
|
# Marko + Rollup
|
2
2
|
|
3
|
-
|
3
|
+
This is Marko’s official integration plugin for [the Rollup bundler](https://rollupjs.org/).
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
```sh
|
8
|
+
npm install --save-dev \
|
9
|
+
@marko/rollup \
|
10
|
+
rollup \
|
11
|
+
@rollup/plugin-node-resolve \
|
12
|
+
@rollup/plugin-commonjs
|
7
13
|
```
|
8
14
|
|
9
|
-
|
15
|
+
> **Note**: The Marko runtime is CommonJS, so don’t forget the `@rollup/plugin-commonjs` package!
|
16
|
+
|
17
|
+
## Configuration
|
18
|
+
|
19
|
+
`@marko/rollup` exports two methods for use in [Rollup configuration files](https://rollupjs.org/guide/en/#configuration-files): `.browser()` and `.server()`.
|
20
|
+
|
21
|
+
You _probably_ want to use both, since that’ll get you…
|
22
|
+
|
23
|
+
- Automatic [`input` entrypoint configuration](https://rollupjs.org/guide/en/#input) for route-based bundle splitting
|
24
|
+
- Complete control over asset loading with [the `<rollup>` tag](#rollup-tag)
|
25
|
+
- The strengths behind why Marko exists in the first place: cooperation between servers and browsers for high performance in both
|
26
|
+
|
27
|
+
> **ProTip**: You _could_ use only `.browser()` or only `.server()` to build a completely client-side-rendered or server-side-rendered app. That would be a little odd, but you could.
|
10
28
|
|
11
|
-
|
29
|
+
### Config example
|
12
30
|
|
13
|
-
```
|
31
|
+
```js
|
14
32
|
import nodeResolve from "@rollup/plugin-node-resolve";
|
15
33
|
import commonjs from "@rollup/plugin-commonjs";
|
16
34
|
import marko from "@marko/rollup";
|
17
35
|
|
18
|
-
|
19
|
-
|
36
|
+
const sharedPlugins = [
|
37
|
+
commonjs({
|
38
|
+
extensions: [".js", ".marko"]
|
39
|
+
}),
|
40
|
+
// If using Marko’s `style {}` blocks, you’ll need an appropriate plugin, like npmjs.com/rollup-plugin-postcss
|
41
|
+
postcss({ external: true })
|
42
|
+
]
|
43
|
+
|
44
|
+
const serverAssetsConfig = {
|
45
|
+
input: "src/start-server.js",
|
46
|
+
plugins: [
|
47
|
+
marko.server(),
|
48
|
+
nodeResolve({ preferBuiltins: true })
|
49
|
+
...sharedPlugins
|
50
|
+
]
|
51
|
+
};
|
52
|
+
const browsersAssetsConfig = {
|
20
53
|
plugins: [
|
21
54
|
marko.browser(),
|
22
|
-
nodeResolve({
|
23
|
-
|
24
|
-
extensions: [".js", ".marko"]
|
25
|
-
}),
|
26
|
-
// NOTE: The Marko runtime uses commonjs so this plugin is also required.
|
27
|
-
commonjs({
|
28
|
-
extensions: [".js", ".marko"]
|
29
|
-
}),
|
30
|
-
// If using `style` blocks with Marko you must use an appropriate plugin.
|
31
|
-
postcss({
|
32
|
-
external: true
|
33
|
-
})
|
55
|
+
nodeResolve({ browser: true })
|
56
|
+
...sharedPlugins
|
34
57
|
]
|
35
58
|
};
|
59
|
+
|
60
|
+
export default [serverAssetsConfig, browsersAssetsConfig];
|
36
61
|
```
|
37
62
|
|
38
|
-
|
63
|
+
### Advanced config example
|
39
64
|
|
40
|
-
|
65
|
+
The following configuration file is long and hairy, which may be upsetting to some viewers. However, it does show how to accomplish the following:
|
41
66
|
|
42
|
-
|
43
|
-
|
44
|
-
|
67
|
+
- Support for Rollup’s watch mode
|
68
|
+
- A bundle analyzer
|
69
|
+
- The ability to `import` JSON files to use their data
|
70
|
+
- The ability to `import` image files to use their asset URLs for `img[src]` and such
|
71
|
+
- Dead-code elimination for development-only code
|
72
|
+
- Static compression of assets for something like [NGiNX’s `gzip_static`](https://nginx.org/en/docs/http/ngx_http_gzip_static_module.html)
|
73
|
+
- A CSS preprocessor (Sass, in this case)
|
74
|
+
- Browserslist to automatically configure:
|
75
|
+
- Babel for JS transpilation
|
76
|
+
- Autoprefixer for CSS transpilation
|
45
77
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
78
|
+
<details><summary>Big ugly production-esque Rollup config</summary>
|
79
|
+
|
80
|
+
```js
|
81
|
+
import { builtinModules } from "module";
|
82
|
+
import path from "path";
|
83
|
+
import autoprefixer from "autoprefixer";
|
84
|
+
import babelPlugin from "@rollup/plugin-babel";
|
85
|
+
import commonjsPlugin from "@rollup/plugin-commonjs";
|
86
|
+
import jsonPlugin from "@rollup/plugin-json";
|
87
|
+
import markoPlugin from "@marko/rollup";
|
88
|
+
import nodeResolvePlugin from "@rollup/plugin-node-resolve";
|
89
|
+
import replacePlugin from "@rollup/plugin-replace";
|
90
|
+
import runPlugin from "@rollup/plugin-run";
|
91
|
+
import stylesPlugin from "rollup-plugin-styles";
|
92
|
+
import urlPlugin from "@rollup/plugin-url";
|
93
|
+
import pkg from "./package.json";
|
94
|
+
|
95
|
+
const __DEV__ = process.env.NODE_ENV === "development";
|
96
|
+
const __PROD__ = !__DEV__;
|
97
|
+
|
98
|
+
const isWatch = Boolean(process.env.ROLLUP_WATCH);
|
99
|
+
|
100
|
+
const publicPath = "/s/"; // Guess what character is only 5 bits under HPACK
|
101
|
+
const assetFileNames = "[name]-[hash][extname]";
|
102
|
+
|
103
|
+
const externalDependencies = [
|
104
|
+
...Object.keys(pkg.dependencies),
|
105
|
+
...builtinModules
|
106
|
+
];
|
107
|
+
|
108
|
+
process.env.SASS_PATH = "./:./node_modules";
|
109
|
+
|
110
|
+
export default (async () => [
|
111
|
+
compiler("server", {
|
112
|
+
input: "index.js",
|
113
|
+
output: {
|
114
|
+
dir: "built/server/",
|
115
|
+
assetFileNames: `../browser/${assetFileNames}`,
|
116
|
+
format: "cjs",
|
117
|
+
sourcemap: true
|
118
|
+
},
|
119
|
+
external: id =>
|
120
|
+
externalDependencies.some(
|
121
|
+
dependency => id === dependency || id.startsWith(dependency + "/")
|
122
|
+
),
|
123
|
+
plugins: [isWatch && runPlugin({ execArgv: ["--enable-source-maps"] })]
|
124
|
+
}),
|
125
|
+
|
126
|
+
compiler("browser", {
|
127
|
+
output: {
|
128
|
+
dir: "built/browser/",
|
129
|
+
chunkFileNames: __PROD__ ? "[name]-[hash].js" : null,
|
130
|
+
entryFileNames: __PROD__ ? "[name]-[hash].js" : null,
|
131
|
+
assetFileNames,
|
132
|
+
sourcemap: true,
|
133
|
+
sourcemapExcludeSources: __PROD__
|
134
|
+
},
|
135
|
+
plugins: [
|
136
|
+
stylesPlugin({
|
137
|
+
mode: "extract",
|
138
|
+
sourceMap: true,
|
139
|
+
config: {
|
140
|
+
target: "browserslist:css",
|
141
|
+
plugins: [autoprefixer({ env: "css" })]
|
142
|
+
},
|
143
|
+
minimize: __PROD__,
|
144
|
+
url: {
|
145
|
+
publicPath,
|
146
|
+
hash: assetFileNames
|
147
|
+
}
|
148
|
+
}),
|
149
|
+
__PROD__ && (await import("rollup-plugin-terser")).terser(),
|
150
|
+
__PROD__ &&
|
151
|
+
(await import("rollup-plugin-gzip")).default({
|
152
|
+
filter: /\.(?:js|css|svg|json|xml|txt)$/,
|
153
|
+
minSize: 1024,
|
154
|
+
gzipOptions: {
|
155
|
+
level: 9,
|
156
|
+
memLevel: 9
|
157
|
+
}
|
158
|
+
}),
|
159
|
+
__PROD__ &&
|
160
|
+
!isWatch &&
|
161
|
+
(await import("rollup-plugin-visualizer")).default(),
|
162
|
+
__PROD__ &&
|
163
|
+
!isWatch && {
|
164
|
+
name: "bundle-visualizer-location",
|
165
|
+
writeBundle() {
|
166
|
+
console.info(
|
167
|
+
`📊 Bundle visualizer at \x1b[4;36mfile://${path.join(
|
168
|
+
__dirname,
|
169
|
+
"../../",
|
170
|
+
bundleAnalyzerFilename
|
171
|
+
)}\x1b[0m`
|
172
|
+
);
|
173
|
+
}
|
174
|
+
}
|
175
|
+
]
|
176
|
+
})
|
177
|
+
])();
|
178
|
+
|
179
|
+
function compiler(target, config) {
|
180
|
+
const isBrowser = target === "browser";
|
181
|
+
const browserslistEnv = isBrowser ? "js" : "server";
|
182
|
+
const babelConfig = {
|
183
|
+
comments: false,
|
184
|
+
browserslistEnv,
|
185
|
+
compact: false,
|
186
|
+
babelrc: false,
|
187
|
+
caller: { target }
|
188
|
+
};
|
189
|
+
if (isBrowser) {
|
190
|
+
babelConfig.presets = [
|
191
|
+
[
|
192
|
+
"@babel/preset-env",
|
193
|
+
{
|
194
|
+
browserslistEnv,
|
195
|
+
bugfixes: true
|
196
|
+
}
|
197
|
+
]
|
198
|
+
];
|
199
|
+
}
|
200
|
+
|
201
|
+
return {
|
202
|
+
...config,
|
203
|
+
preserveEntrySignatures: false,
|
204
|
+
plugins: [
|
205
|
+
markoPlugin[target]({ babelConfig }),
|
206
|
+
nodeResolvePlugin({
|
207
|
+
browser: isBrowser,
|
208
|
+
preferBuiltins: !isBrowser
|
209
|
+
}),
|
210
|
+
commonjsPlugin(),
|
211
|
+
replacePlugin({
|
212
|
+
preventAssignment: true,
|
213
|
+
values: { __DEV__, __PROD__ }
|
214
|
+
}),
|
215
|
+
babelPlugin({
|
216
|
+
babelHelpers: "bundled",
|
217
|
+
...babelConfig
|
218
|
+
}),
|
219
|
+
jsonPlugin(),
|
220
|
+
urlPlugin({
|
221
|
+
publicPath,
|
222
|
+
destDir: "built/browser/",
|
223
|
+
fileName: assetFileNames,
|
224
|
+
include: "**/*.{svg,png,jpg,jpeg}",
|
225
|
+
limit: 0, // Never Base64 & inline
|
226
|
+
emitFiles: !isBrowser
|
227
|
+
}),
|
228
|
+
...config.plugins
|
229
|
+
]
|
230
|
+
};
|
231
|
+
}
|
61
232
|
```
|
62
233
|
|
234
|
+
</details>
|
235
|
+
|
63
236
|
## `<rollup>` tag
|
64
237
|
|
65
|
-
|
238
|
+
Using both `.server()` and `.browser()` enables **the `<rollup>` tag**, which gives you complete control over how your app loads assets. That lets you do things like:
|
66
239
|
|
67
|
-
|
68
|
-
|
240
|
+
- [Critical CSS](https://web.dev/extract-critical-css/) for components as they write out within a kB budget, or [as components first appear on the page](https://jakearchibald.com/2016/link-in-body/#a-simpler-better-way), or any other style-loading mad science
|
241
|
+
- [`module`/`nomodule` scripts](https://philipwalton.com/articles/using-native-javascript-modules-in-production-today/) for smaller bundles in modern browsers
|
242
|
+
- [Content-Security Policy `nonce`s](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce) or [Subresource `integrity` hashes](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)
|
243
|
+
- Anything a web page can do, really. You can even combine `<rollup>` with [the `serialize` option](#options.serialize) to be as fancy as you wanna be.
|
69
244
|
|
70
|
-
The
|
245
|
+
The `<rollup>` tag provides two [tag parameters](https://markojs.com/docs/syntax/#parameters):
|
246
|
+
|
247
|
+
1. `entry` is the generated `input` string that the `server` plugin gave to the `browser` plugin. You can use it to find the corresponding entry chunk from Rollup’s `output` (the next parameter).
|
248
|
+
|
249
|
+
2. `output` is an array of `AssetInfo | ChunkInfo` objects with most of [the data returned from Rollup's `generateBundle` hook](https://rollupjs.org/guide/en/#generatebundle). Some properties are omitted, like `code` and `map`, since they’re often too large to inline directly. However, each chunk also has a `size` property, to let you filter out empty chunks, inline code yourself below a certain size, or other delightful devilishness.
|
250
|
+
|
251
|
+
For example, using the `entry` name and properties of `output` items to load scripts:
|
71
252
|
|
72
253
|
```marko
|
73
254
|
<head>
|
74
255
|
<rollup|entry, output|>
|
75
256
|
$ const entryChunk = output.find(chunk => chunk.name === entry);
|
76
257
|
|
77
|
-
<if(entryChunk.size /*
|
258
|
+
<if(entryChunk.size /* only load non-empty JS entry points */)>
|
78
259
|
<for|fileName| of=entryChunk.imports>
|
79
|
-
<link rel="modulepreload" href=fileName/>
|
260
|
+
<link rel="modulepreload" href=fileName />
|
80
261
|
</for>
|
81
262
|
|
82
|
-
<script async type="module" src=entryChunk.fileName
|
263
|
+
<script async type="module" src=entryChunk.fileName></script>
|
83
264
|
</if>
|
84
265
|
</rollup>
|
85
266
|
</head>
|
86
267
|
```
|
87
268
|
|
88
|
-
|
269
|
+
> **Note**: It’s up to you to transform the chunk data (also called the **manifest**) into `<link>`s, `<script>`s, and other HTML to load assets. Opting into complete control means we can’t do any of it for you.
|
89
270
|
|
90
|
-
If your
|
271
|
+
If your Rollup `browser` config contains multiple `output` options, or you have multiple `browser` configs, every `output`’s chunk is passed to the `<rollup>` tag.
|
91
272
|
|
92
|
-
For example if you have
|
273
|
+
For example, if you have both `esm` and `iife` build outputs configured:
|
93
274
|
|
94
|
-
```
|
275
|
+
```js
|
95
276
|
{
|
96
|
-
plugins: [
|
97
|
-
marko.browser()
|
98
|
-
...
|
99
|
-
],
|
100
277
|
output: [
|
101
|
-
{ dir:
|
102
|
-
{ dir:
|
103
|
-
]
|
278
|
+
{ dir: "dist/iife", format: "iife" },
|
279
|
+
{ dir: "dist/esm", format: "esm" }
|
280
|
+
];
|
104
281
|
}
|
105
282
|
```
|
106
283
|
|
107
|
-
|
284
|
+
…you could cross-reference assets from both…
|
108
285
|
|
109
286
|
```marko
|
110
|
-
<
|
111
|
-
|
112
|
-
|
113
|
-
$ const esmEntryChunk = esmOutput.find(chunk => chunk.name === entry);
|
287
|
+
<rollup|entry, iifeOutput, esmOutput|>
|
288
|
+
$ const iifeEntryChunk = iifeOutput.find(chunk => chunk.name === entry);
|
289
|
+
$ const esmEntryChunk = esmOutput.find(chunk => chunk.name === entry);
|
114
290
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
</head>
|
291
|
+
<script src=esmEntryChunk.fileName type="module" async></script>
|
292
|
+
<script src=iifeEntryChunk.fileName nomodule async></script>
|
293
|
+
</rollup>
|
119
294
|
```
|
120
295
|
|
121
|
-
and
|
122
|
-
|
123
|
-
# Top level components
|
124
|
-
|
125
|
-
Marko was designed to send as little JavaScript to the browser as possible. One of the ways we do this is by automatically determining which templates in your app should be shipped to the browser. When rendering a template on the server, it is only necessary to bundle the styles and interactive components rendered by that template.
|
126
|
-
|
127
|
-
To send the minimal amount of Marko templates to the browser you can provide a Marko template directly as the `input`.
|
128
|
-
This will also automatically invoke code to initialize the components in the browser, so there is no need to call
|
129
|
-
`template.render` yourself in the browser.
|
130
|
-
|
131
|
-
> Note: if you are using _linked_ plugins then the server plugin will automatically tell the browser compiler which Marko templates to load.
|
132
|
-
|
133
|
-
```js
|
134
|
-
export default {
|
135
|
-
input: "./my-marko-page.marko",
|
136
|
-
plugins: [
|
137
|
-
marko.browser(),
|
138
|
-
...
|
139
|
-
],
|
140
|
-
...
|
141
|
-
}
|
142
|
-
```
|
296
|
+
…and _boom:_ you now have [a `module`/`nomodule` setup](https://philipwalton.com/articles/using-native-javascript-modules-in-production-today/).
|
143
297
|
|
144
298
|
## Options
|
145
299
|
|
146
|
-
|
300
|
+
### `options.babelConfig`
|
147
301
|
|
148
|
-
|
302
|
+
Both the `.server()` and `.browser()` plugins accept this option.
|
149
303
|
|
150
|
-
You can manually override the Babel configuration
|
304
|
+
You can manually override the builtin Babel configuration by passing a `babelConfig` object. By default, [Babel’s regular config file resolution](https://babeljs.io/docs/en/config-files) will be used.
|
151
305
|
|
152
|
-
```
|
306
|
+
```js
|
153
307
|
marko.browser({
|
154
308
|
babelConfig: {
|
155
309
|
presets: ["@babel/preset-env"]
|
@@ -157,42 +311,40 @@ marko.browser({
|
|
157
311
|
});
|
158
312
|
```
|
159
313
|
|
160
|
-
### options.runtimeId
|
314
|
+
### `options.runtimeId`
|
315
|
+
|
316
|
+
Both the `.server()` and `.browser()` plugins accept this option. In fact, you _really_ want to use it with both simultaneously.
|
161
317
|
|
162
|
-
In some cases you may want to embed multiple isolated copies of Marko on the page.
|
318
|
+
In some cases, you may want to embed multiple isolated copies of Marko on the page. (If you can’t think of why, then don’t worry about this option.)
|
163
319
|
|
164
|
-
|
320
|
+
Since Marko uses some `window` properties to initialize, multiple instances can cause issues. For example, by default Marko checks `window.$components` for server-rendered hydration. Usually you can change these `window` properties by [rendering with `{ $global: { runtimeId: "MY_MARKO_RUNTIME_ID" } }` as input](https://markojs.com/docs/rendering/#global-data) on the server, but since `@marko/rollup` usually writes the autoinitialization code for you, instead this plugin exposes a `runtimeId` option to automatically set `$global.runtimeId` to initialize properly in the browser:
|
165
321
|
|
166
322
|
```js
|
167
323
|
const runtimeId = "MY_MARKO_RUNTIME_ID";
|
168
|
-
// Make
|
324
|
+
// Make the `runtimeId` the same across `server` and `browser`, or it’ll error!
|
169
325
|
marko.server({ runtimeId });
|
170
326
|
marko.browser({ runtimeId });
|
171
327
|
```
|
172
328
|
|
173
|
-
### options.serialize
|
329
|
+
### `options.serialize`
|
174
330
|
|
175
|
-
This option is only available for the
|
176
|
-
|
331
|
+
This option is only available for the `.browser()` plugin. It lets you inspect and transform the `output` chunks before they’re passed to [the `<rollup>` tag](#rollup-tag).
|
332
|
+
|
333
|
+
For example, if you _did_ want to include the `code` property from the Rollup chunk — say, to inline code small enough that it’s not worth the overhead of an HTTP request, you’d try something like the following:
|
177
334
|
|
178
335
|
```js
|
179
336
|
marko.browser({
|
180
337
|
serialize(output) {
|
181
|
-
return output.map(
|
182
|
-
|
183
|
-
? {
|
184
|
-
type: "asset",
|
185
|
-
fileName: chunk.fileName
|
186
|
-
}
|
338
|
+
return output.map(({ type, fileName, isEntry, code }) =>
|
339
|
+
type === "asset"
|
340
|
+
? { type, fileName }
|
187
341
|
: {
|
188
|
-
type
|
189
|
-
name
|
190
|
-
isEntry
|
191
|
-
fileName
|
192
|
-
code
|
193
|
-
|
194
|
-
? chunk.code
|
195
|
-
: undefined // only inline small code chunks
|
342
|
+
type,
|
343
|
+
name,
|
344
|
+
isEntry,
|
345
|
+
fileName,
|
346
|
+
// only inline code chunks below 1kB
|
347
|
+
inline: code.trim().length < 1024 && code
|
196
348
|
}
|
197
349
|
);
|
198
350
|
}
|
@@ -10,10 +10,16 @@
|
|
10
10
|
|
11
11
|
- Some software doesn’t support HTTP/2 or higher “upstream” connections at all or very well — if your Node server uses HTTP/2, you may need to downgrade.
|
12
12
|
|
13
|
-
- Automatic gzip/brotli compression may have their buffer sizes set too high; you can tune their buffers to be smaller for faster streaming in exchange for slightly worse compression.
|
14
|
-
|
15
13
|
- Check if “upstream” connections are `keep-alive`: overhead from closing and reopening connections may delay responses.
|
16
14
|
|
15
|
+
- For typical modern webpage filesizes, the following bullet points probably won’t matter. But if you want to stream **small chunks of data with the lowest latency**, investigate these sources of buffering:
|
16
|
+
|
17
|
+
- Automatic gzip/brotli compression may have their buffer sizes set too high; you can tune their buffers to be smaller for faster streaming in exchange for slightly worse compression.
|
18
|
+
|
19
|
+
- You can [tune HTTPS record sizes for lower latency, as described in High Performance Browser Networking](https://hpbn.co/transport-layer-security-tls/#optimize-tls-record-size).
|
20
|
+
|
21
|
+
- Turning off MIME sniffing with [the `X-Content-Type-Options`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options) header eliminates browser buffering at the very beginning of HTTP responses
|
22
|
+
|
17
23
|
### NGiNX
|
18
24
|
|
19
25
|
Most of NGiNX’s relevant parameters are inside [its builtin `http_proxy` module](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering):
|
package/index.d.ts
ADDED
@@ -0,0 +1,317 @@
|
|
1
|
+
declare module "*.marko" {
|
2
|
+
const template: Marko.Template;
|
3
|
+
export default template;
|
4
|
+
}
|
5
|
+
|
6
|
+
declare namespace NodeJS {
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
8
|
+
interface ReadableStream {}
|
9
|
+
}
|
10
|
+
|
11
|
+
declare namespace Marko {
|
12
|
+
/** A mutable global object for the current render. */
|
13
|
+
export interface Global {
|
14
|
+
serializedGlobals?: Record<string, boolean>;
|
15
|
+
[attr: PropertyKey]: unknown;
|
16
|
+
}
|
17
|
+
|
18
|
+
export type TemplateInput<Input = { [attr: PropertyKey]: any }> = Input & {
|
19
|
+
$global?: Global;
|
20
|
+
};
|
21
|
+
|
22
|
+
export interface Out<Component extends Marko.Component = Marko.Component>
|
23
|
+
extends PromiseLike<RenderResult<Component>> {
|
24
|
+
/** The underlying ReadableStream Marko is writing into. */
|
25
|
+
stream: unknown;
|
26
|
+
/** A mutable global object for the current render. */
|
27
|
+
global: Global;
|
28
|
+
/** Disable all async rendering. Will error if something beings async. */
|
29
|
+
sync(): void;
|
30
|
+
/** Returns true if async rendering is disabled. */
|
31
|
+
isSync(): boolean;
|
32
|
+
/** Write unescaped text at the current stream position. */
|
33
|
+
write(val: string | void): this;
|
34
|
+
/** Write javascript content to be merged with the scripts Marko sends out on the next flush. */
|
35
|
+
script(val: string | void): this;
|
36
|
+
/** Returns the currently rendered html content. */
|
37
|
+
toString(): string;
|
38
|
+
/** Starts a new async/forked stream. */
|
39
|
+
beginAsync(options?: {
|
40
|
+
name?: string;
|
41
|
+
timeout?: number;
|
42
|
+
last?: boolean;
|
43
|
+
}): Out;
|
44
|
+
/** Marks the current stream as complete (async streams may still be executing). */
|
45
|
+
end(val?: string | void): this;
|
46
|
+
emit(eventName: PropertyKey, ...args: any[]): boolean;
|
47
|
+
on(eventName: PropertyKey, listener: (...args: any[]) => any): this;
|
48
|
+
once(eventName: PropertyKey, listener: (...args: any[]) => any): this;
|
49
|
+
prependListener(
|
50
|
+
eventName: PropertyKey,
|
51
|
+
listener: (...args: any[]) => any
|
52
|
+
): this;
|
53
|
+
removeListener(
|
54
|
+
eventName: PropertyKey,
|
55
|
+
listener: (...args: any[]) => any
|
56
|
+
): this;
|
57
|
+
/** Register a callback executed when the last async out has completed. */
|
58
|
+
onLast(listener: (next: () => void) => unknown): this;
|
59
|
+
/** Pipe Marko's stream to another stream. */
|
60
|
+
pipe(stream: unknown): this;
|
61
|
+
/** Emits an error on the stream. */
|
62
|
+
error(e: Error): this;
|
63
|
+
/** Schedules a Marko to flush buffered html to the underlying stream. */
|
64
|
+
flush(): this;
|
65
|
+
/** Creates a detached out stream (used for out of order flushing). */
|
66
|
+
createOut(): Out;
|
67
|
+
/** Write escaped text at the current stream position. */
|
68
|
+
text(val: string | void): void;
|
69
|
+
}
|
70
|
+
|
71
|
+
/** Body content created from by a component, typically held in an object with a renderBody property. */
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
73
|
+
export interface Body<
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
75
|
+
in Params extends readonly any[] = [],
|
76
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
77
|
+
out Return = void
|
78
|
+
> {}
|
79
|
+
|
80
|
+
/** Valid data types which can be passed in as a <${dynamic}/> tag name. */
|
81
|
+
export type DynamicTagName =
|
82
|
+
| {
|
83
|
+
renderBody?: Body<any, any> | Template | string | void | false;
|
84
|
+
}
|
85
|
+
| Body<any, any>
|
86
|
+
| Template
|
87
|
+
| string
|
88
|
+
| void
|
89
|
+
| false;
|
90
|
+
|
91
|
+
/** Extract the return tag type from a renderBody. */
|
92
|
+
export type BodyReturnType<B> = B extends Body<any, infer Return>
|
93
|
+
? Return
|
94
|
+
: never;
|
95
|
+
|
96
|
+
/** Extract the tag parameter types received by a renderBody. */
|
97
|
+
export type BodyParamaters<B> = B extends Body<infer Params, any>
|
98
|
+
? Params
|
99
|
+
: never;
|
100
|
+
|
101
|
+
export abstract class Component<
|
102
|
+
Input extends Record<PropertyKey, any> = Record<PropertyKey, any>
|
103
|
+
> implements Emitter
|
104
|
+
{
|
105
|
+
/** A unique id for this instance. */
|
106
|
+
public readonly id: string;
|
107
|
+
/** The top level element rendered by this instance. */
|
108
|
+
public readonly el: Element | void;
|
109
|
+
/** The attributes passed to this instance. */
|
110
|
+
public readonly input: Input;
|
111
|
+
/** @deprecated */
|
112
|
+
public readonly els: Element[];
|
113
|
+
/** Mutable state that when changed causes a rerender. */
|
114
|
+
abstract state: undefined | null | Record<PropertyKey, any>;
|
115
|
+
|
116
|
+
/** Returns the amount of event handlers listening to a specific event. */
|
117
|
+
listenerCount(eventName: PropertyKey): number;
|
118
|
+
/**
|
119
|
+
* Used to wrap an existing event emitted and ensure that all events are
|
120
|
+
* cleaned up once this component is destroyed
|
121
|
+
* */
|
122
|
+
subscribeTo(
|
123
|
+
emitter: unknown
|
124
|
+
): Omit<Emitter, "listenerCount" | "prependListener" | "emit">;
|
125
|
+
/** Emits an event on the component instance. */
|
126
|
+
emit(eventName: PropertyKey, ...args: any[]): boolean;
|
127
|
+
/** Listen to an event on the component instance. */
|
128
|
+
on(eventName: PropertyKey, listener: (...args: any[]) => any): this;
|
129
|
+
/** Listen to an event on the component instance once. */
|
130
|
+
once(eventName: PropertyKey, listener: (...args: any[]) => any): this;
|
131
|
+
/** Listen to an event on the component instance before all other listeners. */
|
132
|
+
prependListener(
|
133
|
+
eventName: PropertyKey,
|
134
|
+
listener: (...args: any[]) => any
|
135
|
+
): this;
|
136
|
+
/** Remove a listener from the component instance. */
|
137
|
+
removeListener(
|
138
|
+
eventName: PropertyKey,
|
139
|
+
listener: (...args: any[]) => any
|
140
|
+
): this;
|
141
|
+
/** Remove all listeners from the component instance. */
|
142
|
+
removeAllListeners(eventName?: PropertyKey): this;
|
143
|
+
/** Removes the component instance from the DOM and cleans up all active event handlers including all children. */
|
144
|
+
destroy(): void;
|
145
|
+
/** Schedule an update (similar to if a state had been changed). */
|
146
|
+
forceUpdate(): void;
|
147
|
+
/** Generates a unique id derived from the current unique instance id (similar to :scoped in the template). */
|
148
|
+
elId(key?: string, index?: number): string;
|
149
|
+
/** @alias elId */
|
150
|
+
getElId(key?: string, index?: number): string;
|
151
|
+
/** Gets an element reference by its `key` attribute in the template. */
|
152
|
+
getEl<T extends Element | void = Element | void>(
|
153
|
+
key?: string,
|
154
|
+
index?: number
|
155
|
+
): T;
|
156
|
+
/** Gets all element references by their `key` attribute in the template. */
|
157
|
+
getEls<T extends Element[] = Element[]>(key: string): T;
|
158
|
+
/** Gets a component reference by its `key` attribute in the template. */
|
159
|
+
getComponent<T extends Component | void = Component | void>(
|
160
|
+
key: string,
|
161
|
+
index?: number
|
162
|
+
): T;
|
163
|
+
/** Gets all component references by their `key` attribute in the template. */
|
164
|
+
getComponents<T extends Component[] = Component[]>(key: string): T;
|
165
|
+
/** True if this instance has been removed from the dom. */
|
166
|
+
/** True if this instance is scheduled to rerender. */
|
167
|
+
isDestroyed(): boolean;
|
168
|
+
/** Replace the entire state object with a new one, removing old properties. */
|
169
|
+
replaceState(state: this["state"]): void;
|
170
|
+
/**
|
171
|
+
* Update a property on this.state (should prefer mutating this.state directly).
|
172
|
+
* When passed an object as the first argument, it will be merged into the state.
|
173
|
+
*/
|
174
|
+
setState<Key extends PropertyKey>(
|
175
|
+
name: Key & keyof this["state"],
|
176
|
+
value: (this["state"] & Record<PropertyKey, unknown>)[Key]
|
177
|
+
): void;
|
178
|
+
setState(value: Partial<this["state"]>): void;
|
179
|
+
|
180
|
+
/** Schedules an update related to a specific state property and optionally updates the value. */
|
181
|
+
setStateDirty<Key extends PropertyKey>(
|
182
|
+
name: Key & keyof this["state"],
|
183
|
+
value?: (this["state"] & Record<PropertyKey, unknown>)[Key]
|
184
|
+
): void;
|
185
|
+
/** Synchronously flush any scheduled updates. */
|
186
|
+
update(): void;
|
187
|
+
/** Appends the dom for the current instance to a parent DOM element. */
|
188
|
+
appendTo(target: ParentNode): this;
|
189
|
+
/** Inserts the dom for the current instance after a sibling DOM element. */
|
190
|
+
insertAfter(target: ChildNode): this;
|
191
|
+
/** Inserts the dom for the current instance before a sibling DOM element. */
|
192
|
+
insertBefore(target: ChildNode): this;
|
193
|
+
/** Prepends the dom for the current instance to a parent DOM element. */
|
194
|
+
prependTo(target: ParentNode): this;
|
195
|
+
/** Replaces an existing DOM element with the dom for the current instance. */
|
196
|
+
replace(target: ChildNode): this;
|
197
|
+
/** Replaces the children of an existing DOM element with the dom for the current instance. */
|
198
|
+
replaceChildrenOf(target: ParentNode): this;
|
199
|
+
/** Called when the component is firsted created. */
|
200
|
+
abstract onCreate?(input: this["input"], out: Marko.Out): void;
|
201
|
+
/** Called every time the component receives input from it's parent. */
|
202
|
+
abstract onInput?(
|
203
|
+
input: this["input"],
|
204
|
+
out: Marko.Out
|
205
|
+
): void | this["input"];
|
206
|
+
/** Called after a component has successfully rendered, but before it's update has been applied to the dom. */
|
207
|
+
abstract onRender?(out: Marko.Out): void;
|
208
|
+
/** Called after the first time the component renders and is attached to the dom. */
|
209
|
+
abstract onMount?(): void;
|
210
|
+
/** Called when a components render has been applied to the DOM (excluding when it is initially mounted). */
|
211
|
+
abstract onUpdate?(): void;
|
212
|
+
/** Called when a component is destroyed and removed from the dom. */
|
213
|
+
abstract onDestroy?(): void;
|
214
|
+
}
|
215
|
+
|
216
|
+
/** The top level api for a Marko Template. */
|
217
|
+
export abstract class Template {
|
218
|
+
/** Creates a Marko compatible output stream. */
|
219
|
+
createOut(): Out;
|
220
|
+
|
221
|
+
/**
|
222
|
+
* The folowing types are processed up by the @marko/language-tools
|
223
|
+
* and inlined into the compiled template.
|
224
|
+
*
|
225
|
+
* This is done to support generics on each of these methods
|
226
|
+
* until TypeScript supports higher kinded types.
|
227
|
+
*
|
228
|
+
* https://github.com/microsoft/TypeScript/issues/1213
|
229
|
+
*/
|
230
|
+
|
231
|
+
/** @marko-overload-start */
|
232
|
+
/** Asynchronously render the template. */
|
233
|
+
abstract render(
|
234
|
+
input: Marko.TemplateInput,
|
235
|
+
stream?: {
|
236
|
+
write: (chunk: string) => void;
|
237
|
+
end: (chunk?: string) => void;
|
238
|
+
}
|
239
|
+
): Marko.Out<Marko.Component>;
|
240
|
+
|
241
|
+
/** Synchronously render the template. */
|
242
|
+
abstract renderSync(
|
243
|
+
input: Marko.TemplateInput
|
244
|
+
): Marko.RenderResult<Marko.Component>;
|
245
|
+
|
246
|
+
/** Synchronously render a template to a string. */
|
247
|
+
abstract renderToString(input: Marko.TemplateInput): string;
|
248
|
+
|
249
|
+
/** Render a template and return a stream.Readable in nodejs or a ReadableStream in a web worker environment. */
|
250
|
+
abstract stream(
|
251
|
+
input: Marko.TemplateInput
|
252
|
+
): ReadableStream<string> & NodeJS.ReadableStream;
|
253
|
+
/** @marko-overload-end */
|
254
|
+
}
|
255
|
+
|
256
|
+
export interface RenderResult<
|
257
|
+
out Component extends Marko.Component = Marko.Component
|
258
|
+
> {
|
259
|
+
/** Returns the component created as a result of rendering the template. */
|
260
|
+
getComponent(): Component;
|
261
|
+
getComponents(selector?: any): any;
|
262
|
+
/** Triggers the mount lifecycle of a component without necessarily attaching it to the DOM. */
|
263
|
+
afterInsert(host?: any): this;
|
264
|
+
/** Gets the DOM node rendered by a template. */
|
265
|
+
getNode(host?: any): Node;
|
266
|
+
/** Gets the HTML output of the rendered template. */
|
267
|
+
toString(): string;
|
268
|
+
/** Appends the dom of the rendered template to a parent DOM element. */
|
269
|
+
appendTo(target: ParentNode): this;
|
270
|
+
/** Inserts the dom of the rendered template after a sibling DOM element. */
|
271
|
+
insertAfter(target: ChildNode): this;
|
272
|
+
/** Inserts the dom of the rendered template before a sibling DOM element. */
|
273
|
+
insertBefore(target: ChildNode): this;
|
274
|
+
/** Prepends the dom of the rendered template to a parent DOM element. */
|
275
|
+
prependTo(target: ParentNode): this;
|
276
|
+
/** Replaces an existing DOM element with the dom of the rendered template. */
|
277
|
+
replace(target: ChildNode): this;
|
278
|
+
/** Replaces the children of an existing DOM element with the dom of the rendered template. */
|
279
|
+
replaceChildrenOf(target: ParentNode): this;
|
280
|
+
out: Out<Component>;
|
281
|
+
/** @deprecated */
|
282
|
+
document: any;
|
283
|
+
/** @deprecated */
|
284
|
+
getOutput(): string;
|
285
|
+
/** @deprecated */
|
286
|
+
html: string;
|
287
|
+
/** @deprecated */
|
288
|
+
context: Out<Component>;
|
289
|
+
}
|
290
|
+
|
291
|
+
export interface Emitter {
|
292
|
+
listenerCount(eventName: PropertyKey): number;
|
293
|
+
emit(eventName: PropertyKey, ...args: any[]): boolean;
|
294
|
+
on(eventName: PropertyKey, listener: (...args: any[]) => any): this;
|
295
|
+
once(eventName: PropertyKey, listener: (...args: any[]) => any): this;
|
296
|
+
prependListener(
|
297
|
+
eventName: PropertyKey,
|
298
|
+
listener: (...args: any[]) => any
|
299
|
+
): this;
|
300
|
+
removeListener(
|
301
|
+
eventName: PropertyKey,
|
302
|
+
listener: (...args: any[]) => any
|
303
|
+
): this;
|
304
|
+
removeAllListeners(eventName?: PropertyKey): this;
|
305
|
+
}
|
306
|
+
|
307
|
+
export type Repeated<T> = [T, T, ...T[]];
|
308
|
+
export type Repeatable<T> = T | Repeated<T>;
|
309
|
+
export type MaybeRepeatable<T> = undefined | Repeatable<T>;
|
310
|
+
|
311
|
+
export interface NativeTags {
|
312
|
+
[name: string]: {
|
313
|
+
input: Record<string, unknown>;
|
314
|
+
return: unknown;
|
315
|
+
};
|
316
|
+
}
|
317
|
+
}
|
package/package.json
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
{
|
2
2
|
"name": "marko",
|
3
|
-
"version": "5.22.
|
3
|
+
"version": "5.22.4",
|
4
4
|
"license": "MIT",
|
5
5
|
"description": "UI Components + streaming, async, high performance, HTML templating for Node.js and the browser.",
|
6
6
|
"dependencies": {
|
7
|
-
"@marko/compiler": "^5.23.
|
8
|
-
"@marko/translator-default": "^5.22.
|
7
|
+
"@marko/compiler": "^5.23.4",
|
8
|
+
"@marko/translator-default": "^5.22.4",
|
9
9
|
"app-module-path": "^2.2.0",
|
10
10
|
"argly": "^1.2.0",
|
11
11
|
"browser-refresh-client": "1.1.4",
|
@@ -68,8 +68,10 @@
|
|
68
68
|
"components-browser.marko",
|
69
69
|
"components.js",
|
70
70
|
"env.js",
|
71
|
+
"index.d.ts",
|
71
72
|
"index-browser.marko",
|
72
73
|
"index.js",
|
73
74
|
"node-require.js"
|
74
|
-
]
|
75
|
+
],
|
76
|
+
"types": "index.d.ts"
|
75
77
|
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/**
|
2
|
+
* @template T
|
3
|
+
* @typedef {{
|
4
|
+
* value?: T;
|
5
|
+
* then?: Marko.Body<[Awaited<T>], void>;
|
6
|
+
* catch?: Marko.Body<[unknown], void>;
|
7
|
+
* placeholder?: Marko.Body<[], void>;
|
8
|
+
* client-reorder?: boolean;
|
9
|
+
* name?: string;
|
10
|
+
* timeout?: number;
|
11
|
+
* show-after?: string;
|
12
|
+
* }} Input
|
13
|
+
*/
|