This repository has been archived on 2025-03-10. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
layc/src/Utils/Placekeeper.js~
2024-03-20 03:43:27 +00:00

136 lines
3.8 KiB
JavaScript

import Logger from './Logger';
export default class Placekeeper {
static init(content) {
const sections = Array();
const variables = new Map();
const currentSection = new Map();
for (let idx = 0; idx < content.length; idx++) {
const char = content[idx];
if (char == '{') {
if (content[idx + 1] == '{') {
if (currentSection.has('start')) currentSection.clear(); // everything before this was not a section then
// begins a new section meant to be for a variable but still can be an operational section
// @example: {{#if variableName}} {{#for variableName}} {{#while variableName}}
currentSection.set('start', idx);
}
} else if (currentSection.has('start')) {
if (char == '}') {
if (content[idx + 1] == '}') {
// ends a section
currentSection.set('end', idx + 2);
currentSection.set(
'content',
content
.substring(
currentSection.get('start'),
currentSection.get('end')
)
.toString()
.trim()
);
currentSection.set(
'variables',
Placekeeper.parseVariables(
currentSection.get('content')
)
);
sections.push(new Map(currentSection));
currentSection.clear();
idx++;
}
}
}
}
Logger('content to array', Placekeeper.contentToArray(content));
return {
variables,
sections,
};
}
static contentToArray(content) {
const parts = content.split(/\{\{([^}]+)\}\}|\{(#[a-zA-Z]+)\s*([^}]+)\}/);
const result = [];
let stack = [];
function processStack() {
const block = stack.pop();
result.push(new Function('data', 'with(data){return `'+ block.content.join('') + '`;}'));
}
// Process each part of the split content
for (let i = 0; i < parts.length; i++) {
if (parts[i] === '#' && ['for', 'if', 'else', 'elseif', 'while'].includes(parts[i + 1])) {
// Start of control structure
stack.push({ type: parts[i + 1], content: [] });
i += 2; // Skip the control structure identifier
} else if (parts[i] === '/#' && ['for', 'if', 'while'].includes(stack[stack.length - 1].type)) {
// End of control structure
i++;
processStack();
} else if (stack.length > 0) {
// Inside a control structure
stack[stack.length - 1].content.push(parts[i]);
} else if (parts[i] !== undefined && parts[i] !== '#end') {
// Directly executable expression or static string
result.push(parts[i].startsWith('\n') ? '\n' + parts[i].trimStart() : parts[i].trimEnd());
}
}
return result;
}
static variableRegex = new RegExp(/[\w\d]/, 'i');
static parseVariables(content) {
// iterates over the content character by character to extract variables and returns a list of them
const variables = new Map();
let currentVar;
for (let idx = 0; idx < content.length; idx++) {
const char = content[idx];
if (Placekeeper.variableRegex.test(char)) {
if (!(currentVar instanceof Map))
currentVar = new Map([
['name', ''],
['start', idx],
['end', -1],
]);
currentVar.set('name', currentVar.get('name') + char);
} else if (currentVar instanceof Map) {
currentVar.set('end', idx);
if (currentVar.get('name').length > 0) {
variables.set(currentVar.get('name'), currentVar);
}
currentVar = null;
}
}
}
static parse(content, sections) {
// replace all sections with an empty string
if (!Array.isArray(sections)) {
if (!sections instanceof Map) return content;
sections = [...sections.values()];
}
let parts = [];
let offset = 0;
for (const section of sections) {
if (!(section instanceof Map)) {
if (!Array.isArray(section)) continue;
if (section.length < 3) continue;
}
parts.push(content.substring(offset, section.get('start')));
offset = section.get('end');
}
parts.push(content.substring(offset));
return parts.join('');
}
}