diff --git a/lib/parse/index.js b/lib/parse/index.js index 053f0596..93f656dc 100644 --- a/lib/parse/index.js +++ b/lib/parse/index.js @@ -422,7 +422,7 @@ module.exports = function(css, options){ // declarations var decl; - while (decl = declaration()) { + while (decl = declaration() || atmarginbox()) { decls.push(decl); decls = decls.concat(comments()); } @@ -436,6 +436,37 @@ module.exports = function(css, options){ }); } + /** + * Parse margin boxes + */ + + function atmarginbox() { + var pos = position(); + var m = match(/^@((top|bottom|left|right)-(center|right|top|middle|left|bottom)(-corner)?) */); + if (!m) return; + + var name = m[1]; + + if (!open()) return error("@margin-box missing '{'"); + var decls = comments(); + + // declarations + var decl; + while (decl = declaration()) { + decls.push(decl); + decls = decls.concat(comments()); + } + + if (!close()) return error("@margin-box missing '}'"); + + return pos({ + type: 'margin-box', + name: name, + declarations: decls + }); + + } + /** * Parse document. */ diff --git a/lib/stringify/compress.js b/lib/stringify/compress.js index 929b4a21..f3dc5212 100644 --- a/lib/stringify/compress.js +++ b/lib/stringify/compress.js @@ -145,6 +145,17 @@ Compiler.prototype.page = function(node){ + this.emit('}'); }; +/** + * Visit margin-box node. + */ + +Compiler.prototype['margin-box'] = function(node){ + return this.emit('@' + node.name + ' ', node.position) + + this.emit('{') + + this.mapVisit(node.declarations) + + this.emit('}'); +}; + /** * Visit font-face node. */ diff --git a/lib/stringify/identity.js b/lib/stringify/identity.js index b390c91e..2ca7c789 100644 --- a/lib/stringify/identity.js +++ b/lib/stringify/identity.js @@ -175,6 +175,20 @@ Compiler.prototype.page = function(node){ + this.emit('\n}'); }; +/** + * Visit margin-box node. + */ + +Compiler.prototype['margin-box'] = function(node){ + return this.emit(this.indent()) + + this.emit('@' + node.name + ' ', node.position) + + this.emit('{\n') + + this.emit(this.indent(1)) + + this.mapVisit(node.declarations, '\n') + + this.emit(this.indent(-1)) + + this.emit('\n' + this.indent() + '}'); +}; + /** * Visit font-face node. */ diff --git a/package.json b/package.json index 93bb8910..67e8c284 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css", - "version": "2.2.1", + "version": "2.2.2", "description": "CSS parser / stringifier", "main": "index", "files": [ diff --git a/test/cases/paged-media/ast.json b/test/cases/paged-media/ast.json index 12333876..c8efd2a0 100644 --- a/test/cases/paged-media/ast.json +++ b/test/cases/paged-media/ast.json @@ -1,6 +1,7 @@ { "type": "stylesheet", "stylesheet": { + "source": "input.css", "rules": [ { "type": "comment", @@ -135,7 +136,142 @@ }, "source": "input.css" } + }, + { + "type": "page", + "selectors": [ + "named-page" + ], + "declarations": [ + { + "type": "declaration", + "property": "size", + "value": "A4 landscape", + "position": { + "start": { + "line": 16, + "column": 3 + }, + "end": { + "line": 16, + "column": 21 + }, + "source": "input.css" + } + } + ], + "position": { + "start": { + "line": 15, + "column": 1 + }, + "end": { + "line": 17, + "column": 2 + }, + "source": "input.css" + } + }, + { + "type": "page", + "selectors": [], + "declarations": [ + { + "type": "declaration", + "property": "size", + "value": "210mm 279mm", + "position": { + "start": { + "line": 20, + "column": 3 + }, + "end": { + "line": 20, + "column": 20 + }, + "source": "input.css" + } + }, + { + "type": "margin-box", + "name": "top-left", + "declarations": [ + { + "type": "declaration", + "property": "padding-top", + "value": "0", + "position": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 23, + "column": 19 + }, + "source": "input.css" + } + } + ], + "position": { + "start": { + "line": 22, + "column": 3 + }, + "end": { + "line": 24, + "column": 4 + }, + "source": "input.css" + } + }, + { + "type": "margin-box", + "name": "top-right", + "declarations": [ + { + "type": "declaration", + "property": "content", + "value": "\"foo\"", + "position": { + "start": { + "line": 27, + "column": 5 + }, + "end": { + "line": 27, + "column": 19 + }, + "source": "input.css" + } + } + ], + "position": { + "start": { + "line": 26, + "column": 3 + }, + "end": { + "line": 28, + "column": 4 + }, + "source": "input.css" + } + } + ], + "position": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 29, + "column": 2 + }, + "source": "input.css" + } } - ] + ], + "parsingErrors": [] } -} +} \ No newline at end of file diff --git a/test/cases/paged-media/compressed.css b/test/cases/paged-media/compressed.css index 13113164..84934bca 100644 --- a/test/cases/paged-media/compressed.css +++ b/test/cases/paged-media/compressed.css @@ -1 +1 @@ -@page toc, index:blank{color:green;}@page {font-size:16pt;}@page :left{margin-left:5cm;} +@page toc, index:blank{color:green;}@page {font-size:16pt;}@page :left{margin-left:5cm;}@page named-page{size:A4 landscape;}@page {size:210mm 279mm;@top-left {padding-top:0;}@top-right {content:"foo";}} diff --git a/test/cases/paged-media/input.css b/test/cases/paged-media/input.css index 68b8e0f3..fd1725d2 100644 --- a/test/cases/paged-media/input.css +++ b/test/cases/paged-media/input.css @@ -11,3 +11,19 @@ @page :left { margin-left: 5cm; } + +@page named-page { + size: A4 landscape; +} + +@page { + size: 210mm 279mm; + + @top-left { + padding-top: 0; + } + + @top-right { + content: "foo"; + } +} diff --git a/test/cases/paged-media/output.css b/test/cases/paged-media/output.css index 583fcc9d..49896f3d 100644 --- a/test/cases/paged-media/output.css +++ b/test/cases/paged-media/output.css @@ -12,3 +12,17 @@ @page :left { margin-left: 5cm; } + +@page named-page { + size: A4 landscape; +} + +@page { + size: 210mm 279mm; + @top-left { + padding-top: 0; + } + @top-right { + content: "foo"; + } +} \ No newline at end of file