@qrxcode/js 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +152 -26
- package/dist/index.cjs +21 -9
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +21 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -29,9 +29,8 @@ and natural as following someone on social media.
|
|
|
29
29
|
|
|
30
30
|
Examples of flows:
|
|
31
31
|
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
- JSON feeds
|
|
32
|
+
- Feed flows
|
|
33
|
+
- QRX flows
|
|
35
34
|
|
|
36
35
|
In QRX, a "flow" is a recognized machine-readable relationship
|
|
37
36
|
that applications can discover and interact with.
|
|
@@ -42,41 +41,107 @@ QRX helps applications discover and work with them more naturally.
|
|
|
42
41
|
|
|
43
42
|
Learn more at https://qrx.dev
|
|
44
43
|
|
|
45
|
-
## Breaking change in 0.
|
|
44
|
+
## Breaking change in 0.3.0
|
|
46
45
|
|
|
47
|
-
Version `0.
|
|
46
|
+
Version `0.3.0` introduced a breaking cleanup of feed flow classification.
|
|
48
47
|
|
|
49
|
-
Before `0.
|
|
48
|
+
Before `0.3.0`, RSS, Atom, and JSON Feed were represented as separate
|
|
49
|
+
QRX flow types:
|
|
50
50
|
|
|
51
51
|
```js
|
|
52
52
|
{
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
flowType: "rss",
|
|
54
|
+
rel: "alternate",
|
|
55
|
+
href: "https://example.com/feed.xml",
|
|
56
|
+
type: "application/rss+xml"
|
|
55
57
|
}
|
|
56
58
|
````
|
|
57
59
|
|
|
58
|
-
Starting from `0.
|
|
60
|
+
Starting from `0.3.0`, RSS, Atom, and JSON Feed are represented as the same
|
|
61
|
+
QRX flow category:
|
|
59
62
|
|
|
60
63
|
```js
|
|
61
64
|
{
|
|
62
|
-
flowType: "
|
|
65
|
+
flowType: "feed",
|
|
63
66
|
rel: "alternate",
|
|
64
67
|
href: "https://example.com/feed.xml",
|
|
65
68
|
type: "application/rss+xml"
|
|
66
69
|
}
|
|
67
70
|
```
|
|
68
71
|
|
|
69
|
-
|
|
72
|
+
The actual feed format remains in the original HTML/link media type:
|
|
73
|
+
|
|
74
|
+
```js
|
|
75
|
+
type: "application/rss+xml"
|
|
76
|
+
type: "application/atom+xml"
|
|
77
|
+
type: "application/feed+json"
|
|
78
|
+
```
|
|
70
79
|
|
|
71
|
-
|
|
72
|
-
* QRX flow classification is now `flow.flowType`.
|
|
73
|
-
* `flow.type` now means the original HTML/link media type.
|
|
74
|
-
* `flow.url` is now `flow.href`.
|
|
80
|
+
Core formula:
|
|
75
81
|
|
|
76
|
-
|
|
82
|
+
```txt
|
|
83
|
+
flowType = QRX category
|
|
84
|
+
type = original web/media format
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Migration:
|
|
88
|
+
|
|
89
|
+
* `flow.flowType === "rss"` is now `flow.flowType === "feed" && flow.type === "application/rss+xml"`.
|
|
90
|
+
* `flow.flowType === "atom"` is now `flow.flowType === "feed" && flow.type === "application/atom+xml"`.
|
|
91
|
+
* `flow.flowType === "jsonfeed"` is now `flow.flowType === "feed" && flow.type === "application/feed+json"`.
|
|
77
92
|
|
|
78
93
|
QRX discovers recognized flows. Applications decide what to do with them.
|
|
79
94
|
|
|
95
|
+
## New in 0.4.0
|
|
96
|
+
|
|
97
|
+
Version `0.4.0` adds a new flow category:
|
|
98
|
+
|
|
99
|
+
```js
|
|
100
|
+
flowType: "qrx"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
A QRX flow is discovered from an explicit HTML `<link>` declaration:
|
|
104
|
+
|
|
105
|
+
```html
|
|
106
|
+
<link
|
|
107
|
+
rel="qrx"
|
|
108
|
+
type="application/qrx+json"
|
|
109
|
+
href="/qrx.json">
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
QRX flow discovery requires all of these:
|
|
113
|
+
|
|
114
|
+
* `rel="qrx"`
|
|
115
|
+
* `href`
|
|
116
|
+
* explicit `type`
|
|
117
|
+
|
|
118
|
+
For `qrx` flows, `rel` must be exactly `qrx`.
|
|
119
|
+
|
|
120
|
+
These are valid:
|
|
121
|
+
|
|
122
|
+
```html
|
|
123
|
+
<link rel="qrx" type="application/qrx+json" href="/qrx.json">
|
|
124
|
+
<link rel="qrx" type="text/html" href="/demo.html">
|
|
125
|
+
<link rel="qrx" type="application/json" href="/manifest.json">
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
These are not valid QRX flow declarations:
|
|
129
|
+
|
|
130
|
+
```html
|
|
131
|
+
<link rel="alternate qrx" type="application/qrx+json" href="/qrx.json">
|
|
132
|
+
<link rel="qrx something" type="application/qrx+json" href="/qrx.json">
|
|
133
|
+
<link rel="notqrx" type="application/qrx+json" href="/qrx.json">
|
|
134
|
+
<link rel="qrx" href="/qrx.json">
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The `type` value can be any explicit media type, not only
|
|
138
|
+
`application/qrx+json`.
|
|
139
|
+
|
|
140
|
+
The package does not fetch or parse QRX payloads. It only discovers the
|
|
141
|
+
declared flow.
|
|
142
|
+
|
|
143
|
+
Applications decide what to do with discovered QRX flows.
|
|
144
|
+
|
|
80
145
|
## Install
|
|
81
146
|
|
|
82
147
|
```bash
|
|
@@ -89,7 +154,7 @@ npm install @qrxcode/js
|
|
|
89
154
|
import { resolveQRX } from "@qrxcode/js";
|
|
90
155
|
|
|
91
156
|
const result = await resolveQRX(
|
|
92
|
-
"https://
|
|
157
|
+
"https://example.com"
|
|
93
158
|
);
|
|
94
159
|
|
|
95
160
|
console.log(result.flows);
|
|
@@ -100,28 +165,76 @@ console.log(result.flows);
|
|
|
100
165
|
```js
|
|
101
166
|
[
|
|
102
167
|
{
|
|
103
|
-
flowType: "
|
|
168
|
+
flowType: "feed",
|
|
104
169
|
rel: "alternate",
|
|
105
|
-
href: "https://
|
|
170
|
+
href: "https://example.com/feed.xml",
|
|
106
171
|
type: "application/rss+xml"
|
|
107
172
|
},
|
|
108
173
|
{
|
|
109
|
-
flowType: "
|
|
110
|
-
rel: "
|
|
111
|
-
href: "https://
|
|
112
|
-
type: "application/
|
|
174
|
+
flowType: "qrx",
|
|
175
|
+
rel: "qrx",
|
|
176
|
+
href: "https://example.com/qrx.json",
|
|
177
|
+
type: "application/qrx+json"
|
|
113
178
|
}
|
|
114
179
|
]
|
|
115
180
|
```
|
|
116
181
|
|
|
182
|
+
## Selecting flows
|
|
183
|
+
|
|
184
|
+
To select all feed flows:
|
|
185
|
+
|
|
186
|
+
```js
|
|
187
|
+
import {
|
|
188
|
+
resolveQRX,
|
|
189
|
+
selectFlowsByFlowType
|
|
190
|
+
} from "@qrxcode/js";
|
|
191
|
+
|
|
192
|
+
const result = await resolveQRX(
|
|
193
|
+
"https://example.com"
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
const feeds = selectFlowsByFlowType(
|
|
197
|
+
result.flows,
|
|
198
|
+
["feed"]
|
|
199
|
+
);
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
This returns RSS, Atom, and JSON Feed flows together.
|
|
203
|
+
|
|
204
|
+
To select only RSS feeds, filter by the original media type:
|
|
205
|
+
|
|
206
|
+
```js
|
|
207
|
+
const rssFeeds = result.flows.filter(
|
|
208
|
+
(discoveredFlow) =>
|
|
209
|
+
discoveredFlow.flowType === "feed" &&
|
|
210
|
+
discoveredFlow.type === "application/rss+xml"
|
|
211
|
+
);
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
To select QRX flows:
|
|
215
|
+
|
|
216
|
+
```js
|
|
217
|
+
const qrxFlows = selectFlowsByFlowType(
|
|
218
|
+
result.flows,
|
|
219
|
+
["qrx"]
|
|
220
|
+
);
|
|
221
|
+
```
|
|
222
|
+
|
|
117
223
|
## Supported flow types
|
|
118
224
|
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
|
|
225
|
+
* feed
|
|
226
|
+
* qrx
|
|
227
|
+
|
|
228
|
+
## Supported feed formats
|
|
229
|
+
|
|
230
|
+
* RSS: `application/rss+xml`
|
|
231
|
+
* Atom: `application/atom+xml`
|
|
232
|
+
* JSON Feed: `application/feed+json`
|
|
122
233
|
|
|
123
234
|
## Supported discovery methods
|
|
124
235
|
|
|
236
|
+
Feed flow:
|
|
237
|
+
|
|
125
238
|
```html
|
|
126
239
|
<link
|
|
127
240
|
rel="alternate"
|
|
@@ -143,9 +256,22 @@ console.log(result.flows);
|
|
|
143
256
|
href="/feed.json">
|
|
144
257
|
```
|
|
145
258
|
|
|
259
|
+
QRX flow:
|
|
260
|
+
|
|
261
|
+
```html
|
|
262
|
+
<link
|
|
263
|
+
rel="qrx"
|
|
264
|
+
type="application/qrx+json"
|
|
265
|
+
href="/qrx.json">
|
|
266
|
+
```
|
|
267
|
+
|
|
146
268
|
## Philosophy
|
|
147
269
|
|
|
148
270
|
QRX does not change QR codes.
|
|
149
271
|
|
|
272
|
+
QRX discovers recognized flows.
|
|
273
|
+
|
|
274
|
+
Applications decide what to do with them.
|
|
275
|
+
|
|
150
276
|
With QRX, sources can expose machine-readable flows,
|
|
151
277
|
and applications can understand and interact with them naturally.
|
package/dist/index.cjs
CHANGED
|
@@ -27,11 +27,11 @@ __export(index_exports, {
|
|
|
27
27
|
module.exports = __toCommonJS(index_exports);
|
|
28
28
|
|
|
29
29
|
// src/detect.ts
|
|
30
|
-
var
|
|
31
|
-
"application/rss+xml"
|
|
32
|
-
"application/atom+xml"
|
|
33
|
-
"application/feed+json"
|
|
34
|
-
|
|
30
|
+
var FEED_TYPES = /* @__PURE__ */ new Set([
|
|
31
|
+
"application/rss+xml",
|
|
32
|
+
"application/atom+xml",
|
|
33
|
+
"application/feed+json"
|
|
34
|
+
]);
|
|
35
35
|
function detectFlows(html, sourceUrl) {
|
|
36
36
|
const flows = [];
|
|
37
37
|
const linkTagRegex = /<link\s+[^>]*>/gi;
|
|
@@ -45,17 +45,29 @@ function detectFlows(html, sourceUrl) {
|
|
|
45
45
|
}
|
|
46
46
|
const normalizedRel = rel.trim();
|
|
47
47
|
const normalizedType = type.trim().toLowerCase();
|
|
48
|
+
const resolvedHref = new URL(
|
|
49
|
+
href,
|
|
50
|
+
sourceUrl
|
|
51
|
+
).toString();
|
|
52
|
+
if (normalizedRel === "qrx") {
|
|
53
|
+
flows.push({
|
|
54
|
+
flowType: "qrx",
|
|
55
|
+
rel: normalizedRel,
|
|
56
|
+
href: resolvedHref,
|
|
57
|
+
type: normalizedType
|
|
58
|
+
});
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
48
61
|
if (!hasRel(normalizedRel, "alternate")) {
|
|
49
62
|
continue;
|
|
50
63
|
}
|
|
51
|
-
|
|
52
|
-
if (!flowType) {
|
|
64
|
+
if (!FEED_TYPES.has(normalizedType)) {
|
|
53
65
|
continue;
|
|
54
66
|
}
|
|
55
67
|
flows.push({
|
|
56
|
-
flowType,
|
|
68
|
+
flowType: "feed",
|
|
57
69
|
rel: normalizedRel,
|
|
58
|
-
href:
|
|
70
|
+
href: resolvedHref,
|
|
59
71
|
type: normalizedType
|
|
60
72
|
});
|
|
61
73
|
}
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// src/detect.ts
|
|
2
|
-
var
|
|
3
|
-
"application/rss+xml"
|
|
4
|
-
"application/atom+xml"
|
|
5
|
-
"application/feed+json"
|
|
6
|
-
|
|
2
|
+
var FEED_TYPES = /* @__PURE__ */ new Set([
|
|
3
|
+
"application/rss+xml",
|
|
4
|
+
"application/atom+xml",
|
|
5
|
+
"application/feed+json"
|
|
6
|
+
]);
|
|
7
7
|
function detectFlows(html, sourceUrl) {
|
|
8
8
|
const flows = [];
|
|
9
9
|
const linkTagRegex = /<link\s+[^>]*>/gi;
|
|
@@ -17,17 +17,29 @@ function detectFlows(html, sourceUrl) {
|
|
|
17
17
|
}
|
|
18
18
|
const normalizedRel = rel.trim();
|
|
19
19
|
const normalizedType = type.trim().toLowerCase();
|
|
20
|
+
const resolvedHref = new URL(
|
|
21
|
+
href,
|
|
22
|
+
sourceUrl
|
|
23
|
+
).toString();
|
|
24
|
+
if (normalizedRel === "qrx") {
|
|
25
|
+
flows.push({
|
|
26
|
+
flowType: "qrx",
|
|
27
|
+
rel: normalizedRel,
|
|
28
|
+
href: resolvedHref,
|
|
29
|
+
type: normalizedType
|
|
30
|
+
});
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
20
33
|
if (!hasRel(normalizedRel, "alternate")) {
|
|
21
34
|
continue;
|
|
22
35
|
}
|
|
23
|
-
|
|
24
|
-
if (!flowType) {
|
|
36
|
+
if (!FEED_TYPES.has(normalizedType)) {
|
|
25
37
|
continue;
|
|
26
38
|
}
|
|
27
39
|
flows.push({
|
|
28
|
-
flowType,
|
|
40
|
+
flowType: "feed",
|
|
29
41
|
rel: normalizedRel,
|
|
30
|
-
href:
|
|
42
|
+
href: resolvedHref,
|
|
31
43
|
type: normalizedType
|
|
32
44
|
});
|
|
33
45
|
}
|