@webqit/webflo 0.11.6 → 0.11.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -22,6 +22,7 @@ Ok, we've put all of that up for a straight read!
22
22
  + [Webflo Applications](#webflo-applications)
23
23
  + [Workflow API](#workflow-api)
24
24
  + [Webflo Config](#webflo-config)
25
+ + [Technology Stack](#technology-stack)
25
26
  + [Getting Started](#getting-started)
26
27
  + [Getting Involved](#getting-involved)
27
28
 
@@ -137,9 +138,9 @@ For when your application involves routing:
137
138
  For when your application involves pages and a UI:
138
139
  + [The HTML Standard](https://html.spec.whatwg.org/) is held for all things *markup* - across client, server, and Service Worker environments! Webflo is all about using conventional `.html`-based pages and templates, valid HTML syntax, etc. You are able to get away with a "zero-JavaScript" proposition, or a *Progressive Enhancement* proposition that makes do with "just-enough JavaScript"!
139
140
 
140
- > Your markup is also easily extendable with [OOHTML](https://github.com/webqit/oohtml) - a set of new features for HTML that makes it fun to hand-author your UI! Within OOHTML are [HTML Modules](https://github.com/webqit/oohtml#html-modules) and [HTML Imports](https://github.com/webqit/oohtml#html-imports), [Reactive Scripts](https://github.com/webqit/oohtml#subscript) and more!
141
+ > Your markup is also easily extendable with [OOHTML](#oohtml) - a set of new features for HTML that makes it fun to hand-author your UI! Within OOHTML are [HTML Modules](https://github.com/webqit/oohtml#html-modules) and [HTML Imports](https://github.com/webqit/oohtml#html-imports), [Reactive Scripts](https://github.com/webqit/oohtml#subscript) and more!
141
142
 
142
- + [WHATWG DOM](https://dom.spec.whatwg.org/) is universally available - not only on the client-side, but also on the server-side via [OOHTML-SSR](https://github.com/webqit/oohtml-ssr) - for all things *dynamic pages*: rendering, manipulation, interactivity, etc.
143
+ + [WHATWG DOM](https://dom.spec.whatwg.org/) is universally available - not only on the client-side, but also on the server-side via [OOHTML-SSR](#oohtml-ssr) - for all things *dynamic pages*: rendering, manipulation, interactivity, etc.
143
144
 
144
145
  > Your DOM is also easily enrichable with [Custom Elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements), plus [Subscript Elements](https://github.com/webqit/oohtml#subscript) and [The State API](https://github.com/webqit/oohtml#state-api) from OOHTML.
145
146
 
@@ -249,7 +250,10 @@ export default function(event, context, next) {
249
250
  }
250
251
  ```
251
252
 
252
- Each function receives an `event` object representing details - e.g. `event.request`, `event.url`, `event.session` - about the current request. (Details ahead.)
253
+ > **Note**
254
+ > <br>Other [*method*](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods)-specific function names may be used: `get`, `post`, `put`, `patch`, `del` (for *delete*), `options`, `head`, etc.
255
+
256
+ Each function receives an `event` object representing details - e.g. `event.request`, `event.url`, `event.session` - about the current request. ([Details ahead](#workflow-api).)
253
257
 
254
258
  For *server-based* applications (e.g. traditional web apps and API backends), server-side handlers go into a directory named `server`.
255
259
 
@@ -562,7 +566,7 @@ But, we can also access the route in a way that gets the data rendered into the
562
566
  Now, for Single Page Applications, subsequent navigations, after the initial page load, just ask for the data on destination URLs and perform [Client-Side Rendering](#client-and-server-side-rendering) on the same running document. Navigation is sleek and instant!
563
567
 
564
568
  > **Note**
565
- > <br>Unless disabled in [config](#spa_routing), SPA routing is automatically built into your app's JS bundle from the `npm run generate` command. So, it just works!
569
+ > <br>Unless disabled, [SPA Routing](#spa_routing) is automatically built into your app's JS bundle from the `npm run generate` command. So, it just works!
566
570
 
567
571
  With no extra work, your application can function as either a *Multi Page App (MPA)* or a *Single Page App (SPA)*!
568
572
 
@@ -596,7 +600,7 @@ my-app
596
600
 
597
601
  This, in both cases, is templating - the ability to define HTML *partials* once, and have them reused multiple times. Webflo just concerns itself with templating, and the choice of a Multi Page Application or Single Page Application becomes yours! And heck, you can even have the best of both worlds in the same application - with an architecture we'll call [Multi SPA](#in-a-multi-spa-layout)! It's all a *layout* thing!
598
602
 
599
- Now, with pages in Webflo being [DOM-based](#overview) (both client-side and [server-side](https://github.com/webqit/oohtml-ssr)), documents can be manipulated directly with DOM APIs, e.g. to replace or insert nodes, attributes, etc. But even better, templating in Webflo is based on the [HTML Modules](https://github.com/webqit/oohtml#html-modules) and [HTML Imports](https://github.com/webqit/oohtml#html-imports) features in [OOHTML](https://github.com/webqit/oohtml) - unless disabled in [config](#oohtml_support). These features provide a powerful declarative templating system on top of the standard [HTML `<template>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template) element - with a *module*, *export* and *import* paradigm.
603
+ Now, with pages in Webflo being [DOM-based](#overview) (both client-side and [server-side](#oohtml-ssr)), documents can be manipulated directly with DOM APIs, e.g. to replace or insert nodes, attributes, etc. But even better, templating in Webflo is based on the [HTML Modules](https://github.com/webqit/oohtml#html-modules) and [HTML Imports](https://github.com/webqit/oohtml#html-imports) features in [OOHTML](#oohtml) - unless disabled in config. These features provide a powerful declarative templating system on top of the standard [HTML `<template>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template) element - with a *module*, *export* and *import* paradigm.
600
604
 
601
605
  Here, you are able to define reusable contents in a `<template>` element...
602
606
 
@@ -817,7 +821,7 @@ The Webflo `generate` command automatically figures out a given architecture and
817
821
 
818
822
  #### Bundling
819
823
 
820
- Template `.html` files are bundled from the filesystem into a single file using the [OOHTML CLI](https://github.com/webqit/oohtml-cli) utility. On installing this utility, you may want to add the following to your npm scripts in `package.json`.
824
+ Template `.html` files are bundled from the filesystem into a single file using the [OOHTML CLI](#oohtml-cli) utility. On installing this utility, you may want to add the following to your npm scripts in `package.json`.
821
825
 
822
826
  ```json
823
827
  "scripts": {
@@ -830,11 +834,11 @@ The `--recursive` flag gets the bundler to recursively bundle *subroots* in a [M
830
834
  The `--auto-embed` flag gets the bundler to automatically embed the generated `bundle.html` file on the matched `index.html` document. A value of `routes` for the flag ends up as the name of the *embed* template: `<template name="routes" src="/bundle.html"></template>`.
831
835
 
832
836
  > **Note**
833
- > <br>If your HTML files are actually based off the `public` directory, you'll need to tell the above command to run in the `public` directory, either by [configuring the bundler](https://github.com/webqit/oohtml-cli#other-options), or by rewriting the command with a prefix: `cd public && oohtml bundle --recursive --auto-embed=routes`.
837
+ > <br>If your HTML files are actually based off the `public` directory, you'll need to tell the above command to run in the `public` directory, either by [configuring the bundler](https://github.com/webqit/oohtml-cli#other-options), or by rewriting the command with a prefix: `cd public && oohtml bundle --recursive --auto-embed=routes`.
834
838
 
835
839
  ### Client and Server-Side Rendering
836
840
 
837
- With pages in Webflo being [DOM-based](#overview) (both client-side and [server-side](https://github.com/webqit/oohtml-ssr)), we are able to access and manipulate documents and elements using familiar DOM APIs - e.g. to replace or insert contents, attributes, etc. Rendering in Webflo is based on this concept!
841
+ With pages in Webflo being [DOM-based](#overview) (both client-side and [server-side](#oohtml-ssr)), we are able to access and manipulate documents and elements using familiar DOM APIs - e.g. to replace or insert contents, attributes, etc. Rendering in Webflo is based on this concept!
838
842
 
839
843
  Here, Webflo simply makes sure that the data obtained from each route is available as part of the `document` object, such that it is accessible to our rendering logic as a `data` property on the [`document.state`](#the-idea-of-state) object - [`document.state.data`](#the-documentstatedata-object).
840
844
 
@@ -880,7 +884,7 @@ public
880
884
 
881
885
  From here, even the most-rudimentary form of rendering (using vanilla HTML and native DOM methods) becomes possible, and this is a good thing: you get away with less tooling until you absolutely need to add up on tooling!
882
886
 
883
- However, since the `document` objects in Webflo natively support [OOHTML](https://github.com/webqit/oohtml) - unless disabled in [config](#oohtml_support), we are able to write reactive UI logic! Here, OOHTML makes it possible to embed reactive `<script>` elements (called [Subscript](https://github.com/webqit/oohtml#subscript)) right within HTML elements - where each expression automatically self-updates whenever references to data, or its properties, get an update!
887
+ However, since the `document` objects in Webflo natively support [OOHTML](#oohtml) - unless disabled in config, we are able to write reactive UI logic! Here, OOHTML makes it possible to embed reactive `<script>` elements (called [Subscript](https://github.com/webqit/oohtml#subscript)) right within HTML elements - where each expression automatically self-updates whenever references to data, or its properties, get an update!
884
888
 
885
889
  ```html
886
890
  <!--
@@ -929,7 +933,9 @@ Going forward, we can get to write more succinct code! Using the [Namespaced HTM
929
933
  document.title = title;
930
934
  let { headline1, headline2 } = this.namespace;
931
935
  $(headline1).html(title);
932
- $(headline2).html(title);
936
+ if (headline2) {
937
+ $(headline2).html(title);
938
+ }
933
939
  </script>
934
940
  </body>
935
941
  </html>
@@ -1058,14 +1064,14 @@ Observer.observe(state, propertyName, change => {
1058
1064
 
1059
1065
  This way, all the moving parts of your application remain coordinated, and can easily be rendered to reflect them on the UI!
1060
1066
 
1061
- For all things application state, Webflo leverages the [State API](https://github.com/webqit/oohtml#state-api) that's natively available in OOHTML-based documents - both client-side and server-side. This API exposes an application-wide `document.state` object and a per-element `element.state` object. And these are *live* read/write objects that can be observed for property changes using the [Observer API](https://github.com/webqit/observer). It comes off as the simplest approach to state and reactivity!
1067
+ For all things application state, Webflo leverages the [State API](https://github.com/webqit/oohtml#state-api) that's natively available in OOHTML-based documents - both client-side and server-side. This API exposes an application-wide `document.state` object and a per-element `element.state` object. And these are *live* read/write objects that can be observed for property changes using the [Observer API](#the-observer-api). It comes off as the simplest approach to state and reactivity!
1062
1068
 
1063
1069
  > **Note**
1064
- > <br>The State API is not available when the OOHTML support level in config is switched away from `full` and `scripting`.
1070
+ > <br>The State API is not available when the [OOHTML support level](#oohtml) in config is switched away from `full` and `scripting`.
1065
1071
 
1066
1072
  #### The `document.state.data` Object
1067
1073
 
1068
- This property represents the data obtained from route handers on each navigation. Webflo simply exposes this data and lets the page's [rendering logic](#client-and-server-side-rendering), or other parts of the application, take over.
1074
+ This property reperesents the application data at any point in time - obtained from route handers on each navigation. Webflo simply updates this property and lets the page's [rendering logic](#client-and-server-side-rendering), or other parts of the application, take over.
1069
1075
 
1070
1076
  ```js
1071
1077
  Observer.observe(document.state, 'data', e => {
@@ -1073,9 +1079,16 @@ Observer.observe(document.state, 'data', e => {
1073
1079
  });
1074
1080
  ```
1075
1081
 
1082
+ ```html
1083
+ <script type="subscript">
1084
+ let { title } = document.state.data;
1085
+ document.title = title;
1086
+ </script>
1087
+ ```
1088
+
1076
1089
  #### The `document.state.url` Object
1077
1090
 
1078
- This is a *live* object that reperesents the properties of the application URL at any point in time. The object exposes the same URL properties as with the [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) API, but as *live* properties that can be observed as navigation happens, and modified to initiate navigation - all using the [Observer API](https://github.com/webqit/observer).
1091
+ This is a *live* object that reperesents the properties of the application URL at any point in time. The object exposes the same URL properties as with the [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) API, but as *live* properties that can be observed as navigation happens, and modified to initiate navigation - all using the [Observer API](#the-observer-api).
1079
1092
 
1080
1093
  ```js
1081
1094
  console.log(document.state.url) // { hash, host, hostname, href, origin, password, pathname, port, protocol, search, searchParams, username }
@@ -1113,11 +1126,18 @@ document.addEventListener('synthetic-navigation', e => {
1113
1126
  });
1114
1127
  ```
1115
1128
 
1129
+ ```html
1130
+ <script type="subscript">
1131
+ let { query: { as: role } } = document.state.url;
1132
+ document.title = 'Login as ' + role;
1133
+ </script>
1134
+ ```
1135
+
1116
1136
  ### Requests and Responses
1117
1137
 
1118
- On each request, the event object passed to route handlers exposes the incoming request as `event.request`. This is an instance of `event.Request` - an extension of the [WHATWG Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) class. The event object also exposes `event.Response` - an extension of the [WHATWG Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) class, for returning instance-based responses.
1138
+ On each request, the event object passed to route handlers exposes the incoming request as `event.request`. This is an instance of `event.Request` - an extension of the [WHATWG Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) class. The event object also exposes `event.Response` - an extension of the [WHATWG Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) class, for returning instance-based responses. You enjoy routing that is based on standard interfaces!
1119
1139
 
1120
- Now, routes in Webflo can be designed for different types of request/response scenarios. Webflo does the heavy lifting on each request/response flow!
1140
+ Routes in Webflo can be designed for different types of request/response scenarios. Here are some important ones:
1121
1141
 
1122
1142
  #### Scenario 1: Static File Requests and Responses
1123
1143
 
@@ -1216,49 +1236,117 @@ console.log(event.request.headers.cookies); // { 'Cookie-1': 'cookie-val', 'Cook
1216
1236
 
1217
1237
  ### Webflo Applications
1218
1238
 
1219
- In just a few concepts, Webflo comes ready for any type of application! Now, here's how it all works.
1239
+ In just a few concepts, Webflo comes ready for any type of application!
1220
1240
 
1221
1241
  + [Client-Side Applications](#client-side-applications)
1242
+ + [Progressive Web Apps](#progressive-web-apps)
1222
1243
  + [API Backends](#api-backends)
1223
1244
  + [Static Sites](#static-sites)
1224
1245
 
1225
1246
  #### Client-Side Applications
1226
1247
 
1227
- Web pages that embed the Webflo client JS bundle deliver a great user experience.
1228
- + **First-paint-ready.** On the first page request, you get a [server-rendered](#client-and-server-side-rendering) HTML page that's optimized for the first paint of your application.
1229
- + **Fluid and app-like.** On being loaded, the state of the application is restored through hydration, and [subsequent navigations](#spa-navigation) are sleek and instant, while performing [Client-Side Rendering](#client-and-server-side-rendering).
1248
+ Web pages that embed the Webflo client JS bundle deliver a great user experience. It's simple: the `npm run generate` command does both the building and embedding of the script, or scripts, for the document root, or document roots (in a [Multi Page](#in-a-multi-page-layout) / [Multi SPA](#in-a-multi-spa-layout) layout)!
1230
1249
 
1231
- For these client-side applications, the `npm run generate` command does both the building and embedding of the script for each document root in the application.
1250
+ On being loaded, the state of the application is initialized, or is restored through hydration - where [Server-Side Rendering](#client-and-server-side-rendering) was involved to optimize for first paint, and an app-like experience kicks in! For [Single-Page Applications](#in-a-single-page-layout), [Client-Side Rendering](#client-and-server-side-rendering) is performed on each navigation.
1232
1251
 
1233
1252
  ##### SPA Navigation
1234
1253
 
1235
- Unless disabled in [config](#spa_navigation), it is factored-in at build time for the application client JS to be able to automatially figure out when to intercept a navigation event and prevent a full page reload, and when not to. It follows the following rules:
1254
+ Unless disabled in config, it is factored-in at build time for the application client JS to be able to automatially figure out when to intercept a navigation event and prevent a full page reload, and when not to. It follows the following rules:
1236
1255
  + When it ascertains that the destination URL is based on the current running `index.html` document in the browser (an SPA architecture), a full page reload is prevented for *soft* navigation. But where the destination URL points out of the current document root (a [Multi SPA](#in-a-multi-spa-layout) architecture), navigation is allowed as a normal page load, and a new page root is loaded.
1237
1256
  + If navigation is initiated with any of the following keys pressed: Meta Key, Alt Key, Shift Key, Ctrl Key, navigation is allowed to work the default way - regardless of the first rule above.
1238
1257
  + If navigation is initiated from a link element that has the `target` attribute, or the `download` attribute, navigation is allowed to work the default way - regardless of the first rule above.
1239
1258
  + If navigation is initiated from a form element that has the `target` attribute, navigation is allowed to work the default way - regardless of the first rule above.
1240
1259
 
1241
- > To entirely disable SPA navigation in config where necessary, run `webflo config client` and follow the prompt.
1260
+ <details>
1261
+ <summary>Default Config</summary>
1262
+
1263
+ > File: `.webqit/webflo/client.json` | Command: `webflo config client spa_navigation=TRUE`
1264
+
1265
+ ```json
1266
+ { "spa_navigation": true }
1267
+ ```
1268
+ </details>
1242
1269
 
1243
1270
  ##### SPA State
1244
1271
 
1245
- On the client side of a Webflo application, [the idea of state](#the-idea-of-state) also goes further to include the following aspects of the client-side lifecycle that can be used to provide visual cues on the UI.
1272
+ On the client side of a Webflo application, [the idea of state](#the-idea-of-state) also includes the following aspects of the client-side lifecycle that can be used to provide visual cues on the UI.
1246
1273
 
1247
1274
  ###### The `document.state.network` Object
1248
1275
 
1249
1276
  This is a *live* object that exposes the network activity and network state of the application.
1250
1277
 
1251
1278
  ```js
1252
- console.log(document.state.network) // { requesting, remote, error, redirecting, online, }
1279
+ console.log(document.state.network) // { requesting, remote, error, redirecting, connectivity, }
1253
1280
  ```
1254
1281
 
1255
1282
  + **`network.requesting`: `null|Object`** - This property tells when a request is ongoing, in which case it exposes the `params` object used to initiate the request.
1283
+
1284
+ On the UI, this could be used to hide a menu drawer that may have been open.
1285
+
1286
+ ```html
1287
+ <menu-drawer>
1288
+ <script type="subscript">
1289
+ let { network: { requesting } } = document.state;
1290
+ if (requesting) {
1291
+ $(this).attr('open', false);
1292
+ }
1293
+ </script>
1294
+ </menu-drawer>
1295
+ ```
1296
+
1256
1297
  + **`network.remote`: `null|String`** - This property tells when a remote request is ongoing - usually the same navigation requests as at `network.requesting`, but when not handled by any client-side route handlers, or when `next()`ed to this point by route handlers. The `remote` property also goes live when a route handler calls the special `fetch()` function that they recieve on their fourth parameter.
1298
+
1299
+ On the UI, this could be used to show/hide a spinner, or progress bar, to provide a visual cue.
1300
+
1301
+ ```html
1302
+ <progress-bar>
1303
+ <script type="subscript">
1304
+ let { network: { remote } } = document.state;
1305
+ $(this).attr('hidden', !remote);
1306
+ </script>
1307
+ </progress-bar>
1308
+ ```
1309
+
1257
1310
  + **`network.error`: `null|Error`** - This property tells when a request is *errored* in which case it contains an `Error` instance of the error. For requests that can be retried, the `Error` instance also has a custom `retry()` method.
1311
+
1312
+ On the UI, this could be used to show/hide cute error elements.
1313
+
1314
+ ```html
1315
+ <nice-error>
1316
+ <script type="subscript">
1317
+ let { network: { error } } = document.state;
1318
+ $(this).attr('hidden', !error);
1319
+ </script>
1320
+ </nice-error>
1321
+ ```
1322
+
1258
1323
  + **`network.redirecting`: `null|String`** - This property tells when a client-side redirect is ongoing - see [Scenario 4: Single Page Navigation Requests and Responses](#scenario-4-single-page-navigation-requests-and-responses) - in which case it exposes the destination URL.
1259
- + **`network.online`: `Boolean`** - This property tells of [the browser's ability to connect to the network](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/onLine).
1260
-
1261
- Now, being a *live* object means that `document.state.network` can be observed using the [Observer API](https://github.com/webqit/observer).
1324
+
1325
+ On the UI, this could be used to prevent further interactions with the outgoing page.
1326
+
1327
+ ```html
1328
+ <body>
1329
+ <script type="subscript">
1330
+ let { network: { redirecting } } = document.state;
1331
+ $(this).css(redirecting ? { pointerEvents: 'none', filter: 'blur(2)' } : { pointerEvents: 'auto', filter: 'blur(0)' });
1332
+ </script>
1333
+ </body>
1334
+ ```
1335
+
1336
+ + **`network.connectivity`: `String`** - This property tells of [the browser's ability to connect to the network](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/onLine): `online`, `offline`.
1337
+
1338
+ On the UI, this could be used to show/hide a connectivity status.
1339
+
1340
+ ```html
1341
+ <body>
1342
+ <script type="subscript">
1343
+ let { network: { connectivity } } = document.state;
1344
+ $(this).attr( 'connectivity', connectivity });
1345
+ </script>
1346
+ </body>
1347
+ ```
1348
+
1349
+ Here are some additional examples with the [Observer API](#the-observer-api).
1262
1350
 
1263
1351
  ```js
1264
1352
  // Visualize the network state
@@ -1272,12 +1360,12 @@ Observer.observe(document.state.network, onlineVisualizer);
1272
1360
  ```
1273
1361
 
1274
1362
  ```js
1275
- // Visualize the 'online' property
1276
- let onlineVisualizer = e => {
1277
- console.log('You are ', e.value ? 'online' : 'offline');
1363
+ // Visualize the 'connectivity' property
1364
+ let connectivityVisualizer = e => {
1365
+ console.log('You are ', e.value);
1278
1366
  };
1279
- Observer.observe(document.state.network, 'online', onlineVisualizer);
1280
- // Or: Observer.observe(document.state, [ ['network', 'online'] ], onlineVisualizer);
1367
+ Observer.observe(document.state.network, 'connectivity', connectivityVisualizer);
1368
+ // Or: Observer.observe(document.state, [ ['network', 'connectivity'] ], connectivityeVisualizer);
1281
1369
  ```
1282
1370
 
1283
1371
  ```js
@@ -1292,28 +1380,124 @@ Observer.observe(document.state.network, 'error', e => {
1292
1380
  });
1293
1381
  ```
1294
1382
 
1295
- ###### Form Actions
1383
+ ##### Form Actions
1296
1384
 
1297
- When navigation occurs [via form submissions](#scenario-4-single-page-navigation-requests-and-responses), the form element and the submit button are made to go on the *active* state while the request is processed. For both of these elements, the Webflo client simply sets the `element.state.active` to `true` on submission, then `false`, on completion.
1385
+ When navigation occurs [via form submissions](#scenario-4-single-page-navigation-requests-and-responses), the form element and the submit button are made to go on the *active* state while the request is being processed. For both of these elements, the Webflo client simply sets the `element.state.active` to `true` on submission, then `false`, on completion.
1298
1386
 
1299
- <!-- TODO: method overrides -->
1387
+ ```html
1388
+ <form method="post">
1389
+ <input name="username" placeholder="Your username..." />
1390
+ <script>
1391
+ $(this).css(this.state.active ? { pointerEvents: 'none', opacity: 'o.5' } : { pointerEvents: 'auto', opacity: '1' });
1392
+ </script>
1393
+ </form>
1394
+ ```
1300
1395
 
1301
- ##### Service Workers
1396
+ One more thing: HTML forms can only accept two HTTP methods on their `method` attribute: `GET`, `POST`! The same constraint exists on the equivalent `formmethod` attribue in submit buttons. You are able to overcome this in Webflo by using alternative `data-` attributes: `data-method`, `data-formmethod`, respectively.
1302
1397
 
1303
- Webflo client-side applications are intended to provide an app-like-first experience. So unless disabled in [config](#enable_service_worker), a [Service Worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) is built as part of your application on running the `npm run generate` command. You may define [route handlers in the `/worker` directory](#handler-functions-and-layout) of your application, and these will be built into the service worker to handle Same-Origin requests of the application. Where there are no *worker* handlers, or where they forward these requests, the request is fetched, either from the cache, or from the network, depending on the fetching strategy built into the Service Worker.
1398
+ ```html
1399
+ <form data-method="patch">
1400
+ <input name="price" placeholder="Enter new price..." />
1401
+ </form>
1402
+ ```
1403
+
1404
+ #### Progressive Web Apps
1405
+
1406
+ Webflo client-side applications are intended to provide an app-like-first experience. So unless disabled in config, a [Service Worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) is built as part of your application on running the `npm run generate` command. You may define [route handlers in the `/worker` directory](#handler-functions-and-layout) of your application, and these will be built into the service worker to handle Same-Origin requests of the application. Where there are no *worker* handlers, or where these forward incoming requests, requests are fetched, either from the cache, or from the network, depending on the fetching strategy built into the Service Worker.
1304
1407
 
1305
- ###### Fetching Strategy
1408
+ <details>
1409
+ <summary>Default Config</summary>
1410
+
1411
+ > File: `.webqit/webflo/client.json` | Command: `webflo config client enable_service_worker=TRUE`
1306
1412
 
1307
- + **Network First** - This strategy tells the Service Worker to always attempt fetching from the network first for given resources, before fetching from the cache. On every successful network fetch, a copy of the response is saved to the cache for next time. (This is good for resources that need to be fresh to the user on a "best effort" basis.) Unless [changed](#default_fetching_strategy), this is Webflo's default fetching strategy. When not the default strategy, a list of specific URLs that should be fetched this way can be [configured](#network_first_urls).
1308
- + **Cache First** - This strategy tells the Service Worker to always attempt fetching from the cache first for given resources, before fetching from the network. After serving a cached response, or where not found in cache, a network fetch happens and a copy of the response is saved to the cache for next time. (This is good for resources that do not critially need to be fresh to the user.) When not the default strategy, a list of specific URLs that should be fetched this way can be [configured](#cache_first_urls).
1309
- + **Network Only** - This strategy tells the Service Worker to always fetch given resources from the network only. They are simply not available when offline. (This is good for resources that critially need to be fresh to the user.) When not the default strategy, a list of specific URLs that should be fetched this way can be [configured](#network_only_urls).
1310
- + **Cache Only** - This strategy tells the Service Worker to always fetch given resources from the cache only. (This is good for resources that do not change often.) When not the default strategy, a list of specific URLs that should be fetched this way can be [configured](#cache_only_urls). The listed resources are pre-cached ahead of when they'll be needed - and are served from the cache each time. (Pre-caching happens on the one-time `install` event of the Service Worker.)
1413
+ ```json
1414
+ { "enable_service_worker": true }
1415
+ ```
1416
+ </details>
1417
+
1418
+ ##### Fetching Strategy
1419
+
1420
+ + **Network First** - This strategy tells the Service Worker to always attempt fetching from the network first for given resources, before fetching from the cache. On every successful network fetch, a copy of the response is saved to the cache for next time. (This is good for resources that need to be fresh to the user on a "best effort" basis.) Unless changed, this is Webflo's default fetching strategy. When not the default strategy, a list of specific URLs that should be fetched this way can be configured.
1421
+
1422
+ <details>
1423
+ <summary>Default Config</summary>
1424
+
1425
+ > File: `.webqit/webflo/client.json` | Command: `webflo config client default_fetching_strategy=network-first`
1426
+
1427
+ ```json
1428
+ { "default_fetching_strategy": "network-first" }
1429
+ ```
1430
+
1431
+ *To list specific URLs...*
1432
+
1433
+ ```json
1434
+ { "network_first_urls": [ "/logo.png" ] }
1435
+ ```
1436
+ </details>
1437
+
1438
+ + **Cache First** - This strategy tells the Service Worker to always attempt fetching from the cache first for given resources, before fetching from the network. After serving a cached response, or where not found in cache, a network fetch happens and a copy of the response is saved to the cache for next time. (This is good for resources that do not critially need to be fresh to the user.) When not the default strategy, a list of specific URLs that should be fetched this way can be configured.
1439
+
1440
+ <details>
1441
+ <summary>Default Config</summary>
1442
+
1443
+ > File: `.webqit/webflo/client.json` | Command: `webflo config client default_fetching_strategy=cache-first`
1444
+
1445
+ ```json
1446
+ { "default_fetching_strategy": "cache-first" }
1447
+ ```
1448
+
1449
+ *To list specific URLs...*
1450
+
1451
+ ```json
1452
+ { "cache_first_urls": [ "/logo.png" ] }
1453
+ ```
1454
+ </details>
1455
+
1456
+ + **Network Only** - This strategy tells the Service Worker to always fetch given resources from the network only. They are simply not available when offline. (This is good for resources that critially need to be fresh to the user.) When not the default strategy, a list of specific URLs that should be fetched this way can be configured.
1457
+
1458
+ <details>
1459
+ <summary>Default Config</summary>
1460
+
1461
+ > File: `.webqit/webflo/client.json` | Command: `webflo config client default_fetching_strategy=network-only`
1462
+
1463
+ ```json
1464
+ { "default_fetching_strategy": "network-only" }
1465
+ ```
1466
+
1467
+ *To list specific URLs...*
1468
+
1469
+ ```json
1470
+ { "network_only_urls": [ "/logo.png" ] }
1471
+ ```
1472
+ </details>
1473
+
1474
+ + **Cache Only** - This strategy tells the Service Worker to always fetch given resources from the cache only. (This is good for resources that do not change often.) When not the default strategy, a list of specific URLs that should be fetched this way can be configured. The listed resources are pre-cached ahead of when they'll be needed - and are served from the cache each time. (Pre-caching happens on the one-time `install` event of the Service Worker.)
1475
+
1476
+ <details>
1477
+ <summary>Default Config</summary>
1478
+
1479
+ > File: `.webqit/webflo/client.json` | Command: `webflo config client default_fetching_strategy=cache-only`
1480
+
1481
+ ```json
1482
+ { "default_fetching_strategy": "cache-only" }
1483
+ ```
1484
+
1485
+ *To list specific URLs...*
1486
+
1487
+ ```json
1488
+ { "cache_only_urls": [ "/logo.png" ] }
1489
+ ```
1490
+ </details>
1311
1491
 
1312
1492
  In all cases above, the convention for specifying URLs for a strategy accepts [URL patterns](https://developer.mozilla.org/en-US/docs/Web/API/URLPattern) - against which URLs can be matched on the fly. For example, to place all files in an `/image` directory (and subdirectories) on the *Cache First* strategy, the pattern `/image/*` can be used. To place all `.svg` files in an `/icons` directory (including subdirectories) on the *Cache Only* strategy, the pattern `/icons/*.svg` can be used. (Specifically for the *Cache Only* strategy, patterns are resolved at Service Worker build-time, and each pattern must match, at least, a file.)
1313
1493
 
1314
- ###### Cross-Thread Communications
1494
+ ```json
1495
+ { "cache_only_urls": [ "/icons/*.svg" ] }
1496
+ ```
1497
+
1498
+ ##### Cross-Thread Communications
1315
1499
 
1316
- A couple APIs exists in browsers for establishing a two-way communication channel between a page and its service worker, for firing UI Notifications from either ends, and for implementing Push Notifications. Webflo offers to simply this with a unifying set of conventions:
1500
+ A couple APIs exists in browsers for establishing a two-way communication channel between a page and its Service Worker, for firing UI Notifications from either ends, and for implementing Push Notifications. Webflo offers to simply this with a unifying set of conventions:
1317
1501
 
1318
1502
  + The `workport` API - an object with simple methods for working with *cross-thread* messages, UI and Push Notifications.
1319
1503
 
@@ -1467,10 +1651,10 @@ And if you will partition your backend for both page routes and a formal REST AP
1467
1651
  ```shell
1468
1652
  server
1469
1653
  ├── index.js ──┐
1470
- ├── cart/index.js ├── Page Routes
1654
+ ├── cart/index.js ├─ Page Routes
1471
1655
  ├── products/index.js ──┘
1472
1656
  ├── api/v1/index.js ──┐
1473
- ├── api/v1/orders/index.js ├── REST API
1657
+ ├── api/v1/orders/index.js ├─ REST API
1474
1658
  └── api/v1/products/index.js ──┘
1475
1659
  ```
1476
1660
 
@@ -1521,7 +1705,46 @@ You have a static site!
1521
1705
 
1522
1706
  ### Webflo Config
1523
1707
 
1524
- > TODO
1708
+ Webflo comes *convention-first*! But it is entirely configurable for when you need it! The easiest way to do this is to run the command `webflo config` and follow the walkthrough. To simply get an overview, use the command `webflo config help`, and all commands and their description are shown.
1709
+
1710
+ ## Technology Stack
1711
+
1712
+ Webflo applications are often built on/with the following technologies.
1713
+
1714
+ ### OOHTML
1715
+
1716
+ [OOHTML](https://github.com/webqit/oohtml) is a proposed set of new features for HTML that makes it fun to hand-author your UI! Within OOHTML are [HTML Modules](https://github.com/webqit/oohtml#html-modules) and [HTML Imports](https://github.com/webqit/oohtml#html-imports), [Reactive Scripts](https://github.com/webqit/oohtml#subscript) and more!
1717
+
1718
+ Webflo natively supports OOHTML in full! But it is also possible to switch this to none, or to partial support - when specific features aren't needed anywhere in your application. Server-side and client-side support for OOHTML exist independently. This is good when, for example, your application places more importance on SSR, and less on CSR, in which case a reduced support for OOHTML can reduce the overall client JS bundle size.
1719
+
1720
+ <details>
1721
+ <summary>Default Config</summary>
1722
+
1723
+ > File: `.webqit/webflo/client.json` | Command: `webflo config client oohtml_support=full`
1724
+
1725
+ > File: `.webqit/webflo/client.json` | Command: `webflo config server oohtml_support=full`
1726
+
1727
+ ```json
1728
+ { "oohtml_support": "full" }
1729
+ ```
1730
+
1731
+ *Values: `full`, `namespacing`, `scripting`, `templating`, `none` - See [details at OOHTML SSR](https://github.com/webqit/oohtml-ssr#options)*
1732
+ </details>
1733
+
1734
+
1735
+ ### OOHTML SSR
1736
+
1737
+ [OOHTML SSR](https://github.com/webqit/oohtml-ssr) is a server-side DOM implementation with native support for OOHTML. This is internally used by Webflo as the Server-Side Rendering engine, and it it what gives Webflo its native support for OOHTML.
1738
+
1739
+ ### OOHTML CLI
1740
+
1741
+ [OOHTML CLI](https://github.com/webqit/oohtml-cli) is a small Command Line utility that automates certain aspects of hand-authored OOHTML-based documents.
1742
+
1743
+ ### The Observer API
1744
+
1745
+ [The Observer API](https://github.com/webqit/observer) is a simple set of functions for intercepting and observing JavaScript objects and arrays. (Reflection, Interception, and Events.)
1746
+
1747
+ This is part of OOHTML's reactivity system, and it is made available on OOHTML-based documents as `window.WebQit.Observer`.
1525
1748
 
1526
1749
  ## Getting Started
1527
1750
 
@@ -1539,13 +1762,3 @@ All forms of contributions and PR are welcome! To report bugs or request feature
1539
1762
  ## License
1540
1763
 
1541
1764
  MIT.
1542
-
1543
- ...
1544
-
1545
- ## Getting Involved
1546
-
1547
- All forms of contributions and PR are welcome! To report bugs or request features, please submit an [issue](https://github.com/webqit/webflo/issues).
1548
-
1549
- ## License
1550
-
1551
- MIT.
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "vanila-javascript"
13
13
  ],
14
14
  "homepage": "https://webqit.io/tooling/webflo",
15
- "version": "0.11.6",
15
+ "version": "0.11.9",
16
16
  "license": "MIT",
17
17
  "repository": {
18
18
  "type": "git",
@@ -118,7 +118,7 @@ export default class Runtime {
118
118
  return params;
119
119
  }, {});
120
120
  // We support method hacking
121
- submitParams.method = (submitter && submitter.dataset.method) || form.dataset.method || submitParams.method;
121
+ submitParams.method = (submitter && submitter.dataset.formmethod) || form.dataset.method || submitParams.method;
122
122
  submitParams.submitter = submitter;
123
123
  // ---------------
124
124
  var actionEl = window.document.createElement('a');
@@ -152,8 +152,8 @@ export default class Runtime {
152
152
  // -----------------------
153
153
  // Initialize network
154
154
  Observer.set(this, 'network', {});
155
- window.addEventListener('online', () => Observer.set(this.network, 'online', navigator.onLine));
156
- window.addEventListener('offline', () => Observer.set(this.network, 'online', navigator.onLine));
155
+ window.addEventListener('online', () => Observer.set(this.network, 'connectivity', 'online'));
156
+ window.addEventListener('offline', () => Observer.set(this.network, 'connectivity', 'offline'));
157
157
 
158
158
  // -----------------------
159
159
  // Service Worker && COMM