aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--webAO/client.js11
-rw-r--r--webAO/utils/aoml.js128
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