Skip to content
This repository has been archived by the owner on Sep 6, 2022. It is now read-only.

Commit

Permalink
address feedback from @nakhbari
Browse files Browse the repository at this point in the history
  • Loading branch information
snatchev committed Aug 3, 2018
1 parent 207d688 commit aa54d95
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 19 deletions.
Expand Up @@ -23,7 +23,7 @@ describe('LogLineComponent', () => {
timestamp: 1531944769
};

fixture.detectChanges(); //onInit
fixture.detectChanges(); // onInit
}));

it('should create the correct span dom tree of ansi codes', () => {
Expand Down
35 changes: 20 additions & 15 deletions web/app/common/components/log-viewer/log-line/log-line.component.ts
@@ -1,6 +1,11 @@
import { Component, AfterViewInit, ViewChild, ElementRef, Input, ViewEncapsulation } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { Component, AfterViewInit, ViewChild, ElementRef, Input, Inject, ViewEncapsulation } from '@angular/core';

const ANSI_PATTERN = /\u001b\[([0-9;]+)?m/;
const ANSI_RESET_CODE = '0';

type AnsiCode = string;
type AnsiTuple = [AnsiCode, string];

export interface LogLine {
timestamp: number;
Expand All @@ -20,21 +25,22 @@ export class LogLineComponent implements AfterViewInit {
@Input() log: LogLine;
@ViewChild('logLine', { read: ElementRef }) logLineEl: ElementRef;

constructor(@Inject(DOCUMENT) private readonly document: any) {}

ngAfterViewInit() {
const parentEl = this.logLineEl.nativeElement;
let currentSpanEl = parentEl;
const stack = this.tokenize(this.log.message);

stack.forEach(tuple => {
for (const tuple of stack) {
const [code, text] = tuple;
if (code === '0') {
if (code === ANSI_RESET_CODE) {
parentEl.innerHTML += text;
currentSpanEl = parentEl;
}
else {
} else {
currentSpanEl = this.injectSpan(currentSpanEl, text, code);
}
});
}
}

/**
Expand All @@ -43,20 +49,19 @@ export class LogLineComponent implements AfterViewInit {
* this method will split and group the result into an array of tuples [ansi code, text]
* NOTE: that the capture comes after the string, so we transpose them.
**/
private tokenize(text: string): [string, string][] {
const tuples = text.split(ANSI_PATTERN);
private tokenize(ansiText: string): AnsiTuple[] {
const tuples = ansiText.split(ANSI_PATTERN);

// if the text starts with a match capture (and thus returning empty string as [0]),
// use that captured ansi code as the beginning style
if (tuples[0] === '') {
tuples.shift();
}
// otherwise, we must assume we are starting each line as the default '0'
else {
tuples.unshift('0');
} else {
// otherwise, we must assume we are starting each line as the default '0'
tuples.unshift(ANSI_RESET_CODE);
}

const stack = [];
const stack: AnsiTuple[] = [];

for (let i = 0; i < tuples.length; i += 2) {
const code = tuples[i];
Expand All @@ -66,8 +71,8 @@ export class LogLineComponent implements AfterViewInit {
return stack;
}

private injectSpan(parent: HTMLElement, text: string, ansiCode: string): HTMLSpanElement {
const span = document.createElement('span');
private injectSpan(parent: HTMLElement, text: string, ansiCode: AnsiCode): HTMLSpanElement {
const span = this.document.createElement('span');
const classNames = ansiCode.split(';').map(c => `fci-ansi-${c}`).join(' ');
span.className = classNames;
span.innerText = text;
Expand Down
@@ -1,4 +1,4 @@
<ng-container *ngIf="logLines.length <= 0">Connecting...</ng-container>
<ng-container *ngFor="let log of logLines">
<ng-container class="fci-log-viewer" *ngFor="let log of logLines">
<fci-log-line [log]="log"></fci-log-line>
</ng-container>
16 changes: 14 additions & 2 deletions web/app/common/components/log-viewer/log-viewer.component.spec.ts
Expand Up @@ -2,6 +2,8 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { LogViewerComponent } from './log-viewer.component';
import { LogLineModule } from './log-line/log-line.module';
import { LogLine } from './log-line/log-line.component';
import { getElement } from '../../test_helpers/element_helper_functions';

describe('LogViewerComponent', () => {
let component: LogViewerComponent;
Expand All @@ -18,10 +20,20 @@ describe('LogViewerComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(LogViewerComponent);
component = fixture.componentInstance;
component.logLines = [{
timestamp: 1533326666,
message: 'this was a message',
level: 'DEBUG',
status: 0,
}];

fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
/*
it('should create a log viewer component with log lines', () => {
const element = getElement(fixture.debugElement, '.fci-log-viewer');
expect(element.nativeElement.innerHTML).toEqual('');
});
*/
});

0 comments on commit aa54d95

Please sign in to comment.