Implements {ex,im}porting {as,from} ANSI.

Bump to v1.1.2.
This commit is contained in:
Lucio Andrés Illanes Albornoz 2019-08-25 18:39:49 +02:00
parent a002cb96bb
commit 922b9b6c5d
14 changed files with 285 additions and 88 deletions

View File

@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<widget id="com.lalbornoz.MiRCART" version="1.1.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"> <widget id="com.lalbornoz.MiRCART" version="1.1.2" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<author email="lucio@lucioillanes.de" href="https://github.com/lalbornoz/MiRCART#readme"> <author email="lucio@lucioillanes.de" href="https://github.com/lalbornoz/MiRCART#readme">
Lucio Andrés Illanes Albornoz &lt;lucio@lucioillanes.de&gt;, based on work by JOLLO NET NA Lucio Andrés Illanes Albornoz &lt;lucio@lucioillanes.de&gt;, based on work by JOLLO NET NA
</author> </author>

2
MiRCART-cordoba/package-lock.json generated vendored
View File

@ -1,6 +1,6 @@
{ {
"name": "MiRCART-cordoba", "name": "MiRCART-cordoba",
"version": "1.1.0", "version": "1.1.2",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View File

@ -30,5 +30,5 @@
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"version": "1.1.0" "version": "1.1.2"
} }

2
MiRCART-nw/package-lock.json generated vendored
View File

@ -1,5 +1,5 @@
{ {
"name": "MiRCART", "name": "MiRCART",
"version": "1.1.0", "version": "1.1.2",
"lockfileVersion": 1 "lockfileVersion": 1
} }

View File

@ -18,7 +18,7 @@
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"version": "1.1.0", "version": "1.1.2",
"window": { "window": {
"title": "MiRCART (standalone NW app)", "title": "MiRCART (standalone NW app)",
"toolbar": true, "toolbar": true,

View File

@ -20,10 +20,12 @@ body.grid #palette_wrapper > div:first-child {
/* {{{ .initial styles */ /* {{{ .initial styles */
.initial #add_custom_el, .initial #add_custom_el,
.initial #doc_el, .initial #doc_el,
.initial #export_button, .initial #export_format_el,
.initial #format_el, .initial #export_textarea,
.initial #grid_el, .initial #import_button,
.initial #import_format_el,
.initial #import_textarea, .initial #import_textarea,
.initial #grid_el,
.initial #load_el, .initial #load_el,
.initial #save_el, .initial #save_el,
.initial #vertical_checkbox { .initial #vertical_checkbox {
@ -109,6 +111,7 @@ body.grid #palette_wrapper > div:first-child {
.hidden { visibility: hidden; } .hidden { visibility: hidden; }
.loading .vertical #ui_wrapper { clear: none } .loading .vertical #ui_wrapper { clear: none }
#experimental_palette_toggle.focused { box-shadow: none; } #experimental_palette_toggle.focused { box-shadow: none; }
#export_wrapper { display: none; }
#import_wrapper { display: none; } #import_wrapper { display: none; }
#tools_block > * { cursor: crosshair; } #tools_block > * { cursor: crosshair; }
#workspace_wrapper { width: 100%; } #workspace_wrapper { width: 100%; }
@ -247,6 +250,16 @@ textarea, input[type=text], body {
top: 0; top: 0;
width: 30px; width: 30px;
} }
#export_textarea {
background: #001100;
border: 1px solid #333333;
color: #00FF00;
font-family: 'FixedsysExcelsior301Regular';
font-size: 12pt;
height: 300px;
outline: 0;
width: 37vw;
}
#import_textarea { #import_textarea {
background: #001100; background: #001100;
border: 1px solid #333333; border: 1px solid #333333;

View File

@ -7,7 +7,7 @@
<link charset="utf-8" href="../css/fonts.css" rel="stylesheet" type="text/css" /> <link charset="utf-8" href="../css/fonts.css" rel="stylesheet" type="text/css" />
<link charset="utf-8" href="../css/help.css" rel="stylesheet" type="text/css" /> <link charset="utf-8" href="../css/help.css" rel="stylesheet" type="text/css" />
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" /> <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<title>MiRCART v1.1.0 documentation</title> <title>MiRCART v1.1.2 documentation</title>
</head> </head>
<!-- }}} --> <!-- }}} -->
<!-- {{{ BODY --> <!-- {{{ BODY -->

View File

@ -46,7 +46,7 @@ function bind () {
var ae = document.activeElement var ae = document.activeElement
if (ae !== import_textarea) { if ((ae !== export_textarea) && (ae !== import_textarea)) {
cursor_input.focus() cursor_input.focus()
} }

View File

@ -2,50 +2,55 @@ var clipboard = (function () {
var exports = { var exports = {
format: "mirc", format: "mirc",
importing: false, exporting: false,
visible: false, visible: false,
canvas: document.createElement("canvas"), canvas: document.createElement("canvas"),
canvas_r: document.createElement("canvas"), canvas_r: document.createElement("canvas"),
bind: function () { bind: function () {
import_button.addEventListener("click", exports.import_colorcode) export_textarea.addEventListener("focus", exports.export_focus)
import_textarea.addEventListener("focus", exports.focus) export_textarea.addEventListener("blur", exports.blur)
import_textarea.addEventListener("blur", exports.blur) import_button.addEventListener("click", exports.import_click)
import_textarea.addEventListener('paste', exports.paste) import_textarea.addEventListener("focus", exports.import_focus)
import_textarea.addEventListener("paste", exports.paste)
}, },
setFormat: function (name) { setFormat: function (name) {
return function () { return function () {
clipboard.format = name clipboard.format = name
if (! clipboard.importing) { clipboard.export_data() } if (! clipboard.exporting) { clipboard.export_data() }
} }
}, },
show: function () { import_wrapper.style.display = "block"; clipboard.visible = true; changed = false }, import_hide: function () { import_wrapper.style.display = "none"; clipboard.visible = false },
hide: function () { import_wrapper.style.display = "none"; clipboard.visible = false }, import_show: function () { import_wrapper.style.display = "block"; clipboard.visible = true; },
focus: function () { export_hide: function () { export_wrapper.style.display = "none"; clipboard.visible = false },
if (! clipboard.importing) { export_show: function () { export_wrapper.style.display = "block"; clipboard.visible = true; changed = false },
export_focus: function () {
if (! clipboard.exporting) {
export_textarea.focus()
export_textarea.select()
}
},
import_focus: function () {
import_textarea.focus() import_textarea.focus()
import_textarea.select() import_textarea.select()
}
}, },
blur: function () { blur: function () {
}, },
import_mode: function () { export_mode: function () {
focus() exports.export_focus()
clipboard.importing = true clipboard.exporting = true
format_el.style.display = 'none' export_cutoff_warning_el.style.display = "none"
cutoff_warning_el.style.display = 'none' export_format_el.style.display = "inline"
import_buttons.style.display = "inline" clipboard.export_data()
import_textarea.value = ""
}, },
export_mode: function () { import_mode: function () {
focus() import_button.style.display = "inline"
clipboard.importing = false import_format_el.style.display = "inline"
import_buttons.style.display = "none" import_textarea.value = ""
format_el.style.display = 'inline' exports.import_focus()
cutoff_warning_el.style.display = 'none'
clipboard.export_data()
}, },
paste: function (e) { paste: function (e) {
@ -65,7 +70,101 @@ var clipboard = (function () {
}) })
}, },
import_colorcode: function (data, no_undo) { import_click: function (data, no_undo) {
switch (controls.load_format.value) {
case 'ansi':
exports.import_ansi(data, no_undo)
break
case 'mirc':
exports.import_mirc(data, no_undo)
break
}
},
import_ansi: function (data, no_undo) {
if (data && data.preventDefault) {
data = import_textarea.value
} else {
data = data || import_textarea.value
}
var to_json = function(string, opts){
var lines_in = string.split(/\r?\n/)
var lines_out = []
var w = 0, h = 0
for (var y = 0; y < lines_in.length; y++) {
var bg = 1, fg = 15
var cells = [], line = lines_in[y]
if (line.length === 0) {
continue
} else {
for (var x = 0; x < line.length; x++) {
var m = line.substring(x).match(/^\x1b\[(\d{1,3});(\d{1,3})m/);
if (m !== null) {
if (ansi_bg_import[parseInt(m[1])] !== undefined) {
bg = ansi_bg_import[parseInt(m[1])];
}
if (ansi_fg_import[parseInt(m[1])] !== undefined) {
fg = ansi_fg_import[parseInt(m[1])];
}
if (ansi_bg_import[parseInt(m[2])] !== undefined) {
bg = ansi_bg_import[parseInt(m[2])];
}
if (ansi_fg_import[parseInt(m[2])] !== undefined) {
fg = ansi_fg_import[parseInt(m[2])];
}
x += (m[0].length - 1)
} else {
var m = line.substring(x).match(/^\x1b\[(\d{1,3})m/);
if (m !== null) {
if (ansi_bg_import[parseInt(m[1])] !== undefined) {
bg = ansi_bg_import[parseInt(m[1])];
}
if (ansi_fg_import[parseInt(m[1])] !== undefined) {
fg = ansi_fg_import[parseInt(m[1])];
}
x += (m[0].length - 1)
} else {
cells.push({bg: bg, fg: fg, value: line[x]})
}
}
}
if (cells.length > 0) {
if (w < cells.length) {
w = cells.length
}
lines_out.push(cells); h++;
}
}
}
return {h: h, lines: lines_out, w: w}
}
var json = to_json(data, {fg:0, bg:1})
if (!no_undo) undo.new()
if (!no_undo) undo.save_rect(0,0, canvas.w, canvas.h)
if (json.w !== canvas.w || json.h !== canvas.h){
if (!no_undo) undo.save_size(canvas.w, canvas.h)
canvas.resize(json.w, json.h, true)
}
canvas.clear()
for (var y = 0, line; line = json.lines[y]; y++){
var row = canvas.aa[y]
for (var x = 0, char; char = line[x]; x++){
var lex = row[x]
lex.char = char.value
lex.fg = char.fg
lex.bg = char.bg
lex.opacity = 1
lex.build()
}
}
current_filetool && current_filetool.blur()
},
import_mirc: function (data, no_undo) {
if (data && data.preventDefault) { if (data && data.preventDefault) {
data = import_textarea.value data = import_textarea.value
} else { } else {
@ -167,17 +266,20 @@ var clipboard = (function () {
case 'ascii': case 'ascii':
output = canvas.ascii() output = canvas.ascii()
break break
case 'ansi':
output = canvas.ansi()
break
case 'mirc': case 'mirc':
output = canvas.mirc({cutoff: 425}) output = canvas.mirc({cutoff: 425})
break break
} }
if (output.cutoff){ if (output.cutoff){
cutoff_warning_el.style.display = 'block' export_cutoff_warning_el.style.display = 'block'
} else { } else {
cutoff_warning_el.style.display = 'none' export_cutoff_warning_el.style.display = 'none'
} }
import_textarea.value = output export_textarea.value = output
clipboard.focus() clipboard.export_focus()
return output return output
}, },

View File

@ -68,39 +68,77 @@ Object.keys(css_lookup).forEach(function(color){
}) })
var ansi_fg = [ var ansi_fg = [
97, // white 97, // Bright White
30, // black 30, // Black
34, // dark blue 94, // Light Blue
32, // green 32, // Green
91, // light red 91, // Red
31, // dark red 31, // Light Red
35, // purple 35, // Pink
33, // "dark yellow" (orange?) 33, // Yellow
93, // "light yellow" 93, // Light Yellow
92, // light green 92, // Light Green
36, // cyan (teal?) 36, // Cyan
96, // light cyan 96, // Light Cyan
94, // light blue 34, // Blue
95, // light magenta 95, // Light Pink
90, // dark gray 90, // Grey
37, // light gray 37, // Light Grey
] ]
var ansi_fg_import = {
97: 0, // Bright White
30: 1, // Black
94: 2, // Light Blue
32: 3, // Green
91: 4, // Red
31: 5, // Light Red
35: 6, // Pink
33: 7, // Yellow
93: 8, // Light Yellow
92: 9, // Light Green
36: 10, // Cyan
96: 11, // Light Cyan
34: 12, // Blue
95: 13, // Light Pink
90: 14, // Grey
37: 15, // Light Grey
}
var ansi_bg = [ var ansi_bg = [
107, // white 107, // Bright White
40, // black 40, // Black
44, // dark blue 104, // Light Blue
42, // green 42, // Green
101, // light red 101, // Red
41, // dark red 41, // Light Red
45, // purple 45, // Pink
43, // yellow (orange) 43, // Yellow
103, // light yellow 103, // Light Yellow
102, // light green 102, // Light Green
46, // cyan (teal?) 46, // Cyan
106, // light cyan 106, // Light Cyan
104, // light blue 44, // Blue
105, // light magenta 105, // Light Pink
100, // dark gray 100, // Grey
47, // light gray 47, // Light Grey
] ]
var ansi_bg_import = {
107: 0, // Bright White
40: 1, // Black
104: 2, // Light Blue
42: 3, // Green
101: 4, // Red
41: 5, // Light Red
45: 6, // Pink
43: 7, // Yellow
103: 8, // Light Yellow
102: 9, // Light Green
46: 10, // Cyan
106: 11, // Light Cyan
44: 12, // Blue
105: 13, // Light Pink
100: 14, // Grey
47: 15, // Light Grey
}

View File

@ -47,15 +47,29 @@ Lex.prototype.sanitize = function(){
default: return this.char default: return this.char
} }
} }
Lex.prototype.ansi = function(bg_, fg_){
var char = this.char || " "
var charIsNaN = isNaN(parseInt(char))
if ((bg_ == this.fg) && (fg_ == this.bg)) {
bg_ = this.bg; fg_ = this.fg
return [bg_, fg_, "\x1b[7m" + char]
} else if ((bg_ != this.bg) && (fg_ != this.fg)) {
bg_ = this.bg; fg_ = this.fg;
return [bg_, fg_, "\x1b[" + ansi_bg[bg_] + ";" + ansi_fg[fg_] + "m" + char]
} else if (bg_ != this.bg) {
bg_ = this.bg
return [bg_, fg_, "\x1b[" + ansi_bg[bg_] + "m" + char]
} else if (fg_ != this.fg) {
fg_ = this.fg
return [bg_, fg_, "\x1b[" + ansi_fg[fg_] + "m" + char]
}
}
Lex.prototype.mirc = function(bg_, fg_){ Lex.prototype.mirc = function(bg_, fg_){
var char = this.char || " " var char = this.char || " "
var charIsNaN = isNaN(parseInt(char)) var charIsNaN = isNaN(parseInt(char))
if ((bg_ == this.fg) && (fg_ == this.bg)) { if ((bg_ == this.fg) && (fg_ == this.bg)) {
bg_ = this.bg; fg_ = this.fg bg_ = this.bg; fg_ = this.fg
return [bg_, fg_, "\x16" + char] return [bg_, fg_, "\x16" + char]
} else if ((bg_ != this.bg) && (fg_ == this.fg)) {
bg_ = this.bg
return [bg_, fg_, "\x03," + ((this.bg&15) < 10 && !charIsNaN ? "0" : "") + (this.bg&15) + char]
} else if ((bg_ == this.bg) && (fg_ != this.fg)) { } else if ((bg_ == this.bg) && (fg_ != this.fg)) {
fg_ = this.fg fg_ = this.fg
return [bg_, fg_, "\x03" + ((this.fg&15) < 10 && !charIsNaN ? "0" : "") + (this.fg&15) + char] return [bg_, fg_, "\x03" + ((this.fg&15) < 10 && !charIsNaN ? "0" : "") + (this.fg&15) + char]

View File

@ -239,6 +239,26 @@ Matrix.prototype.ascii = function () {
var txt = lines.join("\n") var txt = lines.join("\n")
return txt return txt
} }
Matrix.prototype.ansi = function (opts) {
var lines = this.aa.map(function(row, y){
var last, line = ""
row.forEach(function(lex, x) {
var bg_ = -1, fg_ = -1
if (lex.eqColor(last)) {
line += lex.sanitize()
}
else {
[bg_, fg_, line_] = lex.ansi(bg_, fg_)
line += line_; last = lex;
}
})
return line
})
var txt = lines.filter(function(line){ return line.length > 0 }).join('\n')
return txt
}
Matrix.prototype.mirc = function (opts) { Matrix.prototype.mirc = function (opts) {
var cutoff = false var cutoff = false
var lines = this.aa.map(function(row, y){ var lines = this.aa.map(function(row, y){

View File

@ -131,26 +131,32 @@ var controls = (function(){
ClipboardTool = FileTool.extend({ ClipboardTool = FileTool.extend({
blur: function(){ blur: function(){
this.__blur() this.__blur()
clipboard.hide() clipboard.export_hide()
clipboard.import_hide()
} }
}) })
controls.save = new ClipboardTool (save_el) controls.save = new ClipboardTool (save_el)
controls.save.use = function(){ controls.save.use = function(){
clipboard.show() clipboard.export_show()
clipboard.export_mode() clipboard.export_mode()
} }
controls.load = new ClipboardTool (load_el) controls.load = new ClipboardTool (load_el)
controls.load.use = function(){ controls.load.use = function(){
// console.log("use") clipboard.import_show()
clipboard.show()
clipboard.import_mode() clipboard.import_mode()
} }
controls.save_format = new RadioGroup(format_el) controls.load_format = new RadioGroup(import_format_el)
controls.load_format.name = 'load_format'
controls.load_format.memorable = true
var cs = controls.load_format.controls
//
controls.save_format = new RadioGroup(export_format_el)
controls.save_format.name = 'save_format' controls.save_format.name = 'save_format'
controls.save_format.memorable = true controls.save_format.memorable = true
var cs = controls.save_format.controls var cs = controls.save_format.controls
cs.mirc.use = cs.ascii.use = function(){ cs.mirc.use = cs.ansi.use = cs.ascii.use = function(){
clipboard.export_data() clipboard.export_data()
} }
// //

View File

@ -9,7 +9,7 @@
<link charset="utf-8" href="assets/css/sally.css" rel="stylesheet" type="text/css" /> <link charset="utf-8" href="assets/css/sally.css" rel="stylesheet" type="text/css" />
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" /> <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<meta content="width=device-width, maximum-scale=1.0, user-scalable=yes" name="viewport" /> <meta content="width=device-width, maximum-scale=1.0, user-scalable=yes" name="viewport" />
<title>MiRCART v1.1.0</title> <title>MiRCART v1.1.2</title>
</head> </head>
<!-- }}} --> <!-- }}} -->
<!-- {{{ BODY --> <!-- {{{ BODY -->
@ -72,13 +72,17 @@
<span id="grid_el" class="tool">_ grid</span> <span id="grid_el" class="tool">_ grid</span>
<span id="vertical_checkbox" class="tool">x vertical</span> <span id="vertical_checkbox" class="tool">x vertical</span>
</div> </div>
<div id="export_wrapper">
<span id="export_format_el">ascii ansi *mirc</span>
<div id="gallery_wrapper"></div><br />
<div id="export_cutoff_warning_el">character limit of 425 exceeded</div>
<textarea id="export_textarea" cols="100" rows="30"></textarea>
</div>
<div id="import_wrapper"> <div id="import_wrapper">
<span id="format_el">ascii *mirc</span> <span id="import_format_el">ansi *mirc</span>
<span id="import_buttons"> <span id="import_buttons">
<button id="import_button">import</button> <button id="import_button">import</button>
</span> </span><br />
<div id="gallery_wrapper" /><br />
<div id="cutoff_warning_el">character limit of 425 exceeded</div>
<textarea id="import_textarea" cols="100" rows="30"></textarea> <textarea id="import_textarea" cols="100" rows="30"></textarea>
</div> </div>
</div> </div>