From 102a53b84d0242c026b311d28f2ae9decaf79e6c Mon Sep 17 00:00:00 2001 From: simonpipe Date: Thu, 9 Jul 2026 19:11:18 +0200 Subject: [PATCH] Update Core.js --- Core.js | 377 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 356 insertions(+), 21 deletions(-) diff --git a/Core.js b/Core.js index 16c3bc3..9ec77cc 100644 --- a/Core.js +++ b/Core.js @@ -363,49 +363,384 @@ 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 = []; + this.headings = []; + this.counters = [0, 0, 0, 0, 0, 0]; + } + + use(plugin) { + this.plugins.push(plugin); + return this; + } + + parse(text) { + this.headings = []; + this.counters = [0, 0, 0, 0, 0, 0]; + var html = text; + + if (this.plugins && this.plugins.length > 0) { + for (var i = 0; i < this.plugins.length; i++) { + if (this.plugins[i].before) { + html = this.plugins[i].before(html); + } + } + } + + html = this._parseBlocks(html); + 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); + } + } + } + + return html; + } + + _parseBlocks(text) { + var lines = text.replace(/\r\n/g, '\n').split('\n'); + var result = []; + var inBlock = false; + var blockType = null; + var blockMeta = ""; + var blockBuffer = []; + + for (var i = 0; i < lines.length; i++) { + var line = lines[i]; + + if (!inBlock && line.startsWith('&') && line.trim().length > 1) { + inBlock = true; + var fullHeader = line.substring(1).trim(); + var spaceIndex = fullHeader.indexOf(' '); + + if (spaceIndex !== -1) { + blockType = fullHeader.substring(0, spaceIndex).toLowerCase(); + blockMeta = fullHeader.substring(spaceIndex).trim(); + } else { + blockType = fullHeader.toLowerCase(); + blockMeta = ""; + } + blockBuffer = []; + continue; + } + + if (inBlock && line.trim() === '&') { + result.push(this._renderBlock(blockType, blockMeta, blockBuffer)); + inBlock = false; + blockType = null; + blockMeta = ""; + continue; + } + + if (inBlock) { + blockBuffer.push(line); + } else { + var trimmed = line.trim(); + + if (trimmed === '___') { + result.push('
'); + } else if (trimmed.startsWith('- ')) { + var 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 + ''); + } else { + result.push(this._parseInline(line)); + } + } + } + + return this._processParagraphsAndLists(result); + } + + _renderBlock(type, meta, lines) { + var content = lines.join('\n'); + var self = this; + + switch (type) { + case 'toc': + var tocWrapper = ''; + if (meta || content.trim()) { + tocWrapper = '
\n'; + if (meta) { + tocWrapper += '

' + meta + '

\n'; + } + if (content.trim()) { + var 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 + '
'; + + case 'q': + var 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 + '
'; + + case 'f': + var fSummary = meta || 'Details'; + var 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
'; + + case 't': + return this._renderTable(meta, lines); + + default: + var defContent = lines.map(function(l) { return self._parseInline(l); }).join('
'); + return '
' + defContent + '
'; + } + } + + _renderTable(meta, lines) { + var tableHtml = '\n'; + var currentCells = []; + var cellBuffer = []; + var 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]; + + if (j === parts.length - 1) { + if (part.trim() !== '') { + cellBuffer.push(part); + } + if (line.endsWith('|') && cellBuffer.length > 0) { + currentCells.push(cellBuffer.join('\n')); + cellBuffer = []; + } + } else { + cellBuffer.push(part); + currentCells.push(cellBuffer.join('\n')); + cellBuffer = []; + } + } + + if (line.endsWith('|') && currentCells.length > 0) { + var rowContent = currentCells.map(function(c) { + var parsedCell = self._parseInline(c.trim()).replace(/\n/g, '
'); + return ''; + }).join('\n'); + tableHtml += '\n' + rowContent + '\n\n'; + currentCells = []; + } + } + tableHtml += '
' + parsedCell + '
'; + return tableHtml; + } + + _parseInline(text) { + if (!text) return ''; + var html = text; + + var escapes = []; + html = html.replace(/\\(.)/g, function(match, char) { + escapes.push(char); + return ''; + }); + + html = html.replace(/\/\/(\s|$)/g, '$1'); + + var self = this; + var processHeading = function(pattern, callback) { + var match; + while ((match = pattern.exec(html)) !== null) { + var fullMatch = match[0]; + var level = parseInt(match[1]); + var titleAndRest = match[2]; + + var title = titleAndRest; + var rest = ""; + var closeIdx = titleAndRest.indexOf('/#'); + if (closeIdx !== -1) { + title = titleAndRest.substring(0, closeIdx); + rest = titleAndRest.substring(closeIdx + 2); + } + + var 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); + self.headings.push({ level: level, text: fullTitle, id: id }); + return '' + fullTitle + '' + rest; + }); + + processHeading(/^([1-6])-#\s*(.*)/g, function(level, title, rest) { + return '' + title + '' + rest; + }); + + processHeading(/^([1-6])#\s*(.*)/g, function(level, title, rest) { + var id = _suSlugify(title); + self.headings.push({ level: level, text: title, id: id }); + return '' + title + '' + rest; + }); + + var inlineRules = [ + { tag: 'strong', symbol: '\\*\\*' }, + { tag: 'span style="font-weight: 500;"', symbol: '\\*' }, + { tag: 'em', symbol: '%' }, + { tag: 'u', symbol: '_' }, + { tag: 'del', symbol: '~' }, + { tag: 'mark', symbol: '=' }, + { tag: 'sup', symbol: '\\^' }, + { tag: 'sub', symbol: '°' }, + { tag: 'code', symbol: '`' } + ]; + + for (var k = 0; k < inlineRules.length; k++) { + var rule = inlineRules[k]; + var tagSimple = rule.tag.split(' ')[0]; + + var regex = new RegExp(rule.symbol + '(.+?)\\x2F' + rule.symbol, 'g'); + html = html.replace(regex, '<' + rule.tag + '>$1'); + + var resetRegex = new RegExp(rule.symbol + '(.+?)(?=)', 'g'); + html = html.replace(resetRegex, '<' + rule.tag + '>$1'); + } + + html = html.replace(//g, ''); + + var alignMap = { 'l': 'left', 'r': 'right', 'c': 'center', 'j': 'justify' }; + html = html.replace(/>([lrcj])\s+(.+?)\s*\/>/g, function(m, dir, content) { + return '
' + content + '
'; + }); + + html = html.replace(/!\[([^\]]+)\s+w:(\d+)\]\(([^)]+)\)/g, '$1'); + html = html.replace(/!\[([^\]]+)\]\(([^)]+)\)/g, '$1'); + html = html.replace(/\[([^\]]+)\]\{([^}]+)\}/g, '$1'); + html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, ''); + + html = html.replace(/\^x\[([^\]]+)\]\^/g, '[*]'); + html = html.replace(/\^(\d+)\[([^\]]+)\]\^/g, '[$1]'); + + html = html.replace(//g, function(match, idx) { + return escapes[idx]; + }); + + return html; + } + + _getAutoNumber(level) { + var idx = level - 1; + this.counters[idx]++; + for (var i = idx + 1; i < 6; i++) { + this.counters[i] = 0; + } + var activeParts = this.counters.slice(0, level); + return activeParts.join('.') + '.'; + } + + _injectTOC(html) { + if (!html.includes('')) { + return html; + } + if (this.headings.length === 0) { + return html.replace('', ''); + } + + var tocListHtml = '
\n\n'.repeat(diffFinal); + } + tocListHtml += '\n
'; + + return html.replace('', tocListHtml); + } - /** - * INTERN: Fasst freie Listen-Elemente zusammen und generiert Absätze (p) - */ _processParagraphsAndLists(elements) { - let processed = []; - let paragraphBuffer = []; - let listBuffer = []; - let currentListType = null; + var processed = []; + var paragraphBuffer = []; + var listBuffer = []; + var currentListType = null; - const flushList = function() { + var flushList = function() { if (listBuffer.length > 0) { - let items = listBuffer.map(function(item) { return `
  • ${item}
  • `; }).join('\n'); - processed.push(`<${currentListType}>\n${items}\n`); + var items = listBuffer.map(function(item) { return '
  • ' + item + '
  • '; }).join('\n'); + processed.push('<' + currentListType + '>\n' + items + '\n'); listBuffer = []; currentListType = null; } }; - const flushParagraph = function() { + var flushParagraph = function() { if (paragraphBuffer.length > 0) { - let pContent = paragraphBuffer.join('
    '); - processed.push(`

    ${pContent}

    `); + var pContent = paragraphBuffer.join('
    '); + processed.push('

    ' + pContent + '

    '); paragraphBuffer = []; } }; - for (let i = 0; i < elements.length; i++) { - let element = elements[i]; - let isUlItem = element.startsWith(''); - let isOlItem = element.startsWith(''); + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + var isUlItem = element.startsWith(''); + var isOlItem = element.startsWith(''); if (isUlItem || isOlItem) { flushParagraph(); - let type = isUlItem ? 'ul' : 'ol'; - let content = isUlItem ? element.replace(/<\/?ul-item>/g, '') : element.replace(/<\/?ol-item>/g, ''); + var type = isUlItem ? 'ul' : 'ol'; + var content = isUlItem ? element.replace(/<\/?ul-item>/g, '') : element.replace(/<\/?ol-item>/g, ''); if (currentListType && currentListType !== type) { flushList(); } currentListType = type; listBuffer.push(content); - } else if (element.startsWith('<') && !/^(||||||||||||||||||||||)/i.test(element)) { flushList(); flushParagraph(); processed.push(element); @@ -423,4 +758,4 @@ class SimonUp { return processed.join('\n'); } -} \ No newline at end of file +}