UNPKG

@markuplint/ml-spec

Version:

Types and schema that specs of the Markup languages for markuplint

81 lines (80 loc) 2.42 kB
import { resolveNamespace } from '../utils/resolve-namespace.js'; const cacheMap = new Map(); const schemaCache = new WeakSet(); export function getAttrSpecs(localName, namespace, schema) { if (!schemaCache.has(schema)) { cacheMap.clear(); } const { localNameWithNS } = resolveNamespace(localName, namespace ?? undefined); const cache = cacheMap.get(localNameWithNS); if (cache !== undefined) { return cache; } schemaCache.add(schema); const elSpec = schema.specs.find(spec => spec.name === localNameWithNS); if (!elSpec) { cacheMap.set(localNameWithNS, null); return null; } const globalAttrs = schema.def['#globalAttrs']; let attrs = {}; for (const catName in elSpec.globalAttrs) { // @ts-ignore const catAttrs = elSpec.globalAttrs[catName]; if (catAttrs === false) { continue; } if (typeof catAttrs === 'boolean') { const global = globalAttrs[catName]; attrs = { ...attrs, ...global, }; continue; } if (Array.isArray(catAttrs)) { const global = globalAttrs[catName]; if (!global) { continue; } for (const selectedName of catAttrs) { const selected = global[selectedName]; attrs[selectedName] = { ...attrs[selectedName], ...selected, }; } continue; } } for (const attrName in elSpec.attributes) { const attr = elSpec.attributes[attrName]; if (!attr) { continue; } const current = attrs[attrName]; attrs[attrName] = { description: '', ...current, ...attr, }; } const attrList = Object.keys(attrs).map(name => { const attr = attrs[name]; return { name, type: 'Any', ...attr }; }); attrList.sort(nameCompare); cacheMap.set(localNameWithNS, attrList); return attrList; } export function nameCompare(a, b) { const nameA = typeof a === 'string' ? a : a.name.toUpperCase(); const nameB = typeof b === 'string' ? b : b.name.toUpperCase(); if (nameA < nameB) { return -1; } if (nameA > nameB) { return 1; } return 0; }