1
0
mirror of https://github.com/amir20/dozzle.git synced 2025-12-24 14:31:44 +01:00

feat!: strips all ansi colors and disables showing any colors (#2626)

This commit is contained in:
Amir Raminfar
2023-12-28 07:27:52 -08:00
committed by GitHub
parent 15fc01d265
commit 0ab9c730c7
7 changed files with 22 additions and 43 deletions

View File

@@ -140,19 +140,6 @@ describe("<LogEventSource />", () => {
expect(wrapper.find("ul.events").html()).toMatchSnapshot();
});
test("should render messages with color", async () => {
const wrapper = createLogEventSource();
sources[sourceUrl].emitOpen();
sources[sourceUrl].emitMessage({
data: '{"ts":1560336942459,"m":"\\u001b[30mblack\\u001b[37mwhite", "id":1}',
});
vi.runAllTimers();
await nextTick();
expect(wrapper.find("ul.events").html()).toMatchSnapshot();
});
test("should render messages with html entities", async () => {
const wrapper = createLogEventSource();
sources[sourceUrl].emitOpen();

View File

@@ -5,26 +5,22 @@
<log-level class="flex" :level="logEntry.level" :position="logEntry.position" />
<div
class="whitespace-pre-wrap [word-break:break-word] group-[.disable-wrap]:whitespace-nowrap"
v-html="colorize(logEntry.message)"
v-html="markSearch(logEntry.message)"
></div>
<log-message-actions
class="duration-250 absolute -right-1 opacity-0 transition-opacity delay-150 group-hover/entry:opacity-100"
:message="decodeXML(stripAnsi(logEntry.message))"
:message="decodeXML(logEntry.message)"
:log-entry="logEntry"
/>
</div>
</template>
<script lang="ts" setup>
import { SimpleLogEntry } from "@/models/LogEntry";
import AnsiConvertor from "ansi-to-html";
import stripAnsi from "strip-ansi";
import { decodeXML } from "entities";
const ansiConvertor = new AnsiConvertor({ escapeXML: false, fg: "var(--text-color)" });
defineProps<{
logEntry: SimpleLogEntry;
}>();
const { markSearch } = useSearchFilter();
const colorize = (value: string) => markSearch(ansiConvertor.toHtml(value));
</script>

View File

@@ -79,6 +79,9 @@ func (g *EventGenerator) consumeReader() {
message, streamType, readerError := readEvent(g.reader, g.tty)
if message != "" {
logEvent := createEvent(message, streamType)
if _, ok := logEvent.Message.(string); ok {
logEvent.Message = stripANSI(logEvent.Message.(string))
}
logEvent.Level = guessLogLevel(logEvent)
g.buffer <- logEvent
}

View File

@@ -6,7 +6,6 @@ import (
)
var KEY_VALUE_REGEX = regexp.MustCompile(`level=(\w+)`)
var ANSI_COLOR_REGEX = regexp.MustCompile(`\x1b\[[0-9;]*m`)
var LOG_LEVELS = []string{"error", "warn", "warning", "info", "debug", "trace", "fatal"}
var LOG_LEVELS_PLAIN = map[string]*regexp.Regexp{}
var LOG_LEVEL_BRACKET = map[string]*regexp.Regexp{}
@@ -24,13 +23,12 @@ func init() {
func guessLogLevel(logEvent *LogEvent) string {
switch value := logEvent.Message.(type) {
case string:
stripped := ANSI_COLOR_REGEX.ReplaceAllString(value, "") // remove ansi color codes
for _, level := range LOG_LEVELS {
if LOG_LEVELS_PLAIN[level].MatchString(stripped) {
if LOG_LEVELS_PLAIN[level].MatchString(value) {
return level
}
if LOG_LEVEL_BRACKET[level].MatchString(stripped) {
if LOG_LEVEL_BRACKET[level].MatchString(value) {
return level
}

View File

@@ -0,0 +1,13 @@
package docker
import (
"regexp"
)
const ansi = "[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))"
var re = regexp.MustCompile(ansi)
func stripANSI(str string) string {
return re.ReplaceAllString(str, "")
}

View File

@@ -42,7 +42,6 @@
"@vueuse/integrations": "^10.7.1",
"@vueuse/math": "^10.7.1",
"@vueuse/router": "^10.7.1",
"ansi-to-html": "^0.7.2",
"autoprefixer": "^10.4.16",
"d3-array": "^3.2.4",
"d3-ease": "^3.0.1",
@@ -59,7 +58,6 @@
"postcss": "^8.4.32",
"postcss-mixins": "^9.0.4",
"splitpanes": "^3.1.5",
"strip-ansi": "^7.1.0",
"tailwindcss": "^3.4.0",
"unplugin-auto-import": "^0.17.3",
"unplugin-icons": "^0.18.1",

20
pnpm-lock.yaml generated
View File

@@ -47,9 +47,6 @@ dependencies:
'@vueuse/router':
specifier: ^10.7.1
version: 10.7.1(vue-router@4.2.5)(vue@3.3.13)
ansi-to-html:
specifier: ^0.7.2
version: 0.7.2
autoprefixer:
specifier: ^10.4.16
version: 10.4.16(postcss@8.4.32)
@@ -98,9 +95,6 @@ dependencies:
splitpanes:
specifier: ^3.1.5
version: 3.1.5
strip-ansi:
specifier: ^7.1.0
version: 7.1.0
tailwindcss:
specifier: ^3.4.0
version: 3.4.0(ts-node@10.9.2)
@@ -2031,6 +2025,7 @@ packages:
/ansi-regex@6.0.1:
resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
engines: {node: '>=12'}
dev: true
/ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
@@ -2049,14 +2044,6 @@ packages:
engines: {node: '>=12'}
dev: true
/ansi-to-html@0.7.2:
resolution: {integrity: sha512-v6MqmEpNlxF+POuyhKkidusCHWWkaLcGRURzivcU3I9tv7k4JVhFcnukrM5Rlk2rUywdZuzYAZ+kbZqWCnfN3g==}
engines: {node: '>=8.0.0'}
hasBin: true
dependencies:
entities: 2.2.0
dev: false
/any-promise@1.3.0:
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
dev: false
@@ -2714,10 +2701,6 @@ packages:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
dev: true
/entities@2.2.0:
resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==}
dev: false
/entities@4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'}
@@ -4645,6 +4628,7 @@ packages:
engines: {node: '>=12'}
dependencies:
ansi-regex: 6.0.1
dev: true
/strip-final-newline@2.0.0:
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}