diff --git a/css-doodle.js b/css-doodle.js index 4f245ce..dd4b1f0 100644 --- a/css-doodle.js +++ b/css-doodle.js @@ -303,15 +303,26 @@ const is = { }; function iterator(input) { - let index = 0; + let index = 0, col = 1, line = 1; return { curr: (n = 0) => input[index + n], - next: () => input[index++], end: () => input.length <= index, - index: () => index + info: () => ({ index, col, line }), + next: () => { + let next = input[index++]; + if (next == '\n') line++, col = 0; + else col++; + return next; + } }; } +function throw_error(msg, { col, line }) { + throw new Error( + `(at line ${ line }, column ${ col }) ${ msg }` + ); +} + function skip_block(it) { let [skipped, c] = [it.curr(), it.curr()]; let is_close_bracket = is.close_bracket_of(c); @@ -336,7 +347,7 @@ function read_property(it) { while (!it.end()) { if ((c = it.curr()) == ':') break; else if (!/[a-zA-Z\-]/.test(c)) { - throw new Error('Syntax error: Bad property name.'); + throw_error('Syntax error: Bad property name.', it.info()); } else if (!is.white_space(c)) prop += c; it.next(); @@ -417,6 +428,9 @@ function read_value(it) { value.push(read_func(it)); } else if (!is.white_space(c) || !is.white_space(it.curr(-1))) { + if (c == ':') { + throw_error('Syntax error: Bad property name.', it.info()); + } text.value += c; } it.next(); @@ -533,10 +547,6 @@ function compile(input, size) { return generator(tokenizer(input), size); } -function clamp(num, min, max) { - return (num <= min) ? min : ((num >= max) ? max : num); -} - function parse(size) { const split = (size + '') .replace(/\s+/g, '') @@ -553,6 +563,10 @@ function parse(size) { }; } +function clamp(num, min, max) { + return (num <= min) ? min : ((num >= max) ? max : num); +} + class Doodle extends HTMLElement { constructor() { super(); diff --git a/src/parse-size.js b/src/parse-size.js index 93171b9..4481250 100644 --- a/src/parse-size.js +++ b/src/parse-size.js @@ -1,7 +1,3 @@ -function clamp(num, min, max) { - return (num <= min) ? min : ((num >= max) ? max : num); -} - export default function parse(size) { const split = (size + '') .replace(/\s+/g, '') @@ -17,3 +13,7 @@ export default function parse(size) { count: ret.x * ret.y }; } + +function clamp(num, min, max) { + return (num <= min) ? min : ((num >= max) ? max : num); +} diff --git a/src/tokenizer.js b/src/tokenizer.js index 7de3fd8..c0ed153 100644 --- a/src/tokenizer.js +++ b/src/tokenizer.js @@ -29,15 +29,26 @@ const is = { }; function iterator(input) { - let index = 0; + let index = 0, col = 1, line = 1; return { curr: (n = 0) => input[index + n], - next: () => input[index++], end: () => input.length <= index, - index: () => index + info: () => ({ index, col, line }), + next: () => { + let next = input[index++]; + if (next == '\n') line++, col = 0; + else col++; + return next; + } }; } +function throw_error(msg, { col, line }) { + throw new Error( + `(at line ${ line }, column ${ col }) ${ msg }` + ); +} + function skip_block(it) { let [skipped, c] = [it.curr(), it.curr()]; let is_close_bracket = is.close_bracket_of(c); @@ -62,7 +73,7 @@ function read_property(it) { while (!it.end()) { if ((c = it.curr()) == ':') break; else if (!/[a-zA-Z\-]/.test(c)) { - throw new Error('Syntax error: Bad property name.'); + throw_error('Syntax error: Bad property name.', it.info()); } else if (!is.white_space(c)) prop += c; it.next(); @@ -143,6 +154,9 @@ function read_value(it) { value.push(read_func(it)); } else if (!is.white_space(c) || !is.white_space(it.curr(-1))) { + if (c == ':') { + throw_error('Syntax error: Bad property name.', it.info()); + } text.value += c; } it.next();