Merge pull request #68 from eepp/weechat-js-full-styling

Full styling
This commit is contained in:
David Cormier 2013-10-26 08:50:37 -07:00
commit c1612f4c46
6 changed files with 3169 additions and 858 deletions

View file

@ -49,6 +49,9 @@ table {
tr { tr {
line-height: 100%; line-height: 100%;
} }
tr:hover {
background-color: #222222;
}
td.time { td.time {
padding-right: 5px; padding-right: 5px;
vertical-align: top; vertical-align: top;
@ -59,6 +62,7 @@ td.prefix {
vertical-align: top; vertical-align: top;
padding-right: 5px; padding-right: 5px;
white-space: pre; white-space: pre;
border-right: 1px solid #444;
} }
td.message { td.message {
word-wrap: break-word; word-wrap: break-word;
@ -85,7 +89,7 @@ hr {
body { body {
color: #ddd; color: #ddd;
background-color: #222; background-color: #181818;
padding-left: 0; padding-left: 0;
padding-right: 5px; padding-right: 5px;
padding-bottom:70px; padding-bottom:70px;
@ -175,13 +179,14 @@ input[type=text], input[type=password], .badge {
} }
#bufferlines { #bufferlines {
font-family: 'Terminus', 'Inconsolata', 'Consolas', 'Monaco', 'Ubuntu Mono', monospace; font-family: 'Terminus', 'Consolas', 'Monaco', 'Inconsolata', 'Ubuntu Mono', monospace;
position: relative; position: relative;
height: 99%; height: 99%;
overflow-y: auto; overflow-y: auto;
margin-left: 14%; margin-left: 14%;
width: auto; width: auto;
top: 25px; /* topbar */ top: 25px; /* topbar */
padding-bottom: 10px;
} }
#bufferlines .btn { #bufferlines .btn {
font-family: sans-serif; font-family: sans-serif;
@ -190,6 +195,9 @@ input[type=text], input[type=password], .badge {
.navbar-fixed-bottom { .navbar-fixed-bottom {
margin: 0 5px 0 14%; margin: 0 5px 0 14%;
} }
.navbar-inverse {
background-color: #181818;
}
@media (max-width: 968px) { @media (max-width: 968px) {
#sidebar, #bufferlines { #sidebar, #bufferlines {
position: relative; position: relative;

1929
css/style.css Normal file

File diff suppressed because it is too large Load diff

View file

@ -7,6 +7,7 @@
<title ng-bind-template="WeeChat {{ pageTitle}}"></title> <title ng-bind-template="WeeChat {{ pageTitle}}"></title>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" media="screen"> <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" media="screen">
<link rel="shortcut icon" type="image/png" href="img/favicon.png" > <link rel="shortcut icon" type="image/png" href="img/favicon.png" >
<link href="css/style.css" rel="stylesheet" media="screen">
<link href="css/glowingbear.css" rel="stylesheet" media="screen"> <link href="css/glowingbear.css" rel="stylesheet" media="screen">
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.2/angular.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.2/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.2/angular-sanitize.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.2/angular-sanitize.min.js"></script>
@ -91,7 +92,8 @@
<div>To start using, please enable relay in your WeeChat client: <div>To start using, please enable relay in your WeeChat client:
<pre> <pre>
/set relay.network.password yourpassword /set relay.network.password yourpassword
/relay add weechat 9001</pre> /relay add weechat 9001
</pre>
<span class="label label-warning">WeeChat version 0.4.2 or higher is required.</span><br> <span class="label label-warning">WeeChat version 0.4.2 or higher is required.</span><br>
The communication goes directly between your browser and your weechat in clear text. The communication goes directly between your browser and your weechat in clear text.
Connection settings are saved between sessions, including password, in your own browser. Connection settings are saved between sessions, including password, in your own browser.
@ -217,12 +219,12 @@
<tr class="bufferline" ng-repeat-start="bufferline in activeBuffer().lines"> <tr class="bufferline" ng-repeat-start="bufferline in activeBuffer().lines">
<td ng-hide="notimestamp" class="time"> <td ng-hide="notimestamp" class="time">
<span class="date text-muted"> <span class="date text-muted">
{{ bufferline.date | date:'HH:mm' }} <span class="cof-chat_time cob-chat_time coa-chat_time">{{ bufferline.date | date:'HH' }}</span><span class="cof-chat_time_delimiters cob-chat_time_delimiters coa-chat_time_delimiters">:</span><span class="cof-chat_time cob-chat_time coa-chat_time">{{ bufferline.date | date:'mm' }}</span>
</span> </span>
</td> </td>
<td class="prefix vertical-line"><span ng-repeat="part in bufferline.prefix" style="{{ part.fg }}">{{ part.text }}</span></td> <td class="prefix"><span ng-repeat="part in bufferline.prefix" ng-class="{{ part.classes }}">{{ part.text }}</span></td>
<td class="message"> <td class="message">
<span ng-repeat="part in bufferline.content" class="text" style="{{ part.fg }}" ng-bind-html="part.text"></span> <span ng-repeat="part in bufferline.content" class="text" ng-class="{{ part.classes }}" ng-bind-html="part.text"></span>
<div ng-repeat="metadata in bufferline.metadata"> <div ng-repeat="metadata in bufferline.metadata">
<div ng-show="metadata.visible"> <div ng-show="metadata.visible">

View file

@ -4,7 +4,7 @@
*/ */
var models = angular.module('weechatModels', []); var models = angular.module('weechatModels', []);
models.service('models', ['$rootScope', 'colors', function($rootScope, colors) { models.service('models', ['$rootScope', function($rootScope) {
/* /*
* Buffer class * Buffer class
*/ */
@ -59,36 +59,55 @@ models.service('models', ['$rootScope', 'colors', function($rootScope, colors) {
* BufferLine class * BufferLine class
*/ */
this.BufferLine = function(message) { this.BufferLine = function(message) {
/*
* Parse the text elements from the buffer line added
*
* @param message weechat message
*/
function parseLineAddedTextElements(message) {
var text = colors.parse(message);
text_elements =_.map(text, function(text_element) {
if (text_element && ('fg' in text_element)) {
text_element['fg'] = colors.prepareCss(text_element['fg']);
}
// TODO: parse background as well
return text_element;
});
return text_elements;
}
var buffer = message['buffer']; var buffer = message['buffer'];
var date = message['date']; var date = message['date'];
function addClasses(textElements) {
var typeToClassPrefixFg = {
'option': 'cof-',
'weechat': 'cwf-',
'ext': 'cef-'
};
var typeToClassPrefixBg = {
'option': 'cob-',
'weechat': 'cwb-',
'ext': 'ceb-'
};
textElements.forEach(function(textEl) {
textEl.classes = [];
var prefix = parseLineAddedTextElements(message['prefix']); // foreground color
var prefix = typeToClassPrefixFg[textEl.fgColor.type];
textEl.classes.push(prefix + textEl.fgColor.name);
// background color
prefix = typeToClassPrefixBg[textEl.bgColor.type];
textEl.classes.push(prefix + textEl.bgColor.name);
// attributes
if (textEl.attrs.name !== null) {
textEl.classes.push('coa-' + textEl.attrs.name);
}
for (var attr in textEl.attrs.override) {
val = textEl.attrs.override[attr];
if (val) {
textEl.classes.push('a-' + attr);
} else {
textEl.classes.push('a-no-' + attr);
}
}
});
}
var prefix = weeChat.Protocol.rawText2Rich(message['prefix']);
addClasses(prefix);
var tags_array = message['tags_array']; var tags_array = message['tags_array'];
var displayed = message['displayed']; var displayed = message['displayed'];
var highlight = message['highlight']; var highlight = message['highlight'];
var content = parseLineAddedTextElements(message['message']); var content = weeChat.Protocol.rawText2Rich(message['message']);
addClasses(content);
var rtext = ""; var rtext = "";
if(content[0] != undefined) { if(content[0] != undefined) {
@ -104,6 +123,7 @@ models.service('models', ['$rootScope', 'colors', function($rootScope, colors) {
highlight: highlight, highlight: highlight,
displayed: displayed, displayed: displayed,
text: rtext, text: rtext,
} }
} }

View file

@ -14,16 +14,7 @@ weechat.filter('toArray', function () {
} }
}); });
weechat.factory('colors', [function($scope) { weechat.factory('handlers', ['$rootScope', 'models', 'plugins', function($rootScope, models, plugins) {
return {
prepareCss: weeChat.color.prepareCss,
parse: weeChat.color.parse
};
}]);
weechat.factory('handlers', ['$rootScope', 'colors', 'models', 'plugins', function($rootScope, colors, models, plugins) {
var handleBufferClosing = function(message) { var handleBufferClosing = function(message) {
var bufferMessage = message['objects'][0]['content'][0]; var bufferMessage = message['objects'][0]['content'][0];
@ -147,7 +138,7 @@ weechat.factory('handlers', ['$rootScope', 'colors', 'models', 'plugins', functi
}]); }]);
weechat.factory('connection', ['$q', '$rootScope', '$log', '$store', 'handlers', 'colors', 'models', function($q, $rootScope, $log, storage, handlers, colors, models) { weechat.factory('connection', ['$q', '$rootScope', '$log', '$store', 'handlers', 'models', function($q, $rootScope, $log, storage, handlers, models) {
protocol = new weeChat.Protocol(); protocol = new weeChat.Protocol();
var websocket = null; var websocket = null;

View file

@ -1,178 +1,15 @@
(function(exports) {// http://weechat.org/files/doc/devel/weechat_dev.en.html#color_codes_in_strings (function(exports) {// http://weechat.org/files/doc/devel/weechat_dev.en.html#color_codes_in_strings
(function() { /**
// http://weechat.org/files/doc/devel/weechat_dev.en.html#color_codes_in_strings
var part, fg, bg, attrs;
// XTerm 8-bit pallete
var colors = [
'#666666', '#AA0000', '#00AA00', '#AA5500', '#0000AA',
'#AA00AA', '#00AAAA', '#AAAAAA', '#555555', '#FF5555',
'#55FF55', '#FFFF55', '#5555FF', '#FF55FF', '#55FFFF',
'#FFFFFF', '#666666', '#00005F', '#000087', '#0000AF',
'#0000D7', '#0000FF', '#005F00', '#005F5F', '#005F87',
'#005FAF', '#005FD7', '#005FFF', '#008700', '#00875F',
'#008787', '#0087AF', '#0087D7', '#00AF00', '#00AF5F',
'#00AF87', '#00AFAF', '#00AFD7', '#00AFFF', '#00D700',
'#00D75F', '#00D787', '#00D7AF', '#00D7D7', '#00D7FF',
'#00FF00', '#00FF5F', '#00FF87', '#00FFAF', '#00FFD7',
'#00FFFF', '#5F0000', '#5F005F', '#5F0087', '#5F00AF',
'#5F00D7', '#5F00FF', '#5F5F00', '#5F5F5F', '#5F5F87',
'#5F5FAF', '#5F5FD7', '#5F5FFF', '#5F8700', '#5F875F',
'#5F8787', '#5F87AF', '#5F87D7', '#5F87FF', '#5FAF00',
'#5FAF5F', '#5FAF87', '#5FAFAF', '#5FAFD7', '#5FAFFF',
'#5FD700', '#5FD75F', '#5FD787', '#5FD7AF', '#5FD7D7',
'#5FD7FF', '#5FFF00', '#5FFF5F', '#5FFF87', '#5FFFAF',
'#5FFFD7', '#5FFFFF', '#870000', '#87005F', '#870087',
'#8700AF', '#8700D7', '#8700FF', '#875F00', '#875F5F',
'#875F87', '#875FAF', '#875FD7', '#875FFF', '#878700',
'#87875F', '#878787', '#8787AF', '#8787D7', '#8787FF',
'#87AF00', '#87AF5F', '#87AF87', '#87AFAF', '#87AFD7',
'#87AFFF', '#87D700', '#87D75F', '#87D787', '#87D7AF',
'#87D7D7', '#87D7FF', '#87FF00', '#87FF5F', '#87FF87',
'#87FFAF', '#87FFD7', '#87FFFF', '#AF0000', '#AF005F',
'#AF0087', '#AF00AF', '#AF00D7', '#AF00FF', '#AF5F00',
'#AF5F5F', '#AF5F87', '#AF5FAF', '#AF5FD7', '#AF5FFF',
'#AF8700', '#AF875F', '#AF8787', '#AF87AF', '#AF87D7',
'#AF87FF', '#AFAF00', '#AFAF5F', '#AFAF87', '#AFAFAF',
'#AFAFD7', '#AFAFFF', '#AFD700', '#AFD75F', '#AFD787',
'#AFD7AF', '#AFD7D7', '#AFD7FF', '#AFFF00', '#AFFF5F',
'#AFFF87', '#AFFFAF', '#AFFFD7', '#AFFFFF', '#D70000',
'#D7005F', '#D70087', '#D700AF', '#D700D7', '#D700FF',
'#D75F00', '#D75F5F', '#D75F87', '#D75FAF', '#D75FD7',
'#D75FFF', '#D78700', '#D7875F', '#D78787', '#D787AF',
'#D787D7', '#D787FF', '#D7AF00', '#D7AF5F', '#D7AF87',
'#D7AFAF', '#D7AFD7', '#D7AFFF', '#D7D700', '#D7D75F',
'#D7D787', '#D7D7AF', '#D7D7D7', '#D7D7FF', '#D7FF00',
'#D7FF5F', '#D7FF87', '#D7FFAF', '#D7FFD7', '#D7FFFF',
'#FF0000', '#FF005F', '#FF0087', '#FF00AF', '#FF00D7',
'#FF00FF', '#FF5F00', '#FF5F5F', '#FF5F87', '#FF5FAF',
'#FF5FD7', '#FF5FFF', '#FF8700', '#FF875F', '#FF8787',
'#FF87AF', '#FF87D7', '#FF87FF', '#FFAF00', '#FFAF5F',
'#FFAF87', '#FFAFAF', '#FFAFD7', '#FFAFFF', '#FFD700',
'#FFD75F', '#FFD787', '#FFD7AF', '#FFD7D7', '#FFD7FF',
'#FFFF00', '#FFFF5F', '#FFFF87', '#FFFFAF', '#FFFFD7',
'#FFFFFF', '#080808', '#121212', '#1C1C1C', '#262626',
'#303030', '#3A3A3A', '#444444', '#4E4E4E', '#585858',
'#626262', '#6C6C6C', '#767676', '#808080', '#8A8A8A',
'#949494', '#9E9E9E', '#A8A8A8', '#B2B2B2', '#BCBCBC',
'#C6C6C6', '#D0D0D0', '#DADADA', '#E4E4E4', '#EEEEEE'
];
// Push the basic color list on top of the extended color list
// and then when weechat requests a basic color (0-15) we rewrite
// it to be a number in the extended color table
colors.push.apply(colors, ['', 'black', 'darkgray', 'darkred', 'red', 'darkgreen', 'lightgreen', 'brown',
'yellow', 'darkblue', 'lightblue', 'darkmagenta', 'magenta', 'darkcyan', 'lightcyan', 'gray', 'white'
]);
function setAttrs() {
while (part.match(/^[\*\/\_\|]/)) {
attrs.push(part.charAt(0));
part = part.slice(1);
}
}
function getColor() {
var c;
if (part.match(/^@/)) {
c = part.slice(1, 6);
part = part.slice(6);
} else {
c = part.slice(0, 2);
// Rewrite the basic color value to the part in the extended
// palette where we store the basic colors
c = parseInt(c, 10) + 255;
part = part.slice(2);
}
return c;
}
function prepareCss(color) {
/*
* Translates a weechat color to CSS
*/
return 'color: ' + color;
}
var prefixes = {
'\x19': function() {
if (part.match(/^F/)) {
part = part.slice(1);
setAttrs();
fg = getColor();
} else if (part.match(/^B/)) {
part = part.slice(1);
setAttrs();
bg = getColor();
} else {
setAttrs();
fg = getColor();
if (part.match(/^,/)) {
part = part.slice(1);
bg = getColor();
}
}
},
'\x1A': function() {
// Don't know what to do
},
'\x1B': function() {
attrs = [];
},
'\x1C': function() {
fg = '';
bg = '';
}
};
function parse(text) {
if (!text) {
return text;
}
var f, parts = text.split(/(\x19|\x1A|\x1B|\x1C)/);
if (parts.length === 1) return [{
text: parts[0]
}];
attrs = [];
return parts.map(function(p) {
var res, tmp = prefixes[p.charAt(0)];
if (f) {
part = p;
f();
res = {
text: part,
fg: colors[parseInt(fg, 10)],
bg: colors[parseInt(bg, 10)],
attrs: attrs
};
if (!res.fg) res.fg = fg;
if (!res.bg) res.bg = bg;
}
f = tmp;
return res;
}).filter(function(p) {
return p;
});
}
exports.color = {
prepareCss: prepareCss,
parse: parse
};
})();
;/**
* WeeChat protocol handling. * WeeChat protocol handling.
* *
* This object parses messages and formats commands for the WeeChat * This object parses messages and formats commands for the WeeChat
* protocol. It's independent from the communication layer and thus * protocol. It's independent from the communication layer and thus
* may be used with any network mechanism. * may be used with any network mechanism.
*/ */
(function() { (function() {
var WeeChatProtocol = function() { var WeeChatProtocol = function() {
// specific parsing for each message type // specific parsing for each object type
this._types = { this._types = {
'chr': this._getChar, 'chr': this._getChar,
'int': this._getInt, 'int': this._getInt,
@ -190,7 +27,7 @@
} }
}; };
// string value for some message types // string value for some object types
this._typesStr = { this._typesStr = {
'chr': this._strDirect, 'chr': this._strDirect,
'str': this._strDirect, 'str': this._strDirect,
@ -200,6 +37,529 @@
}; };
}; };
/**
* WeeChat colors names.
*/
WeeChatProtocol._weeChatColorsNames = [
'default',
'black',
'darkgray',
'darkred',
'lightred',
'darkgreen',
'lightgreen',
'brown',
'yellow',
'darkblue',
'lightblue',
'darkmagenta',
'lightmagenta',
'darkcyan',
'lightcyan',
'gray',
'white'
];
/**
* Style options names.
*/
WeeChatProtocol._colorsOptionsNames = [
'separator',
'chat',
'chat_time',
'chat_time_delimiters',
'chat_prefix_error',
'chat_prefix_network',
'chat_prefix_action',
'chat_prefix_join',
'chat_prefix_quit',
'chat_prefix_more',
'chat_prefix_suffix',
'chat_buffer',
'chat_server',
'chat_channel',
'chat_nick',
'chat_nick_self',
'chat_nick_other',
'invalid',
'invalid',
'invalid',
'invalid',
'invalid',
'invalid',
'invalid',
'invalid',
'invalid',
'invalid',
'chat_host',
'chat_delimiters',
'chat_highlight',
'chat_read_marker',
'chat_text_found',
'chat_value',
'chat_prefix_buffer',
'chat_tags',
'chat_inactive_window',
'chat_inactive_buffer',
'chat_prefix_buffer_inactive_buffer',
'chat_nick_offline',
'chat_nick_offline_highlight',
'chat_nick_prefix',
'chat_nick_suffix',
'emphasis',
'chat_day_change'
];
/**
* Gets the default color.
*
* @return Default color
*/
WeeChatProtocol._getDefaultColor = function() {
return {
type: 'weechat',
name: 'default'
};
}
/**
* Gets the default attributes.
*
* @return Default attributes
*/
WeeChatProtocol._getDefaultAttributes = function() {
return {
name: null,
override: {
'bold': false,
'reverse': false,
'italic': false,
'underline': false
}
};
}
/**
* Gets the default style (default colors and attributes).
*
* @return Default style
*/
WeeChatProtocol._getDefaultStyle = function() {
return {
fgColor: WeeChatProtocol._getDefaultColor(),
bgColor: WeeChatProtocol._getDefaultColor(),
attrs: WeeChatProtocol._getDefaultAttributes()
};
}
/**
* Clones a color object.
*
* @param color Color object to clone
* @return Cloned color object
*/
WeeChatProtocol._cloneColor = function(color) {
var clone = {};
for (var key in color) {
clone[key] = color[key];
}
return clone;
}
/**
* Clones an attributes object.
*
* @param attrs Attributes object to clone
* @return Cloned attributes object
*/
WeeChatProtocol._cloneAttrs = function(attrs) {
var clone = {};
clone.name = attrs.name;
clone.override = {};
for (var attr in attrs.override) {
clone.override[attr] = attrs.override[attr];
}
return clone;
}
/**
* Gets the name of an attribute from its character.
*
* @param ch Character of attribute
* @return Name of attribute
*/
WeeChatProtocol._attrNameFromChar = function(ch) {
var chars = {
'*': 'bold',
'!': 'reverse',
'/': 'italic',
'_': 'underline'
};
if (ch in chars) {
return chars[ch];
}
return null;
}
/**
* Gets an attributes object from a string of attribute characters.
*
* @param str String of attribute characters
* @return Attributes object (null if unchanged)
*/
WeeChatProtocol._attrsFromStr = function(str) {
var attrs = WeeChatProtocol._getDefaultAttributes();
for (var i = 0; i < str.length; ++i) {
var ch = str.charAt(i);
if (ch == '|') {
// means keep attributes, so unchanged
return null;
}
var attrName = WeeChatProtocol._attrNameFromChar(ch);
if (attrName === null) {
// ignore invalid attribute
continue;
}
attrs.override[attrName] = true;
}
return attrs;
}
/**
* Gets a single color from a string representing its index (WeeChat and
* extended colors only, NOT colors options).
*
* @param str Color string (e.g., "05" or "00134")
* @return Color object
*/
WeeChatProtocol._getColorObj = function(str) {
if (str.length == 2) {
var code = parseInt(str);
if (code > 16) {
// should never happen
return WeeChatProtocol._getDefaultColor();
} else {
return {
type: 'weechat',
name: WeeChatProtocol._weeChatColorsNames[code]
};
}
} else {
var codeStr = str.substring(1);
return {
type: 'ext',
name: parseInt(codeStr).toString()
};
}
}
/**
* Gets colors and attributes of text element.
*
* See <http://www.weechat.org/files/doc/devel/weechat_dev.en.html#color_codes_in_strings>.
*
* @param txt Text element
* @return Colors, attributes and plain text of this text element:
* fgColor: Foreground color (null if unchanged)
* bgColor: Background color (null if unchanged)
* attrs: Attributes (null if unchanged)
* text: Plain text element
*/
WeeChatProtocol._getStyle = function(txt) {
var matchers = [
{
// color option
// STD
regex: /^(\d{2})/,
fn: function(m) {
var ret = {};
var optionCode = parseInt(m[1]);
if (optionCode > 43) {
// should never happen
return {
fgColor: null,
bgColor: null,
attrs: null
};
}
var optionName = WeeChatProtocol._colorsOptionsNames[optionCode];
ret.fgColor = {
type: 'option',
name: optionName
};
ret.bgColor = WeeChatProtocol._cloneColor(ret.fgColor);
ret.attrs = {
name: optionName,
override: {}
};
return ret;
}
},
{
// ncurses pair
// EXT
regex: /^@(\d{5})/,
fn: function(m) {
// unimplemented case
return {
fgColor: null,
bgColor: null,
attrs: null
};
}
},
{
// foreground color with F
// "F" + (A)STD
// "F" + (A)EXT
regex: /^F(?:([*!\/_|]*)(\d{2})|@([*!\/_|]*)(\d{5}))/,
fn: function(m) {
var ret = {
bgColor: null
};
if (m[2]) {
ret.attrs = WeeChatProtocol._attrsFromStr(m[1]);
ret.fgColor = WeeChatProtocol._getColorObj(m[2]);
} else {
ret.attrs = WeeChatProtocol._attrsFromStr(m[3]);
ret.fgColor = WeeChatProtocol._getColorObj(m[4]);
}
return ret;
}
},
{
// background color (no attributes)
// "B" + STD
// "B" + EXT
regex: /^B(\d{2}|@\d{5})/,
fn: function(m) {
return {
fgColor: null,
bgColor: WeeChatProtocol._getColorObj(m[1]),
attrs: null
};
}
},
{
// foreground, background (+ attributes)
// "*" + (A)STD + "," + STD
// "*" + (A)STD + "," + EXT
// "*" + (A)EXT + "," + STD
// "*" + (A)EXT + "," + EXT
regex: /^\*(?:([*!\/_|]*)(\d{2})|@([*!\/_|]*)(\d{5})),(\d{2}|@\d{5})/,
fn: function(m) {
var ret = {};
if (m[2]) {
ret.attrs = WeeChatProtocol._attrsFromStr(m[1]);
ret.fgColor = WeeChatProtocol._getColorObj(m[2]);
} else {
ret.attrs = WeeChatProtocol._attrsFromStr(m[3]);
ret.fgColor = WeeChatProtocol._getColorObj(m[4]);
}
ret.bgColor = WeeChatProtocol._getColorObj(m[5]);
return ret;
}
},
{
// foreground color with * (+ attributes) (fall back, must be checked before previous case)
// "*" + (A)STD
// "*" + (A)EXT
regex: /^\*([*!\/_|]*)(\d{2}|@\d{5})/,
fn: function(m) {
return {
fgColor: WeeChatProtocol._getColorObj(m[2]),
bgColor: null,
attrs: WeeChatProtocol._attrsFromStr(m[1])
};
}
},
{
// emphasis
// "E"
regex: /^E/,
fn: function(m) {
var ret = {};
ret.fgColor = {
type: 'option',
name: 'emphasis'
};
ret.bgColor = WeeChatProtocol._cloneColor(ret.fgColor);
ret.attrs = {
name: 'emphasis',
override: {}
};
return ret;
}
}
];
// parse
var ret = {
fgColor: null,
bgColor: null,
attrs: null,
text: txt
};
matchers.some(function(matcher) {
var m = txt.match(matcher.regex);
if (m) {
ret = matcher.fn(m);
ret.text = txt.substring(m[0].length);
return true;
}
return false;
});
return ret;
}
/**
* Transforms a raw text into an array of text elements with integrated
* colors and attributes.
*
* @param rawText Raw text to transform
* @return Array of text elements
*/
WeeChatProtocol.rawText2Rich = function(rawText) {
/* This is subtle, but JavaScript adds the token to the output list
* when it's surrounded by capturing parentheses.
*/
var parts = rawText.split(/(\x19|\x1a|\x1b|\x1c)/);
// no colors/attributes
if (parts.length == 1) {
return [
{
attrs: WeeChatProtocol._getDefaultAttributes(),
fgColor: WeeChatProtocol._getDefaultColor(),
bgColor: WeeChatProtocol._getDefaultColor(),
text: parts[0]
}
];
}
// find the style of every part
var curFgColor = WeeChatProtocol._getDefaultColor();
var curBgColor = WeeChatProtocol._getDefaultColor();
var curAttrs = WeeChatProtocol._getDefaultAttributes();
var curSpecialToken = null;
var curAttrsOnlyFalseOverrides = true;
return parts.map(function(p) {
if (p.length == 0) {
return null;
}
var firstCharCode = p.charCodeAt(0);
var firstChar = p.charAt(0);
if (firstCharCode >= 0x19 && firstCharCode <= 0x1c) {
// special token
if (firstCharCode == 0x1c) {
// always reset colors
curFgColor = WeeChatProtocol._getDefaultColor();
curBgColor = WeeChatProtocol._getDefaultColor();
if (curSpecialToken != 0x19) {
// also reset attributes
curAttrs = WeeChatProtocol._getDefaultAttributes();
}
}
curSpecialToken = firstCharCode;
return null;
}
var text = p;
if (curSpecialToken == 0x19) {
// get new style
var style = WeeChatProtocol._getStyle(p);
// set foreground color if changed
if (style.fgColor !== null) {
curFgColor = style.fgColor;
}
// set background color if changed
if (style.bgColor !== null) {
curBgColor = style.bgColor;
}
// set attibutes if changed
if (style.attrs !== null) {
curAttrs = style.attrs;
}
// set plain text
text = style.text;
} else if (curSpecialToken == 0x1a || curSpecialToken == 0x1b) {
// set/reset attribute
var orideVal = (curSpecialToken == 0x1a);
// set attribute override if we don't have to keep all of them
if (firstChar != '|') {
var orideName = WeeChatProtocol._attrNameFromChar(firstChar);
if (orideName) {
// known attribute
curAttrs.override[orideName] = orideVal;
text = p.substring(1);
}
}
}
// reset current special token
curSpecialToken = null;
// if text is empty, don't bother returning it
if (text.length == 0) {
return null;
}
/* As long as attributes are only false overrides, without any option
* name, it's safe to remove them.
*/
if (curAttrsOnlyFalseOverrides && curAttrs.name === null) {
var allReset = true;
for (var attr in curAttrs.override) {
if (curAttrs.override[attr]) {
allReset = false;
break;
}
}
if (allReset) {
curAttrs.override = {};
} else {
curAttrsOnlyFalseOverrides = false;
}
}
// parsed text element
return {
fgColor: WeeChatProtocol._cloneColor(curFgColor),
bgColor: WeeChatProtocol._cloneColor(curBgColor),
attrs: WeeChatProtocol._cloneAttrs(curAttrs),
text: text
};
}).filter(function(p) {
return p !== null;
});
};
/** /**
* Unsigned integer array to string. * Unsigned integer array to string.
* *
@ -800,7 +1160,7 @@
* @param data Message data (ArrayBuffer) * @param data Message data (ArrayBuffer)
* @return Message value * @return Message value
*/ */
parse: function(data) { parse: function(data, optionsValues) {
var self = this; var self = this;
this._setData(data); this._setData(data);
@ -815,12 +1175,13 @@
objects.push(object); objects.push(object);
object = self._getObject(); object = self._getObject();
} }
var msg = {
return {
header: header, header: header,
id: id, id: id,
objects: objects, objects: objects,
}; };
return msg;
} }
}; };