Initial commit

This commit is contained in:
robert committed 2025-05-30 18:13:30 +08:00
commit e49726988c
5445 files changed
+1089914

No files matched your search

+505
View File
@@ -0,0 +1,505 @@
'use strict';
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
const convertToJSON = ast => {
return buildJSONFromNode(ast.value.children[0])
};
const buildJSONFromNode = node => {
if (!node) return null
const json = {};
switch (node.type) {
case "ELEMENT": {
let element = {};
const attribs = buildAttributes(node.value.attributes);
const children = buildJSONFromNode(node.value.children);
if (attribs) {
element = Object.assign(element, attribs);
}
if (children) {
const jsonChildren = buildChildren(node.value.children);
element = Object.assign(element, jsonChildren);
}
json[node.value.type] = element;
break
}
case "ATTRIBUTE": {
const attribNameAndValue = node.value;
json[attribNameAndValue.name] = attribNameAndValue.value;
break
}
case "CONTENT": {
return {content: node.value}
}
}
return json
};
const buildChildren = children => {
if (!children || !Array.isArray(children) || children.length === 0) return null
if (isContentChildren(children)) {
return {
content: children[0].value
}
}
return {
children: children.map(buildJSONFromNode)
}
};
const isContentChildren = children => children && Array.isArray(children) && children.length === 1 && children[0].type === "CONTENT";
const buildAttributes = arrayNodes => {
if (arrayNodes && Array.isArray(arrayNodes)) {
const jsonArray = arrayNodes.map(buildJSONFromNode);
return jsonArray.reduce((agg, j) => Object.assign(agg, j), {})
}
return null
};
var astToJson = {
convert: convertToJSON
};
const Token$2 = (type, value) => ({
type,
value
});
var model = {
Token: Token$2
};
const { Token: Token$1 } = model;
const EOF_TOKEN = Token$1("EOF");
const isCharBlank = (char) =>
char === ' ' || char === '\n' || char === '\r' || char === '\t';
const skipXMLDocumentHeader = (xmlAsString, pos) => {
if (xmlAsString.startsWith('<?xml', pos)) {
const len = xmlAsString.length;
while (pos < len) {
if (xmlAsString[pos] !== '?') {
pos++;
} else if (xmlAsString[pos + 1] === '>') {
return pos + 2 // skip "?>""
} else {
pos++;
}
}
}
return pos
};
const replaceQuotes = (str) => str.replace(/'/g, "'");
const getInitialPosForLexer = (xmlAsString) => {
let pos = 0;
while (pos < xmlAsString.length && isCharBlank(xmlAsString[pos])) pos++;
return skipXMLDocumentHeader(xmlAsString, pos)
};
function createLexer$1(xmlAsString) {
let currentToken = null;
let pos = getInitialPosForLexer(xmlAsString);
let scopingElement = [];
const peek = () => xmlAsString[pos];
const hasNext = () => currentToken !== EOF_TOKEN && pos < xmlAsString.length;
const isBlankSpace = () => isCharBlank(xmlAsString[pos]);
const skipQuotes = () => {
if (hasNext() && isQuote(peek())) pos++;
};
const isQuote = (char) => '"' === char || "'" === char;
const skipSpaces = () => {
while (hasNext() && isBlankSpace()) pos++;
};
const readAlphaNumericCharsOrBrackets = (areSpecialCharsSupported) => {
if (hasNext()) {
if (xmlAsString[pos] === '<') {
let buffer = '<';
pos++;
if (hasNext() && xmlAsString[pos] === '/') {
pos++;
buffer = '</';
} else if (
hasNext() &&
xmlAsString[pos] === '!' &&
xmlAsString[pos + 1] === '-' &&
xmlAsString[pos + 2] === '-'
) {
// its a comment
pos++;
pos++;
pos++;
buffer = '<!--';
}
return buffer
} else if (peek() === '/') {
let buffer = '/';
pos++;
if (hasNext() && peek() === '>') {
pos++;
buffer = '/>';
}
return buffer
} else if (xmlAsString[pos] === '=' || xmlAsString[pos] === '>') {
const buffer = xmlAsString[pos];
pos++;
return buffer
}
}
return readAlphaNumericChars(!!areSpecialCharsSupported)
};
const readAlphaNumericChars = (areSpecialCharsSupported) => {
const ELEMENT_TYPE_MATCHER = /[a-zA-Z0-9_:-]/;
const NAMES_VALS_CONTENT_MATCHER = /[^>=<]/u;
const matcher = areSpecialCharsSupported
? NAMES_VALS_CONTENT_MATCHER
: ELEMENT_TYPE_MATCHER;
let start = pos;
while (hasNext() && xmlAsString[pos].match(matcher)) pos++;
return replaceQuotes(xmlAsString.substring(start, pos))
};
const isElementBegin = () =>
currentToken && currentToken.type === "OPEN_BRACKET";
const isAssignToAttribute = () =>
currentToken && currentToken.type === "ASSIGN";
const next = () => {
const prevPos = pos;
skipSpaces();
const numOfSpacesSkipped = pos - prevPos;
if (!hasNext()) {
currentToken = EOF_TOKEN;
} else if (isElementBegin()) {
// starting new element
skipSpaces();
const buffer = readAlphaNumericCharsOrBrackets(false);
currentToken = Token$1("ELEMENT_TYPE", buffer);
scopingElement.push(buffer);
} else if (isAssignToAttribute()) {
// assign value to attribute
skipQuotes();
const openingQuote = xmlAsString[pos - 1];
let start = pos;
while (hasNext() && peek() !== openingQuote) pos++;
const buffer = replaceQuotes(xmlAsString.substring(start, pos));
pos++;
currentToken = Token$1("ATTRIB_VALUE", buffer);
} else {
skipSpaces();
let buffer = readAlphaNumericCharsOrBrackets(true);
switch (buffer) {
case '=': {
if (currentToken.type === "ATTRIB_NAME") {
currentToken = Token$1("ASSIGN");
} else {
currentToken = Token$1("CONTENT", buffer);
}
break
}
case '</': {
const start = pos;
while (xmlAsString[pos] !== '>') pos++;
currentToken = Token$1(
"CLOSE_ELEMENT",
xmlAsString.substring(start, pos)
);
pos++; // skip the ">"
scopingElement.pop();
break
}
case '/>': {
const scopingElementName = scopingElement.pop();
currentToken = Token$1(
"CLOSE_ELEMENT",
scopingElementName
);
break
}
case '<!--': {
// skipComment contents
const closingBuff = ['!', '-', '-'];
while (
hasNext() &&
(closingBuff[2] !== '>' ||
closingBuff[1] !== '-' ||
closingBuff[0] !== '-')
) {
closingBuff.shift();
closingBuff.push(xmlAsString[pos]);
pos++;
}
return next()
}
case '>': {
currentToken = Token$1("CLOSE_BRACKET");
break
}
case '<': {
currentToken = Token$1("OPEN_BRACKET");
break
}
default: {
// here we fall if we have alphanumeric string, which can be related to attributes, content or nothing
if (buffer && buffer.length > 0) {
if (currentToken.type === "CLOSE_BRACKET") {
let suffix = '';
if (peek() !== '<') {
suffix = readAlphaNumericChars(true);
}
currentToken = Token$1(
"CONTENT",
buffer + suffix
);
} else if (
currentToken.type !== "ATTRIB_NAME" &&
currentToken.type !== "CONTENT"
) {
if (
currentToken.type === "CLOSE_ELEMENT"
) {
// we're assuming this is content, part of unstructured data
buffer = ' '.repeat(numOfSpacesSkipped) + buffer;
currentToken = Token$1("CONTENT", buffer);
} else {
// it should be an attribute name token
currentToken = Token$1(
"ATTRIB_NAME",
buffer
);
}
} else {
const contentBuffer =
' '.repeat(numOfSpacesSkipped) + buffer; // spaces included as content
currentToken = Token$1(
"CONTENT",
contentBuffer
);
}
break
} else {
const errMsg =
'Unknown Syntax : "' + xmlAsString[pos] + '"';
throw new Error(errMsg)
}
}
}
}
return currentToken
};
return {
peek,
next,
hasNext,
// prettier-ignore
...({})
}
}
var lexer = {
createLexer: createLexer$1
};
const { createLexer } = lexer;
const { Token } = model;
// AST Node types
const [ROOT, ELEMENT, ATTRIBUTE, CONTENT] = [
'ROOT',
'ELEMENT',
'ATTRIBUTE',
'CONTENT'
];
const Node = (type, value) => ({
type,
value
});
const ContentNode = (value) => Node(CONTENT, value);
const ElementNode = (type, attributes, children) => {
return Node(ELEMENT, {
type,
attributes,
children
})
};
const AttribNode = (name, value) => {
return Node(ATTRIBUTE, {
name,
value
})
};
const parseXML = (lexer) => {
/*
How does the grammar look?
| expr: StructuredXML | UnstructuredXML | Content
| StructuredXML: (openBracket + ElementName) + (AttributeList)* + closeBracket + (expr)* + closeElement
| UnstructuredXML: Content* + expr* + Content*
| Content: String
| openBracket: <
| closeBracket: >
| closeElement: </ + ElementName + closeBracket
| ElementName: String
| AttributeList: AttributeName + "=" + AttributeValue + AttributeList*
| AttributeName: String
| AttributeValue: String
*/
const rootNode = Node(ROOT, {
children: parseExpr(lexer, Token(ROOT, 'ROOT'))
});
return rootNode
};
const parseExpr = (lexer, scopingElement) => {
const children = [];
while (lexer.hasNext()) {
const lexem = lexer.next();
switch (lexem.type) {
case "OPEN_BRACKET": {
const elementLexem = lexer.next();
const [elementAttributes, currentToken] =
parseElementAttributes(lexer);
let elementChildren = [];
if (currentToken.type !== "CLOSE_ELEMENT") {
elementChildren = parseExpr(lexer, elementLexem);
}
if (
elementChildren &&
elementChildren.length > 0 &&
elementChildren[0].type === "CONTENT"
) {
elementChildren = reduceChildrenElements(elementChildren);
}
children.push(
ElementNode(
elementLexem.value,
elementAttributes,
elementChildren
)
);
break
}
case "CLOSE_ELEMENT": {
if (lexem.value === scopingElement.value) return children
break
}
case "CONTENT": {
children.push(ContentNode(lexem.value));
break
}
case "EOF": {
return children
}
default: {
throw new Error(
`Unknown Lexem type: ${lexem.type} "${lexem.value}, scoping element: ${scopingElement.value}"`
)
}
}
}
return children
};
const parseElementAttributes = (lexer) => {
const attribs = [];
let currentToken = lexer.peek();
if (
!lexer.hasNext() ||
(currentToken && currentToken.type === "CLOSE_BRACKET") ||
(currentToken && currentToken.type === "CLOSE_ELEMENT")
) {
return [attribs, currentToken]
}
currentToken = lexer.next();
while (
lexer.hasNext() &&
currentToken &&
currentToken.type !== "CLOSE_BRACKET" &&
currentToken.type !== "CLOSE_ELEMENT"
) {
const attribName = currentToken;
lexer.next(); //assignment token
const attribValue = lexer.next();
const attributeNode = AttribNode(attribName.value, attribValue.value);
attribs.push(attributeNode);
currentToken = lexer.next();
}
return [attribs, currentToken]
};
function reduceChildrenElements(elementChildren) {
let reduced = [],
buffer = '';
elementChildren.forEach((child) => {
if (child.type === "CONTENT") {
buffer += child.value;
} else {
if (buffer.length) {
reduced.push(ContentNode(buffer));
buffer = '';
}
reduced.push(child);
}
});
if (buffer.length) reduced.push(ContentNode(buffer));
return reduced
}
function transpile$1(xmlAsString, astConverter) {
const lexer = createLexer(xmlAsString);
const ast = parseXML(lexer);
if (astConverter) {
return astConverter.convert(ast)
}
return ast
}
var transpiler = {
AttribNode,
ContentNode,
ElementNode,
Node,
transpile: transpile$1
};
const jsonConverter = astToJson;
const { transpile } = transpiler;
function convertXML(xmlAsString, customConverter) {
return transpile(xmlAsString, customConverter || jsonConverter)
}
function createAST(xmlAsString) {
return transpile(xmlAsString)
}
var xmlToJson = {
convertXML,
createAST
};
var xmlToJson$1 = /*@__PURE__*/getDefaultExportFromCjs(xmlToJson);
module.exports = xmlToJson$1;
+1
View File
@@ -0,0 +1 @@
"use strict";function e(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}const t=e=>{if(!e)return null;const n={};switch(e.type){case"ELEMENT":{let a={};const u=s(e.value.attributes),c=t(e.value.children);if(u&&(a=Object.assign(a,u)),c){const t=r(e.value.children);a=Object.assign(a,t)}n[e.value.type]=a;break}case"ATTRIBUTE":{const t=e.value;n[t.name]=t.value;break}case"CONTENT":return{content:e.value}}return n},r=e=>e&&Array.isArray(e)&&0!==e.length?n(e)?{content:e[0].value}:{children:e.map(t)}:null,n=e=>e&&Array.isArray(e)&&1===e.length&&"CONTENT"===e[0].type,s=e=>{if(e&&Array.isArray(e)){return e.map(t).reduce(((e,t)=>Object.assign(e,t)),{})}return null};var a={convert:e=>t(e.value.children[0])};var u={Token:(e,t)=>({type:e,value:t})};const{Token:c}=u,l=c("EOF"),E=e=>" "===e||"\n"===e||"\r"===e||"\t"===e,o=e=>e.replace(/'/g,"'");var T={createLexer:function(e){let t=null,r=(e=>{let t=0;for(;t<e.length&&E(e[t]);)t++;return((e,t)=>{if(e.startsWith("<?xml",t)){const r=e.length;for(;t<r;)if("?"!==e[t])t++;else{if(">"===e[t+1])return t+2;t++}}return t})(e,t)})(e),n=[];const s=()=>e[r],a=()=>t!==l&&r<e.length,u=e=>'"'===e||"'"===e,T=()=>{for(;a()&&E(e[r]);)r++},i=t=>{if(a()){if("<"===e[r]){let t="<";return r++,a()&&"/"===e[r]?(r++,t="</"):a()&&"!"===e[r]&&"-"===e[r+1]&&"-"===e[r+2]&&(r++,r++,r++,t="\x3c!--"),t}if("/"===s()){let e="/";return r++,a()&&">"===s()&&(r++,e="/>"),e}if("="===e[r]||">"===e[r]){const t=e[r];return r++,t}}return p(!!t)},p=t=>{const n=t?/[^>=<]/u:/[a-zA-Z0-9_:-]/;let s=r;for(;a()&&e[r].match(n);)r++;return o(e.substring(s,r))},N=()=>{const E=r;T();const f=r-E;if(a())if(t&&"OPEN_BRACKET"===t.type){T();const e=i(!1);t=c("ELEMENT_TYPE",e),n.push(e)}else if(t&&"ASSIGN"===t.type){a()&&u(s())&&r++;const n=e[r-1];let l=r;for(;a()&&s()!==n;)r++;const E=o(e.substring(l,r));r++,t=c("ATTRIB_VALUE",E)}else{T();let u=i(!0);switch(u){case"=":t="ATTRIB_NAME"===t.type?c("ASSIGN"):c("CONTENT",u);break;case"</":{const s=r;for(;">"!==e[r];)r++;t=c("CLOSE_ELEMENT",e.substring(s,r)),r++,n.pop();break}case"/>":{const e=n.pop();t=c("CLOSE_ELEMENT",e);break}case"\x3c!--":{const t=["!","-","-"];for(;a()&&(">"!==t[2]||"-"!==t[1]||"-"!==t[0]);)t.shift(),t.push(e[r]),r++;return N()}case">":t=c("CLOSE_BRACKET");break;case"<":t=c("OPEN_BRACKET");break;default:if(u&&u.length>0){if("CLOSE_BRACKET"===t.type){let e="";"<"!==s()&&(e=p(!0)),t=c("CONTENT",u+e)}else if("ATTRIB_NAME"!==t.type&&"CONTENT"!==t.type)"CLOSE_ELEMENT"===t.type?(u=" ".repeat(f)+u,t=c("CONTENT",u)):t=c("ATTRIB_NAME",u);else{const e=" ".repeat(f)+u;t=c("CONTENT",e)}break}{const t='Unknown Syntax : "'+e[r]+'"';throw new Error(t)}}}else t=l;return t};return{peek:s,next:N,hasNext:a}}};const{createLexer:i}=T,{Token:p}=u,[N,f,h,O]=["ROOT","ELEMENT","ATTRIBUTE","CONTENT"],y=(e,t)=>({type:e,value:t}),C=e=>y(O,e),v=(e,t,r)=>y(f,{type:e,attributes:t,children:r}),A=(e,t)=>y(h,{name:e,value:t}),L=(e,t)=>{const r=[];for(;e.hasNext();){const n=e.next();switch(n.type){case"OPEN_BRACKET":{const t=e.next(),[n,s]=_(e);let a=[];"CLOSE_ELEMENT"!==s.type&&(a=L(e,t)),a&&a.length>0&&"CONTENT"===a[0].type&&(a=b(a)),r.push(v(t.value,n,a));break}case"CLOSE_ELEMENT":if(n.value===t.value)return r;break;case"CONTENT":r.push(C(n.value));break;case"EOF":return r;default:throw new Error(`Unknown Lexem type: ${n.type} "${n.value}, scoping element: ${t.value}"`)}}return r},_=e=>{const t=[];let r=e.peek();if(!e.hasNext()||r&&"CLOSE_BRACKET"===r.type||r&&"CLOSE_ELEMENT"===r.type)return[t,r];for(r=e.next();e.hasNext()&&r&&"CLOSE_BRACKET"!==r.type&&"CLOSE_ELEMENT"!==r.type;){const n=r;e.next();const s=e.next(),a=A(n.value,s.value);t.push(a),r=e.next()}return[t,r]};function b(e){let t=[],r="";return e.forEach((e=>{"CONTENT"===e.type?r+=e.value:(r.length&&(t.push(C(r)),r=""),t.push(e))})),r.length&&t.push(C(r)),t}var x={AttribNode:A,ContentNode:C,ElementNode:v,Node:y,transpile:function(e,t){const r=(e=>y(N,{children:L(e,p(N,"ROOT"))}))(i(e));return t?t.convert(r):r}};const k=a,{transpile:d}=x;var g=e({convertXML:function(e,t){return d(e,t||k)},createAST:function(e){return d(e)}});module.exports=g;