vsn 1.0.2 → 1.0.3

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/plugins/microdata.ts"],"sourcesContent":["import type { Engine } from \"../runtime/engine\";\n\ntype MicrodataOptions = {\n key?: string;\n flatten?: boolean;\n};\n\ntype ExtractResult = Record<string, any>;\n\nconst META_TYPE = \"@type\";\nconst META_ID = \"@id\";\n\nexport function registerMicrodata(engine: Engine): void {\n engine.registerBehaviorModifier(\"microdata\", {\n onBind: ({ element, scope, args }) => {\n const options = normalizeOptions(args);\n const root = resolveItemscopeRoot(element);\n if (!root) {\n return;\n }\n const data = extractMicrodata(root, options);\n applyMicrodataToScope(scope, data, options);\n }\n });\n\n engine.registerGlobal(\"microdata\", (target?: any, maybeOptions?: any) => {\n const options = normalizeOptions(\n isPlainObject(target) ? target : maybeOptions\n );\n const root = resolveTargetElement(engine, target);\n if (!root) {\n return undefined;\n }\n const data = extractMicrodata(resolveItemscopeRoot(root) ?? root, options);\n if (typeof target === \"string\" && !isPlainObject(maybeOptions)) {\n return data[target];\n }\n return data;\n });\n}\n\nexport default registerMicrodata;\n\nconst globals = (globalThis as Record<string, any>);\nconst plugins = globals.VSNPlugins ?? {};\nplugins.microdata = (instance: Engine) => registerMicrodata(instance);\nglobals.VSNPlugins = plugins;\n\nconst autoEngine = globals.VSNEngine;\nif (autoEngine && typeof autoEngine.registerBehaviorModifier === \"function\") {\n registerMicrodata(autoEngine as Engine);\n}\n\nfunction normalizeOptions(value: any): MicrodataOptions {\n if (!value) {\n return {};\n }\n if (typeof value === \"string\") {\n return { key: value };\n }\n if (isPlainObject(value)) {\n const options: MicrodataOptions = {};\n if (typeof value.key === \"string\") {\n options.key = value.key;\n }\n if (typeof value.flatten === \"boolean\") {\n options.flatten = value.flatten;\n }\n return options;\n }\n return {};\n}\n\nfunction isPlainObject(value: any): value is Record<string, any> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction resolveTargetElement(engine: Engine, target?: any): Element | undefined {\n if (!target) {\n return engine.getCurrentElement();\n }\n if (target instanceof Element) {\n return target;\n }\n if (Array.isArray(target) && target[0] instanceof Element) {\n return target[0];\n }\n return engine.getCurrentElement();\n}\n\nfunction resolveItemscopeRoot(element: Element): Element | undefined {\n if (element.hasAttribute(\"itemscope\")) {\n return element;\n }\n return element.querySelector(\"[itemscope]\") ?? undefined;\n}\n\nfunction extractMicrodata(root: Element, options: MicrodataOptions): ExtractResult {\n const result: ExtractResult = {};\n const itemType = root.getAttribute(\"itemtype\");\n const itemId = root.getAttribute(\"itemid\");\n if (itemType) {\n result[META_TYPE] = itemType;\n }\n if (itemId) {\n result[META_ID] = itemId;\n }\n\n collectItemProps(root, result, options);\n return result;\n}\n\nfunction collectItemProps(root: Element, result: ExtractResult, options: MicrodataOptions): void {\n const children = Array.from(root.children);\n for (const child of children) {\n const hasItemprop = child.hasAttribute(\"itemprop\");\n const hasItemscope = child.hasAttribute(\"itemscope\");\n\n if (hasItemscope && !hasItemprop) {\n continue;\n }\n\n if (hasItemprop) {\n const props = (child.getAttribute(\"itemprop\") ?? \"\")\n .split(/\\s+/)\n .map((prop) => prop.trim())\n .filter(Boolean);\n const value = hasItemscope ? extractMicrodata(child, options) : readItemValue(child);\n for (const prop of props) {\n addValue(result, prop, value);\n }\n if (options.flatten && value && typeof value === \"object\" && !Array.isArray(value)) {\n for (const [key, nestedValue] of Object.entries(value)) {\n if (key.startsWith(\"@\")) {\n continue;\n }\n addValue(result, key, nestedValue);\n }\n }\n if (hasItemscope) {\n continue;\n }\n }\n\n collectItemProps(child, result, options);\n }\n}\n\nfunction readItemValue(element: Element): string {\n if (element instanceof HTMLMetaElement) {\n return element.content ?? \"\";\n }\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {\n return element.value ?? \"\";\n }\n if (element instanceof HTMLSelectElement) {\n return element.value ?? \"\";\n }\n if (element instanceof HTMLTimeElement) {\n return element.dateTime || element.getAttribute(\"datetime\") || \"\";\n }\n if (element instanceof HTMLAnchorElement || element instanceof HTMLLinkElement) {\n return element.getAttribute(\"href\") ?? \"\";\n }\n if (element instanceof HTMLImageElement) {\n return element.getAttribute(\"src\") ?? \"\";\n }\n if (element.hasAttribute(\"content\")) {\n return element.getAttribute(\"content\") ?? \"\";\n }\n return (element.textContent ?? \"\").trim();\n}\n\nfunction addValue(result: ExtractResult, key: string, value: any): void {\n if (result[key] === undefined) {\n result[key] = value;\n return;\n }\n if (Array.isArray(result[key])) {\n result[key].push(value);\n return;\n }\n result[key] = [result[key], value];\n}\n\nfunction applyMicrodataToScope(scope: any, data: ExtractResult, options: MicrodataOptions): void {\n if (options.key) {\n scope.setPath?.(options.key, data);\n return;\n }\n for (const [key, value] of Object.entries(data)) {\n if (key === META_TYPE) {\n scope.setPath?.(\"itemtype\", value);\n continue;\n }\n if (key === META_ID) {\n scope.setPath?.(\"itemid\", value);\n continue;\n }\n scope.setPath?.(key, value);\n }\n}\n"],"mappings":"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","names":["META_TYPE","registerMicrodata","engine","element","scope","args","options","normalizeOptions","root","resolveItemscopeRoot","data","extractMicrodata","applyMicrodataToScope","target","maybeOptions","isPlainObject","resolveTargetElement","microdata_default","globals","plugins","instance","autoEngine","value","result","itemType","itemId","META_TYPE","collectItemProps","children","child","hasItemprop","hasItemscope","props","prop","readItemValue","addValue","key","nestedValue"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vsn",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "SEO Friendly Javascript/Typescript Framework",
5
5
  "keywords": [
6
6
  "framework",
@@ -36,6 +36,7 @@
36
36
  "build": "tsup",
37
37
  "dev": "tsup --watch",
38
38
  "test": "vitest run",
39
+ "coverage": "vitest run --coverage",
39
40
  "test:watch": "vitest",
40
41
  "typecheck": "tsc -p tsconfig.json --noEmit",
41
42
  "clean": "rm -rf dist",