diff options
| -rw-r--r-- | webAO/client.js | 11 | ||||
| -rw-r--r-- | webAO/utils/aoml.js | 128 |
2 files changed, 135 insertions, 4 deletions
diff --git a/webAO/client.js b/webAO/client.js index 14bfd08..87db272 100644 --- a/webAO/client.js +++ b/webAO/client.js @@ -10,7 +10,7 @@ import fileExistsSync from './utils/fileExistsSync'; import { escapeChat, encodeChat, prepChat, safeTags, } from './encoding.js'; - +import mlConfig from './utils/aoml'; // Load some defaults for the background and evidence dropdowns import vanilla_character_arr from './constants/characters.js'; import vanilla_music_arr from './constants/music.js'; @@ -43,6 +43,8 @@ const DEFAULT_HOST = 'http://attorneyoffline.de/base/'; let AO_HOST = asset || DEFAULT_HOST; const THEME = theme || 'default'; +const attorneyMarkdown = mlConfig(AO_HOST) + const UPDATE_INTERVAL = 60; /** @@ -1938,6 +1940,7 @@ class Viewport { * @param {object} chatmsg the new chat message */ async say(chatmsg) { + this.chatmsg = chatmsg; this.textnow = ''; this.sfxplayed = 0; @@ -2089,7 +2092,7 @@ class Viewport { if (soundChecks.some((check) => this.chatmsg.sound === check)) { this.chatmsg.sound = this.chatmsg.effects[2]; } - + this.chatmsg.parsed = attorneyMarkdown.applyMarkdown(chatmsg.content, this.colors[this.chatmsg.color]) this.tick(); } @@ -2241,8 +2244,7 @@ class Viewport { this.currentBlipChannel %= this.blipChannels.length; } this.textnow = this.chatmsg.content.substring(0, this.textnow.length + 1); - - chatBoxInner.innerText = this.textnow; + chatBoxInner.appendChild(this.chatmsg.parsed[this.textnow.length - 1]); // scroll to bottom chatBox.scrollTop = chatBox.scrollHeight; @@ -2325,6 +2327,7 @@ export function onEnter(event) { if (emote_mod === 0) { emote_mod = 1; } } else if (emote_mod === 1) { emote_mod = 0; } + client.sendIC( 'chat', myemo.preanim, diff --git a/webAO/utils/aoml.js b/webAO/utils/aoml.js new file mode 100644 index 0000000..9506fbf --- /dev/null +++ b/webAO/utils/aoml.js @@ -0,0 +1,128 @@ +import request from "../services/request" + + +const aomlParser = (text) => { + let parsed = {} + let currentHeader = '' + for (const line of text.split(/\r?\n/)) { + if (line === '') { + currentHeader = '' + continue; + } + const content = line.split(' = ') + const contentName = content[0] + const contentValue = content[1] + if (currentHeader === '') { + currentHeader = contentName + parsed[currentHeader] = { + color: contentValue + } + } else { + const contentKey = contentName.split('_')[1] + parsed[currentHeader][contentKey] = contentValue + } + } + return parsed +} + + + + +const mlConfig = (AO_HOST) => { + const defaultUrl = `${AO_HOST}themes/default/chat_config.ini` + let aomlParsed = {} + + request(defaultUrl).then((data) => { + aomlParsed = aomlParser(data) + } + ); + + const createIdentifiers = () => { + const identifiers = new Map() + for (const [ruleName, value] of Object.entries(aomlParsed)) { + if (identifiers.has(value.start)) { + throw new Error() + } + else if (value.start && value.end) { + identifiers.set(value.start, value) + identifiers.set(value.end, value) + } + + + } + return identifiers + } + const colorIdentifiers = () => { + let colorIdentifier = {} + for (const [ruleName, value] of Object.entries(aomlParsed)) { + colorIdentifier[value.start] = value.color + } + return colorIdentifier + } + const applyMarkdown = (text, defaultColor) => { + const identifiers = createIdentifiers(aomlParsed) + const startIdentifiers = new Set(identifiers.keys()) + const colorIdentifier = colorIdentifiers() + const identifierClosingStack = [] + + const colorStack = [[255, 255, 255]] + // each value in output will be an html element + let output = [] + for (const letter of text) { + let currentSelector = document.createElement('span') + let letterIdentifier = identifiers.get(letter) + const lastItem = identifierClosingStack.length + const closingToLookFor = identifierClosingStack[lastItem-1] + const keepChar = Number(letterIdentifier?.remove) === 0 + + if (letter === closingToLookFor) { + identifierClosingStack.pop() + if (keepChar) { + currentSelector.innerHTML = letter + if (colorStack.length === 1){ + currentSelector.className = `text_${defaultColor}` + } else { + const r = colorStack[colorStack.length-1][0] + const g = colorStack[colorStack.length-1][1] + const b = colorStack[colorStack.length-1][2] + const currentColor = `color: rgb(${r},${g},${b});` + currentSelector.setAttribute('style', currentColor) + } + output.push(currentSelector) + } + colorStack.pop() + continue; + } + else if (startIdentifiers.has(letter)) { + identifierClosingStack.push(identifiers.get(letter).end) + const colors = colorIdentifier[letter].split(',') + const r = colors[0] + const g = colors[1] + const b = colors[2] + colorStack.push([r,g,b]) + if (keepChar) { + currentSelector.innerHTML = letter + } + + } else { + currentSelector.innerHTML = letter + } + if (colorStack.length === 1) { + currentSelector.className = `test_${defaultColor}` + } else { + const r = colorStack[colorStack.length-1][0] + const g = colorStack[colorStack.length-1][1] + const b = colorStack[colorStack.length-1][2] + const currentColor = `color: rgb(${r},${g},${b});` + currentSelector.setAttribute('style', currentColor) + } + output.push(currentSelector) + } + return output + } + return { + applyMarkdown + } +} + +export default mlConfig
\ No newline at end of file |
