@xylabs/sdk-meta 4.9.3 → 4.9.5

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.
@@ -1,4 +1,5 @@
1
1
  // src/html/mergeDocumentHead.ts
2
+ import { isString } from "@xylabs/typeof";
2
3
  import { load } from "cheerio";
3
4
  var opts = {};
4
5
  var mergeDocumentHead = (destination, source) => {
@@ -8,7 +9,7 @@ var mergeDocumentHead = (destination, source) => {
8
9
  const el = $destination(element);
9
10
  if (el[0].tagName === "meta") {
10
11
  const property = el.attr("property");
11
- if (property) {
12
+ if (isString(property)) {
12
13
  const match = $destination(`head meta[property="${property}"]`);
13
14
  if (match.length > 0) {
14
15
  match.replaceWith(el);
@@ -23,15 +24,16 @@ var mergeDocumentHead = (destination, source) => {
23
24
  };
24
25
 
25
26
  // src/lib/getMetaAsDict.ts
27
+ import { isString as isString2 } from "@xylabs/typeof";
26
28
  var propertyDelimiter = ":";
27
- var getMetaAsDict = (obj, parentKey = "") => {
29
+ var getMetaAsDict = (obj, parentKey) => {
28
30
  let flatRecord = {};
29
31
  for (const key in obj) {
30
32
  if (typeof obj[key] === "object" && obj[key] !== null) {
31
33
  const childRecord = getMetaAsDict(obj[key], `${parentKey}${key}${propertyDelimiter}`);
32
34
  flatRecord = { ...flatRecord, ...childRecord };
33
35
  } else {
34
- const newKey = parentKey ? `${parentKey}${key}` : key;
36
+ const newKey = isString2(parentKey) ? `${parentKey}${key}` : key;
35
37
  const trimmed = newKey.endsWith(propertyDelimiter) ? newKey.slice(0, -1) : newKey;
36
38
  flatRecord[trimmed] = `${obj[key]}`;
37
39
  }
@@ -40,6 +42,7 @@ var getMetaAsDict = (obj, parentKey = "") => {
40
42
  };
41
43
 
42
44
  // src/meta/builder.ts
45
+ import { isString as isString3 } from "@xylabs/typeof";
43
46
  import { load as load2 } from "cheerio";
44
47
  var addMetaToHead = ($, name, value) => {
45
48
  if (typeof value === "string") {
@@ -68,15 +71,15 @@ var metaBuilder = (html, meta, handler) => {
68
71
  const $ = load2(html);
69
72
  const metaProperties = getMetaAsDict(meta);
70
73
  for (const [key, value] of Object.entries(metaProperties)) {
71
- if (value) addMetaToHead($, key, value);
74
+ addMetaToHead($, key, value);
72
75
  }
73
- if (meta.description) {
76
+ if (isString3(meta.description)) {
74
77
  addMetaToHead($, "description", meta.description);
75
78
  }
76
- if (meta.title) {
79
+ if (isString3(meta.title)) {
77
80
  $("title").text(meta.title);
78
81
  }
79
- if (handler) {
82
+ if (isString3(handler)) {
80
83
  addMetaToHead($, "meta-handler", handler);
81
84
  }
82
85
  return $.html();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/html/mergeDocumentHead.ts","../../src/lib/getMetaAsDict.ts","../../src/meta/builder.ts"],"sourcesContent":["import { load } from 'cheerio'\n\nconst opts = {}\n// const opts = { decodeEntities: false }\n\nexport const mergeDocumentHead = (destination: string, source: string) => {\n const $destination = load(destination, opts)\n const $source = load(source, opts)\n\n // For each child node of the source head\n $source('head')\n .children()\n .each((_, element) => {\n const el = $destination(element)\n\n // Special case for meta tags: We want to match them by the name attribute\n if (el[0].tagName === 'meta') {\n const property = el.attr('property')\n if (property) {\n const match = $destination(`head meta[property=\"${property}\"]`)\n\n // If it exists, replace it, otherwise append it\n if (match.length > 0) {\n match.replaceWith(el)\n return\n } else {\n $destination('head').append(el)\n }\n }\n // else {\n // // For all other elements, just check if the same element exists in the first HTML string\n // const match = $destination(el[0].tagName)\n\n // // If it exists, replace it, otherwise append it\n // if (match.length > 0) {\n // match.replaceWith(el)\n // } else {\n // $destination('head').append(el)\n // }\n // }\n }\n })\n\n // Return the merged HTML\n return $destination.html(opts)\n}\n","// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type StringIndexable = { [key: string]: any }\n\nconst propertyDelimiter = ':'\n\nexport const getMetaAsDict = (obj: StringIndexable, parentKey = ''): Record<string, string> => {\n let flatRecord: StringIndexable = {}\n for (const key in obj) {\n if (typeof obj[key] === 'object' && obj[key] !== null) {\n // If the value is another object, we want to iterate through its keys as well.\n const childRecord = getMetaAsDict(obj[key] as StringIndexable, `${parentKey}${key}${propertyDelimiter}`)\n flatRecord = { ...flatRecord, ...childRecord }\n } else {\n // Concatenate the key with its parent key.\n const newKey = parentKey ? `${parentKey}${key}` : key\n const trimmed = newKey.endsWith(propertyDelimiter) ? newKey.slice(0, -1) : newKey\n flatRecord[trimmed] = `${obj[key]}`\n }\n }\n return flatRecord\n}\n","import type { CheerioAPI } from 'cheerio'\nimport { load } from 'cheerio'\n\nimport { getMetaAsDict } from '../lib/index.ts'\nimport type { Meta } from '../models/index.ts'\n\n/* test change */\n\nconst addMetaToHead = ($: CheerioAPI, name: string, value: string | object) => {\n if (typeof value === 'string') {\n const newMeta = `<meta property=\"${name}\" content=\"${value}\" />`\n const existingMeta = $(`head meta[property=\"${name}\"]`)\n if ((existingMeta?.length ?? 0) > 0) {\n existingMeta.replaceWith(newMeta)\n } else {\n $('head').append(newMeta)\n }\n } else if (Array.isArray(value)) {\n for (const item of value) addMetaToHead($, `${name}`, item)\n } else if (typeof value === 'object') {\n for (let [key, v] of Object.entries(value)) {\n if (key === 'url') {\n addMetaToHead($, name, v)\n } else {\n addMetaToHead($, `${name}:${key}`, v)\n }\n }\n } else {\n throw new TypeError(`Invalid item type [${name}, ${typeof value}]`)\n }\n}\n\nexport const metaBuilder = (html: string, meta: Meta, handler?: string) => {\n const $ = load(html)\n // NOTE: This assumes unique meta properties (no duplicates)\n // which is generally the case, but not always (you can have\n // multiple og:video:tag tags, for example)\n const metaProperties = getMetaAsDict(meta)\n for (const [key, value] of Object.entries(metaProperties)) {\n if (value) addMetaToHead($, key, value)\n }\n if (meta.description) {\n addMetaToHead($, 'description', meta.description)\n }\n if (meta.title) {\n $('title').text(meta.title)\n }\n if (handler) {\n addMetaToHead($, 'meta-handler', handler)\n }\n return $.html()\n}\n"],"mappings":"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","names":["load","load"]}
1
+ {"version":3,"sources":["../../src/html/mergeDocumentHead.ts","../../src/lib/getMetaAsDict.ts","../../src/meta/builder.ts"],"sourcesContent":["import { isString } from '@xylabs/typeof'\nimport { load } from 'cheerio'\n\nconst opts = {}\n// const opts = { decodeEntities: false }\n\nexport const mergeDocumentHead = (destination: string, source: string) => {\n const $destination = load(destination, opts)\n const $source = load(source, opts)\n\n // For each child node of the source head\n $source('head')\n .children()\n .each((_, element) => {\n const el = $destination(element)\n\n // Special case for meta tags: We want to match them by the name attribute\n if (el[0].tagName === 'meta') {\n const property = el.attr('property')\n if (isString(property)) {\n const match = $destination(`head meta[property=\"${property}\"]`)\n\n // If it exists, replace it, otherwise append it\n if (match.length > 0) {\n match.replaceWith(el)\n return\n } else {\n $destination('head').append(el)\n }\n }\n // else {\n // // For all other elements, just check if the same element exists in the first HTML string\n // const match = $destination(el[0].tagName)\n\n // // If it exists, replace it, otherwise append it\n // if (match.length > 0) {\n // match.replaceWith(el)\n // } else {\n // $destination('head').append(el)\n // }\n // }\n }\n })\n\n // Return the merged HTML\n return $destination.html(opts)\n}\n","import { isString } from '@xylabs/typeof'\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type StringIndexable = { [key: string]: any }\n\nconst propertyDelimiter = ':'\n\nexport const getMetaAsDict = (obj: StringIndexable, parentKey?: string): Record<string, string> => {\n let flatRecord: StringIndexable = {}\n for (const key in obj) {\n if (typeof obj[key] === 'object' && obj[key] !== null) {\n // If the value is another object, we want to iterate through its keys as well.\n const childRecord = getMetaAsDict(obj[key] as StringIndexable, `${parentKey}${key}${propertyDelimiter}`)\n flatRecord = { ...flatRecord, ...childRecord }\n } else {\n // Concatenate the key with its parent key.\n const newKey = isString(parentKey) ? `${parentKey}${key}` : key\n const trimmed = newKey.endsWith(propertyDelimiter) ? newKey.slice(0, -1) : newKey\n flatRecord[trimmed] = `${obj[key]}`\n }\n }\n return flatRecord\n}\n","import { isString } from '@xylabs/typeof'\nimport type { CheerioAPI } from 'cheerio'\nimport { load } from 'cheerio'\n\nimport { getMetaAsDict } from '../lib/index.ts'\nimport type { Meta } from '../models/index.ts'\n\n/* test change */\n\nconst addMetaToHead = ($: CheerioAPI, name: string, value: string | object) => {\n if (typeof value === 'string') {\n const newMeta = `<meta property=\"${name}\" content=\"${value}\" />`\n const existingMeta = $(`head meta[property=\"${name}\"]`)\n if ((existingMeta?.length ?? 0) > 0) {\n existingMeta.replaceWith(newMeta)\n } else {\n $('head').append(newMeta)\n }\n } else if (Array.isArray(value)) {\n for (const item of value) addMetaToHead($, `${name}`, item)\n } else if (typeof value === 'object') {\n for (let [key, v] of Object.entries(value)) {\n if (key === 'url') {\n addMetaToHead($, name, v)\n } else {\n addMetaToHead($, `${name}:${key}`, v)\n }\n }\n } else {\n throw new TypeError(`Invalid item type [${name}, ${typeof value}]`)\n }\n}\n\nexport const metaBuilder = (html: string, meta: Meta, handler?: string) => {\n const $ = load(html)\n // NOTE: This assumes unique meta properties (no duplicates)\n // which is generally the case, but not always (you can have\n // multiple og:video:tag tags, for example)\n const metaProperties = getMetaAsDict(meta)\n for (const [key, value] of Object.entries(metaProperties)) {\n addMetaToHead($, key, value)\n }\n if (isString(meta.description)) {\n addMetaToHead($, 'description', meta.description)\n }\n if (isString(meta.title)) {\n $('title').text(meta.title)\n }\n if (isString(handler)) {\n addMetaToHead($, 'meta-handler', handler)\n }\n return $.html()\n}\n"],"mappings":"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","names":["isString","isString","load","load","isString"]}
@@ -1 +1 @@
1
- {"version":3,"file":"mergeDocumentHead.d.ts","sourceRoot":"","sources":["../../../src/html/mergeDocumentHead.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,iBAAiB,GAAI,aAAa,MAAM,EAAE,QAAQ,MAAM,WAwCpE,CAAA"}
1
+ {"version":3,"file":"mergeDocumentHead.d.ts","sourceRoot":"","sources":["../../../src/html/mergeDocumentHead.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,iBAAiB,GAAI,aAAa,MAAM,EAAE,QAAQ,MAAM,WAwCpE,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"getMetaAsDict.d.ts","sourceRoot":"","sources":["../../../src/lib/getMetaAsDict.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,eAAe,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,CAAA;AAIpD,eAAO,MAAM,aAAa,GAAI,KAAK,eAAe,EAAE,kBAAc,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAezF,CAAA"}
1
+ {"version":3,"file":"getMetaAsDict.d.ts","sourceRoot":"","sources":["../../../src/lib/getMetaAsDict.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,eAAe,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,CAAA;AAIpD,eAAO,MAAM,aAAa,GAAI,KAAK,eAAe,EAAE,YAAY,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAe7F,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../../src/meta/builder.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAA;AA4B9C,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,EAAE,MAAM,IAAI,EAAE,UAAU,MAAM,WAmBrE,CAAA"}
1
+ {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../../src/meta/builder.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAA;AA4B9C,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,EAAE,MAAM,IAAI,EAAE,UAAU,MAAM,WAmBrE,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xylabs/sdk-meta",
3
- "version": "4.9.3",
3
+ "version": "4.9.5",
4
4
  "description": "Base functionality used throughout XYO TypeScript/JavaScript libraries",
5
5
  "keywords": [
6
6
  "meta",
@@ -31,10 +31,11 @@
31
31
  "module": "dist/neutral/index.mjs",
32
32
  "types": "dist/types/index.d.ts",
33
33
  "dependencies": {
34
+ "@xylabs/typeof": "^4.9.5",
34
35
  "cheerio": "^1.0.0"
35
36
  },
36
37
  "devDependencies": {
37
- "@types/node": "^22.15.12",
38
+ "@types/node": "^22.15.17",
38
39
  "@xylabs/ts-scripts-yarn3": "^6.5.5",
39
40
  "@xylabs/tsconfig": "^6.5.5",
40
41
  "typescript": "^5.8.3",
@@ -1,3 +1,4 @@
1
+ import { isString } from '@xylabs/typeof'
1
2
  import { load } from 'cheerio'
2
3
 
3
4
  const opts = {}
@@ -16,7 +17,7 @@ export const mergeDocumentHead = (destination: string, source: string) => {
16
17
  // Special case for meta tags: We want to match them by the name attribute
17
18
  if (el[0].tagName === 'meta') {
18
19
  const property = el.attr('property')
19
- if (property) {
20
+ if (isString(property)) {
20
21
  const match = $destination(`head meta[property="${property}"]`)
21
22
 
22
23
  // If it exists, replace it, otherwise append it
@@ -1,9 +1,10 @@
1
+ import { isString } from '@xylabs/typeof'
1
2
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2
3
  export type StringIndexable = { [key: string]: any }
3
4
 
4
5
  const propertyDelimiter = ':'
5
6
 
6
- export const getMetaAsDict = (obj: StringIndexable, parentKey = ''): Record<string, string> => {
7
+ export const getMetaAsDict = (obj: StringIndexable, parentKey?: string): Record<string, string> => {
7
8
  let flatRecord: StringIndexable = {}
8
9
  for (const key in obj) {
9
10
  if (typeof obj[key] === 'object' && obj[key] !== null) {
@@ -12,7 +13,7 @@ export const getMetaAsDict = (obj: StringIndexable, parentKey = ''): Record<stri
12
13
  flatRecord = { ...flatRecord, ...childRecord }
13
14
  } else {
14
15
  // Concatenate the key with its parent key.
15
- const newKey = parentKey ? `${parentKey}${key}` : key
16
+ const newKey = isString(parentKey) ? `${parentKey}${key}` : key
16
17
  const trimmed = newKey.endsWith(propertyDelimiter) ? newKey.slice(0, -1) : newKey
17
18
  flatRecord[trimmed] = `${obj[key]}`
18
19
  }
@@ -1,3 +1,4 @@
1
+ import { isString } from '@xylabs/typeof'
1
2
  import type { CheerioAPI } from 'cheerio'
2
3
  import { load } from 'cheerio'
3
4
 
@@ -37,15 +38,15 @@ export const metaBuilder = (html: string, meta: Meta, handler?: string) => {
37
38
  // multiple og:video:tag tags, for example)
38
39
  const metaProperties = getMetaAsDict(meta)
39
40
  for (const [key, value] of Object.entries(metaProperties)) {
40
- if (value) addMetaToHead($, key, value)
41
+ addMetaToHead($, key, value)
41
42
  }
42
- if (meta.description) {
43
+ if (isString(meta.description)) {
43
44
  addMetaToHead($, 'description', meta.description)
44
45
  }
45
- if (meta.title) {
46
+ if (isString(meta.title)) {
46
47
  $('title').text(meta.title)
47
48
  }
48
- if (handler) {
49
+ if (isString(handler)) {
49
50
  addMetaToHead($, 'meta-handler', handler)
50
51
  }
51
52
  return $.html()