yini-parser
Version:
Node.js parser for YINI — a clean, structured INI alternative with types, simple section nesting, comments, and strict mode.
104 lines (103 loc) • 4.62 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const print_1 = require("../utils/print");
const yiniHelpers_1 = require("../yiniHelpers");
const extractSignificantYiniLine_1 = require("./extractSignificantYiniLine");
/**
* Check and identify the section header parts via tokenizing the parts and return them as strings.
* @param rawHeaderLine Raw line with the section header where the header
* marker will be identified. E.g. does the header start with '^^^' or '^3'
* and then some identifier.
*
* Below, copied from YINI Specification v1.0.0 Beta 7.
* Form 1: Identifier of Simple Form:
* - Keys must be non-empty.
* - Keys are case-sensitive (`Title` and `title` are different).
* - Can only contain letters (a-z or A-Z), digits (0-9) and underscores `_`.
* - Must begin with a letter or an underscore `_`.
* - Note: Cannot contain hyphens (`-`) or periods (`.`).
*
* Form 2: Backticked Identifier:
* - A phrase is a name wrapped in backticks ``` ` ```.
* - Backticked identifiers must be on a single line and must not contain tabs or new lines unless using escaping codes, except for ordinary spaces.
* - Special control characters (U+0000–U+001F) must be escaped.
*
* @note Returns the parts as strings; each part needs to be analyzed separately against the contraints in the specifications.
* @returns An object with the identified header parts: marker characters, parsed name, and parsed level string.
*/
const extractHeaderParts = (rawLine, errorHandler = null, ctx = null) => {
(0, print_1.debugPrint)('-> Entered extractHeaderParts(..)');
rawLine = rawLine.trim();
const str = (0, extractSignificantYiniLine_1.extractYiniLine)(rawLine);
(0, print_1.debugPrint)('rawLine: >>>' + rawLine + '<<<');
(0, print_1.debugPrint)(' str: >>>' + str + '<<<');
// Edge case: empty line.
if (!str) {
errorHandler.pushOrBail(ctx, 'Internal-Error', 'Received blank argument in extractHeaderParts(..)', 'Sorry, an unintended internal error happened.');
}
let pos = 0;
const len = str.length;
let markerCharsPart = '';
let numberPart = '';
let sectionNamePart = '';
let isBacktickedName = false;
// 1. Skip leading whitespace.
while (pos < len && (str[pos] === ' ' || str[pos] === '\t'))
pos++;
// 2. Collect marker(s): ^, <, §, €.
while (pos < len && (0, yiniHelpers_1.isMarkerCharacter)(str[pos])) {
markerCharsPart += str[pos];
pos++;
}
// 3. Numeric part (for numeric shorthand; only if single marker found).
if (markerCharsPart.length === 1 &&
pos < len &&
str[pos] >= '1' &&
str[pos] <= '9') {
// Start collecting number part.
while (pos < len && str[pos] >= '0' && str[pos] <= '9') {
numberPart += str[pos];
pos++;
}
markerCharsPart += numberPart; // E.g., "^7".
}
// 4. Skip whitespace between marker and section name.
while (pos < len && (str[pos] === ' ' || str[pos] === '\t'))
pos++;
// 5. Collect section name (identifier or backticked).
if (pos < len && str[pos] === '`') {
// Backticked identifier.
let start = pos;
pos++; // Skip initial backtick.
while (pos < len && str[pos] !== '`')
pos++;
pos++; // Include the closing backtick (if found).
sectionNamePart = str.slice(start, pos).trim();
isBacktickedName = true;
}
else {
// Non-backticked: take the rest of the line, trim off any trailing comments, etc.
sectionNamePart = str.slice(pos).trim();
// Optionally, strip trailing comments or newlines here if needed.
}
if (isBacktickedName) {
(0, print_1.debugPrint)('Backticed sectionNamePart: ' + sectionNamePart);
// sectionNamePart = trimBackticks(sectionNamePart)
}
(0, print_1.debugPrint)();
(0, print_1.debugPrint)('------');
(0, print_1.debugPrint)('<- About to leave extractHeaderParts(..)');
(0, print_1.debugPrint)();
(0, print_1.debugPrint)(' markerCharsPart: >>>' + markerCharsPart + '<<<');
(0, print_1.debugPrint)(' sectionNamePart: >>>' + sectionNamePart + '<<<');
(0, print_1.debugPrint)(' numberPart: >>>' + numberPart + '<<<');
(0, print_1.debugPrint)(' isBacktickedName: ' + isBacktickedName);
(0, print_1.debugPrint)();
return {
strMarkerChars: markerCharsPart,
strSectionName: sectionNamePart,
strNumberPart: numberPart,
isBacktickedName,
};
};
exports.default = extractHeaderParts;