diff --git a/assets/paged.polyfill.js b/assets/paged.polyfill.js
index 5008dbe..3100799 100644
--- a/assets/paged.polyfill.js
+++ b/assets/paged.polyfill.js
@@ -23185,4 +23185,10067 @@
function unpackSyntaxes(dict) {
const result = {};
-
\ No newline at end of file
+ for (const key in dict) {
+ result[key] = dict[key].syntax;
+ }
+
+ return result;
+ }
+
+ function patchAtrules(dict, patchDict) {
+ const result = {};
+
+ // copy all syntaxes for an original dict
+ for (const key in dict) {
+ const patchDescriptors = (patchDict[key] && patchDict[key].descriptors) || null;
+
+ result[key] = {
+ prelude: key in patchDict && 'prelude' in patchDict[key]
+ ? patchDict[key].prelude
+ : dict[key].prelude || null,
+ descriptors: dict[key].descriptors
+ ? patchDictionary(dict[key].descriptors, patchDescriptors || {})
+ : patchDescriptors && unpackSyntaxes(patchDescriptors)
+ };
+ }
+
+ // apply a patch
+ for (const key in patchDict) {
+ if (!hasOwnProperty.call(dict, key)) {
+ result[key] = {
+ prelude: patchDict[key].prelude || null,
+ descriptors: patchDict[key].descriptors && unpackSyntaxes(patchDict[key].descriptors)
+ };
+ }
+ }
+
+ return result;
+ }
+
+ var data$1 = {
+ types: patchDictionary(mdnSyntaxes, patch.syntaxes),
+ atrules: patchAtrules(preprocessAtrules(mdnAtrules), patch.atrules),
+ properties: patchDictionary(mdnProperties, patch.properties)
+ };
+
+ var cmpChar$2 = tokenizer$3.cmpChar;
+ var isDigit$1 = tokenizer$3.isDigit;
+ var TYPE$y = tokenizer$3.TYPE;
+
+ var WHITESPACE$8 = TYPE$y.WhiteSpace;
+ var COMMENT$6 = TYPE$y.Comment;
+ var IDENT$f = TYPE$y.Ident;
+ var NUMBER$6 = TYPE$y.Number;
+ var DIMENSION$5 = TYPE$y.Dimension;
+ var PLUSSIGN$5 = 0x002B; // U+002B PLUS SIGN (+)
+ var HYPHENMINUS$2 = 0x002D; // U+002D HYPHEN-MINUS (-)
+ var N = 0x006E; // U+006E LATIN SMALL LETTER N (n)
+ var DISALLOW_SIGN = true;
+ var ALLOW_SIGN = false;
+
+ function checkInteger(offset, disallowSign) {
+ var pos = this.scanner.tokenStart + offset;
+ var code = this.scanner.source.charCodeAt(pos);
+
+ if (code === PLUSSIGN$5 || code === HYPHENMINUS$2) {
+ if (disallowSign) {
+ this.error('Number sign is not allowed');
+ }
+ pos++;
+ }
+
+ for (; pos < this.scanner.tokenEnd; pos++) {
+ if (!isDigit$1(this.scanner.source.charCodeAt(pos))) {
+ this.error('Integer is expected', pos);
+ }
+ }
+ }
+
+ function checkTokenIsInteger(disallowSign) {
+ return checkInteger.call(this, 0, disallowSign);
+ }
+
+ function expectCharCode(offset, code) {
+ if (!cmpChar$2(this.scanner.source, this.scanner.tokenStart + offset, code)) {
+ var msg = '';
+
+ switch (code) {
+ case N:
+ msg = 'N is expected';
+ break;
+ case HYPHENMINUS$2:
+ msg = 'HyphenMinus is expected';
+ break;
+ }
+
+ this.error(msg, this.scanner.tokenStart + offset);
+ }
+ }
+
+ // ...
+ // ... ['+' | '-']
+ function consumeB() {
+ var offset = 0;
+ var sign = 0;
+ var type = this.scanner.tokenType;
+
+ while (type === WHITESPACE$8 || type === COMMENT$6) {
+ type = this.scanner.lookupType(++offset);
+ }
+
+ if (type !== NUMBER$6) {
+ if (this.scanner.isDelim(PLUSSIGN$5, offset) ||
+ this.scanner.isDelim(HYPHENMINUS$2, offset)) {
+ sign = this.scanner.isDelim(PLUSSIGN$5, offset) ? PLUSSIGN$5 : HYPHENMINUS$2;
+
+ do {
+ type = this.scanner.lookupType(++offset);
+ } while (type === WHITESPACE$8 || type === COMMENT$6);
+
+ if (type !== NUMBER$6) {
+ this.scanner.skip(offset);
+ checkTokenIsInteger.call(this, DISALLOW_SIGN);
+ }
+ } else {
+ return null;
+ }
+ }
+
+ if (offset > 0) {
+ this.scanner.skip(offset);
+ }
+
+ if (sign === 0) {
+ type = this.scanner.source.charCodeAt(this.scanner.tokenStart);
+ if (type !== PLUSSIGN$5 && type !== HYPHENMINUS$2) {
+ this.error('Number sign is expected');
+ }
+ }
+
+ checkTokenIsInteger.call(this, sign !== 0);
+ return sign === HYPHENMINUS$2 ? '-' + this.consume(NUMBER$6) : this.consume(NUMBER$6);
+ }
+
+ // An+B microsyntax https://www.w3.org/TR/css-syntax-3/#anb
+ var AnPlusB = {
+ name: 'AnPlusB',
+ structure: {
+ a: [String, null],
+ b: [String, null]
+ },
+ parse: function() {
+ /* eslint-disable brace-style*/
+ var start = this.scanner.tokenStart;
+ var a = null;
+ var b = null;
+
+ //
+ if (this.scanner.tokenType === NUMBER$6) {
+ checkTokenIsInteger.call(this, ALLOW_SIGN);
+ b = this.consume(NUMBER$6);
+ }
+
+ // -n
+ // -n
+ // -n ['+' | '-']
+ // -n-
+ //
+ else if (this.scanner.tokenType === IDENT$f && cmpChar$2(this.scanner.source, this.scanner.tokenStart, HYPHENMINUS$2)) {
+ a = '-1';
+
+ expectCharCode.call(this, 1, N);
+
+ switch (this.scanner.getTokenLength()) {
+ // -n
+ // -n
+ // -n ['+' | '-']
+ case 2:
+ this.scanner.next();
+ b = consumeB.call(this);
+ break;
+
+ // -n-
+ case 3:
+ expectCharCode.call(this, 2, HYPHENMINUS$2);
+
+ this.scanner.next();
+ this.scanner.skipSC();
+
+ checkTokenIsInteger.call(this, DISALLOW_SIGN);
+
+ b = '-' + this.consume(NUMBER$6);
+ break;
+
+ //
+ default:
+ expectCharCode.call(this, 2, HYPHENMINUS$2);
+ checkInteger.call(this, 3, DISALLOW_SIGN);
+ this.scanner.next();
+
+ b = this.scanner.substrToCursor(start + 2);
+ }
+ }
+
+ // '+'? n
+ // '+'? n
+ // '+'? n ['+' | '-']
+ // '+'? n-
+ // '+'?
+ else if (this.scanner.tokenType === IDENT$f || (this.scanner.isDelim(PLUSSIGN$5) && this.scanner.lookupType(1) === IDENT$f)) {
+ var sign = 0;
+ a = '1';
+
+ // just ignore a plus
+ if (this.scanner.isDelim(PLUSSIGN$5)) {
+ sign = 1;
+ this.scanner.next();
+ }
+
+ expectCharCode.call(this, 0, N);
+
+ switch (this.scanner.getTokenLength()) {
+ // '+'? n
+ // '+'? n
+ // '+'? n ['+' | '-']
+ case 1:
+ this.scanner.next();
+ b = consumeB.call(this);
+ break;
+
+ // '+'? n-
+ case 2:
+ expectCharCode.call(this, 1, HYPHENMINUS$2);
+
+ this.scanner.next();
+ this.scanner.skipSC();
+
+ checkTokenIsInteger.call(this, DISALLOW_SIGN);
+
+ b = '-' + this.consume(NUMBER$6);
+ break;
+
+ // '+'?
+ default:
+ expectCharCode.call(this, 1, HYPHENMINUS$2);
+ checkInteger.call(this, 2, DISALLOW_SIGN);
+ this.scanner.next();
+
+ b = this.scanner.substrToCursor(start + sign + 1);
+ }
+ }
+
+ //
+ //
+ //
+ //
+ // ['+' | '-']
+ else if (this.scanner.tokenType === DIMENSION$5) {
+ var code = this.scanner.source.charCodeAt(this.scanner.tokenStart);
+ var sign = code === PLUSSIGN$5 || code === HYPHENMINUS$2;
+
+ for (var i = this.scanner.tokenStart + sign; i < this.scanner.tokenEnd; i++) {
+ if (!isDigit$1(this.scanner.source.charCodeAt(i))) {
+ break;
+ }
+ }
+
+ if (i === this.scanner.tokenStart + sign) {
+ this.error('Integer is expected', this.scanner.tokenStart + sign);
+ }
+
+ expectCharCode.call(this, i - this.scanner.tokenStart, N);
+ a = this.scanner.source.substring(start, i);
+
+ //
+ //
+ // ['+' | '-']
+ if (i + 1 === this.scanner.tokenEnd) {
+ this.scanner.next();
+ b = consumeB.call(this);
+ } else {
+ expectCharCode.call(this, i - this.scanner.tokenStart + 1, HYPHENMINUS$2);
+
+ //
+ if (i + 2 === this.scanner.tokenEnd) {
+ this.scanner.next();
+ this.scanner.skipSC();
+ checkTokenIsInteger.call(this, DISALLOW_SIGN);
+ b = '-' + this.consume(NUMBER$6);
+ }
+ //
+ else {
+ checkInteger.call(this, i - this.scanner.tokenStart + 2, DISALLOW_SIGN);
+ this.scanner.next();
+ b = this.scanner.substrToCursor(i + 1);
+ }
+ }
+ } else {
+ this.error();
+ }
+
+ if (a !== null && a.charCodeAt(0) === PLUSSIGN$5) {
+ a = a.substr(1);
+ }
+
+ if (b !== null && b.charCodeAt(0) === PLUSSIGN$5) {
+ b = b.substr(1);
+ }
+
+ return {
+ type: 'AnPlusB',
+ loc: this.getLocation(start, this.scanner.tokenStart),
+ a: a,
+ b: b
+ };
+ },
+ generate: function(node) {
+ var a = node.a !== null && node.a !== undefined;
+ var b = node.b !== null && node.b !== undefined;
+
+ if (a) {
+ this.chunk(
+ node.a === '+1' ? '+n' : // eslint-disable-line operator-linebreak, indent
+ node.a === '1' ? 'n' : // eslint-disable-line operator-linebreak, indent
+ node.a === '-1' ? '-n' : // eslint-disable-line operator-linebreak, indent
+ node.a + 'n' // eslint-disable-line operator-linebreak, indent
+ );
+
+ if (b) {
+ b = String(node.b);
+ if (b.charAt(0) === '-' || b.charAt(0) === '+') {
+ this.chunk(b.charAt(0));
+ this.chunk(b.substr(1));
+ } else {
+ this.chunk('+');
+ this.chunk(b);
+ }
+ }
+ } else {
+ this.chunk(String(node.b));
+ }
+ }
+ };
+
+ var tokenizer = tokenizer$3;
+ var TYPE$x = tokenizer.TYPE;
+
+ var WhiteSpace$1 = TYPE$x.WhiteSpace;
+ var Semicolon = TYPE$x.Semicolon;
+ var LeftCurlyBracket = TYPE$x.LeftCurlyBracket;
+ var Delim = TYPE$x.Delim;
+ var EXCLAMATIONMARK$2 = 0x0021; // U+0021 EXCLAMATION MARK (!)
+
+ function getOffsetExcludeWS() {
+ if (this.scanner.tokenIndex > 0) {
+ if (this.scanner.lookupType(-1) === WhiteSpace$1) {
+ return this.scanner.tokenIndex > 1
+ ? this.scanner.getTokenStart(this.scanner.tokenIndex - 1)
+ : this.scanner.firstCharOffset;
+ }
+ }
+
+ return this.scanner.tokenStart;
+ }
+
+ // 0, 0, false
+ function balanceEnd() {
+ return 0;
+ }
+
+ // LEFTCURLYBRACKET, 0, false
+ function leftCurlyBracket(tokenType) {
+ return tokenType === LeftCurlyBracket ? 1 : 0;
+ }
+
+ // LEFTCURLYBRACKET, SEMICOLON, false
+ function leftCurlyBracketOrSemicolon(tokenType) {
+ return tokenType === LeftCurlyBracket || tokenType === Semicolon ? 1 : 0;
+ }
+
+ // EXCLAMATIONMARK, SEMICOLON, false
+ function exclamationMarkOrSemicolon(tokenType, source, offset) {
+ if (tokenType === Delim && source.charCodeAt(offset) === EXCLAMATIONMARK$2) {
+ return 1;
+ }
+
+ return tokenType === Semicolon ? 1 : 0;
+ }
+
+ // 0, SEMICOLON, true
+ function semicolonIncluded(tokenType) {
+ return tokenType === Semicolon ? 2 : 0;
+ }
+
+ var Raw = {
+ name: 'Raw',
+ structure: {
+ value: String
+ },
+ parse: function(startToken, mode, excludeWhiteSpace) {
+ var startOffset = this.scanner.getTokenStart(startToken);
+ var endOffset;
+
+ this.scanner.skip(
+ this.scanner.getRawLength(startToken, mode || balanceEnd)
+ );
+
+ if (excludeWhiteSpace && this.scanner.tokenStart > startOffset) {
+ endOffset = getOffsetExcludeWS.call(this);
+ } else {
+ endOffset = this.scanner.tokenStart;
+ }
+
+ return {
+ type: 'Raw',
+ loc: this.getLocation(startOffset, endOffset),
+ value: this.scanner.source.substring(startOffset, endOffset)
+ };
+ },
+ generate: function(node) {
+ this.chunk(node.value);
+ },
+
+ mode: {
+ default: balanceEnd,
+ leftCurlyBracket: leftCurlyBracket,
+ leftCurlyBracketOrSemicolon: leftCurlyBracketOrSemicolon,
+ exclamationMarkOrSemicolon: exclamationMarkOrSemicolon,
+ semicolonIncluded: semicolonIncluded
+ }
+ };
+
+ var TYPE$w = tokenizer$3.TYPE;
+ var rawMode$5 = Raw.mode;
+
+ var ATKEYWORD$2 = TYPE$w.AtKeyword;
+ var SEMICOLON$4 = TYPE$w.Semicolon;
+ var LEFTCURLYBRACKET$3 = TYPE$w.LeftCurlyBracket;
+ var RIGHTCURLYBRACKET$1 = TYPE$w.RightCurlyBracket;
+
+ function consumeRaw$5(startToken) {
+ return this.Raw(startToken, rawMode$5.leftCurlyBracketOrSemicolon, true);
+ }
+
+ function isDeclarationBlockAtrule() {
+ for (var offset = 1, type; type = this.scanner.lookupType(offset); offset++) {
+ if (type === RIGHTCURLYBRACKET$1) {
+ return true;
+ }
+
+ if (type === LEFTCURLYBRACKET$3 ||
+ type === ATKEYWORD$2) {
+ return false;
+ }
+ }
+
+ return false;
+ }
+
+ var Atrule = {
+ name: 'Atrule',
+ structure: {
+ name: String,
+ prelude: ['AtrulePrelude', 'Raw', null],
+ block: ['Block', null]
+ },
+ parse: function() {
+ var start = this.scanner.tokenStart;
+ var name;
+ var nameLowerCase;
+ var prelude = null;
+ var block = null;
+
+ this.eat(ATKEYWORD$2);
+
+ name = this.scanner.substrToCursor(start + 1);
+ nameLowerCase = name.toLowerCase();
+ this.scanner.skipSC();
+
+ // parse prelude
+ if (this.scanner.eof === false &&
+ this.scanner.tokenType !== LEFTCURLYBRACKET$3 &&
+ this.scanner.tokenType !== SEMICOLON$4) {
+ if (this.parseAtrulePrelude) {
+ prelude = this.parseWithFallback(this.AtrulePrelude.bind(this, name), consumeRaw$5);
+
+ // turn empty AtrulePrelude into null
+ if (prelude.type === 'AtrulePrelude' && prelude.children.head === null) {
+ prelude = null;
+ }
+ } else {
+ prelude = consumeRaw$5.call(this, this.scanner.tokenIndex);
+ }
+
+ this.scanner.skipSC();
+ }
+
+ switch (this.scanner.tokenType) {
+ case SEMICOLON$4:
+ this.scanner.next();
+ break;
+
+ case LEFTCURLYBRACKET$3:
+ if (this.atrule.hasOwnProperty(nameLowerCase) &&
+ typeof this.atrule[nameLowerCase].block === 'function') {
+ block = this.atrule[nameLowerCase].block.call(this);
+ } else {
+ // TODO: should consume block content as Raw?
+ block = this.Block(isDeclarationBlockAtrule.call(this));
+ }
+
+ break;
+ }
+
+ return {
+ type: 'Atrule',
+ loc: this.getLocation(start, this.scanner.tokenStart),
+ name: name,
+ prelude: prelude,
+ block: block
+ };
+ },
+ generate: function(node) {
+ this.chunk('@');
+ this.chunk(node.name);
+
+ if (node.prelude !== null) {
+ this.chunk(' ');
+ this.node(node.prelude);
+ }
+
+ if (node.block) {
+ this.node(node.block);
+ } else {
+ this.chunk(';');
+ }
+ },
+ walkContext: 'atrule'
+ };
+
+ var TYPE$v = tokenizer$3.TYPE;
+
+ var SEMICOLON$3 = TYPE$v.Semicolon;
+ var LEFTCURLYBRACKET$2 = TYPE$v.LeftCurlyBracket;
+
+ var AtrulePrelude = {
+ name: 'AtrulePrelude',
+ structure: {
+ children: [[]]
+ },
+ parse: function(name) {
+ var children = null;
+
+ if (name !== null) {
+ name = name.toLowerCase();
+ }
+
+ this.scanner.skipSC();
+
+ if (this.atrule.hasOwnProperty(name) &&
+ typeof this.atrule[name].prelude === 'function') {
+ // custom consumer
+ children = this.atrule[name].prelude.call(this);
+ } else {
+ // default consumer
+ children = this.readSequence(this.scope.AtrulePrelude);
+ }
+
+ this.scanner.skipSC();
+
+ if (this.scanner.eof !== true &&
+ this.scanner.tokenType !== LEFTCURLYBRACKET$2 &&
+ this.scanner.tokenType !== SEMICOLON$3) {
+ this.error('Semicolon or block is expected');
+ }
+
+ if (children === null) {
+ children = this.createList();
+ }
+
+ return {
+ type: 'AtrulePrelude',
+ loc: this.getLocationFromList(children),
+ children: children
+ };
+ },
+ generate: function(node) {
+ this.children(node);
+ },
+ walkContext: 'atrulePrelude'
+ };
+
+ var TYPE$u = tokenizer$3.TYPE;
+
+ var IDENT$e = TYPE$u.Ident;
+ var STRING$3 = TYPE$u.String;
+ var COLON$6 = TYPE$u.Colon;
+ var LEFTSQUAREBRACKET$3 = TYPE$u.LeftSquareBracket;
+ var RIGHTSQUAREBRACKET$1 = TYPE$u.RightSquareBracket;
+ var DOLLARSIGN$1 = 0x0024; // U+0024 DOLLAR SIGN ($)
+ var ASTERISK$5 = 0x002A; // U+002A ASTERISK (*)
+ var EQUALSSIGN = 0x003D; // U+003D EQUALS SIGN (=)
+ var CIRCUMFLEXACCENT = 0x005E; // U+005E (^)
+ var VERTICALLINE$2 = 0x007C; // U+007C VERTICAL LINE (|)
+ var TILDE$2 = 0x007E; // U+007E TILDE (~)
+
+ function getAttributeName() {
+ if (this.scanner.eof) {
+ this.error('Unexpected end of input');
+ }
+
+ var start = this.scanner.tokenStart;
+ var expectIdent = false;
+ var checkColon = true;
+
+ if (this.scanner.isDelim(ASTERISK$5)) {
+ expectIdent = true;
+ checkColon = false;
+ this.scanner.next();
+ } else if (!this.scanner.isDelim(VERTICALLINE$2)) {
+ this.eat(IDENT$e);
+ }
+
+ if (this.scanner.isDelim(VERTICALLINE$2)) {
+ if (this.scanner.source.charCodeAt(this.scanner.tokenStart + 1) !== EQUALSSIGN) {
+ this.scanner.next();
+ this.eat(IDENT$e);
+ } else if (expectIdent) {
+ this.error('Identifier is expected', this.scanner.tokenEnd);
+ }
+ } else if (expectIdent) {
+ this.error('Vertical line is expected');
+ }
+
+ if (checkColon && this.scanner.tokenType === COLON$6) {
+ this.scanner.next();
+ this.eat(IDENT$e);
+ }
+
+ return {
+ type: 'Identifier',
+ loc: this.getLocation(start, this.scanner.tokenStart),
+ name: this.scanner.substrToCursor(start)
+ };
+ }
+
+ function getOperator() {
+ var start = this.scanner.tokenStart;
+ var code = this.scanner.source.charCodeAt(start);
+
+ if (code !== EQUALSSIGN && // =
+ code !== TILDE$2 && // ~=
+ code !== CIRCUMFLEXACCENT && // ^=
+ code !== DOLLARSIGN$1 && // $=
+ code !== ASTERISK$5 && // *=
+ code !== VERTICALLINE$2 // |=
+ ) {
+ this.error('Attribute selector (=, ~=, ^=, $=, *=, |=) is expected');
+ }
+
+ this.scanner.next();
+
+ if (code !== EQUALSSIGN) {
+ if (!this.scanner.isDelim(EQUALSSIGN)) {
+ this.error('Equal sign is expected');
+ }
+
+ this.scanner.next();
+ }
+
+ return this.scanner.substrToCursor(start);
+ }
+
+ // '[' ']'
+ // '[' [ | ] ? ']'
+ var AttributeSelector = {
+ name: 'AttributeSelector',
+ structure: {
+ name: 'Identifier',
+ matcher: [String, null],
+ value: ['String', 'Identifier', null],
+ flags: [String, null]
+ },
+ parse: function() {
+ var start = this.scanner.tokenStart;
+ var name;
+ var matcher = null;
+ var value = null;
+ var flags = null;
+
+ this.eat(LEFTSQUAREBRACKET$3);
+ this.scanner.skipSC();
+
+ name = getAttributeName.call(this);
+ this.scanner.skipSC();
+
+ if (this.scanner.tokenType !== RIGHTSQUAREBRACKET$1) {
+ // avoid case `[name i]`
+ if (this.scanner.tokenType !== IDENT$e) {
+ matcher = getOperator.call(this);
+
+ this.scanner.skipSC();
+
+ value = this.scanner.tokenType === STRING$3
+ ? this.String()
+ : this.Identifier();
+
+ this.scanner.skipSC();
+ }
+
+ // attribute flags
+ if (this.scanner.tokenType === IDENT$e) {
+ flags = this.scanner.getTokenValue();
+ this.scanner.next();
+
+ this.scanner.skipSC();
+ }
+ }
+
+ this.eat(RIGHTSQUAREBRACKET$1);
+
+ return {
+ type: 'AttributeSelector',
+ loc: this.getLocation(start, this.scanner.tokenStart),
+ name: name,
+ matcher: matcher,
+ value: value,
+ flags: flags
+ };
+ },
+ generate: function(node) {
+ var flagsPrefix = ' ';
+
+ this.chunk('[');
+ this.node(node.name);
+
+ if (node.matcher !== null) {
+ this.chunk(node.matcher);
+
+ if (node.value !== null) {
+ this.node(node.value);
+
+ // space between string and flags is not required
+ if (node.value.type === 'String') {
+ flagsPrefix = '';
+ }
+ }
+ }
+
+ if (node.flags !== null) {
+ this.chunk(flagsPrefix);
+ this.chunk(node.flags);
+ }
+
+ this.chunk(']');
+ }
+ };
+
+ var TYPE$t = tokenizer$3.TYPE;
+ var rawMode$4 = Raw.mode;
+
+ var WHITESPACE$7 = TYPE$t.WhiteSpace;
+ var COMMENT$5 = TYPE$t.Comment;
+ var SEMICOLON$2 = TYPE$t.Semicolon;
+ var ATKEYWORD$1 = TYPE$t.AtKeyword;
+ var LEFTCURLYBRACKET$1 = TYPE$t.LeftCurlyBracket;
+ var RIGHTCURLYBRACKET = TYPE$t.RightCurlyBracket;
+
+ function consumeRaw$4(startToken) {
+ return this.Raw(startToken, null, true);
+ }
+ function consumeRule() {
+ return this.parseWithFallback(this.Rule, consumeRaw$4);
+ }
+ function consumeRawDeclaration(startToken) {
+ return this.Raw(startToken, rawMode$4.semicolonIncluded, true);
+ }
+ function consumeDeclaration() {
+ if (this.scanner.tokenType === SEMICOLON$2) {
+ return consumeRawDeclaration.call(this, this.scanner.tokenIndex);
+ }
+
+ var node = this.parseWithFallback(this.Declaration, consumeRawDeclaration);
+
+ if (this.scanner.tokenType === SEMICOLON$2) {
+ this.scanner.next();
+ }
+
+ return node;
+ }
+
+ var Block = {
+ name: 'Block',
+ structure: {
+ children: [[
+ 'Atrule',
+ 'Rule',
+ 'Declaration'
+ ]]
+ },
+ parse: function(isDeclaration) {
+ var consumer = isDeclaration ? consumeDeclaration : consumeRule;
+
+ var start = this.scanner.tokenStart;
+ var children = this.createList();
+
+ this.eat(LEFTCURLYBRACKET$1);
+
+ scan:
+ while (!this.scanner.eof) {
+ switch (this.scanner.tokenType) {
+ case RIGHTCURLYBRACKET:
+ break scan;
+
+ case WHITESPACE$7:
+ case COMMENT$5:
+ this.scanner.next();
+ break;
+
+ case ATKEYWORD$1:
+ children.push(this.parseWithFallback(this.Atrule, consumeRaw$4));
+ break;
+
+ default:
+ children.push(consumer.call(this));
+ }
+ }
+
+ if (!this.scanner.eof) {
+ this.eat(RIGHTCURLYBRACKET);
+ }
+
+ return {
+ type: 'Block',
+ loc: this.getLocation(start, this.scanner.tokenStart),
+ children: children
+ };
+ },
+ generate: function(node) {
+ this.chunk('{');
+ this.children(node, function(prev) {
+ if (prev.type === 'Declaration') {
+ this.chunk(';');
+ }
+ });
+ this.chunk('}');
+ },
+ walkContext: 'block'
+ };
+
+ var TYPE$s = tokenizer$3.TYPE;
+
+ var LEFTSQUAREBRACKET$2 = TYPE$s.LeftSquareBracket;
+ var RIGHTSQUAREBRACKET = TYPE$s.RightSquareBracket;
+
+ var Brackets = {
+ name: 'Brackets',
+ structure: {
+ children: [[]]
+ },
+ parse: function(readSequence, recognizer) {
+ var start = this.scanner.tokenStart;
+ var children = null;
+
+ this.eat(LEFTSQUAREBRACKET$2);
+
+ children = readSequence.call(this, recognizer);
+
+ if (!this.scanner.eof) {
+ this.eat(RIGHTSQUAREBRACKET);
+ }
+
+ return {
+ type: 'Brackets',
+ loc: this.getLocation(start, this.scanner.tokenStart),
+ children: children
+ };
+ },
+ generate: function(node) {
+ this.chunk('[');
+ this.children(node);
+ this.chunk(']');
+ }
+ };
+
+ var CDC$1 = tokenizer$3.TYPE.CDC;
+
+ var CDC_1 = {
+ name: 'CDC',
+ structure: [],
+ parse: function() {
+ var start = this.scanner.tokenStart;
+
+ this.eat(CDC$1); // -->
+
+ return {
+ type: 'CDC',
+ loc: this.getLocation(start, this.scanner.tokenStart)
+ };
+ },
+ generate: function() {
+ this.chunk('-->');
+ }
+ };
+
+ var CDO$1 = tokenizer$3.TYPE.CDO;
+
+ var CDO_1 = {
+ name: 'CDO',
+ structure: [],
+ parse: function() {
+ var start = this.scanner.tokenStart;
+
+ this.eat(CDO$1); //
+ child = this.CDC();
+ break;
+
+ // CSS Syntax Module Level 3
+ // §2.2 Error handling
+ // At the "top level" of a stylesheet, an starts an at-rule.
+ case ATKEYWORD:
+ child = this.parseWithFallback(this.Atrule, consumeRaw$1);
+ break;
+
+ // Anything else starts a qualified rule ...
+ default:
+ child = this.parseWithFallback(this.Rule, consumeRaw$1);
+ }
+
+ children.push(child);
+ }
+
+ return {
+ type: 'StyleSheet',
+ loc: this.getLocation(start, this.scanner.tokenStart),
+ children: children
+ };
+ },
+ generate: function(node) {
+ this.children(node);
+ },
+ walkContext: 'stylesheet'
+ };
+
+ var TYPE$7 = tokenizer$3.TYPE;
+
+ var IDENT$5 = TYPE$7.Ident;
+ var ASTERISK$2 = 0x002A; // U+002A ASTERISK (*)
+ var VERTICALLINE$1 = 0x007C; // U+007C VERTICAL LINE (|)
+
+ function eatIdentifierOrAsterisk() {
+ if (this.scanner.tokenType !== IDENT$5 &&
+ this.scanner.isDelim(ASTERISK$2) === false) {
+ this.error('Identifier or asterisk is expected');
+ }
+
+ this.scanner.next();
+ }
+
+ // ident
+ // ident|ident
+ // ident|*
+ // *
+ // *|ident
+ // *|*
+ // |ident
+ // |*
+ var TypeSelector = {
+ name: 'TypeSelector',
+ structure: {
+ name: String
+ },
+ parse: function() {
+ var start = this.scanner.tokenStart;
+
+ if (this.scanner.isDelim(VERTICALLINE$1)) {
+ this.scanner.next();
+ eatIdentifierOrAsterisk.call(this);
+ } else {
+ eatIdentifierOrAsterisk.call(this);
+
+ if (this.scanner.isDelim(VERTICALLINE$1)) {
+ this.scanner.next();
+ eatIdentifierOrAsterisk.call(this);
+ }
+ }
+
+ return {
+ type: 'TypeSelector',
+ loc: this.getLocation(start, this.scanner.tokenStart),
+ name: this.scanner.substrToCursor(start)
+ };
+ },
+ generate: function(node) {
+ this.chunk(node.name);
+ }
+ };
+
+ var isHexDigit = tokenizer$3.isHexDigit;
+ var cmpChar$1 = tokenizer$3.cmpChar;
+ var TYPE$6 = tokenizer$3.TYPE;
+ var NAME = tokenizer$3.NAME;
+
+ var IDENT$4 = TYPE$6.Ident;
+ var NUMBER$2 = TYPE$6.Number;
+ var DIMENSION$2 = TYPE$6.Dimension;
+ var PLUSSIGN$2 = 0x002B; // U+002B PLUS SIGN (+)
+ var HYPHENMINUS$1 = 0x002D; // U+002D HYPHEN-MINUS (-)
+ var QUESTIONMARK = 0x003F; // U+003F QUESTION MARK (?)
+ var U$1 = 0x0075; // U+0075 LATIN SMALL LETTER U (u)
+
+ function eatHexSequence(offset, allowDash) {
+ for (var pos = this.scanner.tokenStart + offset, len = 0; pos < this.scanner.tokenEnd; pos++) {
+ var code = this.scanner.source.charCodeAt(pos);
+
+ if (code === HYPHENMINUS$1 && allowDash && len !== 0) {
+ if (eatHexSequence.call(this, offset + len + 1, false) === 0) {
+ this.error();
+ }
+
+ return -1;
+ }
+
+ if (!isHexDigit(code)) {
+ this.error(
+ allowDash && len !== 0
+ ? 'HyphenMinus' + (len < 6 ? ' or hex digit' : '') + ' is expected'
+ : (len < 6 ? 'Hex digit is expected' : 'Unexpected input'),
+ pos
+ );
+ }
+
+ if (++len > 6) {
+ this.error('Too many hex digits', pos);
+ } }
+
+ this.scanner.next();
+ return len;
+ }
+
+ function eatQuestionMarkSequence(max) {
+ var count = 0;
+
+ while (this.scanner.isDelim(QUESTIONMARK)) {
+ if (++count > max) {
+ this.error('Too many question marks');
+ }
+
+ this.scanner.next();
+ }
+ }
+
+ function startsWith(code) {
+ if (this.scanner.source.charCodeAt(this.scanner.tokenStart) !== code) {
+ this.error(NAME[code] + ' is expected');
+ }
+ }
+
+ // https://drafts.csswg.org/css-syntax/#urange
+ // Informally, the production has three forms:
+ // U+0001
+ // Defines a range consisting of a single code point, in this case the code point "1".
+ // U+0001-00ff
+ // Defines a range of codepoints between the first and the second value, in this case
+ // the range between "1" and "ff" (255 in decimal) inclusive.
+ // U+00??
+ // Defines a range of codepoints where the "?" characters range over all hex digits,
+ // in this case defining the same as the value U+0000-00ff.
+ // In each form, a maximum of 6 digits is allowed for each hexadecimal number (if you treat "?" as a hexadecimal digit).
+ //
+ // =
+ // u '+' '?'* |
+ // u '?'* |
+ // u '?'* |
+ // u |
+ // u |
+ // u '+' '?'+
+ function scanUnicodeRange() {
+ var hexLength = 0;
+
+ // u '+' '?'*
+ // u '+' '?'+
+ if (this.scanner.isDelim(PLUSSIGN$2)) {
+ this.scanner.next();
+
+ if (this.scanner.tokenType === IDENT$4) {
+ hexLength = eatHexSequence.call(this, 0, true);
+ if (hexLength > 0) {
+ eatQuestionMarkSequence.call(this, 6 - hexLength);
+ }
+ return;
+ }
+
+ if (this.scanner.isDelim(QUESTIONMARK)) {
+ this.scanner.next();
+ eatQuestionMarkSequence.call(this, 5);
+ return;
+ }
+
+ this.error('Hex digit or question mark is expected');
+ return;
+ }
+
+ // u '?'*
+ // u
+ // u
+ if (this.scanner.tokenType === NUMBER$2) {
+ startsWith.call(this, PLUSSIGN$2);
+ hexLength = eatHexSequence.call(this, 1, true);
+
+ if (this.scanner.isDelim(QUESTIONMARK)) {
+ eatQuestionMarkSequence.call(this, 6 - hexLength);
+ return;
+ }
+
+ if (this.scanner.tokenType === DIMENSION$2 ||
+ this.scanner.tokenType === NUMBER$2) {
+ startsWith.call(this, HYPHENMINUS$1);
+ eatHexSequence.call(this, 1, false);
+ return;
+ }
+
+ return;
+ }
+
+ // u '?'*
+ if (this.scanner.tokenType === DIMENSION$2) {
+ startsWith.call(this, PLUSSIGN$2);
+ hexLength = eatHexSequence.call(this, 1, true);
+
+ if (hexLength > 0) {
+ eatQuestionMarkSequence.call(this, 6 - hexLength);
+ }
+
+ return;
+ }
+
+ this.error();
+ }
+
+ var UnicodeRange = {
+ name: 'UnicodeRange',
+ structure: {
+ value: String
+ },
+ parse: function() {
+ var start = this.scanner.tokenStart;
+
+ // U or u
+ if (!cmpChar$1(this.scanner.source, start, U$1)) {
+ this.error('U is expected');
+ }
+
+ if (!cmpChar$1(this.scanner.source, start + 1, PLUSSIGN$2)) {
+ this.error('Plus sign is expected');
+ }
+
+ this.scanner.next();
+ scanUnicodeRange.call(this);
+
+ return {
+ type: 'UnicodeRange',
+ loc: this.getLocation(start, this.scanner.tokenStart),
+ value: this.scanner.substrToCursor(start)
+ };
+ },
+ generate: function(node) {
+ this.chunk(node.value);
+ }
+ };
+
+ var isWhiteSpace = tokenizer$3.isWhiteSpace;
+ var cmpStr$1 = tokenizer$3.cmpStr;
+ var TYPE$5 = tokenizer$3.TYPE;
+
+ var FUNCTION$3 = TYPE$5.Function;
+ var URL$3 = TYPE$5.Url;
+ var RIGHTPARENTHESIS = TYPE$5.RightParenthesis;
+
+ // | )
+ var Url = {
+ name: 'Url',
+ structure: {
+ value: ['String', 'Raw']
+ },
+ parse: function() {
+ var start = this.scanner.tokenStart;
+ var value;
+
+ switch (this.scanner.tokenType) {
+ case URL$3:
+ var rawStart = start + 4;
+ var rawEnd = this.scanner.tokenEnd - 1;
+
+ while (rawStart < rawEnd && isWhiteSpace(this.scanner.source.charCodeAt(rawStart))) {
+ rawStart++;
+ }
+
+ while (rawStart < rawEnd && isWhiteSpace(this.scanner.source.charCodeAt(rawEnd - 1))) {
+ rawEnd--;
+ }
+
+ value = {
+ type: 'Raw',
+ loc: this.getLocation(rawStart, rawEnd),
+ value: this.scanner.source.substring(rawStart, rawEnd)
+ };
+
+ this.eat(URL$3);
+ break;
+
+ case FUNCTION$3:
+ if (!cmpStr$1(this.scanner.source, this.scanner.tokenStart, this.scanner.tokenEnd, 'url(')) {
+ this.error('Function name must be `url`');
+ }
+
+ this.eat(FUNCTION$3);
+ this.scanner.skipSC();
+ value = this.String();
+ this.scanner.skipSC();
+ this.eat(RIGHTPARENTHESIS);
+ break;
+
+ default:
+ this.error('Url or Function is expected');
+ }
+
+ return {
+ type: 'Url',
+ loc: this.getLocation(start, this.scanner.tokenStart),
+ value: value
+ };
+ },
+ generate: function(node) {
+ this.chunk('url');
+ this.chunk('(');
+ this.node(node.value);
+ this.chunk(')');
+ }
+ };
+
+ var Value = {
+ name: 'Value',
+ structure: {
+ children: [[]]
+ },
+ parse: function() {
+ var start = this.scanner.tokenStart;
+ var children = this.readSequence(this.scope.Value);
+
+ return {
+ type: 'Value',
+ loc: this.getLocation(start, this.scanner.tokenStart),
+ children: children
+ };
+ },
+ generate: function(node) {
+ this.children(node);
+ }
+ };
+
+ var WHITESPACE$2 = tokenizer$3.TYPE.WhiteSpace;
+ var SPACE = Object.freeze({
+ type: 'WhiteSpace',
+ loc: null,
+ value: ' '
+ });
+
+ var WhiteSpace = {
+ name: 'WhiteSpace',
+ structure: {
+ value: String
+ },
+ parse: function() {
+ this.eat(WHITESPACE$2);
+ return SPACE;
+
+ // return {
+ // type: 'WhiteSpace',
+ // loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
+ // value: this.consume(WHITESPACE)
+ // };
+ },
+ generate: function(node) {
+ this.chunk(node.value);
+ }
+ };
+
+ var node = {
+ AnPlusB: AnPlusB,
+ Atrule: Atrule,
+ AtrulePrelude: AtrulePrelude,
+ AttributeSelector: AttributeSelector,
+ Block: Block,
+ Brackets: Brackets,
+ CDC: CDC_1,
+ CDO: CDO_1,
+ ClassSelector: ClassSelector,
+ Combinator: Combinator,
+ Comment: Comment,
+ Declaration: Declaration,
+ DeclarationList: DeclarationList,
+ Dimension: Dimension,
+ Function: _Function,
+ Hash: Hash,
+ Identifier: Identifier,
+ IdSelector: IdSelector,
+ MediaFeature: MediaFeature,
+ MediaQuery: MediaQuery,
+ MediaQueryList: MediaQueryList,
+ Nth: Nth,
+ Number: _Number,
+ Operator: Operator,
+ Parentheses: Parentheses,
+ Percentage: Percentage,
+ PseudoClassSelector: PseudoClassSelector,
+ PseudoElementSelector: PseudoElementSelector,
+ Ratio: Ratio,
+ Raw: Raw,
+ Rule: Rule,
+ Selector: Selector,
+ SelectorList: SelectorList,
+ String: _String,
+ StyleSheet: StyleSheet,
+ TypeSelector: TypeSelector,
+ UnicodeRange: UnicodeRange,
+ Url: Url,
+ Value: Value,
+ WhiteSpace: WhiteSpace
+ };
+
+ var data = data$1;
+
+ var lexer = {
+ generic: true,
+ types: data.types,
+ atrules: data.atrules,
+ properties: data.properties,
+ node: node
+ };
+
+ var cmpChar = tokenizer$3.cmpChar;
+ var cmpStr = tokenizer$3.cmpStr;
+ var TYPE$4 = tokenizer$3.TYPE;
+
+ var IDENT$3 = TYPE$4.Ident;
+ var STRING$1 = TYPE$4.String;
+ var NUMBER$1 = TYPE$4.Number;
+ var FUNCTION$2 = TYPE$4.Function;
+ var URL$2 = TYPE$4.Url;
+ var HASH$1 = TYPE$4.Hash;
+ var DIMENSION$1 = TYPE$4.Dimension;
+ var PERCENTAGE$1 = TYPE$4.Percentage;
+ var LEFTPARENTHESIS$2 = TYPE$4.LeftParenthesis;
+ var LEFTSQUAREBRACKET$1 = TYPE$4.LeftSquareBracket;
+ var COMMA$1 = TYPE$4.Comma;
+ var DELIM$1 = TYPE$4.Delim;
+ var NUMBERSIGN$1 = 0x0023; // U+0023 NUMBER SIGN (#)
+ var ASTERISK$1 = 0x002A; // U+002A ASTERISK (*)
+ var PLUSSIGN$1 = 0x002B; // U+002B PLUS SIGN (+)
+ var HYPHENMINUS = 0x002D; // U+002D HYPHEN-MINUS (-)
+ var SOLIDUS$1 = 0x002F; // U+002F SOLIDUS (/)
+ var U = 0x0075; // U+0075 LATIN SMALL LETTER U (u)
+
+ var _default = function defaultRecognizer(context) {
+ switch (this.scanner.tokenType) {
+ case HASH$1:
+ return this.Hash();
+
+ case COMMA$1:
+ context.space = null;
+ context.ignoreWSAfter = true;
+ return this.Operator();
+
+ case LEFTPARENTHESIS$2:
+ return this.Parentheses(this.readSequence, context.recognizer);
+
+ case LEFTSQUAREBRACKET$1:
+ return this.Brackets(this.readSequence, context.recognizer);
+
+ case STRING$1:
+ return this.String();
+
+ case DIMENSION$1:
+ return this.Dimension();
+
+ case PERCENTAGE$1:
+ return this.Percentage();
+
+ case NUMBER$1:
+ return this.Number();
+
+ case FUNCTION$2:
+ return cmpStr(this.scanner.source, this.scanner.tokenStart, this.scanner.tokenEnd, 'url(')
+ ? this.Url()
+ : this.Function(this.readSequence, context.recognizer);
+
+ case URL$2:
+ return this.Url();
+
+ case IDENT$3:
+ // check for unicode range, it should start with u+ or U+
+ if (cmpChar(this.scanner.source, this.scanner.tokenStart, U) &&
+ cmpChar(this.scanner.source, this.scanner.tokenStart + 1, PLUSSIGN$1)) {
+ return this.UnicodeRange();
+ } else {
+ return this.Identifier();
+ }
+
+ case DELIM$1:
+ var code = this.scanner.source.charCodeAt(this.scanner.tokenStart);
+
+ if (code === SOLIDUS$1 ||
+ code === ASTERISK$1 ||
+ code === PLUSSIGN$1 ||
+ code === HYPHENMINUS) {
+ return this.Operator(); // TODO: replace with Delim
+ }
+
+ // TODO: produce a node with Delim node type
+
+ if (code === NUMBERSIGN$1) {
+ this.error('Hex or identifier is expected', this.scanner.tokenStart + 1);
+ }
+
+ break;
+ }
+ };
+
+ var atrulePrelude = {
+ getNode: _default
+ };
+
+ var TYPE$3 = tokenizer$3.TYPE;
+
+ var DELIM = TYPE$3.Delim;
+ var IDENT$2 = TYPE$3.Ident;
+ var DIMENSION = TYPE$3.Dimension;
+ var PERCENTAGE = TYPE$3.Percentage;
+ var NUMBER = TYPE$3.Number;
+ var HASH = TYPE$3.Hash;
+ var COLON$1 = TYPE$3.Colon;
+ var LEFTSQUAREBRACKET = TYPE$3.LeftSquareBracket;
+ var NUMBERSIGN = 0x0023; // U+0023 NUMBER SIGN (#)
+ var ASTERISK = 0x002A; // U+002A ASTERISK (*)
+ var PLUSSIGN = 0x002B; // U+002B PLUS SIGN (+)
+ var SOLIDUS = 0x002F; // U+002F SOLIDUS (/)
+ var FULLSTOP = 0x002E; // U+002E FULL STOP (.)
+ var GREATERTHANSIGN = 0x003E; // U+003E GREATER-THAN SIGN (>)
+ var VERTICALLINE = 0x007C; // U+007C VERTICAL LINE (|)
+ var TILDE = 0x007E; // U+007E TILDE (~)
+
+ function getNode(context) {
+ switch (this.scanner.tokenType) {
+ case LEFTSQUAREBRACKET:
+ return this.AttributeSelector();
+
+ case HASH:
+ return this.IdSelector();
+
+ case COLON$1:
+ if (this.scanner.lookupType(1) === COLON$1) {
+ return this.PseudoElementSelector();
+ } else {
+ return this.PseudoClassSelector();
+ }
+
+ case IDENT$2:
+ return this.TypeSelector();
+
+ case NUMBER:
+ case PERCENTAGE:
+ return this.Percentage();
+
+ case DIMENSION:
+ // throws when .123ident
+ if (this.scanner.source.charCodeAt(this.scanner.tokenStart) === FULLSTOP) {
+ this.error('Identifier is expected', this.scanner.tokenStart + 1);
+ }
+ break;
+
+ case DELIM:
+ var code = this.scanner.source.charCodeAt(this.scanner.tokenStart);
+
+ switch (code) {
+ case PLUSSIGN:
+ case GREATERTHANSIGN:
+ case TILDE:
+ context.space = null;
+ context.ignoreWSAfter = true;
+ return this.Combinator();
+
+ case SOLIDUS: // /deep/
+ return this.Combinator();
+
+ case FULLSTOP:
+ return this.ClassSelector();
+
+ case ASTERISK:
+ case VERTICALLINE:
+ return this.TypeSelector();
+
+ case NUMBERSIGN:
+ return this.IdSelector();
+ }
+
+ break;
+ }
+ }
+ var selector = {
+ getNode: getNode
+ };
+
+ // legacy IE function
+ // expression( )
+ var expression = function() {
+ return this.createSingleNodeList(
+ this.Raw(this.scanner.tokenIndex, null, false)
+ );
+ };
+
+ var TYPE$2 = tokenizer$3.TYPE;
+ var rawMode = Raw.mode;
+
+ var COMMA = TYPE$2.Comma;
+ var WHITESPACE$1 = TYPE$2.WhiteSpace;
+
+ // var( , ? )
+ var _var = function() {
+ var children = this.createList();
+
+ this.scanner.skipSC();
+
+ // NOTE: Don't check more than a first argument is an ident, rest checks are for lexer
+ children.push(this.Identifier());
+
+ this.scanner.skipSC();
+
+ if (this.scanner.tokenType === COMMA) {
+ children.push(this.Operator());
+
+ const startIndex = this.scanner.tokenIndex;
+ const value = this.parseCustomProperty
+ ? this.Value(null)
+ : this.Raw(this.scanner.tokenIndex, rawMode.exclamationMarkOrSemicolon, false);
+
+ if (value.type === 'Value' && value.children.isEmpty()) {
+ for (let offset = startIndex - this.scanner.tokenIndex; offset <= 0; offset++) {
+ if (this.scanner.lookupType(offset) === WHITESPACE$1) {
+ value.children.appendData({
+ type: 'WhiteSpace',
+ loc: null,
+ value: ' '
+ });
+ break;
+ }
+ }
+ }
+
+ children.push(value);
+ }
+
+ return children;
+ };
+
+ var value$2 = {
+ getNode: _default,
+ 'expression': expression,
+ 'var': _var
+ };
+
+ var scope = {
+ AtrulePrelude: atrulePrelude,
+ Selector: selector,
+ Value: value$2
+ };
+
+ var fontFace = {
+ parse: {
+ prelude: null,
+ block: function() {
+ return this.Block(true);
+ }
+ }
+ };
+
+ var TYPE$1 = tokenizer$3.TYPE;
+
+ var STRING = TYPE$1.String;
+ var IDENT$1 = TYPE$1.Ident;
+ var URL$1 = TYPE$1.Url;
+ var FUNCTION$1 = TYPE$1.Function;
+ var LEFTPARENTHESIS$1 = TYPE$1.LeftParenthesis;
+
+ var _import = {
+ parse: {
+ prelude: function() {
+ var children = this.createList();
+
+ this.scanner.skipSC();
+
+ switch (this.scanner.tokenType) {
+ case STRING:
+ children.push(this.String());
+ break;
+
+ case URL$1:
+ case FUNCTION$1:
+ children.push(this.Url());
+ break;
+
+ default:
+ this.error('String or url() is expected');
+ }
+
+ if (this.lookupNonWSType(0) === IDENT$1 ||
+ this.lookupNonWSType(0) === LEFTPARENTHESIS$1) {
+ children.push(this.WhiteSpace());
+ children.push(this.MediaQueryList());
+ }
+
+ return children;
+ },
+ block: null
+ }
+ };
+
+ var media = {
+ parse: {
+ prelude: function() {
+ return this.createSingleNodeList(
+ this.MediaQueryList()
+ );
+ },
+ block: function() {
+ return this.Block(false);
+ }
+ }
+ };
+
+ var page = {
+ parse: {
+ prelude: function() {
+ return this.createSingleNodeList(
+ this.SelectorList()
+ );
+ },
+ block: function() {
+ return this.Block(true);
+ }
+ }
+ };
+
+ var TYPE = tokenizer$3.TYPE;
+
+ var WHITESPACE = TYPE.WhiteSpace;
+ var COMMENT = TYPE.Comment;
+ var IDENT = TYPE.Ident;
+ var FUNCTION = TYPE.Function;
+ var COLON = TYPE.Colon;
+ var LEFTPARENTHESIS = TYPE.LeftParenthesis;
+
+ function consumeRaw() {
+ return this.createSingleNodeList(
+ this.Raw(this.scanner.tokenIndex, null, false)
+ );
+ }
+
+ function parentheses() {
+ this.scanner.skipSC();
+
+ if (this.scanner.tokenType === IDENT &&
+ this.lookupNonWSType(1) === COLON) {
+ return this.createSingleNodeList(
+ this.Declaration()
+ );
+ }
+
+ return readSequence.call(this);
+ }
+
+ function readSequence() {
+ var children = this.createList();
+ var space = null;
+ var child;
+
+ this.scanner.skipSC();
+
+ scan:
+ while (!this.scanner.eof) {
+ switch (this.scanner.tokenType) {
+ case WHITESPACE:
+ space = this.WhiteSpace();
+ continue;
+
+ case COMMENT:
+ this.scanner.next();
+ continue;
+
+ case FUNCTION:
+ child = this.Function(consumeRaw, this.scope.AtrulePrelude);
+ break;
+
+ case IDENT:
+ child = this.Identifier();
+ break;
+
+ case LEFTPARENTHESIS:
+ child = this.Parentheses(parentheses, this.scope.AtrulePrelude);
+ break;
+
+ default:
+ break scan;
+ }
+
+ if (space !== null) {
+ children.push(space);
+ space = null;
+ }
+
+ children.push(child);
+ }
+
+ return children;
+ }
+
+ var supports = {
+ parse: {
+ prelude: function() {
+ var children = readSequence.call(this);
+
+ if (this.getFirstListNode(children) === null) {
+ this.error('Condition is expected');
+ }
+
+ return children;
+ },
+ block: function() {
+ return this.Block(false);
+ }
+ }
+ };
+
+ var atrule = {
+ 'font-face': fontFace,
+ 'import': _import,
+ 'media': media,
+ 'page': page,
+ 'supports': supports
+ };
+
+ var dir = {
+ parse: function() {
+ return this.createSingleNodeList(
+ this.Identifier()
+ );
+ }
+ };
+
+ var has = {
+ parse: function() {
+ return this.createSingleNodeList(
+ this.SelectorList()
+ );
+ }
+ };
+
+ var lang = {
+ parse: function() {
+ return this.createSingleNodeList(
+ this.Identifier()
+ );
+ }
+ };
+
+ var selectorList = {
+ parse: function selectorList() {
+ return this.createSingleNodeList(
+ this.SelectorList()
+ );
+ }
+ };
+
+ var matches = selectorList;
+
+ var not = selectorList;
+
+ var ALLOW_OF_CLAUSE = true;
+
+ var nthWithOfClause = {
+ parse: function nthWithOfClause() {
+ return this.createSingleNodeList(
+ this.Nth(ALLOW_OF_CLAUSE)
+ );
+ }
+ };
+
+ var nthChild = nthWithOfClause;
+
+ var nthLastChild = nthWithOfClause;
+
+ var DISALLOW_OF_CLAUSE = false;
+
+ var nth = {
+ parse: function nth() {
+ return this.createSingleNodeList(
+ this.Nth(DISALLOW_OF_CLAUSE)
+ );
+ }
+ };
+
+ var nthLastOfType = nth;
+
+ var nthOfType = nth;
+
+ var slotted = {
+ parse: function compoundSelector() {
+ return this.createSingleNodeList(
+ this.Selector()
+ );
+ }
+ };
+
+ var pseudo = {
+ 'dir': dir,
+ 'has': has,
+ 'lang': lang,
+ 'matches': matches,
+ 'not': not,
+ 'nth-child': nthChild,
+ 'nth-last-child': nthLastChild,
+ 'nth-last-of-type': nthLastOfType,
+ 'nth-of-type': nthOfType,
+ 'slotted': slotted
+ };
+
+ var parser = {
+ parseContext: {
+ default: 'StyleSheet',
+ stylesheet: 'StyleSheet',
+ atrule: 'Atrule',
+ atrulePrelude: function(options) {
+ return this.AtrulePrelude(options.atrule ? String(options.atrule) : null);
+ },
+ mediaQueryList: 'MediaQueryList',
+ mediaQuery: 'MediaQuery',
+ rule: 'Rule',
+ selectorList: 'SelectorList',
+ selector: 'Selector',
+ block: function() {
+ return this.Block(true);
+ },
+ declarationList: 'DeclarationList',
+ declaration: 'Declaration',
+ value: 'Value'
+ },
+ scope: scope,
+ atrule: atrule,
+ pseudo: pseudo,
+ node: node
+ };
+
+ var walker = {
+ node: node
+ };
+
+ var _args = [
+ [
+ "css-tree@1.1.3",
+ "/home/gitlab-runner/builds/BQJy2NwB/0/pagedjs/pagedjs"
+ ]
+ ];
+ var _from = "css-tree@1.1.3";
+ var _id = "css-tree@1.1.3";
+ var _inBundle = false;
+ var _integrity = "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==";
+ var _location = "/css-tree";
+ var _phantomChildren = {
+ };
+ var _requested = {
+ type: "version",
+ registry: true,
+ raw: "css-tree@1.1.3",
+ name: "css-tree",
+ escapedName: "css-tree",
+ rawSpec: "1.1.3",
+ saveSpec: null,
+ fetchSpec: "1.1.3"
+ };
+ var _requiredBy = [
+ "/"
+ ];
+ var _resolved = "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz";
+ var _spec = "1.1.3";
+ var _where = "/home/gitlab-runner/builds/BQJy2NwB/0/pagedjs/pagedjs";
+ var author = {
+ name: "Roman Dvornov",
+ email: "rdvornov@gmail.com",
+ url: "https://github.com/lahmatiy"
+ };
+ var bugs = {
+ url: "https://github.com/csstree/csstree/issues"
+ };
+ var dependencies = {
+ "mdn-data": "2.0.14",
+ "source-map": "^0.6.1"
+ };
+ var description = "A tool set for CSS: fast detailed parser (CSS → AST), walker (AST traversal), generator (AST → CSS) and lexer (validation and matching) based on specs and browser implementations";
+ var devDependencies = {
+ "@rollup/plugin-commonjs": "^11.0.2",
+ "@rollup/plugin-json": "^4.0.2",
+ "@rollup/plugin-node-resolve": "^7.1.1",
+ coveralls: "^3.0.9",
+ eslint: "^6.8.0",
+ "json-to-ast": "^2.1.0",
+ mocha: "^6.2.3",
+ nyc: "^14.1.1",
+ rollup: "^1.32.1",
+ "rollup-plugin-terser": "^5.3.0"
+ };
+ var engines = {
+ node: ">=8.0.0"
+ };
+ var files = [
+ "data",
+ "dist",
+ "lib"
+ ];
+ var homepage = "https://github.com/csstree/csstree#readme";
+ var jsdelivr = "dist/csstree.min.js";
+ var keywords = [
+ "css",
+ "ast",
+ "tokenizer",
+ "parser",
+ "walker",
+ "lexer",
+ "generator",
+ "utils",
+ "syntax",
+ "validation"
+ ];
+ var license = "MIT";
+ var main = "lib/index.js";
+ var name = "css-tree";
+ var repository = {
+ type: "git",
+ url: "git+https://github.com/csstree/csstree.git"
+ };
+ var scripts = {
+ build: "rollup --config",
+ coverage: "nyc npm test",
+ coveralls: "nyc report --reporter=text-lcov | coveralls",
+ hydrogen: "node --trace-hydrogen --trace-phase=Z --trace-deopt --code-comments --hydrogen-track-positions --redirect-code-traces --redirect-code-traces-to=code.asm --trace_hydrogen_file=code.cfg --print-opt-code bin/parse --stat -o /dev/null",
+ lint: "eslint data lib scripts test && node scripts/review-syntax-patch --lint && node scripts/update-docs --lint",
+ "lint-and-test": "npm run lint && npm test",
+ prepublishOnly: "npm run build",
+ "review:syntax-patch": "node scripts/review-syntax-patch",
+ test: "mocha --reporter progress",
+ travis: "nyc npm run lint-and-test && npm run coveralls",
+ "update:docs": "node scripts/update-docs"
+ };
+ var unpkg = "dist/csstree.min.js";
+ var version = "1.1.3";
+ var require$$4 = {
+ _args: _args,
+ _from: _from,
+ _id: _id,
+ _inBundle: _inBundle,
+ _integrity: _integrity,
+ _location: _location,
+ _phantomChildren: _phantomChildren,
+ _requested: _requested,
+ _requiredBy: _requiredBy,
+ _resolved: _resolved,
+ _spec: _spec,
+ _where: _where,
+ author: author,
+ bugs: bugs,
+ dependencies: dependencies,
+ description: description,
+ devDependencies: devDependencies,
+ engines: engines,
+ files: files,
+ homepage: homepage,
+ jsdelivr: jsdelivr,
+ keywords: keywords,
+ license: license,
+ main: main,
+ name: name,
+ repository: repository,
+ scripts: scripts,
+ unpkg: unpkg,
+ version: version
+ };
+
+ function merge() {
+ var dest = {};
+
+ for (var i = 0; i < arguments.length; i++) {
+ var src = arguments[i];
+ for (var key in src) {
+ dest[key] = src[key];
+ }
+ }
+
+ return dest;
+ }
+
+ syntax.exports = create$4.create(
+ merge(
+ lexer,
+ parser,
+ walker
+ )
+ );
+ syntax.exports.version = require$$4.version;
+
+ var syntaxExports = syntax.exports;
+
+ var lib = syntaxExports;
+
+ var csstree = /*@__PURE__*/getDefaultExportFromCjs(lib);
+
+ class Sheet {
+ constructor(url, hooks) {
+
+ if (hooks) {
+ this.hooks = hooks;
+ } else {
+ this.hooks = {};
+ this.hooks.onUrl = new Hook(this);
+ this.hooks.onAtPage = new Hook(this);
+ this.hooks.onAtMedia = new Hook(this);
+ this.hooks.onRule = new Hook(this);
+ this.hooks.onDeclaration = new Hook(this);
+ this.hooks.onSelector = new Hook(this);
+ this.hooks.onPseudoSelector = new Hook(this);
+
+ this.hooks.onContent = new Hook(this);
+ this.hooks.onImport = new Hook(this);
+
+ this.hooks.beforeTreeParse = new Hook(this);
+ this.hooks.beforeTreeWalk = new Hook(this);
+ this.hooks.afterTreeWalk = new Hook(this);
+ }
+
+ try {
+ this.url = new URL(url, window.location.href);
+ } catch (e) {
+ this.url = new URL(window.location.href);
+ }
+ }
+
+
+
+ // parse
+ async parse(text) {
+ this.text = text;
+
+ await this.hooks.beforeTreeParse.trigger(this.text, this);
+
+ // send to csstree
+ this.ast = csstree.parse(this._text);
+
+ await this.hooks.beforeTreeWalk.trigger(this.ast);
+
+ // Replace urls
+ this.replaceUrls(this.ast);
+
+ // Scope
+ this.id = UUID();
+ // this.addScope(this.ast, this.uuid);
+
+ // Replace IDs with data-id
+ this.replaceIds(this.ast);
+
+ this.imported = [];
+
+ // Trigger Hooks
+ this.urls(this.ast);
+ this.rules(this.ast);
+ this.atrules(this.ast);
+
+ await this.hooks.afterTreeWalk.trigger(this.ast, this);
+
+ // return ast
+ return this.ast;
+ }
+
+
+
+ insertRule(rule) {
+ let inserted = this.ast.children.appendData(rule);
+
+ this.declarations(rule);
+
+ return inserted;
+ }
+
+ urls(ast) {
+ csstree.walk(ast, {
+ visit: "Url",
+ enter: (node, item, list) => {
+ this.hooks.onUrl.trigger(node, item, list);
+ }
+ });
+ }
+
+ atrules(ast) {
+ csstree.walk(ast, {
+ visit: "Atrule",
+ enter: (node, item, list) => {
+ const basename = csstree.keyword(node.name).basename;
+
+ if (basename === "page") {
+ this.hooks.onAtPage.trigger(node, item, list);
+ this.declarations(node, item, list);
+ }
+
+ if (basename === "media") {
+ this.hooks.onAtMedia.trigger(node, item, list);
+ this.declarations(node, item, list);
+ }
+
+ if (basename === "import") {
+ this.hooks.onImport.trigger(node, item, list);
+ this.imports(node, item, list);
+ }
+ }
+ });
+ }
+
+
+ rules(ast) {
+ csstree.walk(ast, {
+ visit: "Rule",
+ enter: (ruleNode, ruleItem, rulelist) => {
+
+ this.hooks.onRule.trigger(ruleNode, ruleItem, rulelist);
+ this.declarations(ruleNode, ruleItem, rulelist);
+ this.onSelector(ruleNode, ruleItem, rulelist);
+
+ }
+ });
+ }
+
+ declarations(ruleNode, ruleItem, rulelist) {
+ csstree.walk(ruleNode, {
+ visit: "Declaration",
+ enter: (declarationNode, dItem, dList) => {
+
+ this.hooks.onDeclaration.trigger(declarationNode, dItem, dList, {ruleNode, ruleItem, rulelist});
+
+ if (declarationNode.property === "content") {
+ csstree.walk(declarationNode, {
+ visit: "Function",
+ enter: (funcNode, fItem, fList) => {
+ this.hooks.onContent.trigger(funcNode, fItem, fList, {declarationNode, dItem, dList}, {ruleNode, ruleItem, rulelist});
+ }
+ });
+ }
+
+ }
+ });
+ }
+
+ // add pseudo elements to parser
+ onSelector(ruleNode, ruleItem, rulelist) {
+ csstree.walk(ruleNode, {
+ visit: "Selector",
+ enter: (selectNode, selectItem, selectList) => {
+ this.hooks.onSelector.trigger(selectNode, selectItem, selectList, {ruleNode, ruleItem, rulelist});
+
+ if (selectNode.children.forEach(node => {if (node.type === "PseudoElementSelector") {
+ csstree.walk(node, {
+ visit: "PseudoElementSelector",
+ enter: (pseudoNode, pItem, pList) => {
+ this.hooks.onPseudoSelector.trigger(pseudoNode, pItem, pList, {selectNode, selectItem, selectList}, {ruleNode, ruleItem, rulelist});
+ }
+ });
+ }}));
+ }
+ });
+ }
+
+ replaceUrls(ast) {
+ csstree.walk(ast, {
+ visit: "Url",
+ enter: (node, item, list) => {
+ let content = node.value.value;
+ if ((node.value.type === "Raw" && content.startsWith("data:")) || (node.value.type === "String" && (content.startsWith("\"data:") || content.startsWith("'data:")))) ; else {
+ let href = content.replace(/["']/g, "");
+ let url = new URL(href, this.url);
+ node.value.value = url.toString();
+ }
+ }
+ });
+ }
+
+ addScope(ast, id) {
+ // Get all selector lists
+ // add an id
+ csstree.walk(ast, {
+ visit: "Selector",
+ enter: (node, item, list) => {
+ let children = node.children;
+ children.prepend(children.createItem({
+ type: "WhiteSpace",
+ value: " "
+ }));
+ children.prepend(children.createItem({
+ type: "IdSelector",
+ name: id,
+ loc: null,
+ children: null
+ }));
+ }
+ });
+ }
+
+ getNamedPageSelectors(ast) {
+ let namedPageSelectors = {};
+ csstree.walk(ast, {
+ visit: "Rule",
+ enter: (node, item, list) => {
+ csstree.walk(node, {
+ visit: "Declaration",
+ enter: (declaration, dItem, dList) => {
+ if (declaration.property === "page") {
+ let value = declaration.value.children.first();
+ let name = value.name;
+ let selector = csstree.generate(node.prelude);
+ namedPageSelectors[name] = {
+ name: name,
+ selector: selector
+ };
+
+ // dList.remove(dItem);
+
+ // Add in page break
+ declaration.property = "break-before";
+ value.type = "Identifier";
+ value.name = "always";
+
+ }
+ }
+ });
+ }
+ });
+ return namedPageSelectors;
+ }
+
+ replaceIds(ast) {
+ csstree.walk(ast, {
+ visit: "Rule",
+ enter: (node, item, list) => {
+
+ csstree.walk(node, {
+ visit: "IdSelector",
+ enter: (idNode, idItem, idList) => {
+ let name = idNode.name;
+ idNode.flags = null;
+ idNode.matcher = "=";
+ idNode.name = {type: "Identifier", loc: null, name: "data-id"};
+ idNode.type = "AttributeSelector";
+ idNode.value = {type: "String", loc: null, value: `"${name}"`};
+ }
+ });
+ }
+ });
+ }
+
+ imports(node, item, list) {
+ // console.log("import", node, item, list);
+ let queries = [];
+ csstree.walk(node, {
+ visit: "MediaQuery",
+ enter: (mqNode, mqItem, mqList) => {
+ csstree.walk(mqNode, {
+ visit: "Identifier",
+ enter: (identNode, identItem, identList) => {
+ queries.push(identNode.name);
+ }
+ });
+ }
+ });
+
+ // Just basic media query support for now
+ let shouldNotApply = queries.some((query, index) => {
+ let q = query;
+ if (q === "not") {
+ q = queries[index + 1];
+ return !(q === "screen" || q === "speech");
+ } else {
+ return (q === "screen" || q === "speech");
+ }
+ });
+
+ if (shouldNotApply) {
+ return;
+ }
+
+ csstree.walk(node, {
+ visit: "String",
+ enter: (urlNode, urlItem, urlList) => {
+ let href = urlNode.value.replace(/["']/g, "");
+ let url = new URL(href, this.url);
+ let value = url.toString();
+
+ this.imported.push(value);
+
+ // Remove the original
+ list.remove(item);
+ }
+ });
+ }
+
+ set text(t) {
+ this._text = t;
+ }
+
+ get text() {
+ return this._text;
+ }
+
+ // generate string
+ toString(ast) {
+ return csstree.generate(ast || this.ast);
+ }
+ }
+
+ var baseStyles = `
+:root {
+ --pagedjs-width: 8.5in;
+ --pagedjs-height: 11in;
+ --pagedjs-width-right: 8.5in;
+ --pagedjs-height-right: 11in;
+ --pagedjs-width-left: 8.5in;
+ --pagedjs-height-left: 11in;
+ --pagedjs-pagebox-width: 8.5in;
+ --pagedjs-pagebox-height: 11in;
+ --pagedjs-footnotes-height: 0mm;
+ --pagedjs-margin-top: 1in;
+ --pagedjs-margin-right: 1in;
+ --pagedjs-margin-bottom: 1in;
+ --pagedjs-margin-left: 1in;
+ --pagedjs-padding-top: 0mm;
+ --pagedjs-padding-right: 0mm;
+ --pagedjs-padding-bottom: 0mm;
+ --pagedjs-padding-left: 0mm;
+ --pagedjs-border-top: 0mm;
+ --pagedjs-border-right: 0mm;
+ --pagedjs-border-bottom: 0mm;
+ --pagedjs-border-left: 0mm;
+ --pagedjs-bleed-top: 0mm;
+ --pagedjs-bleed-right: 0mm;
+ --pagedjs-bleed-bottom: 0mm;
+ --pagedjs-bleed-left: 0mm;
+ --pagedjs-bleed-right-top: 0mm;
+ --pagedjs-bleed-right-right: 0mm;
+ --pagedjs-bleed-right-bottom: 0mm;
+ --pagedjs-bleed-right-left: 0mm;
+ --pagedjs-bleed-left-top: 0mm;
+ --pagedjs-bleed-left-right: 0mm;
+ --pagedjs-bleed-left-bottom: 0mm;
+ --pagedjs-bleed-left-left: 0mm;
+ --pagedjs-crop-color: black;
+ --pagedjs-crop-shadow: white;
+ --pagedjs-crop-offset: 2mm;
+ --pagedjs-crop-stroke: 1px;
+ --pagedjs-cross-size: 5mm;
+ --pagedjs-mark-cross-display: none;
+ --pagedjs-mark-crop-display: none;
+ --pagedjs-page-count: 0;
+ --pagedjs-page-counter-increment: 1;
+ --pagedjs-footnotes-count: 0;
+ --pagedjs-column-gap-offset: 1000px;
+}
+
+@page {
+ size: letter;
+ margin: 0;
+}
+
+.pagedjs_sheet {
+ box-sizing: border-box;
+ width: var(--pagedjs-width);
+ height: var(--pagedjs-height);
+ overflow: hidden;
+ position: relative;
+ display: grid;
+ grid-template-columns: [bleed-left] var(--pagedjs-bleed-left) [sheet-center] calc(var(--pagedjs-width) - var(--pagedjs-bleed-left) - var(--pagedjs-bleed-right)) [bleed-right] var(--pagedjs-bleed-right);
+ grid-template-rows: [bleed-top] var(--pagedjs-bleed-top) [sheet-middle] calc(var(--pagedjs-height) - var(--pagedjs-bleed-top) - var(--pagedjs-bleed-bottom)) [bleed-bottom] var(--pagedjs-bleed-bottom);
+}
+
+.pagedjs_right_page .pagedjs_sheet {
+ width: var(--pagedjs-width-right);
+ height: var(--pagedjs-height-right);
+ grid-template-columns: [bleed-left] var(--pagedjs-bleed-right-left) [sheet-center] calc(var(--pagedjs-width) - var(--pagedjs-bleed-right-left) - var(--pagedjs-bleed-right-right)) [bleed-right] var(--pagedjs-bleed-right-right);
+ grid-template-rows: [bleed-top] var(--pagedjs-bleed-right-top) [sheet-middle] calc(var(--pagedjs-height) - var(--pagedjs-bleed-right-top) - var(--pagedjs-bleed-right-bottom)) [bleed-bottom] var(--pagedjs-bleed-right-bottom);
+}
+
+.pagedjs_left_page .pagedjs_sheet {
+ width: var(--pagedjs-width-left);
+ height: var(--pagedjs-height-left);
+ grid-template-columns: [bleed-left] var(--pagedjs-bleed-left-left) [sheet-center] calc(var(--pagedjs-width) - var(--pagedjs-bleed-left-left) - var(--pagedjs-bleed-left-right)) [bleed-right] var(--pagedjs-bleed-left-right);
+ grid-template-rows: [bleed-top] var(--pagedjs-bleed-left-top) [sheet-middle] calc(var(--pagedjs-height) - var(--pagedjs-bleed-left-top) - var(--pagedjs-bleed-left-bottom)) [bleed-bottom] var(--pagedjs-bleed-left-bottom);
+}
+
+.pagedjs_bleed {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-wrap: nowrap;
+ overflow: hidden;
+}
+
+.pagedjs_bleed-top {
+ grid-column: bleed-left / -1;
+ grid-row: bleed-top;
+ flex-direction: row;
+}
+
+.pagedjs_bleed-bottom {
+ grid-column: bleed-left / -1;
+ grid-row: bleed-bottom;
+ flex-direction: row;
+}
+
+.pagedjs_bleed-left {
+ grid-column: bleed-left;
+ grid-row: bleed-top / -1;
+ flex-direction: column;
+}
+
+.pagedjs_bleed-right {
+ grid-column: bleed-right;
+ grid-row: bleed-top / -1;
+ flex-direction: column;
+}
+
+.pagedjs_marks-crop {
+ display: var(--pagedjs-mark-crop-display);
+ flex-grow: 0;
+ flex-shrink: 0;
+ z-index: 9999999999;
+}
+
+.pagedjs_bleed-top .pagedjs_marks-crop:nth-child(1),
+.pagedjs_bleed-bottom .pagedjs_marks-crop:nth-child(1) {
+ width: calc(var(--pagedjs-bleed-left) - var(--pagedjs-crop-stroke));
+ border-right: var(--pagedjs-crop-stroke) solid var(--pagedjs-crop-color);
+ box-shadow: 1px 0px 0px 0px var(--pagedjs-crop-shadow);
+}
+
+.pagedjs_right_page .pagedjs_bleed-top .pagedjs_marks-crop:nth-child(1),
+.pagedjs_right_page .pagedjs_bleed-bottom .pagedjs_marks-crop:nth-child(1) {
+ width: calc(var(--pagedjs-bleed-right-left) - var(--pagedjs-crop-stroke));
+}
+
+.pagedjs_left_page .pagedjs_bleed-top .pagedjs_marks-crop:nth-child(1),
+.pagedjs_left_page .pagedjs_bleed-bottom .pagedjs_marks-crop:nth-child(1) {
+ width: calc(var(--pagedjs-bleed-left-left) - var(--pagedjs-crop-stroke));
+}
+
+.pagedjs_bleed-top .pagedjs_marks-crop:nth-child(3),
+.pagedjs_bleed-bottom .pagedjs_marks-crop:nth-child(3) {
+ width: calc(var(--pagedjs-bleed-right) - var(--pagedjs-crop-stroke));
+ border-left: var(--pagedjs-crop-stroke) solid var(--pagedjs-crop-color);
+ box-shadow: -1px 0px 0px 0px var(--pagedjs-crop-shadow);
+}
+
+.pagedjs_right_page .pagedjs_bleed-top .pagedjs_marks-crop:nth-child(3),
+.pagedjs_right_page .pagedjs_bleed-bottom .pagedjs_marks-crop:nth-child(3) {
+ width: calc(var(--pagedjs-bleed-right-right) - var(--pagedjs-crop-stroke));
+}
+
+.pagedjs_left_page .pagedjs_bleed-top .pagedjs_marks-crop:nth-child(3),
+.pagedjs_left_page .pagedjs_bleed-bottom .pagedjs_marks-crop:nth-child(3) {
+ width: calc(var(--pagedjs-bleed-left-right) - var(--pagedjs-crop-stroke));
+}
+
+.pagedjs_bleed-top .pagedjs_marks-crop {
+ align-self: flex-start;
+ height: calc(var(--pagedjs-bleed-top) - var(--pagedjs-crop-offset));
+}
+
+.pagedjs_right_page .pagedjs_bleed-top .pagedjs_marks-crop {
+ height: calc(var(--pagedjs-bleed-right-top) - var(--pagedjs-crop-offset));
+}
+
+.pagedjs_left_page .pagedjs_bleed-top .pagedjs_marks-crop {
+ height: calc(var(--pagedjs-bleed-left-top) - var(--pagedjs-crop-offset));
+}
+
+.pagedjs_bleed-bottom .pagedjs_marks-crop {
+ align-self: flex-end;
+ height: calc(var(--pagedjs-bleed-bottom) - var(--pagedjs-crop-offset));
+}
+
+.pagedjs_right_page .pagedjs_bleed-bottom .pagedjs_marks-crop {
+ height: calc(var(--pagedjs-bleed-right-bottom) - var(--pagedjs-crop-offset));
+}
+
+.pagedjs_left_page .pagedjs_bleed-bottom .pagedjs_marks-crop {
+ height: calc(var(--pagedjs-bleed-left-bottom) - var(--pagedjs-crop-offset));
+}
+
+.pagedjs_bleed-left .pagedjs_marks-crop:nth-child(1),
+.pagedjs_bleed-right .pagedjs_marks-crop:nth-child(1) {
+ height: calc(var(--pagedjs-bleed-top) - var(--pagedjs-crop-stroke));
+ border-bottom: var(--pagedjs-crop-stroke) solid var(--pagedjs-crop-color);
+ box-shadow: 0px 1px 0px 0px var(--pagedjs-crop-shadow);
+}
+
+.pagedjs_right_page .pagedjs_bleed-left .pagedjs_marks-crop:nth-child(1),
+.pagedjs_right_page .pagedjs_bleed-right .pagedjs_marks-crop:nth-child(1) {
+ height: calc(var(--pagedjs-bleed-right-top) - var(--pagedjs-crop-stroke));
+}
+
+.pagedjs_left_page .pagedjs_bleed-left .pagedjs_marks-crop:nth-child(1),
+.pagedjs_left_page .pagedjs_bleed-right .pagedjs_marks-crop:nth-child(1) {
+ height: calc(var(--pagedjs-bleed-left-top) - var(--pagedjs-crop-stroke));
+}
+
+.pagedjs_bleed-left .pagedjs_marks-crop:nth-child(3),
+.pagedjs_bleed-right .pagedjs_marks-crop:nth-child(3) {
+ height: calc(var(--pagedjs-bleed-bottom) - var(--pagedjs-crop-stroke));
+ border-top: var(--pagedjs-crop-stroke) solid var(--pagedjs-crop-color);
+ box-shadow: 0px -1px 0px 0px var(--pagedjs-crop-shadow);
+}
+
+.pagedjs_right_page .pagedjs_bleed-left .pagedjs_marks-crop:nth-child(3),
+.pagedjs_right_page .pagedjs_bleed-right .pagedjs_marks-crop:nth-child(3) {
+ height: calc(var(--pagedjs-bleed-right-bottom) - var(--pagedjs-crop-stroke));
+}
+
+.pagedjs_left_page .pagedjs_bleed-left .pagedjs_marks-crop:nth-child(3),
+.pagedjs_left_page .pagedjs_bleed-right .pagedjs_marks-crop:nth-child(3) {
+ height: calc(var(--pagedjs-bleed-left-bottom) - var(--pagedjs-crop-stroke));
+}
+
+.pagedjs_bleed-left .pagedjs_marks-crop {
+ width: calc(var(--pagedjs-bleed-left) - var(--pagedjs-crop-offset));
+ align-self: flex-start;
+}
+
+.pagedjs_right_page .pagedjs_bleed-left .pagedjs_marks-crop {
+ width: calc(var(--pagedjs-bleed-right-left) - var(--pagedjs-crop-offset));
+}
+
+.pagedjs_left_page .pagedjs_bleed-left .pagedjs_marks-crop {
+ width: calc(var(--pagedjs-bleed-left-left) - var(--pagedjs-crop-offset));
+}
+
+.pagedjs_bleed-right .pagedjs_marks-crop {
+ width: calc(var(--pagedjs-bleed-right) - var(--pagedjs-crop-offset));
+ align-self: flex-end;
+}
+
+.pagedjs_right_page .pagedjs_bleed-right .pagedjs_marks-crop {
+ width: calc(var(--pagedjs-bleed-right-right) - var(--pagedjs-crop-offset));
+}
+
+.pagedjs_left_page .pagedjs_bleed-right .pagedjs_marks-crop {
+ width: calc(var(--pagedjs-bleed-left-right) - var(--pagedjs-crop-offset));
+}
+
+.pagedjs_marks-middle {
+ display: flex;
+ flex-grow: 1;
+ flex-shrink: 0;
+ align-items: center;
+ justify-content: center;
+}
+
+.pagedjs_marks-cross {
+ display: var(--pagedjs-mark-cross-display);
+ background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSIzMi41MzdweCIgaGVpZ2h0PSIzMi41MzdweCIgdmlld0JveD0iMC4xMDQgMC4xMDQgMzIuNTM3IDMyLjUzNyIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwLjEwNCAwLjEwNCAzMi41MzcgMzIuNTM3IiB4bWw6c3BhY2U9InByZXNlcnZlIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMy4zODkzIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIGQ9Ik0yOS45MzEsMTYuMzczYzAsNy40ODktNi4wNjgsMTMuNTYtMTMuNTU4LDEzLjU2Yy03LjQ4MywwLTEzLjU1Ny02LjA3Mi0xMy41NTctMTMuNTZjMC03LjQ4Niw2LjA3NC0xMy41NTQsMTMuNTU3LTEzLjU1NEMyMy44NjIsMi44MTksMjkuOTMxLDguODg3LDI5LjkzMSwxNi4zNzN6Ii8+PGxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjMuMzg5MyIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiB4MT0iMC4xMDQiIHkxPSIxNi4zNzMiIHgyPSIzMi42NDIiIHkyPSIxNi4zNzMiLz48bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMy4zODkzIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHgxPSIxNi4zNzMiIHkxPSIwLjEwNCIgeDI9IjE2LjM3MyIgeTI9IjMyLjY0MiIvPjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIzLjM4OTMiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgZD0iTTI0LjUwOCwxNi4zNzNjMCw0LjQ5Ni0zLjYzOCw4LjEzNS04LjEzNSw4LjEzNWMtNC40OTEsMC04LjEzNS0zLjYzOC04LjEzNS04LjEzNWMwLTQuNDg5LDMuNjQ0LTguMTM1LDguMTM1LTguMTM1QzIwLjg2OSw4LjIzOSwyNC41MDgsMTEuODg0LDI0LjUwOCwxNi4zNzN6Ii8+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuNjc3OCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBkPSJNMjkuOTMxLDE2LjM3M2MwLDcuNDg5LTYuMDY4LDEzLjU2LTEzLjU1OCwxMy41NmMtNy40ODMsMC0xMy41NTctNi4wNzItMTMuNTU3LTEzLjU2YzAtNy40ODYsNi4wNzQtMTMuNTU0LDEzLjU1Ny0xMy41NTRDMjMuODYyLDIuODE5LDI5LjkzMSw4Ljg4NywyOS45MzEsMTYuMzczeiIvPjxsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwLjY3NzgiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgeDE9IjAuMTA0IiB5MT0iMTYuMzczIiB4Mj0iMzIuNjQyIiB5Mj0iMTYuMzczIi8+PGxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAuNjc3OCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiB4MT0iMTYuMzczIiB5MT0iMC4xMDQiIHgyPSIxNi4zNzMiIHkyPSIzMi42NDIiLz48cGF0aCBkPSJNMjQuNTA4LDE2LjM3M2MwLDQuNDk2LTMuNjM4LDguMTM1LTguMTM1LDguMTM1Yy00LjQ5MSwwLTguMTM1LTMuNjM4LTguMTM1LTguMTM1YzAtNC40ODksMy42NDQtOC4xMzUsOC4xMzUtOC4xMzVDMjAuODY5LDguMjM5LDI0LjUwOCwxMS44ODQsMjQuNTA4LDE2LjM3MyIvPjxsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIwLjY3NzgiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgeDE9IjguMjM5IiB5MT0iMTYuMzczIiB4Mj0iMjQuNTA4IiB5Mj0iMTYuMzczIi8+PGxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjAuNjc3OCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiB4MT0iMTYuMzczIiB5MT0iOC4yMzkiIHgyPSIxNi4zNzMiIHkyPSIyNC41MDgiLz48L3N2Zz4=);
+ background-repeat: no-repeat;
+ background-position: 50% 50%;
+ background-size: var(--pagedjs-cross-size);
+
+ z-index: 2147483647;
+ width: var(--pagedjs-cross-size);
+ height: var(--pagedjs-cross-size);
+}
+
+.pagedjs_pagebox {
+ box-sizing: border-box;
+ width: var(--pagedjs-pagebox-width);
+ height: var(--pagedjs-pagebox-height);
+ position: relative;
+ display: grid;
+ grid-template-columns: [left] var(--pagedjs-margin-left) [center] calc(var(--pagedjs-pagebox-width) - var(--pagedjs-margin-left) - var(--pagedjs-margin-right)) [right] var(--pagedjs-margin-right);
+ grid-template-rows: [header] var(--pagedjs-margin-top) [page] calc(var(--pagedjs-pagebox-height) - var(--pagedjs-margin-top) - var(--pagedjs-margin-bottom)) [footer] var(--pagedjs-margin-bottom);
+ grid-column: sheet-center;
+ grid-row: sheet-middle;
+}
+
+.pagedjs_pagebox * {
+ box-sizing: border-box;
+}
+
+.pagedjs_margin-top {
+ width: calc(var(--pagedjs-pagebox-width) - var(--pagedjs-margin-left) - var(--pagedjs-margin-right));
+ height: var(--pagedjs-margin-top);
+ grid-column: center;
+ grid-row: header;
+ flex-wrap: nowrap;
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ grid-template-rows: 100%;
+}
+
+.pagedjs_margin-top-left-corner-holder {
+ width: var(--pagedjs-margin-left);
+ height: var(--pagedjs-margin-top);
+ display: flex;
+ grid-column: left;
+ grid-row: header;
+}
+
+.pagedjs_margin-top-right-corner-holder {
+ width: var(--pagedjs-margin-right);
+ height: var(--pagedjs-margin-top);
+ display: flex;
+ grid-column: right;
+ grid-row: header;
+}
+
+.pagedjs_margin-top-left-corner {
+ width: var(--pagedjs-margin-left);
+}
+
+.pagedjs_margin-top-right-corner {
+ width: var(--pagedjs-margin-right);
+}
+
+.pagedjs_margin-right {
+ height: calc(var(--pagedjs-pagebox-height) - var(--pagedjs-margin-top) - var(--pagedjs-margin-bottom));
+ width: var(--pagedjs-margin-right);
+ right: 0;
+ grid-column: right;
+ grid-row: page;
+ display: grid;
+ grid-template-rows: repeat(3, 33.3333%);
+ grid-template-columns: 100%;
+}
+
+.pagedjs_margin-bottom {
+ width: calc(var(--pagedjs-pagebox-width) - var(--pagedjs-margin-left) - var(--pagedjs-margin-right));
+ height: var(--pagedjs-margin-bottom);
+ grid-column: center;
+ grid-row: footer;
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ grid-template-rows: 100%;
+}
+
+.pagedjs_margin-bottom-left-corner-holder {
+ width: var(--pagedjs-margin-left);
+ height: var(--pagedjs-margin-bottom);
+ display: flex;
+ grid-column: left;
+ grid-row: footer;
+}
+
+.pagedjs_margin-bottom-right-corner-holder {
+ width: var(--pagedjs-margin-right);
+ height: var(--pagedjs-margin-bottom);
+ display: flex;
+ grid-column: right;
+ grid-row: footer;
+}
+
+.pagedjs_margin-bottom-left-corner {
+ width: var(--pagedjs-margin-left);
+}
+
+.pagedjs_margin-bottom-right-corner {
+ width: var(--pagedjs-margin-right);
+}
+
+
+
+.pagedjs_margin-left {
+ height: calc(var(--pagedjs-pagebox-height) - var(--pagedjs-margin-top) - var(--pagedjs-margin-bottom));
+ width: var(--pagedjs-margin-left);
+ grid-column: left;
+ grid-row: page;
+ display: grid;
+ grid-template-rows: repeat(3, 33.33333%);
+ grid-template-columns: 100%;
+}
+
+.pagedjs_pages .pagedjs_pagebox .pagedjs_margin:not(.hasContent) {
+ visibility: hidden;
+}
+
+.pagedjs_pagebox > .pagedjs_area {
+ grid-column: center;
+ grid-row: page;
+ width: 100%;
+ height: 100%;
+ padding: var(--pagedjs-padding-top) var(--pagedjs-padding-right) var(--pagedjs-padding-bottom) var(--pagedjs-padding-left);
+ border-top: var(--pagedjs-border-top);
+ border-right: var(--pagedjs-border-right);
+ border-bottom: var(--pagedjs-border-bottom);
+ border-left: var(--pagedjs-border-left);
+}
+
+.pagedjs_pagebox > .pagedjs_area > .pagedjs_page_content {
+ width: 100%;
+ height: calc(100% - var(--pagedjs-footnotes-height));
+ position: relative;
+ column-fill: auto;
+}
+
+.pagedjs_pagebox > .pagedjs_area > .pagedjs_page_content > div {
+ height: inherit;
+}
+
+.pagedjs_pagebox > .pagedjs_area > .pagedjs_footnote_area {
+ position: relative;
+ overflow: hidden;
+ height: var(--pagedjs-footnotes-height);
+ display: flex;
+ justify-content: flex-end;
+ flex-flow: column;
+}
+
+.pagedjs_pagebox > .pagedjs_area > .pagedjs_footnote_area > .pagedjs_footnote_content {
+ overflow: hidden;
+}
+
+.pagedjs_pagebox > .pagedjs_area > .pagedjs_footnote_area > .pagedjs_footnote_inner_content {
+ overflow: hidden;
+}
+
+.pagedjs_area [data-footnote-call] {
+ all: unset;
+ counter-increment: footnote;
+}
+
+.pagedjs_area [data-split-from] {
+ counter-increment: unset;
+ counter-reset: unset;
+}
+
+[data-footnote-call]::after {
+ vertical-align: super;
+ font-size: 65%;
+ line-height: normal;
+ content: counter(footnote);
+}
+
+@supports ( font-variant-position: super ) {
+ [data-footnote-call]::after {
+ vertical-align: baseline;
+ font-size: 100%;
+ line-height: inherit;
+ font-variant-position: super;
+ }
+}
+
+.pagedjs_footnote_empty {
+ display: none;
+}
+
+.pagedjs_area [data-split-from] {
+ counter-increment: unset;
+ counter-reset: unset;
+}
+
+[data-footnote-marker] {
+ text-indent: 0;
+ display: list-item;
+ list-style-position: inside;
+}
+
+[data-footnote-marker][data-split-from] {
+ list-style: none;
+}
+
+[data-footnote-marker]:not([data-split-from]) {
+ counter-increment: footnote-marker;
+}
+
+[data-footnote-marker]::marker {
+ content: counter(footnote-marker) ". ";
+}
+
+[data-footnote-marker][data-split-from]::marker {
+ content: unset;
+}
+
+.pagedjs_area .pagedjs_footnote_inner_content [data-note-display="inline"] {
+ display: inline;
+}
+
+.pagedjs_page {
+ counter-increment: page var(--pagedjs-page-counter-increment);
+ width: var(--pagedjs-width);
+ height: var(--pagedjs-height);
+}
+
+.pagedjs_page.pagedjs_right_page {
+ width: var(--pagedjs-width-right);
+ height: var(--pagedjs-height-right);
+}
+
+.pagedjs_page.pagedjs_left_page {
+ width: var(--pagedjs-width-left);
+ height: var(--pagedjs-height-left);
+}
+
+.pagedjs_pages {
+ counter-reset: pages var(--pagedjs-page-count) footnote var(--pagedjs-footnotes-count) footnote-marker var(--pagedjs-footnotes-count);
+}
+
+.pagedjs_pagebox .pagedjs_margin-top-left-corner,
+.pagedjs_pagebox .pagedjs_margin-top-right-corner,
+.pagedjs_pagebox .pagedjs_margin-bottom-left-corner,
+.pagedjs_pagebox .pagedjs_margin-bottom-right-corner,
+.pagedjs_pagebox .pagedjs_margin-top-left,
+.pagedjs_pagebox .pagedjs_margin-top-right,
+.pagedjs_pagebox .pagedjs_margin-bottom-left,
+.pagedjs_pagebox .pagedjs_margin-bottom-right,
+.pagedjs_pagebox .pagedjs_margin-top-center,
+.pagedjs_pagebox .pagedjs_margin-bottom-center,
+.pagedjs_pagebox .pagedjs_margin-top-center,
+.pagedjs_pagebox .pagedjs_margin-bottom-center,
+.pagedjs_margin-right-middle,
+.pagedjs_margin-left-middle {
+ display: flex;
+ align-items: center;
+}
+
+.pagedjs_margin-right-top,
+.pagedjs_margin-left-top {
+ display: flex;
+ align-items: flex-top;
+}
+
+
+.pagedjs_margin-right-bottom,
+.pagedjs_margin-left-bottom {
+ display: flex;
+ align-items: flex-end;
+}
+
+
+
+/*
+.pagedjs_pagebox .pagedjs_margin-top-center,
+.pagedjs_pagebox .pagedjs_margin-bottom-center {
+ height: 100%;
+ display: none;
+ align-items: center;
+ flex: 1 0 33%;
+ margin: 0 auto;
+}
+
+.pagedjs_pagebox .pagedjs_margin-top-left-corner,
+.pagedjs_pagebox .pagedjs_margin-top-right-corner,
+.pagedjs_pagebox .pagedjs_margin-bottom-right-corner,
+.pagedjs_pagebox .pagedjs_margin-bottom-left-corner {
+ display: none;
+ align-items: center;
+}
+
+.pagedjs_pagebox .pagedjs_margin-left-top,
+.pagedjs_pagebox .pagedjs_margin-right-top {
+ display: none;
+ align-items: flex-start;
+}
+
+.pagedjs_pagebox .pagedjs_margin-right-middle,
+.pagedjs_pagebox .pagedjs_margin-left-middle {
+ display: none;
+ align-items: center;
+}
+
+.pagedjs_pagebox .pagedjs_margin-left-bottom,
+.pagedjs_pagebox .pagedjs_margin-right-bottom {
+ display: none;
+ align-items: flex-end;
+}
+*/
+
+.pagedjs_pagebox .pagedjs_margin-top-left,
+.pagedjs_pagebox .pagedjs_margin-top-right-corner,
+.pagedjs_pagebox .pagedjs_margin-bottom-left,
+.pagedjs_pagebox .pagedjs_margin-bottom-right-corner { text-align: left; }
+
+.pagedjs_pagebox .pagedjs_margin-top-left-corner,
+.pagedjs_pagebox .pagedjs_margin-top-right,
+.pagedjs_pagebox .pagedjs_margin-bottom-left-corner,
+.pagedjs_pagebox .pagedjs_margin-bottom-right { text-align: right; }
+
+.pagedjs_pagebox .pagedjs_margin-top-center,
+.pagedjs_pagebox .pagedjs_margin-bottom-center,
+.pagedjs_pagebox .pagedjs_margin-left-top,
+.pagedjs_pagebox .pagedjs_margin-left-middle,
+.pagedjs_pagebox .pagedjs_margin-left-bottom,
+.pagedjs_pagebox .pagedjs_margin-right-top,
+.pagedjs_pagebox .pagedjs_margin-right-middle,
+.pagedjs_pagebox .pagedjs_margin-right-bottom { text-align: center; }
+
+.pagedjs_pages .pagedjs_margin .pagedjs_margin-content {
+ width: 100%;
+}
+
+.pagedjs_pages .pagedjs_margin-left .pagedjs_margin-content::after,
+.pagedjs_pages .pagedjs_margin-top .pagedjs_margin-content::after,
+.pagedjs_pages .pagedjs_margin-right .pagedjs_margin-content::after,
+.pagedjs_pages .pagedjs_margin-bottom .pagedjs_margin-content::after {
+ display: block;
+}
+
+.pagedjs_pages > .pagedjs_page > .pagedjs_sheet > .pagedjs_pagebox > .pagedjs_area > div [data-split-to] {
+ margin-bottom: unset;
+ padding-bottom: unset;
+}
+
+.pagedjs_pages > .pagedjs_page > .pagedjs_sheet > .pagedjs_pagebox > .pagedjs_area > div [data-split-from] {
+ text-indent: unset;
+ margin-top: unset;
+ padding-top: unset;
+ initial-letter: unset;
+}
+
+.pagedjs_pages > .pagedjs_page > .pagedjs_sheet > .pagedjs_pagebox > .pagedjs_area > div [data-split-from] > *::first-letter,
+.pagedjs_pages > .pagedjs_page > .pagedjs_sheet > .pagedjs_pagebox > .pagedjs_area > div [data-split-from]::first-letter {
+ color: unset;
+ font-size: unset;
+ font-weight: unset;
+ font-family: unset;
+ color: unset;
+ line-height: unset;
+ float: unset;
+ padding: unset;
+ margin: unset;
+}
+
+.pagedjs_pages > .pagedjs_page > .pagedjs_sheet > .pagedjs_pagebox > .pagedjs_area > div [data-split-to]:not([data-footnote-call]):after,
+.pagedjs_pages > .pagedjs_page > .pagedjs_sheet > .pagedjs_pagebox > .pagedjs_area > div [data-split-to]:not([data-footnote-call])::after {
+ content: unset;
+}
+
+.pagedjs_pages > .pagedjs_page > .pagedjs_sheet > .pagedjs_pagebox > .pagedjs_area > div [data-split-from]:not([data-footnote-call]):before,
+.pagedjs_pages > .pagedjs_page > .pagedjs_sheet > .pagedjs_pagebox > .pagedjs_area > div [data-split-from]:not([data-footnote-call])::before {
+ content: unset;
+}
+
+.pagedjs_pages > .pagedjs_page > .pagedjs_sheet > .pagedjs_pagebox > .pagedjs_area > div li[data-split-from]:first-of-type {
+ list-style: none;
+}
+
+/*
+[data-page]:not([data-split-from]),
+[data-break-before="page"]:not([data-split-from]),
+[data-break-before="always"]:not([data-split-from]),
+[data-break-before="left"]:not([data-split-from]),
+[data-break-before="right"]:not([data-split-from]),
+[data-break-before="recto"]:not([data-split-from]),
+[data-break-before="verso"]:not([data-split-from])
+{
+ break-before: column;
+}
+
+[data-page]:not([data-split-to]),
+[data-break-after="page"]:not([data-split-to]),
+[data-break-after="always"]:not([data-split-to]),
+[data-break-after="left"]:not([data-split-to]),
+[data-break-after="right"]:not([data-split-to]),
+[data-break-after="recto"]:not([data-split-to]),
+[data-break-after="verso"]:not([data-split-to])
+{
+ break-after: column;
+}
+*/
+
+.pagedjs_clear-after::after {
+ content: none !important;
+}
+
+[data-align-last-split-element='justify'] {
+ text-align-last: justify;
+}
+
+
+@media print {
+ html {
+ width: 100%;
+ height: 100%;
+ -webkit-print-color-adjust: exact;
+ print-color-adjust: exact;
+ }
+ body {
+ margin: 0;
+ padding: 0;
+ width: 100% !important;
+ height: 100% !important;
+ min-width: 100%;
+ max-width: 100%;
+ min-height: 100%;
+ max-height: 100%;
+ }
+ .pagedjs_pages {
+ width: auto;
+ display: block !important;
+ transform: none !important;
+ height: 100% !important;
+ min-height: 100%;
+ max-height: 100%;
+ overflow: visible;
+ }
+ .pagedjs_page {
+ margin: 0;
+ padding: 0;
+ max-height: 100%;
+ min-height: 100%;
+ height: 100% !important;
+ page-break-after: always;
+ break-after: page;
+ }
+ .pagedjs_sheet {
+ margin: 0;
+ padding: 0;
+ max-height: 100%;
+ min-height: 100%;
+ height: 100% !important;
+ }
+}
+`;
+
+ async function request(url, options={}) {
+ return new Promise(function(resolve, reject) {
+ let request = new XMLHttpRequest();
+
+ request.open(options.method || "get", url, true);
+
+ for (let i in options.headers) {
+ request.setRequestHeader(i, options.headers[i]);
+ }
+
+ request.withCredentials = options.credentials === "include";
+
+ request.onload = () => {
+ // Chrome returns a status code of 0 for local files
+ const status = request.status === 0 && url.startsWith("file://") ? 200 : request.status;
+ resolve(new Response(request.responseText, {status}));
+ };
+
+ request.onerror = reject;
+
+ request.send(options.body || null);
+ });
+ }
+
+ class Polisher {
+ constructor(setup) {
+ this.sheets = [];
+ this.inserted = [];
+
+ this.hooks = {};
+ this.hooks.onUrl = new Hook(this);
+ this.hooks.onAtPage = new Hook(this);
+ this.hooks.onAtMedia = new Hook(this);
+ this.hooks.onRule = new Hook(this);
+ this.hooks.onDeclaration = new Hook(this);
+ this.hooks.onContent = new Hook(this);
+ this.hooks.onSelector = new Hook(this);
+ this.hooks.onPseudoSelector = new Hook(this);
+
+ this.hooks.onImport = new Hook(this);
+
+ this.hooks.beforeTreeParse = new Hook(this);
+ this.hooks.beforeTreeWalk = new Hook(this);
+ this.hooks.afterTreeWalk = new Hook(this);
+
+ if (setup !== false) {
+ this.setup();
+ }
+ }
+
+ setup() {
+ this.base = this.insert(baseStyles);
+ this.styleEl = document.createElement("style");
+ document.head.appendChild(this.styleEl);
+ this.styleSheet = this.styleEl.sheet;
+ return this.styleSheet;
+ }
+
+ async add() {
+ let fetched = [];
+ let urls = [];
+
+ for (var i = 0; i < arguments.length; i++) {
+ let f;
+
+ if (typeof arguments[i] === "object") {
+ for (let url in arguments[i]) {
+ let obj = arguments[i];
+ f = new Promise(function(resolve, reject) {
+ urls.push(url);
+ resolve(obj[url]);
+ });
+ }
+ } else {
+ urls.push(arguments[i]);
+ f = request(arguments[i]).then((response) => {
+ return response.text();
+ });
+ }
+
+
+ fetched.push(f);
+ }
+
+ return await Promise.all(fetched)
+ .then(async (originals) => {
+ let text = "";
+ for (let index = 0; index < originals.length; index++) {
+ text = await this.convertViaSheet(originals[index], urls[index]);
+ this.insert(text);
+ }
+ return text;
+ });
+ }
+
+ async convertViaSheet(cssStr, href) {
+ let sheet = new Sheet(href, this.hooks);
+ await sheet.parse(cssStr);
+
+ // Insert the imported sheets first
+ for (let url of sheet.imported) {
+ let str = await request(url).then((response) => {
+ return response.text();
+ });
+ let text = await this.convertViaSheet(str, url);
+ this.insert(text);
+ }
+
+ this.sheets.push(sheet);
+
+ if (typeof sheet.width !== "undefined") {
+ this.width = sheet.width;
+ }
+ if (typeof sheet.height !== "undefined") {
+ this.height = sheet.height;
+ }
+ if (typeof sheet.orientation !== "undefined") {
+ this.orientation = sheet.orientation;
+ }
+ return sheet.toString();
+ }
+
+ insert(text){
+ let head = document.querySelector("head");
+ let style = document.createElement("style");
+ style.setAttribute("data-pagedjs-inserted-styles", "true");
+
+ style.appendChild(document.createTextNode(text));
+
+ head.appendChild(style);
+
+ this.inserted.push(style);
+ return style;
+ }
+
+ destroy() {
+ this.styleEl.remove();
+ this.inserted.forEach((s) => {
+ s.remove();
+ });
+ this.sheets = [];
+ }
+ }
+
+ class Handler {
+ constructor(chunker, polisher, caller) {
+ let hooks = Object.assign({}, chunker && chunker.hooks, polisher && polisher.hooks, caller && caller.hooks);
+ this.chunker = chunker;
+ this.polisher = polisher;
+ this.caller = caller;
+
+ for (let name in hooks) {
+ if (name in this) {
+ let hook = hooks[name];
+ hook.register(this[name].bind(this));
+ }
+ }
+ }
+ }
+
+ EventEmitter(Handler.prototype);
+
+ // https://www.w3.org/TR/css3-page/#page-size-prop
+
+ var pageSizes = {
+ "A0": {
+ width: {
+ value: 841,
+ unit: "mm"
+ },
+ height: {
+ value: 1189,
+ unit: "mm"
+ }
+ },
+ "A1": {
+ width: {
+ value: 594,
+ unit: "mm"
+ },
+ height: {
+ value: 841,
+ unit: "mm"
+ }
+ },
+ "A2": {
+ width: {
+ value: 420,
+ unit: "mm"
+ },
+ height: {
+ value: 594,
+ unit: "mm"
+ }
+ },
+ "A3": {
+ width: {
+ value: 297,
+ unit: "mm"
+ },
+ height: {
+ value: 420,
+ unit: "mm"
+ }
+ },
+ "A4": {
+ width: {
+ value: 210,
+ unit: "mm"
+ },
+ height: {
+ value: 297,
+ unit: "mm"
+ }
+ },
+ "A5": {
+ width: {
+ value: 148,
+ unit: "mm"
+ },
+ height: {
+ value: 210,
+ unit: "mm"
+ }
+ },
+ "A6": {
+ width: {
+ value: 105,
+ unit: "mm"
+ },
+ height: {
+ value: 148,
+ unit: "mm"
+ }
+ },
+ "A7": {
+ width: {
+ value: 74,
+ unit: "mm"
+ },
+ height: {
+ value: 105,
+ unit: "mm"
+ }
+ },
+ "A8": {
+ width: {
+ value: 52,
+ unit: "mm"
+ },
+ height: {
+ value: 74,
+ unit: "mm"
+ }
+ },
+ "A9": {
+ width: {
+ value: 37,
+ unit: "mm"
+ },
+ height: {
+ value: 52,
+ unit: "mm"
+ }
+ },
+ "A10": {
+ width: {
+ value: 26,
+ unit: "mm"
+ },
+ height: {
+ value: 37,
+ unit: "mm"
+ }
+ },
+ "B4": {
+ width: {
+ value: 250,
+ unit: "mm"
+ },
+ height: {
+ value: 353,
+ unit: "mm"
+ }
+ },
+ "B5": {
+ width: {
+ value: 176,
+ unit: "mm"
+ },
+ height: {
+ value: 250,
+ unit: "mm"
+ }
+ },
+ "letter": {
+ width: {
+ value: 8.5,
+ unit: "in"
+ },
+ height: {
+ value: 11,
+ unit: "in"
+ }
+ },
+ "legal": {
+ width: {
+ value: 8.5,
+ unit: "in"
+ },
+ height: {
+ value: 14,
+ unit: "in"
+ }
+ },
+ "ledger": {
+ width: {
+ value: 11,
+ unit: "in"
+ },
+ height: {
+ value: 17,
+ unit: "in"
+ }
+ }
+ };
+
+ class AtPage extends Handler {
+ constructor(chunker, polisher, caller) {
+ super(chunker, polisher, caller);
+
+ this.pages = {};
+
+ this.width = undefined;
+ this.height = undefined;
+ this.orientation = undefined;
+ this.marginalia = {};
+ }
+
+ pageModel(selector) {
+ return {
+ selector: selector,
+ name: undefined,
+ psuedo: undefined,
+ nth: undefined,
+ marginalia: {},
+ width: undefined,
+ height: undefined,
+ orientation: undefined,
+ margin: {
+ top: {},
+ right: {},
+ left: {},
+ bottom: {}
+ },
+ padding: {
+ top: {},
+ right: {},
+ left: {},
+ bottom: {}
+ },
+ border: {
+ top: {},
+ right: {},
+ left: {},
+ bottom: {}
+ },
+ backgroundOrigin: undefined,
+ block: {},
+ marks: undefined,
+ notes: undefined,
+ added: false
+ };
+ }
+
+ // Find and Remove @page rules
+ onAtPage(node, item, list) {
+ let page, marginalia;
+ let selector = "";
+ let named, psuedo, nth;
+ let needsMerge = false;
+
+ if (node.prelude) {
+ named = this.getTypeSelector(node);
+ psuedo = this.getPsuedoSelector(node);
+ nth = this.getNthSelector(node);
+ selector = csstree.generate(node.prelude);
+ } else {
+ selector = "*";
+ }
+
+ if (selector in this.pages) {
+ // this.pages[selector] = Object.assign(this.pages[selector], page);
+ // console.log("after", selector, this.pages[selector]);
+
+ // this.pages[selector].added = false;
+ page = this.pages[selector];
+ marginalia = this.replaceMarginalia(node);
+ needsMerge = true;
+ // Mark page for getting classes added again
+ page.added = false;
+ } else {
+ page = this.pageModel(selector);
+ marginalia = this.replaceMarginalia(node);
+ this.pages[selector] = page;
+ }
+
+ page.name = named;
+ page.psuedo = psuedo;
+ page.nth = nth;
+
+ if (needsMerge) {
+ page.marginalia = Object.assign(page.marginalia, marginalia);
+ } else {
+ page.marginalia = marginalia;
+ }
+
+ let notes = this.replaceNotes(node);
+ page.notes = notes;
+
+ let declarations = this.replaceDeclarations(node);
+
+ if (declarations.size) {
+ page.size = declarations.size;
+ page.width = declarations.size.width;
+ page.height = declarations.size.height;
+ page.orientation = declarations.size.orientation;
+ page.format = declarations.size.format;
+ }
+
+ if (declarations.bleed && declarations.bleed[0] != "auto") {
+ switch (declarations.bleed.length) {
+ case 4: // top right bottom left
+ page.bleed = {
+ top: declarations.bleed[0],
+ right: declarations.bleed[1],
+ bottom: declarations.bleed[2],
+ left: declarations.bleed[3]
+ };
+ break;
+ case 3: // top right bottom right
+ page.bleed = {
+ top: declarations.bleed[0],
+ right: declarations.bleed[1],
+ bottom: declarations.bleed[2],
+ left: declarations.bleed[1]
+ };
+ break;
+ case 2: // top right top right
+ page.bleed = {
+ top: declarations.bleed[0],
+ right: declarations.bleed[1],
+ bottom: declarations.bleed[0],
+ left: declarations.bleed[1]
+ };
+ break;
+ default:
+ page.bleed = {
+ top: declarations.bleed[0],
+ right: declarations.bleed[0],
+ bottom: declarations.bleed[0],
+ left: declarations.bleed[0]
+ };
+ }
+ }
+
+ if (declarations.marks) {
+ if (!declarations.bleed || declarations.bleed && declarations.bleed[0] === "auto") {
+ // Spec say 6pt, but needs more space for marks
+ page.bleed = {
+ top: { value: 6, unit: "mm" },
+ right: { value: 6, unit: "mm" },
+ bottom: { value: 6, unit: "mm" },
+ left: { value: 6, unit: "mm" }
+ };
+ }
+
+ page.marks = declarations.marks;
+ }
+
+ if (declarations.margin) {
+ page.margin = declarations.margin;
+ }
+ if (declarations.padding) {
+ page.padding = declarations.padding;
+ }
+
+ if (declarations.border) {
+ page.border = declarations.border;
+ }
+
+ if (declarations.marks) {
+ page.marks = declarations.marks;
+ }
+
+ if (needsMerge) {
+ page.block.children.appendList(node.block.children);
+ } else {
+ page.block = node.block;
+ }
+
+ // Remove the rule
+ list.remove(item);
+ }
+
+ /* Handled in breaks */
+ /*
+ afterParsed(parsed) {
+ for (let b in this.named) {
+ // Find elements
+ let elements = parsed.querySelectorAll(b);
+ // Add break data
+ for (var i = 0; i < elements.length; i++) {
+ elements[i].setAttribute("data-page", this.named[b]);
+ }
+ }
+ }
+ */
+
+ afterTreeWalk(ast, sheet) {
+ let dirtyPage = "*" in this.pages && this.pages["*"].added === false;
+
+ this.addPageClasses(this.pages, ast, sheet);
+
+ if (dirtyPage) {
+ let width = this.pages["*"].width;
+ let height = this.pages["*"].height;
+ let format = this.pages["*"].format;
+ let orientation = this.pages["*"].orientation;
+ let bleed = this.pages["*"].bleed;
+ let marks = this.pages["*"].marks;
+ let bleedverso = undefined;
+ let bleedrecto = undefined;
+
+ if (":left" in this.pages) {
+ bleedverso = this.pages[":left"].bleed;
+ }
+
+ if (":right" in this.pages) {
+ bleedrecto = this.pages[":right"].bleed;
+ }
+
+ if ((width && height) &&
+ (this.width !== width || this.height !== height)) {
+ this.width = width;
+ this.height = height;
+ this.format = format;
+ this.orientation = orientation;
+
+ this.addRootVars(ast, width, height, orientation, bleed, bleedrecto, bleedverso, marks);
+ this.addRootPage(ast, this.pages["*"].size, bleed, bleedrecto, bleedverso);
+
+ this.emit("size", { width, height, orientation, format, bleed });
+ this.emit("atpages", this.pages);
+ }
+
+ }
+ }
+
+ getTypeSelector(ast) {
+ // Find page name
+ let name;
+
+ csstree.walk(ast, {
+ visit: "TypeSelector",
+ enter: (node, item, list) => {
+ name = node.name;
+ }
+ });
+
+ return name;
+ }
+
+ getPsuedoSelector(ast) {
+ // Find if it has :left & :right & :black & :first
+ let name;
+ csstree.walk(ast, {
+ visit: "PseudoClassSelector",
+ enter: (node, item, list) => {
+ if (node.name !== "nth") {
+ name = node.name;
+ }
+ }
+ });
+
+ return name;
+ }
+
+ getNthSelector(ast) {
+ // Find if it has :nth
+ let nth;
+ csstree.walk(ast, {
+ visit: "PseudoClassSelector",
+ enter: (node, item, list) => {
+ if (node.name === "nth" && node.children) {
+ let raw = node.children.first();
+ nth = raw.value;
+ }
+ }
+ });
+
+ return nth;
+ }
+
+ replaceMarginalia(ast) {
+ let parsed = {};
+ const MARGINS = [
+ "top-left-corner", "top-left", "top", "top-center", "top-right", "top-right-corner",
+ "bottom-left-corner", "bottom-left", "bottom", "bottom-center", "bottom-right", "bottom-right-corner",
+ "left-top", "left-middle", "left", "left-bottom", "top-right-corner",
+ "right-top", "right-middle", "right", "right-bottom", "right-right-corner"
+ ];
+ csstree.walk(ast.block, {
+ visit: "Atrule",
+ enter: (node, item, list) => {
+ let name = node.name;
+ if (MARGINS.includes(name)) {
+ if (name === "top") {
+ name = "top-center";
+ }
+ if (name === "right") {
+ name = "right-middle";
+ }
+ if (name === "left") {
+ name = "left-middle";
+ }
+ if (name === "bottom") {
+ name = "bottom-center";
+ }
+ parsed[name] = node.block;
+ list.remove(item);
+ }
+ }
+ });
+
+ return parsed;
+ }
+
+ replaceNotes(ast) {
+ let parsed = {};
+
+ csstree.walk(ast.block, {
+ visit: "Atrule",
+ enter: (node, item, list) => {
+ let name = node.name;
+ if (name === "footnote") {
+ parsed[name] = node.block;
+ list.remove(item);
+ }
+ }
+ });
+
+ return parsed;
+ }
+
+ replaceDeclarations(ast) {
+ let parsed = {};
+
+ csstree.walk(ast.block, {
+ visit: "Declaration",
+ enter: (declaration, dItem, dList) => {
+ let prop = csstree.property(declaration.property).name;
+ // let value = declaration.value;
+
+ if (prop === "marks") {
+ parsed.marks = [];
+ csstree.walk(declaration, {
+ visit: "Identifier",
+ enter: (ident) => {
+ parsed.marks.push(ident.name);
+ }
+ });
+ dList.remove(dItem);
+ } else if (prop === "margin") {
+ parsed.margin = this.getMargins(declaration);
+ dList.remove(dItem);
+
+ } else if (prop.indexOf("margin-") === 0) {
+ let m = prop.substring("margin-".length);
+ if (!parsed.margin) {
+ parsed.margin = {
+ top: {},
+ right: {},
+ left: {},
+ bottom: {}
+ };
+ }
+ parsed.margin[m] = declaration.value.children.first();
+ dList.remove(dItem);
+
+ } else if (prop === "padding") {
+ parsed.padding = this.getPaddings(declaration.value);
+ dList.remove(dItem);
+
+ } else if (prop.indexOf("padding-") === 0) {
+ let p = prop.substring("padding-".length);
+ if (!parsed.padding) {
+ parsed.padding = {
+ top: {},
+ right: {},
+ left: {},
+ bottom: {}
+ };
+ }
+ parsed.padding[p] = declaration.value.children.first();
+ dList.remove(dItem);
+ }
+
+ else if (prop === "border") {
+ if (!parsed.border) {
+ parsed.border = {
+ top: {},
+ right: {},
+ left: {},
+ bottom: {}
+ };
+ }
+ parsed.border.top = csstree.generate(declaration.value);
+ parsed.border.right = csstree.generate(declaration.value);
+ parsed.border.left = csstree.generate(declaration.value);
+ parsed.border.bottom = csstree.generate(declaration.value);
+
+ dList.remove(dItem);
+
+ }
+
+ else if (prop.indexOf("border-") === 0) {
+ if (!parsed.border) {
+ parsed.border = {
+ top: {},
+ right: {},
+ left: {},
+ bottom: {}
+ };
+ }
+ let p = prop.substring("border-".length);
+
+ parsed.border[p] = csstree.generate(declaration.value);
+ dList.remove(dItem);
+
+ }
+
+ else if (prop === "size") {
+ parsed.size = this.getSize(declaration);
+ dList.remove(dItem);
+ } else if (prop === "bleed") {
+ parsed.bleed = [];
+
+ csstree.walk(declaration, {
+ enter: (subNode) => {
+ switch (subNode.type) {
+ case "String": // bleed: "auto"
+ if (subNode.value.indexOf("auto") > -1) {
+ parsed.bleed.push("auto");
+ }
+ break;
+ case "Dimension": // bleed: 1in 2in, bleed: 20px ect.
+ parsed.bleed.push({
+ value: subNode.value,
+ unit: subNode.unit
+ });
+ break;
+ case "Number":
+ parsed.bleed.push({
+ value: subNode.value,
+ unit: "px"
+ });
+ break;
+ // ignore
+ }
+
+ }
+ });
+
+ dList.remove(dItem);
+ }
+
+ }
+ });
+
+ return parsed;
+
+ }
+ getSize(declaration) {
+ let width, height, orientation, format;
+
+ // Get size: Xmm Ymm
+ csstree.walk(declaration, {
+ visit: "Dimension",
+ enter: (node, item, list) => {
+ let { value, unit } = node;
+ if (typeof width === "undefined") {
+ width = { value, unit };
+ } else if (typeof height === "undefined") {
+ height = { value, unit };
+ }
+ }
+ });
+
+ // Get size: "A4"
+ csstree.walk(declaration, {
+ visit: "String",
+ enter: (node, item, list) => {
+ let name = node.value.replace(/["|']/g, "");
+ let s = pageSizes[name];
+ if (s) {
+ width = s.width;
+ height = s.height;
+ }
+ }
+ });
+
+ // Get Format or Landscape or Portrait
+ csstree.walk(declaration, {
+ visit: "Identifier",
+ enter: (node, item, list) => {
+ let name = node.name;
+ if (name === "landscape" || name === "portrait") {
+ orientation = node.name;
+ } else if (name !== "auto") {
+ let s = pageSizes[name];
+ if (s) {
+ width = s.width;
+ height = s.height;
+ }
+ format = name;
+ }
+ }
+ });
+
+ return {
+ width,
+ height,
+ orientation,
+ format
+ };
+ }
+
+ getMargins(declaration) {
+ let margins = [];
+ let margin = {
+ top: {},
+ right: {},
+ left: {},
+ bottom: {}
+ };
+
+ csstree.walk(declaration, {
+ enter: (node) => {
+ switch (node.type) {
+ case "Dimension": // margin: 1in 2in, margin: 20px, etc...
+ margins.push(node);
+ break;
+ case "Number": // margin: 0
+ margins.push({value: node.value, unit: "px"});
+ break;
+ // ignore
+ }
+ }
+ });
+
+ if (margins.length === 1) {
+ for (let m in margin) {
+ margin[m] = margins[0];
+ }
+ } else if (margins.length === 2) {
+ margin.top = margins[0];
+ margin.right = margins[1];
+ margin.bottom = margins[0];
+ margin.left = margins[1];
+ } else if (margins.length === 3) {
+ margin.top = margins[0];
+ margin.right = margins[1];
+ margin.bottom = margins[2];
+ margin.left = margins[1];
+ } else if (margins.length === 4) {
+ margin.top = margins[0];
+ margin.right = margins[1];
+ margin.bottom = margins[2];
+ margin.left = margins[3];
+ }
+
+ return margin;
+ }
+
+ getPaddings(declaration) {
+ let paddings = [];
+ let padding = {
+ top: {},
+ right: {},
+ left: {},
+ bottom: {}
+ };
+
+ csstree.walk(declaration, {
+ enter: (node) => {
+ switch (node.type) {
+ case "Dimension": // padding: 1in 2in, padding: 20px, etc...
+ paddings.push(node);
+ break;
+ case "Number": // padding: 0
+ paddings.push({value: node.value, unit: "px"});
+ break;
+ // ignore
+ }
+ }
+ });
+ if (paddings.length === 1) {
+ for (let p in padding) {
+ padding[p] = paddings[0];
+ }
+ } else if (paddings.length === 2) {
+
+ padding.top = paddings[0];
+ padding.right = paddings[1];
+ padding.bottom = paddings[0];
+ padding.left = paddings[1];
+ } else if (paddings.length === 3) {
+
+ padding.top = paddings[0];
+ padding.right = paddings[1];
+ padding.bottom = paddings[2];
+ padding.left = paddings[1];
+ } else if (paddings.length === 4) {
+
+ padding.top = paddings[0];
+ padding.right = paddings[1];
+ padding.bottom = paddings[2];
+ padding.left = paddings[3];
+ }
+ return padding;
+ }
+
+ // get values for the border on the @page to pass them to the element with the .pagedjs_area class
+ getBorders(declaration) {
+ let border = {
+ top: {},
+ right: {},
+ left: {},
+ bottom: {}
+ };
+
+ if (declaration.prop == "border") {
+ border.top = csstree.generate(declaration.value);
+ border.right = csstree.generate(declaration.value);
+ border.bottom = csstree.generate(declaration.value);
+ border.left = csstree.generate(declaration.value);
+
+ }
+ else if (declaration.prop == "border-top") {
+ border.top = csstree.generate(declaration.value);
+ }
+ else if (declaration.prop == "border-right") {
+ border.right = csstree.generate(declaration.value);
+
+ }
+ else if (declaration.prop == "border-bottom") {
+ border.bottom = csstree.generate(declaration.value);
+
+ }
+ else if (declaration.prop == "border-left") {
+ border.left = csstree.generate(declaration.value);
+ }
+
+ return border;
+ }
+
+
+ addPageClasses(pages, ast, sheet) {
+ // First add * page
+ if ("*" in pages && pages["*"].added === false) {
+ let p = this.createPage(pages["*"], ast.children, sheet);
+ sheet.insertRule(p);
+ pages["*"].added = true;
+ }
+ // Add :left & :right
+ if (":left" in pages && pages[":left"].added === false) {
+ let left = this.createPage(pages[":left"], ast.children, sheet);
+ sheet.insertRule(left);
+ pages[":left"].added = true;
+ }
+ if (":right" in pages && pages[":right"].added === false) {
+ let right = this.createPage(pages[":right"], ast.children, sheet);
+ sheet.insertRule(right);
+ pages[":right"].added = true;
+ }
+ // Add :first & :blank
+ if (":first" in pages && pages[":first"].added === false) {
+ let first = this.createPage(pages[":first"], ast.children, sheet);
+ sheet.insertRule(first);
+ pages[":first"].added = true;
+ }
+ if (":blank" in pages && pages[":blank"].added === false) {
+ let blank = this.createPage(pages[":blank"], ast.children, sheet);
+ sheet.insertRule(blank);
+ pages[":blank"].added = true;
+ }
+ // Add nth pages
+ for (let pg in pages) {
+ if (pages[pg].nth && pages[pg].added === false) {
+ let nth = this.createPage(pages[pg], ast.children, sheet);
+ sheet.insertRule(nth);
+ pages[pg].added = true;
+ }
+ }
+
+ // Add named pages
+ for (let pg in pages) {
+ if (pages[pg].name && pages[pg].added === false) {
+ let named = this.createPage(pages[pg], ast.children, sheet);
+ sheet.insertRule(named);
+ pages[pg].added = true;
+ }
+ }
+
+ }
+
+ createPage(page, ruleList, sheet) {
+
+ let selectors = this.selectorsForPage(page);
+ let children = page.block.children.copy();
+ let block = {
+ type: "Block",
+ loc: 0,
+ children: children
+ };
+
+
+ let rule = this.createRule(selectors, block);
+
+ this.addMarginVars(page.margin, children, children.first());
+ this.addPaddingVars(page.padding, children, children.first());
+ this.addBorderVars(page.border, children, children.first());
+
+
+ if (page.width) {
+ this.addDimensions(page.width, page.height, page.orientation, children, children.first());
+ }
+
+ if (page.marginalia) {
+ this.addMarginaliaStyles(page, ruleList, rule, sheet);
+ this.addMarginaliaContent(page, ruleList, rule, sheet);
+ }
+
+ if(page.notes) {
+ this.addNotesStyles(page.notes, page, ruleList, rule, sheet);
+ }
+
+ return rule;
+ }
+
+ addMarginVars(margin, list, item) {
+ // variables for margins
+ for (let m in margin) {
+ if (typeof margin[m].value !== "undefined") {
+ let value = margin[m].value + (margin[m].unit || "");
+ let mVar = list.createItem({
+ type: "Declaration",
+ property: "--pagedjs-margin-" + m,
+ value: {
+ type: "Raw",
+ value: value
+ }
+ });
+ list.append(mVar, item);
+
+ }
+ }
+ }
+
+ addPaddingVars(padding, list, item) {
+ // variables for padding
+ for (let p in padding) {
+
+ if (typeof padding[p].value !== "undefined") {
+ let value = padding[p].value + (padding[p].unit || "");
+ let pVar = list.createItem({
+ type: "Declaration",
+ property: "--pagedjs-padding-" + p,
+ value: {
+ type: "Raw",
+ value: value
+ }
+ });
+
+ list.append(pVar, item);
+ }
+
+ }
+ }
+
+ addBorderVars(border, list, item) {
+ // variables for borders
+ for (const name of Object.keys(border)) {
+ const value = border[name];
+ // value is an empty object when undefined
+ if (typeof value === "string") {
+ const borderItem = list.createItem({
+ type: "Declaration",
+ property: "--pagedjs-border-" + name,
+ value: {
+ type: "Raw",
+ value: value
+ }
+ });
+ list.append(borderItem, item);
+ }
+ }
+ }
+
+ addDimensions(width, height, orientation, list, item) {
+ let widthString, heightString;
+
+ widthString = CSSValueToString(width);
+ heightString = CSSValueToString(height);
+
+ if (orientation && orientation !== "portrait") {
+ // reverse for orientation
+ [widthString, heightString] = [heightString, widthString];
+ }
+
+ // width variable
+ let wVar = this.createVariable("--pagedjs-pagebox-width", widthString);
+ list.appendData(wVar);
+
+ // height variable
+ let hVar = this.createVariable("--pagedjs-pagebox-height", heightString);
+ list.appendData(hVar);
+
+ // let w = this.createDimension("width", width);
+ // let h = this.createDimension("height", height);
+ // list.appendData(w);
+ // list.appendData(h);
+ }
+
+ addMarginaliaStyles(page, list, item, sheet) {
+ for (let loc in page.marginalia) {
+ let block = csstree.clone(page.marginalia[loc]);
+ let hasContent = false;
+
+ if (block.children.isEmpty()) {
+ continue;
+ }
+
+ csstree.walk(block, {
+ visit: "Declaration",
+ enter: (node, item, list) => {
+ if (node.property === "content") {
+ if (node.value.children && node.value.children.first().name === "none") {
+ hasContent = false;
+ } else {
+ hasContent = true;
+ }
+ list.remove(item);
+ }
+ if (node.property === "vertical-align") {
+ csstree.walk(node, {
+ visit: "Identifier",
+ enter: (identNode, identItem, identlist) => {
+ let name = identNode.name;
+ if (name === "top") {
+ identNode.name = "flex-start";
+ } else if (name === "middle") {
+ identNode.name = "center";
+ } else if (name === "bottom") {
+ identNode.name = "flex-end";
+ }
+ }
+ });
+ node.property = "align-items";
+ }
+
+ if (node.property === "width" &&
+ (loc === "top-left" ||
+ loc === "top-center" ||
+ loc === "top-right" ||
+ loc === "bottom-left" ||
+ loc === "bottom-center" ||
+ loc === "bottom-right")) {
+ let c = csstree.clone(node);
+ c.property = "max-width";
+ list.appendData(c);
+ }
+
+ if (node.property === "height" &&
+ (loc === "left-top" ||
+ loc === "left-middle" ||
+ loc === "left-bottom" ||
+ loc === "right-top" ||
+ loc === "right-middle" ||
+ loc === "right-bottom")) {
+ let c = csstree.clone(node);
+ c.property = "max-height";
+ list.appendData(c);
+ }
+ }
+ });
+
+ let marginSelectors = this.selectorsForPageMargin(page, loc);
+ let marginRule = this.createRule(marginSelectors, block);
+
+ list.appendData(marginRule);
+
+ let sel = csstree.generate({
+ type: "Selector",
+ children: marginSelectors
+ });
+
+ this.marginalia[sel] = {
+ page: page,
+ selector: sel,
+ block: page.marginalia[loc],
+ hasContent: hasContent
+ };
+
+ }
+ }
+
+ addMarginaliaContent(page, list, item, sheet) {
+ let displayNone;
+ // Just content
+ for (let loc in page.marginalia) {
+ let content = csstree.clone(page.marginalia[loc]);
+ csstree.walk(content, {
+ visit: "Declaration",
+ enter: (node, item, list) => {
+ if (node.property !== "content") {
+ list.remove(item);
+ }
+
+ if (node.value.children && node.value.children.first().name === "none") {
+ displayNone = true;
+ }
+ }
+ });
+
+ if (content.children.isEmpty()) {
+ continue;
+ }
+
+ let displaySelectors = this.selectorsForPageMargin(page, loc);
+ let displayDeclaration;
+
+ displaySelectors.insertData({
+ type: "Combinator",
+ name: ">"
+ });
+
+ displaySelectors.insertData({
+ type: "ClassSelector",
+ name: "pagedjs_margin-content"
+ });
+
+ displaySelectors.insertData({
+ type: "Combinator",
+ name: ">"
+ });
+
+ displaySelectors.insertData({
+ type: "TypeSelector",
+ name: "*"
+ });
+
+ if (displayNone) {
+ displayDeclaration = this.createDeclaration("display", "none");
+ } else {
+ displayDeclaration = this.createDeclaration("display", "block");
+ }
+
+ let displayRule = this.createRule(displaySelectors, [displayDeclaration]);
+ sheet.insertRule(displayRule);
+
+ // insert content rule
+ let contentSelectors = this.selectorsForPageMargin(page, loc);
+
+ contentSelectors.insertData({
+ type: "Combinator",
+ name: ">"
+ });
+
+ contentSelectors.insertData({
+ type: "ClassSelector",
+ name: "pagedjs_margin-content"
+ });
+
+ contentSelectors.insertData({
+ type: "PseudoElementSelector",
+ name: "after",
+ children: null
+ });
+
+ let contentRule = this.createRule(contentSelectors, content);
+ sheet.insertRule(contentRule);
+ }
+ }
+
+ addRootVars(ast, width, height, orientation, bleed, bleedrecto, bleedverso, marks) {
+ let rules = [];
+ let selectors = new csstree.List();
+ selectors.insertData({
+ type: "PseudoClassSelector",
+ name: "root",
+ children: null
+ });
+
+ let widthString, heightString;
+ let widthStringRight, heightStringRight;
+ let widthStringLeft, heightStringLeft;
+
+ if (!bleed) {
+ widthString = CSSValueToString(width);
+ heightString = CSSValueToString(height);
+ widthStringRight = CSSValueToString(width);
+ heightStringRight = CSSValueToString(height);
+ widthStringLeft = CSSValueToString(width);
+ heightStringLeft = CSSValueToString(height);
+ } else {
+ widthString = `calc( ${CSSValueToString(width)} + ${CSSValueToString(bleed.left)} + ${CSSValueToString(bleed.right)} )`;
+ heightString = `calc( ${CSSValueToString(height)} + ${CSSValueToString(bleed.top)} + ${CSSValueToString(bleed.bottom)} )`;
+
+ widthStringRight = `calc( ${CSSValueToString(width)} + ${CSSValueToString(bleed.left)} + ${CSSValueToString(bleed.right)} )`;
+ heightStringRight = `calc( ${CSSValueToString(height)} + ${CSSValueToString(bleed.top)} + ${CSSValueToString(bleed.bottom)} )`;
+
+ widthStringLeft = `calc( ${CSSValueToString(width)} + ${CSSValueToString(bleed.left)} + ${CSSValueToString(bleed.right)} )`;
+ heightStringLeft = `calc( ${CSSValueToString(height)} + ${CSSValueToString(bleed.top)} + ${CSSValueToString(bleed.bottom)} )`;
+
+ let bleedTop = this.createVariable("--pagedjs-bleed-top", CSSValueToString(bleed.top));
+ let bleedRight = this.createVariable("--pagedjs-bleed-right", CSSValueToString(bleed.right));
+ let bleedBottom = this.createVariable("--pagedjs-bleed-bottom", CSSValueToString(bleed.bottom));
+ let bleedLeft = this.createVariable("--pagedjs-bleed-left", CSSValueToString(bleed.left));
+
+ let bleedTopRecto = this.createVariable("--pagedjs-bleed-right-top", CSSValueToString(bleed.top));
+ let bleedRightRecto = this.createVariable("--pagedjs-bleed-right-right", CSSValueToString(bleed.right));
+ let bleedBottomRecto = this.createVariable("--pagedjs-bleed-right-bottom", CSSValueToString(bleed.bottom));
+ let bleedLeftRecto = this.createVariable("--pagedjs-bleed-right-left", CSSValueToString(bleed.left));
+
+ let bleedTopVerso = this.createVariable("--pagedjs-bleed-left-top", CSSValueToString(bleed.top));
+ let bleedRightVerso = this.createVariable("--pagedjs-bleed-left-right", CSSValueToString(bleed.right));
+ let bleedBottomVerso = this.createVariable("--pagedjs-bleed-left-bottom", CSSValueToString(bleed.bottom));
+ let bleedLeftVerso = this.createVariable("--pagedjs-bleed-left-left", CSSValueToString(bleed.left));
+
+ if (bleedrecto) {
+ bleedTopRecto = this.createVariable("--pagedjs-bleed-right-top", CSSValueToString(bleedrecto.top));
+ bleedRightRecto = this.createVariable("--pagedjs-bleed-right-right", CSSValueToString(bleedrecto.right));
+ bleedBottomRecto = this.createVariable("--pagedjs-bleed-right-bottom", CSSValueToString(bleedrecto.bottom));
+ bleedLeftRecto = this.createVariable("--pagedjs-bleed-right-left", CSSValueToString(bleedrecto.left));
+
+ widthStringRight = `calc( ${CSSValueToString(width)} + ${CSSValueToString(bleedrecto.left)} + ${CSSValueToString(bleedrecto.right)} )`;
+ heightStringRight = `calc( ${CSSValueToString(height)} + ${CSSValueToString(bleedrecto.top)} + ${CSSValueToString(bleedrecto.bottom)} )`;
+ }
+ if (bleedverso) {
+ bleedTopVerso = this.createVariable("--pagedjs-bleed-left-top", CSSValueToString(bleedverso.top));
+ bleedRightVerso = this.createVariable("--pagedjs-bleed-left-right", CSSValueToString(bleedverso.right));
+ bleedBottomVerso = this.createVariable("--pagedjs-bleed-left-bottom", CSSValueToString(bleedverso.bottom));
+ bleedLeftVerso = this.createVariable("--pagedjs-bleed-left-left", CSSValueToString(bleedverso.left));
+
+ widthStringLeft = `calc( ${CSSValueToString(width)} + ${CSSValueToString(bleedverso.left)} + ${CSSValueToString(bleedverso.right)} )`;
+ heightStringLeft = `calc( ${CSSValueToString(height)} + ${CSSValueToString(bleedverso.top)} + ${CSSValueToString(bleedverso.bottom)} )`;
+ }
+
+ let pageWidthVar = this.createVariable("--pagedjs-width", CSSValueToString(width));
+ let pageHeightVar = this.createVariable("--pagedjs-height", CSSValueToString(height));
+
+ rules.push(
+ bleedTop,
+ bleedRight,
+ bleedBottom,
+ bleedLeft,
+ bleedTopRecto,
+ bleedRightRecto,
+ bleedBottomRecto,
+ bleedLeftRecto,
+ bleedTopVerso,
+ bleedRightVerso,
+ bleedBottomVerso,
+ bleedLeftVerso,
+ pageWidthVar,
+ pageHeightVar
+ );
+ }
+
+ if (marks) {
+ marks.forEach((mark) => {
+ let markDisplay = this.createVariable("--pagedjs-mark-" + mark + "-display", "block");
+ rules.push(markDisplay);
+ });
+ }
+
+ // orientation variable
+ if (orientation) {
+ let oVar = this.createVariable("--pagedjs-orientation", orientation);
+ rules.push(oVar);
+
+ if (orientation !== "portrait") {
+ // reverse for orientation
+ [widthString, heightString] = [heightString, widthString];
+ [widthStringRight, heightStringRight] = [heightStringRight, widthStringRight];
+ [widthStringLeft, heightStringLeft] = [heightStringLeft, widthStringLeft];
+ }
+ }
+
+ let wVar = this.createVariable("--pagedjs-width", widthString);
+ let hVar = this.createVariable("--pagedjs-height", heightString);
+
+ let wVarR = this.createVariable("--pagedjs-width-right", widthStringRight);
+ let hVarR = this.createVariable("--pagedjs-height-right", heightStringRight);
+
+ let wVarL = this.createVariable("--pagedjs-width-left", widthStringLeft);
+ let hVarL = this.createVariable("--pagedjs-height-left", heightStringLeft);
+
+ rules.push(wVar, hVar, wVarR, hVarR, wVarL, hVarL);
+
+ let rule = this.createRule(selectors, rules);
+
+ ast.children.appendData(rule);
+ }
+
+
+ addNotesStyles(notes, page, list, item, sheet) {
+
+ for (const note in notes) {
+ let selectors = this.selectorsForPage(page);
+
+ selectors.insertData({
+ type: "Combinator",
+ name: " "
+ });
+
+ selectors.insertData({
+ type: "ClassSelector",
+ name: "pagedjs_" + note + "_content"
+ });
+
+ let notesRule = this.createRule(selectors, notes[note]);
+
+ list.appendData(notesRule);
+ }
+
+ }
+
+ /*
+ @page {
+ size: var(--pagedjs-width) var(--pagedjs-height);
+ margin: 0;
+ padding: 0;
+ }
+ */
+ addRootPage(ast, size, bleed, bleedrecto, bleedverso) {
+ let { width, height, orientation, format } = size;
+ let children = new csstree.List();
+ let childrenLeft = new csstree.List();
+ let childrenRight = new csstree.List();
+ let dimensions = new csstree.List();
+ let dimensionsLeft = new csstree.List();
+ let dimensionsRight = new csstree.List();
+
+ if (bleed) {
+ let widthCalculations = new csstree.List();
+ let heightCalculations = new csstree.List();
+
+ // width
+ widthCalculations.appendData({
+ type: "Dimension",
+ unit: width.unit,
+ value: width.value
+ });
+
+ widthCalculations.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ widthCalculations.appendData({
+ type: "Operator",
+ value: "+"
+ });
+
+ widthCalculations.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ widthCalculations.appendData({
+ type: "Dimension",
+ unit: bleed.left.unit,
+ value: bleed.left.value
+ });
+
+ widthCalculations.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ widthCalculations.appendData({
+ type: "Operator",
+ value: "+"
+ });
+
+ widthCalculations.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ widthCalculations.appendData({
+ type: "Dimension",
+ unit: bleed.right.unit,
+ value: bleed.right.value
+ });
+
+ // height
+ heightCalculations.appendData({
+ type: "Dimension",
+ unit: height.unit,
+ value: height.value
+ });
+
+ heightCalculations.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ heightCalculations.appendData({
+ type: "Operator",
+ value: "+"
+ });
+
+ heightCalculations.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ heightCalculations.appendData({
+ type: "Dimension",
+ unit: bleed.top.unit,
+ value: bleed.top.value
+ });
+
+ heightCalculations.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ heightCalculations.appendData({
+ type: "Operator",
+ value: "+"
+ });
+
+ heightCalculations.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ heightCalculations.appendData({
+ type: "Dimension",
+ unit: bleed.bottom.unit,
+ value: bleed.bottom.value
+ });
+
+ dimensions.appendData({
+ type: "Function",
+ name: "calc",
+ children: widthCalculations
+ });
+
+ dimensions.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ dimensions.appendData({
+ type: "Function",
+ name: "calc",
+ children: heightCalculations
+ });
+
+ } else if (format) {
+ dimensions.appendData({
+ type: "Identifier",
+ name: format
+ });
+
+ if (orientation) {
+ dimensions.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ dimensions.appendData({
+ type: "Identifier",
+ name: orientation
+ });
+ }
+ } else {
+ dimensions.appendData({
+ type: "Dimension",
+ unit: width.unit,
+ value: width.value
+ });
+
+ dimensions.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ dimensions.appendData({
+ type: "Dimension",
+ unit: height.unit,
+ value: height.value
+ });
+ }
+
+ children.appendData({
+ type: "Declaration",
+ property: "size",
+ loc: null,
+ value: {
+ type: "Value",
+ children: dimensions
+ }
+ });
+
+ children.appendData({
+ type: "Declaration",
+ property: "margin",
+ loc: null,
+ value: {
+ type: "Value",
+ children: [{
+ type: "Dimension",
+ unit: "px",
+ value: 0
+ }]
+ }
+ });
+
+ children.appendData({
+ type: "Declaration",
+ property: "padding",
+ loc: null,
+ value: {
+ type: "Value",
+ children: [{
+ type: "Dimension",
+ unit: "px",
+ value: 0
+ }]
+ }
+ });
+
+ children.appendData({
+ type: "Declaration",
+ property: "padding",
+ loc: null,
+ value: {
+ type: "Value",
+ children: [{
+ type: "Dimension",
+ unit: "px",
+ value: 0
+ }]
+ }
+ });
+
+ let rule = ast.children.createItem({
+ type: "Atrule",
+ prelude: null,
+ name: "page",
+ block: {
+ type: "Block",
+ loc: null,
+ children: children
+ }
+ });
+
+ ast.children.append(rule);
+
+ if (bleedverso) {
+ let widthCalculationsLeft = new csstree.List();
+ let heightCalculationsLeft = new csstree.List();
+
+ // width
+ widthCalculationsLeft.appendData({
+ type: "Dimension",
+ unit: width.unit,
+ value: width.value
+ });
+
+ widthCalculationsLeft.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ widthCalculationsLeft.appendData({
+ type: "Operator",
+ value: "+"
+ });
+
+ widthCalculationsLeft.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ widthCalculationsLeft.appendData({
+ type: "Dimension",
+ unit: bleedverso.left.unit,
+ value: bleedverso.left.value
+ });
+
+ widthCalculationsLeft.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ widthCalculationsLeft.appendData({
+ type: "Operator",
+ value: "+"
+ });
+
+ widthCalculationsLeft.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ widthCalculationsLeft.appendData({
+ type: "Dimension",
+ unit: bleedverso.right.unit,
+ value: bleedverso.right.value
+ });
+
+ // height
+ heightCalculationsLeft.appendData({
+ type: "Dimension",
+ unit: height.unit,
+ value: height.value
+ });
+
+ heightCalculationsLeft.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ heightCalculationsLeft.appendData({
+ type: "Operator",
+ value: "+"
+ });
+
+ heightCalculationsLeft.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ heightCalculationsLeft.appendData({
+ type: "Dimension",
+ unit: bleedverso.top.unit,
+ value: bleedverso.top.value
+ });
+
+ heightCalculationsLeft.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ heightCalculationsLeft.appendData({
+ type: "Operator",
+ value: "+"
+ });
+
+ heightCalculationsLeft.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ heightCalculationsLeft.appendData({
+ type: "Dimension",
+ unit: bleedverso.bottom.unit,
+ value: bleedverso.bottom.value
+ });
+
+ dimensionsLeft.appendData({
+ type: "Function",
+ name: "calc",
+ children: widthCalculationsLeft
+ });
+
+ dimensionsLeft.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ dimensionsLeft.appendData({
+ type: "Function",
+ name: "calc",
+ children: heightCalculationsLeft
+ });
+
+ childrenLeft.appendData({
+ type: "Declaration",
+ property: "size",
+ loc: null,
+ value: {
+ type: "Value",
+ children: dimensionsLeft
+ }
+ });
+
+ let ruleLeft = ast.children.createItem({
+ type: "Atrule",
+ prelude: null,
+ name: "page :left",
+ block: {
+ type: "Block",
+ loc: null,
+ children: childrenLeft
+ }
+ });
+
+ ast.children.append(ruleLeft);
+
+ }
+
+ if (bleedrecto) {
+ let widthCalculationsRight = new csstree.List();
+ let heightCalculationsRight = new csstree.List();
+
+ // width
+ widthCalculationsRight.appendData({
+ type: "Dimension",
+ unit: width.unit,
+ value: width.value
+ });
+
+ widthCalculationsRight.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ widthCalculationsRight.appendData({
+ type: "Operator",
+ value: "+"
+ });
+
+ widthCalculationsRight.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ widthCalculationsRight.appendData({
+ type: "Dimension",
+ unit: bleedrecto.left.unit,
+ value: bleedrecto.left.value
+ });
+
+ widthCalculationsRight.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ widthCalculationsRight.appendData({
+ type: "Operator",
+ value: "+"
+ });
+
+ widthCalculationsRight.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ widthCalculationsRight.appendData({
+ type: "Dimension",
+ unit: bleedrecto.right.unit,
+ value: bleedrecto.right.value
+ });
+
+ // height
+ heightCalculationsRight.appendData({
+ type: "Dimension",
+ unit: height.unit,
+ value: height.value
+ });
+
+ heightCalculationsRight.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ heightCalculationsRight.appendData({
+ type: "Operator",
+ value: "+"
+ });
+
+ heightCalculationsRight.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ heightCalculationsRight.appendData({
+ type: "Dimension",
+ unit: bleedrecto.top.unit,
+ value: bleedrecto.top.value
+ });
+
+ heightCalculationsRight.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ heightCalculationsRight.appendData({
+ type: "Operator",
+ value: "+"
+ });
+
+ heightCalculationsRight.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ heightCalculationsRight.appendData({
+ type: "Dimension",
+ unit: bleedrecto.bottom.unit,
+ value: bleedrecto.bottom.value
+ });
+
+ dimensionsRight.appendData({
+ type: "Function",
+ name: "calc",
+ children: widthCalculationsRight
+ });
+
+ dimensionsRight.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ dimensionsRight.appendData({
+ type: "Function",
+ name: "calc",
+ children: heightCalculationsRight
+ });
+
+ childrenRight.appendData({
+ type: "Declaration",
+ property: "size",
+ loc: null,
+ value: {
+ type: "Value",
+ children: dimensionsRight
+ }
+ });
+
+ let ruleRight = ast.children.createItem({
+ type: "Atrule",
+ prelude: null,
+ name: "page :right",
+ block: {
+ type: "Block",
+ loc: null,
+ children: childrenRight
+ }
+ });
+
+ ast.children.append(ruleRight);
+
+ }
+ }
+
+ getNth(nth) {
+ let n = nth.indexOf("n");
+ let plus = nth.indexOf("+");
+ let splitN = nth.split("n");
+ let splitP = nth.split("+");
+ let a = null;
+ let b = null;
+ if (n > -1) {
+ a = splitN[0];
+ if (plus > -1) {
+ b = splitP[1];
+ }
+ } else {
+ b = nth;
+ }
+
+ return {
+ type: "Nth",
+ loc: null,
+ selector: null,
+ nth: {
+ type: "AnPlusB",
+ loc: null,
+ a: a,
+ b: b
+ }
+ };
+ }
+
+ addPageAttributes(page, start, pages) {
+ let namedPages = [start.dataset.page];
+
+ if (namedPages && namedPages.length) {
+ for (const named of namedPages) {
+ if (!named) {
+ continue;
+ }
+ page.name = named;
+ page.element.classList.add("pagedjs_named_page");
+ page.element.classList.add("pagedjs_" + named + "_page");
+
+ if (!start.dataset.splitFrom) {
+ page.element.classList.add("pagedjs_" + named + "_first_page");
+ }
+ }
+ }
+ }
+
+ getStartElement(content, breakToken) {
+ let node = breakToken && breakToken.node;
+
+ if (!content && !breakToken) {
+ return;
+ }
+
+ // No break
+ if (!node) {
+ return content.children[0];
+ }
+
+ // Top level element
+ if (node.nodeType === 1 && node.parentNode.nodeType === 11) {
+ return node;
+ }
+
+ // Named page
+ if (node.nodeType === 1 && node.dataset.page) {
+ return node;
+ }
+
+ // Get top level Named parent
+ let fragment = rebuildAncestors(node);
+ let pages = fragment.querySelectorAll("[data-page]");
+
+ if (pages.length) {
+ return pages[pages.length - 1];
+ } else {
+ return fragment.children[0];
+ }
+ }
+
+ beforePageLayout(page, contents, breakToken, chunker) {
+ let start = this.getStartElement(contents, breakToken);
+ if (start) {
+ this.addPageAttributes(page, start, chunker.pages);
+ }
+ // page.element.querySelector('.paged_area').style.color = red;
+ }
+
+ finalizePage(fragment, page, breakToken, chunker) {
+ for (let m in this.marginalia) {
+ let margin = this.marginalia[m];
+ let sels = m.split(" ");
+
+ let content;
+ if (page.element.matches(sels[0]) && margin.hasContent) {
+ content = page.element.querySelector(sels[1]);
+ content.classList.add("hasContent");
+ }
+ }
+
+ // check center
+ ["top", "bottom"].forEach((loc) => {
+ let marginGroup = page.element.querySelector(".pagedjs_margin-" + loc);
+ let center = page.element.querySelector(".pagedjs_margin-" + loc + "-center");
+ let left = page.element.querySelector(".pagedjs_margin-" + loc + "-left");
+ let right = page.element.querySelector(".pagedjs_margin-" + loc + "-right");
+
+ let centerContent = center.classList.contains("hasContent");
+ let leftContent = left.classList.contains("hasContent");
+ let rightContent = right.classList.contains("hasContent");
+ let centerWidth, leftWidth, rightWidth;
+
+ if (leftContent) {
+ leftWidth = window.getComputedStyle(left)["max-width"];
+ }
+
+ if (rightContent) {
+ rightWidth = window.getComputedStyle(right)["max-width"];
+ }
+
+
+ if (centerContent) {
+ centerWidth = window.getComputedStyle(center)["max-width"];
+
+ if (centerWidth === "none" || centerWidth === "auto") {
+ if (!leftContent && !rightContent) {
+ marginGroup.style["grid-template-columns"] = "0 1fr 0";
+ } else if (leftContent) {
+ if (!rightContent) {
+ if (leftWidth !== "none" && leftWidth !== "auto") {
+ marginGroup.style["grid-template-columns"] = leftWidth + " 1fr " + leftWidth;
+ } else {
+ marginGroup.style["grid-template-columns"] = "auto auto 1fr";
+ left.style["white-space"] = "nowrap";
+ center.style["white-space"] = "nowrap";
+ let leftOuterWidth = left.offsetWidth;
+ let centerOuterWidth = center.offsetWidth;
+ let outerwidths = leftOuterWidth + centerOuterWidth;
+ let newcenterWidth = centerOuterWidth * 100 / outerwidths;
+ marginGroup.style["grid-template-columns"] = "minmax(16.66%, 1fr) minmax(33%, " + newcenterWidth + "%) minmax(16.66%, 1fr)";
+ left.style["white-space"] = "normal";
+ center.style["white-space"] = "normal";
+ }
+ } else {
+ if (leftWidth !== "none" && leftWidth !== "auto") {
+ if (rightWidth !== "none" && rightWidth !== "auto") {
+ marginGroup.style["grid-template-columns"] = leftWidth + " 1fr " + rightWidth;
+ } else {
+ marginGroup.style["grid-template-columns"] = leftWidth + " 1fr " + leftWidth;
+ }
+ } else {
+ if (rightWidth !== "none" && rightWidth !== "auto") {
+ marginGroup.style["grid-template-columns"] = rightWidth + " 1fr " + rightWidth;
+ } else {
+ marginGroup.style["grid-template-columns"] = "auto auto 1fr";
+ left.style["white-space"] = "nowrap";
+ center.style["white-space"] = "nowrap";
+ right.style["white-space"] = "nowrap";
+ let leftOuterWidth = left.offsetWidth;
+ let centerOuterWidth = center.offsetWidth;
+ let rightOuterWidth = right.offsetWidth;
+ let outerwidths = leftOuterWidth + centerOuterWidth + rightOuterWidth;
+ let newcenterWidth = centerOuterWidth * 100 / outerwidths;
+ if (newcenterWidth > 40) {
+ marginGroup.style["grid-template-columns"] = "minmax(16.66%, 1fr) minmax(33%, " + newcenterWidth + "%) minmax(16.66%, 1fr)";
+ } else {
+ marginGroup.style["grid-template-columns"] = "repeat(3, 1fr)";
+ }
+ left.style["white-space"] = "normal";
+ center.style["white-space"] = "normal";
+ right.style["white-space"] = "normal";
+ }
+ }
+ }
+ } else {
+ if (rightWidth !== "none" && rightWidth !== "auto") {
+ marginGroup.style["grid-template-columns"] = rightWidth + " 1fr " + rightWidth;
+ } else {
+ marginGroup.style["grid-template-columns"] = "auto auto 1fr";
+ right.style["white-space"] = "nowrap";
+ center.style["white-space"] = "nowrap";
+ let rightOuterWidth = right.offsetWidth;
+ let centerOuterWidth = center.offsetWidth;
+ let outerwidths = rightOuterWidth + centerOuterWidth;
+ let newcenterWidth = centerOuterWidth * 100 / outerwidths;
+ marginGroup.style["grid-template-columns"] = "minmax(16.66%, 1fr) minmax(33%, " + newcenterWidth + "%) minmax(16.66%, 1fr)";
+ right.style["white-space"] = "normal";
+ center.style["white-space"] = "normal";
+ }
+ }
+ } else if (centerWidth !== "none" && centerWidth !== "auto") {
+ if (leftContent && leftWidth !== "none" && leftWidth !== "auto") {
+ marginGroup.style["grid-template-columns"] = leftWidth + " " + centerWidth + " 1fr";
+ } else if (rightContent && rightWidth !== "none" && rightWidth !== "auto") {
+ marginGroup.style["grid-template-columns"] = "1fr " + centerWidth + " " + rightWidth;
+ } else {
+ marginGroup.style["grid-template-columns"] = "1fr " + centerWidth + " 1fr";
+ }
+
+ }
+
+ } else {
+ if (leftContent) {
+ if (!rightContent) {
+ marginGroup.style["grid-template-columns"] = "1fr 0 0";
+ } else {
+ if (leftWidth !== "none" && leftWidth !== "auto") {
+ if (rightWidth !== "none" && rightWidth !== "auto") {
+ marginGroup.style["grid-template-columns"] = leftWidth + " 1fr " + rightWidth;
+ } else {
+ marginGroup.style["grid-template-columns"] = leftWidth + " 0 1fr";
+ }
+ } else {
+ if (rightWidth !== "none" && rightWidth !== "auto") {
+ marginGroup.style["grid-template-columns"] = "1fr 0 " + rightWidth;
+ } else {
+ marginGroup.style["grid-template-columns"] = "auto 1fr auto";
+ left.style["white-space"] = "nowrap";
+ right.style["white-space"] = "nowrap";
+ let leftOuterWidth = left.offsetWidth;
+ let rightOuterWidth = right.offsetWidth;
+ let outerwidths = leftOuterWidth + rightOuterWidth;
+ let newLeftWidth = leftOuterWidth * 100 / outerwidths;
+ marginGroup.style["grid-template-columns"] = "minmax(16.66%, " + newLeftWidth + "%) 0 1fr";
+ left.style["white-space"] = "normal";
+ right.style["white-space"] = "normal";
+ }
+ }
+ }
+ } else {
+ if (rightWidth !== "none" && rightWidth !== "auto") {
+ marginGroup.style["grid-template-columns"] = "1fr 0 " + rightWidth;
+ } else {
+ marginGroup.style["grid-template-columns"] = "0 0 1fr";
+ }
+ }
+ }
+ });
+
+ // check middle
+ ["left", "right"].forEach((loc) => {
+ let middle = page.element.querySelector(".pagedjs_margin-" + loc + "-middle.hasContent");
+ let marginGroup = page.element.querySelector(".pagedjs_margin-" + loc);
+ let top = page.element.querySelector(".pagedjs_margin-" + loc + "-top");
+ let bottom = page.element.querySelector(".pagedjs_margin-" + loc + "-bottom");
+ let topContent = top.classList.contains("hasContent");
+ let bottomContent = bottom.classList.contains("hasContent");
+ let middleHeight, topHeight, bottomHeight;
+
+ if (topContent) {
+ topHeight = window.getComputedStyle(top)["max-height"];
+ }
+
+ if (bottomContent) {
+ bottomHeight = window.getComputedStyle(bottom)["max-height"];
+ }
+
+ if (middle) {
+ middleHeight = window.getComputedStyle(middle)["max-height"];
+
+ if (middleHeight === "none" || middleHeight === "auto") {
+ if (!topContent && !bottomContent) {
+ marginGroup.style["grid-template-rows"] = "0 1fr 0";
+ } else if (topContent) {
+ if (!bottomContent) {
+ if (topHeight !== "none" && topHeight !== "auto") {
+ marginGroup.style["grid-template-rows"] = topHeight + " calc(100% - " + topHeight + "*2) " + topHeight;
+ }
+ } else {
+ if (topHeight !== "none" && topHeight !== "auto") {
+ if (bottomHeight !== "none" && bottomHeight !== "auto") {
+ marginGroup.style["grid-template-rows"] = topHeight + " calc(100% - " + topHeight + " - " + bottomHeight + ") " + bottomHeight;
+ } else {
+ marginGroup.style["grid-template-rows"] = topHeight + " calc(100% - " + topHeight + "*2) " + topHeight;
+ }
+ } else {
+ if (bottomHeight !== "none" && bottomHeight !== "auto") {
+ marginGroup.style["grid-template-rows"] = bottomHeight + " calc(100% - " + bottomHeight + "*2) " + bottomHeight;
+ }
+ }
+ }
+ } else {
+ if (bottomHeight !== "none" && bottomHeight !== "auto") {
+ marginGroup.style["grid-template-rows"] = bottomHeight + " calc(100% - " + bottomHeight + "*2) " + bottomHeight;
+ }
+ }
+ } else {
+ if (topContent && topHeight !== "none" && topHeight !== "auto") {
+ marginGroup.style["grid-template-rows"] = topHeight + " " + middleHeight + " calc(100% - (" + topHeight + " + " + middleHeight + "))";
+ } else if (bottomContent && bottomHeight !== "none" && bottomHeight !== "auto") {
+ marginGroup.style["grid-template-rows"] = "1fr " + middleHeight + " " + bottomHeight;
+ } else {
+ marginGroup.style["grid-template-rows"] = "calc((100% - " + middleHeight + ")/2) " + middleHeight + " calc((100% - " + middleHeight + ")/2)";
+ }
+
+ }
+
+ } else {
+ if (topContent) {
+ if (!bottomContent) {
+ marginGroup.style["grid-template-rows"] = "1fr 0 0";
+ } else {
+ if (topHeight !== "none" && topHeight !== "auto") {
+ if (bottomHeight !== "none" && bottomHeight !== "auto") {
+ marginGroup.style["grid-template-rows"] = topHeight + " 1fr " + bottomHeight;
+ } else {
+ marginGroup.style["grid-template-rows"] = topHeight + " 0 1fr";
+ }
+ } else {
+ if (bottomHeight !== "none" && bottomHeight !== "auto") {
+ marginGroup.style["grid-template-rows"] = "1fr 0 " + bottomHeight;
+ } else {
+ marginGroup.style["grid-template-rows"] = "1fr 0 1fr";
+ }
+ }
+ }
+ } else {
+ if (bottomHeight !== "none" && bottomHeight !== "auto") {
+ marginGroup.style["grid-template-rows"] = "1fr 0 " + bottomHeight;
+ } else {
+ marginGroup.style["grid-template-rows"] = "0 0 1fr";
+ }
+ }
+ }
+
+
+
+ });
+
+ }
+
+ // CSS Tree Helpers
+
+ selectorsForPage(page) {
+ let nthlist;
+ let nth;
+
+ let selectors = new csstree.List();
+
+ selectors.insertData({
+ type: "ClassSelector",
+ name: "pagedjs_page"
+ });
+
+ // Named page
+ if (page.name) {
+ selectors.insertData({
+ type: "ClassSelector",
+ name: "pagedjs_named_page"
+ });
+
+ selectors.insertData({
+ type: "ClassSelector",
+ name: "pagedjs_" + page.name + "_page"
+ });
+ }
+
+ // PsuedoSelector
+ if (page.psuedo && !(page.name && page.psuedo === "first")) {
+ selectors.insertData({
+ type: "ClassSelector",
+ name: "pagedjs_" + page.psuedo + "_page"
+ });
+ }
+
+ if (page.name && page.psuedo === "first") {
+ selectors.insertData({
+ type: "ClassSelector",
+ name: "pagedjs_" + page.name + "_" + page.psuedo + "_page"
+ });
+ }
+
+ // Nth
+ if (page.nth) {
+ nthlist = new csstree.List();
+ nth = this.getNth(page.nth);
+
+ nthlist.insertData(nth);
+
+ selectors.insertData({
+ type: "PseudoClassSelector",
+ name: "nth-of-type",
+ children: nthlist
+ });
+ }
+
+ return selectors;
+ }
+
+ selectorsForPageMargin(page, margin) {
+ let selectors = this.selectorsForPage(page);
+
+ selectors.insertData({
+ type: "Combinator",
+ name: " "
+ });
+
+ selectors.insertData({
+ type: "ClassSelector",
+ name: "pagedjs_margin-" + margin
+ });
+
+ return selectors;
+ }
+
+ createDeclaration(property, value, important) {
+ let children = new csstree.List();
+
+ children.insertData({
+ type: "Identifier",
+ loc: null,
+ name: value
+ });
+
+ return {
+ type: "Declaration",
+ loc: null,
+ important: important,
+ property: property,
+ value: {
+ type: "Value",
+ loc: null,
+ children: children
+ }
+ };
+ }
+
+ createVariable(property, value) {
+ return {
+ type: "Declaration",
+ loc: null,
+ property: property,
+ value: {
+ type: "Raw",
+ value: value
+ }
+ };
+ }
+
+ createCalculatedDimension(property, items, important, operator = "+") {
+ let children = new csstree.List();
+ let calculations = new csstree.List();
+
+ items.forEach((item, index) => {
+ calculations.appendData({
+ type: "Dimension",
+ unit: item.unit,
+ value: item.value
+ });
+
+ calculations.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ if (index + 1 < items.length) {
+ calculations.appendData({
+ type: "Operator",
+ value: operator
+ });
+
+ calculations.appendData({
+ type: "WhiteSpace",
+ value: " "
+ });
+ }
+ });
+
+ children.insertData({
+ type: "Function",
+ loc: null,
+ name: "calc",
+ children: calculations
+ });
+
+ return {
+ type: "Declaration",
+ loc: null,
+ important: important,
+ property: property,
+ value: {
+ type: "Value",
+ loc: null,
+ children: children
+ }
+ };
+ }
+
+ createDimension(property, cssValue, important) {
+ let children = new csstree.List();
+
+ children.insertData({
+ type: "Dimension",
+ loc: null,
+ value: cssValue.value,
+ unit: cssValue.unit
+ });
+
+ return {
+ type: "Declaration",
+ loc: null,
+ important: important,
+ property: property,
+ value: {
+ type: "Value",
+ loc: null,
+ children: children
+ }
+ };
+ }
+
+ createBlock(declarations) {
+ let block = new csstree.List();
+
+ declarations.forEach((declaration) => {
+ block.insertData(declaration);
+ });
+
+ return {
+ type: "Block",
+ loc: null,
+ children: block
+ };
+ }
+
+ createRule(selectors, block) {
+ let selectorList = new csstree.List();
+ selectorList.insertData({
+ type: "Selector",
+ children: selectors
+ });
+
+ if (Array.isArray(block)) {
+ block = this.createBlock(block);
+ }
+
+ return {
+ type: "Rule",
+ prelude: {
+ type: "SelectorList",
+ children: selectorList
+ },
+ block: block
+ };
+ }
+
+ }
+
+ class Breaks extends Handler {
+ constructor(chunker, polisher, caller) {
+ super(chunker, polisher, caller);
+
+ this.breaks = {};
+ }
+
+ onDeclaration(declaration, dItem, dList, rule) {
+ let property = declaration.property;
+
+ if (property === "page") {
+ let children = declaration.value.children.first();
+ let value = children.name;
+ let selector = csstree.generate(rule.ruleNode.prelude);
+ let name = value;
+
+ let breaker = {
+ property: property,
+ value: value,
+ selector: selector,
+ name: name
+ };
+
+ selector.split(",").forEach((s) => {
+ if (!this.breaks[s]) {
+ this.breaks[s] = [breaker];
+ } else {
+ this.breaks[s].push(breaker);
+ }
+ });
+
+ dList.remove(dItem);
+ }
+
+ if (property === "break-before" ||
+ property === "break-after" ||
+ property === "page-break-before" ||
+ property === "page-break-after"
+ ) {
+ let child = declaration.value.children.first();
+ let value = child.name;
+ let selector = csstree.generate(rule.ruleNode.prelude);
+
+ if (property === "page-break-before") {
+ property = "break-before";
+ } else if (property === "page-break-after") {
+ property = "break-after";
+ }
+
+ let breaker = {
+ property: property,
+ value: value,
+ selector: selector
+ };
+
+ selector.split(",").forEach((s) => {
+ if (!this.breaks[s]) {
+ this.breaks[s] = [breaker];
+ } else {
+ this.breaks[s].push(breaker);
+ }
+ });
+
+ // Remove from CSS -- handle right / left in module
+ dList.remove(dItem);
+ }
+ }
+
+ afterParsed(parsed) {
+ this.processBreaks(parsed, this.breaks);
+ }
+
+ processBreaks(parsed, breaks) {
+ for (let b in breaks) {
+ // Find elements
+ let elements = parsed.querySelectorAll(b);
+ // Add break data
+ for (var i = 0; i < elements.length; i++) {
+ for (let prop of breaks[b]) {
+
+ if (prop.property === "break-after") {
+ let nodeAfter = displayedElementAfter(elements[i], parsed);
+
+ elements[i].setAttribute("data-break-after", prop.value);
+
+ if (nodeAfter) {
+ nodeAfter.setAttribute("data-previous-break-after", prop.value);
+ }
+ } else if (prop.property === "break-before") {
+ let nodeBefore = displayedElementBefore(elements[i], parsed);
+
+ // Breaks are only allowed between siblings, not between a box and its container.
+ // If we cannot find a node before we should not break!
+ // https://drafts.csswg.org/css-break-3/#break-propagation
+ if (nodeBefore) {
+ if (prop.value === "page" && needsPageBreak(elements[i], nodeBefore)) {
+ // we ignore this explicit page break because an implicit page break is already needed
+ continue;
+ }
+ elements[i].setAttribute("data-break-before", prop.value);
+ nodeBefore.setAttribute("data-next-break-before", prop.value);
+ }
+ } else if (prop.property === "page") {
+ elements[i].setAttribute("data-page", prop.value);
+
+ let nodeAfter = displayedElementAfter(elements[i], parsed);
+
+ if (nodeAfter) {
+ nodeAfter.setAttribute("data-after-page", prop.value);
+ }
+ } else {
+ elements[i].setAttribute("data-" + prop.property, prop.value);
+ }
+ }
+ }
+ }
+ }
+
+ mergeBreaks(pageBreaks, newBreaks) {
+ for (let b in newBreaks) {
+ if (b in pageBreaks) {
+ pageBreaks[b] = pageBreaks[b].concat(newBreaks[b]);
+ } else {
+ pageBreaks[b] = newBreaks[b];
+ }
+ }
+ return pageBreaks;
+ }
+
+ addBreakAttributes(pageElement, page) {
+ let before = pageElement.querySelector("[data-break-before]");
+ let after = pageElement.querySelector("[data-break-after]");
+ let previousBreakAfter = pageElement.querySelector("[data-previous-break-after]");
+
+ if (before) {
+ if (before.dataset.splitFrom) {
+ page.splitFrom = before.dataset.splitFrom;
+ pageElement.setAttribute("data-split-from", before.dataset.splitFrom);
+ } else if (before.dataset.breakBefore && before.dataset.breakBefore !== "avoid") {
+ page.breakBefore = before.dataset.breakBefore;
+ pageElement.setAttribute("data-break-before", before.dataset.breakBefore);
+ }
+ }
+
+ if (after && after.dataset) {
+ if (after.dataset.splitTo) {
+ page.splitTo = after.dataset.splitTo;
+ pageElement.setAttribute("data-split-to", after.dataset.splitTo);
+ } else if (after.dataset.breakAfter && after.dataset.breakAfter !== "avoid") {
+ page.breakAfter = after.dataset.breakAfter;
+ pageElement.setAttribute("data-break-after", after.dataset.breakAfter);
+ }
+ }
+
+ if (previousBreakAfter && previousBreakAfter.dataset) {
+ if (previousBreakAfter.dataset.previousBreakAfter && previousBreakAfter.dataset.previousBreakAfter !== "avoid") {
+ page.previousBreakAfter = previousBreakAfter.dataset.previousBreakAfter;
+ }
+ }
+ }
+
+ afterPageLayout(pageElement, page) {
+ this.addBreakAttributes(pageElement, page);
+ }
+ }
+
+ class PrintMedia extends Handler {
+ constructor(chunker, polisher, caller) {
+ super(chunker, polisher, caller);
+ }
+
+ onAtMedia(node, item, list) {
+ let media = this.getMediaName(node);
+ let rules;
+ if (media.includes("print")) {
+ rules = node.block.children;
+
+ // Append rules to the end of main rules list
+ // TODO: this isn't working right, needs to check what is in the prelude
+ /*
+ rules.forEach((selectList) => {
+ if (selectList.prelude) {
+ selectList.prelude.children.forEach((rule) => {
+
+ rule.children.prependData({
+ type: "Combinator",
+ name: " "
+ });
+
+ rule.children.prependData({
+ type: "ClassSelector",
+ name: "pagedjs_page"
+ });
+ });
+ }
+ });
+
+ list.insertList(rules, item);
+ */
+
+ // Append rules to the end of main rules list
+ list.appendList(rules);
+
+ // Remove rules from the @media block
+ list.remove(item);
+ } else if (!media.includes("all") && !media.includes("pagedjs-ignore")) {
+ list.remove(item);
+ }
+
+ }
+
+ getMediaName(node) {
+ let media = [];
+
+ if (typeof node.prelude === "undefined" ||
+ node.prelude.type !== "AtrulePrelude" ) {
+ return;
+ }
+
+ csstree.walk(node.prelude, {
+ visit: "Identifier",
+ enter: (identNode, iItem, iList) => {
+ media.push(identNode.name);
+ }
+ });
+ return media;
+ }
+
+
+ }
+
+ class Splits extends Handler {
+ constructor(chunker, polisher, caller) {
+ super(chunker, polisher, caller);
+ }
+
+ afterPageLayout(pageElement, page, breakToken, chunker) {
+ let splits = Array.from(pageElement.querySelectorAll("[data-split-from]"));
+ let pages = pageElement.parentNode;
+ let index = Array.prototype.indexOf.call(pages.children, pageElement);
+ let prevPage;
+
+ if (index === 0) {
+ return;
+ }
+
+ prevPage = pages.children[index - 1];
+
+ let from; // Capture the last from element
+ splits.forEach((split) => {
+ let ref = split.dataset.ref;
+ from = prevPage.querySelector("[data-ref='"+ ref +"']:not([data-split-to])");
+
+ if (from) {
+ from.dataset.splitTo = ref;
+
+ if (!from.dataset.splitFrom) {
+ from.dataset.splitOriginal = true;
+ }
+ }
+ });
+
+ // Fix alignment on the deepest split element
+ if (from) {
+ this.handleAlignment(from);
+ }
+ }
+
+ handleAlignment(node) {
+ let styles = window.getComputedStyle(node);
+ let align = styles["text-align"];
+ let alignLast = styles["text-align-last"];
+ node.dataset.lastSplitElement = "true";
+ if (align === "justify" && alignLast === "auto") {
+ node.dataset.alignLastSplitElement = "justify";
+ } else {
+ node.dataset.alignLastSplitElement = alignLast;
+ }
+ }
+
+ }
+
+ class Counters extends Handler {
+ constructor(chunker, polisher, caller) {
+ super(chunker, polisher, caller);
+
+ this.styleSheet = polisher.styleSheet;
+ this.counters = {};
+ this.resetCountersMap = new Map();
+ }
+
+ onDeclaration(declaration, dItem, dList, rule) {
+ let property = declaration.property;
+
+ if (property === "counter-increment") {
+ this.handleIncrement(declaration, rule);
+ // clean up empty declaration
+ let hasProperities = false;
+ declaration.value.children.forEach((data) => {
+ if (data.type && data.type !== "WhiteSpace") {
+ hasProperities = true;
+ }
+ });
+ if (!hasProperities) {
+ dList.remove(dItem);
+ }
+ } else if (property === "counter-reset") {
+ this.handleReset(declaration, rule);
+ // clean up empty declaration
+ let hasProperities = false;
+ declaration.value.children.forEach((data) => {
+ if (data.type && data.type !== "WhiteSpace") {
+ hasProperities = true;
+ }
+ });
+ if (!hasProperities) {
+ dList.remove(dItem);
+ }
+ }
+ }
+
+ afterParsed(parsed) {
+ this.processCounters(parsed, this.counters);
+ this.scopeCounters(this.counters);
+ }
+
+ addCounter(name) {
+ if (name in this.counters) {
+ return this.counters[name];
+ }
+
+ this.counters[name] = {
+ name: name,
+ increments: {},
+ resets: {}
+ };
+
+ return this.counters[name];
+ }
+
+ handleIncrement(declaration, rule) {
+ let increments = [];
+ let children = declaration.value.children;
+
+ children.forEach((data, item) => {
+ if (data.type && data.type === "Identifier") {
+ let name = data.name;
+
+ if (name === "page" || name.indexOf("target-counter-") === 0) {
+ return;
+ }
+
+ let whitespace, number, value;
+ if (item.next && item.next.data.type === "WhiteSpace") {
+ whitespace = item.next;
+ }
+ if (whitespace && whitespace.next && whitespace.next.data.type === "Number") {
+ number = whitespace.next;
+ value = parseInt(number.data.value);
+ }
+
+ let selector = csstree.generate(rule.ruleNode.prelude);
+
+ let counter;
+ if (!(name in this.counters)) {
+ counter = this.addCounter(name);
+ } else {
+ counter = this.counters[name];
+ }
+ let increment = {
+ selector: selector,
+ number: value || 1
+ };
+ counter.increments[selector] = increment;
+ increments.push(increment);
+
+ // Remove the parsed resets
+ children.remove(item);
+ if (whitespace) {
+ children.remove(whitespace);
+ }
+ if (number) {
+ children.remove(number);
+ }
+ }
+ });
+
+ return increments;
+ }
+
+ handleReset(declaration, rule) {
+ let children = declaration.value.children;
+
+ children.forEach((data, item) => {
+ if (data.type && data.type === "Identifier") {
+ let name = data.name;
+ let whitespace, number, value;
+ if (item.next && item.next.data.type === "WhiteSpace") {
+ whitespace = item.next;
+ }
+ if (whitespace && whitespace.next) {
+ if (whitespace.next.data.type === "Number") {
+ // The counter reset value is specified using a number. E.g. counter-reset: c2 5;
+ number = whitespace.next;
+ value = parseInt(number.data.value);
+ } else if (whitespace.next.data.type === "Function" && whitespace.next.data.name === "var") {
+ // The counter reset value is specified using a CSS variable (custom property).
+ // E.g. counter-reset: c2 var(--my-variable);
+ // See https://developer.mozilla.org/en-US/docs/Web/CSS/var
+ number = whitespace.next;
+ // Use the variable name (e.g. '--my-variable') as value for now. The actual value is resolved later by the
+ // processCounterResets function.
+ value = whitespace.next.data.children.head.data.name;
+ }
+ }
+
+ let counter;
+ let selector;
+ let prelude = rule.ruleNode.prelude;
+
+ if (rule.ruleNode.type === "Atrule" && rule.ruleNode.name === "page") {
+ selector = ".pagedjs_page";
+ } else {
+ selector = csstree.generate(prelude || rule.ruleNode);
+ }
+
+ if (name === "footnote") {
+ this.addFootnoteMarkerCounter(declaration.value.children);
+ }
+
+ if (!(name in this.counters)) {
+ counter = this.addCounter(name);
+ } else {
+ counter = this.counters[name];
+ }
+
+ let reset = {
+ selector: selector,
+ number: value || 0
+ };
+
+ counter.resets[selector] = reset;
+
+ if (selector !== ".pagedjs_page") {
+ // Remove the parsed resets
+ children.remove(item);
+ if (whitespace) {
+ children.remove(whitespace);
+ }
+ if (number) {
+ children.remove(number);
+ }
+ }
+ }
+ });
+ }
+
+ processCounters(parsed, counters) {
+ let counter;
+ for (let c in counters) {
+ counter = this.counters[c];
+ this.processCounterIncrements(parsed, counter);
+ this.processCounterResets(parsed, counter);
+ if (c !== "page") {
+ this.addCounterValues(parsed, counter);
+ }
+ }
+ }
+
+ scopeCounters(counters) {
+ let countersArray = [];
+ for (let c in counters) {
+ if(c !== "page") {
+ countersArray.push(`${counters[c].name} 0`);
+ }
+ }
+ // Add to pages to allow cross page scope
+ this.insertRule(`.pagedjs_pages { counter-reset: ${countersArray.join(" ")} page 0 pages var(--pagedjs-page-count) footnote var(--pagedjs-footnotes-count) footnote-marker var(--pagedjs-footnotes-count)}`);
+ }
+
+ insertRule(rule) {
+ this.styleSheet.insertRule(rule, this.styleSheet.cssRules.length);
+ }
+
+ processCounterIncrements(parsed, counter) {
+ let increment;
+ for (let inc in counter.increments) {
+ increment = counter.increments[inc];
+ // Find elements for increments
+ let incrementElements = parsed.querySelectorAll(increment.selector);
+ // Add counter data
+ for (let i = 0; i < incrementElements.length; i++) {
+ incrementElements[i].setAttribute("data-counter-"+ counter.name +"-increment", increment.number);
+ if (incrementElements[i].getAttribute("data-counter-increment")) {
+ incrementElements[i].setAttribute("data-counter-increment", incrementElements[i].getAttribute("data-counter-increment") + " " + counter.name);
+ } else {
+ incrementElements[i].setAttribute("data-counter-increment", counter.name);
+ }
+ }
+ }
+ }
+
+ processCounterResets(parsed, counter) {
+ let reset;
+ for (let r in counter.resets) {
+ reset = counter.resets[r];
+ // Find elements for resets
+ let resetElements = parsed.querySelectorAll(reset.selector);
+ // Add counter data
+ for (var i = 0; i < resetElements.length; i++) {
+ let value = reset.number;
+ if (typeof value === "string" && value.startsWith("--")) {
+ // The value is specified using a CSS variable (custom property).
+ // FIXME: We get the variable value only from the inline style of the element because at this point the
+ // element is detached and thus using:
+ //
+ // getComputedStyle(resetElements[i]).getPropertyValue(value)
+ //
+ // always returns an empty string. We could try to temporarily attach the element to get its computed style,
+ // but for now using the inline style is enough for us.
+ value = resetElements[i].style.getPropertyValue(value) || 0;
+ }
+ resetElements[i].setAttribute("data-counter-"+ counter.name +"-reset", value);
+ if (resetElements[i].getAttribute("data-counter-reset")) {
+ resetElements[i].setAttribute("data-counter-reset", resetElements[i].getAttribute("data-counter-reset") + " " + counter.name);
+ } else {
+ resetElements[i].setAttribute("data-counter-reset", counter.name);
+ }
+ }
+ }
+ }
+
+ addCounterValues(parsed, counter) {
+ let counterName = counter.name;
+
+ if (counterName === "page" || counterName === "footnote") {
+ return;
+ }
+
+ let elements = parsed.querySelectorAll("[data-counter-"+ counterName +"-reset], [data-counter-"+ counterName +"-increment]");
+
+ let count = 0;
+ let element;
+ let increment, reset;
+ let resetValue, incrementValue, resetDelta;
+ let incrementArray;
+
+ for (let i = 0; i < elements.length; i++) {
+ element = elements[i];
+ resetDelta = 0;
+ incrementArray = [];
+
+ if (element.hasAttribute("data-counter-"+ counterName +"-reset")) {
+ reset = element.getAttribute("data-counter-"+ counterName +"-reset");
+ resetValue = parseInt(reset);
+
+ // Use negative increment value inplace of reset
+ resetDelta = resetValue - count;
+ incrementArray.push(`${counterName} ${resetDelta}`);
+
+ count = resetValue;
+ }
+
+ if (element.hasAttribute("data-counter-"+ counterName +"-increment")) {
+
+ increment = element.getAttribute("data-counter-"+ counterName +"-increment");
+ incrementValue = parseInt(increment);
+
+ count += incrementValue;
+
+ element.setAttribute("data-counter-"+counterName+"-value", count);
+
+ incrementArray.push(`${counterName} ${incrementValue}`);
+ }
+
+ if (incrementArray.length > 0) {
+ this.incrementCounterForElement(element, incrementArray);
+ }
+
+ }
+ }
+
+ addFootnoteMarkerCounter(list) {
+ let markers = [];
+ csstree.walk(list, {
+ visit: "Identifier",
+ enter: (identNode, iItem, iList) => {
+ markers.push(identNode.name);
+ }
+ });
+
+ // Already added
+ if (markers.includes("footnote-maker")) {
+ return;
+ }
+
+ list.insertData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ list.insertData({
+ type: "Identifier",
+ name: "footnote-marker"
+ });
+
+ list.insertData({
+ type: "WhiteSpace",
+ value: " "
+ });
+
+ list.insertData({
+ type: "Number",
+ value: 0
+ });
+ }
+
+ incrementCounterForElement(element, incrementArray) {
+ if (!element || !incrementArray || incrementArray.length === 0) return;
+
+ const ref = element.dataset.ref;
+ const increments = Array.from(this.styleSheet.cssRules).filter((rule) => {
+ return rule.selectorText === `[data-ref="${element.dataset.ref}"]:not([data-split-from])`
+ && rule.style[0] === "counter-increment";
+ }).map(rule => rule.style.counterIncrement);
+
+ // Merge the current increments by summing the values because we generate both a decrement and an increment when the
+ // element resets and increments the counter at the same time. E.g. ['c1 -7', 'c1 1'] should lead to 'c1 -6'.
+ increments.push(this.mergeIncrements(incrementArray,
+ (prev, next) => (parseInt(prev) || 0) + (parseInt(next) || 0)));
+
+ // Keep the last value for each counter when merging with the previous increments. E.g. ['c1 -7 c2 3', 'c1 1']
+ // should lead to 'c1 1 c2 3'.
+ const counterIncrement = this.mergeIncrements(increments, (prev, next) => next);
+ this.insertRule(`[data-ref="${ref}"]:not([data-split-from]) { counter-increment: ${counterIncrement} }`);
+ }
+
+ /**
+ * Merge multiple values of a counter-increment CSS rule, using the specified operator.
+ *
+ * @param {Array} incrementArray the values to merge, e.g. ['c1 1', 'c1 -7 c2 1']
+ * @param {Function} operator the function used to merge counter values (e.g. keep the last value of a counter or sum
+ * the counter values)
+ * @return {string} the merged value of the counter-increment CSS rule
+ */
+ mergeIncrements(incrementArray, operator) {
+ const increments = {};
+ incrementArray.forEach(increment => {
+ let values = increment.split(" ");
+ for (let i = 0; i < values.length; i+=2) {
+ increments[values[i]] = operator(increments[values[i]], values[i + 1]);
+ }
+ });
+
+ return Object.entries(increments).map(([key, value]) => `${key} ${value}`).join(" ");
+ }
+
+ afterPageLayout(pageElement, page) {
+ let resets = [];
+
+ let pgreset = pageElement.querySelectorAll("[data-counter-page-reset]:not([data-split-from])");
+ pgreset.forEach((reset) => {
+ const ref = reset.dataset && reset.dataset.ref;
+ if (ref && this.resetCountersMap.has(ref)) ; else {
+ if (ref) {
+ this.resetCountersMap.set(ref, "");
+ }
+ let value = reset.dataset.counterPageReset;
+ resets.push(`page ${value}`);
+ }
+ });
+
+ let notereset = pageElement.querySelectorAll("[data-counter-footnote-reset]:not([data-split-from])");
+ notereset.forEach((reset) => {
+ let value = reset.dataset.counterFootnoteReset;
+ resets.push(`footnote ${value}`);
+ resets.push(`footnote-marker ${value}`);
+ });
+
+ if (resets.length) {
+ this.styleSheet.insertRule(`[data-page-number="${pageElement.dataset.pageNumber}"] { counter-increment: none; counter-reset: ${resets.join(" ")} }`, this.styleSheet.cssRules.length);
+ }
+ }
+
+ }
+
+ class Lists extends Handler {
+ constructor(chunker, polisher, caller) {
+ super(chunker, polisher, caller);
+ }
+ afterParsed(content) {
+ const orderedLists = content.querySelectorAll("ol");
+
+ for (var list of orderedLists) {
+ this.addDataNumbers(list);
+ }
+ }
+
+ afterPageLayout(pageElement, page, breakToken, chunker) {
+ var orderedLists = pageElement.getElementsByTagName("ol");
+ for (var list of orderedLists) {
+ if (list.firstElementChild) {
+ list.start = list.firstElementChild.dataset.itemNum;
+ }
+ }
+ }
+
+ addDataNumbers(list) {
+ let start = 1;
+ if (list.hasAttribute("start")) {
+ start = parseInt(list.getAttribute("start"), 10);
+ if (isNaN(start)) {
+ start = 1;
+ }
+ }
+ let items = list.children;
+ for (var i = 0; i < items.length; i++) {
+ items[i].setAttribute("data-item-num", i + start);
+ }
+ }
+
+ }
+
+ class PositionFixed extends Handler {
+ constructor(chunker, polisher, caller) {
+ super(chunker, polisher, caller);
+ this.styleSheet = polisher.styleSheet;
+ this.fixedElementsSelector = [];
+ this.fixedElements = [];
+ }
+
+ onDeclaration(declaration, dItem, dList, rule) {
+ if (declaration.property === "position" && declaration.value.children.first().name === "fixed") {
+ let selector = csstree.generate(rule.ruleNode.prelude);
+ this.fixedElementsSelector.push(selector);
+ dList.remove(dItem);
+ }
+ }
+
+ afterParsed(fragment) {
+ this.fixedElementsSelector.forEach(fixedEl => {
+ fragment.querySelectorAll(`${fixedEl}`).forEach(el => {
+ el.style.setProperty("position", "absolute");
+ this.fixedElements.push(el);
+ el.remove();
+ });
+ });
+ }
+
+ afterPageLayout(pageElement, page, breakToken) {
+ this.fixedElements.forEach(el => {
+ const clone = el.cloneNode(true);
+ pageElement.querySelector(".pagedjs_pagebox").insertAdjacentElement("afterbegin", clone);
+ });
+ }
+ }
+
+ class PageCounterIncrement extends Handler {
+ constructor(chunker, polisher, caller) {
+ super(chunker, polisher, caller);
+
+ this.styleSheet = polisher.styleSheet;
+ this.pageCounter = {
+ name: "page",
+ increments: {},
+ resets: {}
+ };
+ }
+
+ onDeclaration(declaration, dItem, dList, rule) {
+ const property = declaration.property;
+
+ if (property === "counter-increment") {
+ let inc = this.handleIncrement(declaration, rule);
+ if (inc) {
+ dList.remove(dItem);
+ }
+ }
+ }
+
+ afterParsed(_) {
+ for (const inc in this.pageCounter.increments) {
+ const increment = this.pageCounter.increments[inc];
+ this.insertRule(`${increment.selector} { --pagedjs-page-counter-increment: ${increment.number} }`);
+ }
+ }
+
+ handleIncrement(declaration, rule) {
+ const identifier = declaration.value.children.first();
+ const number = declaration.value.children.getSize() > 1 ? declaration.value.children.last().value : 1;
+ const name = identifier && identifier.name;
+
+ if (name && name.indexOf("target-counter-") === 0) {
+ return;
+ }
+ // A counter named page is automatically created and incremented by 1 on every page of the document,
+ // unless the counter-increment property in the page context explicitly specifies a different increment for the page counter.
+ // https://www.w3.org/TR/css-page-3/#page-based-counters
+ if (name !== "page") {
+ return;
+ }
+ // the counter-increment property is not defined on the page context (i.e. @page rule), ignoring...
+ if (rule.ruleNode.name === "page" && rule.ruleNode.type === "Atrule") {
+ return;
+ }
+ const selector = csstree.generate(rule.ruleNode.prelude);
+ return this.pageCounter.increments[selector] = {
+ selector: selector,
+ number
+ };
+ }
+
+ insertRule(rule) {
+ this.styleSheet.insertRule(rule, this.styleSheet.cssRules.length);
+ }
+ }
+
+ class NthOfType extends Handler {
+ constructor(chunker, polisher, caller) {
+ super(chunker, polisher, caller);
+
+ this.styleSheet = polisher.styleSheet;
+ this.selectors = {};
+ }
+
+ onRule(ruleNode, ruleItem, rulelist) {
+ let selector = csstree.generate(ruleNode.prelude);
+ if (selector.match(/:(first|last|nth)-of-type/)) {
+
+ let declarations = csstree.generate(ruleNode.block);
+ declarations = declarations.replace(/[{}]/g,"");
+
+ let uuid = "nth-of-type-" + UUID();
+
+ selector.split(",").forEach((s) => {
+ if (!this.selectors[s]) {
+ this.selectors[s] = [uuid, declarations];
+ } else {
+ this.selectors[s][1] = `${this.selectors[s][1]};${declarations}` ;
+ }
+ });
+
+ rulelist.remove(ruleItem);
+ }
+ }
+
+ afterParsed(parsed) {
+ this.processSelectors(parsed, this.selectors);
+ }
+
+ processSelectors(parsed, selectors) {
+ // add the new attributes to matching elements
+ for (let s in selectors) {
+ let elements = parsed.querySelectorAll(s);
+
+ for (var i = 0; i < elements.length; i++) {
+ let dataNthOfType = elements[i].getAttribute("data-nth-of-type");
+
+ if (dataNthOfType && dataNthOfType != "") {
+ dataNthOfType = `${dataNthOfType},${selectors[s][0]}`;
+ elements[i].setAttribute("data-nth-of-type", dataNthOfType);
+ } else {
+ elements[i].setAttribute("data-nth-of-type", selectors[s][0]);
+ }
+ }
+
+ let rule = `*[data-nth-of-type*='${selectors[s][0]}'] { ${selectors[s][1]}; }`;
+ this.styleSheet.insertRule(rule, this.styleSheet.cssRules.length);
+ }
+ }
+ }
+
+ class Following extends Handler {
+ constructor(chunker, polisher, caller) {
+ super(chunker, polisher, caller);
+
+ this.styleSheet = polisher.styleSheet;
+ this.selectors = {};
+ }
+
+ onRule(ruleNode, ruleItem, rulelist) {
+ let selector = csstree.generate(ruleNode.prelude);
+ if (selector.match(/\+/)) {
+
+ let declarations = csstree.generate(ruleNode.block);
+ declarations = declarations.replace(/[{}]/g,"");
+
+ let uuid = "following-" + UUID();
+
+ selector.split(",").forEach((s) => {
+ if (!this.selectors[s]) {
+ this.selectors[s] = [uuid, declarations];
+ } else {
+ this.selectors[s][1] = `${this.selectors[s][1]};${declarations}` ;
+ }
+ });
+
+ rulelist.remove(ruleItem);
+ }
+ }
+
+ afterParsed(parsed) {
+ this.processSelectors(parsed, this.selectors);
+ }
+
+ processSelectors(parsed, selectors) {
+ // add the new attributes to matching elements
+ for (let s in selectors) {
+ let elements = parsed.querySelectorAll(s);
+
+ for (var i = 0; i < elements.length; i++) {
+ let dataFollowing = elements[i].getAttribute("data-following");
+
+ if (dataFollowing && dataFollowing != "") {
+ dataFollowing = `${dataFollowing},${selectors[s][0]}`;
+ elements[i].setAttribute("data-following", dataFollowing);
+ } else {
+ elements[i].setAttribute("data-following", selectors[s][0]);
+ }
+ }
+
+ let rule = `*[data-following*='${selectors[s][0]}'] { ${selectors[s][1]}; }`;
+ this.styleSheet.insertRule(rule, this.styleSheet.cssRules.length);
+ }
+ }
+ }
+
+ class Footnotes extends Handler {
+ constructor(chunker, polisher, caller) {
+ super(chunker, polisher, caller);
+
+ this.footnotes = {};
+ this.needsLayout = [];
+ }
+
+ onDeclaration(declaration, dItem, dList, rule) {
+ let property = declaration.property;
+ if (property === "float") {
+ let identifier = declaration.value.children && declaration.value.children.first();
+ let location = identifier && identifier.name;
+ if (location === "footnote") {
+ let selector = csstree.generate(rule.ruleNode.prelude);
+ this.footnotes[selector] = {
+ selector: selector,
+ policy: "auto",
+ display: "block"
+ };
+ dList.remove(dItem);
+ }
+ }
+ if (property === "footnote-policy") {
+ let identifier = declaration.value.children && declaration.value.children.first();
+ let policy = identifier && identifier.name;
+ if (policy) {
+ let selector = csstree.generate(rule.ruleNode.prelude);
+ let note = this.footnotes[selector];
+ if (note) {
+ note.policy = policy;
+ }
+ }
+ }
+ if (property === "footnote-display") {
+ let identifier = declaration.value.children && declaration.value.children.first();
+ let display = identifier && identifier.name;
+ let selector = csstree.generate(rule.ruleNode.prelude);
+ if (display && this.footnotes[selector]) {
+ let note = this.footnotes[selector];
+ if (note) {
+ note.display = display;
+ }
+ }
+ }
+ }
+
+ onPseudoSelector(pseudoNode, pItem, pList, selector, rule) {
+ let name = pseudoNode.name;
+ if (name === "footnote-marker") {
+ // switch ::footnote-marker to [data-footnote-marker]::before
+ let prelude = rule.ruleNode.prelude;
+ let newPrelude = new csstree.List();
+
+ // Can't get remove to work, so just copying everything else
+ prelude.children.first().children.each((node) => {
+ if (node.type !== "PseudoElementSelector") {
+ newPrelude.appendData(node);
+ }
+ });
+
+ // Add our data call
+ newPrelude.appendData({
+ type: "AttributeSelector",
+ name: {
+ type: "Identifier",
+ name: "data-footnote-marker",
+ },
+ flags: null,
+ loc: null,
+ matcher: null,
+ value: null
+ });
+
+ // Add new pseudo element
+ newPrelude.appendData({
+ type: "PseudoElementSelector",
+ name: "marker",
+ loc: null,
+ children: null
+ });
+
+ prelude.children.first().children = newPrelude;
+ }
+
+ if (name === "footnote-call") {
+ // switch ::footnote-call to [data-footnote-call]::after
+
+ let prelude = rule.ruleNode.prelude;
+ let newPrelude = new csstree.List();
+
+ // Can't get remove to work, so just copying everything else
+ prelude.children.first().children.each((node) => {
+ if (node.type !== "PseudoElementSelector") {
+ newPrelude.appendData(node);
+ }
+ });
+
+ // Add our data call
+ newPrelude.appendData({
+ type: "AttributeSelector",
+ name: {
+ type: "Identifier",
+ name: "data-footnote-call",
+ },
+ flags: null,
+ loc: null,
+ matcher: null,
+ value: null
+ });
+
+ // Add new pseudo element
+ newPrelude.appendData({
+ type: "PseudoElementSelector",
+ name: "after",
+ loc: null,
+ children: null
+ });
+
+ prelude.children.first().children = newPrelude;
+ }
+ }
+
+ afterParsed(parsed) {
+ this.processFootnotes(parsed, this.footnotes);
+ }
+
+ processFootnotes(parsed, notes) {
+ for (let n in notes) {
+ // Find elements
+ let elements = parsed.querySelectorAll(n);
+ let element;
+ let note = notes[n];
+ for (var i = 0; i < elements.length; i++) {
+ element = elements[i];
+ // Add note type
+ element.setAttribute("data-note", "footnote");
+ element.setAttribute("data-break-before", "avoid");
+ element.setAttribute("data-note-policy", note.policy || "auto");
+ element.setAttribute("data-note-display", note.display || "block");
+ // Mark all parents
+ this.processFootnoteContainer(element);
+ }
+ }
+ }
+
+ processFootnoteContainer(node) {
+ // Find the container
+ let element = node.parentElement;
+ let prevElement = element;
+ // Walk up the dom until we find a container element
+ while (element) {
+ if (isContainer(element)) {
+ // Add flag to the previous non-container element that will render with children
+ prevElement.setAttribute("data-has-notes", "true");
+ break;
+ }
+
+ prevElement = element;
+ element = element.parentElement;
+
+ // If no containers were found and there are no further parents flag the last element
+ if (!element) {
+ prevElement.setAttribute("data-has-notes", "true");
+ }
+ }
+ }
+
+ renderNode(node) {
+ if (node.nodeType == 1) {
+ // Get all notes
+ let notes;
+
+ // Ingnore html element nodes, like mathml
+ if (!node.dataset) {
+ return;
+ }
+
+ if (node.dataset.note === "footnote") {
+ notes = [node];
+ } else if (node.dataset.hasNotes || node.querySelectorAll("[data-note='footnote']")) {
+ notes = node.querySelectorAll("[data-note='footnote']");
+ }
+
+ if (notes && notes.length) {
+ this.findVisibleFootnotes(notes, node);
+ }
+ }
+ }
+
+ findVisibleFootnotes(notes, node) {
+ let area, size, right;
+ area = node.closest(".pagedjs_page_content");
+ size = area.getBoundingClientRect();
+ right = size.left + size.width;
+
+ for (let i = 0; i < notes.length; ++i) {
+ let currentNote = notes[i];
+ let bounds = currentNote.getBoundingClientRect();
+ let left = bounds.left;
+
+ if (left < right) {
+ // Add call for the note
+ this.moveFootnote(currentNote, node.closest(".pagedjs_area"), true);
+ }
+ }
+ }
+
+ moveFootnote(node, pageArea, needsNoteCall) {
+ // let pageArea = node.closest(".pagedjs_area");
+ let noteArea = pageArea.querySelector(".pagedjs_footnote_area");
+ let noteContent = noteArea.querySelector(".pagedjs_footnote_content");
+ let noteInnerContent = noteContent.querySelector(".pagedjs_footnote_inner_content");
+
+ if (!isElement(node)) {
+ return;
+ }
+
+ // Add call for the note
+ let noteCall;
+ if (needsNoteCall) {
+ noteCall = this.createFootnoteCall(node);
+ }
+
+ // Remove the break before attribute for future layout
+ node.removeAttribute("data-break-before");
+
+ // Check if note already exists for overflow
+ let existing = noteInnerContent.querySelector(`[data-ref="${node.dataset.ref}"]`);
+ if (existing) {
+ // Remove the note from the flow but no need to render it again
+ node.remove();
+ return;
+ }
+
+ // Add the note node
+ noteInnerContent.appendChild(node);
+
+ // Remove empty class
+ if (noteContent.classList.contains("pagedjs_footnote_empty")) {
+ noteContent.classList.remove("pagedjs_footnote_empty");
+ }
+
+ // Add marker
+ node.dataset.footnoteMarker = node.dataset.ref;
+
+ // Add Id
+ node.id = `note-${node.dataset.ref}`;
+
+ // Get note content size
+ let height = noteContent.scrollHeight;
+
+ // Check the noteCall is still on screen
+ let area = pageArea.querySelector(".pagedjs_page_content");
+ let size = area.getBoundingClientRect();
+ let right = size.left + size.width;
+
+ // TODO: add a max height in CSS
+
+ // Check element sizes
+ let noteCallBounds = noteCall && noteCall.getBoundingClientRect();
+ let noteAreaBounds = noteArea.getBoundingClientRect();
+
+ // Get the @footnote margins
+ let noteContentMargins = this.marginsHeight(noteContent);
+ let noteContentPadding = this.paddingHeight(noteContent);
+ let noteContentBorders = this.borderHeight(noteContent);
+ let total = noteContentMargins + noteContentPadding + noteContentBorders;
+
+ // Get the top of the @footnote area
+ let notAreaTop = Math.floor(noteAreaBounds.top);
+ // If the height isn't set yet, remove the margins from the top
+ if (noteAreaBounds.height === 0) {
+ notAreaTop -= this.marginsHeight(noteContent, false);
+ notAreaTop -= this.paddingHeight(noteContent, false);
+ notAreaTop -= this.borderHeight(noteContent, false);
+ }
+ // Determine the note call position and offset per policy
+ let notePolicy = node.dataset.notePolicy;
+ let noteCallPosition = 0;
+ let noteCallOffset = 0;
+ if (noteCall) {
+ // Get the correct line bottom for super or sub styled callouts
+ let prevSibling = noteCall.previousSibling;
+ let range = new Range();
+ if (prevSibling) {
+ range.setStartBefore(prevSibling);
+ } else {
+ range.setStartBefore(noteCall);
+ }
+ range.setEndAfter(noteCall);
+ let rangeBounds = range.getBoundingClientRect();
+ noteCallPosition = rangeBounds.bottom;
+ if (!notePolicy || notePolicy === "auto") {
+ noteCallOffset = Math.ceil(rangeBounds.bottom);
+ } else if (notePolicy === "line") {
+ noteCallOffset = Math.ceil(rangeBounds.top);
+ } else if (notePolicy === "block") {
+ // Check that there is a previous element on the page
+ let parentParagraph = noteCall.closest("p").previousElementSibling;
+ if (parentParagraph) {
+ noteCallOffset = Math.ceil(
+ parentParagraph.getBoundingClientRect().bottom
+ );
+ } else {
+ noteCallOffset = Math.ceil(rangeBounds.bottom);
+ }
+ }
+ }
+
+ let contentDelta = height + total - noteAreaBounds.height;
+ // Space between the top of the footnotes area and the bottom of the footnote call
+ let noteDelta = noteCallPosition ? notAreaTop - noteCallPosition : 0;
+ // Space needed for the force a break for the policy of the footnote
+ let notePolicyDelta = noteCallPosition ? Math.floor(noteAreaBounds.top) - noteCallOffset : 0;
+ let hasNotes = noteArea.querySelector("[data-note='footnote']");
+ if (needsNoteCall && noteCallBounds.left > right) {
+ // Note is offscreen and will be chunked to the next page on overflow
+ node.remove();
+ } else if (!hasNotes && needsNoteCall && total > noteDelta) {
+ // No space to add even the footnote area
+ pageArea.style.setProperty("--pagedjs-footnotes-height", "0px");
+ // Add a wrapper as this div is removed later
+ let wrapperDiv = document.createElement("div");
+ wrapperDiv.appendChild(node);
+ // Push to the layout queue for the next page
+ this.needsLayout.push(wrapperDiv);
+ } else if (!needsNoteCall) {
+ // Call was previously added, force adding footnote
+ pageArea.style.setProperty(
+ "--pagedjs-footnotes-height",
+ `${height + total}px`
+ );
+ } else if (noteCallPosition < noteAreaBounds.top - contentDelta) {
+ // the current note content will fit without pushing the call to the next page
+ pageArea.style.setProperty(
+ "--pagedjs-footnotes-height",
+ `${height + noteContentMargins + noteContentBorders}px`
+ );
+ } else {
+ // set height to just before note call
+ pageArea.style.setProperty(
+ "--pagedjs-footnotes-height",
+ `${noteAreaBounds.height + notePolicyDelta}px`
+ );
+ noteInnerContent.style.height =
+ noteAreaBounds.height + notePolicyDelta - total + "px";
+ }
+ }
+
+ createFootnoteCall(node) {
+ let parentElement = node.parentElement;
+ let footnoteCall = document.createElement("a");
+ for (const className of node.classList) {
+ footnoteCall.classList.add(`${className}`);
+ }
+
+ footnoteCall.dataset.footnoteCall = node.dataset.ref;
+ footnoteCall.dataset.ref = node.dataset.ref;
+
+ // Increment for counters
+ footnoteCall.dataset.dataCounterFootnoteIncrement = 1;
+
+ // Add link
+ footnoteCall.href = `#note-${node.dataset.ref}`;
+
+ parentElement.insertBefore(footnoteCall, node);
+
+ return footnoteCall;
+ }
+
+ afterPageLayout(pageElement, page, breakToken, chunker) {
+ let pageArea = pageElement.querySelector(".pagedjs_area");
+ let noteArea = page.footnotesArea;
+ let noteContent = noteArea.querySelector(".pagedjs_footnote_content");
+ let noteInnerContent = noteArea.querySelector(".pagedjs_footnote_inner_content");
+
+ let noteContentBounds = noteContent.getBoundingClientRect();
+ let { width } = noteContentBounds;
+
+ noteInnerContent.style.columnWidth = Math.round(width) + "px";
+ noteInnerContent.style.columnGap = "calc(var(--pagedjs-margin-right) + var(--pagedjs-margin-left))";
+
+ // Get overflow
+ let layout = new Layout(noteArea, undefined, chunker.settings);
+ let overflow = layout.findOverflow(noteInnerContent, noteContentBounds);
+
+ if (overflow) {
+ let { startContainer, startOffset } = overflow;
+ let startIsNode;
+ if (isElement(startContainer)) {
+ let start = startContainer.childNodes[startOffset];
+ startIsNode = isElement(start) && start.hasAttribute("data-footnote-marker");
+ }
+
+ let extracted = overflow.extractContents();
+
+ if (!startIsNode) {
+ let splitChild = extracted.firstElementChild;
+ splitChild.dataset.splitFrom = splitChild.dataset.ref;
+
+ this.handleAlignment(noteInnerContent.lastElementChild);
+ }
+
+ this.needsLayout.push(extracted);
+
+ noteContent.style.removeProperty("height");
+ noteInnerContent.style.removeProperty("height");
+
+ let noteInnerContentBounds = noteInnerContent.getBoundingClientRect();
+ let { height } = noteInnerContentBounds;
+
+ // Get the @footnote margins
+ let noteContentMargins = this.marginsHeight(noteContent);
+ let noteContentPadding = this.paddingHeight(noteContent);
+ let noteContentBorders = this.borderHeight(noteContent);
+ pageArea.style.setProperty(
+ "--pagedjs-footnotes-height",
+ `${height + noteContentMargins + noteContentBorders + noteContentPadding}px`
+ );
+
+ // Hide footnote content if empty
+ if (noteInnerContent.childNodes.length === 0) {
+ noteContent.classList.add("pagedjs_footnote_empty");
+ }
+
+ if (!breakToken) {
+ chunker.clonePage(page);
+ } else {
+ let breakBefore, previousBreakAfter;
+ if (
+ breakToken.node &&
+ typeof breakToken.node.dataset !== "undefined" &&
+ typeof breakToken.node.dataset.previousBreakAfter !== "undefined"
+ ) {
+ previousBreakAfter = breakToken.node.dataset.previousBreakAfter;
+ }
+
+ if (
+ breakToken.node &&
+ typeof breakToken.node.dataset !== "undefined" &&
+ typeof breakToken.node.dataset.breakBefore !== "undefined"
+ ) {
+ breakBefore = breakToken.node.dataset.breakBefore;
+ }
+
+ if (breakBefore || previousBreakAfter) {
+ chunker.clonePage(page);
+ }
+ }
+ }
+ noteInnerContent.style.height = "auto";
+ }
+
+ handleAlignment(node) {
+ let styles = window.getComputedStyle(node);
+ let alignLast = styles["text-align-last"];
+ node.dataset.lastSplitElement = "true";
+ if (alignLast === "auto") {
+ node.dataset.alignLastSplitElement = "justify";
+ } else {
+ node.dataset.alignLastSplitElement = alignLast;
+ }
+ }
+
+ beforePageLayout(page) {
+ while (this.needsLayout.length) {
+ let fragment = this.needsLayout.shift();
+
+ Array.from(fragment.childNodes).forEach((node) => {
+ this.moveFootnote(
+ node,
+ page.element.querySelector(".pagedjs_area"),
+ false
+ );
+ });
+ }
+ }
+
+ afterOverflowRemoved(removed, rendered) {
+ // Find the page area
+ let area = rendered.closest(".pagedjs_area");
+ // Get any rendered footnotes
+ let notes = area.querySelectorAll(".pagedjs_footnote_area [data-note='footnote']");
+ for (let n = 0; n < notes.length; n++) {
+ const note = notes[n];
+ // Check if the call for that footnote has been removed with the overflow
+ let call = removed.querySelector(`[data-footnote-call="${note.dataset.ref}"]`);
+ if (call) {
+ note.remove();
+ }
+ }
+ // Hide footnote content if empty
+ let noteInnerContent = area.querySelector(".pagedjs_footnote_inner_content");
+ if (noteInnerContent && noteInnerContent.childNodes.length === 0) {
+ noteInnerContent.parentElement.classList.add("pagedjs_footnote_empty");
+ }
+ }
+
+ marginsHeight(element, total=true) {
+ let styles = window.getComputedStyle(element);
+ let marginTop = parseInt(styles.marginTop);
+ let marginBottom = parseInt(styles.marginBottom);
+ let margin = 0;
+ if (marginTop) {
+ margin += marginTop;
+ }
+ if (marginBottom && total) {
+ margin += marginBottom;
+ }
+ return margin;
+ }
+
+ paddingHeight(element, total=true) {
+ let styles = window.getComputedStyle(element);
+ let paddingTop = parseInt(styles.paddingTop);
+ let paddingBottom = parseInt(styles.paddingBottom);
+ let padding = 0;
+ if (paddingTop) {
+ padding += paddingTop;
+ }
+ if (paddingBottom && total) {
+ padding += paddingBottom;
+ }
+ return padding;
+ }
+
+ borderHeight(element, total=true) {
+ let styles = window.getComputedStyle(element);
+ let borderTop = parseInt(styles.borderTop);
+ let borderBottom = parseInt(styles.borderBottom);
+ let borders = 0;
+ if (borderTop) {
+ borders += borderTop;
+ }
+ if (borderBottom && total) {
+ borders += borderBottom;
+ }
+ return borders;
+ }
+ }
+
+ var pagedMediaHandlers = [
+ PrintMedia,
+ AtPage,
+ Breaks,
+ Splits,
+ Counters,
+ Lists,
+ PositionFixed,
+ PageCounterIncrement,
+ NthOfType,
+ Following,
+ Footnotes
+ ];
+
+ class RunningHeaders extends Handler {
+ constructor(chunker, polisher, caller) {
+ super(chunker, polisher, caller);
+
+ this.runningSelectors = {};
+ this.elements = {};
+ }
+
+ onDeclaration(declaration, dItem, dList, rule) {
+ if (declaration.property === "position") {
+ let selector = csstree.generate(rule.ruleNode.prelude);
+ let identifier = declaration.value.children.first().name;
+
+ if (identifier === "running") {
+ let value;
+ csstree.walk(declaration, {
+ visit: "Function",
+ enter: (node, item, list) => {
+ value = node.children.first().name;
+ }
+ });
+
+ this.runningSelectors[value] = {
+ identifier: identifier,
+ value: value,
+ selector: selector
+ };
+ }
+ }
+
+ if (declaration.property === "content") {
+
+ csstree.walk(declaration, {
+ visit: "Function",
+ enter: (funcNode, fItem, fList) => {
+
+ if (funcNode.name.indexOf("element") > -1) {
+
+ let selector = csstree.generate(rule.ruleNode.prelude);
+
+ let func = funcNode.name;
+
+ let value = funcNode.children.first().name;
+
+ let args = [value];
+
+ // we only handle first for now
+ let style = "first";
+
+ selector.split(",").forEach((s) => {
+ // remove before / after
+ s = s.replace(/::after|::before/, "");
+
+ this.elements[s] = {
+ func: func,
+ args: args,
+ value: value,
+ style: style ,
+ selector: s,
+ fullSelector: selector
+ };
+ });
+ }
+
+ }
+ });
+ }
+ }
+
+ afterParsed(fragment) {
+ for (let name of Object.keys(this.runningSelectors)) {
+ let set = this.runningSelectors[name];
+ let selected = Array.from(fragment.querySelectorAll(set.selector));
+
+ if (set.identifier === "running") {
+ for (let header of selected) {
+ header.style.display = "none";
+ }
+ }
+
+ }
+ }
+
+ afterPageLayout(fragment) {
+ for (let name of Object.keys(this.runningSelectors)) {
+ let set = this.runningSelectors[name];
+ let selected = fragment.querySelector(set.selector);
+ if (selected) {
+ // let cssVar;
+ if (set.identifier === "running") {
+ // cssVar = selected.textContent.replace(/\\([\s\S])|(["|'])/g,"\\$1$2");
+ // this.styleSheet.insertRule(`:root { --string-${name}: "${cssVar}"; }`, this.styleSheet.cssRules.length);
+ // fragment.style.setProperty(`--string-${name}`, `"${cssVar}"`);
+ set.first = selected;
+ } else {
+ console.warn(set.value + "needs css replacement");
+ }
+ }
+ }
+
+ // move elements
+ if (!this.orderedSelectors) {
+ this.orderedSelectors = this.orderSelectors(this.elements);
+ }
+
+ for (let selector of this.orderedSelectors) {
+ if (selector) {
+
+ let el = this.elements[selector];
+ let selected = fragment.querySelector(selector);
+ if (selected) {
+ let running = this.runningSelectors[el.args[0]];
+ if (running && running.first) {
+ selected.innerHTML = ""; // Clear node
+ // selected.classList.add("pagedjs_clear-after"); // Clear ::after
+ let clone = running.first.cloneNode(true);
+ clone.style.display = null;
+ selected.appendChild(clone);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Assign a weight to @page selector classes
+ * 1) page
+ * 2) left & right
+ * 3) blank
+ * 4) first & nth
+ * 5) named page
+ * 6) named left & right
+ * 7) named first & nth
+ * @param {string} [s] selector string
+ * @return {int} weight
+ */
+ pageWeight(s) {
+ let weight = 1;
+ let selector = s.split(" ");
+ let parts = selector.length && selector[0].split(".");
+
+ parts.shift(); // remove empty first part
+
+ switch (parts.length) {
+ case 4:
+ if (/^pagedjs_[\w-]+_first_page$/.test(parts[3])) {
+ weight = 7;
+ } else if (parts[3] === "pagedjs_left_page" || parts[3] === "pagedjs_right_page") {
+ weight = 6;
+ }
+ break;
+ case 3:
+ if (parts[1] === "pagedjs_named_page") {
+ if (parts[2].indexOf(":nth-of-type") > -1) {
+ weight = 7;
+ } else {
+ weight = 5;
+ }
+ }
+ break;
+ case 2:
+ if (parts[1] === "pagedjs_first_page") {
+ weight = 4;
+ } else if (parts[1] === "pagedjs_blank_page") {
+ weight = 3;
+ } else if (parts[1] === "pagedjs_left_page" || parts[1] === "pagedjs_right_page") {
+ weight = 2;
+ }
+ break;
+ default:
+ if (parts[0].indexOf(":nth-of-type") > -1) {
+ weight = 4;
+ } else {
+ weight = 1;
+ }
+ }
+
+ return weight;
+ }
+
+ /**
+ * Orders the selectors based on weight
+ *
+ * Does not try to deduplicate base on specifity of the selector
+ * Previous matched selector will just be overwritten
+ * @param {obj} [obj] selectors object
+ * @return {Array} orderedSelectors
+ */
+ orderSelectors(obj) {
+ let selectors = Object.keys(obj);
+ let weighted = {
+ 1: [],
+ 2: [],
+ 3: [],
+ 4: [],
+ 5: [],
+ 6: [],
+ 7: []
+ };
+
+ let orderedSelectors = [];
+
+ for (let s of selectors) {
+ let w = this.pageWeight(s);
+ weighted[w].unshift(s);
+ }
+
+ for (var i = 1; i <= 7; i++) {
+ orderedSelectors = orderedSelectors.concat(weighted[i]);
+ }
+
+ return orderedSelectors;
+ }
+
+ beforeTreeParse(text, sheet) {
+ // element(x) is parsed as image element selector, so update element to element-ident
+ sheet.text = text.replace(/element[\s]*\(([^|^#)]*)\)/g, "element-ident($1)");
+ }
+ }
+
+ function cleanPseudoContent(el, trim = "\"' ") {
+ if(el == null) return;
+ return el
+ .replace(new RegExp(`^[${trim}]+`), "")
+ .replace(new RegExp(`[${trim}]+$`), "")
+ .replace(/["']/g, match => {
+ return "\\" + match;
+ })
+ .replace(/[\n]/g, match => {
+ return "\\00000A";
+ });
+ }
+
+ function cleanSelector(el) {
+ if(el == null) return;
+ return el
+ .replace(new RegExp("::footnote-call", "g"), "")
+ .replace(new RegExp("::footnote-marker", "g"), "");
+ }
+
+ class StringSets extends Handler {
+ constructor(chunker, polisher, caller) {
+ super(chunker, polisher, caller);
+
+ this.stringSetSelectors = {};
+ this.type;
+ // pageLastString = last string variable defined on the page
+ this.pageLastString;
+
+ }
+
+ onDeclaration(declaration, dItem, dList, rule) {
+ if (declaration.property === "string-set") {
+ let selector = csstree.generate(rule.ruleNode.prelude);
+
+ let identifiers = [];
+ let functions = [];
+ let values = [];
+
+ declaration.value.children.forEach((child) => {
+ if (child.type === "Identifier") {
+ identifiers.push(child.name);
+ }
+ if (child.type === "Function") {
+ functions.push(child.name);
+ child.children.forEach((subchild) => {
+ if (subchild.type === "Identifier") {
+ values.push(subchild.name);
+ }
+ });
+ }
+ });
+
+ identifiers.forEach((identifier, index) => {
+ let func = functions[index];
+ let value = values[index];
+ this.stringSetSelectors[identifier] = {
+ identifier,
+ func,
+ value,
+ selector
+ };
+ });
+
+ }
+ }
+
+ onContent(funcNode, fItem, fList, declaration, rule) {
+
+ if (funcNode.name === "string") {
+ let identifier = funcNode.children && funcNode.children.first().name;
+ this.type = funcNode.children.last().name;
+ funcNode.name = "var";
+ funcNode.children = new csstree.List();
+
+
+ if(this.type === "first" || this.type === "last" || this.type === "start" || this.type === "first-except"){
+ funcNode.children.append(
+ funcNode.children.createItem({
+ type: "Identifier",
+ loc: null,
+ name: "--pagedjs-string-" + this.type + "-" + identifier
+ })
+ );
+ }else {
+ funcNode.children.append(
+ funcNode.children.createItem({
+ type: "Identifier",
+ loc: null,
+ name: "--pagedjs-string-first-" + identifier
+ })
+ );
+ }
+ }
+ }
+
+ afterPageLayout(fragment) {
+
+
+ if ( this.pageLastString === undefined )
+ {
+ this.pageLastString = {};
+ }
+
+
+ for (let name of Object.keys(this.stringSetSelectors)) {
+
+ let set = this.stringSetSelectors[name];
+ let value = set.value;
+ let func = set.func;
+ let selected = fragment.querySelectorAll(set.selector);
+
+ // Get the last found string for the current identifier
+ let stringPrevPage = ( name in this.pageLastString ) ? this.pageLastString[name] : "";
+
+ let varFirst, varLast, varStart, varFirstExcept;
+
+ if(selected.length == 0){
+ // if there is no sel. on the page
+ varFirst = stringPrevPage;
+ varLast = stringPrevPage;
+ varStart = stringPrevPage;
+ varFirstExcept = stringPrevPage;
+ }else {
+
+ selected.forEach((sel) => {
+ // push each content into the array to define in the variable the first and the last element of the page.
+ if (func === "content") {
+ this.pageLastString[name] = selected[selected.length - 1].textContent;
+ }
+
+ if (func === "attr") {
+ this.pageLastString[name] = selected[selected.length - 1].getAttribute(value) || "";
+ }
+
+ });
+
+ /* FIRST */
+
+ if (func === "content") {
+ varFirst = selected[0].textContent;
+ }
+
+ if (func === "attr") {
+ varFirst = selected[0].getAttribute(value) || "";
+ }
+
+
+ /* LAST */
+
+ if (func === "content") {
+ varLast = selected[selected.length - 1].textContent;
+ }
+
+ if (func === "attr") {
+ varLast = selected[selected.length - 1].getAttribute(value) || "";
+ }
+
+
+ /* START */
+
+ // Hack to find if the sel. is the first elem of the page / find a better way
+ let selTop = selected[0].getBoundingClientRect().top;
+ let pageContent = selected[0].closest(".pagedjs_page_content");
+ let pageContentTop = pageContent.getBoundingClientRect().top;
+
+ if(selTop == pageContentTop){
+ varStart = varFirst;
+ }else {
+ varStart = stringPrevPage;
+ }
+
+ /* FIRST EXCEPT */
+
+ varFirstExcept = "";
+
+ }
+
+ fragment.style.setProperty(`--pagedjs-string-first-${name}`, `"${cleanPseudoContent(varFirst)}`);
+ fragment.style.setProperty(`--pagedjs-string-last-${name}`, `"${cleanPseudoContent(varLast)}`);
+ fragment.style.setProperty(`--pagedjs-string-start-${name}`, `"${cleanPseudoContent(varStart)}`);
+ fragment.style.setProperty(`--pagedjs-string-first-except-${name}`, `"${cleanPseudoContent(varFirstExcept)}`);
+
+
+ }
+ }
+
+
+ }
+
+ class TargetCounters extends Handler {
+ constructor(chunker, polisher, caller) {
+ super(chunker, polisher, caller);
+
+ this.styleSheet = polisher.styleSheet;
+
+ this.counterTargets = {};
+ }
+
+ onContent(funcNode, fItem, fList, declaration, rule) {
+ if (funcNode.name === "target-counter") {
+ let selector = csstree.generate(rule.ruleNode.prelude);
+
+ let first = funcNode.children.first();
+ let func = first.name;
+
+ let value = csstree.generate(funcNode);
+
+ let args = [];
+
+ first.children.forEach((child) => {
+ if (child.type === "Identifier") {
+
+ args.push(child.name);
+ }
+ });
+
+ let counter;
+ let style;
+ let styleIdentifier;
+
+ funcNode.children.forEach((child) => {
+ if (child.type === "Identifier") {
+ if (!counter) {
+ counter = child.name;
+ } else if (!style) {
+ styleIdentifier = csstree.clone(child);
+ style = child.name;
+ }
+ }
+ });
+
+ let variable = "target-counter-" + UUID();
+
+ selector.split(",").forEach((s) => {
+ this.counterTargets[s] = {
+ func: func,
+ args: args,
+ value: value,
+ counter: counter,
+ style: style,
+ selector: s,
+ fullSelector: selector,
+ variable: variable
+ };
+ });
+
+ // Replace with counter
+ funcNode.name = "counter";
+ funcNode.children = new csstree.List();
+ funcNode.children.appendData({
+ type: "Identifier",
+ loc: 0,
+ name: variable
+ });
+
+ if (styleIdentifier) {
+ funcNode.children.appendData({type: "Operator", loc: null, value: ","});
+ funcNode.children.appendData(styleIdentifier);
+ }
+ }
+ }
+
+ afterPageLayout(fragment, page, breakToken, chunker) {
+ Object.keys(this.counterTargets).forEach((name) => {
+ let target = this.counterTargets[name];
+ let split = target.selector.split(/::?/g);
+ let query = split[0];
+
+ let queried = chunker.pagesArea.querySelectorAll(query + ":not([data-" + target.variable + "])");
+
+ queried.forEach((selected, index) => {
+ // TODO: handle func other than attr
+ if (target.func !== "attr") {
+ return;
+ }
+ let val = attr(selected, target.args);
+ let element = chunker.pagesArea.querySelector(querySelectorEscape(val));
+
+ if (element) {
+ let selector = UUID();
+ selected.setAttribute("data-" + target.variable, selector);
+ // TODO: handle other counter types (by query)
+ let pseudo = "";
+ if (split.length > 1) {
+ pseudo += "::" + split[1];
+ }
+ if (target.counter === "page") {
+ let pages = chunker.pagesArea.querySelectorAll(".pagedjs_page");
+ let pg = 0;
+ for (let i = 0; i < pages.length; i++) {
+ let page = pages[i];
+ let styles = window.getComputedStyle(page);
+ let reset = styles["counter-reset"].replace("page", "").trim();
+ let increment = styles["counter-increment"].replace("page", "").trim();
+
+ if (reset !== "none") {
+ pg = parseInt(reset);
+ }
+ if (increment !== "none") {
+ pg += parseInt(increment);
+ }
+
+ if (page.contains(element)){
+ break;
+ }
+ }
+ this.styleSheet.insertRule(`[data-${target.variable}="${selector}"]${pseudo} { counter-reset: ${target.variable} ${pg}; }`, this.styleSheet.cssRules.length);
+ } else {
+ let value = element.getAttribute(`data-counter-${target.counter}-value`);
+ if (value) {
+ this.styleSheet.insertRule(`[data-${target.variable}="${selector}"]${pseudo} { counter-reset: ${target.variable} ${target.variable} ${parseInt(value)}; }`, this.styleSheet.cssRules.length);
+ }
+ }
+
+ // force redraw
+ let el = document.querySelector(`[data-${target.variable}="${selector}"]`);
+ if (el) {
+ el.style.display = "none";
+ el.clientHeight;
+ el.style.removeProperty("display");
+ }
+ }
+ });
+ });
+ }
+ }
+
+ // import { nodeAfter } from "../../utils/dom";
+
+ class TargetText extends Handler {
+ constructor(chunker, polisher, caller) {
+ super(chunker, polisher, caller);
+
+ this.styleSheet = polisher.styleSheet;
+ this.textTargets = {};
+ this.beforeContent = "";
+ this.afterContent = "";
+ this.selector = {};
+ }
+
+ onContent(funcNode, fItem, fList, declaration, rule) {
+ if (funcNode.name === "target-text") {
+ this.selector = csstree.generate(rule.ruleNode.prelude);
+ let first = funcNode.children.first();
+ let last = funcNode.children.last();
+ let func = first.name;
+
+ let value = csstree.generate(funcNode);
+
+ let args = [];
+
+ first.children.forEach(child => {
+ if (child.type === "Identifier") {
+ args.push(child.name);
+ }
+ });
+
+ let style;
+ if (last !== first) {
+ style = last.name;
+ }
+
+ let variable = "--pagedjs-" + UUID();
+
+ this.selector.split(",").forEach(s => {
+ this.textTargets[s] = {
+ func: func,
+ args: args,
+ value: value,
+ style: style || "content",
+ selector: s,
+ fullSelector: this.selector,
+ variable: variable
+ };
+ });
+
+ // Replace with variable
+ funcNode.name = "var";
+ funcNode.children = new csstree.List();
+ funcNode.children.appendData({
+ type: "Identifier",
+ loc: 0,
+ name: variable
+ });
+ }
+ }
+
+ // parse this on the ONCONTENT : get all before and after and replace the value with a variable
+ onPseudoSelector(pseudoNode, pItem, pList, selector, rule) {
+ // console.log(pseudoNode);
+ // console.log(rule);
+
+ rule.ruleNode.block.children.forEach(properties => {
+ if (pseudoNode.name === "before" && properties.property === "content") {
+ // let beforeVariable = "--pagedjs-" + UUID();
+
+ let contenu = properties.value.children;
+ contenu.forEach(prop => {
+ if (prop.type === "String") {
+ this.beforeContent = prop.value;
+ }
+ });
+ } else if (pseudoNode.name === "after" && properties.property === "content") {
+ properties.value.children.forEach(prop => {
+ if (prop.type === "String") {
+ this.afterContent = prop.value;
+ }
+ });
+ }
+ });
+ }
+
+ afterParsed(fragment) {
+ Object.keys(this.textTargets).forEach(name => {
+ let target = this.textTargets[name];
+ let split = target.selector.split("::");
+ let query = split[0];
+ let queried = fragment.querySelectorAll(query);
+ let textContent;
+ queried.forEach((selected, index) => {
+ let val = attr(selected, target.args);
+ let element = fragment.querySelector(querySelectorEscape(val));
+ if (element) {
+ // content & first-letter & before & after refactorized
+ if (target.style) {
+ this.selector = UUID();
+ selected.setAttribute("data-target-text", this.selector);
+
+ let psuedo = "";
+ if (split.length > 1) {
+ psuedo += "::" + split[1];
+ }
+
+ if (target.style === "before" || target.style === "after") {
+ const pseudoType = `${target.style}Content`;
+ textContent = cleanPseudoContent(this[pseudoType]);
+ } else {
+ textContent = cleanPseudoContent(element.textContent, " ");
+ }
+ textContent = target.style === "first-letter" ? textContent.charAt(0) : textContent;
+ this.styleSheet.insertRule(`[data-target-text="${this.selector}"]${psuedo} { ${target.variable}: "${textContent}" }`);
+ } else {
+ console.warn("missed target", val);
+ }
+ }
+ });
+ });
+ }
+ }
+
+ var generatedContentHandlers = [
+ RunningHeaders,
+ StringSets,
+ TargetCounters,
+ TargetText
+ ];
+
+ class WhiteSpaceFilter extends Handler {
+ constructor(chunker, polisher, caller) {
+ super(chunker, polisher, caller);
+ }
+
+ filter(content) {
+
+ filterTree(content, (node) => {
+ return this.filterEmpty(node);
+ }, NodeFilter.SHOW_TEXT);
+
+ }
+
+ filterEmpty(node) {
+ if (node.textContent.length > 1 && isIgnorable(node)) {
+
+ // Do not touch the content if text is pre-formatted
+ let parent = node.parentNode;
+ let pre = isElement(parent) && parent.closest("pre");
+ if (pre) {
+ return NodeFilter.FILTER_REJECT;
+ }
+
+ const previousSibling = previousSignificantNode(node);
+ const nextSibling = nextSignificantNode(node);
+
+ if (nextSibling === null && previousSibling === null) {
+ // we should not remove a Node that does not have any siblings.
+ node.textContent = " ";
+ return NodeFilter.FILTER_REJECT;
+ }
+ if (nextSibling === null) {
+ // we can safely remove this node
+ return NodeFilter.FILTER_ACCEPT;
+ }
+ if (previousSibling === null) {
+ // we can safely remove this node
+ return NodeFilter.FILTER_ACCEPT;
+ }
+
+ // replace the content with a single space
+ node.textContent = " ";
+
+ // TODO: we also need to preserve sequences of white spaces when the parent has "white-space" rule:
+ // pre
+ // Sequences of white space are preserved. Lines are only broken at newline characters in the source and at elements.
+ //
+ // pre-wrap
+ // Sequences of white space are preserved. Lines are broken at newline characters, at , and as necessary to fill line boxes.
+ //
+ // pre-line
+ // Sequences of white space are collapsed. Lines are broken at newline characters, at , and as necessary to fill line boxes.
+ //
+ // break-spaces
+ // The behavior is identical to that of pre-wrap, except that:
+ // - Any sequence of preserved white space always takes up space, including at the end of the line.
+ // - A line breaking opportunity exists after every preserved white space character, including between white space characters.
+ // - Such preserved spaces take up space and do not hang, and thus affect the box’s intrinsic sizes (min-content size and max-content size).
+ //
+ // See: https://developer.mozilla.org/en-US/docs/Web/CSS/white-space#Values
+
+ return NodeFilter.FILTER_REJECT;
+ } else {
+ return NodeFilter.FILTER_REJECT;
+ }
+ }
+
+ }
+
+ class CommentsFilter extends Handler {
+ constructor(chunker, polisher, caller) {
+ super(chunker, polisher, caller);
+ }
+
+ filter(content) {
+ filterTree(content, null, NodeFilter.SHOW_COMMENT);
+ }
+
+ }
+
+ class ScriptsFilter extends Handler {
+ constructor(chunker, polisher, caller) {
+ super(chunker, polisher, caller);
+ }
+
+ filter(content) {
+ content.querySelectorAll("script").forEach( script => { script.remove(); });
+ }
+
+ }
+
+ var clearCut = {};
+
+ /**
+ * Originally ported from https://github.com/keeganstreet/specificity/blob/866bf7ab4e7f62a7179c15b13a95af4e1c7b1afa/specificity.js
+ *
+ * Calculates the specificity of CSS selectors
+ * http://www.w3.org/TR/css3-selectors/#specificity
+ *
+ * Returns a selector integer value
+ */
+
+ (function (exports) {
+ // The following regular expressions assume that selectors matching the preceding regular expressions have been removed
+ var attributeRegex = /(\[[^\]]+\])/g;
+ var idRegex = /(#[^\s\+>~\.\[:]+)/g;
+ var classRegex = /(\.[^\s\+>~\.\[:]+)/g;
+ var pseudoElementRegex = /(::[^\s\+>~\.\[:]+|:first-line|:first-letter|:before|:after)/g;
+ var pseudoClassRegex = /(:[^\s\+>~\.\[:]+)/g;
+ var elementRegex = /([^\s\+>~\.\[:]+)/g;
+ var notRegex = /:not\(([^\)]*)\)/g;
+ var ruleRegex = /\{[^]*/gm;
+ var separatorRegex = /[\*\s\+>~]/g;
+ var straysRegex = /[#\.]/g;
+
+ // Find matches for a regular expression in a string and push their details to parts
+ // Type is "a" for IDs, "b" for classes, attributes and pseudo-classes and "c" for elements and pseudo-elements
+ var findMatch = function(regex, type, types, selector) {
+ var matches = selector.match(regex);
+ if (matches) {
+ for (var i = 0; i < matches.length; i++) {
+ types[type]++;
+ // Replace this simple selector with whitespace so it won't be counted in further simple selectors
+ selector = selector.replace(matches[i], ' ');
+ }
+ }
+
+ return selector;
+ };
+
+ // Calculate the specificity for a selector by dividing it into simple selectors and counting them
+ var calculate = function(selector) {
+ var commaIndex = selector.indexOf(',');
+ if (commaIndex !== -1) {
+ selector = selector.substring(0, commaIndex);
+ }
+
+ var types = {
+ a: 0,
+ b: 0,
+ c: 0
+ };
+
+ // Remove the negation psuedo-class (:not) but leave its argument because specificity is calculated on its argument
+ selector = selector.replace(notRegex, ' $1 ');
+
+ // Remove anything after a left brace in case a user has pasted in a rule, not just a selector
+ selector = selector.replace(ruleRegex, ' ');
+
+ // Add attribute selectors to parts collection (type b)
+ selector = findMatch(attributeRegex, 'b', types, selector);
+
+ // Add ID selectors to parts collection (type a)
+ selector = findMatch(idRegex, 'a', types, selector);
+
+ // Add class selectors to parts collection (type b)
+ selector = findMatch(classRegex, 'b', types, selector);
+
+ // Add pseudo-element selectors to parts collection (type c)
+ selector = findMatch(pseudoElementRegex, 'c', types, selector);
+
+ // Add pseudo-class selectors to parts collection (type b)
+ selector = findMatch(pseudoClassRegex, 'b', types, selector);
+
+ // Remove universal selector and separator characters
+ selector = selector.replace(separatorRegex, ' ');
+
+ // Remove any stray dots or hashes which aren't attached to words
+ // These may be present if the user is live-editing this selector
+ selector = selector.replace(straysRegex, ' ');
+
+ // The only things left should be element selectors (type c)
+ findMatch(elementRegex, 'c', types, selector);
+
+ return (types.a * 100) + (types.b * 10) + (types.c * 1);
+ };
+
+ var specificityCache = {};
+
+ exports.calculateSpecificity = function(selector) {
+ var specificity = specificityCache[selector];
+ if (specificity === undefined) {
+ specificity = calculate(selector);
+ specificityCache[selector] = specificity;
+ }
+ return specificity;
+ };
+
+ var validSelectorCache = {};
+ var testSelectorElement = null;
+
+ exports.isSelectorValid = function(selector) {
+ var valid = validSelectorCache[selector];
+ if (valid === undefined) {
+ if (testSelectorElement == null) {
+ testSelectorElement = document.createElement('div');
+ }
+
+ try {
+ testSelectorElement.querySelector(selector);
+ valid = true;
+ } catch (error) {
+ valid = false;
+ }
+ validSelectorCache[selector] = valid;
+ }
+ return valid;
+ };
+
+ exports.validateSelector = function(selector) {
+ if (!exports.isSelectorValid(selector)) {
+ var error = new SyntaxError(selector + ' is not a valid selector');
+ error.code = 'EBADSELECTOR';
+ throw error;
+ }
+ };
+ } (clearCut));
+
+ class UndisplayedFilter extends Handler {
+ constructor(chunker, polisher, caller) {
+ super(chunker, polisher, caller);
+ this.displayRules = {};
+ }
+
+ onDeclaration(declaration, dItem, dList, rule) {
+ if (declaration.property === "display") {
+ let selector = csstree.generate(rule.ruleNode.prelude);
+ let value = declaration.value.children.first().name;
+
+ selector.split(",").forEach((s) => {
+ this.displayRules[s] = {
+ value: value,
+ selector: s,
+ specificity: clearCut.calculateSpecificity(s),
+ important: declaration.important
+ };
+ });
+ }
+ }
+
+ filter(content) {
+ let { matches, selectors } = this.sortDisplayedSelectors(content, this.displayRules);
+
+ // Find matching elements that have display styles
+ for (let i = 0; i < matches.length; i++) {
+ let element = matches[i];
+ let selector = selectors[i];
+ let displayValue = selector[selector.length-1].value;
+ if(this.removable(element) && displayValue === "none") {
+ element.dataset.undisplayed = "undisplayed";
+ }
+ }
+
+ // Find elements that have inline styles
+ let styledElements = content.querySelectorAll("[style]");
+ for (let i = 0; i < styledElements.length; i++) {
+ let element = styledElements[i];
+ if (this.removable(element)) {
+ element.dataset.undisplayed = "undisplayed";
+ }
+ }
+ }
+
+ sorter(a, b) {
+ if (a.important && !b.important) {
+ return 1;
+ }
+
+ if (b.important && !a.important) {
+ return -1;
+ }
+
+ return a.specificity - b.specificity;
+ }
+
+ sortDisplayedSelectors(content, displayRules=[]) {
+ let matches = [];
+ let selectors = [];
+ for (let d in displayRules) {
+ let displayItem = displayRules[d];
+ let selector = displayItem.selector;
+ let query = [];
+ try {
+ try {
+ query = content.querySelectorAll(selector);
+ } catch (e) {
+ query = content.querySelectorAll(cleanSelector(selector));
+ }
+ } catch (e) {
+ query = [];
+ }
+ let elements = Array.from(query);
+ for (let e of elements) {
+ if (matches.includes(e)) {
+ let index = matches.indexOf(e);
+ selectors[index].push(displayItem);
+ selectors[index] = selectors[index].sort(this.sorter);
+ } else {
+ matches.push(e);
+ selectors.push([displayItem]);
+ }
+ }
+ }
+
+ return { matches, selectors };
+ }
+
+ removable(element) {
+ if (element.style &&
+ element.style.display !== "" &&
+ element.style.display !== "none") {
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ var filters = [
+ WhiteSpaceFilter,
+ CommentsFilter,
+ ScriptsFilter,
+ UndisplayedFilter
+ ];
+
+ var isImplemented$3 = function () {
+ var from = Array.from, arr, result;
+ if (typeof from !== "function") return false;
+ arr = ["raz", "dwa"];
+ result = from(arr);
+ return Boolean(result && (result !== arr) && (result[1] === "dwa"));
+ };
+
+ var isImplemented$2;
+ var hasRequiredIsImplemented;
+
+ function requireIsImplemented () {
+ if (hasRequiredIsImplemented) return isImplemented$2;
+ hasRequiredIsImplemented = 1;
+
+ var validTypes = { object: true, symbol: true };
+
+ isImplemented$2 = function () {
+ var symbol;
+ if (typeof Symbol !== 'function') return false;
+ symbol = Symbol('test symbol');
+ try { String(symbol); } catch (e) { return false; }
+
+ // Return 'true' also for polyfills
+ if (!validTypes[typeof Symbol.iterator]) return false;
+ if (!validTypes[typeof Symbol.toPrimitive]) return false;
+ if (!validTypes[typeof Symbol.toStringTag]) return false;
+
+ return true;
+ };
+ return isImplemented$2;
+ }
+
+ var isSymbol;
+ var hasRequiredIsSymbol;
+
+ function requireIsSymbol () {
+ if (hasRequiredIsSymbol) return isSymbol;
+ hasRequiredIsSymbol = 1;
+
+ isSymbol = function (x) {
+ if (!x) return false;
+ if (typeof x === 'symbol') return true;
+ if (!x.constructor) return false;
+ if (x.constructor.name !== 'Symbol') return false;
+ return (x[x.constructor.toStringTag] === 'Symbol');
+ };
+ return isSymbol;
+ }
+
+ var validateSymbol;
+ var hasRequiredValidateSymbol;
+
+ function requireValidateSymbol () {
+ if (hasRequiredValidateSymbol) return validateSymbol;
+ hasRequiredValidateSymbol = 1;
+
+ var isSymbol = requireIsSymbol();
+
+ validateSymbol = function (value) {
+ if (!isSymbol(value)) throw new TypeError(value + " is not a symbol");
+ return value;
+ };
+ return validateSymbol;
+ }
+
+ var polyfill;
+ var hasRequiredPolyfill;
+
+ function requirePolyfill () {
+ if (hasRequiredPolyfill) return polyfill;
+ hasRequiredPolyfill = 1;
+
+ var d = dExports
+ , validateSymbol = requireValidateSymbol()
+
+ , create = Object.create, defineProperties = Object.defineProperties
+ , defineProperty = Object.defineProperty, objPrototype = Object.prototype
+ , NativeSymbol, SymbolPolyfill, HiddenSymbol, globalSymbols = create(null)
+ , isNativeSafe;
+
+ if (typeof Symbol === 'function') {
+ NativeSymbol = Symbol;
+ try {
+ String(NativeSymbol());
+ isNativeSafe = true;
+ } catch (ignore) {}
+ }
+
+ var generateName = (function () {
+ var created = create(null);
+ return function (desc) {
+ var postfix = 0, name, ie11BugWorkaround;
+ while (created[desc + (postfix || '')]) ++postfix;
+ desc += (postfix || '');
+ created[desc] = true;
+ name = '@@' + desc;
+ defineProperty(objPrototype, name, d.gs(null, function (value) {
+ // For IE11 issue see:
+ // https://connect.microsoft.com/IE/feedbackdetail/view/1928508/
+ // ie11-broken-getters-on-dom-objects
+ // https://github.com/medikoo/es6-symbol/issues/12
+ if (ie11BugWorkaround) return;
+ ie11BugWorkaround = true;
+ defineProperty(this, name, d(value));
+ ie11BugWorkaround = false;
+ }));
+ return name;
+ };
+ }());
+
+ // Internal constructor (not one exposed) for creating Symbol instances.
+ // This one is used to ensure that `someSymbol instanceof Symbol` always return false
+ HiddenSymbol = function Symbol(description) {
+ if (this instanceof HiddenSymbol) throw new TypeError('Symbol is not a constructor');
+ return SymbolPolyfill(description);
+ };
+
+ // Exposed `Symbol` constructor
+ // (returns instances of HiddenSymbol)
+ polyfill = SymbolPolyfill = function Symbol(description) {
+ var symbol;
+ if (this instanceof Symbol) throw new TypeError('Symbol is not a constructor');
+ if (isNativeSafe) return NativeSymbol(description);
+ symbol = create(HiddenSymbol.prototype);
+ description = (description === undefined ? '' : String(description));
+ return defineProperties(symbol, {
+ __description__: d('', description),
+ __name__: d('', generateName(description))
+ });
+ };
+ defineProperties(SymbolPolyfill, {
+ for: d(function (key) {
+ if (globalSymbols[key]) return globalSymbols[key];
+ return (globalSymbols[key] = SymbolPolyfill(String(key)));
+ }),
+ keyFor: d(function (s) {
+ var key;
+ validateSymbol(s);
+ for (key in globalSymbols) if (globalSymbols[key] === s) return key;
+ }),
+
+ // To ensure proper interoperability with other native functions (e.g. Array.from)
+ // fallback to eventual native implementation of given symbol
+ hasInstance: d('', (NativeSymbol && NativeSymbol.hasInstance) || SymbolPolyfill('hasInstance')),
+ isConcatSpreadable: d('', (NativeSymbol && NativeSymbol.isConcatSpreadable) ||
+ SymbolPolyfill('isConcatSpreadable')),
+ iterator: d('', (NativeSymbol && NativeSymbol.iterator) || SymbolPolyfill('iterator')),
+ match: d('', (NativeSymbol && NativeSymbol.match) || SymbolPolyfill('match')),
+ replace: d('', (NativeSymbol && NativeSymbol.replace) || SymbolPolyfill('replace')),
+ search: d('', (NativeSymbol && NativeSymbol.search) || SymbolPolyfill('search')),
+ species: d('', (NativeSymbol && NativeSymbol.species) || SymbolPolyfill('species')),
+ split: d('', (NativeSymbol && NativeSymbol.split) || SymbolPolyfill('split')),
+ toPrimitive: d('', (NativeSymbol && NativeSymbol.toPrimitive) || SymbolPolyfill('toPrimitive')),
+ toStringTag: d('', (NativeSymbol && NativeSymbol.toStringTag) || SymbolPolyfill('toStringTag')),
+ unscopables: d('', (NativeSymbol && NativeSymbol.unscopables) || SymbolPolyfill('unscopables'))
+ });
+
+ // Internal tweaks for real symbol producer
+ defineProperties(HiddenSymbol.prototype, {
+ constructor: d(SymbolPolyfill),
+ toString: d('', function () { return this.__name__; })
+ });
+
+ // Proper implementation of methods exposed on Symbol.prototype
+ // They won't be accessible on produced symbol instances as they derive from HiddenSymbol.prototype
+ defineProperties(SymbolPolyfill.prototype, {
+ toString: d(function () { return 'Symbol (' + validateSymbol(this).__description__ + ')'; }),
+ valueOf: d(function () { return validateSymbol(this); })
+ });
+ defineProperty(SymbolPolyfill.prototype, SymbolPolyfill.toPrimitive, d('', function () {
+ var symbol = validateSymbol(this);
+ if (typeof symbol === 'symbol') return symbol;
+ return symbol.toString();
+ }));
+ defineProperty(SymbolPolyfill.prototype, SymbolPolyfill.toStringTag, d('c', 'Symbol'));
+
+ // Proper implementaton of toPrimitive and toStringTag for returned symbol instances
+ defineProperty(HiddenSymbol.prototype, SymbolPolyfill.toStringTag,
+ d('c', SymbolPolyfill.prototype[SymbolPolyfill.toStringTag]));
+
+ // Note: It's important to define `toPrimitive` as last one, as some implementations
+ // implement `toPrimitive` natively without implementing `toStringTag` (or other specified symbols)
+ // And that may invoke error in definition flow:
+ // See: https://github.com/medikoo/es6-symbol/issues/13#issuecomment-164146149
+ defineProperty(HiddenSymbol.prototype, SymbolPolyfill.toPrimitive,
+ d('c', SymbolPolyfill.prototype[SymbolPolyfill.toPrimitive]));
+ return polyfill;
+ }
+
+ var es6Symbol;
+ var hasRequiredEs6Symbol;
+
+ function requireEs6Symbol () {
+ if (hasRequiredEs6Symbol) return es6Symbol;
+ hasRequiredEs6Symbol = 1;
+
+ es6Symbol = requireIsImplemented()() ? Symbol : requirePolyfill();
+ return es6Symbol;
+ }
+
+ var isArguments;
+ var hasRequiredIsArguments;
+
+ function requireIsArguments () {
+ if (hasRequiredIsArguments) return isArguments;
+ hasRequiredIsArguments = 1;
+
+ var objToString = Object.prototype.toString
+ , id = objToString.call(
+ (function () {
+ return arguments;
+ })()
+ );
+
+ isArguments = function (value) {
+ return objToString.call(value) === id;
+ };
+ return isArguments;
+ }
+
+ var isFunction;
+ var hasRequiredIsFunction;
+
+ function requireIsFunction () {
+ if (hasRequiredIsFunction) return isFunction;
+ hasRequiredIsFunction = 1;
+
+ var objToString = Object.prototype.toString, id = objToString.call(noop$4);
+
+ isFunction = function (value) {
+ return typeof value === "function" && objToString.call(value) === id;
+ };
+ return isFunction;
+ }
+
+ var isImplemented$1 = function () {
+ var sign = Math.sign;
+ if (typeof sign !== "function") return false;
+ return (sign(10) === 1) && (sign(-20) === -1);
+ };
+
+ var shim$2;
+ var hasRequiredShim$2;
+
+ function requireShim$2 () {
+ if (hasRequiredShim$2) return shim$2;
+ hasRequiredShim$2 = 1;
+
+ shim$2 = function (value) {
+ value = Number(value);
+ if (isNaN(value) || (value === 0)) return value;
+ return value > 0 ? 1 : -1;
+ };
+ return shim$2;
+ }
+
+ var sign$1 = isImplemented$1()
+ ? Math.sign
+ : requireShim$2();
+
+ var sign = sign$1
+
+ , abs$1 = Math.abs, floor$1 = Math.floor;
+
+ var toInteger$1 = function (value) {
+ if (isNaN(value)) return 0;
+ value = Number(value);
+ if ((value === 0) || !isFinite(value)) return value;
+ return sign(value) * floor$1(abs$1(value));
+ };
+
+ var toInteger = toInteger$1
+
+ , max = Math.max;
+
+ var toPosInteger = function (value) {
+ return max(0, toInteger(value));
+ };
+
+ var isString;
+ var hasRequiredIsString;
+
+ function requireIsString () {
+ if (hasRequiredIsString) return isString;
+ hasRequiredIsString = 1;
+
+ var objToString = Object.prototype.toString, id = objToString.call("");
+
+ isString = function (value) {
+ return (
+ typeof value === "string" ||
+ (value &&
+ typeof value === "object" &&
+ (value instanceof String || objToString.call(value) === id)) ||
+ false
+ );
+ };
+ return isString;
+ }
+
+ var shim$1;
+ var hasRequiredShim$1;
+
+ function requireShim$1 () {
+ if (hasRequiredShim$1) return shim$1;
+ hasRequiredShim$1 = 1;
+
+ var iteratorSymbol = requireEs6Symbol().iterator
+ , isArguments = requireIsArguments()
+ , isFunction = requireIsFunction()
+ , toPosInt = toPosInteger
+ , callable = validCallable
+ , validValue$1 = validValue
+ , isValue = isValue$3
+ , isString = requireIsString()
+ , isArray = Array.isArray
+ , call = Function.prototype.call
+ , desc = { configurable: true, enumerable: true, writable: true, value: null }
+ , defineProperty = Object.defineProperty;
+
+ // eslint-disable-next-line complexity
+ shim$1 = function (arrayLike /*, mapFn, thisArg*/) {
+ var mapFn = arguments[1]
+ , thisArg = arguments[2]
+ , Context
+ , i
+ , j
+ , arr
+ , length
+ , code
+ , iterator
+ , result
+ , getIterator
+ , value;
+
+ arrayLike = Object(validValue$1(arrayLike));
+
+ if (isValue(mapFn)) callable(mapFn);
+ if (!this || this === Array || !isFunction(this)) {
+ // Result: Plain array
+ if (!mapFn) {
+ if (isArguments(arrayLike)) {
+ // Source: Arguments
+ length = arrayLike.length;
+ if (length !== 1) return Array.apply(null, arrayLike);
+ arr = new Array(1);
+ arr[0] = arrayLike[0];
+ return arr;
+ }
+ if (isArray(arrayLike)) {
+ // Source: Array
+ arr = new Array(length = arrayLike.length);
+ for (i = 0; i < length; ++i) arr[i] = arrayLike[i];
+ return arr;
+ }
+ }
+ arr = [];
+ } else {
+ // Result: Non plain array
+ Context = this;
+ }
+
+ if (!isArray(arrayLike)) {
+ if ((getIterator = arrayLike[iteratorSymbol]) !== undefined) {
+ // Source: Iterator
+ iterator = callable(getIterator).call(arrayLike);
+ if (Context) arr = new Context();
+ result = iterator.next();
+ i = 0;
+ while (!result.done) {
+ value = mapFn ? call.call(mapFn, thisArg, result.value, i) : result.value;
+ if (Context) {
+ desc.value = value;
+ defineProperty(arr, i, desc);
+ } else {
+ arr[i] = value;
+ }
+ result = iterator.next();
+ ++i;
+ }
+ length = i;
+ } else if (isString(arrayLike)) {
+ // Source: String
+ length = arrayLike.length;
+ if (Context) arr = new Context();
+ for (i = 0, j = 0; i < length; ++i) {
+ value = arrayLike[i];
+ if (i + 1 < length) {
+ code = value.charCodeAt(0);
+ // eslint-disable-next-line max-depth
+ if (code >= 0xd800 && code <= 0xdbff) value += arrayLike[++i];
+ }
+ value = mapFn ? call.call(mapFn, thisArg, value, j) : value;
+ if (Context) {
+ desc.value = value;
+ defineProperty(arr, j, desc);
+ } else {
+ arr[j] = value;
+ }
+ ++j;
+ }
+ length = j;
+ }
+ }
+ if (length === undefined) {
+ // Source: array or array-like
+ length = toPosInt(arrayLike.length);
+ if (Context) arr = new Context(length);
+ for (i = 0; i < length; ++i) {
+ value = mapFn ? call.call(mapFn, thisArg, arrayLike[i], i) : arrayLike[i];
+ if (Context) {
+ desc.value = value;
+ defineProperty(arr, i, desc);
+ } else {
+ arr[i] = value;
+ }
+ }
+ }
+ if (Context) {
+ desc.value = null;
+ arr.length = length;
+ }
+ return arr;
+ };
+ return shim$1;
+ }
+
+ var from = isImplemented$3()
+ ? Array.from
+ : requireShim$1();
+
+ var isImplemented = function () {
+ var numberIsNaN = Number.isNaN;
+ if (typeof numberIsNaN !== "function") return false;
+ return !numberIsNaN({}) && numberIsNaN(NaN) && !numberIsNaN(34);
+ };
+
+ var shim;
+ var hasRequiredShim;
+
+ function requireShim () {
+ if (hasRequiredShim) return shim;
+ hasRequiredShim = 1;
+
+ shim = function (value) {
+ // eslint-disable-next-line no-self-compare
+ return value !== value;
+ };
+ return shim;
+ }
+
+ var isNan = isImplemented()
+ ? Number.isNaN
+ : requireShim();
+
+ var numberIsNaN = isNan
+ , toPosInt = toPosInteger
+ , value$1 = validValue
+ , indexOf$1 = Array.prototype.indexOf
+ , objHasOwnProperty = Object.prototype.hasOwnProperty
+ , abs = Math.abs
+ , floor = Math.floor;
+
+ var eIndexOf = function (searchElement /*, fromIndex*/) {
+ var i, length, fromIndex, val;
+ if (!numberIsNaN(searchElement)) return indexOf$1.apply(this, arguments);
+
+ length = toPosInt(value$1(this).length);
+ fromIndex = arguments[1];
+ if (isNaN(fromIndex)) fromIndex = 0;
+ else if (fromIndex >= 0) fromIndex = floor(fromIndex);
+ else fromIndex = toPosInt(this.length) - floor(abs(fromIndex));
+
+ for (i = fromIndex; i < length; ++i) {
+ if (objHasOwnProperty.call(this, i)) {
+ val = this[i];
+ if (numberIsNaN(val)) return i; // Jslint: ignore
+ }
+ }
+ return -1;
+ };
+
+ var indexOf = eIndexOf
+ , forEach = Array.prototype.forEach
+ , splice = Array.prototype.splice;
+
+ // eslint-disable-next-line no-unused-vars
+ var remove$1 = function (itemToRemove /*, …item*/) {
+ forEach.call(
+ arguments,
+ function (item) {
+ var index = indexOf.call(this, item);
+ if (index !== -1) splice.call(this, index, 1);
+ },
+ this
+ );
+ };
+
+ var isValue = isValue$3;
+
+ var map = { function: true, object: true };
+
+ var isObject$1 = function (value) {
+ return (isValue(value) && map[typeof value]) || false;
+ };
+
+ var isObject = isObject$1;
+
+ var validObject = function (value) {
+ if (!isObject(value)) throw new TypeError(value + " is not an Object");
+ return value;
+ };
+
+ var aFrom = from
+ , remove = remove$1
+ , value = validObject
+ , d = dExports
+ , emit = eventEmitterExports.methods.emit
+
+ , defineProperty = Object.defineProperty
+ , hasOwnProperty$1 = Object.prototype.hasOwnProperty
+ , getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
+
+ var pipe = function (e1, e2/*, name*/) {
+ var pipes, pipe, desc, name;
+
+ (value(e1) && value(e2));
+ name = arguments[2];
+ if (name === undefined) name = 'emit';
+
+ pipe = {
+ close: function () { remove.call(pipes, e2); }
+ };
+ if (hasOwnProperty$1.call(e1, '__eePipes__')) {
+ (pipes = e1.__eePipes__).push(e2);
+ return pipe;
+ }
+ defineProperty(e1, '__eePipes__', d('c', pipes = [e2]));
+ desc = getOwnPropertyDescriptor(e1, name);
+ if (!desc) {
+ desc = d('c', undefined);
+ } else {
+ delete desc.get;
+ delete desc.set;
+ }
+ desc.value = function () {
+ var i, emitter, data = aFrom(pipes);
+ emit.apply(this, arguments);
+ for (i = 0; (emitter = data[i]); ++i) emit.apply(emitter, arguments);
+ };
+ defineProperty(e1, name, desc);
+ return pipe;
+ };
+
+ var pipe$1 = /*@__PURE__*/getDefaultExportFromCjs(pipe);
+
+ let registeredHandlers = [...pagedMediaHandlers, ...generatedContentHandlers, ...filters];
+
+ class Handlers {
+ constructor(chunker, polisher, caller) {
+
+ registeredHandlers.forEach((Handler) => {
+ let handler = new Handler(chunker, polisher, caller);
+ pipe$1(handler, this);
+ });
+ }
+ }
+
+ EventEmitter(Handlers.prototype);
+
+ function registerHandlers() {
+ for (var i = 0; i < arguments.length; i++) {
+ registeredHandlers.push(arguments[i]);
+ }
+ }
+
+ function initializeHandlers(chunker, polisher, caller) {
+ let handlers = new Handlers(chunker, polisher, caller);
+ return handlers;
+ }
+
+ class Previewer {
+ constructor(options) {
+ // this.preview = this.getParams("preview") !== "false";
+
+ this.settings = options || {};
+
+ // Process styles
+ this.polisher = new Polisher(false);
+
+ // Chunk contents
+ this.chunker = new Chunker(undefined, undefined, this.settings);
+
+ // Hooks
+ this.hooks = {};
+ this.hooks.beforePreview = new Hook(this);
+ this.hooks.afterPreview = new Hook(this);
+
+ // default size
+ this.size = {
+ width: {
+ value: 8.5,
+ unit: "in"
+ },
+ height: {
+ value: 11,
+ unit: "in"
+ },
+ format: undefined,
+ orientation: undefined
+ };
+
+ this.chunker.on("page", (page) => {
+ this.emit("page", page);
+ });
+
+ this.chunker.on("rendering", () => {
+ this.emit("rendering", this.chunker);
+ });
+ }
+
+ initializeHandlers() {
+ let handlers = initializeHandlers(this.chunker, this.polisher, this);
+
+ handlers.on("size", (size) => {
+ this.size = size;
+ this.emit("size", size);
+ });
+
+ handlers.on("atpages", (pages) => {
+ this.atpages = pages;
+ this.emit("atpages", pages);
+ });
+
+ return handlers;
+ }
+
+ registerHandlers() {
+ return registerHandlers.apply(registerHandlers, arguments);
+ }
+
+ getParams(name) {
+ let param;
+ let url = new URL(window.location);
+ let params = new URLSearchParams(url.search);
+ for(var pair of params.entries()) {
+ if(pair[0] === name) {
+ param = pair[1];
+ }
+ }
+
+ return param;
+ }
+
+ wrapContent() {
+ // Wrap body in template tag
+ let body = document.querySelector("body");
+
+ // Check if a template exists
+ let template;
+ template = body.querySelector(":scope > template[data-ref='pagedjs-content']");
+
+ if (!template) {
+ // Otherwise create one
+ template = document.createElement("template");
+ template.dataset.ref = "pagedjs-content";
+ template.innerHTML = body.innerHTML;
+ body.innerHTML = "";
+ body.appendChild(template);
+ }
+
+ return template.content;
+ }
+
+ removeStyles(doc=document) {
+ // Get all stylesheets
+ const stylesheets = Array.from(doc.querySelectorAll("link[rel='stylesheet']:not([data-pagedjs-ignore], [media~='screen'])"));
+ // Get inline styles
+ const inlineStyles = Array.from(doc.querySelectorAll("style:not([data-pagedjs-inserted-styles], [data-pagedjs-ignore], [media~='screen'])"));
+ const elements = [...stylesheets, ...inlineStyles];
+ return elements
+ // preserve order
+ .sort(function (element1, element2) {
+ const position = element1.compareDocumentPosition(element2);
+ if (position === Node.DOCUMENT_POSITION_PRECEDING) {
+ return 1;
+ } else if (position === Node.DOCUMENT_POSITION_FOLLOWING) {
+ return -1;
+ }
+ return 0;
+ })
+ // extract the href
+ .map((element) => {
+ if (element.nodeName === "STYLE") {
+ const obj = {};
+ obj[window.location.href] = element.textContent;
+ element.remove();
+ return obj;
+ }
+ if (element.nodeName === "LINK") {
+ element.remove();
+ return element.href;
+ }
+ // ignore
+ console.warn(`Unable to process: ${element}, ignoring.`);
+ });
+ }
+
+ async preview(content, stylesheets, renderTo) {
+
+ await this.hooks.beforePreview.trigger(content, renderTo);
+
+ if (!content) {
+ content = this.wrapContent();
+ }
+
+ if (!stylesheets) {
+ stylesheets = this.removeStyles();
+ }
+
+ this.polisher.setup();
+
+ this.handlers = this.initializeHandlers();
+
+ await this.polisher.add(...stylesheets);
+
+ let startTime = performance.now();
+
+ // Render flow
+ let flow = await this.chunker.flow(content, renderTo);
+
+ let endTime = performance.now();
+
+ flow.performance = (endTime - startTime);
+ flow.size = this.size;
+
+ this.emit("rendered", flow);
+
+ await this.hooks.afterPreview.trigger(flow.pages);
+
+ return flow;
+ }
+ }
+
+ EventEmitter(Previewer.prototype);
+
+ var Paged = /*#__PURE__*/Object.freeze({
+ __proto__: null,
+ Chunker: Chunker,
+ Handler: Handler,
+ Polisher: Polisher,
+ Previewer: Previewer,
+ initializeHandlers: initializeHandlers,
+ registerHandlers: registerHandlers,
+ registeredHandlers: registeredHandlers
+ });
+
+ window.Paged = Paged;
+
+ let ready = new Promise(function(resolve, reject){
+ if (document.readyState === "interactive" || document.readyState === "complete") {
+ resolve(document.readyState);
+ return;
+ }
+
+ document.onreadystatechange = function ($) {
+ if (document.readyState === "interactive") {
+ resolve(document.readyState);
+ }
+ };
+ });
+
+ let config = window.PagedConfig || {
+ auto: true,
+ before: undefined,
+ after: undefined,
+ content: undefined,
+ stylesheets: undefined,
+ renderTo: undefined,
+ settings: undefined
+ };
+
+ let previewer = new Previewer(config.settings);
+
+ ready.then(async function () {
+ let done;
+ if (config.before) {
+ await config.before();
+ }
+
+ if(config.auto !== false) {
+ done = await previewer.preview(config.content, config.stylesheets, config.renderTo);
+ }
+
+
+ if (config.after) {
+ await config.after(done);
+ }
+ });
+
+ return previewer;
+
+}));
diff --git a/assets/template.html b/assets/template.html
index ebd7fd2..381e27c 100644
--- a/assets/template.html
+++ b/assets/template.html
@@ -4,7 +4,7 @@
$title$
-
+
diff --git a/images/design-to-pack.jpg b/images/design-to-pack.jpg
new file mode 100644
index 0000000..ea1c88c
Binary files /dev/null and b/images/design-to-pack.jpg differ
diff --git a/images/design-to-pack.png b/images/design-to-pack.png
deleted file mode 100644
index d1ebc0a..0000000
Binary files a/images/design-to-pack.png and /dev/null differ
diff --git a/images/resin.png b/images/resin.png
index 33cb959..e440e9a 100644
Binary files a/images/resin.png and b/images/resin.png differ
diff --git a/images/studio-variable_Adrien_small.png b/images/studio-variable_Adrien_small.png
new file mode 100644
index 0000000..8c4a2bd
Binary files /dev/null and b/images/studio-variable_Adrien_small.png differ
diff --git a/images/studio-variable_Julie_small.png b/images/studio-variable_Julie_small.png
new file mode 100644
index 0000000..e0b76b9
Binary files /dev/null and b/images/studio-variable_Julie_small.png differ
diff --git a/index.html b/index.html
index f9cd41a..8d29f1c 100644
--- a/index.html
+++ b/index.html
@@ -4,7 +4,7 @@
Studio Variable
-
+
@@ -16,9 +16,9 @@
- Proposition Direction 6ème
+ Proposition Direction 6ème!
29 décembre 2025
- contact@studio-varible.com
+ contact@studio-variable.com
+
Studio Variable – Proposition Direction 6ème!
@@ -52,7 +52,7 @@
Équipe
-
+
.
Julie Blanc
@@ -66,7 +66,7 @@
-
+
.
Adrien Payet
@@ -362,7 +362,7 @@
de parfum. L’interface permet de collaborer du brief aux produits
finis, en passant par les vues 3D interactives.
-
+
.
diff --git a/src/equipe.md b/src/equipe.md
index d81eee4..f94801f 100644
--- a/src/equipe.md
+++ b/src/equipe.md
@@ -2,7 +2,7 @@
-
+
# Julie Blanc
@@ -14,7 +14,7 @@ Julie est designer, développeuse et chercheuse. Elle a co-fondé le studio Vari
-
+
# Adrien Payet
diff --git a/src/meta.yaml b/src/meta.yaml
index c1b442a..427d6ee 100644
--- a/src/meta.yaml
+++ b/src/meta.yaml
@@ -1,8 +1,8 @@
---
title: "Studio Variable"
baseline: "Design × code"
-client: "Proposition Direction 6ème"
+client: "Proposition Direction 6ème!"
date: "29 décembre 2025"
-contact: "contact@studio-varible.com"
-footer: "Studio Variable – Proposition Direction 6ème"
+contact: "contact@studio-variable.com"
+footer: "Studio Variable – Proposition Direction 6ème!"
---
\ No newline at end of file
diff --git a/src/portfolio-1img/design-to-pack.md b/src/portfolio-1img/design-to-pack.md
index de60e66..075d943 100644
--- a/src/portfolio-1img/design-to-pack.md
+++ b/src/portfolio-1img/design-to-pack.md
@@ -2,7 +2,7 @@
Plateforme complète de gestion de projets de création de flacons de parfum. L'interface permet de collaborer du brief aux produits finis, en passant par les vues 3D interactives.
-
+