diff --git a/Core.js b/Core.js
index 9ec77cc..7f06c75 100644
--- a/Core.js
+++ b/Core.js
@@ -363,17 +363,11 @@ class SimonUp {
return html.replace('', tocListHtml);
}
+
/**
* SimonUp Core Compiler (Core.js) - Version 1.2
* Eine moderne, fluss- und blockorientierte Auszeichnungssprache.
*/
-
-// Globale Hilfsfunktionen außerhalb der Klasse, um Parsing-Verschachtelungen zu verhindern
-function _suSlugify(text) {
- if (!text) return '';
- return text.toLowerCase().replace(/[^a-z0-9\s-]/g, '').replace(/\s+/g, '-');
-}
-
class SimonUp {
constructor() {
this.plugins = [];
@@ -381,18 +375,25 @@ class SimonUp {
this.counters = [0, 0, 0, 0, 0, 0];
}
+ /**
+ * Registriert eine Erweiterung (Plugin)
+ */
use(plugin) {
this.plugins.push(plugin);
return this;
}
+ /**
+ * Hauptfunktion: Wandelt SimonUp-Text (.up) in valides HTML um
+ */
parse(text) {
this.headings = [];
this.counters = [0, 0, 0, 0, 0, 0];
- var html = text;
+
+ let html = text;
if (this.plugins && this.plugins.length > 0) {
- for (var i = 0; i < this.plugins.length; i++) {
+ for (let i = 0; i < this.plugins.length; i++) {
if (this.plugins[i].before) {
html = this.plugins[i].before(html);
}
@@ -403,9 +404,9 @@ class SimonUp {
html = this._injectTOC(html);
if (this.plugins && this.plugins.length > 0) {
- for (var j = 0; j < this.plugins.length; j++) {
- if (this.plugins[j].after) {
- html = this.plugins[j].after(html);
+ for (let i = 0; i < this.plugins.length; i++) {
+ if (this.plugins[i].after) {
+ html = this.plugins[i].after(html);
}
}
}
@@ -413,21 +414,24 @@ class SimonUp {
return html;
}
+ /**
+ * INTERN: Verarbeitet strukturelle Blöcke und freie Strukturen zeilenweise
+ */
_parseBlocks(text) {
- var lines = text.replace(/\r\n/g, '\n').split('\n');
- var result = [];
- var inBlock = false;
- var blockType = null;
- var blockMeta = "";
- var blockBuffer = [];
+ const lines = text.replace(/\r\n/g, '\n').split('\n');
+ let result = [];
+ let inBlock = false;
+ let blockType = null;
+ let blockMeta = "";
+ let blockBuffer = [];
- for (var i = 0; i < lines.length; i++) {
- var line = lines[i];
+ for (let i = 0; i < lines.length; i++) {
+ let line = lines[i];
if (!inBlock && line.startsWith('&') && line.trim().length > 1) {
inBlock = true;
- var fullHeader = line.substring(1).trim();
- var spaceIndex = fullHeader.indexOf(' ');
+ const fullHeader = line.substring(1).trim();
+ const spaceIndex = fullHeader.indexOf(' ');
if (spaceIndex !== -1) {
blockType = fullHeader.substring(0, spaceIndex).toLowerCase();
@@ -440,7 +444,7 @@ class SimonUp {
continue;
}
- if (inBlock && line.trim() === '&') {
+ if (inBlock && line.trim().replace(/\u00A0/g, ' ') === '&') {
result.push(this._renderBlock(blockType, blockMeta, blockBuffer));
inBlock = false;
blockType = null;
@@ -451,17 +455,17 @@ class SimonUp {
if (inBlock) {
blockBuffer.push(line);
} else {
- var trimmed = line.trim();
+ let trimmed = line.trim();
if (trimmed === '___') {
result.push('
');
} else if (trimmed.startsWith('- ')) {
- var insideUl = this._parseInline(line.replace(/^\s*-\s+/, ''));
- result.push('' + insideUl + '');
+ let insideUl = this._parseInline(line.replace(/^\s*-\s+/, ''));
+ result.push(`${insideUl}`);
} else if (/^\d+\.\s+/.test(trimmed)) {
- var cleanLine = line.replace(/^\s*\d+\.\s+/, '');
- var insideOl = this._parseInline(cleanLine);
- result.push('' + insideOl + '');
+ let cleanLine = line.replace(/^\s*\d+\.\s+/, '');
+ let insideOl = this._parseInline(cleanLine);
+ result.push(`${insideOl}`);
} else {
result.push(this._parseInline(line));
}
@@ -471,69 +475,75 @@ class SimonUp {
return this._processParagraphsAndLists(result);
}
+ /**
+ * INTERN: Erzeugt das HTML für einen geschlossenen Block
+ */
_renderBlock(type, meta, lines) {
- var content = lines.join('\n');
- var self = this;
+ const content = lines.join('\n');
+ let self = this;
switch (type) {
case 'toc':
- var tocWrapper = '';
+ let tocWrapper = '';
if (meta || content.trim()) {
tocWrapper = '\n';
if (meta) {
- tocWrapper += '
' + meta + '
\n';
+ tocWrapper += `
${meta}
\n`;
}
if (content.trim()) {
- var intro = lines.map(function(l) { return self._parseInline(l); }).join('
');
- tocWrapper += '
' + intro + '
\n';
+ const intro = lines.map(function(l) { return self._parseInline(l); }).join('
');
+ tocWrapper += `
${intro}
\n`;
}
tocWrapper += '\n
';
}
return tocWrapper;
case 'c':
- var langClass = meta ? ' class="language-' + meta + '"' : '';
- var escapedCode = content.replace(/&/g, '&').replace(//g, '>');
- return '' + escapedCode + '
';
+ const langClass = meta ? ` class="language-${meta}"` : '';
+ const escapedCode = content.replace(/&/g, '&').replace(//g, '>');
+ return `${escapedCode}
`;
case 'q':
- var qContent = lines.map(function(l) { return self._parseInline(l); }).join('
');
- return '' + qContent + '
';
+ const qContent = lines.map(function(l) { return self._parseInline(l); }).join('
');
+ return `${qContent}
`;
case 'b':
- var bContent = lines.map(function(l) { return self._parseInline(l); }).join('
');
- return '' + bContent + '
';
+ const bContent = lines.map(function(l) { return self._parseInline(l); }).join('
');
+ return `${bContent}
`;
case 'f':
- var fSummary = meta || 'Details';
- var fContent = lines.map(function(l) { return self._parseInline(l); }).join('
');
- return '\n' + fSummary + '
\n' + fContent + '
\n ';
+ const fSummary = meta || 'Details';
+ const fContent = lines.map(function(l) { return self._parseInline(l); }).join('
');
+ return `\n${fSummary}
\n${fContent}
\n `;
case 'i':
- var iColor = meta || '#ff6347';
- var iContent = lines.map(function(l) { return self._parseInline(l); }).join('
');
- return '\n' + iContent + '\n
';
+ const iColor = meta || '#ff6347';
+ const iContent = lines.map(function(l) { return self._parseInline(l); }).join('
');
+ return `\n${iContent}\n
`;
case 't':
return this._renderTable(meta, lines);
default:
- var defContent = lines.map(function(l) { return self._parseInline(l); }).join('
');
- return '' + defContent + '
';
+ const defContent = lines.map(function(l) { return self._parseInline(l); }).join('
');
+ return `${defContent}
`;
}
}
+ /**
+ * INTERN: Hilfsfunktion zum Rendern von Multi-line-Tabellen und Galerien
+ */
_renderTable(meta, lines) {
- var tableHtml = '\n';
- var currentCells = [];
- var cellBuffer = [];
- var self = this;
+ let tableHtml = '\n';
+ let currentCells = [];
+ let cellBuffer = [];
+ let self = this;
- for (var i = 0; i < lines.length; i++) {
- var line = lines[i];
- var parts = line.split('|');
- for (var j = 0; j < parts.length; j++) {
- var part = parts[j];
+ for (let i = 0; i < lines.length; i++) {
+ let line = lines[i];
+ let parts = line.split('|');
+ for (let j = 0; j < parts.length; j++) {
+ let part = parts[j];
if (j === parts.length - 1) {
if (part.trim() !== '') {
@@ -551,11 +561,11 @@ class SimonUp {
}
if (line.endsWith('|') && currentCells.length > 0) {
- var rowContent = currentCells.map(function(c) {
- var parsedCell = self._parseInline(c.trim()).replace(/\n/g, '
');
- return '' + parsedCell + ' | ';
+ let rowContent = currentCells.map(function(c) {
+ let parsedCell = self._parseInline(c.trim()).replace(/\n/g, '
');
+ return `${parsedCell} | `;
}).join('\n');
- tableHtml += '\n' + rowContent + '\n
\n';
+ tableHtml += `\n${rowContent}\n
\n`;
currentCells = [];
}
}
@@ -563,58 +573,61 @@ class SimonUp {
return tableHtml;
}
+ /**
+ * INTERN: Verarbeitet Fluss-Formatierungen (Inline) mittels V1.2-RegEx
+ */
_parseInline(text) {
if (!text) return '';
- var html = text;
+ let html = text;
- var escapes = [];
+ const escapes = [];
html = html.replace(/\\(.)/g, function(match, char) {
escapes.push(char);
return '';
});
- html = html.replace(/\/\/(\s|$)/g, '$1');
+ html = html.replace(/\/\/(( \s|$))/g, '$1');
- var self = this;
- var processHeading = function(pattern, callback) {
- var match;
+ let self = this;
+ const processHeading = function(pattern, callback) {
+ let match;
while ((match = pattern.exec(html)) !== null) {
- var fullMatch = match[0];
- var level = parseInt(match[1]);
- var titleAndRest = match[2];
+ const fullMatch = match[0];
+ const level = parseInt(match[1]);
+ const titleAndRest = match[2];
- var title = titleAndRest;
- var rest = "";
- var closeIdx = titleAndRest.indexOf('/#');
+ let title = titleAndRest;
+ let rest = "";
+ const closeIdx = titleAndRest.indexOf('/#');
if (closeIdx !== -1) {
title = titleAndRest.substring(0, closeIdx);
rest = titleAndRest.substring(closeIdx + 2);
}
- var result = callback(level, title.trim(), rest);
+ const result = callback(level, title.trim(), rest);
html = html.substring(0, match.index) + result + html.substring(match.index + fullMatch.length);
}
};
processHeading(/^([1-6])x#\s*(.*)/g, function(level, title, rest) {
- var numStr = self._getAutoNumber(level);
- var fullTitle = numStr + ' ' + title;
- var id = _suSlugify(fullTitle);
+ const numStr = self._getAutoNumber(level);
+ const fullTitle = `${numStr} ${title}`;
+ const id = self._slugify(fullTitle);
self.headings.push({ level: level, text: fullTitle, id: id });
- return '' + fullTitle + '' + rest;
+ return `${fullTitle}${rest}`;
});
processHeading(/^([1-6])-#\s*(.*)/g, function(level, title, rest) {
- return '' + title + '' + rest;
+ return `${title}${rest}`;
});
processHeading(/^([1-6])#\s*(.*)/g, function(level, title, rest) {
- var id = _suSlugify(title);
+ const id = self._slugify(title);
self.headings.push({ level: level, text: title, id: id });
- return '' + title + '' + rest;
+ return `${title}${rest}`;
});
- var inlineRules = [
+ const inlineRules = [
{ tag: 'strong', symbol: '\\*\\*' },
{ tag: 'span style="font-weight: 500;"', symbol: '\\*' },
{ tag: 'em', symbol: '%' },
@@ -626,31 +639,31 @@ class SimonUp {
{ tag: 'code', symbol: '`' }
];
- for (var k = 0; k < inlineRules.length; k++) {
- var rule = inlineRules[k];
- var tagSimple = rule.tag.split(' ')[0];
+ for (let k = 0; k < inlineRules.length; k++) {
+ let rule = inlineRules[k];
+ let tagSimple = rule.tag.split(' ')[0];
- var regex = new RegExp(rule.symbol + '(.+?)\\x2F' + rule.symbol, 'g');
- html = html.replace(regex, '<' + rule.tag + '>$1' + tagSimple + '>');
+ let regex = new RegExp(rule.symbol + '(.+?)\\\\' + rule.symbol, 'g');
+ html = html.replace(regex, `<${rule.tag}>$1${tagSimple}>`);
- var resetRegex = new RegExp(rule.symbol + '(.+?)(?=)', 'g');
- html = html.replace(resetRegex, '<' + rule.tag + '>$1' + tagSimple + '>');
+ let resetRegex = new RegExp(rule.symbol + '(.+?)(?=)', 'g');
+ html = html.replace(resetRegex, `<${rule.tag}>$1${tagSimple}>`);
}
html = html.replace(//g, '');
- var alignMap = { 'l': 'left', 'r': 'right', 'c': 'center', 'j': 'justify' };
+ const alignMap = { 'l': 'left', 'r': 'right', 'c': 'center', 'j': 'justify' };
html = html.replace(/>([lrcj])\s+(.+?)\s*\/>/g, function(m, dir, content) {
- return '' + content + '
';
+ return `${content}
`;
});
html = html.replace(/!\[([^\]]+)\s+w:(\d+)\]\(([^)]+)\)/g, '
');
html = html.replace(/!\[([^\]]+)\]\(([^)]+)\)/g, '
');
html = html.replace(/\[([^\]]+)\]\{([^}]+)\}/g, '$1');
- html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '');
+ html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '$1');
- html = html.replace(/\^x\[([^\]]+)\]\^/g, '');
- html = html.replace(/\^(\d+)\[([^\]]+)\]\^/g, '');
+ html = html.replace(/\^x\[([^\]]+)\]\^x/g, '');
+ html = html.replace(/\^(\d+)\[([^\]]+)\]\^x/g, '');
html = html.replace(//g, function(match, idx) {
return escapes[idx];
@@ -659,16 +672,31 @@ class SimonUp {
return html;
}
+ /**
+ * INTERN: Errechnet die nächste fortlaufende Kapitelnummer
+ */
_getAutoNumber(level) {
- var idx = level - 1;
+ let idx = level - 1;
this.counters[idx]++;
- for (var i = idx + 1; i < 6; i++) {
+ for (let i = idx + 1; i < 6; i++) {
this.counters[i] = 0;
}
- var activeParts = this.counters.slice(0, level);
+ let activeParts = this.counters.slice(0, level);
return activeParts.join('.') + '.';
}
+ /**
+ * INTERN: Macht aus Text eine URL-konforme ID
+ */
+ _slugify(text) {
+ return text.toLowerCase()
+ .replace(/[^a-z0-9\s-]/g, '')
+ .replace(/\s+/g, '-');
+ }
+
+ /**
+ * INTERN: Erzeugt die fertige HTML-Liste des TOC und injiziert sie in den Block
+ */
_injectTOC(html) {
if (!html.includes('')) {
return html;
@@ -677,24 +705,24 @@ class SimonUp {
return html.replace('', '');
}
- var tocListHtml = '