irctokens
Version:
RFC1459 and IRCv3 protocol tokeniser
141 lines • 4.9 kB
JavaScript
;
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var _Line_hostmask;
Object.defineProperty(exports, "__esModule", { value: true });
exports.tokenise = exports.Line = void 0;
const const_1 = require("./const");
const formatting_1 = require("./formatting");
const hostmask_1 = require("./hostmask");
class Line {
constructor({ tags, source, command, params }) {
_Line_hostmask.set(this, void 0);
this.tags = tags;
this.source = source;
this.command = command;
this.params = params;
}
get hostmask() {
if (this.source) {
if (!__classPrivateFieldGet(this, _Line_hostmask, "f"))
__classPrivateFieldSet(this, _Line_hostmask, hostmask_1.hostmask(this.source), "f");
return __classPrivateFieldGet(this, _Line_hostmask, "f");
}
else {
throw new TypeError('cannot parse hostmask from null source');
}
}
format() {
return formatting_1.format({
tags: this.tags,
source: this.source,
command: this.command,
params: this.params
});
}
withSource(source) {
return new Line({
tags: this.tags,
source,
command: this.command,
params: this.params
});
}
copy() {
return new Line(this);
}
}
exports.Line = Line;
_Line_hostmask = new WeakMap();
function unescapeTag(value) {
let unescaped = '';
if (!value)
return unescaped;
const escaped = value.split('');
while (escaped.length) {
const current = escaped.shift();
if (current === '\\') {
if (escaped.length) {
const next = escaped.shift();
const duo = `${current}${next}`;
const index = const_1.TAG_ESCAPED.indexOf(duo);
if (index > -1)
unescaped += const_1.TAG_UNESCAPED[index];
else
unescaped += next;
}
}
else {
unescaped += current;
}
}
return unescaped;
}
function _tokenise(line) {
let value = line;
let tags;
if (value[0] === '@') {
let tagsS;
[tagsS, value] = value.substring(1).split(/ (.*)/);
tags = {};
for (const part of tagsS.split(';')) {
const [key, val] = part.split(/=(.*)/);
tags[key] = unescapeTag(val);
}
}
let trailing;
[value, trailing] = value.split(/ :(.*)/);
const params = value.split(' ').filter(part => !!part);
let source;
if (params[0][0] === ':') {
source = params.shift().substring(1);
}
if (!params.length)
throw TypeError('Cannot tokenise command-less line');
const command = params.shift().toLocaleUpperCase();
if (typeof trailing === 'string')
params.push(trailing);
return new Line({
tags,
source,
command,
params
});
}
function tokenise(line, encoding = 'utf8', fallback = 'latin1') {
let dline = '';
const decoder = new TextDecoder(encoding, { fatal: true });
const fallbackDecoder = new TextDecoder(fallback, { fatal: true });
if (line instanceof Uint8Array) {
if (line[0] === '@'.charCodeAt(0)) {
const idx = line.indexOf(' '.charCodeAt(0));
const tagsB = line.slice(0, idx + 1);
line = line.slice(idx + 1);
dline += decoder.decode(tagsB);
}
try {
dline += decoder.decode(line);
}
catch {
dline += fallbackDecoder.decode(line);
}
}
else {
dline = line;
}
if (dline.includes('\x00')) {
[dline] = dline.split('\x00');
}
return _tokenise(dline);
}
exports.tokenise = tokenise;
//# sourceMappingURL=line.js.map