From 42345b253b3708e0792bb3c3e36cfe5f70c6adcc Mon Sep 17 00:00:00 2001 From: realtradam Date: Fri, 11 Nov 2022 21:00:47 -0500 Subject: cards have export and many other additions/changes --- cards/card.html | 278 ++++++- cards/card.rb | 26 +- cards/cardback.png | Bin 0 -> 80602 bytes cards/cardback.svg | 223 +++++ cards/common_weapons.rb | 295 +++++++ cards/inspiration_cardback.jpg | Bin 0 -> 53923 bytes cards/web/bundle.js | 1768 ++++++++++++++++++++++++++++++++++++++++ cards/web/index.html | 2 + cards/web/main.js | 6 + src/attributes.md | 4 +- src/combat.md | 6 +- src/social.md | 49 +- 12 files changed, 2625 insertions(+), 32 deletions(-) create mode 100644 cards/cardback.png create mode 100644 cards/cardback.svg create mode 100644 cards/common_weapons.rb create mode 100644 cards/inspiration_cardback.jpg create mode 100644 cards/web/bundle.js create mode 100644 cards/web/index.html create mode 100644 cards/web/main.js diff --git a/cards/card.html b/cards/card.html index ba55466..3ef3b9f 100644 --- a/cards/card.html +++ b/cards/card.html @@ -94,7 +94,7 @@ font-size: 50px; display: flex; justify-content: flex-start; - gap: 15px; + gap: 5px; text-align: left; padding: 35px 30px 30px 30px; flex-direction: column; @@ -198,29 +198,138 @@ display: flex; } .card_wrapper { - width: 3300px; + min-height: 2850px; + width: 5775px; display: flex; flex-wrap: wrap; height: 100%; } + button { + font-size: 50px; + padding: 30px; + margin: 30px; + } p { margin: 0; } -
-
+ +
+
-
- 1 🩸 +

+ Thrusting Sword +

+
+ ⚔️ 5 +
+
+ Pre 🎲 +
+
+
+
+
+
+ + ↪️ + +
+
+

🎲 d6 + Prescision to hit.

+
+
+
+
+
+

Opportune Strike: When targeting an enemy with this weapon, mark them until the end of their turn. While marked if they attack somone other then you then you can perform a reposte on them.

+
+
+
+
+

“World Famous Iron Toothpick”

+
+
+
+
+ Weapon +
+
+
+
+
+
+

+ Spear +

+
+ ⚔️ 4 +
+
+ Str 🎲 +
+
+
+
+
+
+ + ↪️ + +
+
+

🎲 d6 + (Prescision or Strength) to hit.

+
+
+
+
+
+

Reach: When making an attack, you ignore repostes from your target.

+
+
+
+
+

“Getting up close and personal while staying far away”

+
+
+
+ Weapon +
+
+
+
+
+

- Wispy Flame + Dagger

+
+ ⚔️ 3 +
+
+ Pre 🎲 +
+
+
+ + ↪️ + +
+
+

🎲 d6 + (Prescision or Strength) to hit.

+
+
+
+
+
@@ -228,58 +337,58 @@
-

(even) Deal melee 🎲 d4 damage. If it is a small object set it on fire.

+

(even) Swift Attack: Refresh this card.


-

“Portable Candle”

+

“A quick and convinient way to turn a spleen into a sheath”

- Blood Magic + Weapon
-
+
-
- 1 🩸 -

- Summon Flesh + Bow

+
+ ⚔️ 5 +
- - ♥️ + + ↪️
-

(5 or less) Heal a target within arms reach equal to the card played.

+

🎲 d8 + Prescision to hit.


-

If this spell heals for more then half of the target’s max health then they get flesh mass disease.

+

Ranged: When making an attack, you ignore repostes from your target.


-

“Writhing flesh mass that assimilates”

+

“One stringed instrument that got repurposed as a weapon.”

- Blood Magic + Weapon
@@ -287,8 +396,11 @@

- Slingshot + Crossbow

+
+ ⚔️ 7 +
@@ -299,18 +411,31 @@
-

Attack with a 🎲 d6 roll. On success deal ⚔️ Prescision damage.

+

(must be loaded) 🎲 d6 + Prescision to hit.


-

Ranged: This weapon avoids melee reposte attacks.

+
+
+ + ↪️ + +
+
+

Reload: Load this weapon.

+
+
+
+
+
+

Ranged: When making an attack, you ignore repostes from your target.


-

“Only a troublemaker would use this.”

+

“No one will cross you with this weapon”

@@ -319,5 +444,108 @@
+
+
+
+

+ Warhammer +

+
+
+
+
+ Weapon +
+
+
+
+
+
+

+ Straight Sword +

+
+
+
+
+ Weapon +
+
+
+
+
+
+

+ Axe +

+
+
+
+
+ Weapon +
+
+
+
+
+
+

+ Staff +

+
+
+
+
+ Weapon +
+
+
+
+
+
+

+ Curved Sword +

+
+
+
+
+ Weapon +
+
+
+
+
+
+

+ Caestus +

+
+
+
+

While equipped: Unarmed Strikes deal Strength additional damage.

+
+
+
+
+

“Weapon of choice for a fit bronze statue”

+
+
+
+
+ Equipment +
+
+
+ + diff --git a/cards/card.rb b/cards/card.rb index f0ea693..2d53fdc 100644 --- a/cards/card.rb +++ b/cards/card.rb @@ -37,8 +37,14 @@ class Card rule 'p' do margin 0 end + rule 'button' do + font size: 50.px + padding 30.px + margin 30.px + end rule '.card_wrapper' do - width (825 * 4).px + min height: (1425 * 2).px + width (825 * 7).px display :flex flex wrap: :wrap height 100.% @@ -139,7 +145,7 @@ class Card font size: 50.px display :flex justify content: 'flex-start' - gap 15.px + gap 5.px text align: :left padding '35px 30px 30px 30px' flex direction: :column @@ -223,7 +229,10 @@ class Card end end end - _.div.card_wrapper do + _.button onclick: "downloadAsImage()" do + "Download" + end + _.div.card_wrapper.card_wrapper! do cards.each do |card| _.div.card(style: "background:linear-gradient(225deg, rgba(0,0,0,1) -50%, #{card.color} 100%)") do _.div.group do @@ -331,6 +340,17 @@ class Card end end end + _.script src: "./web/bundle.js" + _.script do + <<-SCRIPT +function downloadAsImage() { + htmlToImage.toPng(document.getElementById('card_wrapper')) + .then(function (dataUrl) { + download(dataUrl, 'card_wrapper.png'); + }); +} + SCRIPT + end end end end diff --git a/cards/cardback.png b/cards/cardback.png new file mode 100644 index 0000000..73dd350 Binary files /dev/null and b/cards/cardback.png differ diff --git a/cards/cardback.svg b/cards/cardback.svg new file mode 100644 index 0000000..1099321 --- /dev/null +++ b/cards/cardback.svg @@ -0,0 +1,223 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cards/common_weapons.rb b/cards/common_weapons.rb new file mode 100644 index 0000000..8879c5a --- /dev/null +++ b/cards/common_weapons.rb @@ -0,0 +1,295 @@ +load 'card.rb' + +cards = [] + +card = Card.new +card.title = "Thrusting Sword" +card.color = 'rebeccapurple' +#card.attrib_top_right = '1' +#card.attrib_top_right_icon = '🩸' +#card.attrib_top_right = '2' +#card.attrib_top_right_icon = '🛡️' +card.attrib_bottom_right = 'Pre' +card.attrib_bottom_right_icon = '🎲' +card.attrib_bottom_left = '5' +card.attrib_bottom_left_icon = '⚔️' +card.actions.push Card::Action.new( + content: '🎲 **d6 + Prescision** to hit.', + symbol: :tap, +) +card.actions.push Card::Action.new( + seperator: true, + content: '**Opportune Strike**: When targeting an enemy with this weapon, mark them until the end of their turn. While marked if they attack somone other then you then you can perform a reposte on them.', + #symbol: :spades, +) +card.flavour = '"World Famous Iron Toothpick"' +card.type = 'Weapon' +cards.push card + + +card = Card.new +card.title = "Spear" +card.color = 'rebeccapurple' +#card.attrib_top_right = '1' +#card.attrib_top_right_icon = '🩸' +#card.attrib_top_right = '2' +#card.attrib_top_right_icon = '🛡️' +card.attrib_bottom_right = 'Str' +card.attrib_bottom_right_icon = '🎲' +card.attrib_bottom_left = '4' +card.attrib_bottom_left_icon = '⚔️' +card.actions.push Card::Action.new( + content: '🎲 **d6 + (Prescision or Strength)** to hit.', + symbol: :tap, +) +card.actions.push Card::Action.new( + seperator: true, + content: '**Reach**: When making an attack, you ignore repostes from your target.', + # TODO: this is the same as the bow making it superiour + #symbol: :spades, +) +card.flavour = '"Getting up close and personal while staying far away"' +card.type = 'Weapon' +cards.push card + + +card = Card.new +card.title = "Dagger" +card.color = 'rebeccapurple' +#card.attrib_top_right = '1' +#card.attrib_top_right_icon = '🩸' +#card.attrib_top_right = '2' +#card.attrib_top_right_icon = '🛡️' +card.attrib_bottom_right = 'Pre' +card.attrib_bottom_right_icon = '🎲' +card.attrib_bottom_left = '3' +card.attrib_bottom_left_icon = '⚔️' +card.actions.push Card::Action.new( + content: '🎲 **d6 + (Prescision or Strength)** to hit.', + symbol: :tap, +) +card.actions.push Card::Action.new( + seperator: true, + content: '(even) **Swift Attack**: Refresh this card.', + symbol: :spades + #symbol: :spades, +) +card.flavour = '"A quick and convinient way to turn a spleen into a sheath"' +card.type = 'Weapon' +cards.push card + +card = Card.new +card.title = "Bow" +card.color = 'rebeccapurple' +#card.attrib_top_right = '1' +#card.attrib_top_right_icon = '🩸' +#card.attrib_top_right = '2' +#card.attrib_top_right_icon = '🛡️' +#card.attrib_bottom_right = 'Pre' +#card.attrib_bottom_right_icon = '🎲' +card.attrib_bottom_left = '5' +card.attrib_bottom_left_icon = '⚔️' +card.actions.push Card::Action.new( + content: '🎲 **d8 + Prescision** to hit.', + symbol: :tap, +) +card.actions.push Card::Action.new( + seperator: true, + content: '**Ranged**: When making an attack, you ignore repostes from your target.', +) +card.flavour = '"One stringed instrument that got repurposed as a weapon."' +card.type = 'Weapon' +cards.push card + +card = Card.new +card.title = "Crossbow" +card.color = 'rebeccapurple' +#card.attrib_top_right = '1' +#card.attrib_top_right_icon = '🩸' +#card.attrib_top_right = '2' +#card.attrib_top_right_icon = '🛡️' +#card.attrib_bottom_right = 'Pre' +#card.attrib_bottom_right_icon = '🎲' +card.attrib_bottom_left = '7' +card.attrib_bottom_left_icon = '⚔️' +card.actions.push Card::Action.new( + content: '(must be loaded) 🎲 **d6 + Prescision** to hit.', + symbol: :tap, +) +card.actions.push Card::Action.new( + seperator: true, + content: '**Reload**: Load this weapon.', + symbol: :tap, +) +card.actions.push Card::Action.new( + seperator: true, + content: '**Ranged**: When making an attack, you ignore repostes from your target.', +) +card.flavour = '"No one will cross you with this weapon"' +card.type = 'Weapon' +cards.push card + +card = Card.new +card.title = "Warhammer" +card.color = 'rebeccapurple' +#card.attrib_top_right = '1' +#card.attrib_top_right_icon = '🩸' +#card.attrib_top_right = '2' +#card.attrib_top_right_icon = '🛡️' +#card.attrib_bottom_right = 'Pre' +#card.attrib_bottom_right_icon = '🎲' +#card.attrib_bottom_left = '3' +#card.attrib_bottom_left_icon = '⚔️' +#card.actions.push Card::Action.new( +# content: '(must be loaded) 🎲 **d8 + Prescision** to hit. Deals ⚔️ **7 damage**.', +# symbol: :tap, +#) +#card.actions.push Card::Action.new( +# seperator: true, +# content: '**Reload**: Load this weapon.', +# symbol: :tap, +#) +#card.actions.push Card::Action.new( +# seperator: true, +# content: '**Ranged**: When making an attack, you ignore repostes from your target.', +#) +card.type = 'Weapon' +cards.push card + +card = Card.new +card.title = "Straight Sword" +card.color = 'rebeccapurple' +#card.attrib_top_right = '1' +#card.attrib_top_right_icon = '🩸' +#card.attrib_top_right = '2' +#card.attrib_top_right_icon = '🛡️' +#card.attrib_bottom_right = 'Pre' +#card.attrib_bottom_right_icon = '🎲' +#card.attrib_bottom_left = '3' +#card.attrib_bottom_left_icon = '⚔️' +#card.actions.push Card::Action.new( +# content: '(must be loaded) 🎲 **d8 + Prescision** to hit. Deals ⚔️ **7 damage**.', +# symbol: :tap, +#) +#card.actions.push Card::Action.new( +# seperator: true, +# content: '**Reload**: Load this weapon.', +# symbol: :tap, +#) +#card.actions.push Card::Action.new( +# seperator: true, +# content: '**Ranged**: When making an attack, you ignore repostes from your target.', +#) +card.type = 'Weapon' +cards.push card + +card = Card.new +card.title = "Axe" +card.color = 'rebeccapurple' +#card.attrib_top_right = '1' +#card.attrib_top_right_icon = '🩸' +#card.attrib_top_right = '2' +#card.attrib_top_right_icon = '🛡️' +#card.attrib_bottom_right = 'Pre' +#card.attrib_bottom_right_icon = '🎲' +#card.attrib_bottom_left = '3' +#card.attrib_bottom_left_icon = '⚔️' +#card.actions.push Card::Action.new( +# content: '(must be loaded) 🎲 **d8 + Prescision** to hit. Deals ⚔️ **7 damage**.', +# symbol: :tap, +#) +#card.actions.push Card::Action.new( +# seperator: true, +# content: '**Reload**: Load this weapon.', +# symbol: :tap, +#) +#card.actions.push Card::Action.new( +# seperator: true, +# content: '**Ranged**: When making an attack, you ignore repostes from your target.', +#) +card.type = 'Weapon' +cards.push card + +card = Card.new +card.title = "Staff" +card.color = 'rebeccapurple' +#card.attrib_top_right = '1' +#card.attrib_top_right_icon = '🩸' +#card.attrib_top_right = '2' +#card.attrib_top_right_icon = '🛡️' +#card.attrib_bottom_right = 'Pre' +#card.attrib_bottom_right_icon = '🎲' +#card.attrib_bottom_left = '3' +#card.attrib_bottom_left_icon = '⚔️' +#card.actions.push Card::Action.new( +# content: '(must be loaded) 🎲 **d8 + Prescision** to hit. Deals ⚔️ **7 damage**.', +# symbol: :tap, +#) +#card.actions.push Card::Action.new( +# seperator: true, +# content: '**Reload**: Load this weapon.', +# symbol: :tap, +#) +#card.actions.push Card::Action.new( +# seperator: true, +# content: '**Ranged**: When making an attack, you ignore repostes from your target.', +#) +card.type = 'Weapon' +cards.push card + +card = Card.new +card.title = "Curved Sword" +card.color = 'rebeccapurple' +#card.attrib_top_right = '1' +#card.attrib_top_right_icon = '🩸' +#card.attrib_top_right = '2' +#card.attrib_top_right_icon = '🛡️' +#card.attrib_bottom_right = 'Pre' +#card.attrib_bottom_right_icon = '🎲' +#card.attrib_bottom_left = '3' +#card.attrib_bottom_left_icon = '⚔️' +#card.actions.push Card::Action.new( +# content: '(must be loaded) 🎲 **d8 + Prescision** to hit. Deals ⚔️ **7 damage**.', +# symbol: :tap, +#) +#card.actions.push Card::Action.new( +# seperator: true, +# content: '**Reload**: Load this weapon.', +# symbol: :tap, +#) +#card.actions.push Card::Action.new( +# seperator: true, +# content: '**Ranged**: When making an attack, you ignore repostes from your target.', +#) +card.type = 'Weapon' +cards.push card + +card = Card.new +card.title = "Caestus" +card.color = 'DarkBlue' +#card.attrib_top_right = '1' +#card.attrib_top_right_icon = '🩸' +#card.attrib_top_right = '2' +#card.attrib_top_right_icon = '🛡️' +#card.attrib_bottom_right = 'Pre' +#card.attrib_bottom_right_icon = '🎲' +#card.attrib_bottom_left = '3' +#card.attrib_bottom_left_icon = '⚔️' +#card.actions.push Card::Action.new( +# content: '(must be loaded) 🎲 **d8 + Prescision** to hit. Deals ⚔️ **7 damage**.', +# symbol: :tap, +#) +card.actions.push Card::Action.new( + #seperator: true, + content: 'While equipped: Unarmed Strikes deal **Strength** additional damage.', + #symbol: :tap, +) +#card.actions.push Card::Action.new( +# seperator: true, +# content: '**Ranged**: When making an attack, you ignore repostes from your target.', +#) +card.flavour = '"Weapon of choice for a fit bronze statue"' +card.type = 'Equipment' +cards.push card + +File.write('card.html', Card.build(cards)) diff --git a/cards/inspiration_cardback.jpg b/cards/inspiration_cardback.jpg new file mode 100644 index 0000000..2b82919 Binary files /dev/null and b/cards/inspiration_cardback.jpg differ diff --git a/cards/web/bundle.js b/cards/web/bundle.js new file mode 100644 index 0000000..01086bf --- /dev/null +++ b/cards/web/bundle.js @@ -0,0 +1,1768 @@ +(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],2:[function(require,module,exports){ +const htmlToImage = require("html-to-image") +const download = require("downloadjs") + +window.htmlToImage = htmlToImage +window.download = download + + +},{"downloadjs":3,"html-to-image":11}],3:[function(require,module,exports){ +//download.js v4.2, by dandavis; 2008-2016. [MIT] see http://danml.com/download.html for tests/usage +// v1 landed a FF+Chrome compat way of downloading strings to local un-named files, upgraded to use a hidden frame and optional mime +// v2 added named files via a[download], msSaveBlob, IE (10+) support, and window.URL support for larger+faster saves than dataURLs +// v3 added dataURL and Blob Input, bind-toggle arity, and legacy dataURL fallback was improved with force-download mime and base64 support. 3.1 improved safari handling. +// v4 adds AMD/UMD, commonJS, and plain browser support +// v4.1 adds url download capability via solo URL argument (same domain/CORS only) +// v4.2 adds semantic variable names, long (over 2MB) dataURL support, and hidden by default temp anchors +// https://github.com/rndme/download + +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define([], factory); + } else if (typeof exports === 'object') { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(); + } else { + // Browser globals (root is window) + root.download = factory(); + } +}(this, function () { + + return function download(data, strFileName, strMimeType) { + + var self = window, // this script is only for browsers anyway... + defaultMime = "application/octet-stream", // this default mime also triggers iframe downloads + mimeType = strMimeType || defaultMime, + payload = data, + url = !strFileName && !strMimeType && payload, + anchor = document.createElement("a"), + toString = function(a){return String(a);}, + myBlob = (self.Blob || self.MozBlob || self.WebKitBlob || toString), + fileName = strFileName || "download", + blob, + reader; + myBlob= myBlob.call ? myBlob.bind(self) : Blob ; + + if(String(this)==="true"){ //reverse arguments, allowing download.bind(true, "text/xml", "export.xml") to act as a callback + payload=[payload, mimeType]; + mimeType=payload[0]; + payload=payload[1]; + } + + + if(url && url.length< 2048){ // if no filename and no mime, assume a url was passed as the only argument + fileName = url.split("/").pop().split("?")[0]; + anchor.href = url; // assign href prop to temp anchor + if(anchor.href.indexOf(url) !== -1){ // if the browser determines that it's a potentially valid url path: + var ajax=new XMLHttpRequest(); + ajax.open( "GET", url, true); + ajax.responseType = 'blob'; + ajax.onload= function(e){ + download(e.target.response, fileName, defaultMime); + }; + setTimeout(function(){ ajax.send();}, 0); // allows setting custom ajax headers using the return: + return ajax; + } // end if valid url? + } // end if url? + + + //go ahead and download dataURLs right away + if(/^data:([\w+-]+\/[\w+.-]+)?[,;]/.test(payload)){ + + if(payload.length > (1024*1024*1.999) && myBlob !== toString ){ + payload=dataUrlToBlob(payload); + mimeType=payload.type || defaultMime; + }else{ + return navigator.msSaveBlob ? // IE10 can't do a[download], only Blobs: + navigator.msSaveBlob(dataUrlToBlob(payload), fileName) : + saver(payload) ; // everyone else can save dataURLs un-processed + } + + }else{//not data url, is it a string with special needs? + if(/([\x80-\xff])/.test(payload)){ + var i=0, tempUiArr= new Uint8Array(payload.length), mx=tempUiArr.length; + for(i;i 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.cloneNode = void 0; +var mimes_1 = require("./mimes"); +var dataurl_1 = require("./dataurl"); +var clone_pseudos_1 = require("./clone-pseudos"); +var util_1 = require("./util"); +function cloneCanvasElement(canvas) { + return __awaiter(this, void 0, void 0, function () { + var dataURL; + return __generator(this, function (_a) { + dataURL = canvas.toDataURL(); + if (dataURL === 'data:,') { + return [2 /*return*/, canvas.cloneNode(false)]; + } + return [2 /*return*/, (0, util_1.createImage)(dataURL)]; + }); + }); +} +function cloneVideoElement(video, options) { + return __awaiter(this, void 0, void 0, function () { + var poster, contentType, dataURL; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + poster = video.poster; + contentType = (0, mimes_1.getMimeType)(poster); + return [4 /*yield*/, (0, dataurl_1.resourceToDataURL)(poster, contentType, options)]; + case 1: + dataURL = _a.sent(); + return [2 /*return*/, (0, util_1.createImage)(dataURL)]; + } + }); + }); +} +function cloneSingleNode(node, options) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + if (node instanceof HTMLCanvasElement) { + return [2 /*return*/, cloneCanvasElement(node)]; + } + if (node instanceof HTMLVideoElement && node.poster) { + return [2 /*return*/, cloneVideoElement(node, options)]; + } + return [2 /*return*/, node.cloneNode(false)]; + }); + }); +} +var isSlotElement = function (node) { + return node.tagName != null && node.tagName.toUpperCase() === 'SLOT'; +}; +function cloneChildren(nativeNode, clonedNode, options) { + var _a; + return __awaiter(this, void 0, void 0, function () { + var children; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + children = isSlotElement(nativeNode) && nativeNode.assignedNodes + ? (0, util_1.toArray)(nativeNode.assignedNodes()) + : (0, util_1.toArray)(((_a = nativeNode.shadowRoot) !== null && _a !== void 0 ? _a : nativeNode).childNodes); + if (children.length === 0 || nativeNode instanceof HTMLVideoElement) { + return [2 /*return*/, clonedNode]; + } + return [4 /*yield*/, children.reduce(function (deferred, child) { + return deferred + .then(function () { return cloneNode(child, options); }) + .then(function (clonedChild) { + if (clonedChild) { + clonedNode.appendChild(clonedChild); + } + }); + }, Promise.resolve())]; + case 1: + _b.sent(); + return [2 /*return*/, clonedNode]; + } + }); + }); +} +function cloneCSSStyle(nativeNode, clonedNode) { + var targetStyle = clonedNode.style; + if (!targetStyle) { + return; + } + var sourceStyle = window.getComputedStyle(nativeNode); + if (sourceStyle.cssText) { + targetStyle.cssText = sourceStyle.cssText; + targetStyle.transformOrigin = sourceStyle.transformOrigin; + } + else { + (0, util_1.toArray)(sourceStyle).forEach(function (name) { + var value = sourceStyle.getPropertyValue(name); + if (name === 'font-size' && value.endsWith('px')) { + var reducedFont = Math.floor(parseFloat(value.substring(0, value.length - 2))) - 0.1; + value = "".concat(reducedFont, "px"); + } + targetStyle.setProperty(name, value, sourceStyle.getPropertyPriority(name)); + }); + } +} +function cloneInputValue(nativeNode, clonedNode) { + if (nativeNode instanceof HTMLTextAreaElement) { + clonedNode.innerHTML = nativeNode.value; + } + if (nativeNode instanceof HTMLInputElement) { + clonedNode.setAttribute('value', nativeNode.value); + } +} +function cloneSelectValue(nativeNode, clonedNode) { + if (nativeNode instanceof HTMLSelectElement) { + var clonedSelect = clonedNode; + var selectedOption = Array.from(clonedSelect.children).find(function (child) { return nativeNode.value === child.getAttribute('value'); }); + if (selectedOption) { + selectedOption.setAttribute('selected', ''); + } + } +} +function decorate(nativeNode, clonedNode) { + if (clonedNode instanceof Element) { + cloneCSSStyle(nativeNode, clonedNode); + (0, clone_pseudos_1.clonePseudoElements)(nativeNode, clonedNode); + cloneInputValue(nativeNode, clonedNode); + cloneSelectValue(nativeNode, clonedNode); + } + return clonedNode; +} +function cloneNode(node, options, isRoot) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + if (!isRoot && options.filter && !options.filter(node)) { + return [2 /*return*/, null]; + } + return [2 /*return*/, Promise.resolve(node) + .then(function (clonedNode) { return cloneSingleNode(clonedNode, options); }) + .then(function (clonedNode) { return cloneChildren(node, clonedNode, options); }) + .then(function (clonedNode) { return decorate(node, clonedNode); })]; + }); + }); +} +exports.cloneNode = cloneNode; + +},{"./clone-pseudos":6,"./dataurl":7,"./mimes":12,"./util":13}],6:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.clonePseudoElements = void 0; +var util_1 = require("./util"); +function formatCSSText(style) { + var content = style.getPropertyValue('content'); + return "".concat(style.cssText, " content: '").concat(content.replace(/'|"/g, ''), "';"); +} +function formatCSSProperties(style) { + return (0, util_1.toArray)(style) + .map(function (name) { + var value = style.getPropertyValue(name); + var priority = style.getPropertyPriority(name); + return "".concat(name, ": ").concat(value).concat(priority ? ' !important' : '', ";"); + }) + .join(' '); +} +function getPseudoElementStyle(className, pseudo, style) { + var selector = ".".concat(className, ":").concat(pseudo); + var cssText = style.cssText + ? formatCSSText(style) + : formatCSSProperties(style); + return document.createTextNode("".concat(selector, "{").concat(cssText, "}")); +} +function clonePseudoElement(nativeNode, clonedNode, pseudo) { + var style = window.getComputedStyle(nativeNode, pseudo); + var content = style.getPropertyValue('content'); + if (content === '' || content === 'none') { + return; + } + var className = (0, util_1.uuid)(); + try { + clonedNode.className = "".concat(clonedNode.className, " ").concat(className); + } + catch (err) { + return; + } + var styleElement = document.createElement('style'); + styleElement.appendChild(getPseudoElementStyle(className, pseudo, style)); + clonedNode.appendChild(styleElement); +} +function clonePseudoElements(nativeNode, clonedNode) { + clonePseudoElement(nativeNode, clonedNode, ':before'); + clonePseudoElement(nativeNode, clonedNode, ':after'); +} +exports.clonePseudoElements = clonePseudoElements; + +},{"./util":13}],7:[function(require,module,exports){ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.resourceToDataURL = exports.fetchAsDataURL = exports.makeDataUrl = exports.isDataUrl = void 0; +function getContentFromDataUrl(dataURL) { + return dataURL.split(/,/)[1]; +} +function isDataUrl(url) { + return url.search(/^(data:)/) !== -1; +} +exports.isDataUrl = isDataUrl; +function makeDataUrl(content, mimeType) { + return "data:".concat(mimeType, ";base64,").concat(content); +} +exports.makeDataUrl = makeDataUrl; +function fetchAsDataURL(url, init, process) { + return __awaiter(this, void 0, void 0, function () { + var res, blob; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, fetch(url, init)]; + case 1: + res = _a.sent(); + if (res.status === 404) { + throw new Error("Resource \"".concat(res.url, "\" not found")); + } + return [4 /*yield*/, res.blob()]; + case 2: + blob = _a.sent(); + return [2 /*return*/, new Promise(function (resolve, reject) { + var reader = new FileReader(); + reader.onerror = reject; + reader.onloadend = function () { + try { + resolve(process({ res: res, result: reader.result })); + } + catch (error) { + reject(error); + } + }; + reader.readAsDataURL(blob); + })]; + } + }); + }); +} +exports.fetchAsDataURL = fetchAsDataURL; +var cache = {}; +function getCacheKey(url, contentType, includeQueryParams) { + var key = url.replace(/\?.*/, ''); + if (includeQueryParams) { + key = url; + } + // font resource + if (/ttf|otf|eot|woff2?/i.test(key)) { + key = key.replace(/.*\//, ''); + } + return contentType ? "[".concat(contentType, "]").concat(key) : key; +} +function resourceToDataURL(resourceUrl, contentType, options) { + return __awaiter(this, void 0, void 0, function () { + var cacheKey, dataURL, content, error_1, msg; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + cacheKey = getCacheKey(resourceUrl, contentType, options.includeQueryParams); + if (cache[cacheKey] != null) { + return [2 /*return*/, cache[cacheKey]]; + } + // ref: https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Bypassing_the_cache + if (options.cacheBust) { + // eslint-disable-next-line no-param-reassign + resourceUrl += (/\?/.test(resourceUrl) ? '&' : '?') + new Date().getTime(); + } + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, fetchAsDataURL(resourceUrl, options.fetchRequestInit, function (_a) { + var res = _a.res, result = _a.result; + if (!contentType) { + // eslint-disable-next-line no-param-reassign + contentType = res.headers.get('Content-Type') || ''; + } + return getContentFromDataUrl(result); + })]; + case 2: + content = _a.sent(); + dataURL = makeDataUrl(content, contentType); + return [3 /*break*/, 4]; + case 3: + error_1 = _a.sent(); + dataURL = options.imagePlaceholder || ''; + msg = "Failed to fetch resource: ".concat(resourceUrl); + if (error_1) { + msg = typeof error_1 === 'string' ? error_1 : error_1.message; + } + if (msg) { + console.warn(msg); + } + return [3 /*break*/, 4]; + case 4: + cache[cacheKey] = dataURL; + return [2 /*return*/, dataURL]; + } + }); + }); +} +exports.resourceToDataURL = resourceToDataURL; + +},{}],8:[function(require,module,exports){ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.embedImages = void 0; +var embed_resources_1 = require("./embed-resources"); +var util_1 = require("./util"); +var dataurl_1 = require("./dataurl"); +var mimes_1 = require("./mimes"); +function embedBackground(clonedNode, options) { + var _a; + return __awaiter(this, void 0, void 0, function () { + var background, cssString; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + background = (_a = clonedNode.style) === null || _a === void 0 ? void 0 : _a.getPropertyValue('background'); + if (!background) return [3 /*break*/, 2]; + return [4 /*yield*/, (0, embed_resources_1.embedResources)(background, null, options)]; + case 1: + cssString = _b.sent(); + clonedNode.style.setProperty('background', cssString, clonedNode.style.getPropertyPriority('background')); + _b.label = 2; + case 2: return [2 /*return*/]; + } + }); + }); +} +function embedImageNode(clonedNode, options) { + return __awaiter(this, void 0, void 0, function () { + var url, dataURL; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (!(clonedNode instanceof HTMLImageElement && !(0, dataurl_1.isDataUrl)(clonedNode.src)) && + !(clonedNode instanceof SVGImageElement && + !(0, dataurl_1.isDataUrl)(clonedNode.href.baseVal))) { + return [2 /*return*/]; + } + url = clonedNode instanceof HTMLImageElement + ? clonedNode.src + : clonedNode.href.baseVal; + return [4 /*yield*/, (0, dataurl_1.resourceToDataURL)(url, (0, mimes_1.getMimeType)(url), options)]; + case 1: + dataURL = _a.sent(); + return [4 /*yield*/, new Promise(function (resolve, reject) { + clonedNode.onload = resolve; + clonedNode.onerror = reject; + if (clonedNode instanceof HTMLImageElement) { + clonedNode.srcset = ''; + clonedNode.src = dataURL; + } + else { + clonedNode.href.baseVal = dataURL; + } + })]; + case 2: + _a.sent(); + return [2 /*return*/]; + } + }); + }); +} +function embedChildren(clonedNode, options) { + return __awaiter(this, void 0, void 0, function () { + var children, deferreds; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + children = (0, util_1.toArray)(clonedNode.childNodes); + deferreds = children.map(function (child) { return embedImages(child, options); }); + return [4 /*yield*/, Promise.all(deferreds).then(function () { return clonedNode; })]; + case 1: + _a.sent(); + return [2 /*return*/]; + } + }); + }); +} +function embedImages(clonedNode, options) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (!(clonedNode instanceof Element)) return [3 /*break*/, 4]; + return [4 /*yield*/, embedBackground(clonedNode, options)]; + case 1: + _a.sent(); + return [4 /*yield*/, embedImageNode(clonedNode, options)]; + case 2: + _a.sent(); + return [4 /*yield*/, embedChildren(clonedNode, options)]; + case 3: + _a.sent(); + _a.label = 4; + case 4: return [2 /*return*/]; + } + }); + }); +} +exports.embedImages = embedImages; + +},{"./dataurl":7,"./embed-resources":9,"./mimes":12,"./util":13}],9:[function(require,module,exports){ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.embedResources = exports.shouldEmbed = exports.embed = exports.parseURLs = void 0; +var util_1 = require("./util"); +var mimes_1 = require("./mimes"); +var dataurl_1 = require("./dataurl"); +var URL_REGEX = /url\((['"]?)([^'"]+?)\1\)/g; +var URL_WITH_FORMAT_REGEX = /url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g; +var FONT_SRC_REGEX = /src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g; +function toRegex(url) { + // eslint-disable-next-line no-useless-escape + var escaped = url.replace(/([.*+?^${}()|\[\]\/\\])/g, '\\$1'); + return new RegExp("(url\\(['\"]?)(".concat(escaped, ")(['\"]?\\))"), 'g'); +} +function parseURLs(cssText) { + var urls = []; + cssText.replace(URL_REGEX, function (raw, quotation, url) { + urls.push(url); + return raw; + }); + return urls.filter(function (url) { return !(0, dataurl_1.isDataUrl)(url); }); +} +exports.parseURLs = parseURLs; +function embed(cssText, resourceURL, baseURL, options, getContentFromUrl) { + return __awaiter(this, void 0, void 0, function () { + var resolvedURL, contentType, dataURL, content, error_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 5, , 6]); + resolvedURL = baseURL ? (0, util_1.resolveUrl)(resourceURL, baseURL) : resourceURL; + contentType = (0, mimes_1.getMimeType)(resourceURL); + dataURL = void 0; + if (!getContentFromUrl) return [3 /*break*/, 2]; + return [4 /*yield*/, getContentFromUrl(resolvedURL)]; + case 1: + content = _a.sent(); + dataURL = (0, dataurl_1.makeDataUrl)(content, contentType); + return [3 /*break*/, 4]; + case 2: return [4 /*yield*/, (0, dataurl_1.resourceToDataURL)(resolvedURL, contentType, options)]; + case 3: + dataURL = _a.sent(); + _a.label = 4; + case 4: return [2 /*return*/, cssText.replace(toRegex(resourceURL), "$1".concat(dataURL, "$3"))]; + case 5: + error_1 = _a.sent(); + return [3 /*break*/, 6]; + case 6: return [2 /*return*/, cssText]; + } + }); + }); +} +exports.embed = embed; +function filterPreferredFontFormat(str, _a) { + var preferredFontFormat = _a.preferredFontFormat; + return !preferredFontFormat + ? str + : str.replace(FONT_SRC_REGEX, function (match) { + // eslint-disable-next-line no-constant-condition + while (true) { + var _a = URL_WITH_FORMAT_REGEX.exec(match) || [], src = _a[0], format = _a[2]; + if (!format) { + return ''; + } + if (format === preferredFontFormat) { + return "src: ".concat(src, ";"); + } + } + }); +} +function shouldEmbed(url) { + return url.search(URL_REGEX) !== -1; +} +exports.shouldEmbed = shouldEmbed; +function embedResources(cssText, baseUrl, options) { + return __awaiter(this, void 0, void 0, function () { + var filteredCSSText, urls; + return __generator(this, function (_a) { + if (!shouldEmbed(cssText)) { + return [2 /*return*/, cssText]; + } + filteredCSSText = filterPreferredFontFormat(cssText, options); + urls = parseURLs(filteredCSSText); + return [2 /*return*/, urls.reduce(function (deferred, url) { + return deferred.then(function (css) { return embed(css, url, baseUrl, options); }); + }, Promise.resolve(filteredCSSText))]; + }); + }); +} +exports.embedResources = embedResources; + +},{"./dataurl":7,"./mimes":12,"./util":13}],10:[function(require,module,exports){ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.embedWebFonts = exports.getWebFontCSS = void 0; +var util_1 = require("./util"); +var dataurl_1 = require("./dataurl"); +var embed_resources_1 = require("./embed-resources"); +var cssFetchCache = {}; +function fetchCSS(url) { + return __awaiter(this, void 0, void 0, function () { + var cache, res, cssText; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + cache = cssFetchCache[url]; + if (cache != null) { + return [2 /*return*/, cache]; + } + return [4 /*yield*/, fetch(url)]; + case 1: + res = _a.sent(); + return [4 /*yield*/, res.text()]; + case 2: + cssText = _a.sent(); + cache = { url: url, cssText: cssText }; + cssFetchCache[url] = cache; + return [2 /*return*/, cache]; + } + }); + }); +} +function embedFonts(data, options) { + return __awaiter(this, void 0, void 0, function () { + var cssText, regexUrl, fontLocs, loadFonts; + var _this = this; + return __generator(this, function (_a) { + cssText = data.cssText; + regexUrl = /url\(["']?([^"')]+)["']?\)/g; + fontLocs = cssText.match(/url\([^)]+\)/g) || []; + loadFonts = fontLocs.map(function (loc) { return __awaiter(_this, void 0, void 0, function () { + var url; + return __generator(this, function (_a) { + url = loc.replace(regexUrl, '$1'); + if (!url.startsWith('https://')) { + url = new URL(url, data.url).href; + } + return [2 /*return*/, (0, dataurl_1.fetchAsDataURL)(url, options.fetchRequestInit, function (_a) { + var result = _a.result; + cssText = cssText.replace(loc, "url(".concat(result, ")")); + return [loc, result]; + })]; + }); + }); }); + return [2 /*return*/, Promise.all(loadFonts).then(function () { return cssText; })]; + }); + }); +} +function parseCSS(source) { + if (source == null) { + return []; + } + var result = []; + var commentsRegex = /(\/\*[\s\S]*?\*\/)/gi; + // strip out comments + var cssText = source.replace(commentsRegex, ''); + // eslint-disable-next-line prefer-regex-literals + var keyframesRegex = new RegExp('((@.*?keyframes [\\s\\S]*?){([\\s\\S]*?}\\s*?)})', 'gi'); + // eslint-disable-next-line no-constant-condition + while (true) { + var matches = keyframesRegex.exec(cssText); + if (matches === null) { + break; + } + result.push(matches[0]); + } + cssText = cssText.replace(keyframesRegex, ''); + var importRegex = /@import[\s\S]*?url\([^)]*\)[\s\S]*?;/gi; + // to match css & media queries together + var combinedCSSRegex = '((\\s*?(?:\\/\\*[\\s\\S]*?\\*\\/)?\\s*?@media[\\s\\S]' + + '*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})'; + // unified regex + var unifiedRegex = new RegExp(combinedCSSRegex, 'gi'); + // eslint-disable-next-line no-constant-condition + while (true) { + var matches = importRegex.exec(cssText); + if (matches === null) { + matches = unifiedRegex.exec(cssText); + if (matches === null) { + break; + } + else { + importRegex.lastIndex = unifiedRegex.lastIndex; + } + } + else { + unifiedRegex.lastIndex = importRegex.lastIndex; + } + result.push(matches[0]); + } + return result; +} +function getCSSRules(styleSheets, options) { + return __awaiter(this, void 0, void 0, function () { + var ret, deferreds; + return __generator(this, function (_a) { + ret = []; + deferreds = []; + // First loop inlines imports + styleSheets.forEach(function (sheet) { + if ('cssRules' in sheet) { + try { + (0, util_1.toArray)(sheet.cssRules || []).forEach(function (item, index) { + if (item.type === CSSRule.IMPORT_RULE) { + var importIndex_1 = index + 1; + var url = item.href; + var deferred = fetchCSS(url) + .then(function (metadata) { return embedFonts(metadata, options); }) + .then(function (cssText) { + return parseCSS(cssText).forEach(function (rule) { + try { + sheet.insertRule(rule, rule.startsWith('@import') + ? (importIndex_1 += 1) + : sheet.cssRules.length); + } + catch (error) { + console.error('Error inserting rule from remote css', { + rule: rule, + error: error, + }); + } + }); + }) + .catch(function (e) { + console.error('Error loading remote css', e.toString()); + }); + deferreds.push(deferred); + } + }); + } + catch (e) { + var inline_1 = styleSheets.find(function (a) { return a.href == null; }) || document.styleSheets[0]; + if (sheet.href != null) { + deferreds.push(fetchCSS(sheet.href) + .then(function (metadata) { return embedFonts(metadata, options); }) + .then(function (cssText) { + return parseCSS(cssText).forEach(function (rule) { + inline_1.insertRule(rule, sheet.cssRules.length); + }); + }) + .catch(function (err) { + console.error('Error loading remote stylesheet', err.toString()); + })); + } + console.error('Error inlining remote css file', e.toString()); + } + } + }); + return [2 /*return*/, Promise.all(deferreds).then(function () { + // Second loop parses rules + styleSheets.forEach(function (sheet) { + if ('cssRules' in sheet) { + try { + (0, util_1.toArray)(sheet.cssRules || []).forEach(function (item) { + ret.push(item); + }); + } + catch (e) { + console.error("Error while reading CSS rules from ".concat(sheet.href), e.toString()); + } + } + }); + return ret; + })]; + }); + }); +} +function getWebFontRules(cssRules) { + return cssRules + .filter(function (rule) { return rule.type === CSSRule.FONT_FACE_RULE; }) + .filter(function (rule) { return (0, embed_resources_1.shouldEmbed)(rule.style.getPropertyValue('src')); }); +} +function parseWebFontRules(node, options) { + return __awaiter(this, void 0, void 0, function () { + var styleSheets, cssRules; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (node.ownerDocument == null) { + throw new Error('Provided element is not within a Document'); + } + styleSheets = (0, util_1.toArray)(node.ownerDocument.styleSheets); + return [4 /*yield*/, getCSSRules(styleSheets, options)]; + case 1: + cssRules = _a.sent(); + return [2 /*return*/, getWebFontRules(cssRules)]; + } + }); + }); +} +function getWebFontCSS(node, options) { + return __awaiter(this, void 0, void 0, function () { + var rules, cssTexts; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, parseWebFontRules(node, options)]; + case 1: + rules = _a.sent(); + return [4 /*yield*/, Promise.all(rules.map(function (rule) { + var baseUrl = rule.parentStyleSheet ? rule.parentStyleSheet.href : null; + return (0, embed_resources_1.embedResources)(rule.cssText, baseUrl, options); + }))]; + case 2: + cssTexts = _a.sent(); + return [2 /*return*/, cssTexts.join('\n')]; + } + }); + }); +} +exports.getWebFontCSS = getWebFontCSS; +function embedWebFonts(clonedNode, options) { + return __awaiter(this, void 0, void 0, function () { + var cssText, _a, _b, styleNode, sytleContent; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + if (!(options.fontEmbedCSS != null)) return [3 /*break*/, 1]; + _a = options.fontEmbedCSS; + return [3 /*break*/, 5]; + case 1: + if (!options.skipFonts) return [3 /*break*/, 2]; + _b = null; + return [3 /*break*/, 4]; + case 2: return [4 /*yield*/, getWebFontCSS(clonedNode, options)]; + case 3: + _b = _c.sent(); + _c.label = 4; + case 4: + _a = _b; + _c.label = 5; + case 5: + cssText = _a; + if (cssText) { + styleNode = document.createElement('style'); + sytleContent = document.createTextNode(cssText); + styleNode.appendChild(sytleContent); + if (clonedNode.firstChild) { + clonedNode.insertBefore(styleNode, clonedNode.firstChild); + } + else { + clonedNode.appendChild(styleNode); + } + } + return [2 /*return*/]; + } + }); + }); +} +exports.embedWebFonts = embedWebFonts; + +},{"./dataurl":7,"./embed-resources":9,"./util":13}],11:[function(require,module,exports){ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getFontEmbedCSS = exports.toBlob = exports.toJpeg = exports.toPng = exports.toPixelData = exports.toCanvas = exports.toSvg = void 0; +var clone_node_1 = require("./clone-node"); +var embed_images_1 = require("./embed-images"); +var apply_style_1 = require("./apply-style"); +var embed_webfonts_1 = require("./embed-webfonts"); +var util_1 = require("./util"); +function toSvg(node, options) { + if (options === void 0) { options = {}; } + return __awaiter(this, void 0, void 0, function () { + var _a, width, height, clonedNode, datauri; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + _a = (0, util_1.getImageSize)(node, options), width = _a.width, height = _a.height; + return [4 /*yield*/, (0, clone_node_1.cloneNode)(node, options, true)]; + case 1: + clonedNode = (_b.sent()); + return [4 /*yield*/, (0, embed_webfonts_1.embedWebFonts)(clonedNode, options)]; + case 2: + _b.sent(); + return [4 /*yield*/, (0, embed_images_1.embedImages)(clonedNode, options)]; + case 3: + _b.sent(); + (0, apply_style_1.applyStyle)(clonedNode, options); + return [4 /*yield*/, (0, util_1.nodeToDataURL)(clonedNode, width, height)]; + case 4: + datauri = _b.sent(); + return [2 /*return*/, datauri]; + } + }); + }); +} +exports.toSvg = toSvg; +function toCanvas(node, options) { + if (options === void 0) { options = {}; } + return __awaiter(this, void 0, void 0, function () { + var _a, width, height, svg, img, canvas, context, ratio, canvasWidth, canvasHeight; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + _a = (0, util_1.getImageSize)(node, options), width = _a.width, height = _a.height; + return [4 /*yield*/, toSvg(node, options)]; + case 1: + svg = _b.sent(); + return [4 /*yield*/, (0, util_1.createImage)(svg)]; + case 2: + img = _b.sent(); + canvas = document.createElement('canvas'); + context = canvas.getContext('2d'); + ratio = options.pixelRatio || (0, util_1.getPixelRatio)(); + canvasWidth = options.canvasWidth || width; + canvasHeight = options.canvasHeight || height; + canvas.width = canvasWidth * ratio; + canvas.height = canvasHeight * ratio; + if (!options.skipAutoScale) { + (0, util_1.checkCanvasDimensions)(canvas); + } + canvas.style.width = "".concat(canvasWidth); + canvas.style.height = "".concat(canvasHeight); + if (options.backgroundColor) { + context.fillStyle = options.backgroundColor; + context.fillRect(0, 0, canvas.width, canvas.height); + } + context.drawImage(img, 0, 0, canvas.width, canvas.height); + return [2 /*return*/, canvas]; + } + }); + }); +} +exports.toCanvas = toCanvas; +function toPixelData(node, options) { + if (options === void 0) { options = {}; } + return __awaiter(this, void 0, void 0, function () { + var _a, width, height, canvas, ctx; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + _a = (0, util_1.getImageSize)(node, options), width = _a.width, height = _a.height; + return [4 /*yield*/, toCanvas(node, options)]; + case 1: + canvas = _b.sent(); + ctx = canvas.getContext('2d'); + return [2 /*return*/, ctx.getImageData(0, 0, width, height).data]; + } + }); + }); +} +exports.toPixelData = toPixelData; +function toPng(node, options) { + if (options === void 0) { options = {}; } + return __awaiter(this, void 0, void 0, function () { + var canvas; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, toCanvas(node, options)]; + case 1: + canvas = _a.sent(); + return [2 /*return*/, canvas.toDataURL()]; + } + }); + }); +} +exports.toPng = toPng; +function toJpeg(node, options) { + if (options === void 0) { options = {}; } + return __awaiter(this, void 0, void 0, function () { + var canvas; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, toCanvas(node, options)]; + case 1: + canvas = _a.sent(); + return [2 /*return*/, canvas.toDataURL('image/jpeg', options.quality || 1)]; + } + }); + }); +} +exports.toJpeg = toJpeg; +function toBlob(node, options) { + if (options === void 0) { options = {}; } + return __awaiter(this, void 0, void 0, function () { + var canvas, blob; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, toCanvas(node, options)]; + case 1: + canvas = _a.sent(); + return [4 /*yield*/, (0, util_1.canvasToBlob)(canvas)]; + case 2: + blob = _a.sent(); + return [2 /*return*/, blob]; + } + }); + }); +} +exports.toBlob = toBlob; +function getFontEmbedCSS(node, options) { + if (options === void 0) { options = {}; } + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, (0, embed_webfonts_1.getWebFontCSS)(node, options)]; + }); + }); +} +exports.getFontEmbedCSS = getFontEmbedCSS; + +},{"./apply-style":4,"./clone-node":5,"./embed-images":8,"./embed-webfonts":10,"./util":13}],12:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getMimeType = void 0; +var WOFF = 'application/font-woff'; +var JPEG = 'image/jpeg'; +var mimes = { + woff: WOFF, + woff2: WOFF, + ttf: 'application/font-truetype', + eot: 'application/vnd.ms-fontobject', + png: 'image/png', + jpg: JPEG, + jpeg: JPEG, + gif: 'image/gif', + tiff: 'image/tiff', + svg: 'image/svg+xml', +}; +function getExtension(url) { + var match = /\.([^./]*?)$/g.exec(url); + return match ? match[1] : ''; +} +function getMimeType(url) { + var extension = getExtension(url).toLowerCase(); + return mimes[extension] || ''; +} +exports.getMimeType = getMimeType; + +},{}],13:[function(require,module,exports){ +(function (process){(function (){ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.nodeToDataURL = exports.svgToDataURL = exports.createImage = exports.canvasToBlob = exports.checkCanvasDimensions = exports.getPixelRatio = exports.getImageSize = exports.toArray = exports.delay = exports.uuid = exports.resolveUrl = void 0; +function resolveUrl(url, baseUrl) { + // url is absolute already + if (url.match(/^[a-z]+:\/\//i)) { + return url; + } + // url is absolute already, without protocol + if (url.match(/^\/\//)) { + return window.location.protocol + url; + } + // dataURI, mailto:, tel:, etc. + if (url.match(/^[a-z]+:/i)) { + return url; + } + var doc = document.implementation.createHTMLDocument(); + var base = doc.createElement('base'); + var a = doc.createElement('a'); + doc.head.appendChild(base); + doc.body.appendChild(a); + if (baseUrl) { + base.href = baseUrl; + } + a.href = url; + return a.href; +} +exports.resolveUrl = resolveUrl; +exports.uuid = (function () { + // generate uuid for className of pseudo elements. + // We should not use GUIDs, otherwise pseudo elements sometimes cannot be captured. + var counter = 0; + // ref: http://stackoverflow.com/a/6248722/2519373 + var random = function () { + // eslint-disable-next-line no-bitwise + return "0000".concat(((Math.random() * Math.pow(36, 4)) << 0).toString(36)).slice(-4); + }; + return function () { + counter += 1; + return "u".concat(random()).concat(counter); + }; +})(); +function delay(ms) { + return function (args) { + return new Promise(function (resolve) { + setTimeout(function () { return resolve(args); }, ms); + }); + }; +} +exports.delay = delay; +function toArray(arrayLike) { + var arr = []; + for (var i = 0, l = arrayLike.length; i < l; i++) { + arr.push(arrayLike[i]); + } + return arr; +} +exports.toArray = toArray; +function px(node, styleProperty) { + var win = node.ownerDocument.defaultView || window; + var val = win.getComputedStyle(node).getPropertyValue(styleProperty); + return val ? parseFloat(val.replace('px', '')) : 0; +} +function getNodeWidth(node) { + var leftBorder = px(node, 'border-left-width'); + var rightBorder = px(node, 'border-right-width'); + return node.clientWidth + leftBorder + rightBorder; +} +function getNodeHeight(node) { + var topBorder = px(node, 'border-top-width'); + var bottomBorder = px(node, 'border-bottom-width'); + return node.clientHeight + topBorder + bottomBorder; +} +function getImageSize(targetNode, options) { + if (options === void 0) { options = {}; } + var width = options.width || getNodeWidth(targetNode); + var height = options.height || getNodeHeight(targetNode); + return { width: width, height: height }; +} +exports.getImageSize = getImageSize; +function getPixelRatio() { + var ratio; + var FINAL_PROCESS; + try { + FINAL_PROCESS = process; + } + catch (e) { + // pass + } + var val = FINAL_PROCESS && FINAL_PROCESS.env + ? FINAL_PROCESS.env.devicePixelRatio + : null; + if (val) { + ratio = parseInt(val, 10); + if (Number.isNaN(ratio)) { + ratio = 1; + } + } + return ratio || window.devicePixelRatio || 1; +} +exports.getPixelRatio = getPixelRatio; +// @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#maximum_canvas_size +var canvasDimensionLimit = 16384; +function checkCanvasDimensions(canvas) { + if (canvas.width > canvasDimensionLimit || + canvas.height > canvasDimensionLimit) { + if (canvas.width > canvasDimensionLimit && + canvas.height > canvasDimensionLimit) { + if (canvas.width > canvas.height) { + canvas.height *= canvasDimensionLimit / canvas.width; + canvas.width = canvasDimensionLimit; + } + else { + canvas.width *= canvasDimensionLimit / canvas.height; + canvas.height = canvasDimensionLimit; + } + } + else if (canvas.width > canvasDimensionLimit) { + canvas.height *= canvasDimensionLimit / canvas.width; + canvas.width = canvasDimensionLimit; + } + else { + canvas.width *= canvasDimensionLimit / canvas.height; + canvas.height = canvasDimensionLimit; + } + } +} +exports.checkCanvasDimensions = checkCanvasDimensions; +function canvasToBlob(canvas, options) { + if (options === void 0) { options = {}; } + if (canvas.toBlob) { + return new Promise(function (resolve) { + canvas.toBlob(resolve, options.type ? options.type : 'image/png', options.quality ? options.quality : 1); + }); + } + return new Promise(function (resolve) { + var binaryString = window.atob(canvas + .toDataURL(options.type ? options.type : undefined, options.quality ? options.quality : undefined) + .split(',')[1]); + var len = binaryString.length; + var binaryArray = new Uint8Array(len); + for (var i = 0; i < len; i += 1) { + binaryArray[i] = binaryString.charCodeAt(i); + } + resolve(new Blob([binaryArray], { + type: options.type ? options.type : 'image/png', + })); + }); +} +exports.canvasToBlob = canvasToBlob; +function createImage(url) { + return new Promise(function (resolve, reject) { + var img = new Image(); + img.onload = function () { return resolve(img); }; + img.onerror = reject; + img.crossOrigin = 'anonymous'; + img.decoding = 'sync'; + img.src = url; + }); +} +exports.createImage = createImage; +function svgToDataURL(svg) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, Promise.resolve() + .then(function () { return new XMLSerializer().serializeToString(svg); }) + .then(encodeURIComponent) + .then(function (html) { return "data:image/svg+xml;charset=utf-8,".concat(html); })]; + }); + }); +} +exports.svgToDataURL = svgToDataURL; +function nodeToDataURL(node, width, height) { + return __awaiter(this, void 0, void 0, function () { + var xmlns, svg, foreignObject; + return __generator(this, function (_a) { + xmlns = 'http://www.w3.org/2000/svg'; + svg = document.createElementNS(xmlns, 'svg'); + foreignObject = document.createElementNS(xmlns, 'foreignObject'); + svg.setAttribute('width', "".concat(width)); + svg.setAttribute('height', "".concat(height)); + svg.setAttribute('viewBox', "0 0 ".concat(width, " ").concat(height)); + foreignObject.setAttribute('width', '100%'); + foreignObject.setAttribute('height', '100%'); + foreignObject.setAttribute('x', '0'); + foreignObject.setAttribute('y', '0'); + foreignObject.setAttribute('externalResourcesRequired', 'true'); + svg.appendChild(foreignObject); + foreignObject.appendChild(node); + return [2 /*return*/, svgToDataURL(svg)]; + }); + }); +} +exports.nodeToDataURL = nodeToDataURL; + +}).call(this)}).call(this,require('_process')) +},{"_process":1}]},{},[2]); diff --git a/cards/web/index.html b/cards/web/index.html new file mode 100644 index 0000000..00f9636 --- /dev/null +++ b/cards/web/index.html @@ -0,0 +1,2 @@ + + diff --git a/cards/web/main.js b/cards/web/main.js new file mode 100644 index 0000000..ee0d315 --- /dev/null +++ b/cards/web/main.js @@ -0,0 +1,6 @@ +const htmlToImage = require("html-to-image") +const download = require("downloadjs") + +window.htmlToImage = htmlToImage +window.download = download + diff --git a/src/attributes.md b/src/attributes.md index fd2de25..279dbe4 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -4,7 +4,7 @@ All attributes are grouped up into 4 distinct groups, each group representing on ## Innate Stats: stats chosen at the start that dont change - For new characters: 16 stat points. max 5 min 1 + For new characters: [4, 3, 3, 2, 2, 1] ### Fitness @@ -21,7 +21,7 @@ All attributes are grouped up into 4 distinct groups, each group representing on --- ## Derived Stats stats derived from the innate stats -**Health**(End+Res): How much damage one can take before being downed. +**Health**((End+Res)x2): How much damage one can take before being downed. **Blood**(Str+Wis): Consumed some spells, some attacks, and when one is downed. You die when it reaches 0. **Memory**(Pre+Per): How much powerful knowledge you can keep. diff --git a/src/combat.md b/src/combat.md index 99abffb..ca026b9 100644 --- a/src/combat.md +++ b/src/combat.md @@ -12,8 +12,11 @@ All abilities are tapped or "deactivated" ## Player Turn -At the start of the player turn abilities that are applicable are refreshed. Now the player can use their abilities or tap +At the start of the player turn abilities that are applicable are refreshed. Now the player can use their abilities or tap. +## Other Player's or Enemy's Turns + +Only tappable abilities are allowed to be used, in reaction to another player or enemy declaring an action. --- @@ -25,4 +28,5 @@ Physical can sometimes miss(roll for hit) but has consistant damage A combat game will be structured in a way inspired by binding of issac board game Player card vs enemy cards. + The location the players are in will determine what doodads are availible (doodads are things like furniture) diff --git a/src/social.md b/src/social.md index d9ccc92..825234a 100644 --- a/src/social.md +++ b/src/social.md @@ -24,4 +24,51 @@ Things you learn about characters can be used to your advantage. Not necessarily The way you dress, as well as the race you play also has an effect on how receptive others are toward your social attempts. As a possible example: wearing expensive fancy attire may make you more trustworthy to rich socialites but could make you less convincing to those less fortunate. Wearing armour may make your appear like a "dumb brute" which can incentivize characters to take it off. Some settlements also could be predisposed to trusting or distrusting certain races, factors that affect your odds of success. ## Resolution -If the difference between difficulty and persuasion is between 1 and 6 then the player must roll to make up the difference. The result of this roll will determine if there is a cost to pay for the success. If the difference is greater then 6 then the persuasion fails. If the difference is 0 or negative then the attempt succeeds. + +The difficulty of a given social combat is decided by the GM by weighing several factors. Factors that matter are reputation in the community, appearance(how you dress and your race) The GM then lays out 1-3+ cards(more is higher difficulty) face down and only reveals one. The next card is only revealed when the current card is "overcome". + +To "overcome" a card one of the players must give a convincing argument/plea/threat/etc correlating to one of their stats. When they do they can play a card matching the number or the suit and thus the card is overcome, causing the next card to be revealed. + +Each individual stat can only be used once in a social encounter. + + + \ No newline at end of file -- cgit v1.2.3