mirror of https://gitee.com/bigwinds/arangodb
Documentation 3.3/backuport examples (#5192)
This commit is contained in:
parent
5757965e26
commit
7515253e93
|
@ -15,54 +15,24 @@ Relationships are established by using the *friendOf* and *thisUser* attributes
|
|||
We'll start with a SQL-ish result set and return each tuple (user name, friends userId)
|
||||
separately. The AQL query to generate such result is:
|
||||
|
||||
```js
|
||||
FOR u IN users
|
||||
FILTER u.active == true
|
||||
LIMIT 0, 4
|
||||
FOR f IN relations
|
||||
FILTER f.type == "friend" && f.friendOf == u.userId
|
||||
RETURN {
|
||||
"user" : u.name,
|
||||
"friendId" : f.thisUser
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"user" : "Abigail",
|
||||
"friendId" : 108
|
||||
},
|
||||
{
|
||||
"user" : "Abigail",
|
||||
"friendId" : 102
|
||||
},
|
||||
{
|
||||
"user" : "Abigail",
|
||||
"friendId" : 106
|
||||
},
|
||||
{
|
||||
"user" : "Fred",
|
||||
"friendId" : 209
|
||||
},
|
||||
{
|
||||
"user" : "Mary",
|
||||
"friendId" : 207
|
||||
},
|
||||
{
|
||||
"user" : "Mary",
|
||||
"friendId" : 104
|
||||
},
|
||||
{
|
||||
"user" : "Mariah",
|
||||
"friendId" : 203
|
||||
},
|
||||
{
|
||||
"user" : "Mariah",
|
||||
"friendId" : 205
|
||||
}
|
||||
]
|
||||
```
|
||||
@startDocuBlockInline joinTuples
|
||||
@EXAMPLE_AQL{joinTuples}
|
||||
@DATASET{joinSampleDataset}
|
||||
FOR u IN users
|
||||
FILTER u.active == true
|
||||
LIMIT 0, 4
|
||||
FOR f IN relations
|
||||
FILTER f.type == @friend && f.friendOf == u.userId
|
||||
RETURN {
|
||||
"user" : u.name,
|
||||
"friendId" : f.thisUser
|
||||
}
|
||||
@BV {
|
||||
friend: "friend"
|
||||
}
|
||||
@END_EXAMPLE_AQL
|
||||
@endDocuBlock joinTuples
|
||||
|
||||
We iterate over the collection users. Only the 'active' users will be examined.
|
||||
For each of these users we will search for up to 4 friends. We locate friends
|
||||
|
|
|
@ -350,12 +350,27 @@ Now let's have a look what the optimizer does behind the curtain and inspect
|
|||
traversal queries using [the explainer](../ExecutionAndPerformance/Optimizer.md):
|
||||
|
||||
@startDocuBlockInline GRAPHTRAV_07_traverse_7
|
||||
@EXAMPLE_ARANGOSH_OUTPUT{GRAPHTRAV_07_traverse_7}
|
||||
db._explain("FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' LET localScopeVar = RAND() > 0.5 FILTER p.edges[0].theTruth != localScopeVar RETURN v._key", {}, {colors: false});
|
||||
db._explain("FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.edges[0].label == 'right_foo' RETURN v._key", {}, {colors: false});
|
||||
@END_EXAMPLE_ARANGOSH_OUTPUT
|
||||
@EXAMPLE_AQL{GRAPHTRAV_07_traverse_7}
|
||||
@DATASET{traversalGraph}
|
||||
@EXPLAIN{TRUE}
|
||||
FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph'
|
||||
LET localScopeVar = RAND() > 0.5
|
||||
FILTER p.edges[0].theTruth != localScopeVar
|
||||
RETURN v._key
|
||||
@END_EXAMPLE_AQL
|
||||
@endDocuBlock GRAPHTRAV_07_traverse_7
|
||||
|
||||
|
||||
@startDocuBlockInline GRAPHTRAV_07_traverse_8
|
||||
@EXAMPLE_AQL{GRAPHTRAV_07_traverse_8}
|
||||
@DATASET{traversalGraph}
|
||||
@EXPLAIN{TRUE}
|
||||
FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph'
|
||||
FILTER p.edges[0].label == 'right_foo'
|
||||
RETURN v._key
|
||||
@END_EXAMPLE_AQL
|
||||
@endDocuBlock GRAPHTRAV_07_traverse_8
|
||||
|
||||
We now see two queries: In one we add a variable *localScopeVar*, which is outside
|
||||
the scope of the traversal itself - it is not known inside of the traverser.
|
||||
Therefore, this filter can only be executed after the traversal, which may be
|
||||
|
|
|
@ -8,9 +8,9 @@ Execution plan:
|
|||
1 SingletonNode 1 * ROOT
|
||||
2 CalculationNode 1 - LET #5 = 1 .. 10 /* range */ /* simple expression */
|
||||
3 EnumerateListNode 10 - FOR x IN #5 /* list iteration */
|
||||
4 CalculationNode 10 - LET then = DATE_NOW() /* v8 expression */
|
||||
4 CalculationNode 10 - LET then = DATE_NOW() /* simple expression */
|
||||
6 EnumerateListNode 100 - FOR y IN #5 /* list iteration */
|
||||
7 CalculationNode 100 - LET now = DATE_NOW() /* v8 expression */
|
||||
7 CalculationNode 100 - LET now = DATE_NOW() /* simple expression */
|
||||
8 CalculationNode 100 - LET nowstr = CONCAT(now, x, y, then) /* simple expression */
|
||||
9 ReturnNode 100 - RETURN nowstr
|
||||
|
||||
|
@ -32,7 +32,7 @@ Execution plan:
|
|||
Id NodeType Est. Comment
|
||||
1 SingletonNode 1 * ROOT
|
||||
3 CalculationNode 1 - LET #4 = 1 .. 10 /* range */ /* simple expression */
|
||||
2 CalculationNode 1 - LET now = DATE_NOW() /* v8 expression */
|
||||
2 CalculationNode 1 - LET now = DATE_NOW() /* simple expression */
|
||||
4 EnumerateListNode 10 - FOR x IN #4 /* list iteration */
|
||||
6 EnumerateListNode 100 - FOR y IN #4 /* list iteration */
|
||||
7 CalculationNode 100 - LET nowstr = CONCAT(now, x, y, now) /* simple expression */
|
||||
|
|
|
@ -1,63 +1,38 @@
|
|||
arangosh> db._explain("FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' LET localScopeVar = RAND() > 0.5 FILTER p.edges[0].theTruth != localScopeVar RETURN v._key", {}, {colors: false});
|
||||
Query string:
|
||||
FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' LET localScopeVar = RAND() > 0.5
|
||||
FILTER p.edges[0].theTruth != localScopeVar RETURN v._key
|
||||
@Q:
|
||||
FOR v,e,p IN <span class="hljs-number">1.</span><span class="hljs-number">.3</span> OUTBOUND <span class="hljs-string">'circles/A'</span> GRAPH <span class="hljs-string">'traversalGraph'</span>
|
||||
LET localScopeVar = RAND() > <span class="hljs-number">0.5</span>
|
||||
FILTER p.edges[<span class="hljs-number">0</span>].theTruth != localScopeVar
|
||||
RETURN v._key
|
||||
|
||||
Execution plan:
|
||||
Id NodeType Est. Comment
|
||||
1 SingletonNode 1 * ROOT
|
||||
2 TraversalNode 1 - FOR v /* vertex */, p /* paths */ IN 1..3 /* min..maxPathDepth */ OUTBOUND 'circles/A' /* startnode */ GRAPH 'traversalGraph'
|
||||
3 CalculationNode 1 - LET localScopeVar = (RAND() > 0.5) /* simple expression */
|
||||
4 CalculationNode 1 - LET #6 = (p.`edges`[0].`theTruth` != localScopeVar) /* simple expression */
|
||||
5 FilterNode 1 - FILTER #6
|
||||
6 CalculationNode 1 - LET #8 = v.`_key` /* attribute expression */
|
||||
7 ReturnNode 1 - RETURN #8
|
||||
@R
|
||||
<span style="color:rgb(85,85,255)">Query string:</span>
|
||||
<span style="color:rgb(0,187,0)"> FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph'
|
||||
LET localScopeVar = RAND() > 0.5
|
||||
FILTER p.edges[0].theTruth != localScopeVar
|
||||
RETURN v._key
|
||||
</span>
|
||||
|
||||
Indexes used:
|
||||
By Type Collection Unique Sparse Selectivity Fields Ranges
|
||||
2 edge edges false false 85.00 % [ `_from`, `_to` ] base OUTBOUND
|
||||
<span style="color:rgb(85,85,255)">Execution plan:</span>
|
||||
<span style="color:rgb(187,0,187)">Id</span> <span style="color:rgb(187,0,187)">NodeType</span> <span style="color:rgb(187,0,187)">Est.</span> <span style="color:rgb(187,0,187)">Comment</span>
|
||||
<span style="color:rgb(187,187,0)">1</span> <span style="color:rgb(0,187,187)">SingletonNode</span> <span style="color:rgb(0,187,0)">1</span> * <span style="color:rgb(0,187,187)">ROOT</span>
|
||||
<span style="color:rgb(187,187,0)">2</span> <span style="color:rgb(0,187,187)">TraversalNode</span> <span style="color:rgb(0,187,0)">1</span> - <span style="color:rgb(0,187,187)">FOR </span><span style="color:rgb(187,187,0)">v</span> <span style="color:rgb(0,0,187)">/* vertex */</span>, <span style="color:rgb(187,187,0)">p</span> <span style="color:rgb(0,0,187)">/* paths */</span> <span style="color:rgb(0,187,187)">IN</span> <span style="color:rgb(0,187,0)">1..3</span> <span style="color:rgb(0,0,187)">/* min..maxPathDepth */</span> <span style="color:rgb(0,187,187)">OUTBOUND</span> '<span style="color:rgb(0,187,0)">circles/A</span>' <span style="color:rgb(0,0,187)">/* startnode */</span> <span style="color:rgb(0,187,187)">GRAPH</span> '<span style="color:rgb(0,187,0)">traversalGraph</span>'
|
||||
<span style="color:rgb(187,187,0)">3</span> <span style="color:rgb(0,187,187)">CalculationNode</span> <span style="color:rgb(0,187,0)">1</span> - <span style="color:rgb(0,187,187)">LET</span> <span style="color:rgb(187,187,0)">localScopeVar</span> = (<span style="color:rgb(0,187,0)">RAND</span>() > <span style="color:rgb(0,187,0)">0.5</span>) <span style="color:rgb(0,0,187)">/* simple expression */</span>
|
||||
<span style="color:rgb(187,187,0)">4</span> <span style="color:rgb(0,187,187)">CalculationNode</span> <span style="color:rgb(0,187,0)">1</span> - <span style="color:rgb(0,187,187)">LET</span> <span style="color:rgb(187,0,187)">#6</span> = (<span style="color:rgb(187,187,0)">p</span>.`<span style="color:rgb(187,187,0)">edges</span>`[<span style="color:rgb(0,187,0)">0</span>].`<span style="color:rgb(187,187,0)">theTruth</span>` != <span style="color:rgb(187,187,0)">localScopeVar</span>) <span style="color:rgb(0,0,187)">/* simple expression */</span>
|
||||
<span style="color:rgb(187,187,0)">5</span> <span style="color:rgb(0,187,187)">FilterNode</span> <span style="color:rgb(0,187,0)">1</span> - <span style="color:rgb(0,187,187)">FILTER</span> <span style="color:rgb(187,0,187)">#6</span>
|
||||
<span style="color:rgb(187,187,0)">6</span> <span style="color:rgb(0,187,187)">CalculationNode</span> <span style="color:rgb(0,187,0)">1</span> - <span style="color:rgb(0,187,187)">LET</span> <span style="color:rgb(187,0,187)">#8</span> = <span style="color:rgb(187,187,0)">v</span>.`<span style="color:rgb(187,187,0)">_key</span>` <span style="color:rgb(0,0,187)">/* attribute expression */</span>
|
||||
<span style="color:rgb(187,187,0)">7</span> <span style="color:rgb(0,187,187)">ReturnNode</span> <span style="color:rgb(0,187,0)">1</span> - <span style="color:rgb(0,187,187)">RETURN</span> <span style="color:rgb(187,0,187)">#8</span>
|
||||
|
||||
Traversals on graphs:
|
||||
Id Depth Vertex collections Edge collections Options Filter conditions
|
||||
2 1..3 circles edges uniqueVertices: none, uniqueEdges: path
|
||||
<span style="color:rgb(85,85,255)">Indexes used:</span>
|
||||
<span style="color:rgb(187,0,187)">By</span> <span style="color:rgb(187,0,187)">Type</span> <span style="color:rgb(187,0,187)">Collection</span> <span style="color:rgb(187,0,187)">Unique</span> <span style="color:rgb(187,0,187)">Sparse</span> <span style="color:rgb(187,0,187)">Selectivity</span> <span style="color:rgb(187,0,187)">Fields</span> <span style="color:rgb(187,0,187)">Ranges</span>
|
||||
<span style="color:rgb(187,187,0)">2</span> <span style="color:rgb(0,187,187)">edge</span> <span style="color:rgb(187,0,0)">edges</span> <span style="color:rgb(0,187,0)">false</span> <span style="color:rgb(0,187,0)">false</span> <span style="color:rgb(0,187,0)">85.00 %</span> [ `<span style="color:rgb(187,187,0)">_from</span>`, `<span style="color:rgb(187,187,0)">_to</span>` ] <span style="color:rgb(0,187,187)">base OUTBOUND</span>
|
||||
|
||||
Optimization rules applied:
|
||||
Id RuleName
|
||||
1 move-calculations-up
|
||||
2 optimize-traversals
|
||||
3 move-calculations-down
|
||||
|
||||
|
||||
arangosh> db._explain("FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.edges[0].label == 'right_foo' RETURN v._key", {}, {colors: false});
|
||||
Query string:
|
||||
FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.edges[0].label == 'right_foo'
|
||||
RETURN v._key
|
||||
|
||||
Execution plan:
|
||||
Id NodeType Est. Comment
|
||||
1 SingletonNode 1 * ROOT
|
||||
2 TraversalNode 1 - FOR v /* vertex */ IN 1..3 /* min..maxPathDepth */ OUTBOUND 'circles/A' /* startnode */ GRAPH 'traversalGraph'
|
||||
5 CalculationNode 1 - LET #7 = v.`_key` /* attribute expression */
|
||||
6 ReturnNode 1 - RETURN #7
|
||||
|
||||
Indexes used:
|
||||
By Type Collection Unique Sparse Selectivity Fields Ranges
|
||||
2 edge edges false false 85.00 % [ `_from`, `_to` ] base OUTBOUND
|
||||
2 edge edges false false 85.00 % [ `_from`, `_to` ] level 0 OUTBOUND
|
||||
|
||||
Traversals on graphs:
|
||||
Id Depth Vertex collections Edge collections Options Filter conditions
|
||||
2 1..3 circles edges uniqueVertices: none, uniqueEdges: path (p.`edges`[0].`label` == "right_foo")
|
||||
|
||||
Optimization rules applied:
|
||||
Id RuleName
|
||||
1 move-calculations-up
|
||||
2 move-filters-up
|
||||
3 move-calculations-up-2
|
||||
4 move-filters-up-2
|
||||
5 optimize-traversals
|
||||
6 remove-filter-covered-by-traversal
|
||||
7 remove-unnecessary-calculations-2
|
||||
8 remove-redundant-path-var
|
||||
<span style="color:rgb(85,85,255)">Traversals on graphs:</span>
|
||||
<span style="color:rgb(187,0,187)">Id</span> <span style="color:rgb(187,0,187)">Depth</span> <span style="color:rgb(187,0,187)">Vertex collections</span> <span style="color:rgb(187,0,187)">Edge collections</span> <span style="color:rgb(187,0,187)">Options</span> <span style="color:rgb(187,0,187)">Filter conditions</span>
|
||||
2 1..3 <span style="color:rgb(187,0,0)">circles</span> <span style="color:rgb(187,0,0)">edges</span> <span style="color:rgb(0,187,187)">uniqueVertices</span>: <span style="color:rgb(0,187,0)">none</span>, <span style="color:rgb(0,187,187)">uniqueEdges</span>: <span style="color:rgb(0,187,0)">path</span>
|
||||
|
||||
<span style="color:rgb(85,85,255)">Optimization rules applied:</span>
|
||||
<span style="color:rgb(187,0,187)">Id</span> <span style="color:rgb(187,0,187)">RuleName</span>
|
||||
<span style="color:rgb(187,187,0)">1</span> <span style="color:rgb(0,187,187)">move-calculations-up</span>
|
||||
<span style="color:rgb(187,187,0)">2</span> <span style="color:rgb(0,187,187)">optimize-traversals</span>
|
||||
<span style="color:rgb(187,187,0)">3</span> <span style="color:rgb(0,187,187)">move-calculations-down</span>
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
shell> curl --dump - http://localhost:8529/redirectMe
|
||||
|
||||
HTTP/1.1 301 Moved Permanently
|
||||
x-content-type-options: nosniff
|
||||
content-type: text/html
|
||||
x-content-type-options: nosniff
|
||||
location: /somewhere.else/
|
||||
|
||||
"<span class="hljs-tag"><<span class="hljs-name">html</span>></span><span class="hljs-tag"><<span class="hljs-name">head</span>></span><span class="hljs-tag"><<span class="hljs-name">title</span>></span>Moved<span class="hljs-tag"></<span class="hljs-name">title</span>></span><span class="hljs-tag"></<span class="hljs-name">head</span>></span><span class="hljs-tag"><<span class="hljs-name">body</span>></span><span class="hljs-tag"><<span class="hljs-name">h1</span>></span>Moved<span class="hljs-tag"></<span class="hljs-name">h1</span>></span><span class="hljs-tag"><<span class="hljs-name">p</span>></span>This page has moved to <span class="hljs-tag"><<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">\</span>"/<span class="hljs-attr">somewhere.else</span>/\"></span>/somewhere.else/<span class="hljs-tag"></<span class="hljs-name">a</span>></span>.<span class="hljs-tag"></<span class="hljs-name">p</span>></span><span class="hljs-tag"></<span class="hljs-name">body</span>></span><span class="hljs-tag"></<span class="hljs-name">html</span>></span>"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
shell> curl --dump - http://localhost:8529/_api/replication/dump?collection=testCollection
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
x-content-type-options: nosniff
|
||||
content-type: application/x-arango-dump; charset=utf-8
|
||||
x-arango-replication-checkmore: false
|
||||
x-content-type-options: nosniff
|
||||
x-arango-replication-lastincluded: 0
|
||||
x-arango-replication-checkmore: false
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
shell> curl -X DELETE --dump - http://localhost:8529/_api/view/15056
|
||||
|
||||
HTTP/<span class="hljs-number">1.1</span> <span class="hljs-number">200</span> OK
|
||||
content-type: application/json; charset=utf<span class="hljs-number">-8</span>
|
||||
x-content-type-options: nosniff
|
||||
|
||||
{
|
||||
<span class="hljs-string">"error"</span> : <span class="hljs-literal">false</span>,
|
||||
<span class="hljs-string">"code"</span> : <span class="hljs-number">200</span>,
|
||||
<span class="hljs-string">"result"</span> : <span class="hljs-literal">true</span>
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
shell> curl --dump - http://localhost:8529/_api/view/15071/properties
|
||||
|
||||
HTTP/<span class="hljs-number">1.1</span> <span class="hljs-number">200</span> OK
|
||||
content-type: application/json; charset=utf<span class="hljs-number">-8</span>
|
||||
x-content-type-options: nosniff
|
||||
|
||||
{
|
||||
<span class="hljs-string">"collections"</span> : [ ],
|
||||
<span class="hljs-string">"commit"</span> : {
|
||||
<span class="hljs-string">"cleanupIntervalStep"</span> : <span class="hljs-number">10</span>,
|
||||
<span class="hljs-string">"commitIntervalMsec"</span> : <span class="hljs-number">60000</span>,
|
||||
<span class="hljs-string">"commitTimeoutMsec"</span> : <span class="hljs-number">5000</span>,
|
||||
<span class="hljs-string">"consolidate"</span> : {
|
||||
<span class="hljs-string">"bytes"</span> : {
|
||||
<span class="hljs-string">"segmentThreshold"</span> : <span class="hljs-number">300</span>,
|
||||
<span class="hljs-string">"threshold"</span> : <span class="hljs-number">0.8500000238418579</span>
|
||||
},
|
||||
<span class="hljs-string">"bytes_accum"</span> : {
|
||||
<span class="hljs-string">"segmentThreshold"</span> : <span class="hljs-number">300</span>,
|
||||
<span class="hljs-string">"threshold"</span> : <span class="hljs-number">0.8500000238418579</span>
|
||||
},
|
||||
<span class="hljs-string">"count"</span> : {
|
||||
<span class="hljs-string">"segmentThreshold"</span> : <span class="hljs-number">300</span>,
|
||||
<span class="hljs-string">"threshold"</span> : <span class="hljs-number">0.8500000238418579</span>
|
||||
},
|
||||
<span class="hljs-string">"fill"</span> : {
|
||||
<span class="hljs-string">"segmentThreshold"</span> : <span class="hljs-number">300</span>,
|
||||
<span class="hljs-string">"threshold"</span> : <span class="hljs-number">0.8500000238418579</span>
|
||||
}
|
||||
}
|
||||
},
|
||||
<span class="hljs-string">"locale"</span> : <span class="hljs-string">"c.UTF-8"</span>,
|
||||
<span class="hljs-string">"threadsMaxIdle"</span> : <span class="hljs-number">5</span>,
|
||||
<span class="hljs-string">"threadsMaxTotal"</span> : <span class="hljs-number">5</span>,
|
||||
<span class="hljs-string">"links"</span> : {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
shell> curl -X POST --data-binary @- --dump - http://localhost:8529/_api/view <<EOF
|
||||
{
|
||||
<span class="hljs-string">"name"</span> : <span class="hljs-string">"testViewBasics"</span>,
|
||||
<span class="hljs-string">"type"</span> : <span class="hljs-string">"arangosearch"</span>,
|
||||
<span class="hljs-string">"properties"</span> : {
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
HTTP/<span class="hljs-number">1.1</span> <span class="hljs-number">201</span> Created
|
||||
content-type: application/json; charset=utf<span class="hljs-number">-8</span>
|
||||
x-content-type-options: nosniff
|
||||
|
||||
{
|
||||
<span class="hljs-string">"id"</span> : <span class="hljs-string">"15079"</span>,
|
||||
<span class="hljs-string">"name"</span> : <span class="hljs-string">"testViewBasics"</span>,
|
||||
<span class="hljs-string">"type"</span> : <span class="hljs-string">"arangosearch"</span>
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
shell> curl -X PUT --data-binary @- --dump - http://localhost:8529/_api/view/products1/rename <<EOF
|
||||
{
|
||||
<span class="hljs-string">"name"</span> : <span class="hljs-string">"viewNewName"</span>
|
||||
}
|
||||
EOF
|
||||
|
||||
HTTP/<span class="hljs-number">1.1</span> <span class="hljs-number">200</span> OK
|
||||
content-type: application/json; charset=utf<span class="hljs-number">-8</span>
|
||||
x-content-type-options: nosniff
|
||||
|
||||
{
|
||||
<span class="hljs-string">"id"</span> : <span class="hljs-string">"15081"</span>,
|
||||
<span class="hljs-string">"name"</span> : <span class="hljs-string">"viewNewName"</span>,
|
||||
<span class="hljs-string">"type"</span> : <span class="hljs-string">"arangosearch"</span>,
|
||||
<span class="hljs-string">"properties"</span> : {
|
||||
<span class="hljs-string">"collections"</span> : [ ],
|
||||
<span class="hljs-string">"commit"</span> : {
|
||||
<span class="hljs-string">"cleanupIntervalStep"</span> : <span class="hljs-number">10</span>,
|
||||
<span class="hljs-string">"commitIntervalMsec"</span> : <span class="hljs-number">60000</span>,
|
||||
<span class="hljs-string">"commitTimeoutMsec"</span> : <span class="hljs-number">5000</span>,
|
||||
<span class="hljs-string">"consolidate"</span> : {
|
||||
<span class="hljs-string">"bytes"</span> : {
|
||||
<span class="hljs-string">"segmentThreshold"</span> : <span class="hljs-number">300</span>,
|
||||
<span class="hljs-string">"threshold"</span> : <span class="hljs-number">0.8500000238418579</span>
|
||||
},
|
||||
<span class="hljs-string">"bytes_accum"</span> : {
|
||||
<span class="hljs-string">"segmentThreshold"</span> : <span class="hljs-number">300</span>,
|
||||
<span class="hljs-string">"threshold"</span> : <span class="hljs-number">0.8500000238418579</span>
|
||||
},
|
||||
<span class="hljs-string">"count"</span> : {
|
||||
<span class="hljs-string">"segmentThreshold"</span> : <span class="hljs-number">300</span>,
|
||||
<span class="hljs-string">"threshold"</span> : <span class="hljs-number">0.8500000238418579</span>
|
||||
},
|
||||
<span class="hljs-string">"fill"</span> : {
|
||||
<span class="hljs-string">"segmentThreshold"</span> : <span class="hljs-number">300</span>,
|
||||
<span class="hljs-string">"threshold"</span> : <span class="hljs-number">0.8500000238418579</span>
|
||||
}
|
||||
}
|
||||
},
|
||||
<span class="hljs-string">"locale"</span> : <span class="hljs-string">"C"</span>,
|
||||
<span class="hljs-string">"threadsMaxIdle"</span> : <span class="hljs-number">5</span>,
|
||||
<span class="hljs-string">"threadsMaxTotal"</span> : <span class="hljs-number">5</span>,
|
||||
<span class="hljs-string">"links"</span> : {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,2 +1,2 @@
|
|||
arangosh> db._collection(<span class="hljs-string">"demo"</span>);
|
||||
[ArangoCollection <span class="hljs-number">92</span>, <span class="hljs-string">"demo"</span> (type <span class="hljs-built_in">document</span>, status loaded)]
|
||||
[ArangoCollection <span class="hljs-number">88</span>, <span class="hljs-string">"demo"</span> (type <span class="hljs-built_in">document</span>, status loaded)]
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
arangosh> db._collection(<span class="hljs-string">"demo"</span>);
|
||||
[ArangoCollection <span class="hljs-number">92</span>, <span class="hljs-string">"demo"</span> (type <span class="hljs-built_in">document</span>, status loaded)]
|
||||
[ArangoCollection <span class="hljs-number">88</span>, <span class="hljs-string">"demo"</span> (type <span class="hljs-built_in">document</span>, status loaded)]
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
arangosh> db.five.all().limit(<span class="hljs-number">2</span>).count(<span class="hljs-literal">true</span>);
|
||||
<span class="hljs-number">2</span>
|
||||
<span class="hljs-literal">null</span>
|
||||
|
|
|
@ -7,17 +7,17 @@ arangosh> graph._commonNeighbors({<span class="hljs-attr">isCapital</span> :
|
|||
<span class="hljs-string">"right"</span> : <span class="hljs-string">"frenchCity/Paris"</span>,
|
||||
<span class="hljs-string">"neighbors"</span> : [
|
||||
<span class="hljs-string">"frenchCity/Lyon"</span>,
|
||||
<span class="hljs-string">"germanCity/Cologne"</span>,
|
||||
<span class="hljs-string">"germanCity/Hamburg"</span>
|
||||
<span class="hljs-string">"germanCity/Hamburg"</span>,
|
||||
<span class="hljs-string">"germanCity/Cologne"</span>
|
||||
]
|
||||
},
|
||||
{
|
||||
<span class="hljs-string">"left"</span> : <span class="hljs-string">"frenchCity/Paris"</span>,
|
||||
<span class="hljs-string">"right"</span> : <span class="hljs-string">"germanCity/Berlin"</span>,
|
||||
<span class="hljs-string">"neighbors"</span> : [
|
||||
<span class="hljs-string">"germanCity/Cologne"</span>,
|
||||
<span class="hljs-string">"germanCity/Hamburg"</span>,
|
||||
<span class="hljs-string">"frenchCity/Lyon"</span>,
|
||||
<span class="hljs-string">"germanCity/Hamburg"</span>
|
||||
<span class="hljs-string">"germanCity/Cologne"</span>
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -10,16 +10,16 @@ arangosh> graph._commonNeighbors(
|
|||
<span class="hljs-string">"left"</span> : <span class="hljs-string">"germanCity/Hamburg"</span>,
|
||||
<span class="hljs-string">"right"</span> : <span class="hljs-string">"germanCity/Cologne"</span>,
|
||||
<span class="hljs-string">"neighbors"</span> : [
|
||||
<span class="hljs-string">"frenchCity/Lyon"</span>,
|
||||
<span class="hljs-string">"frenchCity/Paris"</span>
|
||||
<span class="hljs-string">"frenchCity/Paris"</span>,
|
||||
<span class="hljs-string">"frenchCity/Lyon"</span>
|
||||
]
|
||||
},
|
||||
{
|
||||
<span class="hljs-string">"left"</span> : <span class="hljs-string">"germanCity/Hamburg"</span>,
|
||||
<span class="hljs-string">"right"</span> : <span class="hljs-string">"germanCity/Berlin"</span>,
|
||||
<span class="hljs-string">"neighbors"</span> : [
|
||||
<span class="hljs-string">"frenchCity/Lyon"</span>,
|
||||
<span class="hljs-string">"frenchCity/Paris"</span>,
|
||||
<span class="hljs-string">"frenchCity/Lyon"</span>,
|
||||
<span class="hljs-string">"germanCity/Cologne"</span>
|
||||
]
|
||||
},
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
shell> curl -X POST --header 'x-arango-async: store' --data-binary @- --dump - http://localhost:8529/_api/transaction <<EOF
|
||||
{
|
||||
<span class="hljs-string">"collections"</span> : {
|
||||
<span class="hljs-string">"read"</span> : [
|
||||
<span class="hljs-string">"_frontend"</span>
|
||||
]
|
||||
},
|
||||
<span class="hljs-string">"action"</span> : <span class="hljs-string">"function () {require('internal').sleep(15.0);}"</span>
|
||||
}
|
||||
EOF
|
||||
|
||||
HTTP/1.1 202 Accepted
|
||||
content-type: text/plain; charset=utf-8
|
||||
x-content-type-options: nosniff
|
||||
x-arango-async-id: 152098435649405
|
||||
|
||||
shell> curl --dump - http://localhost:8529/_api/job/152098435649405
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
content-type: text/plain; charset=utf-8
|
||||
x-content-type-options: nosniff
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
@Q:
|
||||
FOR u IN users
|
||||
FILTER u.active == <span class="hljs-literal">true</span>
|
||||
LIMIT <span class="hljs-number">0</span>, <span class="hljs-number">4</span>
|
||||
FOR f IN relations
|
||||
FILTER f.type == @friend && f.friendOf == u.userId
|
||||
RETURN {
|
||||
<span class="hljs-string">"user"</span> : u.name,
|
||||
<span class="hljs-string">"friendId"</span> : f.thisUser
|
||||
}
|
||||
@B
|
||||
{
|
||||
<span class="hljs-string">"friend"</span>: <span class="hljs-string">"friend"</span>
|
||||
}
|
||||
@R
|
||||
[
|
||||
{
|
||||
<span class="hljs-string">"user"</span>: <span class="hljs-string">"Abigail"</span>,
|
||||
<span class="hljs-string">"friendId"</span>: <span class="hljs-number">2</span>
|
||||
},
|
||||
{
|
||||
<span class="hljs-string">"user"</span>: <span class="hljs-string">"Abigail"</span>,
|
||||
<span class="hljs-string">"friendId"</span>: <span class="hljs-number">3</span>
|
||||
},
|
||||
{
|
||||
<span class="hljs-string">"user"</span>: <span class="hljs-string">"Abigail"</span>,
|
||||
<span class="hljs-string">"friendId"</span>: <span class="hljs-number">4</span>
|
||||
},
|
||||
{
|
||||
<span class="hljs-string">"user"</span>: <span class="hljs-string">"Mary"</span>,
|
||||
<span class="hljs-string">"friendId"</span>: <span class="hljs-number">1</span>
|
||||
},
|
||||
{
|
||||
<span class="hljs-string">"user"</span>: <span class="hljs-string">"Mary"</span>,
|
||||
<span class="hljs-string">"friendId"</span>: <span class="hljs-number">4</span>
|
||||
},
|
||||
{
|
||||
<span class="hljs-string">"user"</span>: <span class="hljs-string">"Mariah"</span>,
|
||||
<span class="hljs-string">"friendId"</span>: <span class="hljs-number">1</span>
|
||||
},
|
||||
{
|
||||
<span class="hljs-string">"user"</span>: <span class="hljs-string">"Mariah"</span>,
|
||||
<span class="hljs-string">"friendId"</span>: <span class="hljs-number">2</span>
|
||||
},
|
||||
{
|
||||
<span class="hljs-string">"user"</span>: <span class="hljs-string">"Fred"</span>,
|
||||
<span class="hljs-string">"friendId"</span>: <span class="hljs-number">5</span>
|
||||
},
|
||||
{
|
||||
<span class="hljs-string">"user"</span>: <span class="hljs-string">"Fred"</span>,
|
||||
<span class="hljs-string">"friendId"</span>: <span class="hljs-number">2</span>
|
||||
}
|
||||
]
|
|
@ -1,3 +1,12 @@
|
|||
- [Other Licenses](#other-licenses)
|
||||
* [C/C++ Libraries](#cc-libraries)
|
||||
* [Programs](#programs)
|
||||
* [Javascript](#javascript)
|
||||
+ [Node core modules](#node-core-modules)
|
||||
+ [Bundled NPM modules](#bundled-npm-modules)
|
||||
+ [Backend libraries](#backend-libraries)
|
||||
+ [Frontend libraries](#frontend-libraries)
|
||||
|
||||
# Other Licenses
|
||||
|
||||
## C/C++ Libraries
|
||||
|
@ -176,10 +185,10 @@ exception from the GPL license:
|
|||
* Project Home: https://github.com/chalk/ansi-styles#readme
|
||||
* License: [MIT License](https://github.com/arangodb/arangodb/blob/devel/js/node/node_modules/chalk/node_modules/ansi-styles/package.json)
|
||||
|
||||
#### ansi-styles
|
||||
#### ansi_up
|
||||
|
||||
* Project Home: https://github.com/chalk/ansi-styles#readme
|
||||
* License: [MIT License](https://github.com/arangodb/arangodb/blob/devel/js/node/node_modules/eslint/node_modules/ansi-styles/package.json)
|
||||
* Project Home: https://github.com/drudru/ansi_up
|
||||
* License: [MIT License](https://github.com/drudru/ansi_up#license)
|
||||
|
||||
#### aqb
|
||||
|
||||
|
|
|
@ -655,8 +655,8 @@ Here is how its details work:
|
|||
- all code in between is executed as javascript in the **arangosh** while talking to a valid **arangod**.
|
||||
You may inspect the generated js code in `/tmp/arangosh.examples.js`
|
||||
|
||||
OUTPUT and RUN specifics
|
||||
---------------------------
|
||||
OUTPUT, RUN and AQL specifics
|
||||
-----------------------------
|
||||
By default, Examples should be self contained and thus not depend on each other. They should clean up the collections they create.
|
||||
Building will fail if resources aren't cleaned.
|
||||
However, if you intend a set of OUTPUT and RUN to demonstrate interactively and share generated *ids*, you have to use an alphabetical
|
||||
|
@ -694,6 +694,14 @@ sortable naming scheme so they're executed in sequence. Using `<modulename>_<seq
|
|||
* output the plain text to dump to the user: `logRawResponse(response);`
|
||||
* dump the reply to the errorlog for testing (will mark run as failed): `logErrorResponse(response);`
|
||||
|
||||
- AQL is intended to contain AQL queries that can be pasted into arangosh or the webinterfaces query editor.
|
||||
Usually this query references an example dataset generator in `js/common/modules/@arangodb/examples/examples.js`
|
||||
which the users can also invoke to generate the data in their installation.
|
||||
This sort of example consists of three parts:
|
||||
- @DATASET{datasetName} - the name of the dataset in the above mentioned `examples.js` to be instanciated before executing this query.
|
||||
- @EXPLAIN{TRUE|FALSE} - print execution plan of the AQL query. The default is `FALSE`.
|
||||
- A following AQL query which may either end at the end of the comment block, or at the optional next section:
|
||||
- @BV - verbatim object containing the bind parameters to be passed into the query. Will also be put into the generated snippet.
|
||||
|
||||
Swagger integration
|
||||
===================
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
// //////////////////////////////////////////////////////////////////////////////
|
||||
// / @brief example-users
|
||||
// /
|
||||
// / @file
|
||||
// /
|
||||
// / DISCLAIMER
|
||||
// /
|
||||
// / Copyright 2014 triagens GmbH, Cologne, Germany
|
||||
// /
|
||||
// / Licensed under the Apache License, Version 2.0 (the "License")
|
||||
// / you may not use this file except in compliance with the License.
|
||||
// / You may obtain a copy of the License at
|
||||
// /
|
||||
// / http://www.apache.org/licenses/LICENSE-2.0
|
||||
// /
|
||||
// / Unless required by applicable law or agreed to in writing, software
|
||||
// / distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// / WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// / See the License for the specific language governing permissions and
|
||||
// / limitations under the License.
|
||||
// /
|
||||
// / Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
// /
|
||||
// / @author Wilfried Goesgens
|
||||
// / @author Copyright 2018, ArangoDB Inc
|
||||
// //////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
let db = require("internal").db;
|
||||
let examples = require("@arangodb/graph-examples/example-graph.js");
|
||||
|
||||
exports.Examples = {
|
||||
'traversalGraph': {
|
||||
createDS: function() {
|
||||
examples.loadGraph("traversalGraph");
|
||||
},
|
||||
removeDS: function() {
|
||||
examples.dropGraph("traversalGraph");
|
||||
}
|
||||
},
|
||||
'joinSampleDataset': {
|
||||
createDS: function() {
|
||||
db._create("users");
|
||||
db._create("relations");
|
||||
|
||||
[ [1, "Abigail", true ],
|
||||
[2, "Fred", true ],
|
||||
[3, "Mary", true ],
|
||||
[4, "Mariah", true ],
|
||||
[5, "John", false]
|
||||
].forEach(function (v) {
|
||||
db.users.save( {
|
||||
_key: v[1],
|
||||
name: v[1],
|
||||
active: v[2],
|
||||
userId: v[0]
|
||||
});
|
||||
});
|
||||
|
||||
[
|
||||
[1,2,"friend"],
|
||||
[1,3,"friend"],
|
||||
[1,4,"friend"],
|
||||
[2,5,"friend"],
|
||||
[2,2,"friend"],
|
||||
[3,4,"friend"],
|
||||
[3,1,"friend"],
|
||||
[4,1,"friend"],
|
||||
[4,2,"friend"]
|
||||
].forEach(function (v) {
|
||||
db.relations.save( {
|
||||
type: v[2],
|
||||
friendOf: v[0],
|
||||
thisUser: v[1]
|
||||
});
|
||||
});
|
||||
},
|
||||
removeDS: function() {
|
||||
try {
|
||||
db._drop("users");
|
||||
} catch (e) {}
|
||||
try {
|
||||
db._drop("relations");
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
};
|
|
@ -0,0 +1,2 @@
|
|||
node_modules
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
SOURCE = *.ts
|
||||
TESTS = test/*.js
|
||||
REPORTER = dot
|
||||
|
||||
typescript:
|
||||
./node_modules/.bin/tsc -p .
|
||||
cat ./umd.header ./dist/ansi_up.js ./umd.footer > ansi_up.js
|
||||
mv ./dist/ansi_up.js ./dist/ansi_up.js.include
|
||||
|
||||
test:
|
||||
@NODE_ENV=test ./node_modules/.bin/mocha \
|
||||
--require should \
|
||||
--reporter $(REPORTER) \
|
||||
$(TESTS)
|
||||
|
||||
test_verbose:
|
||||
@NODE_ENV=test ./node_modules/.bin/mocha \
|
||||
--require should \
|
||||
--reporter spec \
|
||||
$(TESTS)
|
||||
|
||||
clean:
|
||||
rm -rf ./node_modules ansi_up.js
|
||||
|
||||
.PHONY: test
|
|
@ -0,0 +1,220 @@
|
|||
# ansi_up.js
|
||||
|
||||
__ansi_up__ is a simple, easy to use library that provides a streaming API to
|
||||
transform text containing
|
||||
[ANSI color escape codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) into proper HTML.
|
||||
It can also transform any text that looks like a URL into an HTML anchor tag.
|
||||
|
||||
This module is a single Javascript file with no dependencies. It is a UMD style module so it
|
||||
can be utilized in a browser, in node.js (CommonJS), or with AMD (require.js). The source code
|
||||
was compiled from TypeScript and its type description ships with the NPM. This code has been used in production since 2011 and is actively maintained.
|
||||
|
||||
For example, turn this terminal output:
|
||||
|
||||
ESC[1;Foreground
|
||||
[1;30m 30 [1;30m 30 [1;30m 30 [1;30m 30 [1;30m 30 [1;30m 30 [1;30m 30 [1;30m 30 [0m
|
||||
[1;31m 31 [1;31m 31 [1;31m 31 [1;31m 31 [1;31m 31 [1;31m 31 [1;31m 31 [1;31m 31 [0m
|
||||
[1;32m 32 [1;32m 32 [1;32m 32 [1;32m 32 [1;32m 32 [1;32m 32 [1;32m 32 [1;32m 32 [0m
|
||||
...
|
||||
|
||||
...into this browser output:
|
||||
|
||||

|
||||
|
||||
|
||||
## Browser Example
|
||||
|
||||
```HTML
|
||||
<script src="ansi_up.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
var txt = "\n\n\033[1;33;40m 33;40 \033[1;33;41m 33;41 \033[1;33;42m 33;42 \033[1;33;43m 33;43 \033[1;33;44m 33;44 \033[1;33;45m 33;45 \033[1;33;46m 33;46 \033[1m\033[0\n\n\033[1;33;42m >> Tests OK\n\n"
|
||||
|
||||
var ansi_up = new AnsiUp;
|
||||
|
||||
var html = ansi_up.ansi_to_html(txt);
|
||||
|
||||
var cdiv = document.getElementById("console");
|
||||
|
||||
cdiv.innerHTML = html;
|
||||
|
||||
</script>
|
||||
```
|
||||
|
||||
## Node Example
|
||||
|
||||
```JavaScript
|
||||
var AU = require('ansi_up');
|
||||
var ansi_up = new AU.default;
|
||||
|
||||
var txt = "\n\n\033[1;33;40m 33;40 \033[1;33;41m 33;41 \033[1;33;42m 33;42 \033[1;33;43m 33;43 \033[1;33;44m 33;44 \033[1;33;45m 33;45 \033[1;33;46m 33;46 \033[1m\033[0\n\n\033[1;33;42m >> Tests OK\n\n"
|
||||
|
||||
var html = ansi_up.ansi_to_html(txt);
|
||||
```
|
||||
|
||||
More examples are in the 'examples' directory in the repo.
|
||||
|
||||
## Installation
|
||||
|
||||
$ npm install ansi_up
|
||||
|
||||
## Versions
|
||||
|
||||
Version 2.x is the latest stateful, streaming version of the API. It is simpler and more correct.
|
||||
Version 1.3.0 was the last of the older, deprecated API.
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. Use whatever module system to import the _ansi_up_ module.
|
||||
2. Instantiate the object.
|
||||
3. For every piece of input that arrives, call **ansi_to_html**.
|
||||
4. Append the emitted HTML to the previous HTML already emitted.
|
||||
|
||||
|
||||
## API Methods
|
||||
|
||||
In order to use _ansi_up_, you must Instantiate an object using your given module
|
||||
system.
|
||||
|
||||
#### ansi_to_html (txt)
|
||||
|
||||
This replaces ANSI terminal escape codes with SPAN tags that wrap the content. See the example output above.
|
||||
|
||||
This function only interprets ANSI SGR (Select Graphic Rendition) codes that can be represented in HTML. For example, cursor movement codes are ignored and hidden from output.
|
||||
|
||||
The default style uses colors that are very close to the prescribed standard. The standard assumes that the text will have a black background. These colors are set as inline styles on the SPAN tags. Another option is to set 'use_classes: true' in the options argument. This will instead set classes on the spans so the colors can be set via CSS. The class names used are of the format ````ansi-*-fg/bg```` and ````ansi-bright-*-fg/bg```` where * is the colour name, i.e black/red/green/yellow/blue/magenta/cyan/white. See the examples directory for a complete CSS theme for these classes.
|
||||
|
||||
#### ansi_to_text (txt)
|
||||
|
||||
This simply removes the ANSI escape codes from the stream.
|
||||
No escaping is done.
|
||||
|
||||
#### linkify(txt)
|
||||
|
||||
This replaces any links in the text with anchor tags that display the link.
|
||||
Only strings starting with 'http' or 'https', and surrounded by whitespace are
|
||||
considered valid patterns.
|
||||
You should only call this method if you can guarantee that the full URL
|
||||
will be passed into ansi_to_html(). If the URL is split along a buffer
|
||||
boundary, then the wrong URL will be 'linkified'.
|
||||
|
||||
## Properties
|
||||
|
||||
#### escape_for_html
|
||||
(default: true)
|
||||
|
||||
This does the minimum escaping of text to make it compliant with HTML.
|
||||
In particular, the '&','<', and '>' characters are escaped.
|
||||
|
||||
|
||||
#### use_classes
|
||||
(default: false)
|
||||
|
||||
This causes the SPAN tags to use class names for the color style instead
|
||||
of specified RGB values.
|
||||
|
||||
## API Overview
|
||||
|
||||
On a high level, _ansi_up_ takes a stream of text and transforms it proper HTML with colors.
|
||||
It does this by buffering the data and performing multiple passes over the
|
||||
stream. Each time it consumes data, it may or may not emit HTML. This HTML will always be
|
||||
proper HTML.
|
||||
|
||||
Because this process requires buffering (ie. stateful), you must insantiate an _ansi_up_ object
|
||||
in order to begin. Also, text may be received later that is styled by a previous.
|
||||
|
||||
The first pass converts characters that are unsafe for HTML into their equivalents. It will only
|
||||
convert '&', '<', and '>' characters. This pass is optional, and is on by default.
|
||||
|
||||
The second pass converts any ANSI color sequences to HTML spans. It does this by recognizing
|
||||
what is termed as ANSI **SGR** codes. All ANSI sequences (SGR and non-SGR) are removed from the
|
||||
output stream. The SGR codes create HTML **SPAN** tags to surround text that is styled by those
|
||||
codes. If the ANSI sequence is incomplete, it will be held in _ansi_up_'s internal buffer
|
||||
until new data is received to complete it.
|
||||
|
||||
The third and final pass transforms URLs to HTML anchors. This will also buffer output until a non URL
|
||||
character is received. This pass is optional, and is off by default.
|
||||
|
||||
|
||||
### Recommended Style of Use
|
||||
|
||||
There are two ways to stream this data to a web page. A push model or a pull model.
|
||||
|
||||
I have personally used a pull model to 'tail' a file.
|
||||
|
||||
In my 'pull' model, I had a process generating a log file on a remote machine.
|
||||
I had a web server running on the same machine. I developed a simple page
|
||||
that used AJAX to poll the web server periodically. Specifically I used an
|
||||
HTTP/1.1 GET request with RFC 7233 Range query. The server would return
|
||||
either range response.
|
||||
|
||||
I would then process each chunk received with _ansi_up_, and append the new
|
||||
spans to the innerHTML of a PRE tag.
|
||||
|
||||
|
||||
### UTF8 note
|
||||
|
||||
One last important note, _ansi_up_ takes its input in the form of a Javascript string.
|
||||
These strings are UTF8. When you take the output of some program and send it to
|
||||
Javascript, there will be buffering. Be sure to not send incomplete UTF8 sequences or
|
||||
Javascript will ignore or drop the sequence from the stream when it converts it to a
|
||||
string.
|
||||
|
||||
|
||||
_ansi_up_ should be called via the functions defined on the module. It is recommended that the HTML is rendered with a monospace font and black background. See the examples, for a basic theme as a CSS definition.
|
||||
At the same, it also properly escapes HTML unsafe characters (&,<,>,etc.) into their proper HTML representation.
|
||||
|
||||
|
||||
## Building
|
||||
|
||||
To build, a simple Makefile handles it all.
|
||||
|
||||
```shell
|
||||
$ make
|
||||
```
|
||||
|
||||
## Running tests
|
||||
|
||||
To run the tests for _ansi_up_, run `npm install` to install dev dependencies. Then:
|
||||
|
||||
```shell
|
||||
$ make test
|
||||
```
|
||||
|
||||
## Credits
|
||||
|
||||
This code was developed by Dru Nelson (<https://github.com/drudru>).
|
||||
|
||||
Thanks goes to the following contributors for their patches:
|
||||
|
||||
- AIZAWA Hina (<https://github.com/fetus-hina>)
|
||||
- James R. White (<https://github.com/jamesrwhite>)
|
||||
- Aaron Stone (<https://github.com/sodabrew>)
|
||||
- Maximilian Antoni (<https://github.com/mantoni>)
|
||||
- Jim Bauwens (<https://github.com/jimbauwens>)
|
||||
- Jacek Jędrzejewski (<https://github.com/eXtreme>)
|
||||
|
||||
## License
|
||||
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2011 Dru Nelson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,334 @@
|
|||
/* ansi_up.js
|
||||
* author : Dru Nelson
|
||||
* license : MIT
|
||||
* http://github.com/drudru/ansi_up
|
||||
*/
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define(['exports'], factory);
|
||||
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
|
||||
// CommonJS
|
||||
factory(exports);
|
||||
} else {
|
||||
// Browser globals
|
||||
var exp = {};
|
||||
factory(exp);
|
||||
root.AnsiUp = exp.default;
|
||||
}
|
||||
}(this, function (exports) {
|
||||
"use strict";
|
||||
function rgx(tmplObj) {
|
||||
var subst = [];
|
||||
for (var _i = 1; _i < arguments.length; _i++) {
|
||||
subst[_i - 1] = arguments[_i];
|
||||
}
|
||||
var regexText = tmplObj.raw[0];
|
||||
var wsrgx = /^\s+|\s+\n|\s+#[\s\S]+?\n/gm;
|
||||
var txt2 = regexText.replace(wsrgx, '');
|
||||
return new RegExp(txt2, 'm');
|
||||
}
|
||||
var AnsiUp = (function () {
|
||||
function AnsiUp() {
|
||||
this.VERSION = "2.0.2";
|
||||
this.ansi_colors = [
|
||||
[
|
||||
{ rgb: [0, 0, 0], class_name: "ansi-black" },
|
||||
{ rgb: [187, 0, 0], class_name: "ansi-red" },
|
||||
{ rgb: [0, 187, 0], class_name: "ansi-green" },
|
||||
{ rgb: [187, 187, 0], class_name: "ansi-yellow" },
|
||||
{ rgb: [0, 0, 187], class_name: "ansi-blue" },
|
||||
{ rgb: [187, 0, 187], class_name: "ansi-magenta" },
|
||||
{ rgb: [0, 187, 187], class_name: "ansi-cyan" },
|
||||
{ rgb: [255, 255, 255], class_name: "ansi-white" }
|
||||
],
|
||||
[
|
||||
{ rgb: [85, 85, 85], class_name: "ansi-bright-black" },
|
||||
{ rgb: [255, 85, 85], class_name: "ansi-bright-red" },
|
||||
{ rgb: [0, 255, 0], class_name: "ansi-bright-green" },
|
||||
{ rgb: [255, 255, 85], class_name: "ansi-bright-yellow" },
|
||||
{ rgb: [85, 85, 255], class_name: "ansi-bright-blue" },
|
||||
{ rgb: [255, 85, 255], class_name: "ansi-bright-magenta" },
|
||||
{ rgb: [85, 255, 255], class_name: "ansi-bright-cyan" },
|
||||
{ rgb: [255, 255, 255], class_name: "ansi-bright-white" }
|
||||
]
|
||||
];
|
||||
this.htmlFormatter = {
|
||||
transform: function (fragment, instance) {
|
||||
var txt = fragment.text;
|
||||
if (txt.length === 0)
|
||||
return txt;
|
||||
if (instance._escape_for_html)
|
||||
txt = instance.old_escape_for_html(txt);
|
||||
if (!fragment.bright && fragment.fg === null && fragment.bg === null)
|
||||
return txt;
|
||||
var styles = [];
|
||||
var classes = [];
|
||||
var fg = fragment.fg;
|
||||
var bg = fragment.bg;
|
||||
if (fg === null && fragment.bright)
|
||||
fg = instance.ansi_colors[1][7];
|
||||
if (!instance._use_classes) {
|
||||
if (fg)
|
||||
styles.push("color:rgb(" + fg.rgb.join(',') + ")");
|
||||
if (bg)
|
||||
styles.push("background-color:rgb(" + bg.rgb + ")");
|
||||
}
|
||||
else {
|
||||
if (fg) {
|
||||
if (fg.class_name !== 'truecolor') {
|
||||
classes.push(fg.class_name + "-fg");
|
||||
}
|
||||
else {
|
||||
styles.push("color:rgb(" + fg.rgb.join(',') + ")");
|
||||
}
|
||||
}
|
||||
if (bg) {
|
||||
if (bg.class_name !== 'truecolor') {
|
||||
classes.push(bg.class_name + "-bg");
|
||||
}
|
||||
else {
|
||||
styles.push("background-color:rgb(" + bg.rgb.join(',') + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
var class_string = '';
|
||||
var style_string = '';
|
||||
if (classes.length)
|
||||
class_string = " class=\"" + classes.join(' ') + "\"";
|
||||
if (styles.length)
|
||||
style_string = " style=\"" + styles.join(';') + "\"";
|
||||
return "<span" + class_string + style_string + ">" + txt + "</span>";
|
||||
},
|
||||
compose: function (segments, instance) {
|
||||
return segments.join("");
|
||||
}
|
||||
};
|
||||
this.textFormatter = {
|
||||
transform: function (fragment, instance) {
|
||||
return fragment.text;
|
||||
},
|
||||
compose: function (segments, instance) {
|
||||
return segments.join("");
|
||||
}
|
||||
};
|
||||
this.setup_256_palette();
|
||||
this._use_classes = false;
|
||||
this._escape_for_html = true;
|
||||
this.bright = false;
|
||||
this.fg = this.bg = null;
|
||||
this._buffer = '';
|
||||
}
|
||||
Object.defineProperty(AnsiUp.prototype, "use_classes", {
|
||||
get: function () {
|
||||
return this._use_classes;
|
||||
},
|
||||
set: function (arg) {
|
||||
this._use_classes = arg;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(AnsiUp.prototype, "escape_for_html", {
|
||||
get: function () {
|
||||
return this._escape_for_html;
|
||||
},
|
||||
set: function (arg) {
|
||||
this._escape_for_html = arg;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
AnsiUp.prototype.setup_256_palette = function () {
|
||||
var _this = this;
|
||||
this.palette_256 = [];
|
||||
this.ansi_colors.forEach(function (palette) {
|
||||
palette.forEach(function (rec) {
|
||||
_this.palette_256.push(rec);
|
||||
});
|
||||
});
|
||||
var levels = [0, 95, 135, 175, 215, 255];
|
||||
for (var r = 0; r < 6; ++r) {
|
||||
for (var g = 0; g < 6; ++g) {
|
||||
for (var b = 0; b < 6; ++b) {
|
||||
var col = { rgb: [levels[r], levels[g], levels[b]], class_name: 'truecolor' };
|
||||
this.palette_256.push(col);
|
||||
}
|
||||
}
|
||||
}
|
||||
var grey_level = 8;
|
||||
for (var i = 0; i < 24; ++i, grey_level += 10) {
|
||||
var gry = { rgb: [grey_level, grey_level, grey_level], class_name: 'truecolor' };
|
||||
this.palette_256.push(gry);
|
||||
}
|
||||
};
|
||||
AnsiUp.prototype.old_escape_for_html = function (txt) {
|
||||
return txt.replace(/[&<>]/gm, function (str) {
|
||||
if (str === "&")
|
||||
return "&";
|
||||
if (str === "<")
|
||||
return "<";
|
||||
if (str === ">")
|
||||
return ">";
|
||||
});
|
||||
};
|
||||
AnsiUp.prototype.old_linkify = function (txt) {
|
||||
return txt.replace(/(https?:\/\/[^\s]+)/gm, function (str) {
|
||||
return "<a href=\"" + str + "\">" + str + "</a>";
|
||||
});
|
||||
};
|
||||
AnsiUp.prototype.detect_incomplete_ansi = function (txt) {
|
||||
return !(/.*?[\x40-\x7e]/.test(txt));
|
||||
};
|
||||
AnsiUp.prototype.detect_incomplete_link = function (txt) {
|
||||
var found = false;
|
||||
for (var i = txt.length - 1; i > 0; i--) {
|
||||
if (/\s|\x1B/.test(txt[i])) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (/(https?:\/\/[^\s]+)/.test(txt))
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
var prefix = txt.substr(i + 1, 4);
|
||||
if (prefix.length === 0)
|
||||
return -1;
|
||||
if ("http".indexOf(prefix) === 0)
|
||||
return (i + 1);
|
||||
};
|
||||
AnsiUp.prototype.ansi_to = function (txt, formatter) {
|
||||
var pkt = this._buffer + txt;
|
||||
this._buffer = '';
|
||||
var raw_text_pkts = pkt.split(/\x1B\[/);
|
||||
if (raw_text_pkts.length === 1)
|
||||
raw_text_pkts.push('');
|
||||
this.handle_incomplete_sequences(raw_text_pkts);
|
||||
var first_chunk = this.with_state(raw_text_pkts.shift());
|
||||
var blocks = new Array(raw_text_pkts.length);
|
||||
for (var i = 0, len = raw_text_pkts.length; i < len; ++i) {
|
||||
blocks[i] = (formatter.transform(this.process_ansi(raw_text_pkts[i]), this));
|
||||
}
|
||||
if (first_chunk.text.length > 0)
|
||||
blocks.unshift(formatter.transform(first_chunk, this));
|
||||
return formatter.compose(blocks, this);
|
||||
};
|
||||
AnsiUp.prototype.ansi_to_html = function (txt) {
|
||||
return this.ansi_to(txt, this.htmlFormatter);
|
||||
};
|
||||
AnsiUp.prototype.ansi_to_text = function (txt) {
|
||||
return this.ansi_to(txt, this.textFormatter);
|
||||
};
|
||||
AnsiUp.prototype.with_state = function (text) {
|
||||
return { bright: this.bright, fg: this.fg, bg: this.bg, text: text };
|
||||
};
|
||||
AnsiUp.prototype.handle_incomplete_sequences = function (chunks) {
|
||||
var last_chunk = chunks[chunks.length - 1];
|
||||
if ((last_chunk.length > 0) && this.detect_incomplete_ansi(last_chunk)) {
|
||||
this._buffer = "\x1B[" + last_chunk;
|
||||
chunks.pop();
|
||||
chunks.push('');
|
||||
}
|
||||
else {
|
||||
if (last_chunk.slice(-1) === "\x1B") {
|
||||
this._buffer = "\x1B";
|
||||
console.log("raw", chunks);
|
||||
chunks.pop();
|
||||
chunks.push(last_chunk.substr(0, last_chunk.length - 1));
|
||||
console.log(chunks);
|
||||
console.log(last_chunk);
|
||||
}
|
||||
if (chunks.length === 2 &&
|
||||
chunks[1] === "" &&
|
||||
chunks[0].slice(-1) === "\x1B") {
|
||||
this._buffer = "\x1B";
|
||||
last_chunk = chunks.shift();
|
||||
chunks.unshift(last_chunk.substr(0, last_chunk.length - 1));
|
||||
}
|
||||
}
|
||||
};
|
||||
AnsiUp.prototype.process_ansi = function (block) {
|
||||
if (!this._sgr_regex) {
|
||||
this._sgr_regex = (_a = ["\n ^ # beginning of line\n ([!<-?]?) # a private-mode char (!, <, =, >, ?)\n ([d;]*) # any digits or semicolons\n ([ -/]? # an intermediate modifier\n [@-~]) # the command\n ([sS]*) # any text following this CSI sequence\n "], _a.raw = ["\n ^ # beginning of line\n ([!\\x3c-\\x3f]?) # a private-mode char (!, <, =, >, ?)\n ([\\d;]*) # any digits or semicolons\n ([\\x20-\\x2f]? # an intermediate modifier\n [\\x40-\\x7e]) # the command\n ([\\s\\S]*) # any text following this CSI sequence\n "], rgx(_a));
|
||||
}
|
||||
var matches = block.match(this._sgr_regex);
|
||||
if (!matches) {
|
||||
return this.with_state(block);
|
||||
}
|
||||
var orig_txt = matches[4];
|
||||
if (matches[1] !== '' || matches[3] !== 'm') {
|
||||
return this.with_state(orig_txt);
|
||||
}
|
||||
var sgr_cmds = matches[2].split(';');
|
||||
while (sgr_cmds.length > 0) {
|
||||
var sgr_cmd_str = sgr_cmds.shift();
|
||||
var num = parseInt(sgr_cmd_str, 10);
|
||||
if (isNaN(num) || num === 0) {
|
||||
this.fg = this.bg = null;
|
||||
this.bright = false;
|
||||
}
|
||||
else if (num === 1) {
|
||||
this.bright = true;
|
||||
}
|
||||
else if (num === 22) {
|
||||
this.bright = false;
|
||||
}
|
||||
else if (num === 39) {
|
||||
this.fg = null;
|
||||
}
|
||||
else if (num === 49) {
|
||||
this.bg = null;
|
||||
}
|
||||
else if ((num >= 30) && (num < 38)) {
|
||||
var bidx = this.bright ? 1 : 0;
|
||||
this.fg = this.ansi_colors[bidx][(num - 30)];
|
||||
}
|
||||
else if ((num >= 90) && (num < 98)) {
|
||||
this.fg = this.ansi_colors[1][(num - 90)];
|
||||
}
|
||||
else if ((num >= 40) && (num < 48)) {
|
||||
this.bg = this.ansi_colors[0][(num - 40)];
|
||||
}
|
||||
else if ((num >= 100) && (num < 108)) {
|
||||
this.bg = this.ansi_colors[1][(num - 100)];
|
||||
}
|
||||
else if (num === 38 || num === 48) {
|
||||
if (sgr_cmds.length > 0) {
|
||||
var is_foreground = (num === 38);
|
||||
var mode_cmd = sgr_cmds.shift();
|
||||
if (mode_cmd === '5' && sgr_cmds.length > 0) {
|
||||
var palette_index = parseInt(sgr_cmds.shift(), 10);
|
||||
if (palette_index >= 0 && palette_index <= 255) {
|
||||
if (is_foreground)
|
||||
this.fg = this.palette_256[palette_index];
|
||||
else
|
||||
this.bg = this.palette_256[palette_index];
|
||||
}
|
||||
}
|
||||
if (mode_cmd === '2' && sgr_cmds.length > 2) {
|
||||
var r = parseInt(sgr_cmds.shift(), 10);
|
||||
var g = parseInt(sgr_cmds.shift(), 10);
|
||||
var b = parseInt(sgr_cmds.shift(), 10);
|
||||
if ((r >= 0 && r <= 255) && (g >= 0 && g <= 255) && (b >= 0 && b <= 255)) {
|
||||
var c = { rgb: [r, g, b], class_name: 'truecolor' };
|
||||
if (is_foreground)
|
||||
this.fg = c;
|
||||
else
|
||||
this.bg = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.with_state(orig_txt);
|
||||
var _a;
|
||||
};
|
||||
return AnsiUp;
|
||||
}());
|
||||
//# sourceMappingURL=ansi_up.js.map
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.default = AnsiUp;
|
||||
}));
|
|
@ -0,0 +1,487 @@
|
|||
/* ansi_up.js
|
||||
* author : Dru Nelson
|
||||
* license : MIT
|
||||
* http://github.com/drudru/ansi_up
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
interface AU_Color
|
||||
{
|
||||
rgb:number[];
|
||||
class_name:string;
|
||||
}
|
||||
|
||||
// Represents the output of process_ansi(): a snapshot of the AnsiUp state machine
|
||||
// at a given point in time, which wraps a fragment of text. This wouuld allow deferred
|
||||
// processing of text fragments and colors, if ever needed.
|
||||
interface TextWithData {
|
||||
fg:AU_Color;
|
||||
bg:AU_Color;
|
||||
bright:boolean;
|
||||
text:string;
|
||||
}
|
||||
|
||||
// Represents an object that is responsible for generating output from parsed ANSI color
|
||||
// metadata and text content.
|
||||
interface Formatter {
|
||||
// Invoked for each generated TextWithData fragment outputted by process_ansi().
|
||||
// this function is responsible for generating output for a single TextWithData
|
||||
// fragment. The result of transform() will be collected into an array that will
|
||||
// be provided to compose().
|
||||
transform(fragment:TextWithData, instance:AnsiUp):any;
|
||||
|
||||
// Invoked on the set of outputs from transform; the return value of this function
|
||||
// will be the final output of ANSI processing.
|
||||
compose(segments:any[], instance:AnsiUp):any;
|
||||
}
|
||||
|
||||
// ES5 template string transformer
|
||||
// NOTE: default is multiline (workaround for now til I can
|
||||
// determine flags inline)
|
||||
function rgx(tmplObj, ...subst) {
|
||||
// Use the 'raw' value so we don't have to double backslash in a template string
|
||||
let regexText:string = tmplObj.raw[0];
|
||||
|
||||
// Remove white-space and comments
|
||||
let wsrgx = /^\s+|\s+\n|\s+#[\s\S]+?\n/gm;
|
||||
let txt2 = regexText.replace(wsrgx, '');
|
||||
return new RegExp(txt2, 'm');
|
||||
}
|
||||
|
||||
class AnsiUp
|
||||
{
|
||||
VERSION = "2.0.2";
|
||||
|
||||
ansi_colors =
|
||||
[
|
||||
// Normal colors
|
||||
[
|
||||
{ rgb: [ 0, 0, 0], class_name: "ansi-black" },
|
||||
{ rgb: [187, 0, 0], class_name: "ansi-red" },
|
||||
{ rgb: [ 0, 187, 0], class_name: "ansi-green" },
|
||||
{ rgb: [187, 187, 0], class_name: "ansi-yellow" },
|
||||
{ rgb: [ 0, 0, 187], class_name: "ansi-blue" },
|
||||
{ rgb: [187, 0, 187], class_name: "ansi-magenta" },
|
||||
{ rgb: [ 0, 187, 187], class_name: "ansi-cyan" },
|
||||
{ rgb: [255, 255, 255], class_name: "ansi-white" }
|
||||
],
|
||||
|
||||
// Bright colors
|
||||
[
|
||||
{ rgb: [ 85, 85, 85], class_name: "ansi-bright-black" },
|
||||
{ rgb: [255, 85, 85], class_name: "ansi-bright-red" },
|
||||
{ rgb: [ 0, 255, 0], class_name: "ansi-bright-green" },
|
||||
{ rgb: [255, 255, 85], class_name: "ansi-bright-yellow" },
|
||||
{ rgb: [ 85, 85, 255], class_name: "ansi-bright-blue" },
|
||||
{ rgb: [255, 85, 255], class_name: "ansi-bright-magenta" },
|
||||
{ rgb: [ 85, 255, 255], class_name: "ansi-bright-cyan" },
|
||||
{ rgb: [255, 255, 255], class_name: "ansi-bright-white" }
|
||||
]
|
||||
];
|
||||
|
||||
htmlFormatter:Formatter = {
|
||||
transform(fragment:TextWithData, instance:AnsiUp):string {
|
||||
let txt = fragment.text;
|
||||
|
||||
if (txt.length === 0)
|
||||
return txt;
|
||||
|
||||
if (instance._escape_for_html)
|
||||
txt = instance.old_escape_for_html(txt);
|
||||
|
||||
// If colors not set, default style is used
|
||||
if (!fragment.bright && fragment.fg === null && fragment.bg === null)
|
||||
return txt;
|
||||
|
||||
let styles:string[] = [];
|
||||
let classes:string[] = [];
|
||||
|
||||
let fg = fragment.fg;
|
||||
let bg = fragment.bg;
|
||||
|
||||
// Handle the case where we are told to be bright, but without a color
|
||||
if (fg === null && fragment.bright)
|
||||
fg = instance.ansi_colors[1][7];
|
||||
|
||||
if (!instance._use_classes) {
|
||||
// USE INLINE STYLES
|
||||
if (fg)
|
||||
styles.push(`color:rgb(${fg.rgb.join(',')})`);
|
||||
if (bg)
|
||||
styles.push(`background-color:rgb(${bg.rgb})`);
|
||||
} else {
|
||||
// USE CLASSES
|
||||
if (fg) {
|
||||
if (fg.class_name !== 'truecolor') {
|
||||
classes.push(`${fg.class_name}-fg`);
|
||||
} else {
|
||||
styles.push(`color:rgb(${fg.rgb.join(',')})`);
|
||||
}
|
||||
}
|
||||
if (bg) {
|
||||
if (bg.class_name !== 'truecolor') {
|
||||
classes.push(`${bg.class_name}-bg`);
|
||||
} else {
|
||||
styles.push(`background-color:rgb(${bg.rgb.join(',')})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let class_string = '';
|
||||
let style_string = '';
|
||||
|
||||
if (classes.length)
|
||||
class_string = ` class="${classes.join(' ')}"`;
|
||||
|
||||
if (styles.length)
|
||||
style_string = ` style="${styles.join(';')}"`;
|
||||
|
||||
return `<span${class_string}${style_string}>${txt}</span>`;
|
||||
},
|
||||
|
||||
compose(segments:string[], instance:AnsiUp):string {
|
||||
return segments.join("");
|
||||
}
|
||||
};
|
||||
|
||||
textFormatter:Formatter = {
|
||||
transform(fragment:TextWithData, instance:AnsiUp):string {
|
||||
return fragment.text;
|
||||
},
|
||||
|
||||
compose(segments:string[], instance:AnsiUp):string {
|
||||
return segments.join("");
|
||||
}
|
||||
};
|
||||
|
||||
// 256 Colors Palette
|
||||
// CSS RGB strings - ex. "255, 255, 255"
|
||||
private palette_256:AU_Color[];
|
||||
|
||||
private fg:AU_Color;
|
||||
private bg:AU_Color;
|
||||
private bright:boolean;
|
||||
|
||||
private _use_classes:boolean;
|
||||
private _escape_for_html;
|
||||
private _sgr_regex:RegExp;
|
||||
|
||||
private _buffer:string;
|
||||
|
||||
constructor()
|
||||
{
|
||||
this.setup_256_palette();
|
||||
this._use_classes = false;
|
||||
this._escape_for_html = true;
|
||||
|
||||
this.bright = false;
|
||||
this.fg = this.bg = null;
|
||||
|
||||
this._buffer = '';
|
||||
}
|
||||
|
||||
set use_classes(arg:boolean)
|
||||
{
|
||||
this._use_classes = arg;
|
||||
}
|
||||
|
||||
get use_classes():boolean
|
||||
{
|
||||
return this._use_classes;
|
||||
}
|
||||
|
||||
set escape_for_html(arg:boolean)
|
||||
{
|
||||
this._escape_for_html = arg;
|
||||
}
|
||||
|
||||
get escape_for_html():boolean
|
||||
{
|
||||
return this._escape_for_html;
|
||||
}
|
||||
|
||||
private setup_256_palette():void
|
||||
{
|
||||
this.palette_256 = [];
|
||||
|
||||
// Index 0..15 : Ansi-Colors
|
||||
this.ansi_colors.forEach( palette => {
|
||||
palette.forEach( rec => {
|
||||
this.palette_256.push(rec);
|
||||
});
|
||||
});
|
||||
|
||||
// Index 16..231 : RGB 6x6x6
|
||||
// https://gist.github.com/jasonm23/2868981#file-xterm-256color-yaml
|
||||
let levels = [0, 95, 135, 175, 215, 255];
|
||||
for (let r = 0; r < 6; ++r) {
|
||||
for (let g = 0; g < 6; ++g) {
|
||||
for (let b = 0; b < 6; ++b) {
|
||||
let col = {rgb:[levels[r], levels[g], levels[b]], class_name:'truecolor'};
|
||||
this.palette_256.push(col);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Index 232..255 : Grayscale
|
||||
let grey_level = 8;
|
||||
for (let i = 0; i < 24; ++i, grey_level += 10) {
|
||||
let gry = {rgb:[grey_level, grey_level, grey_level], class_name:'truecolor'};
|
||||
this.palette_256.push(gry);
|
||||
}
|
||||
}
|
||||
|
||||
private old_escape_for_html(txt:string):string
|
||||
{
|
||||
return txt.replace(/[&<>]/gm, (str) => {
|
||||
if (str === "&") return "&";
|
||||
if (str === "<") return "<";
|
||||
if (str === ">") return ">";
|
||||
});
|
||||
}
|
||||
|
||||
private old_linkify(txt:string):string
|
||||
{
|
||||
return txt.replace(/(https?:\/\/[^\s]+)/gm, (str) => {
|
||||
return `<a href="${str}">${str}</a>`;
|
||||
});
|
||||
}
|
||||
|
||||
private detect_incomplete_ansi(txt:string)
|
||||
{
|
||||
// Scan forwards for a potential command character
|
||||
// If one exists, we must assume we are good
|
||||
// [\x40-\x7e]) # the command
|
||||
|
||||
return !(/.*?[\x40-\x7e]/.test(txt));
|
||||
}
|
||||
|
||||
private detect_incomplete_link(txt:string)
|
||||
{
|
||||
// It would be nice if Javascript RegExp supported
|
||||
// a hitEnd() method
|
||||
|
||||
// Scan backwards for first whitespace
|
||||
var found = false;
|
||||
for (var i = txt.length - 1; i > 0; i--) {
|
||||
if (/\s|\x1B/.test(txt[i])) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
// Handle one other case
|
||||
// Maybe the whole string is a URL?
|
||||
if (/(https?:\/\/[^\s]+)/.test(txt))
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Test if possible prefix
|
||||
var prefix = txt.substr(i + 1, 4);
|
||||
|
||||
if (prefix.length === 0) return -1;
|
||||
|
||||
if ("http".indexOf(prefix) === 0)
|
||||
return (i + 1);
|
||||
}
|
||||
|
||||
ansi_to(txt:string, formatter:Formatter):any {
|
||||
var pkt = this._buffer + txt;
|
||||
this._buffer = '';
|
||||
|
||||
var raw_text_pkts = pkt.split(/\x1B\[/);
|
||||
|
||||
if (raw_text_pkts.length === 1)
|
||||
raw_text_pkts.push('');
|
||||
|
||||
this.handle_incomplete_sequences(raw_text_pkts);
|
||||
|
||||
let first_chunk = this.with_state(raw_text_pkts.shift()); // the first pkt is not the result of the split
|
||||
|
||||
let blocks = new Array(raw_text_pkts.length);
|
||||
for (let i = 0, len = raw_text_pkts.length; i < len; ++i) {
|
||||
blocks[i] = (formatter.transform(this.process_ansi(raw_text_pkts[i]), this));
|
||||
}
|
||||
|
||||
if (first_chunk.text.length > 0)
|
||||
blocks.unshift(formatter.transform(first_chunk, this));
|
||||
|
||||
return formatter.compose(blocks, this);
|
||||
}
|
||||
|
||||
ansi_to_html(txt:string):string
|
||||
{
|
||||
return this.ansi_to(txt, this.htmlFormatter);
|
||||
}
|
||||
|
||||
ansi_to_text(txt:string):string
|
||||
{
|
||||
return this.ansi_to(txt, this.textFormatter);
|
||||
}
|
||||
|
||||
private with_state(text:string):TextWithData {
|
||||
return { bright: this.bright, fg: this.fg, bg: this.bg, text: text };
|
||||
}
|
||||
|
||||
private handle_incomplete_sequences(chunks:string[]):void {
|
||||
// COMPLEX - BEGIN
|
||||
|
||||
// Validate the last chunks for:
|
||||
// - incomplete ANSI sequence
|
||||
// - incomplete ESC
|
||||
// If any of these occur, we may have to buffer
|
||||
var last_chunk = chunks[chunks.length - 1];
|
||||
|
||||
// - incomplete ANSI sequence
|
||||
if ((last_chunk.length > 0) && this.detect_incomplete_ansi(last_chunk)) {
|
||||
this._buffer = "\x1B[" + last_chunk;
|
||||
chunks.pop();
|
||||
chunks.push('');
|
||||
} else {
|
||||
// - incomplete ESC
|
||||
if (last_chunk.slice(-1) === "\x1B") {
|
||||
this._buffer = "\x1B";
|
||||
console.log("raw", chunks);
|
||||
chunks.pop();
|
||||
chunks.push(last_chunk.substr(0, last_chunk.length - 1));
|
||||
console.log(chunks);
|
||||
console.log(last_chunk);
|
||||
}
|
||||
// - Incomplete ESC, only one packet
|
||||
if (chunks.length === 2 &&
|
||||
chunks[1] === "" &&
|
||||
chunks[0].slice(-1) === "\x1B") {
|
||||
this._buffer = "\x1B";
|
||||
last_chunk = chunks.shift();
|
||||
chunks.unshift(last_chunk.substr(0, last_chunk.length - 1));
|
||||
}
|
||||
}
|
||||
|
||||
// COMPLEX - END
|
||||
}
|
||||
|
||||
private process_ansi(block:string):TextWithData
|
||||
{
|
||||
// This must only be called with a string that started with a CSI (the string split above)
|
||||
// The CSI must not be in the string. We consider this string to be a 'block'.
|
||||
// It has an ANSI command at the front that affects the text that follows it.
|
||||
//
|
||||
// All ansi codes are typically in the following format. We parse it and focus
|
||||
// specifically on the graphics commands (SGR)
|
||||
//
|
||||
// CONTROL-SEQUENCE-INTRODUCER CSI (ESC, '[')
|
||||
// PRIVATE-MODE-CHAR (!, <, >, ?)
|
||||
// Numeric parameters separated by semicolons ('0' - '9', ';')
|
||||
// Intermediate-modifiers (0x20 - 0x2f)
|
||||
// COMMAND-CHAR (0x40 - 0x7e)
|
||||
//
|
||||
// We use a regex to parse into capture groups the PRIVATE-MODE-CHAR to the COMMAND
|
||||
// and the following text
|
||||
|
||||
if (!this._sgr_regex) {
|
||||
// This regex is designed to parse an ANSI terminal CSI command. To be more specific,
|
||||
// we follow the XTERM conventions vs. the various other "standards".
|
||||
// http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
||||
//
|
||||
this._sgr_regex = rgx`
|
||||
^ # beginning of line
|
||||
([!\x3c-\x3f]?) # a private-mode char (!, <, =, >, ?)
|
||||
([\d;]*) # any digits or semicolons
|
||||
([\x20-\x2f]? # an intermediate modifier
|
||||
[\x40-\x7e]) # the command
|
||||
([\s\S]*) # any text following this CSI sequence
|
||||
`;
|
||||
}
|
||||
|
||||
let matches = block.match(this._sgr_regex);
|
||||
|
||||
// The regex should have handled all cases!
|
||||
if (!matches) {
|
||||
return this.with_state(block);
|
||||
}
|
||||
|
||||
let orig_txt = matches[4];
|
||||
|
||||
if (matches[1] !== '' || matches[3] !== 'm') {
|
||||
return this.with_state(orig_txt);
|
||||
}
|
||||
|
||||
// Ok - we have a valid "SGR" (Select Graphic Rendition)
|
||||
|
||||
let sgr_cmds = matches[2].split(';');
|
||||
|
||||
// Each of these params affects the SGR state
|
||||
|
||||
// Why do we shift through the array instead of a forEach??
|
||||
// ... because some commands consume the params that follow !
|
||||
while (sgr_cmds.length > 0) {
|
||||
let sgr_cmd_str = sgr_cmds.shift();
|
||||
let num = parseInt(sgr_cmd_str, 10);
|
||||
|
||||
if (isNaN(num) || num === 0) {
|
||||
this.fg = this.bg = null;
|
||||
this.bright = false;
|
||||
} else if (num === 1) {
|
||||
this.bright = true;
|
||||
} else if (num === 22) {
|
||||
this.bright = false;
|
||||
} else if (num === 39) {
|
||||
this.fg = null;
|
||||
} else if (num === 49) {
|
||||
this.bg = null;
|
||||
} else if ((num >= 30) && (num < 38)) {
|
||||
let bidx = this.bright ? 1 : 0;
|
||||
this.fg = this.ansi_colors[bidx][(num - 30)];
|
||||
} else if ((num >= 90) && (num < 98)) {
|
||||
this.fg = this.ansi_colors[1][(num - 90)];
|
||||
} else if ((num >= 40) && (num < 48)) {
|
||||
this.bg = this.ansi_colors[0][(num - 40)];
|
||||
} else if ((num >= 100) && (num < 108)) {
|
||||
this.bg = this.ansi_colors[1][(num - 100)];
|
||||
} else if (num === 38 || num === 48) {
|
||||
|
||||
// extended set foreground/background color
|
||||
|
||||
// validate that param exists
|
||||
if (sgr_cmds.length > 0) {
|
||||
// extend color (38=fg, 48=bg)
|
||||
let is_foreground = (num === 38);
|
||||
|
||||
let mode_cmd = sgr_cmds.shift();
|
||||
|
||||
// MODE '5' - 256 color palette
|
||||
if (mode_cmd === '5' && sgr_cmds.length > 0) {
|
||||
let palette_index = parseInt(sgr_cmds.shift(), 10);
|
||||
if (palette_index >= 0 && palette_index <= 255) {
|
||||
if (is_foreground)
|
||||
this.fg = this.palette_256[palette_index];
|
||||
else
|
||||
this.bg = this.palette_256[palette_index];
|
||||
}
|
||||
}
|
||||
|
||||
// MODE '2' - True Color
|
||||
if (mode_cmd === '2' && sgr_cmds.length > 2) {
|
||||
let r = parseInt(sgr_cmds.shift(), 10);
|
||||
let g = parseInt(sgr_cmds.shift(), 10);
|
||||
let b = parseInt(sgr_cmds.shift(), 10);
|
||||
|
||||
if ((r >= 0 && r <= 255) && (g >= 0 && g <= 255) && (b >= 0 && b <= 255)) {
|
||||
let c = { rgb: [r,g,b], class_name: 'truecolor'};
|
||||
if (is_foreground)
|
||||
this.fg = c;
|
||||
else
|
||||
this.bg = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.with_state(orig_txt);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
interface AU_Color {
|
||||
rgb: number[];
|
||||
class_name: string;
|
||||
}
|
||||
interface TextWithData {
|
||||
fg: AU_Color;
|
||||
bg: AU_Color;
|
||||
bright: boolean;
|
||||
text: string;
|
||||
}
|
||||
interface Formatter {
|
||||
transform(fragment: TextWithData, instance: AnsiUp): any;
|
||||
compose(segments: any[], instance: AnsiUp): any;
|
||||
}
|
||||
declare function rgx(tmplObj: any, ...subst: any[]): RegExp;
|
||||
declare class AnsiUp {
|
||||
VERSION: string;
|
||||
ansi_colors: {
|
||||
rgb: number[];
|
||||
class_name: string;
|
||||
}[][];
|
||||
htmlFormatter: Formatter;
|
||||
textFormatter: Formatter;
|
||||
private palette_256;
|
||||
private fg;
|
||||
private bg;
|
||||
private bright;
|
||||
private _use_classes;
|
||||
private _escape_for_html;
|
||||
private _sgr_regex;
|
||||
private _buffer;
|
||||
constructor();
|
||||
use_classes: boolean;
|
||||
escape_for_html: boolean;
|
||||
private setup_256_palette();
|
||||
private old_escape_for_html(txt);
|
||||
private old_linkify(txt);
|
||||
private detect_incomplete_ansi(txt);
|
||||
private detect_incomplete_link(txt);
|
||||
ansi_to(txt: string, formatter: Formatter): any;
|
||||
ansi_to_html(txt: string): string;
|
||||
ansi_to_text(txt: string): string;
|
||||
private with_state(text);
|
||||
private handle_incomplete_sequences(chunks);
|
||||
private process_ansi(block);
|
||||
}
|
|
@ -0,0 +1,312 @@
|
|||
"use strict";
|
||||
function rgx(tmplObj) {
|
||||
var subst = [];
|
||||
for (var _i = 1; _i < arguments.length; _i++) {
|
||||
subst[_i - 1] = arguments[_i];
|
||||
}
|
||||
var regexText = tmplObj.raw[0];
|
||||
var wsrgx = /^\s+|\s+\n|\s+#[\s\S]+?\n/gm;
|
||||
var txt2 = regexText.replace(wsrgx, '');
|
||||
return new RegExp(txt2, 'm');
|
||||
}
|
||||
var AnsiUp = (function () {
|
||||
function AnsiUp() {
|
||||
this.VERSION = "2.0.1";
|
||||
this.ansi_colors = [
|
||||
[
|
||||
{ rgb: [0, 0, 0], class_name: "ansi-black" },
|
||||
{ rgb: [187, 0, 0], class_name: "ansi-red" },
|
||||
{ rgb: [0, 187, 0], class_name: "ansi-green" },
|
||||
{ rgb: [187, 187, 0], class_name: "ansi-yellow" },
|
||||
{ rgb: [0, 0, 187], class_name: "ansi-blue" },
|
||||
{ rgb: [187, 0, 187], class_name: "ansi-magenta" },
|
||||
{ rgb: [0, 187, 187], class_name: "ansi-cyan" },
|
||||
{ rgb: [255, 255, 255], class_name: "ansi-white" }
|
||||
],
|
||||
[
|
||||
{ rgb: [85, 85, 85], class_name: "ansi-bright-black" },
|
||||
{ rgb: [255, 85, 85], class_name: "ansi-bright-red" },
|
||||
{ rgb: [0, 255, 0], class_name: "ansi-bright-green" },
|
||||
{ rgb: [255, 255, 85], class_name: "ansi-bright-yellow" },
|
||||
{ rgb: [85, 85, 255], class_name: "ansi-bright-blue" },
|
||||
{ rgb: [255, 85, 255], class_name: "ansi-bright-magenta" },
|
||||
{ rgb: [85, 255, 255], class_name: "ansi-bright-cyan" },
|
||||
{ rgb: [255, 255, 255], class_name: "ansi-bright-white" }
|
||||
]
|
||||
];
|
||||
this.htmlFormatter = {
|
||||
transform: function (fragment, instance) {
|
||||
var txt = fragment.text;
|
||||
if (txt.length === 0)
|
||||
return txt;
|
||||
if (instance._escape_for_html)
|
||||
txt = instance.old_escape_for_html(txt);
|
||||
if (!fragment.bright && fragment.fg === null && fragment.bg === null)
|
||||
return txt;
|
||||
var styles = [];
|
||||
var classes = [];
|
||||
var fg = fragment.fg;
|
||||
var bg = fragment.bg;
|
||||
if (fg === null && fragment.bright)
|
||||
fg = instance.ansi_colors[1][7];
|
||||
if (!instance._use_classes) {
|
||||
if (fg)
|
||||
styles.push("color:rgb(" + fg.rgb.join(',') + ")");
|
||||
if (bg)
|
||||
styles.push("background-color:rgb(" + bg.rgb + ")");
|
||||
}
|
||||
else {
|
||||
if (fg) {
|
||||
if (fg.class_name !== 'truecolor') {
|
||||
classes.push(fg.class_name + "-fg");
|
||||
}
|
||||
else {
|
||||
styles.push("color:rgb(" + fg.rgb.join(',') + ")");
|
||||
}
|
||||
}
|
||||
if (bg) {
|
||||
if (bg.class_name !== 'truecolor') {
|
||||
classes.push(bg.class_name + "-bg");
|
||||
}
|
||||
else {
|
||||
styles.push("background-color:rgb(" + bg.rgb.join(',') + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
var class_string = '';
|
||||
var style_string = '';
|
||||
if (classes.length)
|
||||
class_string = " class=\"" + classes.join(' ') + "\"";
|
||||
if (styles.length)
|
||||
style_string = " style=\"" + styles.join(';') + "\"";
|
||||
return "<span" + class_string + style_string + ">" + txt + "</span>";
|
||||
},
|
||||
compose: function (segments, instance) {
|
||||
return segments.join("");
|
||||
}
|
||||
};
|
||||
this.textFormatter = {
|
||||
transform: function (fragment, instance) {
|
||||
return fragment.text;
|
||||
},
|
||||
compose: function (segments, instance) {
|
||||
return segments.join("");
|
||||
}
|
||||
};
|
||||
this.setup_256_palette();
|
||||
this._use_classes = false;
|
||||
this._escape_for_html = true;
|
||||
this.bright = false;
|
||||
this.fg = this.bg = null;
|
||||
this._buffer = '';
|
||||
}
|
||||
Object.defineProperty(AnsiUp.prototype, "use_classes", {
|
||||
get: function () {
|
||||
return this._use_classes;
|
||||
},
|
||||
set: function (arg) {
|
||||
this._use_classes = arg;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(AnsiUp.prototype, "escape_for_html", {
|
||||
get: function () {
|
||||
return this._escape_for_html;
|
||||
},
|
||||
set: function (arg) {
|
||||
this._escape_for_html = arg;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
AnsiUp.prototype.setup_256_palette = function () {
|
||||
var _this = this;
|
||||
this.palette_256 = [];
|
||||
this.ansi_colors.forEach(function (palette) {
|
||||
palette.forEach(function (rec) {
|
||||
_this.palette_256.push(rec);
|
||||
});
|
||||
});
|
||||
var levels = [0, 95, 135, 175, 215, 255];
|
||||
for (var r = 0; r < 6; ++r) {
|
||||
for (var g = 0; g < 6; ++g) {
|
||||
for (var b = 0; b < 6; ++b) {
|
||||
var col = { rgb: [levels[r], levels[g], levels[b]], class_name: 'truecolor' };
|
||||
this.palette_256.push(col);
|
||||
}
|
||||
}
|
||||
}
|
||||
var grey_level = 8;
|
||||
for (var i = 0; i < 24; ++i, grey_level += 10) {
|
||||
var gry = { rgb: [grey_level, grey_level, grey_level], class_name: 'truecolor' };
|
||||
this.palette_256.push(gry);
|
||||
}
|
||||
};
|
||||
AnsiUp.prototype.old_escape_for_html = function (txt) {
|
||||
return txt.replace(/[&<>]/gm, function (str) {
|
||||
if (str === "&")
|
||||
return "&";
|
||||
if (str === "<")
|
||||
return "<";
|
||||
if (str === ">")
|
||||
return ">";
|
||||
});
|
||||
};
|
||||
AnsiUp.prototype.old_linkify = function (txt) {
|
||||
return txt.replace(/(https?:\/\/[^\s]+)/gm, function (str) {
|
||||
return "<a href=\"" + str + "\">" + str + "</a>";
|
||||
});
|
||||
};
|
||||
AnsiUp.prototype.detect_incomplete_ansi = function (txt) {
|
||||
return !(/.*?[\x40-\x7e]/.test(txt));
|
||||
};
|
||||
AnsiUp.prototype.detect_incomplete_link = function (txt) {
|
||||
var found = false;
|
||||
for (var i = txt.length - 1; i > 0; i--) {
|
||||
if (/\s|\x1B/.test(txt[i])) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (/(https?:\/\/[^\s]+)/.test(txt))
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
var prefix = txt.substr(i + 1, 4);
|
||||
if (prefix.length === 0)
|
||||
return -1;
|
||||
if ("http".indexOf(prefix) === 0)
|
||||
return (i + 1);
|
||||
};
|
||||
AnsiUp.prototype.ansi_to = function (txt, formatter) {
|
||||
var pkt = this._buffer + txt;
|
||||
this._buffer = '';
|
||||
var raw_text_pkts = pkt.split(/\x1B\[/);
|
||||
if (raw_text_pkts.length === 1)
|
||||
raw_text_pkts.push('');
|
||||
this.handle_incomplete_sequences(raw_text_pkts);
|
||||
var first_chunk = this.with_state(raw_text_pkts.shift());
|
||||
var blocks = new Array(raw_text_pkts.length);
|
||||
for (var i = 0, len = raw_text_pkts.length; i < len; ++i) {
|
||||
blocks[i] = (formatter.transform(this.process_ansi(raw_text_pkts[i]), this));
|
||||
}
|
||||
if (first_chunk.text.length > 0)
|
||||
blocks.unshift(formatter.transform(first_chunk, this));
|
||||
return formatter.compose(blocks, this);
|
||||
};
|
||||
AnsiUp.prototype.ansi_to_html = function (txt) {
|
||||
return this.ansi_to(txt, this.htmlFormatter);
|
||||
};
|
||||
AnsiUp.prototype.ansi_to_text = function (txt) {
|
||||
return this.ansi_to(txt, this.textFormatter);
|
||||
};
|
||||
AnsiUp.prototype.with_state = function (text) {
|
||||
return { bright: this.bright, fg: this.fg, bg: this.bg, text: text };
|
||||
};
|
||||
AnsiUp.prototype.handle_incomplete_sequences = function (chunks) {
|
||||
var last_chunk = chunks[chunks.length - 1];
|
||||
if ((last_chunk.length > 0) && this.detect_incomplete_ansi(last_chunk)) {
|
||||
this._buffer = "\x1B[" + last_chunk;
|
||||
chunks.pop();
|
||||
chunks.push('');
|
||||
}
|
||||
else {
|
||||
if (last_chunk.slice(-1) === "\x1B") {
|
||||
this._buffer = "\x1B";
|
||||
console.log("raw", chunks);
|
||||
chunks.pop();
|
||||
chunks.push(last_chunk.substr(0, last_chunk.length - 1));
|
||||
console.log(chunks);
|
||||
console.log(last_chunk);
|
||||
}
|
||||
if (chunks.length === 2 &&
|
||||
chunks[1] === "" &&
|
||||
chunks[0].slice(-1) === "\x1B") {
|
||||
this._buffer = "\x1B";
|
||||
last_chunk = chunks.shift();
|
||||
chunks.unshift(last_chunk.substr(0, last_chunk.length - 1));
|
||||
}
|
||||
}
|
||||
};
|
||||
AnsiUp.prototype.process_ansi = function (block) {
|
||||
if (!this._sgr_regex) {
|
||||
this._sgr_regex = (_a = ["\n ^ # beginning of line\n ([!<-?]?) # a private-mode char (!, <, =, >, ?)\n ([d;]*) # any digits or semicolons\n ([ -/]? # an intermediate modifier\n [@-~]) # the command\n ([sS]*) # any text following this CSI sequence\n "], _a.raw = ["\n ^ # beginning of line\n ([!\\x3c-\\x3f]?) # a private-mode char (!, <, =, >, ?)\n ([\\d;]*) # any digits or semicolons\n ([\\x20-\\x2f]? # an intermediate modifier\n [\\x40-\\x7e]) # the command\n ([\\s\\S]*) # any text following this CSI sequence\n "], rgx(_a));
|
||||
}
|
||||
var matches = block.match(this._sgr_regex);
|
||||
if (!matches) {
|
||||
return this.with_state(block);
|
||||
}
|
||||
var orig_txt = matches[4];
|
||||
if (matches[1] !== '' || matches[3] !== 'm') {
|
||||
return this.with_state(orig_txt);
|
||||
}
|
||||
var sgr_cmds = matches[2].split(';');
|
||||
while (sgr_cmds.length > 0) {
|
||||
var sgr_cmd_str = sgr_cmds.shift();
|
||||
var num = parseInt(sgr_cmd_str, 10);
|
||||
if (isNaN(num) || num === 0) {
|
||||
this.fg = this.bg = null;
|
||||
this.bright = false;
|
||||
}
|
||||
else if (num === 1) {
|
||||
this.bright = true;
|
||||
}
|
||||
else if (num === 22) {
|
||||
this.bright = false;
|
||||
}
|
||||
else if (num === 39) {
|
||||
this.fg = null;
|
||||
}
|
||||
else if (num === 49) {
|
||||
this.bg = null;
|
||||
}
|
||||
else if ((num >= 30) && (num < 38)) {
|
||||
var bidx = this.bright ? 1 : 0;
|
||||
this.fg = this.ansi_colors[bidx][(num - 30)];
|
||||
}
|
||||
else if ((num >= 90) && (num < 98)) {
|
||||
this.fg = this.ansi_colors[1][(num - 90)];
|
||||
}
|
||||
else if ((num >= 40) && (num < 48)) {
|
||||
this.bg = this.ansi_colors[0][(num - 40)];
|
||||
}
|
||||
else if ((num >= 100) && (num < 108)) {
|
||||
this.bg = this.ansi_colors[1][(num - 100)];
|
||||
}
|
||||
else if (num === 38 || num === 48) {
|
||||
if (sgr_cmds.length > 0) {
|
||||
var is_foreground = (num === 38);
|
||||
var mode_cmd = sgr_cmds.shift();
|
||||
if (mode_cmd === '5' && sgr_cmds.length > 0) {
|
||||
var palette_index = parseInt(sgr_cmds.shift(), 10);
|
||||
if (palette_index >= 0 && palette_index <= 255) {
|
||||
if (is_foreground)
|
||||
this.fg = this.palette_256[palette_index];
|
||||
else
|
||||
this.bg = this.palette_256[palette_index];
|
||||
}
|
||||
}
|
||||
if (mode_cmd === '2' && sgr_cmds.length > 2) {
|
||||
var r = parseInt(sgr_cmds.shift(), 10);
|
||||
var g = parseInt(sgr_cmds.shift(), 10);
|
||||
var b = parseInt(sgr_cmds.shift(), 10);
|
||||
if ((r >= 0 && r <= 255) && (g >= 0 && g <= 255) && (b >= 0 && b <= 255)) {
|
||||
var c = { rgb: [r, g, b], class_name: 'truecolor' };
|
||||
if (is_foreground)
|
||||
this.fg = c;
|
||||
else
|
||||
this.bg = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.with_state(orig_txt);
|
||||
var _a;
|
||||
};
|
||||
return AnsiUp;
|
||||
}());
|
||||
//# sourceMappingURL=ansi_up.js.map
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,28 @@
|
|||
<html>
|
||||
<head>
|
||||
<style type="text/css">
|
||||
pre {
|
||||
margin: 0;
|
||||
font-family: monaco, "Courier New", Courier, monospace;
|
||||
line-height: 1.3;
|
||||
background: black;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="console"></pre>
|
||||
</body>
|
||||
<script src="../ansi_up.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
var ansi_up = new AnsiUp;
|
||||
|
||||
var txt = "\n\n\033[1;33;40m 33;40 \033[1;33;41m 33;41 \033[1;33;42m 33;42 \033[1;33;43m 33;43 \033[1;33;44m 33;44 \033[1;33;45m 33;45 \033[1;33;46m 33;46 \033[1m\033[0\n\n\033[1;33;42m >> Tests OK\n\n"
|
||||
|
||||
var html = ansi_up.ansi_to_html(txt);
|
||||
|
||||
var cdiv = document.getElementById("console");
|
||||
|
||||
cdiv.innerHTML = html;
|
||||
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<html>
|
||||
<head>
|
||||
<style type="text/css">
|
||||
pre {
|
||||
margin: 0;
|
||||
font-family: monaco, "Courier New", Courier, monospace;
|
||||
line-height: 1.3;
|
||||
background: black;
|
||||
}
|
||||
</style>
|
||||
<script data-main="main.js" src="require.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="console"></pre>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,14 @@
|
|||
// For browser_amd.html
|
||||
require(['ansi_up',"jquery-1.7.2.min.js"], function(au) {
|
||||
|
||||
var a2h = new au.default;
|
||||
|
||||
var txt = "\n\n\033[1;33;40m 33;40 \033[1;33;41m 33;41 \033[1;33;42m 33;42 \033[1;33;43m 33;43 \033[1;33;44m 33;44 \033[1;33;45m 33;45 \033[1;33;46m 33;46 \033[1m\033[0\n\n\033[1;33;42m >> Tests OK\n\n"
|
||||
|
||||
$(function () {
|
||||
|
||||
$("#console").html( a2h.ansi_to_html(txt) );
|
||||
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
RequireJS 2.1.0 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
|
||||
Available via the MIT or new BSD license.
|
||||
see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
var requirejs,require,define;
|
||||
(function(U){function D(b){return M.call(b)==="[object Function]"}function E(b){return M.call(b)==="[object Array]"}function s(b,c){if(b){var d;for(d=0;d<b.length;d+=1)if(b[d]&&c(b[d],d,b))break}}function N(b,c){if(b){var d;for(d=b.length-1;d>-1;d-=1)if(b[d]&&c(b[d],d,b))break}}function F(b,c){for(var d in b)if(b.hasOwnProperty(d)&&c(b[d],d))break}function J(b,c,d,h){c&&F(c,function(c,j){if(d||!G.call(b,j))h&&typeof c!=="string"?(b[j]||(b[j]={}),J(b[j],c,d,h)):b[j]=c});return b}function q(b,c){return function(){return c.apply(b,
|
||||
arguments)}}function V(b){if(!b)return b;var c=U;s(b.split("."),function(b){c=c[b]});return c}function H(b,c,d,h){c=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+b);c.requireType=b;c.requireModules=h;if(d)c.originalError=d;return c}function aa(){if(I&&I.readyState==="interactive")return I;N(document.getElementsByTagName("script"),function(b){if(b.readyState==="interactive")return I=b});return I}var h,r,u,y,p,A,I,B,W,X,ba=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,ca=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
|
||||
Y=/\.js$/,da=/^\.\//;r=Object.prototype;var M=r.toString,G=r.hasOwnProperty,ea=Array.prototype.splice,v=!!(typeof window!=="undefined"&&navigator&&document),Z=!v&&typeof importScripts!=="undefined",fa=v&&navigator.platform==="PLAYSTATION 3"?/^complete$/:/^(complete|loaded)$/,Q=typeof opera!=="undefined"&&opera.toString()==="[object Opera]",w={},n={},O=[],K=!1;if(typeof define==="undefined"){if(typeof requirejs!=="undefined"){if(D(requirejs))return;n=requirejs;requirejs=void 0}typeof require!=="undefined"&&
|
||||
!D(require)&&(n=require,require=void 0);h=requirejs=function(b,c,d,t){var g,j="_";!E(b)&&typeof b!=="string"&&(g=b,E(c)?(b=c,c=d,d=t):b=[]);if(g&&g.context)j=g.context;(t=w[j])||(t=w[j]=h.s.newContext(j));g&&t.configure(g);return t.require(b,c,d)};h.config=function(b){return h(b)};h.nextTick=typeof setTimeout!=="undefined"?function(b){setTimeout(b,4)}:function(b){b()};require||(require=h);h.version="2.1.0";h.jsExtRegExp=/^\/|:|\?|\.js$/;h.isBrowser=v;r=h.s={contexts:w,newContext:function(b){function c(a,
|
||||
f,x){var e,b,k,c,d,i,g,h=f&&f.split("/");e=h;var j=m.map,l=j&&j["*"];if(a&&a.charAt(0)===".")if(f){e=m.pkgs[f]?h=[f]:h.slice(0,h.length-1);f=a=e.concat(a.split("/"));for(e=0;f[e];e+=1)if(b=f[e],b===".")f.splice(e,1),e-=1;else if(b==="..")if(e===1&&(f[2]===".."||f[0]===".."))break;else e>0&&(f.splice(e-1,2),e-=2);e=m.pkgs[f=a[0]];a=a.join("/");e&&a===f+"/"+e.main&&(a=f)}else a.indexOf("./")===0&&(a=a.substring(2));if(x&&(h||l)&&j){f=a.split("/");for(e=f.length;e>0;e-=1){k=f.slice(0,e).join("/");if(h)for(b=
|
||||
h.length;b>0;b-=1)if(x=j[h.slice(0,b).join("/")])if(x=x[k]){c=x;d=e;break}if(c)break;!i&&l&&l[k]&&(i=l[k],g=e)}!c&&i&&(c=i,d=g);c&&(f.splice(0,d,c),a=f.join("/"))}return a}function d(a){v&&s(document.getElementsByTagName("script"),function(f){if(f.getAttribute("data-requiremodule")===a&&f.getAttribute("data-requirecontext")===i.contextName)return f.parentNode.removeChild(f),!0})}function t(a){var f=m.paths[a];if(f&&E(f)&&f.length>1)return d(a),f.shift(),i.require.undef(a),i.require([a]),!0}function g(a){var f,
|
||||
b=a?a.indexOf("!"):-1;b>-1&&(f=a.substring(0,b),a=a.substring(b+1,a.length));return[f,a]}function j(a,f,b,e){var $,k,d=null,h=f?f.name:null,j=a,m=!0,l="";a||(m=!1,a="_@r"+(M+=1));a=g(a);d=a[0];a=a[1];d&&(d=c(d,h,e),k=o[d]);a&&(d?l=k&&k.normalize?k.normalize(a,function(a){return c(a,h,e)}):c(a,h,e):(l=c(a,h,e),a=g(l),d=a[0],l=a[1],b=!0,$=i.nameToUrl(l)));b=d&&!k&&!b?"_unnormalized"+(N+=1):"";return{prefix:d,name:l,parentMap:f,unnormalized:!!b,url:$,originalName:j,isDefine:m,id:(d?d+"!"+l:l)+b}}function n(a){var f=
|
||||
a.id,b=l[f];b||(b=l[f]=new i.Module(a));return b}function p(a,f,b){var e=a.id,c=l[e];if(G.call(o,e)&&(!c||c.defineEmitComplete))f==="defined"&&b(o[e]);else n(a).on(f,b)}function z(a,f){var b=a.requireModules,e=!1;if(f)f(a);else if(s(b,function(f){if(f=l[f])f.error=a,f.events.error&&(e=!0,f.emit("error",a))}),!e)h.onError(a)}function r(){O.length&&(ea.apply(C,[C.length-1,0].concat(O)),O=[])}function u(a,f,b){var e=a.map.id;a.error?a.emit("error",a.error):(f[e]=!0,s(a.depMaps,function(e,k){var c=e.id,
|
||||
d=l[c];d&&!a.depMatched[k]&&!b[c]&&(f[c]?(a.defineDep(k,o[c]),a.check()):u(d,f,b))}),b[e]=!0)}function w(){var a,f,b,e,c=(b=m.waitSeconds*1E3)&&i.startTime+b<(new Date).getTime(),k=[],h=[],g=!1,j=!0;if(!B){B=!0;F(l,function(b){a=b.map;f=a.id;if(b.enabled&&(a.isDefine||h.push(b),!b.error))if(!b.inited&&c)t(f)?g=e=!0:(k.push(f),d(f));else if(!b.inited&&b.fetched&&a.isDefine&&(g=!0,!a.prefix))return j=!1});if(c&&k.length)return b=H("timeout","Load timeout for modules: "+k,null,k),b.contextName=i.contextName,
|
||||
z(b);j&&s(h,function(a){u(a,{},{})});if((!c||e)&&g)if((v||Z)&&!R)R=setTimeout(function(){R=0;w()},50);B=!1}}function y(a){n(j(a[0],null,!0)).init(a[1],a[2])}function A(a){var a=a.currentTarget||a.srcElement,b=i.onScriptLoad;a.detachEvent&&!Q?a.detachEvent("onreadystatechange",b):a.removeEventListener("load",b,!1);b=i.onScriptError;a.detachEvent&&!Q||a.removeEventListener("error",b,!1);return{node:a,id:a&&a.getAttribute("data-requiremodule")}}var B,S,i,L,R,m={waitSeconds:7,baseUrl:"./",paths:{},pkgs:{},
|
||||
shim:{}},l={},T={},C=[],o={},P={},M=1,N=1;L={require:function(a){return a.require?a.require:a.require=i.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports?a.exports:a.exports=o[a.map.id]={}},module:function(a){return a.module?a.module:a.module={id:a.map.id,uri:a.map.url,config:function(){return m.config&&m.config[a.map.id]||{}},exports:o[a.map.id]}}};S=function(a){this.events=T[a.id]||{};this.map=a;this.shim=m.shim[a.id];this.depExports=[];this.depMaps=[];
|
||||
this.depMatched=[];this.pluginMaps={};this.depCount=0};S.prototype={init:function(a,b,c,e){e=e||{};if(!this.inited){this.factory=b;if(c)this.on("error",c);else this.events.error&&(c=q(this,function(a){this.emit("error",a)}));this.depMaps=a&&a.slice(0);this.errback=c;this.inited=!0;this.ignore=e.ignore;e.enabled||this.enabled?this.enable():this.check()}},defineDep:function(a,b){this.depMatched[a]||(this.depMatched[a]=!0,this.depCount-=1,this.depExports[a]=b)},fetch:function(){if(!this.fetched){this.fetched=
|
||||
!0;i.startTime=(new Date).getTime();var a=this.map;if(this.shim)i.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],q(this,function(){return a.prefix?this.callPlugin():this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a=this.map.url;P[a]||(P[a]=!0,i.load(this.map.id,a))},check:function(){if(this.enabled&&!this.enabling){var a,b,c=this.map.id;b=this.depExports;var e=this.exports,d=this.factory;if(this.inited)if(this.error)this.emit("error",this.error);
|
||||
else{if(!this.defining){this.defining=!0;if(this.depCount<1&&!this.defined){if(D(d)){if(this.events.error)try{e=i.execCb(c,d,b,e)}catch(k){a=k}else e=i.execCb(c,d,b,e);if(this.map.isDefine)if((b=this.module)&&b.exports!==void 0&&b.exports!==this.exports)e=b.exports;else if(e===void 0&&this.usingExports)e=this.exports;if(a)return a.requireMap=this.map,a.requireModules=[this.map.id],a.requireType="define",z(this.error=a)}else e=d;this.exports=e;if(this.map.isDefine&&!this.ignore&&(o[c]=e,h.onResourceLoad))h.onResourceLoad(i,
|
||||
this.map,this.depMaps);delete l[c];this.defined=!0}this.defining=!1;if(this.defined&&!this.defineEmitted)this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0}}else this.fetch()}},callPlugin:function(){var a=this.map,b=a.id,d=j(a.prefix);this.depMaps.push(d);p(d,"defined",q(this,function(e){var d,k;k=this.map.name;var x=this.map.parentMap?this.map.parentMap.name:null,g=i.makeRequire(a.parentMap,{enableBuildCallback:!0,skipMap:!0});if(this.map.unnormalized){if(e.normalize&&
|
||||
(k=e.normalize(k,function(a){return c(a,x,!0)})||""),e=j(a.prefix+"!"+k,this.map.parentMap),p(e,"defined",q(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),k=l[e.id]){this.depMaps.push(e);if(this.events.error)k.on("error",q(this,function(a){this.emit("error",a)}));k.enable()}}else d=q(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),d.error=q(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];F(l,function(a){a.map.id.indexOf(b+
|
||||
"_unnormalized")===0&&delete l[a.map.id]});z(a)}),d.fromText=q(this,function(b,e){var f=a.name,c=j(f),k=K;e&&(b=e);k&&(K=!1);n(c);try{h.exec(b)}catch(x){throw Error("fromText eval for "+f+" failed: "+x);}k&&(K=!0);this.depMaps.push(c);i.completeLoad(f);g([f],d)}),e.load(a.name,g,d,m)}));i.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){this.enabling=this.enabled=!0;s(this.depMaps,q(this,function(a,b){var c,e;if(typeof a==="string"){a=j(a,this.map.isDefine?this.map:this.map.parentMap,!1,
|
||||
!this.skipMap);this.depMaps[b]=a;if(c=L[a.id]){this.depExports[b]=c(this);return}this.depCount+=1;p(a,"defined",q(this,function(a){this.defineDep(b,a);this.check()}));this.errback&&p(a,"error",this.errback)}c=a.id;e=l[c];!L[c]&&e&&!e.enabled&&i.enable(a,this)}));F(this.pluginMaps,q(this,function(a){var b=l[a.id];b&&!b.enabled&&i.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){s(this.events[a],function(a){a(b)});
|
||||
a==="error"&&delete this.events[a]}};i={config:m,contextName:b,registry:l,defined:o,urlFetched:P,defQueue:C,Module:S,makeModuleMap:j,nextTick:h.nextTick,configure:function(a){a.baseUrl&&a.baseUrl.charAt(a.baseUrl.length-1)!=="/"&&(a.baseUrl+="/");var b=m.pkgs,c=m.shim,e=m.paths,d=m.map;J(m,a,!0);m.paths=J(e,a.paths,!0);if(a.map)m.map=J(d||{},a.map,!0,!0);if(a.shim)F(a.shim,function(a,b){E(a)&&(a={deps:a});if(a.exports&&!a.exportsFn)a.exportsFn=i.makeShimExports(a);c[b]=a}),m.shim=c;if(a.packages)s(a.packages,
|
||||
function(a){a=typeof a==="string"?{name:a}:a;b[a.name]={name:a.name,location:a.location||a.name,main:(a.main||"main").replace(da,"").replace(Y,"")}}),m.pkgs=b;F(l,function(a,b){if(!a.inited&&!a.map.unnormalized)a.map=j(b)});if(a.deps||a.callback)i.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(U,arguments));return b||V(a.exports)}},makeRequire:function(a,f){function d(e,c,k){var g,m;if(f.enableBuildCallback&&c&&D(c))c.__requireJsBuild=!0;
|
||||
if(typeof e==="string"){if(D(c))return z(H("requireargs","Invalid require call"),k);if(a&&L[e])return L[e](l[a.id]);if(h.get)return h.get(i,e,a);g=j(e,a,!1,!0);g=g.id;return!G.call(o,g)?z(H("notloaded",'Module name "'+g+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):o[g]}for(r();C.length;)if(g=C.shift(),g[0]===null)return z(H("mismatch","Mismatched anonymous define() module: "+g[g.length-1]));else y(g);i.nextTick(function(){m=n(j(null,a));m.skipMap=f.skipMap;m.init(e,c,k,
|
||||
{enabled:!0});w()});return d}f=f||{};J(d,{isBrowser:v,toUrl:function(b){var f=b.lastIndexOf("."),d=null;f!==-1&&(d=b.substring(f,b.length),b=b.substring(0,f));return i.nameToUrl(c(b,a&&a.id,!0),d)},defined:function(b){b=j(b,a,!1,!0).id;return G.call(o,b)},specified:function(b){b=j(b,a,!1,!0).id;return G.call(o,b)||G.call(l,b)}});if(!a)d.undef=function(b){r();var c=j(b,a,!0),f=l[b];delete o[b];delete P[c.url];delete T[b];if(f){if(f.events.defined)T[b]=f.events;delete l[b]}};return d},enable:function(a){l[a.id]&&
|
||||
n(a).enable()},completeLoad:function(a){var b,c,e=m.shim[a]||{},d=e.exports;for(r();C.length;){c=C.shift();if(c[0]===null){c[0]=a;if(b)break;b=!0}else c[0]===a&&(b=!0);y(c)}c=l[a];if(!b&&!o[a]&&c&&!c.inited)if(m.enforceDefine&&(!d||!V(d)))if(t(a))return;else return z(H("nodefine","No define call for "+a,null,[a]));else y([a,e.deps||[],e.exportsFn]);w()},nameToUrl:function(a,b){var c,e,d,g,i,j;if(h.jsExtRegExp.test(a))g=a+(b||"");else{c=m.paths;e=m.pkgs;g=a.split("/");for(i=g.length;i>0;i-=1)if(j=
|
||||
g.slice(0,i).join("/"),d=e[j],j=c[j]){E(j)&&(j=j[0]);g.splice(0,i,j);break}else if(d){c=a===d.name?d.location+"/"+d.main:d.location;g.splice(0,i,c);break}g=g.join("/");g+=b||(/\?/.test(g)?"":".js");g=(g.charAt(0)==="/"||g.match(/^[\w\+\.\-]+:/)?"":m.baseUrl)+g}return m.urlArgs?g+((g.indexOf("?")===-1?"?":"&")+m.urlArgs):g},load:function(a,b){h.load(i,a,b)},execCb:function(a,b,c,d){return b.apply(d,c)},onScriptLoad:function(a){if(a.type==="load"||fa.test((a.currentTarget||a.srcElement).readyState))I=
|
||||
null,a=A(a),i.completeLoad(a.id)},onScriptError:function(a){var b=A(a);if(!t(b.id))return z(H("scripterror","Script error",a,[b.id]))}};i.require=i.makeRequire();return i}};h({});s(["toUrl","undef","defined","specified"],function(b){h[b]=function(){var c=w._;return c.require[b].apply(c,arguments)}});if(v&&(u=r.head=document.getElementsByTagName("head")[0],y=document.getElementsByTagName("base")[0]))u=r.head=y.parentNode;h.onError=function(b){throw b;};h.load=function(b,c,d){var h=b&&b.config||{},
|
||||
g;if(v)return g=h.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script"),g.type=h.scriptType||"text/javascript",g.charset="utf-8",g.async=!0,g.setAttribute("data-requirecontext",b.contextName),g.setAttribute("data-requiremodule",c),g.attachEvent&&!(g.attachEvent.toString&&g.attachEvent.toString().indexOf("[native code")<0)&&!Q?(K=!0,g.attachEvent("onreadystatechange",b.onScriptLoad)):(g.addEventListener("load",b.onScriptLoad,!1),g.addEventListener("error",
|
||||
b.onScriptError,!1)),g.src=d,B=g,y?u.insertBefore(g,y):u.appendChild(g),B=null,g;else Z&&(importScripts(d),b.completeLoad(c))};v&&N(document.getElementsByTagName("script"),function(b){if(!u)u=b.parentNode;if(p=b.getAttribute("data-main")){if(!n.baseUrl)A=p.split("/"),W=A.pop(),X=A.length?A.join("/")+"/":"./",n.baseUrl=X,p=W;p=p.replace(Y,"");n.deps=n.deps?n.deps.concat(p):[p];return!0}});define=function(b,c,d){var h,g;typeof b!=="string"&&(d=c,c=b,b=null);E(c)||(d=c,c=[]);!c.length&&D(d)&&d.length&&
|
||||
(d.toString().replace(ba,"").replace(ca,function(b,d){c.push(d)}),c=(d.length===1?["require"]:["require","exports","module"]).concat(c));if(K&&(h=B||aa()))b||(b=h.getAttribute("data-requiremodule")),g=w[h.getAttribute("data-requirecontext")];(g?g.defQueue:O).push([b,c,d])};define.amd={jQuery:!0};h.exec=function(b){return eval(b)};h(n)}})(this);
|
|
@ -0,0 +1,34 @@
|
|||
// Tomorrow Night Ansi Colour Scheme
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-black-fg { color: #3A3A3A; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-red-fg { color: #DD948E; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-green-fg { color: #B6D1AA; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-yellow-fg { color: #F3D57C; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-blue-fg { color: #8AA9D5; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-magenta-fg { color: #CBAFD5; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-cyan-fg { color: #9AD1D4; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-white-fg { color: #EFEFEF; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-bright-black-fg { color: #5E5D5E; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-bright-red-fg { color: #E69B94; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-bright-green-fg { color: #D1F0C3; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-bright-yellow-fg { color: #F4D799; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-bright-blue-fg { color: #A6CBFE; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-bright-magenta-fg { color: #E7C7F2; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-bright-cyan-fg { color: #B0F0F5; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-bright-white-fg { color: #FFF; }
|
||||
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-black-bg { background-color: #3A3A3A; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-red-bg { background-color: #DD948E; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-green-bg { background-color: #B6D1AA; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-yellow-bg { background-color: #F3D57C; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-blue-bg { background-color: #8AA9D5; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-magenta-bg { background-color: #CBAFD5; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-cyan-bg { background-color: #9AD1D4; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-white-bg { background-color: #EFEFEF; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-bright-black-bg { background-color: #5E5D5E; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-bright-red-bg { background-color: #E69B94; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-bright-green-bg { background-color: #D1F0C3; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-bright-yellow-bg { background-color: #F4D799; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-bright-blue-bg { background-color: #A6CBFE; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-bright-magenta-bg { background-color: #E7C7F2; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-bright-cyan-bg { background-color: #B0F0F5; }
|
||||
.tomorrow-night-eighties-ansi-theme.ansi-bright-white-bg { background-color: #FFF; }
|
|
@ -0,0 +1,132 @@
|
|||
// Tomorrow Night Ansi Colour Scheme
|
||||
|
||||
.tomorrow-night-eighties-ansi-theme {
|
||||
|
||||
.ansi-black-fg {
|
||||
color: #3A3A3A;
|
||||
}
|
||||
|
||||
.ansi-red-fg {
|
||||
color: #DD948E;
|
||||
}
|
||||
|
||||
.ansi-green-fg {
|
||||
color: #B6D1AA;
|
||||
}
|
||||
|
||||
.ansi-yellow-fg {
|
||||
color: #F3D57C;
|
||||
}
|
||||
|
||||
.ansi-blue-fg {
|
||||
color: #8AA9D5;
|
||||
}
|
||||
|
||||
.ansi-magenta-fg {
|
||||
color: #CBAFD5;
|
||||
}
|
||||
|
||||
.ansi-cyan-fg {
|
||||
color: #9AD1D4;
|
||||
}
|
||||
|
||||
.ansi-white-fg {
|
||||
color: #EFEFEF;
|
||||
}
|
||||
|
||||
.ansi-bright-black-fg {
|
||||
color: #5E5D5E;
|
||||
}
|
||||
|
||||
.ansi-bright-red-fg {
|
||||
color: #E69B94;
|
||||
}
|
||||
|
||||
.ansi-bright-green-fg {
|
||||
color: #D1F0C3;
|
||||
}
|
||||
|
||||
.ansi-bright-yellow-fg {
|
||||
color: #F4D799;
|
||||
}
|
||||
|
||||
.ansi-bright-blue-fg {
|
||||
color: #A6CBFE;
|
||||
}
|
||||
|
||||
.ansi-bright-magenta-fg {
|
||||
color: #E7C7F2;
|
||||
}
|
||||
|
||||
.ansi-bright-cyan-fg {
|
||||
color: #B0F0F5;
|
||||
}
|
||||
|
||||
.ansi-bright-white-fg {
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
.ansi-black-bg {
|
||||
background-color: #3A3A3A;
|
||||
}
|
||||
|
||||
.ansi-red-bg {
|
||||
background-color: #DD948E;
|
||||
}
|
||||
|
||||
.ansi-green-bg {
|
||||
background-color: #B6D1AA;
|
||||
}
|
||||
|
||||
.ansi-yellow-bg {
|
||||
background-color: #F3D57C;
|
||||
}
|
||||
|
||||
.ansi-blue-bg {
|
||||
background-color: #8AA9D5;
|
||||
}
|
||||
|
||||
.ansi-magenta-bg {
|
||||
background-color: #CBAFD5;
|
||||
}
|
||||
|
||||
.ansi-cyan-bg {
|
||||
background-color: #9AD1D4;
|
||||
}
|
||||
|
||||
.ansi-white-bg {
|
||||
background-color: #EFEFEF;
|
||||
}
|
||||
|
||||
.ansi-bright-black-bg {
|
||||
background-color: #5E5D5E;
|
||||
}
|
||||
|
||||
.ansi-bright-red-bg {
|
||||
background-color: #E69B94;
|
||||
}
|
||||
|
||||
.ansi-bright-green-bg {
|
||||
background-color: #D1F0C3;
|
||||
}
|
||||
|
||||
.ansi-bright-yellow-bg {
|
||||
background-color: #F4D799;
|
||||
}
|
||||
|
||||
.ansi-bright-blue-bg {
|
||||
background-color: #A6CBFE;
|
||||
}
|
||||
|
||||
.ansi-bright-magenta-bg {
|
||||
background-color: #E7C7F2;
|
||||
}
|
||||
|
||||
.ansi-bright-cyan-bg {
|
||||
background-color: #B0F0F5;
|
||||
}
|
||||
|
||||
.ansi-bright-white-bg {
|
||||
background-color: #FFF;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
"_from": "ansi_up",
|
||||
"_id": "ansi_up@2.0.2",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha1-m1TeUIxcV59baWjmXBuGPgaAq5I=",
|
||||
"_location": "/ansi_up",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "tag",
|
||||
"registry": true,
|
||||
"raw": "ansi_up",
|
||||
"name": "ansi_up",
|
||||
"escapedName": "ansi_up",
|
||||
"rawSpec": "",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "latest"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"#USER",
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/ansi_up/-/ansi_up-2.0.2.tgz",
|
||||
"_shasum": "9b54de508c5c579f5b6968e65c1b863e0680ab92",
|
||||
"_spec": "ansi_up",
|
||||
"_where": "/Users/manu/arangodb-devel/tmp",
|
||||
"author": {
|
||||
"name": "drudru",
|
||||
"email": "drudru@gmail.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "http://github.com/drudru/ansi_up/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"deprecated": false,
|
||||
"description": "Convert ansi sequences in strings to colorful HTML",
|
||||
"devDependencies": {
|
||||
"mocha": "*",
|
||||
"should": "*",
|
||||
"typescript": "^2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"homepage": "https://github.com/drudru/ansi_up#readme",
|
||||
"keywords": [
|
||||
"ansi",
|
||||
"html"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "./ansi_up.js",
|
||||
"name": "ansi_up",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/drudru/ansi_up.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "make typescript",
|
||||
"test": "make test"
|
||||
},
|
||||
"version": "2.0.2"
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
|
@ -0,0 +1,858 @@
|
|||
var AU = require('../ansi_up');
|
||||
var AnsiUp = AU.default;
|
||||
|
||||
var should = require('should');
|
||||
|
||||
describe('ansi_up', function () {
|
||||
|
||||
describe('escape_for_html on', function () {
|
||||
|
||||
describe('ampersands', function () {
|
||||
|
||||
it('should escape a single ampersand', function () {
|
||||
var start = "&";
|
||||
var expected = "&";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should escape some text with ampersands', function () {
|
||||
var start = "abcd&efgh";
|
||||
var expected = "abcd&efgh";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should escape multiple ampersands', function () {
|
||||
var start = " & & ";
|
||||
var expected = " & & ";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should escape an already escaped ampersand', function () {
|
||||
var start = " & ";
|
||||
var expected = " &amp; ";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('less-than', function () {
|
||||
|
||||
it('should escape a single less-than', function () {
|
||||
var start = "<";
|
||||
var expected = "<";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should escape some text with less-thans', function () {
|
||||
var start = "abcd<efgh";
|
||||
var expected = "abcd<efgh";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should escape multiple less-thans', function () {
|
||||
var start = " < < ";
|
||||
var expected = " < < ";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('greater-than', function () {
|
||||
|
||||
it('should escape a single greater-than', function () {
|
||||
var start = ">";
|
||||
var expected = ">";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should escape some text with greater-thans', function () {
|
||||
var start = "abcd>efgh";
|
||||
var expected = "abcd>efgh";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should escape multiple greater-thans', function () {
|
||||
var start = " > > ";
|
||||
var expected = " > > ";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('mixed characters', function () {
|
||||
|
||||
it('should escape a mix of characters that require escaping', function () {
|
||||
var start = "<&>/\\'\"";
|
||||
var expected = "<&>/\\'\"";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('escape_for_html off', function () {
|
||||
|
||||
describe('ampersands', function () {
|
||||
|
||||
it('should escape a single ampersand', function () {
|
||||
var start = "&";
|
||||
var expected = "&";
|
||||
|
||||
var au = new AnsiUp();
|
||||
au.escape_for_html = false;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should escape some text with ampersands', function () {
|
||||
var start = "abcd&efgh";
|
||||
var expected = "abcd&efgh";
|
||||
|
||||
var au = new AnsiUp();
|
||||
au.escape_for_html = false;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should escape multiple ampersands', function () {
|
||||
var start = " & & ";
|
||||
var expected = " & & ";
|
||||
|
||||
var au = new AnsiUp();
|
||||
au.escape_for_html = false;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should escape an already escaped ampersand', function () {
|
||||
var start = " & ";
|
||||
var expected = " & ";
|
||||
|
||||
var au = new AnsiUp();
|
||||
au.escape_for_html = false;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('less-than', function () {
|
||||
|
||||
it('should escape a single less-than', function () {
|
||||
var start = "<";
|
||||
var expected = "<";
|
||||
|
||||
var au = new AnsiUp();
|
||||
au.escape_for_html = false;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should escape some text with less-thans', function () {
|
||||
var start = "abcd<efgh";
|
||||
var expected = "abcd<efgh";
|
||||
|
||||
var au = new AnsiUp();
|
||||
au.escape_for_html = false;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should escape multiple less-thans', function () {
|
||||
var start = " < < ";
|
||||
var expected = " < < ";
|
||||
|
||||
var au = new AnsiUp();
|
||||
au.escape_for_html = false;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('greater-than', function () {
|
||||
|
||||
it('should escape a single greater-than', function () {
|
||||
var start = ">";
|
||||
var expected = ">";
|
||||
|
||||
var au = new AnsiUp();
|
||||
au.escape_for_html = false;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should escape some text with greater-thans', function () {
|
||||
var start = "abcd>efgh";
|
||||
var expected = "abcd>efgh";
|
||||
|
||||
var au = new AnsiUp();
|
||||
au.escape_for_html = false;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should escape multiple greater-thans', function () {
|
||||
var start = " > > ";
|
||||
var expected = " > > ";
|
||||
|
||||
var au = new AnsiUp();
|
||||
au.escape_for_html = false;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('mixed characters', function () {
|
||||
|
||||
it('should escape a mix of characters that require escaping', function () {
|
||||
var start = "<&>/\\'\"";
|
||||
var expected = "<&>/\\'\"";
|
||||
|
||||
var au = new AnsiUp();
|
||||
au.escape_for_html = false;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/* Too difficult
|
||||
|
||||
describe('linkify', function () {
|
||||
|
||||
it('should linkify a url', function () {
|
||||
var start = "http://link.to/me ";
|
||||
var expected = "<a href=\"http://link.to/me\">http://link.to/me</a> ";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should linkify a url split into two chunks', function () {
|
||||
var start1 = " https://link.to/m";
|
||||
var start2 = "e ";
|
||||
var expected = "<a href=\"https://link.to/me\">https://link.to/me</a> ";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start1);
|
||||
l.should.eql("");
|
||||
l = au.ansi_to_html(start2);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should linkify a url split into two chunks with color state', function () {
|
||||
var start1 = "\033[32mhttps://link.to/m";
|
||||
var start2 = "e ";
|
||||
var expected = "<span style=\"color:rgb(0,187,0)\"><a href=\"https://link.to/me\">https://link.to/me</a> </span>";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start1);
|
||||
l.should.eql("");
|
||||
l = au.ansi_to_html(start2);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
});
|
||||
*/
|
||||
|
||||
describe("ansi_to()", function() {
|
||||
|
||||
// Prove that interaction between AnsiUp and the formatter is correct and that formatters
|
||||
// can be completely isolated code.
|
||||
it("accepts an arbitrary formatter and provides ANSI information related to text segments", function() {
|
||||
var attr = 1; // bright
|
||||
var fg = 32; // green fg
|
||||
var bg = 41; // red bg
|
||||
var lines = [
|
||||
"should have no color",
|
||||
"\033[" + attr + ";" + fg + "m " + "should be bright green foreground" + "\033[0m",
|
||||
"\033[" + attr + ";" + bg + ";" + fg + "m " + "should have bright red background with bright green foreground" + "\033[0m"
|
||||
];
|
||||
|
||||
var stats = {};
|
||||
|
||||
// A silly formatter that collects statistics about the text it receives.
|
||||
var statsFormatter = {
|
||||
transform: function(data) {
|
||||
var text = data.text.replace(/^\s+|\s+$/, "");
|
||||
|
||||
if (text.length) {
|
||||
if (!stats[text]) {
|
||||
stats[text] = [];
|
||||
}
|
||||
|
||||
if (data.fg) stats[text].push(data.fg.class_name);
|
||||
if (data.bg) stats[text].push(data.bg.class_name);
|
||||
}
|
||||
|
||||
return text;
|
||||
},
|
||||
|
||||
compose: function(segments) {
|
||||
return "processed: " + segments.filter(function (s) { return s.length; }).join(", ");
|
||||
}
|
||||
};
|
||||
|
||||
var au = new AnsiUp();
|
||||
au.use_classes = true;
|
||||
|
||||
var plainText = au.ansi_to(lines.join(""), statsFormatter);
|
||||
|
||||
plainText.should.eql("processed: should have no color, should be bright green foreground, should have bright red background with bright green foreground");
|
||||
|
||||
stats.should.eql({
|
||||
"should have no color": [],
|
||||
"should be bright green foreground": ["ansi-bright-green"],
|
||||
"should have bright red background with bright green foreground": ["ansi-bright-green", "ansi-red"]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('ansi to html', function () {
|
||||
|
||||
describe('default colors', function () {
|
||||
it('should transform a foreground to html', function () {
|
||||
var attr = 0;
|
||||
var fg = 32;
|
||||
var start = "\033[" + fg + "m " + fg + " \033[0m";
|
||||
|
||||
var expected = "<span style=\"color:rgb(0,187,0)\"> " + fg + " </span>";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
|
||||
it('should transform a attr;foreground to html', function () {
|
||||
var attr = 0;
|
||||
var fg = 32;
|
||||
var start = "\033[" + attr + ";" + fg + "m " + fg + " \033[0m";
|
||||
|
||||
var expected = "<span style=\"color:rgb(0,187,0)\"> " + fg + " </span>";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should transform an empty code to a normal/reset html', function () {
|
||||
var attr = 0;
|
||||
var fg = 32;
|
||||
var start = "\033[" + attr + ";" + fg + "m " + fg + " \033[m x";
|
||||
|
||||
var expected = "<span style=\"color:rgb(0,187,0)\"> " + fg + " </span> x";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should transform a bold attr;foreground to html', function () {
|
||||
var attr = 1;
|
||||
var fg = 32;
|
||||
var start = "\033[" + attr + ";" + fg + "m " + attr + ";" + fg + " \033[0m";
|
||||
|
||||
var expected = "<span style=\"color:rgb(0,255,0)\"> " + attr + ";" + fg + " </span>";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should transform a bold-foreground to html', function () {
|
||||
var fg = 92;
|
||||
var start = "\033[" + fg + "m " + fg + " \033[0m";
|
||||
|
||||
var expected = "<span style=\"color:rgb(0,255,0)\"> " + fg + " </span>";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should transform a bold attr;background;foreground to html', function () {
|
||||
var attr = 1;
|
||||
var fg = 33;
|
||||
var bg = 42;
|
||||
var start = "\033[" + attr + ";" + bg + ";" + fg + "m " + attr + ";" + bg + ";" + fg + " \033[0m";
|
||||
|
||||
var expected = "<span style=\"color:rgb(255,255,85);background-color:rgb(0,187,0)\"> " + attr + ";" + bg + ";" + fg + " </span>";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should transform a bold-background;foreground to html', function () {
|
||||
var fg = 33;
|
||||
var bg = 102;
|
||||
var start = "\033[" + bg + ";" + fg + "m " + bg + ";" + fg + " \033[0m";
|
||||
|
||||
var expected = "<span style=\"color:rgb(187,187,0);background-color:rgb(0,255,0)\"> " + bg + ";" + fg + " </span>";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
|
||||
it('should transform a complex multi-line sequence to html', function () {
|
||||
var attr = 1;
|
||||
var fg = 32;
|
||||
var bg = 42;
|
||||
var start = "\n \033[" + fg + "m " + fg + " \033[0m \n \033[" + bg + "m " + bg + " \033[0m \n zimpper ";
|
||||
|
||||
var expected = "\n <span style=\"color:rgb(0,187,0)\"> " + fg + " </span> \n <span style=\"background-color:rgb(0,187,0)\"> " + bg + " </span> \n zimpper ";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should transform a foreground and background and reset foreground to html', function () {
|
||||
var fg = 37;
|
||||
var bg = 42;
|
||||
var start = "\n\033[40m \033[49m\033[" + fg + ";" + bg + "m " + bg + " \033[39m foobar ";
|
||||
|
||||
var expected = "\n<span style=\"background-color:rgb(0,0,0)\"> </span><span style=\"color:rgb(255,255,255);background-color:rgb(0,187,0)\"> " + bg + " </span><span style=\"background-color:rgb(0,187,0)\"> foobar </span>";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should transform a foreground and background and reset background to html', function () {
|
||||
var fg = 37;
|
||||
var bg = 42;
|
||||
var start = "\n\033[40m \033[49m\033[" + fg + ";" + bg + "m " + fg + " \033[49m foobar ";
|
||||
|
||||
var expected = "\n<span style=\"background-color:rgb(0,0,0)\"> </span><span style=\"color:rgb(255,255,255);background-color:rgb(0,187,0)\"> " + fg + " </span><span style=\"color:rgb(255,255,255)\"> foobar </span>";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should transform a foreground and background and reset them to html', function () {
|
||||
var fg = 37;
|
||||
var bg = 42;
|
||||
var start = "\n\033[40m \033[49m\033[" + fg + ";" + bg + "m " + fg + ';' + bg + " \033[39;49m foobar ";
|
||||
|
||||
var expected = "\n<span style=\"background-color:rgb(0,0,0)\"> </span><span style=\"color:rgb(255,255,255);background-color:rgb(0,187,0)\"> " + fg + ';' + bg + " </span> foobar ";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
describe('transform extended colors (palette)', function () {
|
||||
it('system color, foreground', function () {
|
||||
var start = "\033[38;5;1m" + "red" + "\033[0m";
|
||||
var expected = '<span style="color:rgb(187,0,0)">red</span>';
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('system color, foreground (bright)', function () {
|
||||
var start = "\033[38;5;9m" + "red" + "\033[0m";
|
||||
var expected = '<span style="color:rgb(255,85,85)">red</span>';
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('system color, background', function () {
|
||||
var start = "\033[48;5;1m" + "red" + "\033[0m";
|
||||
var expected = '<span style="background-color:rgb(187,0,0)">red</span>';
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('system color, background (bright)', function () {
|
||||
var start = "\033[48;5;9m" + "red" + "\033[0m";
|
||||
var expected = '<span style="background-color:rgb(255,85,85)">red</span>';
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('palette, foreground', function () {
|
||||
var start = "\033[38;5;171m" + "foo" + "\033[0m";
|
||||
var expected = '<span style="color:rgb(215,95,255)">foo</span>';
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('palette, background', function () {
|
||||
var start = "\033[48;5;171m" + "foo" + "\033[0m";
|
||||
var expected = '<span style="background-color:rgb(215,95,255)">foo</span>';
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('combination of bold and palette', function () {
|
||||
var start = "\033[1;38;5;171m" + "foo" + "\033[0m";
|
||||
var expected = '<span style="color:rgb(215,95,255)">foo</span>';
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('combination of palette and bold', function () {
|
||||
var start = "\033[38;5;171;1m" + "foo" + "\033[0m";
|
||||
var expected = '<span style="color:rgb(215,95,255)">foo</span>';
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('transform extended colors (true color)', function () {
|
||||
it('foreground', function () {
|
||||
var start = "\033[38;2;42;142;242m" + "foo" + "\033[0m";
|
||||
var expected = '<span style="color:rgb(42,142,242)">foo</span>';
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
it('background', function () {
|
||||
var start = "\033[48;2;42;142;242m" + "foo" + "\033[0m";
|
||||
var expected = '<span style="background-color:rgb(42,142,242)">foo</span>';
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
it('both foreground and background', function () {
|
||||
var start = "\033[38;2;42;142;242;48;2;1;2;3m" + "foo" + "\033[0m";
|
||||
var expected = '<span style="color:rgb(42,142,242);background-color:rgb(1,2,3)">foo</span>';
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('themed colors', function () {
|
||||
it('should transform a foreground to html', function () {
|
||||
var attr = 0;
|
||||
var fg = 32;
|
||||
var start = "\033[" + fg + "m " + fg + " \033[0m";
|
||||
|
||||
var expected = "<span class=\"ansi-green-fg\"> " + fg + " </span>";
|
||||
|
||||
var au = new AnsiUp();
|
||||
au.use_classes = true;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should transform a attr;foreground to html', function () {
|
||||
var attr = 0;
|
||||
var fg = 32;
|
||||
var start = "\033[" + attr + ";" + fg + "m " + fg + " \033[0m";
|
||||
|
||||
var expected = "<span class=\"ansi-green-fg\"> " + fg + " </span>";
|
||||
|
||||
var au = new AnsiUp();
|
||||
au.use_classes = true;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should transform a bold attr;foreground to html', function () {
|
||||
var attr = 1;
|
||||
var fg = 32;
|
||||
var start = "\033[" + attr + ";" + fg + "m " + attr + ";" + fg + " \033[0m";
|
||||
|
||||
var expected = "<span class=\"ansi-bright-green-fg\"> " + attr + ";" + fg + " </span>";
|
||||
|
||||
var au = new AnsiUp();
|
||||
au.use_classes = true;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should transform a bold attr;background;foreground to html', function () {
|
||||
var attr = 1;
|
||||
var fg = 33;
|
||||
var bg = 42;
|
||||
var start = "\033[" + attr + ";" + bg + ";" + fg + "m " + attr + ";" + bg + ";" + fg + " \033[0m";
|
||||
|
||||
var expected = "<span class=\"ansi-bright-yellow-fg ansi-green-bg\"> " + attr + ";" + bg + ";" + fg + " </span>";
|
||||
|
||||
var au = new AnsiUp();
|
||||
au.use_classes = true;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should transform a complex multi-line sequence to html', function () {
|
||||
var attr = 1;
|
||||
var fg = 32;
|
||||
var bg = 42;
|
||||
var start = "\n \033[" + fg + "m " + fg + " \033[0m \n \033[" + bg + "m " + bg + " \033[0m \n zimpper ";
|
||||
|
||||
var expected = "\n <span class=\"ansi-green-fg\"> " + fg + " </span> \n <span class=\"ansi-green-bg\"> " + bg + " </span> \n zimpper ";
|
||||
|
||||
var au = new AnsiUp();
|
||||
au.use_classes = true;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
describe('transform extended colors (palette)', function () {
|
||||
it('system color, foreground', function () {
|
||||
var start = "\033[38;5;1m" + "red" + "\033[0m";
|
||||
var expected = '<span class="ansi-red-fg">red</span>';
|
||||
var au = new AnsiUp();
|
||||
au.use_classes = true;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('system color, foreground (bright)', function () {
|
||||
var start = "\033[38;5;9m" + "red" + "\033[0m";
|
||||
var expected = '<span class="ansi-bright-red-fg">red</span>';
|
||||
var au = new AnsiUp();
|
||||
au.use_classes = true;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('system color, background', function () {
|
||||
var start = "\033[48;5;1m" + "red" + "\033[0m";
|
||||
var expected = '<span class="ansi-red-bg">red</span>';
|
||||
var au = new AnsiUp();
|
||||
au.use_classes = true;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('system color, background (bright)', function () {
|
||||
var start = "\033[48;5;9m" + "red" + "\033[0m";
|
||||
var expected = '<span class="ansi-bright-red-bg">red</span>';
|
||||
var au = new AnsiUp();
|
||||
au.use_classes = true;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('palette, foreground', function () {
|
||||
var start = "\033[38;5;171m" + "foo" + "\033[0m";
|
||||
var expected = '<span style="color:rgb(215,95,255)">foo</span>';
|
||||
var au = new AnsiUp();
|
||||
au.use_classes = true;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('palette, background', function () {
|
||||
var start = "\033[48;5;171m" + "foo" + "\033[0m";
|
||||
var expected = '<span style="background-color:rgb(215,95,255)">foo</span>';
|
||||
var au = new AnsiUp();
|
||||
au.use_classes = true;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('combination of bold and palette', function () {
|
||||
var start = "\033[1;38;5;171m" + "foo" + "\033[0m";
|
||||
var expected = '<span style="color:rgb(215,95,255)">foo</span>';
|
||||
var au = new AnsiUp();
|
||||
au.use_classes = true;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('combination of palette and bold', function () {
|
||||
var start = "\033[38;5;171;1m" + "foo" + "\033[0m";
|
||||
var expected = '<span style="color:rgb(215,95,255)">foo</span>';
|
||||
var au = new AnsiUp();
|
||||
au.use_classes = true;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('transform extended colors (true color)', function () {
|
||||
it('foreground', function () {
|
||||
var start = "\033[38;2;42;142;242m" + "foo" + "\033[0m";
|
||||
var expected = '<span style="color:rgb(42,142,242)">foo</span>';
|
||||
var au = new AnsiUp();
|
||||
au.use_classes = true;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
it('background', function () {
|
||||
var start = "\033[48;2;42;142;242m" + "foo" + "\033[0m";
|
||||
var expected = '<span style="background-color:rgb(42,142,242)">foo</span>';
|
||||
var au = new AnsiUp();
|
||||
au.use_classes = true;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
it('both foreground and background', function () {
|
||||
var start = "\033[38;2;42;142;242;48;2;1;2;3m" + "foo" + "\033[0m";
|
||||
var expected = '<span style="color:rgb(42,142,242);background-color:rgb(1,2,3)">foo</span>';
|
||||
var au = new AnsiUp();
|
||||
au.use_classes = true;
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('ignore unsupported CSI', function () {
|
||||
it('should correctly convert a string similar to CSI', function () {
|
||||
// https://github.com/drudru/ansi_up/pull/15
|
||||
// "[1;31m" is a plain text. not an escape sequence.
|
||||
var start = "foo\033[1@bar[1;31mbaz\033[0m";
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
|
||||
// is all plain texts exist?
|
||||
l.should.containEql('foo');
|
||||
l.should.containEql('bar');
|
||||
l.should.containEql('baz');
|
||||
l.should.containEql('1;31m');
|
||||
});
|
||||
it('(italic)', function () {
|
||||
var start = "foo\033[3mbar\033[0mbaz";
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql('foobarbaz');
|
||||
});
|
||||
it('(cursor-up)', function () {
|
||||
var start = "foo\033[1Abar";
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql('foobar');
|
||||
});
|
||||
it('(scroll-left)', function () {
|
||||
// <ESC>[1 @ (including ascii space)
|
||||
var start = "foo\033[1 @bar";
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql('foobar');
|
||||
});
|
||||
it('(DECMC)', function () {
|
||||
var start = "foo\033[?11ibar";
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql('foobar');
|
||||
});
|
||||
/* I cannot find this in the XTERM specs
|
||||
it('(RLIMGCP)', function () {
|
||||
var start = "foo\033[<!3ibar";
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql('foobar');
|
||||
});
|
||||
*/
|
||||
it('(DECSCL)', function () {
|
||||
var start = "foo\033[61;0\"pbar"
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start);
|
||||
l.should.eql('foobar');
|
||||
});
|
||||
});
|
||||
|
||||
describe('buffering situations', function () {
|
||||
|
||||
it('should transform an incomplete prefix', function () {
|
||||
var attr = 0;
|
||||
var fg = 32;
|
||||
var start1 = "\033[" + attr + ";";
|
||||
var start2 = fg + "m " + fg + " \033[0m";
|
||||
|
||||
var expected = "<span style=\"color:rgb(0,187,0)\"> " + fg + " </span>";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start1);
|
||||
l.should.eql("");
|
||||
l = au.ansi_to_html(start2);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
it('should transform a lonely escape', function () {
|
||||
var attr = 0;
|
||||
var fg = 32;
|
||||
var start1 = "xyz \033";
|
||||
var start2 = "[" + attr + ";" + fg + "m " + fg + " \033[0m";
|
||||
|
||||
var expected = "<span style=\"color:rgb(0,187,0)\"> " + fg + " </span>";
|
||||
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_html(start1);
|
||||
l.should.eql("xyz ");
|
||||
l = au.ansi_to_html(start2);
|
||||
l.should.eql(expected);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('ansi to text', function () {
|
||||
it('should remove color sequence', function () {
|
||||
var start = "foo \033[1;32mbar\033[0m baz";
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_text(start);
|
||||
l.should.eql("foo bar baz");
|
||||
});
|
||||
it('should remove unsupported sequence', function () {
|
||||
var start = "foo \033[1Abar";
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_text(start);
|
||||
l.should.eql('foo bar');
|
||||
});
|
||||
it('should keep multiline', function () {
|
||||
var start = "foo \033[1;32mbar\nbaz\033[0m qux";
|
||||
var au = new AnsiUp();
|
||||
var l = au.ansi_to_text(start);
|
||||
l.should.eql("foo bar\nbaz qux");
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "none",
|
||||
"noEmitOnError": true,
|
||||
"removeComments": true,
|
||||
"sourceMap": true,
|
||||
"declaration": true,
|
||||
"noImplicitUseStrict": true,
|
||||
"outDir": "dist"
|
||||
},
|
||||
"exclude": [ "node_modules", "dist" ]
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.default = AnsiUp;
|
||||
}));
|
|
@ -0,0 +1,19 @@
|
|||
/* ansi_up.js
|
||||
* author : Dru Nelson
|
||||
* license : MIT
|
||||
* http://github.com/drudru/ansi_up
|
||||
*/
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define(['exports'], factory);
|
||||
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
|
||||
// CommonJS
|
||||
factory(exports);
|
||||
} else {
|
||||
// Browser globals
|
||||
var exp = {};
|
||||
factory(exp);
|
||||
root.AnsiUp = exp.default;
|
||||
}
|
||||
}(this, function (exports) {
|
|
@ -2,6 +2,7 @@
|
|||
"dependencies": {
|
||||
"accepts": "1.3.3",
|
||||
"ansi-html": "0.0.7",
|
||||
"ansi_up": "2.0.2",
|
||||
"aqb": "2.1.0",
|
||||
"babel-code-frame": "6.22.0",
|
||||
"chai": "3.5.0",
|
||||
|
|
|
@ -87,6 +87,7 @@ ArangoshRunLineNo = {}
|
|||
################################################################################
|
||||
|
||||
ArangoshFiles = {}
|
||||
AQLFiles = {}
|
||||
|
||||
################################################################################
|
||||
### @brief map the source files for error messages
|
||||
|
@ -113,6 +114,10 @@ FilterForTestcase = None
|
|||
STATE_BEGIN = 0
|
||||
STATE_ARANGOSH_OUTPUT = 'HTTP_LOUTPUT'
|
||||
STATE_ARANGOSH_RUN = 'ARANGOSH_OUTPUT'
|
||||
STATE_AQL = 'AQL'
|
||||
STATE_AQL_DS = 'AQL_DS'
|
||||
STATE_AQL_BIND = 'AQL_BV'
|
||||
STATE_AQL_EXPLAIN = 'AQL_EXPLAIN'
|
||||
|
||||
################################################################################
|
||||
### @brief option states
|
||||
|
@ -142,9 +147,14 @@ def generateArangoshHeader():
|
|||
|
||||
regularStartLine = re.compile(r'^(/// )? *@EXAMPLE_ARANGOSH_OUTPUT{([^}]*)}')
|
||||
runLine = re.compile(r'^(/// )? *@EXAMPLE_ARANGOSH_RUN{([^}]*)}')
|
||||
|
||||
aqlLine = re.compile(r'^(/// )? *@EXAMPLE_AQL{([^}]*)}')
|
||||
aqlDataSetLine = re.compile(r'^(/// )? *@DATASET{([^}]*)}')
|
||||
aqlExplainLine = re.compile(r'^(/// )? *@EXPLAIN{(TRUE|FALSE)}')
|
||||
aqlBindvaluesLine = re.compile(r'^(/// )? *@BV (.*)')
|
||||
|
||||
def matchStartLine(line, filename):
|
||||
global regularStartLine, errorStartLine, runLine, FilterForTestcase, filterTestList
|
||||
global regularStartLine, errorStartLine, runLine
|
||||
global aqlLine, FilterForTestcase, filterTestList
|
||||
errorName = ""
|
||||
m = regularStartLine.match(line)
|
||||
|
||||
|
@ -159,6 +169,7 @@ def matchStartLine(line, filename):
|
|||
|
||||
# if we match for filters, only output these!
|
||||
if ((FilterForTestcase != None) and not FilterForTestcase.match(name)):
|
||||
print >> sys.stderr, "Arangosh: filtering out testcase '%s'" %name
|
||||
filterTestList.append(name)
|
||||
return("", STATE_BEGIN);
|
||||
|
||||
|
@ -169,7 +180,7 @@ def matchStartLine(line, filename):
|
|||
if m:
|
||||
strip = m.group(1)
|
||||
name = m.group(2)
|
||||
|
||||
|
||||
if name in ArangoshFiles:
|
||||
print >> sys.stderr, "%s\nduplicate test name '%s' in file %s!\n%s\n" % ('#' * 80, name, filename, '#' * 80)
|
||||
sys.exit(1)
|
||||
|
@ -177,14 +188,59 @@ def matchStartLine(line, filename):
|
|||
# if we match for filters, only output these!
|
||||
if ((FilterForTestcase != None) and not FilterForTestcase.match(name)):
|
||||
filterTestList.append(name)
|
||||
print >> sys.stderr, "CuRL: filtering out testcase '%s'" %name
|
||||
return("", STATE_BEGIN);
|
||||
|
||||
ArangoshFiles[name] = True
|
||||
return (name, STATE_ARANGOSH_RUN)
|
||||
|
||||
m = aqlLine.match(line)
|
||||
if m:
|
||||
strip = m.group(1)
|
||||
name = m.group(2)
|
||||
|
||||
if name in AQLFiles:
|
||||
print >> sys.stderr, "%s\nduplicate test name '%s' in file %s!\n%s\n" % ('#' * 80, name, filename, '#' * 80)
|
||||
sys.exit(1)
|
||||
|
||||
# if we match for filters, only output these!
|
||||
if ((FilterForTestcase != None) and not FilterForTestcase.match(name)):
|
||||
print >> sys.stderr, "AQL: filtering out testcase '%s'" %name
|
||||
filterTestList.append(name)
|
||||
return("", STATE_BEGIN);
|
||||
|
||||
AQLFiles[name] = True
|
||||
return (name, STATE_AQL)
|
||||
|
||||
# Not found, remain in STATE_BEGIN
|
||||
return ("", STATE_BEGIN)
|
||||
|
||||
def matchAqlLine(line, filename, oldState):
|
||||
global aqlDataSetLine, aqlBindvaluesLine
|
||||
m = aqlDataSetLine.match(line)
|
||||
|
||||
if m:
|
||||
strip = m.group(1)
|
||||
name = m.group(2)
|
||||
return (name, STATE_AQL_DS)
|
||||
|
||||
m = aqlExplainLine.match(line)
|
||||
|
||||
if m:
|
||||
strip = m.group(1)
|
||||
TRUExorFALSE = m.group(2)
|
||||
return (TRUExorFALSE, STATE_AQL_EXPLAIN)
|
||||
|
||||
m = aqlBindvaluesLine.match(line)
|
||||
|
||||
if m:
|
||||
strip = m.group(1)
|
||||
bindvalueStart = m.group(2)
|
||||
return (bindvalueStart, STATE_AQL_BIND)
|
||||
|
||||
# Not found, remain in STATE_AQL
|
||||
return (line, oldState)
|
||||
|
||||
endExample = re.compile(r'^(/// )? *@END_EXAMPLE_')
|
||||
#r5 = re.compile(r'^ +')
|
||||
|
||||
|
@ -192,6 +248,10 @@ TESTLINES="testlines"
|
|||
TYPE="type"
|
||||
LINE_NO="lineNo"
|
||||
STRING="string"
|
||||
AQL="aql"
|
||||
AQLDS="aql_dataset"
|
||||
AQLBV="aql_bindvalues"
|
||||
AQLEXPLAIN="aql_explain"
|
||||
|
||||
################################################################################
|
||||
### @brief loop over the lines of one input file
|
||||
|
@ -229,8 +289,29 @@ def analyzeFile(f, filename):
|
|||
if state == STATE_ARANGOSH_RUN:
|
||||
RunTests[name][LINE_NO] = lineNo;
|
||||
RunTests[name][STRING] = "";
|
||||
|
||||
if state == STATE_AQL:
|
||||
RunTests[name][LINE_NO] = lineNo;
|
||||
RunTests[name][AQL] = "";
|
||||
continue
|
||||
|
||||
if state == STATE_AQL:
|
||||
(data, aqlState) = matchAqlLine(line, filename, state)
|
||||
if aqlState == STATE_AQL_BIND:
|
||||
RunTests[name][AQLBV] = data
|
||||
state = aqlState
|
||||
continue
|
||||
if aqlState == STATE_AQL_EXPLAIN:
|
||||
RunTests[name][AQLEXPLAIN] = data
|
||||
# flip back to aql - query will come.
|
||||
state = STATE_AQL
|
||||
continue
|
||||
if aqlState == STATE_AQL_DS:
|
||||
RunTests[name][AQLDS] = data
|
||||
# flip back to aql - query will come.
|
||||
state = STATE_AQL
|
||||
continue
|
||||
|
||||
# we are within a example
|
||||
line = line[len(strip):]
|
||||
showCmd = True
|
||||
|
@ -246,7 +327,8 @@ def analyzeFile(f, filename):
|
|||
continue
|
||||
|
||||
line = line.lstrip('/');
|
||||
line = line.lstrip(' ');
|
||||
if state != STATE_AQL:
|
||||
line = line.lstrip(' ');
|
||||
if state == STATE_ARANGOSH_OUTPUT:
|
||||
line = line.replace("\\", "\\\\").replace("'", "\\'")
|
||||
#print line
|
||||
|
@ -287,6 +369,10 @@ def analyzeFile(f, filename):
|
|||
RunTests[name][TESTLINES].append([line, showCmd, lineNo])
|
||||
elif state == STATE_ARANGOSH_RUN:
|
||||
RunTests[name][STRING] += line + "\n"
|
||||
elif state == STATE_AQL:
|
||||
RunTests[name][AQL] += line + "\n"
|
||||
elif state == STATE_AQL_BIND:
|
||||
RunTests[name][AQLBV] += line + "\n"
|
||||
|
||||
|
||||
def generateSetupFunction():
|
||||
|
@ -332,9 +418,9 @@ def generateArangoshOutput(testName):
|
|||
escapeBS.sub(doubleBS, MapSourceFiles[testName])
|
||||
)
|
||||
except Exception as x:
|
||||
print x
|
||||
print testName
|
||||
print value
|
||||
print >> sys.stderr,x
|
||||
print >> sys.stderr,testName
|
||||
print >> sys.stderr,value
|
||||
raise
|
||||
|
||||
for l in value[TESTLINES]:
|
||||
|
@ -429,6 +515,79 @@ def generateArangoshRun(testName):
|
|||
### @brief generate arangosh run
|
||||
################################################################################
|
||||
|
||||
def generateAQL(testName):
|
||||
value = RunTests[testName]
|
||||
startLineNo = RunTests[testName][LINE_NO]
|
||||
if not AQLBV in value:
|
||||
value[AQLBV] = "{}"
|
||||
|
||||
if not AQLDS in value:
|
||||
value[AQLDS] = ""
|
||||
|
||||
if not AQLEXPLAIN in value:
|
||||
value[AQLEXPLAIN] = 'false'
|
||||
|
||||
print '''
|
||||
%s
|
||||
/// %s
|
||||
(() => {
|
||||
internal.startPrettyPrint(true);
|
||||
internal.stopColorPrint(true);
|
||||
const testName = '%s';
|
||||
const lineCount = 0;
|
||||
const startLineCount = %d;
|
||||
const outputDir = '%s';
|
||||
const sourceFile = '%s';
|
||||
const startTime = time();
|
||||
output = '';
|
||||
''' % (
|
||||
('/'*80),
|
||||
testName,
|
||||
testName,
|
||||
startLineNo,
|
||||
escapeBS.sub(doubleBS, OutputDir),
|
||||
escapeBS.sub(doubleBS, MapSourceFiles[testName])
|
||||
)
|
||||
print " const query = `" + value[AQL] + "`;"
|
||||
print " const bv = " + value[AQLBV] + ";"
|
||||
print " const ds = '" + value[AQLDS] + "';"
|
||||
print " const explainAql = " + value[AQLEXPLAIN].lower() + ";"
|
||||
print '''
|
||||
if (ds !== '') {
|
||||
exds[ds].removeDS();
|
||||
exds[ds].createDS();
|
||||
}
|
||||
|
||||
output += "@Q:\\n"
|
||||
output += highlight("js", query);
|
||||
if (Object.keys(bv).length > 0) {
|
||||
output += "@B\\n"
|
||||
jsonAppender(JSON.stringify(bv, null, 2));
|
||||
}
|
||||
output += "\\n@R\\n";
|
||||
|
||||
if (explainAql) {
|
||||
const explainResult = require('@arangodb/aql/explainer').explain({bindVars:bv, query:query}, {}, false);
|
||||
ansiAppender(explainResult);
|
||||
} else {
|
||||
const result = db._query(query, bv).toArray();
|
||||
jsonAppender(JSON.stringify(result, null, 2));
|
||||
}
|
||||
|
||||
if (ds !== '') {
|
||||
exds[ds].removeDS();
|
||||
}
|
||||
fs.write(outputDir + fs.pathSeparator + testName + '.generated', output);
|
||||
print("[" + (time () - startTime) + "s] done with " + testName);
|
||||
checkForOrphanTestCollections('not all collections were cleaned up after ' + sourceFile + ' Line[' + startLineCount + '] [' + testName + ']:');
|
||||
})();
|
||||
|
||||
'''
|
||||
|
||||
################################################################################
|
||||
### @brief generate arangosh run
|
||||
################################################################################
|
||||
|
||||
def generateArangoshShutdown():
|
||||
print '''
|
||||
if (allErrors.length > 0) {
|
||||
|
@ -443,7 +602,6 @@ if (allErrors.length > 0) {
|
|||
|
||||
def loopDirectories():
|
||||
global ArangoshSetup, OutputDir, FilterForTestcase
|
||||
|
||||
argv = sys.argv
|
||||
argv.pop(0)
|
||||
filenames = []
|
||||
|
@ -501,7 +659,6 @@ def loopDirectories():
|
|||
for filename in filenames:
|
||||
if (filename.find("#") < 0):
|
||||
f = open(filename, "r")
|
||||
|
||||
analyzeFile(f, filename)
|
||||
|
||||
f.close()
|
||||
|
@ -518,12 +675,18 @@ def generateTestCases():
|
|||
generateArangoshOutput(thisTest)
|
||||
elif RunTests[thisTest][TYPE] == STATE_ARANGOSH_RUN:
|
||||
generateArangoshRun(thisTest)
|
||||
elif RunTests[thisTest][TYPE] == STATE_AQL:
|
||||
generateAQL(thisTest)
|
||||
|
||||
|
||||
################################################################################
|
||||
### @brief main
|
||||
################################################################################
|
||||
|
||||
loopDirectories()
|
||||
if len(RunTests) == 0:
|
||||
print >> sys.stderr, "no testcases generated - bailing out"
|
||||
raise Exception("no Testcases")
|
||||
print >> sys.stderr, "filtering test %d cases" %(len(filterTestList))
|
||||
|
||||
generateArangoshHeader()
|
||||
|
|
Loading…
Reference in New Issue