Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
levy committed Nov 29, 2019
2 parents 70ccf21 + 9f5408f commit aa6df81
Show file tree
Hide file tree
Showing 8 changed files with 414 additions and 106 deletions.
45 changes: 43 additions & 2 deletions docs/basic.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,48 @@ basic usage

```vue
<template>
<log-viewer log="here is some logs.\n test some logs"/>
<div>
<div style="margin-bottom:8px;">Show travis log</div>
<log-viewer :log="travisLog" :auto-scroll="false"/>
<div style="margin-top:16px;margin-bottom:8px;">Show nuxt build log</div>
<log-viewer :log="nuxtBuildLog"/>
</div>
</template>
```
<script>
const get = url=>new Promise((resolve, reject)=>{
const xhr = new XMLHttpRequest()
xhr.open("GET",url)
xhr.send()
xhr.onload = data => resolve(data.target.responseText)
})
export default {
data(){
return {
travisLog: '',
nuxtBuildLog:''
}
},
mounted(){
this.getTravisLog()
this.getNuxtBuildLog()
},
methods:{
getTravisLog(){
const travisUrl = 'https://api.travis-ci.com/v3/job/261228572/log.txt' // you can edit other travisUrl.
get(travisUrl).then((text)=>{
this.travisLog = text
})
},
getNuxtBuildLog(){
const logUrl = 'https://mockapi.eolinker.com/IeZWjzy87c204a1f7030b2a17b00f3776ce0a07a5030a1b/log-viewer'
get(logUrl).then(res=>{
res = JSON.parse(res)
this.nuxtBuildLog = res.payload.logs
})
}
}
}
</script>
```
91 changes: 84 additions & 7 deletions src/components/line-content.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,95 @@
<template>
<div class="line-content" :class="className">{{ text }}</div>
<div class="line-content">
<span
v-for="(item, index) in content"
:key="index"
:class="[
item.bold ? 'log-bold' : '',
item.underline ? 'log-underline' : '',
item.italic ? 'log-italic' : '',
item.foreground ? 'log-fore-' + item.foreground : '',
item.background ? 'log-back-' + item.background : ''
]"
>{{ item.text }}</span
>
</div>
</template>
<script>
export default {
name: 'LineContent',
props: {
/**
* log text
* log text content
*/
text: String,
/**
* The line content's class
*/
className: [String, Array, Object]
content: Array
}
}
</script>

<style lang="less">
@black: rgb(0, 0, 0);
@red: rgb(194, 54, 33);
@green: rgb(37, 188, 36);
@yellow: rgb(173, 173, 39);
@blue: rgb(73, 46, 225);
@magenta: rgb(211, 56, 211);
@cyan: rgb(51, 187, 200);
@white: rgb(203, 204, 205);
@bright-black: rgb(129, 131, 131);
@bright-red: rgb(252, 57, 31);
@bright-green: rgb(49, 231, 34);
@bright-yellow: rgb(234, 236, 35);
@bright-blue: rgb(88, 51, 255);
@bright-magenta: rgb(180, 0, 158);
@bright-cyan: rgb(97, 214, 214);
@bright-white: rgb(242, 242, 242);
.log(@color) {
@bright: 'bright-@{color}';
.log-fore-@{color} {
color: @@color;
&.log-underline {
text-decoration-color: @@color;
}
}
.log-fore-bright-@{color} {
color: @@bright;
&.log-underline {
text-decoration-color: @@bright;
}
}
.log-back-@{color} {
background: @@color;
}
.log-back-bright-@{color} {
background: @@bright;
}
}
.line-content {
.log-bold {
font-weight: bold;
}
.log-underline {
text-decoration: underline;
}
.log-italic {
font-style: italic;
}
.log(black);
.log(red);
.log(green);
.log(yellow);
.log(blue);
.log(magenta);
.log(cyan);
.log(white);
}
</style>
12 changes: 7 additions & 5 deletions src/components/line-wrapper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div class="line-wrapper" :style="customStyle">
<line-number v-if="hasNumber" v-bind="numberData"></line-number>
<slot>
<line-content v-bind="data"></line-content>
<line-content :content="data"></line-content>
</slot>
</div>
</template>
Expand All @@ -20,11 +20,13 @@ export default {
* line-content attrs
*/
data: {
type: Object,
type: Array,
default() {
return {
text: ''
}
return [
{
text: ''
}
]
}
},
/**
Expand Down
4 changes: 1 addition & 3 deletions src/log-viewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,7 @@ export default {
}
}
}
props.data = {
text: this.lines[index]
}
props.data = this.lines[index]
return {
props
}
Expand Down
205 changes: 205 additions & 0 deletions src/utils/ansi-parse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
/* eslint-disable no-plusplus, no-continue */
// CSI解释器,参考
// 字体颜色https://github.com/mozilla-frontend-infra/react-lazylog/blob/master/src/ansiparse.js
const foregroundColors = {
'30': 'black',
'31': 'red',
'32': 'green',
'33': 'yellow',
'34': 'blue',
'35': 'magenta',
'36': 'cyan',
'37': 'white',
'90': 'bright-black',
'91': 'bright-red',
'92': 'bright-green',
'93': 'bright-yellow',
'94': 'bright-blue',
'95': 'bright-magenta',
'96': 'bright-cyan',
'97': 'bright-white'
}
// 字体背景
const backgroundColors = {
'40': 'black',
'41': 'red',
'42': 'green',
'43': 'yellow',
'44': 'blue',
'45': 'magenta',
'46': 'cyan',
'47': 'white',
'100': 'bright-black',
'101': 'bright-red',
'102': 'bright-green',
'103': 'bright-yellow',
'104': 'bright-blue',
'105': 'bright-magenta',
'106': 'bright-cyan',
'107': 'bright-white'
}
// 文字状态(粗体,斜体,下划线)
const styles = {
'1': 'bold',
'3': 'italic',
'4': 'underline'
}
// Select Graphic Rendition(SGR) flag
const SGRCode = 'm'
// 非SGR,后续可针对该控制符进行解释
const notSGRCodes = [
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'J',
'K',
'S',
'T',
'f',
's',
'u',
'h',
'l'
]

/**
* 格式化数据类型
* interface formatter {
* text: string,
* foreground?: string,
* background?: string,
* underline?: boolean,
* bold?: boolean,
* italic?: boolean,
* }
**/

/**
* Backspace操作,即删除最后一个字符
* matchingText: string,
* result: formatter[]
* eraseChar: [string,formatter[]]
* */

const eraseChar = (matchingText, result) => {
if (matchingText.length) {
return [matchingText.substr(0, matchingText.length - 1), result]
} else if (result.length) {
const index = result.length - 1
const {text} = result[index]
const newResult =
text.length === 1
? result.slice(0, result.length - 1)
: result.map((item, i) =>
index === i
? {...item, text: text.substr(0, text.length - 1)}
: item
)

return [matchingText, newResult]
}

return [matchingText, result]
}

/**
* str: string
* ansiParse: formatter[]
* This Function only translate these codes: 1,3,4,22-24,30-37,39,40-47,49,90-97,100-107.
* It would be more and more powerful and translate more codes.
**/

const ansiParse = str => {
let matchingControl = null
let matchingCode = null
let matchingText = ''
let ansiState = []
let result = []
let state = {}

for (let i = 0; i < str.length; i++) {
if (matchingControl !== null) {
if (matchingControl === '\x1b' && str[i] === '[') {
if (matchingText) {
state.text = matchingText
result.push(state)
state = {}
matchingText = ''
}

matchingControl = null
matchingCode = ''
} else {
matchingText += matchingControl + str[i]
matchingControl = null
}

continue
} else if (matchingCode !== null) {
if (str[i] === ';') {
ansiState.push(matchingCode)
matchingCode = ''
} else if (str[i] === SGRCode) {
ansiState.push(matchingCode)
matchingCode = null
matchingText = ''

for (let a = 0; a < ansiState.length; a++) {
const ansiCode = +ansiState[a]
if (foregroundColors[ansiCode]) {
state.foreground = foregroundColors[ansiCode]
} else if (backgroundColors[ansiCode]) {
state.background = backgroundColors[ansiCode]
} else if (ansiCode === 39) {
delete state.foreground
} else if (ansiCode === 49) {
delete state.background
} else if (styles[ansiCode]) {
state[styles[ansiCode]] = true
} else if (ansiCode === 22) {
state.bold = false
} else if (ansiCode === 23) {
state.italic = false
} else if (ansiCode === 24) {
state.underline = false
}
}

ansiState = []
} else if (notSGRCodes.indexOf(str[i]) > -1) {
// Ignore codes which is not SGR code and delete them.
// It should be translated in some day.
matchingCode = ''
ansiState = []
} else {
matchingCode += str[i]
}

continue
}

if (str[i] === '\x1b') {
// ESC Control
matchingControl = str[i]
} else if (str[i] === '\u0008') {
// Backspace Control
;[matchingText, result] = eraseChar(matchingText, result)
} else {
matchingText += str[i]
}
}

if (matchingText) {
state.text = matchingText + (matchingControl || '')
result.push(state)
}

return result
}

export default ansiParse
Loading

0 comments on commit aa6df81

Please sign in to comment.