@xylabs/sdk-meta 4.0.7
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/LICENSE +165 -0
- package/README.md +62 -0
- package/dist/neutral/html/index.d.ts +2 -0
- package/dist/neutral/html/index.d.ts.map +1 -0
- package/dist/neutral/html/mergeDocumentHead.d.ts +2 -0
- package/dist/neutral/html/mergeDocumentHead.d.ts.map +1 -0
- package/dist/neutral/index.d.ts +4 -0
- package/dist/neutral/index.d.ts.map +1 -0
- package/dist/neutral/index.mjs +87 -0
- package/dist/neutral/index.mjs.map +1 -0
- package/dist/neutral/lib/getMetaAsDict.d.ts +6 -0
- package/dist/neutral/lib/getMetaAsDict.d.ts.map +1 -0
- package/dist/neutral/lib/index.d.ts +2 -0
- package/dist/neutral/lib/index.d.ts.map +1 -0
- package/dist/neutral/meta/builder.d.ts +3 -0
- package/dist/neutral/meta/builder.d.ts.map +1 -0
- package/dist/neutral/meta/index.d.ts +2 -0
- package/dist/neutral/meta/index.d.ts.map +1 -0
- package/dist/neutral/models/Meta.d.ts +9 -0
- package/dist/neutral/models/Meta.d.ts.map +1 -0
- package/dist/neutral/models/OpenGraph/OpenGraphMeta.d.ts +14 -0
- package/dist/neutral/models/OpenGraph/OpenGraphMeta.d.ts.map +1 -0
- package/dist/neutral/models/OpenGraph/OpenGraphStructured.d.ts +10 -0
- package/dist/neutral/models/OpenGraph/OpenGraphStructured.d.ts.map +1 -0
- package/dist/neutral/models/OpenGraph/OpenGraphStructuredProperty.d.ts +3 -0
- package/dist/neutral/models/OpenGraph/OpenGraphStructuredProperty.d.ts.map +1 -0
- package/dist/neutral/models/OpenGraph/index.d.ts +4 -0
- package/dist/neutral/models/OpenGraph/index.d.ts.map +1 -0
- package/dist/neutral/models/Twitter/Twitter.d.ts +22 -0
- package/dist/neutral/models/Twitter/Twitter.d.ts.map +1 -0
- package/dist/neutral/models/Twitter/TwitterApp.d.ts +18 -0
- package/dist/neutral/models/Twitter/TwitterApp.d.ts.map +1 -0
- package/dist/neutral/models/Twitter/TwitterPlayer.d.ts +7 -0
- package/dist/neutral/models/Twitter/TwitterPlayer.d.ts.map +1 -0
- package/dist/neutral/models/Twitter/index.d.ts +4 -0
- package/dist/neutral/models/Twitter/index.d.ts.map +1 -0
- package/dist/neutral/models/index.d.ts +4 -0
- package/dist/neutral/models/index.d.ts.map +1 -0
- package/package.json +52 -0
- package/src/html/index.ts +1 -0
- package/src/html/mergeDocumentHead.ts +46 -0
- package/src/html/spec/__snapshots__/mergeDocumentHead.approval.spec.ts.snap +45 -0
- package/src/html/spec/destination.html +23 -0
- package/src/html/spec/mergeDocumentHead.approval.spec.ts +20 -0
- package/src/html/spec/mergeDocumentHead.spec.ts +46 -0
- package/src/html/spec/source.html +2724 -0
- package/src/index.ts +3 -0
- package/src/lib/getMetaAsDict.ts +21 -0
- package/src/lib/index.ts +1 -0
- package/src/lib/spec/getMetaAsDict.spec.ts +16 -0
- package/src/meta/builder.ts +49 -0
- package/src/meta/index.ts +1 -0
- package/src/models/Meta.ts +9 -0
- package/src/models/OpenGraph/OpenGraphMeta.ts +17 -0
- package/src/models/OpenGraph/OpenGraphStructured.ts +9 -0
- package/src/models/OpenGraph/OpenGraphStructuredProperty.ts +3 -0
- package/src/models/OpenGraph/index.ts +3 -0
- package/src/models/Twitter/Twitter.ts +67 -0
- package/src/models/Twitter/TwitterApp.ts +17 -0
- package/src/models/Twitter/TwitterPlayer.ts +23 -0
- package/src/models/Twitter/index.ts +3 -0
- package/src/models/index.ts +3 -0
- package/src/spec/__snapshots__/builder.spec.ts.snap +187 -0
- package/src/spec/builder.spec.ts +125 -0
- package/src/spec/template.html +42 -0
- package/typedoc.json +5 -0
- package/xy.config.ts +10 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { load } from 'cheerio'
|
|
2
|
+
|
|
3
|
+
const opts = {}
|
|
4
|
+
// const opts = { decodeEntities: false }
|
|
5
|
+
|
|
6
|
+
export const mergeDocumentHead = (destination: string, source: string) => {
|
|
7
|
+
const $destination = load(destination, opts)
|
|
8
|
+
const $source = load(source, opts)
|
|
9
|
+
|
|
10
|
+
// For each child node of the source head
|
|
11
|
+
$source('head')
|
|
12
|
+
.children()
|
|
13
|
+
.each((_, element) => {
|
|
14
|
+
const el = $destination(element)
|
|
15
|
+
|
|
16
|
+
// Special case for meta tags: We want to match them by the name attribute
|
|
17
|
+
if (el[0].tagName === 'meta') {
|
|
18
|
+
const property = el.attr('property')
|
|
19
|
+
if (property) {
|
|
20
|
+
const match = $destination(`head meta[property="${property}"]`)
|
|
21
|
+
|
|
22
|
+
// If it exists, replace it, otherwise append it
|
|
23
|
+
if (match.length > 0) {
|
|
24
|
+
match.replaceWith(el)
|
|
25
|
+
return
|
|
26
|
+
} else {
|
|
27
|
+
$destination('head').append(el)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// else {
|
|
31
|
+
// // For all other elements, just check if the same element exists in the first HTML string
|
|
32
|
+
// const match = $destination(el[0].tagName)
|
|
33
|
+
|
|
34
|
+
// // If it exists, replace it, otherwise append it
|
|
35
|
+
// if (match.length > 0) {
|
|
36
|
+
// match.replaceWith(el)
|
|
37
|
+
// } else {
|
|
38
|
+
// $destination('head').append(el)
|
|
39
|
+
// }
|
|
40
|
+
// }
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
// Return the merged HTML
|
|
45
|
+
return $destination.html(opts)
|
|
46
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`mergeDocumentHead > with real documents 1`] = `
|
|
4
|
+
"<!DOCTYPE html><html lang="en"><head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<link rel="icon" href="/favicon.ico">
|
|
7
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
8
|
+
<meta name="description" content="Your Data, Forever Long.">
|
|
9
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
10
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
11
|
+
<link href="https://fonts.googleapis.com/css2?family=Roboto+Flex:wght@300;400;500;600;800&display=swap" rel="stylesheet">
|
|
12
|
+
<link rel="apple-touch-icon" href="/foreventory-logo-icon-black.png">
|
|
13
|
+
<link rel="manifest" href="/manifest.json">
|
|
14
|
+
<title>Foreventory</title>
|
|
15
|
+
<script defer="defer" src="/static/js/main.297e104a.js"></script>
|
|
16
|
+
<meta content="website" property="og:type" data-react-helmet="true"><meta property="og:image" content="/netflix/insights/6f088236519e8e0c9ab9294c2e59fb2b8b434091a7559401ae860ff445fb1355/share/1600/900"><meta property="og:image:height" content="900"><meta property="og:image:secure_url" content="/netflix/insights/6f088236519e8e0c9ab9294c2e59fb2b8b434091a7559401ae860ff445fb1355/share/1600/900"><meta property="og:image:type" content="image/png"><meta property="og:image:url" content="/netflix/insights/6f088236519e8e0c9ab9294c2e59fb2b8b434091a7559401ae860ff445fb1355/share/1600/900"><meta property="og:image:width" content="1600"><meta property="twitter:image" content="/netflix/insights/6f088236519e8e0c9ab9294c2e59fb2b8b434091a7559401ae860ff445fb1355/share/1600/900"></head>
|
|
17
|
+
|
|
18
|
+
<body><noscript>You need to enable JavaScript to run this app.</noscript>
|
|
19
|
+
<div id="root"></div>
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
</body></html>"
|
|
23
|
+
`;
|
|
24
|
+
|
|
25
|
+
exports[`mergeDocumentHead with real documents 1`] = `
|
|
26
|
+
"<!DOCTYPE html><html lang="en"><head>
|
|
27
|
+
<meta charset="utf-8">
|
|
28
|
+
<link rel="icon" href="/favicon.ico">
|
|
29
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
30
|
+
<meta name="description" content="Your Data, Forever Long.">
|
|
31
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
32
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
33
|
+
<link href="https://fonts.googleapis.com/css2?family=Roboto+Flex:wght@300;400;500;600;800&display=swap" rel="stylesheet">
|
|
34
|
+
<link rel="apple-touch-icon" href="/foreventory-logo-icon-black.png">
|
|
35
|
+
<link rel="manifest" href="/manifest.json">
|
|
36
|
+
<title>Foreventory</title>
|
|
37
|
+
<script defer="defer" src="/static/js/main.297e104a.js"></script>
|
|
38
|
+
<meta content="website" property="og:type" data-react-helmet="true"><meta property="og:image" content="/netflix/insights/6f088236519e8e0c9ab9294c2e59fb2b8b434091a7559401ae860ff445fb1355/share/1600/900"><meta property="og:image:height" content="900"><meta property="og:image:secure_url" content="/netflix/insights/6f088236519e8e0c9ab9294c2e59fb2b8b434091a7559401ae860ff445fb1355/share/1600/900"><meta property="og:image:type" content="image/png"><meta property="og:image:url" content="/netflix/insights/6f088236519e8e0c9ab9294c2e59fb2b8b434091a7559401ae860ff445fb1355/share/1600/900"><meta property="og:image:width" content="1600"><meta property="twitter:image" content="/netflix/insights/6f088236519e8e0c9ab9294c2e59fb2b8b434091a7559401ae860ff445fb1355/share/1600/900"></head>
|
|
39
|
+
|
|
40
|
+
<body><noscript>You need to enable JavaScript to run this app.</noscript>
|
|
41
|
+
<div id="root"></div>
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
</body></html>"
|
|
45
|
+
`;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8" />
|
|
6
|
+
<link rel="icon" href="/favicon.ico" />
|
|
7
|
+
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
8
|
+
<meta name="description" content="Your Data, Forever Long." />
|
|
9
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
10
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
11
|
+
<link href="https://fonts.googleapis.com/css2?family=Roboto+Flex:wght@300;400;500;600;800&display=swap"
|
|
12
|
+
rel="stylesheet">
|
|
13
|
+
<link rel="apple-touch-icon" href="/foreventory-logo-icon-black.png" />
|
|
14
|
+
<link rel="manifest" href="/manifest.json" />
|
|
15
|
+
<title>Foreventory</title>
|
|
16
|
+
<script defer="defer" src="/static/js/main.297e104a.js"></script>
|
|
17
|
+
</head>
|
|
18
|
+
|
|
19
|
+
<body><noscript>You need to enable JavaScript to run this app.</noscript>
|
|
20
|
+
<div id="root"></div>
|
|
21
|
+
</body>
|
|
22
|
+
|
|
23
|
+
</html>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { readFile, writeFile } from 'node:fs/promises'
|
|
2
|
+
import Path from 'node:path'
|
|
3
|
+
|
|
4
|
+
import { mergeDocumentHead } from '../mergeDocumentHead.ts'
|
|
5
|
+
|
|
6
|
+
const writeDebugFile = false
|
|
7
|
+
|
|
8
|
+
describe('mergeDocumentHead', () => {
|
|
9
|
+
let destination: string
|
|
10
|
+
let source: string
|
|
11
|
+
beforeAll(async () => {
|
|
12
|
+
destination = await readFile(Path.join(__dirname, 'destination.html'), { encoding: 'utf8' })
|
|
13
|
+
source = await readFile(Path.join(__dirname, 'source.html'), { encoding: 'utf8' })
|
|
14
|
+
})
|
|
15
|
+
it('with real documents', async () => {
|
|
16
|
+
const result = mergeDocumentHead(destination, source)
|
|
17
|
+
expect(result).toMatchSnapshot()
|
|
18
|
+
if (writeDebugFile) await writeFile(Path.join(__dirname, 'result.html'), result)
|
|
19
|
+
})
|
|
20
|
+
})
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/* eslint-disable @stylistic/max-len */
|
|
2
|
+
import { mergeDocumentHead } from '../mergeDocumentHead.ts'
|
|
3
|
+
|
|
4
|
+
describe('mergeDocumentHead', () => {
|
|
5
|
+
const cases: [string, string, string, string][] = [
|
|
6
|
+
[
|
|
7
|
+
'Overwrites existing elements',
|
|
8
|
+
'<html><head><meta property="description" content="original"></head><body></body></html>',
|
|
9
|
+
'<html><head><meta property="description" content="updated"></head><body></body></html>',
|
|
10
|
+
'<html><head><meta property="description" content="updated"></head><body></body></html>',
|
|
11
|
+
],
|
|
12
|
+
[
|
|
13
|
+
'Merges unique elements',
|
|
14
|
+
'<html><head><meta property="og:title" content="original"></head><body></body></html>',
|
|
15
|
+
'<html><head><meta property="og:description" content="updated"></head><body></body></html>',
|
|
16
|
+
'<html><head><meta property="og:title" content="original"><meta property="og:description" content="updated"></head><body></body></html>',
|
|
17
|
+
],
|
|
18
|
+
[
|
|
19
|
+
'Overwrites existing elements & merges unique elements',
|
|
20
|
+
'<html><head><meta property="description" content="original"><meta property="og:title" content="original"></head><body></body></html>',
|
|
21
|
+
'<html><head><meta property="description" content="updated"><meta property="og:description" content="updated"></head><body></body></html>',
|
|
22
|
+
'<html><head><meta property="description" content="updated"><meta property="og:title" content="original"><meta property="og:description" content="updated"></head><body></body></html>',
|
|
23
|
+
],
|
|
24
|
+
[
|
|
25
|
+
'Handles missing head tag in source',
|
|
26
|
+
'<html><head><meta property="description" content="original"></head><body></body></html>',
|
|
27
|
+
'<html><body></body></html>',
|
|
28
|
+
'<html><head><meta property="description" content="original"></head><body></body></html>',
|
|
29
|
+
],
|
|
30
|
+
[
|
|
31
|
+
'Handles missing head tag in destination',
|
|
32
|
+
'<html><body></body></html>',
|
|
33
|
+
'<html><head><meta property="description" content="updated"></head><body></body></html>',
|
|
34
|
+
'<html><head><meta property="description" content="updated"></head><body></body></html>',
|
|
35
|
+
],
|
|
36
|
+
[
|
|
37
|
+
'Handles missing head tag in source & destination',
|
|
38
|
+
'<html><body>original</body></html>',
|
|
39
|
+
'<html><body>updated</body></html>',
|
|
40
|
+
'<html><head></head><body>original</body></html>',
|
|
41
|
+
],
|
|
42
|
+
]
|
|
43
|
+
it.each(cases)('%s', (_, a: string, b: string, expected: string) => {
|
|
44
|
+
expect(mergeDocumentHead(a, b)).toBe(expected)
|
|
45
|
+
})
|
|
46
|
+
})
|