├── .devcontainer
└── devcontainer.json
├── .github
└── FUNDING.yml
├── .gitignore
├── LICENSE
├── README.md
├── build-layer.sh
├── docs
├── 00-setup.md
├── 01-use.md
├── 404.html
├── Gemfile
├── LICENSE.txt
├── _config.yml
├── _includes
│ ├── custom-head.html
│ ├── disqus_comments.html
│ ├── footer.html
│ ├── google-analytics.html
│ ├── head.html
│ ├── header.html
│ ├── social-icons
│ │ ├── devto.svg
│ │ ├── dribbble.svg
│ │ ├── facebook.svg
│ │ ├── flickr.svg
│ │ ├── github.svg
│ │ ├── gitlab.svg
│ │ ├── google_scholar.svg
│ │ ├── instagram.svg
│ │ ├── keybase.svg
│ │ ├── linkedin.svg
│ │ ├── mastodon.svg
│ │ ├── microdotblog.svg
│ │ ├── pinterest.svg
│ │ ├── rss.svg
│ │ ├── stackoverflow.svg
│ │ ├── telegram.svg
│ │ ├── twitter.svg
│ │ └── youtube.svg
│ ├── social-item.html
│ ├── social.html
│ └── svg_symbol.html
├── _layouts
│ ├── base.html
│ ├── home.html
│ ├── page.html
│ └── post.html
├── _sass
│ └── minima
│ │ ├── _base.scss
│ │ ├── _layout.scss
│ │ ├── custom-styles.scss
│ │ ├── custom-variables.scss
│ │ ├── initialize.scss
│ │ └── skins
│ │ ├── auto.scss
│ │ ├── classic.scss
│ │ ├── dark.scss
│ │ ├── solarized-dark.scss
│ │ ├── solarized-light.scss
│ │ └── solarized.scss
├── assets
│ ├── DejaVuSansCircle.png
│ ├── css
│ │ └── style.scss
│ └── favicon.ico
├── index.md
├── minima.gemspec
└── script
│ ├── bootstrap
│ ├── build
│ ├── cibuild
│ └── server
├── lib
├── libX11.so.6
├── libXau.so.6
├── libXext.so.6
├── libXrender.so.1
├── libblkid.so.1
├── libbrotlicommon.so.1
├── libbrotlidec.so.1
├── libbz2.so.1
├── libc.so.6
├── libcairo-gobject.so.2
├── libcairo.so.2
├── libdatrie.so.1
├── libffi.so.8
├── libfontconfig.so.1
├── libfreetype.so.6
├── libfribidi.so.0
├── libgcc_s.so.1
├── libgdk_pixbuf-2.0.so.0
├── libgif.so.7
├── libgio-2.0.so.0
├── libglib-2.0.so.0
├── libgmodule-2.0.so.0
├── libgobject-2.0.so.0
├── libgraphite2.so.3
├── libharfbuzz.so.0
├── libjpeg.so.62
├── liblzma.so.5
├── libm.so.6
├── libmount.so.1
├── libpango-1.0.so.0
├── libpangocairo-1.0.so.0
├── libpangoft2-1.0.so.0
├── libpcre2-8.so.0
├── libpixman-1.so.0
├── libpng16.so.16
├── librsvg-2.so.2
├── libselinux.so.1
├── libstdc++.so.6
├── libthai.so.0
├── libxcb-render.so.0
├── libxcb-shm.so.0
├── libxcb.so.1
├── libxml2.so.2
└── libz.so.1
├── nodejs
└── test
│ ├── canvas-font.js
│ ├── canvas-svg.js
│ ├── chart-line.js
│ ├── fabric-rectangle.js
│ └── konva-circle.js
└── package-sam.yml
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | {
2 | "image": "public.ecr.aws/amazonlinux/amazonlinux:2023",
3 | "features": {
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | # github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | # patreon: # Replace with a single Patreon username
5 | # open_collective: # Replace with a single Open Collective username
6 | # ko_fi: # Replace with a single Ko-fi username
7 | # tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | # community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | # liberapay: # Replace with a single Liberapay username
10 | # issuehunt: # Replace with a single IssueHunt username
11 | # otechie: # Replace with a single Otechie username
12 | # custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 |
14 | custom: ['https://paypal.me/charoitel']
15 |
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | docs/.jekyll-cache
3 | docs/_site
4 | docs/Gemfile.lock
5 | nodejs/node_modules
6 | nodejs/node*/node_modules
7 | nodejs/package*.json
8 | package*.json
9 | canvas-nodejs_v*.zip
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020-2025 Charoite Lee
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Canvas Layer for AWS Lambda
2 |
3 | 
4 |
5 | Canvas Layer for AWS Lambda is published and available on [AWS Serverless Application Repository](https://serverlessrepo.aws.amazon.com/applications/arn:aws:serverlessrepo:us-east-1:990551184979:applications~lambda-layer-canvas-nodejs), and GitHub at [charoitel/lambda-layer-canvas-nodejs](https://github.com/charoitel/lambda-layer-canvas-nodejs). The layer aims to provide a Cairo backed Mozilla Web Canvas API implementation layer for AWS Lambda, powered by [node-canvas](https://github.com/Automattic/node-canvas).
6 |
7 | ## About node-canvas
8 |
9 | [node-canvas](https://github.com/Automattic/node-canvas) is a Cairo backed Canvas implementation for Node.js. It implements the [Mozilla Web Canvas API](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) as closely as possible. For the latest API compliance, you may check [Compatibility Status](https://github.com/Automattic/node-canvas/wiki/Compatibility-Status).
10 |
11 | ## How this layer is built?
12 |
13 | The layer is built from source of node-canvas npm package on [amazonlinux](https://hub.docker.com/_/amazonlinux) dev container instance, with following native dependencies installed. You may check the build layer script, ``` build-layer.sh ```, which is available in repository, for details.
14 |
15 | ```bash
16 | gcc-c++ cairo-devel pango-devel libjpeg-turbo-devel giflib-devel librsvg2-devel pango-devel bzip2-devel jq python3
17 | ```
18 |
19 | Since AWS Lambda is a secure and isolated runtime and execution environment, the layer aims to target AWS Lambda compatible and native build. As there are canvas libraries and frameworks relying on node-canvas running on Node.js runtime, this layer may also try to include and support those libraries and frameworks. Currently, following libraries and frameworks are included when building and packaging the layer:
20 |
21 | - [Chart.js](#chartjs-support)
22 | - [Fabric.js](#fabricjs-support)
23 | - [Konva](#konva-support)
24 |
25 | ### Chart.js support
26 |
27 | [Chart.js](https://github.com/chartjs/chart.js) provides a set of frequently used chart types, plugins, and customization options. In addition to a reasonable set of built-in chart types, there are also community-maintained chart types.
28 |
29 | > Current supported version chart.js@4.4.9 with chartjs-node-canvas@5.0.0
30 |
31 | ### Fabric.js support
32 |
33 | [Fabric.js](https://github.com/fabricjs/fabric.js) provides a missing and interactive object model for canvas, as well as an SVG parser, layer of interactivity, and a whole suite of other indispensable tools.
34 |
35 | > Current supported version fabric@6.6.4
36 |
37 | ### Konva support
38 |
39 | [Konva](https://github.com/konvajs/konva) enables high performance animations, transitions, node nesting, layering, filtering, caching, event handling for desktop and mobile applications, and much more.
40 |
41 | > Current supported version konva@9.3.20
42 |
--------------------------------------------------------------------------------
/build-layer.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #
3 | # Setup environment before build layer
4 | # yum update -y
5 | # yum groupinstall "Development Tools" -y
6 | # yum install gcc-c++ cairo-devel pango-devel libjpeg-turbo-devel giflib-devel librsvg2-devel pango-devel bzip2-devel jq python3 -y
7 | #
8 | # Setting Up Node.js, refer https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-up-node-on-ec2-instance.html for details
9 | # curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
10 | # . ~/.nvm/nvm.sh
11 | # nvm install --lts
12 | #
13 | set -e
14 |
15 | LAYER_NAME=canvas-nodejs
16 | LAYER_DESCRIPTION="Cairo backed Mozilla Web Canvas API implementation layer for AWS Lambda"
17 | LAYER_VERSION=3.1.0
18 | LAYER_AUTHOR="Charoite Lee"
19 |
20 | DOT_CHAR="."
21 | NODE_VERSION=$(node -v)
22 | NODE_VERSION=${NODE_VERSION:1}
23 | SEMVER_VERSION=7.7.1
24 |
25 | # Remove packaged layer if exists
26 | if [ -n "$(find . -name 'canvas-nodejs_v*.zip')" ]; then
27 | rm canvas-nodejs_v*.zip
28 | fi
29 |
30 | # Clean and prepare Node.js modules and dependencies
31 | if [ "$(ls -A lib)" ]; then
32 | rm lib/*
33 | fi
34 | cd nodejs
35 | if [ "$(ls -A node*)" ]; then
36 | rm -rf node*
37 | fi
38 | rm -rf node_modules node${NODE_VERSION%%$DOT_CHAR*} package*.json ../package-lock.json
39 | npm init -y
40 | npm install canvas --build-from-source
41 | npm install fabric
42 | npm install konva
43 | npm install chartjs-node-canvas chart.js
44 | npm install mocha --save-dev
45 | jq --arg LAYER_NAME "$LAYER_NAME" --arg LAYER_DESCRIPTION "$LAYER_DESCRIPTION" --arg LAYER_VERSION "$LAYER_VERSION" --arg LAYER_AUTHOR "$LAYER_AUTHOR" --arg SEMVER_VERSION "$SEMVER_VERSION" '.name = $LAYER_NAME | .description = $LAYER_DESCRIPTION | .version = $LAYER_VERSION | .license = "MIT" | .author = $LAYER_AUTHOR | .scripts.test = "mocha" | .overrides.semver = $SEMVER_VERSION ' package.json > package-tmp.json
46 | mv -f package-tmp.json package.json
47 |
48 | # Test if installed modules and dependencies work fine
49 | npm test
50 | cp package-lock.json ..
51 | npm rm mocha
52 |
53 | # Prepare and package layer
54 | mkdir node${NODE_VERSION%%$DOT_CHAR*}
55 | mv node_modules node${NODE_VERSION%%$DOT_CHAR*}
56 | cd ..
57 | find nodejs/node${NODE_VERSION%%$DOT_CHAR*} -type f -name '*.node' 2>/dev/null | grep -v 'obj\.target' | xargs ldd | awk 'NF == 4 { system("cp " $3 " lib") }'
58 | zip -q -r canvas-nodejs_v$LAYER_VERSION-node${NODE_VERSION%%$DOT_CHAR*}.zip . -x LICENSE README.md .git/**\* .github/**\* .gitignore nodejs/test/**\* *.yml build-layer.sh
59 |
--------------------------------------------------------------------------------
/docs/00-setup.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: page
3 | title: Setup
4 | permalink: /setup/
5 | ---
6 |
7 | ## Prerequisites
8 |
9 | In order to start to use [lambda-layer-canvas-nodejs](https://github.com/charoitel/lambda-layer-canvas-nodejs) published on [AWS Serverless Application Repository](https://serverlessrepo.aws.amazon.com/applications/arn:aws:serverlessrepo:us-east-1:990551184979:applications~lambda-layer-canvas-nodejs), you must have your AWS account with following services available:
10 |
11 | - [AWS Serverless Application Repository](https://aws.amazon.com/serverless/serverlessrepo)
12 | - [AWS Lambda](https://aws.amazon.com/lambda)
13 |
14 | ## Serverless application deployment
15 |
16 | Once you have your AWS account ready, there are two ways to deploy [lambda-layer-canvas-nodejs](https://serverlessrepo.aws.amazon.com/applications/arn:aws:serverlessrepo:us-east-1:990551184979:applications~lambda-layer-canvas-nodejs) and make it available in your AWS Lambda console:
17 |
18 | - [Deploy through AWS Serverless Application Repository](#deploy-through-aws-serverless-application-repository)
19 | - [Deploy through AWS Lambda console](#deploy-through-aws-lambda-console)
20 |
21 | ### Deploy through AWS Serverless Application Repository
22 |
23 | 1. Open https://serverlessrepo.aws.amazon.com/applications/arn:aws:serverlessrepo:us-east-1:990551184979:applications~lambda-layer-canvas-nodejs
24 | 2. Click **Deploy** button
25 | 3. Login to your AWS account if you haven't login yet
26 | 4. Edit **_Name_** (Optional)
27 | 5. Click **Deploy** button
28 | 6. Deployment is started and in progress
29 | 7. Check your AWS Lambda console once the deployment is completed
30 |
31 | ### Deploy through AWS Lambda console
32 |
33 | 1. Login to your AWS account and open your AWS Lambda console
34 | 2. Click **Create application** button
35 | 3. Select **_Serverless application_**
36 | 4. Input `lambda-layer-canvas-nodejs` into search box and press _Enter_ key
37 | 5. Click on the title of `lambda-layer-canvas-nodejs` card
38 | 6. Edit **_Name_** (Optional)
39 | 7. Click **Deploy** button
40 | 8. Deployment is started and in progress
41 | 9. Check your AWS Lambda console once the deployment is completed
42 |
43 | ### Using canvas layer
44 |
45 | After the deployment is completed, you may refer [usage example](/lambda-layer-canvas-nodejs/{% link 01-use.md %}) and follow the example where a Lambda function uses the canvas layer to generate PNG graphic with colored text and circle rendered.
46 |
47 | ## Setup environment to build the layer
48 |
49 | Alternately, you may setup your own environment to build the layer according to your specific needs. When using the layer with nodejs-18.x in Amazon Linux, it requires glibc-2.28, meanwhile, compiling glibc-2.28 requires make-4.x or later[^1].
50 |
51 | ```console
52 | $ wget https://ftp.gnu.org/gnu/make/make-4.3.tar.gz
53 | $ tar -xzvf make-4.3.tar.gz
54 | $ cd make-4.3/
55 | $ ./configure --prefix=/usr
56 | $ make
57 | $ make install
58 | ```
59 | Once make-4.x or later is ready, we may start to compiling glibc-2.28 on Amazon Linux. However, during `make install` there would be an error due to `cannot found -lnss_test2` which could be ignored[^2].
60 |
61 | ```console
62 | $ wget https://ftp.gnu.org/gnu/glibc/glibc-2.28.tar.gz
63 | $ tar -xzvf glibc-2.28.tar.gz
64 | $ cd glibc-2.28
65 | $ mkdir build && cd build
66 | $ ../configure --prefix=/usr --enable-add-ons --with-headers=/usr/include --with-binutils=/usr/bin
67 | $ make
68 | $ make install
69 | ...
70 | /usr/bin/ld: cannot find -lnss_test2
71 | collect2: error: ld returned 1 exit status
72 | Execution of gcc -B/usr/bin/ failed!
73 | ...
74 | ```
75 |
76 | To test if the installation of the compiled glibc-2.28 is success or not, we may check if `GLIBC_2.28` is enabled[^1] [^2].
77 |
78 | ```console
79 | $ ls -l /lib64/libc.so.6
80 | lrwxrwxrwx 1 root root 12 Jul 3 15:14 /lib64/libc.so.6 -> libc-2.28.so
81 | $ strings /lib64/libc.so.6 | grep GLIBC
82 | ...
83 | GLIBC_2.22
84 | GLIBC_2.23
85 | GLIBC_2.24
86 | GLIBC_2.25
87 | GLIBC_2.26
88 | GLIBC_2.27
89 | GLIBC_2.28
90 | GLIBC_PRIVATE
91 | ...
92 | ```
93 |
94 | Once your environment is ready, you may execute the build layer script, ``` build-layer.sh ```, to build the layer and deploy through the AWS Lambda console.
95 |
96 | ---
97 |
98 | [^1]: [Centos 7 升级 Glibc-2.28](https://cloud.tencent.com/developer/article/2021784)
99 | [^2]: [CentOS 7.6 编译安装最新版本glibc2.30 实录](https://www.jianshu.com/p/1070373a50f6)
--------------------------------------------------------------------------------
/docs/01-use.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: page
3 | title: Use
4 | permalink: /use/
5 | ---
6 |
7 | ## Using canvas layer in function
8 |
9 | Before starting to use the canvas layer, it is required to have the layer deployed through AWS Serverless Application Repository or AWS Lambda console, you may refer [setup information](/lambda-layer-canvas-nodejs/{% link 00-setup.md %}) for details. Then, you may create your Lambda function using:
10 |
11 | * AWS Lambda console editor; or
12 | * Local tool in your machine; or
13 | * Any way you may prefer
14 |
15 | Following is an example where a Lambda function uses the canvas layer to generate PNG graphic with colored text and circle rendered. There is no environment variable setting is required in this example.
16 |
17 | ## Function structure
18 |
19 | The setup of the function may look like the following structure. For font file, you may use any supported font file you like, in this example, we are going to use DejaVu Sans[^2] which could be originally found in Amazon Linux 2 EC2 instance.
20 |
21 | ```
22 | /var/task/
23 | .
24 | ├── fonts/
25 | ├── DejaVuSans.ttf
26 | ├── fonts.conf
27 | ├── index.js
28 | ```
29 |
30 | ## Font configuration using fonts.config
31 |
32 | Since AWS Lambda does not appear to support even the basic fonts on its own, so we create the fonts directory at the root directory for our Lambda function with following font configuration file[^1].
33 |
34 | ```xml
35 |
36 |
37 |
38 | /var/task/fonts
39 | /tmp/fonts-cache/
40 |
41 |
42 | ```
43 |
44 | ## Build function code in index.js
45 |
46 | Once the setup is ready, we may put following function code and test it in AWS Lambda console.
47 |
48 | ```javascript
49 | let { registerFont, createCanvas } = require('canvas');
50 |
51 | exports.handler = async (event) => {
52 | registerFont(__dirname.concat('/fonts/DejaVuSans.ttf'), { family: 'DejaVu Sans' });
53 |
54 | let canvas = createCanvas(300, 300);
55 | var ctxCircle = canvas.getContext('2d');
56 | var X = canvas.width / 2;
57 | var Y = canvas.height / 2;
58 | var R = 45;
59 | ctxCircle.beginPath();
60 | ctxCircle.arc(X, Y, R, 0, 2 * Math.PI, false);
61 | ctxCircle.lineWidth = 3;
62 | ctxCircle.strokeStyle = '#FF9900';
63 | ctxCircle.stroke();
64 |
65 | var ctxText = canvas.getContext('2d');
66 | ctxText.font = '40px "DejaVu Sans"';
67 | ctxText.fillStyle = '#146EB4';
68 | ctxText.fillText('DejaVu Sans', 15, 120);
69 |
70 | const response = {
71 | statusCode: 200,
72 | body: JSON.stringify(canvas.toDataURL()),
73 | };
74 |
75 | return response;
76 | };
77 | ```
78 | Following is the sample response from the above example function code.
79 |
80 | ```JSON
81 | {
82 | "statusCode": 200,
83 | "body": "\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51AAAABmJLR0QA/wD/AP+gvaeTAAAgAElEQVR4nO3dd3hc5Zn38e99RpI7LhoZTAvhNRBKKAGWloRACsUyNs0hhJqNLZpkU5bsJrtEpJEC2MgBWwYSEjYJmB7JxlSTpSRLaAmBEKqzNBfJDdvYkubc7x8ajc6ojqwyM/Lvc12+POfRc87cmnLrPOc8BUREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREtkWW7QDyRcnMms+625Mt226cXX9D6X9nMyaBkosWjqRg2OlgR4fGZ8zZARgNJIB1hi9z7K9u/nTBlqIlK+YftzLLIUsvFPTVgXa8vCbe0GiruqnWYPCRwzrwdYYtc3gR54UCgmeXzz2xu/23afHy2qswrm7ZNvjVqqrS83p93Fk1XyC0pZGiv9dVle7T2+P2q8qFRfHVw77t2GXAKADzdrWGObYDcLi5zUgUNYbxitqn3Lh51LoRdy+77ZjNAxy19FIwwM9X5FAM7A52kMPJwPcwapss/DBeXru0ZGbNV6lc2meJdDBJBH4bELZsO5wWv/KBUb09riWC89sU/aK3x+xP2126ZFx8zfCnwb5LMlllKAA+b87tG7bb0OtELwNvoBNWV2IYX3C3O+L1G18qmVnz2WwHlGvW3DD5/wx7NFI0wj6Ond6bY44rX7ydm58aKWoMLHF7b47Zr2Y8V1iUSCzBOSRS6ji/x+3MwIOJ1rRpVN24TUNCD3Yx7ASMOcB72QpZ+k6/nck4LKuvKv1k2/Jx5Yu3o7BhdCwsLHYPD3W3ww2mAuNSlYx93W1pSUXtZauqSuf2V4x5ycJf4PaVlk03zqMXZ0SB+TRgRKRo8cobpqzoRYT9Kj70w3KwQ1MFxjoPOa1+bumjbeuubk5S7wFLmPHclfEhH07D7NtAbjd3pVN9dtG9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xX8m4Kv5fl0n+bvdCRwSKX6dgOPz/XeTzilhDXL+S8bQwK2kLw+2HvgvxnKjTSORpdC2ildSwAQuAa6mdbgNNK96869WxrrsRCYDQQlrG+HVzACqgCGR4r9gXGQzeCZLYfWIz+cQjJuAQyPFWzC+xXSq1M9q8FPC2oYkv/C/AvaJFuP8FvhRcjmxnJO8Hvcdmiffi35mX2ttpg0AAAJ5SURBVCHgXA232XYoYW1jvJpCjItwvg+Miv4IZxHO9+1Cns1WfFE+nwMwLgfOhLRJCjcBP2MsPxosNxAkM0pY2yi/kV0oYDZwagc/fgrj1xRy10D3EE9ec5tG87qBn+2gyl0EXGbTeW8g45LcoIS1jfObOZiQ/wSm0P7zsBmowbmPBEvtYpb3Sww3sgMFHItxMk4pMLRNlRC4H/ihlaVWwJZtkBKWAMnrRDG+jXMaUNhJtVcxHgOeIcE/GMHrdk5qqubMnudGRlLAnjh7YRwJHEv6NbWoRuAujB8lVwySbZwSlqTxX1BCI1+juUl2SHf1gXeBt4E6YAOwAWND88EYCal/cWB3WofOdM54Nrl8/B1a5FSilLCkU34ze5PgVIxjgSNo31TrK5txnsF4jAT32EX8o5+eR/KcEpZkxK9nGMM5EuNonP0w9gImQo/nkW8A3gReo7lbwhMU8IydnxqwLdIpJSzZal5JATuzG86uOGNTTcDm/0k2DZubiMYaQv7JWJblW+96ERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERER4f8DqOCCaaubKHMAAAAASUVORK5CYII=\""
84 | }
85 | ```
86 | As a result, the generated PNG graphic with colored text and circle rendered may look like as follow.
87 |
88 | 
89 |
90 | ---
91 |
92 | [^1]: [AWS Lambda Fonts & libfontconfig](https://medium.com/creditorwatch/aws-lambda-fonts-libfontconfig-5e837281a4ce)
93 | [^2]: [DejaVu Fonts](https://dejavu-fonts.github.io/)
94 |
--------------------------------------------------------------------------------
/docs/404.html:
--------------------------------------------------------------------------------
1 | ---
2 | permalink: /404.html
3 | layout: default
4 | ---
5 |
6 |
19 |
20 |
21 |
404
22 |
23 |
Page not found :(
24 |
The requested page could not be found.
25 |
26 |
--------------------------------------------------------------------------------
/docs/Gemfile:
--------------------------------------------------------------------------------
1 | gem "minima"
2 |
--------------------------------------------------------------------------------
/docs/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016-present Parker Moore and the minima contributors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/docs/_config.yml:
--------------------------------------------------------------------------------
1 | title: Canvas Layer for AWS Lambda
2 | description: >
3 | Cairo backed Mozilla Web Canvas API implementation layer for AWS Lambda
4 | theme: minima
5 | minima:
6 | social_links:
7 | - { platform: github, user_url: "https://github.com/charoitel/lambda-layer-canvas-nodejs" }
8 | - { platform: linkedin, user_url: "https://www.linkedin.com/in/charoitel" }
9 |
--------------------------------------------------------------------------------
/docs/_includes/custom-head.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_includes/disqus_comments.html:
--------------------------------------------------------------------------------
1 | {%- if page.comments != false and jekyll.environment == "production" -%}
2 |
3 |
4 |
19 | Please enable JavaScript to view the comments powered by Disqus.
20 | {%- endif -%}
21 |
--------------------------------------------------------------------------------
/docs/_includes/footer.html:
--------------------------------------------------------------------------------
1 |
30 |
--------------------------------------------------------------------------------
/docs/_includes/google-analytics.html:
--------------------------------------------------------------------------------
1 |
2 |
10 |
--------------------------------------------------------------------------------
/docs/_includes/head.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {%- seo -%}
6 |
7 | {%- feed_meta -%}
8 | {%- if jekyll.environment == 'production' and site.google_analytics -%}
9 | {%- include google-analytics.html -%}
10 | {%- endif -%}
11 |
12 | {%- include custom-head.html -%}
13 |
14 |
15 |
--------------------------------------------------------------------------------
/docs/_includes/header.html:
--------------------------------------------------------------------------------
1 |
32 |
--------------------------------------------------------------------------------
/docs/_includes/social-icons/devto.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_includes/social-icons/dribbble.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_includes/social-icons/facebook.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_includes/social-icons/flickr.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_includes/social-icons/github.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_includes/social-icons/gitlab.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_includes/social-icons/google_scholar.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_includes/social-icons/instagram.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_includes/social-icons/keybase.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/docs/_includes/social-icons/linkedin.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_includes/social-icons/mastodon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_includes/social-icons/microdotblog.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_includes/social-icons/pinterest.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/_includes/social-icons/rss.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_includes/social-icons/stackoverflow.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_includes/social-icons/telegram.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_includes/social-icons/twitter.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_includes/social-icons/youtube.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_includes/social-item.html:
--------------------------------------------------------------------------------
1 | {% assign entry = include.item %}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/docs/_includes/social.html:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/docs/_includes/svg_symbol.html:
--------------------------------------------------------------------------------
1 |
2 | {%- include social-icons/{{ include.key }}.svg -%}
3 |
4 |
--------------------------------------------------------------------------------
/docs/_layouts/base.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {%- include head.html -%}
5 |
6 |
7 |
8 | {%- include header.html -%}
9 |
10 |
11 |
12 | {{ content }}
13 |
14 |
15 |
16 | {%- include footer.html -%}
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/docs/_layouts/home.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: base
3 | ---
4 |
5 |
6 | {%- if page.title -%}
7 |
{{ page.title }}
8 | {%- endif -%}
9 |
10 | {{ content }}
11 |
12 |
13 | {% if site.paginate %}
14 | {% assign posts = paginator.posts %}
15 | {% else %}
16 | {% assign posts = site.posts %}
17 | {% endif %}
18 |
19 |
20 | {%- if posts.size > 0 -%}
21 | {%- if page.list_title -%}
22 |
{{ page.list_title }}
23 | {%- endif -%}
24 |
25 | {%- assign date_format = site.minima.date_format | default: "%b %-d, %Y" -%}
26 | {%- for post in posts -%}
27 |
28 | {{ post.date | date: date_format }}
29 |
34 | {%- if site.show_excerpts -%}
35 | {{ post.excerpt }}
36 | {%- endif -%}
37 |
38 | {%- endfor -%}
39 |
40 |
41 | {% if site.paginate %}
42 |
57 | {%- endif %}
58 |
59 | {%- endif -%}
60 |
61 |
--------------------------------------------------------------------------------
/docs/_layouts/page.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: base
3 | ---
4 |
5 |
6 |
9 |
10 |
11 | {{ content }}
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/docs/_layouts/post.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: base
3 | ---
4 |
5 |
6 |
28 |
29 |
30 | {{ content }}
31 |
32 |
33 | {%- if site.disqus.shortname -%}
34 | {%- include disqus_comments.html -%}
35 | {%- endif -%}
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/docs/_sass/minima/_base.scss:
--------------------------------------------------------------------------------
1 | html {
2 | font-size: $base-font-size;
3 | }
4 |
5 | /**
6 | * Reset some basic elements
7 | */
8 | body, h1, h2, h3, h4, h5, h6,
9 | p, blockquote, pre, hr,
10 | dl, dd, ol, ul, figure {
11 | margin: 0;
12 | padding: 0;
13 |
14 | }
15 |
16 |
17 |
18 | /**
19 | * Basic styling
20 | */
21 | body {
22 | font: $base-font-weight #{$base-font-size}/#{$base-line-height} $base-font-family;
23 | color: $text-color;
24 | background-color: $background-color;
25 | -webkit-text-size-adjust: 100%;
26 | -webkit-font-feature-settings: "kern" 1;
27 | -moz-font-feature-settings: "kern" 1;
28 | -o-font-feature-settings: "kern" 1;
29 | font-feature-settings: "kern" 1;
30 | font-kerning: normal;
31 | display: flex;
32 | min-height: 100vh;
33 | flex-direction: column;
34 | overflow-wrap: break-word;
35 | }
36 |
37 |
38 |
39 | /**
40 | * Set `margin-bottom` to maintain vertical rhythm
41 | */
42 | h1, h2, h3, h4, h5, h6,
43 | p, blockquote, pre,
44 | ul, ol, dl, figure,
45 | %vertical-rhythm {
46 | margin-bottom: $spacing-unit * .5;
47 | }
48 |
49 | hr {
50 | margin-top: $spacing-unit;
51 | margin-bottom: $spacing-unit;
52 | }
53 |
54 | /**
55 | * `main` element
56 | */
57 | main {
58 | display: block; /* Default value of `display` of `main` element is 'inline' in IE 11. */
59 | }
60 |
61 |
62 |
63 | /**
64 | * Images
65 | */
66 | img {
67 | max-width: 100%;
68 | vertical-align: middle;
69 | }
70 |
71 |
72 |
73 | /**
74 | * Figures
75 | */
76 | figure > img {
77 | display: block;
78 | }
79 |
80 | figcaption {
81 | font-size: $small-font-size;
82 | }
83 |
84 |
85 |
86 | /**
87 | * Lists
88 | */
89 | ul, ol {
90 | margin-left: $spacing-unit;
91 | }
92 |
93 | li {
94 | > ul,
95 | > ol {
96 | margin-bottom: 0;
97 | }
98 | }
99 |
100 |
101 |
102 | /**
103 | * Headings
104 | */
105 | h1, h2, h3, h4, h5, h6 {
106 | font-weight: $base-font-weight;
107 | }
108 |
109 |
110 |
111 | /**
112 | * Links
113 | */
114 | a {
115 | color: $link-base-color;
116 | text-decoration: none;
117 |
118 | &:visited {
119 | color: $link-visited-color;
120 | }
121 |
122 | &:hover {
123 | color: $link-hover-color;
124 | text-decoration: underline;
125 | }
126 |
127 | .social-media-list &:hover {
128 | text-decoration: none;
129 |
130 | .username {
131 | text-decoration: underline;
132 | }
133 | }
134 | }
135 |
136 |
137 | /**
138 | * Blockquotes
139 | */
140 | blockquote {
141 | color: $brand-color;
142 | border-left: 4px solid $border-color-01;
143 | padding-left: $spacing-unit * .5;
144 | @include relative-font-size(1.125);
145 | font-style: italic;
146 |
147 | > :last-child {
148 | margin-bottom: 0;
149 | }
150 |
151 | i, em {
152 | font-style: normal;
153 | }
154 | }
155 |
156 |
157 |
158 | /**
159 | * Code formatting
160 | */
161 | pre,
162 | code {
163 | font-family: $code-font-family;
164 | font-size: 0.9375em;
165 | border: 1px solid $border-color-01;
166 | border-radius: 3px;
167 | background-color: $code-background-color;
168 | }
169 |
170 | code {
171 | padding: 1px 5px;
172 | }
173 |
174 | pre {
175 | padding: 8px 12px;
176 | overflow-x: auto;
177 |
178 | > code {
179 | border: 0;
180 | padding-right: 0;
181 | padding-left: 0;
182 | }
183 | }
184 |
185 | .highlight {
186 | border-radius: 3px;
187 | background: $code-background-color;
188 | @extend %vertical-rhythm;
189 |
190 | .highlighter-rouge & {
191 | background: $code-background-color;
192 | }
193 | }
194 |
195 |
196 |
197 | /**
198 | * Wrapper
199 | */
200 | .wrapper {
201 | max-width: calc(#{$content-width} - (#{$spacing-unit}));
202 | margin-right: auto;
203 | margin-left: auto;
204 | padding-right: $spacing-unit * .5;
205 | padding-left: $spacing-unit * .5;
206 | @extend %clearfix;
207 |
208 | @media screen and (min-width: $on-large) {
209 | max-width: calc(#{$content-width} - (#{$spacing-unit} * 2));
210 | padding-right: $spacing-unit;
211 | padding-left: $spacing-unit;
212 | }
213 | }
214 |
215 |
216 |
217 | /**
218 | * Clearfix
219 | */
220 | %clearfix:after {
221 | content: "";
222 | display: table;
223 | clear: both;
224 | }
225 |
226 |
227 |
228 | /**
229 | * Icons
230 | */
231 |
232 | .orange {
233 | color: #f66a0a;
234 | }
235 |
236 | .grey {
237 | color: #828282;
238 | }
239 |
240 | .svg-icon {
241 | width: 1.25em;
242 | height: 1.25em;
243 | display: inline-block;
244 | fill: currentColor;
245 | vertical-align: text-bottom;
246 | }
247 |
248 |
249 | /**
250 | * Tables
251 | */
252 | table {
253 | margin-bottom: $spacing-unit;
254 | width: 100%;
255 | text-align: $table-text-align;
256 | color: $table-text-color;
257 | border-collapse: collapse;
258 | border: 1px solid $table-border-color;
259 | tr {
260 | &:nth-child(even) {
261 | background-color: $table-zebra-color;
262 | }
263 | }
264 | th, td {
265 | padding: ($spacing-unit * 33.3333333333 * .01) ($spacing-unit * .5);
266 | }
267 | th {
268 | background-color: $table-header-bg-color;
269 | border: 1px solid $table-header-border;
270 | }
271 | td {
272 | border: 1px solid $table-border-color;
273 | }
274 |
275 | @include media-query($on-laptop) {
276 | display: block;
277 | overflow-x: auto;
278 | -webkit-overflow-scrolling: touch;
279 | -ms-overflow-style: -ms-autohiding-scrollbar;
280 | }
281 | }
282 |
--------------------------------------------------------------------------------
/docs/_sass/minima/_layout.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Site header
3 | */
4 | .site-header {
5 | border-top: 5px solid $border-color-03;
6 | border-bottom: 1px solid $border-color-01;
7 | min-height: $spacing-unit * 1.865;
8 | line-height: $base-line-height * $base-font-size * 2.25;
9 |
10 | // Positioning context for the mobile navigation icon
11 | position: relative;
12 | }
13 |
14 | .site-title {
15 | @include relative-font-size(1.625);
16 | font-weight: 300;
17 | letter-spacing: -1px;
18 | margin-bottom: 0;
19 | float: left;
20 |
21 | @include media-query($on-palm) {
22 | padding-right: 45px;
23 | }
24 |
25 | &,
26 | &:visited {
27 | color: $site-title-color;
28 | }
29 | }
30 |
31 | .site-nav {
32 | position: absolute;
33 | top: 9px;
34 | right: $spacing-unit * .5;
35 | background-color: $background-color;
36 | border: 1px solid $border-color-01;
37 | border-radius: 5px;
38 | text-align: right;
39 |
40 | .nav-trigger {
41 | display: none;
42 | }
43 |
44 | .menu-icon {
45 | float: right;
46 | width: 36px;
47 | height: 26px;
48 | line-height: 0;
49 | padding-top: 10px;
50 | text-align: center;
51 |
52 | > svg path {
53 | fill: $border-color-03;
54 | }
55 | }
56 |
57 | label[for="nav-trigger"] {
58 | display: block;
59 | float: right;
60 | width: 36px;
61 | height: 36px;
62 | z-index: 2;
63 | cursor: pointer;
64 | }
65 |
66 | input ~ .trigger {
67 | clear: both;
68 | display: none;
69 | }
70 |
71 | input:checked ~ .trigger {
72 | display: block;
73 | padding-bottom: 5px;
74 | }
75 |
76 | .page-link {
77 | color: $text-color;
78 | line-height: $base-line-height;
79 | display: block;
80 | padding: 5px 10px;
81 |
82 | // Gaps between nav items, but not on the last one
83 | &:not(:last-child) {
84 | margin-right: 0;
85 | }
86 | margin-left: 20px;
87 | }
88 |
89 | @media screen and (min-width: $on-medium) {
90 | position: static;
91 | float: right;
92 | border: none;
93 | background-color: inherit;
94 |
95 | label[for="nav-trigger"] {
96 | display: none;
97 | }
98 |
99 | .menu-icon {
100 | display: none;
101 | }
102 |
103 | input ~ .trigger {
104 | display: block;
105 | }
106 |
107 | .page-link {
108 | display: inline;
109 | padding: 0;
110 |
111 | &:not(:last-child) {
112 | margin-right: 20px;
113 | }
114 | margin-left: auto;
115 | }
116 | }
117 | }
118 |
119 |
120 |
121 | /**
122 | * Site footer
123 | */
124 | .site-footer {
125 | border-top: 1px solid $border-color-01;
126 | padding: $spacing-unit 0;
127 | }
128 |
129 | .footer-heading {
130 | @include relative-font-size(1.125);
131 | margin-bottom: $spacing-unit * .5;
132 | }
133 |
134 | .feed-subscribe .svg-icon {
135 | padding: 5px 5px 2px 0
136 | }
137 |
138 | .contact-list,
139 | .social-media-list {
140 | list-style: none;
141 | margin-left: 0;
142 | }
143 |
144 | .footer-col-wrapper,
145 | .social-links {
146 | @include relative-font-size(0.9375);
147 | color: $brand-color;
148 | }
149 |
150 | .footer-col {
151 | margin-bottom: $spacing-unit * .5;
152 | }
153 |
154 | .footer-col-1,
155 | .footer-col-2 {
156 | width: calc(50% - (#{$spacing-unit} / 2));
157 | }
158 |
159 | .footer-col-3 {
160 | width: calc(100% - (#{$spacing-unit} / 2));
161 | }
162 |
163 | @media screen and (min-width: $on-large) {
164 | .footer-col-1 {
165 | width: calc(35% - (#{$spacing-unit} / 2));
166 | }
167 |
168 | .footer-col-2 {
169 | width: calc(20% - (#{$spacing-unit} / 2));
170 | }
171 |
172 | .footer-col-3 {
173 | width: calc(45% - (#{$spacing-unit} / 2));
174 | }
175 | }
176 |
177 | @media screen and (min-width: $on-medium) {
178 | .footer-col-wrapper {
179 | display: flex
180 | }
181 |
182 | .footer-col {
183 | width: calc(100% - (#{$spacing-unit} / 2));
184 | padding: 0 ($spacing-unit * .5);
185 |
186 | &:first-child {
187 | padding-right: $spacing-unit * .5;
188 | padding-left: 0;
189 | }
190 |
191 | &:last-child {
192 | padding-right: 0;
193 | padding-left: $spacing-unit * .5;
194 | }
195 | }
196 | }
197 |
198 |
199 |
200 | /**
201 | * Page content
202 | */
203 | .page-content {
204 | padding: $spacing-unit 0;
205 | flex: 1 0 auto;
206 | }
207 |
208 | .page-heading {
209 | @include relative-font-size(2);
210 | }
211 |
212 | .post-list-heading {
213 | @include relative-font-size(1.75);
214 | }
215 |
216 | .post-list {
217 | margin-left: 0;
218 | list-style: none;
219 |
220 | > li {
221 | margin-bottom: $spacing-unit;
222 | }
223 | }
224 |
225 | .post-meta {
226 | font-size: $small-font-size;
227 | color: $brand-color;
228 | }
229 |
230 | .post-link {
231 | display: block;
232 | @include relative-font-size(1.5);
233 | }
234 |
235 |
236 |
237 | /**
238 | * Posts
239 | */
240 | .post-header {
241 | margin-bottom: $spacing-unit;
242 | }
243 |
244 | .post-title,
245 | .post-content h1 {
246 | @include relative-font-size(2.625);
247 | letter-spacing: -1px;
248 | line-height: 1.15;
249 |
250 | @media screen and (min-width: $on-large) {
251 | @include relative-font-size(2.625);
252 | }
253 | }
254 |
255 | .post-content {
256 | margin-bottom: $spacing-unit;
257 |
258 | h1, h2, h3, h4, h5, h6 { margin-top: $spacing-unit }
259 |
260 | h2 {
261 | @include relative-font-size(1.75);
262 |
263 | @media screen and (min-width: $on-large) {
264 | @include relative-font-size(2);
265 | }
266 | }
267 |
268 | h3 {
269 | @include relative-font-size(1.375);
270 |
271 | @media screen and (min-width: $on-large) {
272 | @include relative-font-size(1.625);
273 | }
274 | }
275 |
276 | h4 {
277 | @include relative-font-size(1.25);
278 | }
279 |
280 | h5 {
281 | @include relative-font-size(1.125);
282 | }
283 | h6 {
284 | @include relative-font-size(1.0625);
285 | }
286 | }
287 |
288 |
289 | .social-media-list {
290 | display: table;
291 | margin: 0 auto;
292 | li {
293 | float: left;
294 | margin: 5px 10px 5px 0;
295 | &:last-of-type { margin-right: 0 }
296 | a {
297 | display: block;
298 | padding: 10px 12px;
299 | border: 1px solid $border-color-01;
300 | &:hover { border-color: $border-color-02 }
301 | }
302 | }
303 | }
304 |
305 |
306 |
307 | /**
308 | * Pagination navbar
309 | */
310 | .pagination {
311 | margin-bottom: $spacing-unit;
312 | @extend .social-media-list;
313 | li {
314 | a, div {
315 | min-width: 41px;
316 | text-align: center;
317 | box-sizing: border-box;
318 | }
319 | div {
320 | display: block;
321 | padding: $spacing-unit * .25;
322 | border: 1px solid transparent;
323 |
324 | &.pager-edge {
325 | color: $border-color-01;
326 | border: 1px dashed;
327 | }
328 | }
329 | }
330 | }
331 |
332 |
333 |
334 | /**
335 | * Grid helpers
336 | */
337 | @media screen and (min-width: $on-large) {
338 | .one-half {
339 | width: calc(50% - (#{$spacing-unit} / 2));
340 | }
341 | }
342 |
--------------------------------------------------------------------------------
/docs/_sass/minima/custom-styles.scss:
--------------------------------------------------------------------------------
1 | // Placeholder to allow defining custom styles that override everything else.
2 | // (Use `_sass/minima/custom-variables.scss` to override variable defaults)
3 |
--------------------------------------------------------------------------------
/docs/_sass/minima/custom-variables.scss:
--------------------------------------------------------------------------------
1 | // Placeholder to allow overriding predefined variables smoothly.
2 |
--------------------------------------------------------------------------------
/docs/_sass/minima/initialize.scss:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 |
3 | // Define defaults for each variable.
4 |
5 | $base-font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Segoe UI Emoji", "Segoe UI Symbol", "Apple Color Emoji", Roboto, Helvetica, Arial, sans-serif !default;
6 | $code-font-family: "Menlo", "Inconsolata", "Consolas", "Roboto Mono", "Ubuntu Mono", "Liberation Mono", "Courier New", monospace;
7 | $base-font-size: 16px !default;
8 | $base-font-weight: 400 !default;
9 | $small-font-size: $base-font-size * 0.875 !default;
10 | $base-line-height: 1.5 !default;
11 |
12 | $spacing-unit: 30px !default;
13 |
14 | $table-text-align: left !default;
15 |
16 | // Width of the content area
17 | $content-width: 800px !default;
18 |
19 | $on-palm: 600px !default;
20 | $on-laptop: 800px !default;
21 |
22 | $on-medium: $on-palm !default;
23 | $on-large: $on-laptop !default;
24 |
25 | // Use media queries like this:
26 | // @include media-query($on-palm) {
27 | // .wrapper {
28 | // padding-right: $spacing-unit / 2;
29 | // padding-left: $spacing-unit / 2;
30 | // }
31 | // }
32 | // Notice the following mixin uses max-width, in a deprecated, desktop-first
33 | // approach, whereas media queries used elsewhere now use min-width.
34 | @mixin media-query($device) {
35 | @media screen and (max-width: $device) {
36 | @content;
37 | }
38 | }
39 |
40 | @mixin relative-font-size($ratio) {
41 | font-size: #{$ratio}rem;
42 | }
43 |
44 | // Import pre-styling-overrides hook and style-partials.
45 | @import
46 | "minima/custom-variables", // Hook to override predefined variables.
47 | "minima/base", // Defines element resets.
48 | "minima/layout", // Defines structure and style based on CSS selectors.
49 | "minima/custom-styles" // Hook to override existing styles.
50 | ;
51 |
--------------------------------------------------------------------------------
/docs/_sass/minima/skins/auto.scss:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 |
3 | // Default color scheme settings
4 | // These are overridden in classic.css and dark.scss
5 |
6 | $color-scheme-auto: true !default;
7 | $color-scheme-dark: false !default;
8 |
9 |
10 | // Light mode
11 | // ----------
12 |
13 | $lm-brand-color: #828282 !default;
14 | $lm-brand-color-light: lighten($lm-brand-color, 40%) !default;
15 | $lm-brand-color-dark: darken($lm-brand-color, 25%) !default;
16 |
17 | $lm-site-title-color: $lm-brand-color-dark !default;
18 |
19 | $lm-text-color: #111111 !default;
20 | $lm-background-color: #fdfdfd !default;
21 | $lm-code-background-color: #eeeeff !default;
22 |
23 | $lm-link-base-color: #2a7ae2 !default;
24 | $lm-link-visited-color: darken($lm-link-base-color, 15%) !default;
25 | $lm-link-hover-color: $lm-text-color !default;
26 |
27 | $lm-border-color-01: $lm-brand-color-light !default;
28 | $lm-border-color-02: lighten($lm-brand-color, 35%) !default;
29 | $lm-border-color-03: $lm-brand-color-dark !default;
30 |
31 | $lm-table-text-color: lighten($lm-text-color, 18%) !default;
32 | $lm-table-zebra-color: lighten($lm-brand-color, 46%) !default;
33 | $lm-table-header-bg-color: lighten($lm-brand-color, 43%) !default;
34 | $lm-table-header-border: lighten($lm-brand-color, 37%) !default;
35 | $lm-table-border-color: $lm-border-color-01 !default;
36 |
37 |
38 | // Syntax highlighting styles should be adjusted appropriately for every "skin"
39 | // ----------------------------------------------------------------------------
40 |
41 | @mixin lm-highlight {
42 | .highlight {
43 | .c { color: #998; font-style: italic } // Comment
44 | .err { color: #a61717; background-color: #e3d2d2 } // Error
45 | .k { font-weight: bold } // Keyword
46 | .o { font-weight: bold } // Operator
47 | .cm { color: #998; font-style: italic } // Comment.Multiline
48 | .cp { color: #999; font-weight: bold } // Comment.Preproc
49 | .c1 { color: #998; font-style: italic } // Comment.Single
50 | .cs { color: #999; font-weight: bold; font-style: italic } // Comment.Special
51 | .gd { color: #000; background-color: #fdd } // Generic.Deleted
52 | .gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific
53 | .ge { font-style: italic } // Generic.Emph
54 | .gr { color: #a00 } // Generic.Error
55 | .gh { color: #999 } // Generic.Heading
56 | .gi { color: #000; background-color: #dfd } // Generic.Inserted
57 | .gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific
58 | .go { color: #888 } // Generic.Output
59 | .gp { color: #555 } // Generic.Prompt
60 | .gs { font-weight: bold } // Generic.Strong
61 | .gu { color: #aaa } // Generic.Subheading
62 | .gt { color: #a00 } // Generic.Traceback
63 | .kc { font-weight: bold } // Keyword.Constant
64 | .kd { font-weight: bold } // Keyword.Declaration
65 | .kp { font-weight: bold } // Keyword.Pseudo
66 | .kr { font-weight: bold } // Keyword.Reserved
67 | .kt { color: #458; font-weight: bold } // Keyword.Type
68 | .m { color: #099 } // Literal.Number
69 | .s { color: #d14 } // Literal.String
70 | .na { color: #008080 } // Name.Attribute
71 | .nb { color: #0086B3 } // Name.Builtin
72 | .nc { color: #458; font-weight: bold } // Name.Class
73 | .no { color: #008080 } // Name.Constant
74 | .ni { color: #800080 } // Name.Entity
75 | .ne { color: #900; font-weight: bold } // Name.Exception
76 | .nf { color: #900; font-weight: bold } // Name.Function
77 | .nn { color: #555 } // Name.Namespace
78 | .nt { color: #000080 } // Name.Tag
79 | .nv { color: #008080 } // Name.Variable
80 | .ow { font-weight: bold } // Operator.Word
81 | .w { color: #bbb } // Text.Whitespace
82 | .mf { color: #099 } // Literal.Number.Float
83 | .mh { color: #099 } // Literal.Number.Hex
84 | .mi { color: #099 } // Literal.Number.Integer
85 | .mo { color: #099 } // Literal.Number.Oct
86 | .sb { color: #d14 } // Literal.String.Backtick
87 | .sc { color: #d14 } // Literal.String.Char
88 | .sd { color: #d14 } // Literal.String.Doc
89 | .s2 { color: #d14 } // Literal.String.Double
90 | .se { color: #d14 } // Literal.String.Escape
91 | .sh { color: #d14 } // Literal.String.Heredoc
92 | .si { color: #d14 } // Literal.String.Interpol
93 | .sx { color: #d14 } // Literal.String.Other
94 | .sr { color: #009926 } // Literal.String.Regex
95 | .s1 { color: #d14 } // Literal.String.Single
96 | .ss { color: #990073 } // Literal.String.Symbol
97 | .bp { color: #999 } // Name.Builtin.Pseudo
98 | .vc { color: #008080 } // Name.Variable.Class
99 | .vg { color: #008080 } // Name.Variable.Global
100 | .vi { color: #008080 } // Name.Variable.Instance
101 | .il { color: #099 } // Literal.Number.Integer.Long
102 | }
103 | }
104 |
105 |
106 | // Dark mode
107 | // ---------
108 |
109 | $dm-brand-color: #999999 !default;
110 | $dm-brand-color-light: lighten($dm-brand-color, 5%) !default;
111 | $dm-brand-color-dark: darken($dm-brand-color, 35%) !default;
112 |
113 | $dm-site-title-color: $dm-brand-color-light !default;
114 |
115 | $dm-text-color: #bbbbbb !default;
116 | $dm-background-color: #181818 !default;
117 | $dm-code-background-color: #212121 !default;
118 |
119 | $dm-link-base-color: #79b8ff !default;
120 | $dm-link-visited-color: $dm-link-base-color !default;
121 | $dm-link-hover-color: $dm-text-color !default;
122 |
123 | $dm-border-color-01: $dm-brand-color-dark !default;
124 | $dm-border-color-02: $dm-brand-color-light !default;
125 | $dm-border-color-03: $dm-brand-color !default;
126 |
127 | $dm-table-text-color: $dm-text-color !default;
128 | $dm-table-zebra-color: lighten($dm-background-color, 4%) !default;
129 | $dm-table-header-bg-color: lighten($dm-background-color, 10%) !default;
130 | $dm-table-header-border: lighten($dm-background-color, 21%) !default;
131 | $dm-table-border-color: $dm-border-color-01 !default;
132 |
133 |
134 | // Syntax highlighting styles should be adjusted appropriately for every "skin"
135 | // List of tokens: https://github.com/rouge-ruby/rouge/wiki/List-of-tokens
136 | // Some colors come from Material Theme Darker:
137 | // https://github.com/material-theme/vsc-material-theme/blob/master/scripts/generator/settings/specific/darker-hc.ts
138 | // https://github.com/material-theme/vsc-material-theme/blob/master/scripts/generator/color-set.ts
139 | // ----------------------------------------------------------------------------
140 |
141 | @mixin dm-highlight {
142 | .highlight {
143 | .c { color: #545454; font-style: italic } // Comment
144 | .err { color: #f07178; background-color: #e3d2d2 } // Error
145 | .k { color: #89DDFF; font-weight: bold } // Keyword
146 | .o { font-weight: bold } // Operator
147 | .cm { color: #545454; font-style: italic } // Comment.Multiline
148 | .cp { color: #545454; font-weight: bold } // Comment.Preproc
149 | .c1 { color: #545454; font-style: italic } // Comment.Single
150 | .cs { color: #545454; font-weight: bold; font-style: italic } // Comment.Special
151 | .gd { color: #000; background-color: #fdd } // Generic.Deleted
152 | .gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific
153 | .ge { font-style: italic } // Generic.Emph
154 | .gr { color: #f07178 } // Generic.Error
155 | .gh { color: #999 } // Generic.Heading
156 | .gi { color: #000; background-color: #dfd } // Generic.Inserted
157 | .gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific
158 | .go { color: #888 } // Generic.Output
159 | .gp { color: #555 } // Generic.Prompt
160 | .gs { font-weight: bold } // Generic.Strong
161 | .gu { color: #aaa } // Generic.Subheading
162 | .gt { color: #f07178 } // Generic.Traceback
163 | .kc { font-weight: bold } // Keyword.Constant
164 | .kd { font-weight: bold } // Keyword.Declaration
165 | .kp { font-weight: bold } // Keyword.Pseudo
166 | .kr { font-weight: bold } // Keyword.Reserved
167 | .kt { color: #FFCB6B; font-weight: bold } // Keyword.Type
168 | .m { color: #F78C6C } // Literal.Number
169 | .s { color: #C3E88D } // Literal.String
170 | .na { color: #008080 } // Name.Attribute
171 | .nb { color: #EEFFFF } // Name.Builtin
172 | .nc { color: #FFCB6B; font-weight: bold } // Name.Class
173 | .no { color: #008080 } // Name.Constant
174 | .ni { color: #800080 } // Name.Entity
175 | .ne { color: #900; font-weight: bold } // Name.Exception
176 | .nf { color: #82AAFF; font-weight: bold } // Name.Function
177 | .nn { color: #555 } // Name.Namespace
178 | .nt { color: #FFCB6B } // Name.Tag
179 | .nv { color: #EEFFFF } // Name.Variable
180 | .ow { font-weight: bold } // Operator.Word
181 | .w { color: #EEFFFF } // Text.Whitespace
182 | .mf { color: #F78C6C } // Literal.Number.Float
183 | .mh { color: #F78C6C } // Literal.Number.Hex
184 | .mi { color: #F78C6C } // Literal.Number.Integer
185 | .mo { color: #F78C6C } // Literal.Number.Oct
186 | .sb { color: #C3E88D } // Literal.String.Backtick
187 | .sc { color: #C3E88D } // Literal.String.Char
188 | .sd { color: #C3E88D } // Literal.String.Doc
189 | .s2 { color: #C3E88D } // Literal.String.Double
190 | .se { color: #EEFFFF } // Literal.String.Escape
191 | .sh { color: #C3E88D } // Literal.String.Heredoc
192 | .si { color: #C3E88D } // Literal.String.Interpol
193 | .sx { color: #C3E88D } // Literal.String.Other
194 | .sr { color: #C3E88D } // Literal.String.Regex
195 | .s1 { color: #C3E88D } // Literal.String.Single
196 | .ss { color: #C3E88D } // Literal.String.Symbol
197 | .bp { color: #999 } // Name.Builtin.Pseudo
198 | .vc { color: #FFCB6B } // Name.Variable.Class
199 | .vg { color: #EEFFFF } // Name.Variable.Global
200 | .vi { color: #EEFFFF } // Name.Variable.Instance
201 | .il { color: #F78C6C } // Literal.Number.Integer.Long
202 | }
203 | }
204 |
205 |
206 | // Mode selection
207 | // --------------
208 |
209 |
210 | // Classic skin (always light mode)
211 | // Assign outside of the if construct to establish global variable scope
212 |
213 | $brand-color: $lm-brand-color;
214 | $brand-color-light: $lm-brand-color-light;
215 | $brand-color-dark: $lm-brand-color-dark;
216 |
217 | $site-title-color: $lm-site-title-color;
218 |
219 | $text-color: $lm-text-color;
220 | $background-color: $lm-background-color;
221 | $code-background-color: $lm-code-background-color;
222 |
223 | $link-base-color: $lm-link-base-color;
224 | $link-visited-color: $lm-link-visited-color;
225 | $link-hover-color: $lm-link-hover-color;
226 |
227 | $border-color-01: $lm-border-color-01;
228 | $border-color-02: $lm-border-color-02;
229 | $border-color-03: $lm-border-color-03;
230 |
231 | $table-text-color: $lm-table-text-color;
232 | $table-zebra-color: $lm-table-zebra-color;
233 | $table-header-bg-color: $lm-table-header-bg-color;
234 | $table-header-border: $lm-table-header-border;
235 | $table-border-color: $lm-table-border-color;
236 |
237 |
238 | @if $color-scheme-auto {
239 |
240 | // Auto mode
241 |
242 | :root {
243 | --minima-brand-color: #{$lm-brand-color};
244 | --minima-brand-color-light: #{$lm-brand-color-light};
245 | --minima-brand-color-dark: #{$lm-brand-color-dark};
246 |
247 | --minima-site-title-color: #{$lm-site-title-color};
248 |
249 | --minima-text-color: #{$lm-text-color};
250 | --minima-background-color: #{$lm-background-color};
251 | --minima-code-background-color: #{$lm-code-background-color};
252 |
253 | --minima-link-base-color: #{$lm-link-base-color};
254 | --minima-link-visited-color: #{$lm-link-visited-color};
255 | --minima-link-hover-color: #{$lm-link-hover-color};
256 |
257 | --minima-border-color-01: #{$lm-border-color-01};
258 | --minima-border-color-02: #{$lm-border-color-02};
259 | --minima-border-color-03: #{$lm-border-color-03};
260 |
261 | --minima-table-text-color: #{$lm-table-text-color};
262 | --minima-table-zebra-color: #{$lm-table-zebra-color};
263 | --minima-table-header-bg-color: #{$lm-table-header-bg-color};
264 | --minima-table-header-border: #{$lm-table-header-border};
265 | --minima-table-border-color: #{$lm-table-border-color};
266 | }
267 |
268 | @include lm-highlight;
269 |
270 | @media (prefers-color-scheme: dark) {
271 | :root {
272 | --minima-brand-color: #{$dm-brand-color};
273 | --minima-brand-color-light: #{$dm-brand-color-light};
274 | --minima-brand-color-dark: #{$dm-brand-color-dark};
275 |
276 | --minima-site-title-color: #{$dm-site-title-color};
277 |
278 | --minima-text-color: #{$dm-text-color};
279 | --minima-background-color: #{$dm-background-color};
280 | --minima-code-background-color: #{$dm-code-background-color};
281 |
282 | --minima-link-base-color: #{$dm-link-base-color};
283 | --minima-link-visited-color: #{$dm-link-visited-color};
284 | --minima-link-hover-color: #{$dm-link-hover-color};
285 |
286 | --minima-border-color-01: #{$dm-border-color-01};
287 | --minima-border-color-02: #{$dm-border-color-02};
288 | --minima-border-color-03: #{$dm-border-color-03};
289 |
290 | --minima-table-text-color: #{$dm-table-text-color};
291 | --minima-table-zebra-color: #{$dm-table-zebra-color};
292 | --minima-table-header-bg-color: #{$dm-table-header-bg-color};
293 | --minima-table-header-border: #{$dm-table-header-border};
294 | --minima-table-border-color: #{$dm-table-border-color};
295 | }
296 |
297 | @include dm-highlight;
298 | }
299 |
300 | $brand-color: var(--minima-brand-color);
301 | $brand-color-light: var(--minima-brand-color-light);
302 | $brand-color-dark: var(--minima-brand-color-dark);
303 |
304 | $site-title-color: var(--minima-site-title-color);
305 |
306 | $text-color: var(--minima-text-color);
307 | $background-color: var(--minima-background-color);
308 | $code-background-color: var(--minima-code-background-color);
309 |
310 | $link-base-color: var(--minima-link-base-color);
311 | $link-visited-color: var(--minima-link-visited-color);
312 | $link-hover-color: var(--minima-link-hover-color);
313 |
314 | $border-color-01: var(--minima-border-color-01);
315 | $border-color-02: var(--minima-border-color-02);
316 | $border-color-03: var(--minima-border-color-03);
317 |
318 | $table-text-color: var(--minima-table-text-color);
319 | $table-zebra-color: var(--minima-table-zebra-color);
320 | $table-header-bg-color: var(--minima-table-header-bg-color);
321 | $table-header-border: var(--minima-table-header-border);
322 | $table-border-color: var(--minima-table-border-color);
323 |
324 |
325 | } @else if $color-scheme-dark {
326 |
327 | // Dark skin (always dark mode)
328 |
329 | $brand-color: $dm-brand-color;
330 | $brand-color-light: $dm-brand-color-light;
331 | $brand-color-dark: $dm-brand-color-dark;
332 |
333 | $site-title-color: $dm-site-title-color;
334 |
335 | $text-color: $dm-text-color;
336 | $background-color: $dm-background-color;
337 | $code-background-color: $dm-code-background-color;
338 |
339 | $link-base-color: $dm-link-base-color;
340 | $link-visited-color: $dm-link-visited-color;
341 | $link-hover-color: $dm-link-hover-color;
342 |
343 | $border-color-01: $dm-border-color-01;
344 | $border-color-02: $dm-border-color-02;
345 | $border-color-03: $dm-border-color-03;
346 |
347 | $table-text-color: $dm-table-text-color;
348 | $table-zebra-color: $dm-table-zebra-color;
349 | $table-header-bg-color: $dm-table-header-bg-color;
350 | $table-header-border: $dm-table-header-border;
351 | $table-border-color: $dm-table-border-color;
352 |
353 | @include dm-highlight;
354 |
355 |
356 | } @else {
357 |
358 | // Classic skin syntax highlighting
359 | @include lm-highlight;
360 |
361 | }
362 |
--------------------------------------------------------------------------------
/docs/_sass/minima/skins/classic.scss:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 |
3 | $color-scheme-auto: false;
4 | $color-scheme-dark: false;
5 | @import "minima/skins/auto";
6 |
--------------------------------------------------------------------------------
/docs/_sass/minima/skins/dark.scss:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 |
3 | $color-scheme-auto: false;
4 | $color-scheme-dark: true;
5 | @import "minima/skins/auto";
6 |
--------------------------------------------------------------------------------
/docs/_sass/minima/skins/solarized-dark.scss:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 |
3 | $sol-is-auto: false;
4 | $sol-is-dark: true;
5 | @import "minima/skins/solarized";
6 |
--------------------------------------------------------------------------------
/docs/_sass/minima/skins/solarized-light.scss:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 |
3 | $sol-is-auto: false;
4 | @import "minima/skins/solarized";
5 |
--------------------------------------------------------------------------------
/docs/_sass/minima/skins/solarized.scss:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 |
3 | // Solarized skin
4 | // ==============
5 | // Created by Sander Voerman using the Solarized
6 | // color scheme by Ethan Schoonover .
7 |
8 | // This style sheet implements three options for the minima.skin setting:
9 | // "solarized-light" for light mode, "solarized-dark" for dark mode, and
10 | // "solarized" for light or dark mode depending on user preference.
11 | $sol-is-auto: true !default;
12 | $sol-is-dark: false !default;
13 |
14 |
15 | // Color scheme
16 | // ------------
17 | // The inline comments show the canonical L*a*b values for each color.
18 |
19 | $sol-base03: #002b36; // 15 -12 -12
20 | $sol-base02: #073642; // 20 -12 -12
21 | $sol-base01: #586e75; // 45 -07 -07
22 | $sol-base00: #657b83; // 50 -07 -07
23 | $sol-base0: #839496; // 60 -06 -03
24 | $sol-base1: #93a1a1; // 65 -05 -02
25 | $sol-base2: #eee8d5; // 92 -00 10
26 | $sol-base3: #fdf6e3; // 97 00 10
27 | $sol-yellow: #b58900; // 60 10 65
28 | $sol-orange: #cb4b16; // 50 50 55
29 | $sol-red: #dc322f; // 50 65 45
30 | $sol-magenta: #d33682; // 50 65 -05
31 | $sol-violet: #6c71c4; // 50 15 -45
32 | $sol-blue: #268bd2; // 55 -10 -45
33 | $sol-cyan: #2aa198; // 60 -35 -05
34 | $sol-green: #859900; // 60 -20 65
35 |
36 |
37 | // Mixed colors
38 | // ------------
39 | // While not part of the original Solarized base tones, these derived tones
40 | // are meant to replicate the visual style of the classic skin. They should
41 | // not be used in cases where sufficiently contrasting colors are needed.
42 |
43 | $sol-light-mix1: mix($sol-base1, $sol-base3);
44 | $sol-light-mix2: mix($sol-blue, $sol-base00);
45 | $sol-light-mix3: mix($sol-base2, $sol-base3);
46 | $sol-dark-mix1: mix($sol-base01, $sol-base03);
47 | $sol-dark-mix2: mix($sol-blue, $sol-base0);
48 | $sol-dark-mix3: mix($sol-base02, $sol-base03);
49 |
50 |
51 | // Mode selection
52 | // --------------
53 |
54 | $sol-mono3: $sol-base3;
55 | $sol-mono2: $sol-base2;
56 | $sol-mono1: $sol-base1;
57 | $sol-mono00: $sol-base00;
58 | $sol-mono01: $sol-base01;
59 | $sol-mix1: $sol-light-mix1;
60 | $sol-mix2: $sol-light-mix2;
61 | $sol-mix3: $sol-light-mix3;
62 |
63 | @if $sol-is-dark {
64 | $sol-mono3: $sol-base03;
65 | $sol-mono2: $sol-base02;
66 | $sol-mono1: $sol-base01;
67 | $sol-mono00: $sol-base0;
68 | $sol-mono01: $sol-base1;
69 | $sol-mix1: $sol-dark-mix1;
70 | $sol-mix2: $sol-dark-mix2;
71 | $sol-mix3: $sol-dark-mix3;
72 | }
73 |
74 | @if $sol-is-auto {
75 | :root {
76 | --solarized-mono3: #{$sol-base3};
77 | --solarized-mono2: #{$sol-base2};
78 | --solarized-mono1: #{$sol-base1};
79 | --solarized-mono00: #{$sol-base00};
80 | --solarized-mono01: #{$sol-base01};
81 | --solarized-mix1: #{$sol-light-mix1};
82 | --solarized-mix2: #{$sol-light-mix2};
83 | --solarized-mix3: #{$sol-light-mix3};
84 | }
85 |
86 | @media (prefers-color-scheme: dark) {
87 | :root {
88 | --solarized-mono3: #{$sol-base03};
89 | --solarized-mono2: #{$sol-base02};
90 | --solarized-mono1: #{$sol-base01};
91 | --solarized-mono00: #{$sol-base0};
92 | --solarized-mono01: #{$sol-base1};
93 | --solarized-mix1: #{$sol-dark-mix1};
94 | --solarized-mix2: #{$sol-dark-mix2};
95 | --solarized-mix3: #{$sol-dark-mix3};
96 | }
97 | }
98 |
99 | $sol-mono3: var(--solarized-mono3);
100 | $sol-mono2: var(--solarized-mono2);
101 | $sol-mono1: var(--solarized-mono1);
102 | $sol-mono00: var(--solarized-mono00);
103 | $sol-mono01: var(--solarized-mono01);
104 | $sol-mix1: var(--solarized-mix1);
105 | $sol-mix2: var(--solarized-mix2);
106 | $sol-mix3: var(--solarized-mix3);
107 | }
108 |
109 |
110 | // Minima color variables
111 | // ----------------------
112 |
113 | $brand-color: $sol-mono1 !default;
114 | $brand-color-light: $sol-mix1 !default;
115 | $brand-color-dark: $sol-mono00 !default;
116 |
117 | $site-title-color: $sol-mono00 !default;
118 |
119 | $text-color: $sol-mono01 !default;
120 | $background-color: $sol-mono3 !default;
121 | $code-background-color: $sol-mono2 !default;
122 |
123 | $link-base-color: $sol-blue !default;
124 | $link-visited-color: $sol-mix2 !default;
125 | $link-hover-color: $sol-mono00 !default;
126 |
127 | $border-color-01: $brand-color-light !default;
128 | $border-color-02: $sol-mono1 !default;
129 | $border-color-03: $sol-mono00 !default;
130 |
131 | $table-text-color: $sol-mono00 !default;
132 | $table-zebra-color: $sol-mix3 !default;
133 | $table-header-bg-color: $sol-mono2 !default;
134 | $table-header-border: $sol-mono1 !default;
135 | $table-border-color: $sol-mono1 !default;
136 |
137 |
138 | // Syntax highlighting styles
139 | // --------------------------
140 |
141 | .highlight {
142 | .c { color: $sol-mono1; font-style: italic } // Comment
143 | .err { color: $sol-red } // Error
144 | .k { color: $sol-mono01; font-weight: bold } // Keyword
145 | .o { color: $sol-mono01; font-weight: bold } // Operator
146 | .cm { color: $sol-mono1; font-style: italic } // Comment.Multiline
147 | .cp { color: $sol-mono1; font-weight: bold } // Comment.Preproc
148 | .c1 { color: $sol-mono1; font-style: italic } // Comment.Single
149 | .cs { color: $sol-mono1; font-weight: bold; font-style: italic } // Comment.Special
150 | .gd { color: $sol-red } // Generic.Deleted
151 | .gd .x { color: $sol-red } // Generic.Deleted.Specific
152 | .ge { color: $sol-mono00; font-style: italic } // Generic.Emph
153 | .gr { color: $sol-red } // Generic.Error
154 | .gh { color: $sol-mono1 } // Generic.Heading
155 | .gi { color: $sol-green } // Generic.Inserted
156 | .gi .x { color: $sol-green } // Generic.Inserted.Specific
157 | .go { color: $sol-mono00 } // Generic.Output
158 | .gp { color: $sol-mono00 } // Generic.Prompt
159 | .gs { color: $sol-mono01; font-weight: bold } // Generic.Strong
160 | .gu { color: $sol-mono1 } // Generic.Subheading
161 | .gt { color: $sol-red } // Generic.Traceback
162 | .kc { color: $sol-mono01; font-weight: bold } // Keyword.Constant
163 | .kd { color: $sol-mono01; font-weight: bold } // Keyword.Declaration
164 | .kp { color: $sol-mono01; font-weight: bold } // Keyword.Pseudo
165 | .kr { color: $sol-mono01; font-weight: bold } // Keyword.Reserved
166 | .kt { color: $sol-violet; font-weight: bold } // Keyword.Type
167 | .m { color: $sol-cyan } // Literal.Number
168 | .s { color: $sol-magenta } // Literal.String
169 | .na { color: $sol-cyan } // Name.Attribute
170 | .nb { color: $sol-blue } // Name.Builtin
171 | .nc { color: $sol-violet; font-weight: bold } // Name.Class
172 | .no { color: $sol-cyan } // Name.Constant
173 | .ni { color: $sol-violet } // Name.Entity
174 | .ne { color: $sol-violet; font-weight: bold } // Name.Exception
175 | .nf { color: $sol-blue; font-weight: bold } // Name.Function
176 | .nn { color: $sol-mono00 } // Name.Namespace
177 | .nt { color: $sol-blue } // Name.Tag
178 | .nv { color: $sol-cyan } // Name.Variable
179 | .ow { color: $sol-mono01; font-weight: bold } // Operator.Word
180 | .w { color: $sol-mono1 } // Text.Whitespace
181 | .mf { color: $sol-cyan } // Literal.Number.Float
182 | .mh { color: $sol-cyan } // Literal.Number.Hex
183 | .mi { color: $sol-cyan } // Literal.Number.Integer
184 | .mo { color: $sol-cyan } // Literal.Number.Oct
185 | .sb { color: $sol-magenta } // Literal.String.Backtick
186 | .sc { color: $sol-magenta } // Literal.String.Char
187 | .sd { color: $sol-magenta } // Literal.String.Doc
188 | .s2 { color: $sol-magenta } // Literal.String.Double
189 | .se { color: $sol-magenta } // Literal.String.Escape
190 | .sh { color: $sol-magenta } // Literal.String.Heredoc
191 | .si { color: $sol-magenta } // Literal.String.Interpol
192 | .sx { color: $sol-magenta } // Literal.String.Other
193 | .sr { color: $sol-green } // Literal.String.Regex
194 | .s1 { color: $sol-magenta } // Literal.String.Single
195 | .ss { color: $sol-magenta } // Literal.String.Symbol
196 | .bp { color: $sol-mono1 } // Name.Builtin.Pseudo
197 | .vc { color: $sol-cyan } // Name.Variable.Class
198 | .vg { color: $sol-cyan } // Name.Variable.Global
199 | .vi { color: $sol-cyan } // Name.Variable.Instance
200 | .il { color: $sol-cyan } // Literal.Number.Integer.Long
201 | }
202 |
--------------------------------------------------------------------------------
/docs/assets/DejaVuSansCircle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/docs/assets/DejaVuSansCircle.png
--------------------------------------------------------------------------------
/docs/assets/css/style.scss:
--------------------------------------------------------------------------------
1 | ---
2 | # Only the main Sass file needs front matter (the dashes are enough)
3 | ---
4 |
5 | @import
6 | "minima/skins/{{ site.minima.skin | default: 'classic' }}",
7 | "minima/initialize";
8 |
--------------------------------------------------------------------------------
/docs/assets/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/docs/assets/favicon.ico
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: home
3 | ---
4 |
5 |    
6 |
7 | Canvas Layer for AWS Lambda is published and available on [AWS Serverless Application Repository](https://serverlessrepo.aws.amazon.com/applications/arn:aws:serverlessrepo:us-east-1:990551184979:applications~lambda-layer-canvas-nodejs), and GitHub at [charoitel/lambda-layer-canvas-nodejs](https://github.com/charoitel/lambda-layer-canvas-nodejs). The layer aims to provide a Cairo backed Mozilla Web Canvas API implementation layer for AWS Lambda, powered by [node-canvas](https://github.com/Automattic/node-canvas).
8 |
9 | ## About node-canvas
10 |
11 | [node-canvas](https://github.com/Automattic/node-canvas) is a Cairo backed Canvas implementation for Node.js. It implements the [Mozilla Web Canvas API](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) as closely as possible. For the latest API compliance, you may check [Compatibility Status](https://github.com/Automattic/node-canvas/wiki/Compatibility-Status).
12 |
13 | ## How this layer is built?
14 |
15 | The layer is built from source of node-canvas npm package on [amazonlinux](https://hub.docker.com/_/amazonlinux) dev container instance, with following native dependencies installed. You may check the build layer script, ``` build-layer.sh ```, which is available in repository, for details.
16 |
17 | ```bash
18 | gcc-c++ cairo-devel pango-devel libjpeg-turbo-devel giflib-devel librsvg2-devel pango-devel bzip2-devel jq python3
19 | ```
20 |
21 | Since AWS Lambda is a secure and isolated runtime and execution environment, the layer aims to target AWS Lambda compatible and native build. As there are canvas libraries and frameworks relying on node-canvas running on Node.js runtime, this layer may also try to include and support those libraries and frameworks. Currently, following libraries and frameworks are included when building and packaging the layer:
22 |
23 | - [Chart.js](#chartjs-support)
24 | - [Fabric.js](#fabricjs-support)
25 | - [Konva](#konva-support)
26 |
27 | ### Chart.js support
28 |
29 | [Chart.js](https://github.com/chartjs/chart.js) provides a set of frequently used chart types, plugins, and customization options. In addition to a reasonable set of built-in chart types, there are also community-maintained chart types.
30 |
31 | ### Fabric.js support
32 |
33 | [Fabric.js](https://github.com/fabricjs/fabric.js) provides a missing and interactive object model for canvas, as well as an SVG parser, layer of interactivity, and a whole suite of other indispensable tools.
34 |
35 | ### Konva support
36 |
37 | [Konva](https://github.com/konvajs/konva) enables high performance animations, transitions, node nesting, layering, filtering, caching, event handling for desktop and mobile applications, and much more.
38 |
--------------------------------------------------------------------------------
/docs/minima.gemspec:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | Gem::Specification.new do |spec|
4 | spec.name = "minima"
5 | spec.version = "3.0.0.dev"
6 | spec.authors = ["Joel Glovier"]
7 | spec.email = ["jglovier@github.com"]
8 |
9 | spec.summary = "A beautiful, minimal theme for Jekyll."
10 | spec.homepage = "https://github.com/jekyll/minima"
11 | spec.license = "MIT"
12 |
13 | spec.metadata["plugin_type"] = "theme"
14 |
15 | spec.files = `git ls-files -z`.split("\x0").select do |f|
16 | f.match(%r!^(assets|_(includes|layouts|sass)/|(LICENSE|README)((\.(txt|md|markdown)|$)))!i)
17 | end
18 |
19 | spec.add_runtime_dependency "jekyll", ">= 3.5", "< 5.0"
20 | spec.add_runtime_dependency "jekyll-feed", "~> 0.9"
21 | spec.add_runtime_dependency "jekyll-seo-tag", "~> 2.1"
22 |
23 | spec.add_development_dependency "bundler"
24 | end
25 |
--------------------------------------------------------------------------------
/docs/script/bootstrap:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | gem install bundler
6 | bundle install
7 |
--------------------------------------------------------------------------------
/docs/script/build:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | echo "Building the example site..."
6 | bundle exec jekyll build
7 |
--------------------------------------------------------------------------------
/docs/script/cibuild:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | script/build
6 |
7 | if test -e "./_site/index.html";then
8 | echo "It builds!"
9 | rm -Rf _site
10 | else
11 | echo "Huh. That's odd. The example site doesn't seem to build."
12 | exit 1
13 | fi
14 |
15 | gem build minima.gemspec
16 |
--------------------------------------------------------------------------------
/docs/script/server:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | bundle exec jekyll serve
4 |
--------------------------------------------------------------------------------
/lib/libX11.so.6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libX11.so.6
--------------------------------------------------------------------------------
/lib/libXau.so.6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libXau.so.6
--------------------------------------------------------------------------------
/lib/libXext.so.6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libXext.so.6
--------------------------------------------------------------------------------
/lib/libXrender.so.1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libXrender.so.1
--------------------------------------------------------------------------------
/lib/libblkid.so.1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libblkid.so.1
--------------------------------------------------------------------------------
/lib/libbrotlicommon.so.1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libbrotlicommon.so.1
--------------------------------------------------------------------------------
/lib/libbrotlidec.so.1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libbrotlidec.so.1
--------------------------------------------------------------------------------
/lib/libbz2.so.1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libbz2.so.1
--------------------------------------------------------------------------------
/lib/libc.so.6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libc.so.6
--------------------------------------------------------------------------------
/lib/libcairo-gobject.so.2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libcairo-gobject.so.2
--------------------------------------------------------------------------------
/lib/libcairo.so.2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libcairo.so.2
--------------------------------------------------------------------------------
/lib/libdatrie.so.1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libdatrie.so.1
--------------------------------------------------------------------------------
/lib/libffi.so.8:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libffi.so.8
--------------------------------------------------------------------------------
/lib/libfontconfig.so.1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libfontconfig.so.1
--------------------------------------------------------------------------------
/lib/libfreetype.so.6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libfreetype.so.6
--------------------------------------------------------------------------------
/lib/libfribidi.so.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libfribidi.so.0
--------------------------------------------------------------------------------
/lib/libgcc_s.so.1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libgcc_s.so.1
--------------------------------------------------------------------------------
/lib/libgdk_pixbuf-2.0.so.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libgdk_pixbuf-2.0.so.0
--------------------------------------------------------------------------------
/lib/libgif.so.7:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libgif.so.7
--------------------------------------------------------------------------------
/lib/libgio-2.0.so.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libgio-2.0.so.0
--------------------------------------------------------------------------------
/lib/libglib-2.0.so.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libglib-2.0.so.0
--------------------------------------------------------------------------------
/lib/libgmodule-2.0.so.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libgmodule-2.0.so.0
--------------------------------------------------------------------------------
/lib/libgobject-2.0.so.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libgobject-2.0.so.0
--------------------------------------------------------------------------------
/lib/libgraphite2.so.3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libgraphite2.so.3
--------------------------------------------------------------------------------
/lib/libharfbuzz.so.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libharfbuzz.so.0
--------------------------------------------------------------------------------
/lib/libjpeg.so.62:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libjpeg.so.62
--------------------------------------------------------------------------------
/lib/liblzma.so.5:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/liblzma.so.5
--------------------------------------------------------------------------------
/lib/libm.so.6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libm.so.6
--------------------------------------------------------------------------------
/lib/libmount.so.1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libmount.so.1
--------------------------------------------------------------------------------
/lib/libpango-1.0.so.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libpango-1.0.so.0
--------------------------------------------------------------------------------
/lib/libpangocairo-1.0.so.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libpangocairo-1.0.so.0
--------------------------------------------------------------------------------
/lib/libpangoft2-1.0.so.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libpangoft2-1.0.so.0
--------------------------------------------------------------------------------
/lib/libpcre2-8.so.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libpcre2-8.so.0
--------------------------------------------------------------------------------
/lib/libpixman-1.so.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libpixman-1.so.0
--------------------------------------------------------------------------------
/lib/libpng16.so.16:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libpng16.so.16
--------------------------------------------------------------------------------
/lib/librsvg-2.so.2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/librsvg-2.so.2
--------------------------------------------------------------------------------
/lib/libselinux.so.1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libselinux.so.1
--------------------------------------------------------------------------------
/lib/libstdc++.so.6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libstdc++.so.6
--------------------------------------------------------------------------------
/lib/libthai.so.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libthai.so.0
--------------------------------------------------------------------------------
/lib/libxcb-render.so.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libxcb-render.so.0
--------------------------------------------------------------------------------
/lib/libxcb-shm.so.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libxcb-shm.so.0
--------------------------------------------------------------------------------
/lib/libxcb.so.1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libxcb.so.1
--------------------------------------------------------------------------------
/lib/libxml2.so.2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libxml2.so.2
--------------------------------------------------------------------------------
/lib/libz.so.1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charoitel/lambda-layer-canvas-nodejs/3a2157addadf0dbd46cf83ca9a36f4aa96c51ac1/lib/libz.so.1
--------------------------------------------------------------------------------
/nodejs/test/canvas-font.js:
--------------------------------------------------------------------------------
1 | let { registerFont, createCanvas } = require('canvas');
2 | var assert = require('assert');
3 |
4 | describe('Font', function() {
5 | describe('#registerFont', function() {
6 | it('should register defined Font by name', function() {
7 | registerFont('/usr/share/fonts/dejavu-sans-fonts/DejaVuSans.ttf', { family: 'DejaVu Sans' });
8 | });
9 | }),
10 | describe('#fillText', function() {
11 | it('should write defined Text in canvas', function() {
12 | registerFont('/usr/share/fonts/dejavu-sans-fonts/DejaVuSans-Bold.ttf', { family: 'DejaVu Sans Bold' });
13 | let canvas = createCanvas(300, 300);
14 | let ctx1 = canvas.getContext('2d');
15 | ctx1.font = '30px';
16 | ctx1.fillText('Default', 5, 25);
17 | let ctx2 = canvas.getContext('2d');
18 | ctx2.font = '30px "DejaVu Sans"';
19 | ctx2.fillText('DejaVu Sans', 5, 65);
20 | let ctx3 = canvas.getContext('2d');
21 | ctx3.font = '30px "DejaVu Sans Bold"';
22 | ctx3.fillText('DejaVu Sans Bold', 5, 95);
23 | // console.log(canvas.toDataURL());
24 | assert.strictEqual(canvas.toDataURL(), 'data:image/png;base64,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');
25 | })
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/nodejs/test/canvas-svg.js:
--------------------------------------------------------------------------------
1 | let { registerFont, createCanvas } = require('canvas');
2 | var assert = require('assert');
3 |
4 | describe('SVG', function () {
5 | describe('#fillTextInSVG', function () {
6 | it('should write defined Text in canvas', function () {
7 | registerFont('/usr/share/fonts/dejavu-sans-fonts/DejaVuSans-Bold.ttf', { family: 'DejaVu Sans Bold' });
8 | let canvas = createCanvas(300, 300, 'svg');
9 | let ctx1 = canvas.getContext('2d');
10 | ctx1.font = '30px';
11 | ctx1.fillText('Default', 5, 25);
12 | let ctx2 = canvas.getContext('2d');
13 | ctx2.font = '30px "DejaVu Sans"';
14 | ctx2.fillText('DejaVu Sans', 5, 65);
15 | let ctx3 = canvas.getContext('2d');
16 | ctx3.font = '30px "DejaVu Sans Bold"';
17 | ctx3.fillText('DejaVu Sans Bold', 5, 95);
18 | // console.log(canvas.toDataURL());
19 | assert.strictEqual(canvas.toDataURL(), "data:image/png;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMzAwIiBoZWlnaHQ9IjMwMCIgdmlld0JveD0iMCAwIDMwMCAzMDAiPgo8cGF0aCBmaWxsLXJ1bGU9Im5vbnplcm8iIGZpbGw9InJnYigwJSwgMCUsIDAlKSIgZmlsbC1vcGFjaXR5PSIxIiBkPSJNIDEwLjkwNjI1IDUuNTYyNSBMIDEwLjkwNjI1IDIyLjU2MjUgTCAxNC40ODQzNzUgMjIuNTYyNSBDIDE3LjQ5MjE4OCAyMi41NjI1IDE5LjY5NTMxMiAyMS44ODI4MTIgMjEuMDkzNzUgMjAuNTE1NjI1IEMgMjIuNSAxOS4xNTIzNDQgMjMuMjAzMTI1IDE2Ljk5NjA5NCAyMy4yMDMxMjUgMTQuMDQ2ODc1IEMgMjMuMjAzMTI1IDExLjEwOTM3NSAyMi41IDguOTY0ODQ0IDIxLjA5Mzc1IDcuNjA5Mzc1IEMgMTkuNjk1MzEyIDYuMjQ2MDk0IDE3LjQ5MjE4OCA1LjU2MjUgMTQuNDg0Mzc1IDUuNTYyNSBaIE0gNy45Mzc1IDMuMTI1IEwgMTQuMDMxMjUgMy4xMjUgQyAxOC4yNTc4MTIgMy4xMjUgMjEuMzYzMjgxIDQuMDExNzE5IDIzLjM0Mzc1IDUuNzgxMjUgQyAyNS4zMzIwMzEgNy41NDI5NjkgMjYuMzI4MTI1IDEwLjI5Njg3NSAyNi4zMjgxMjUgMTQuMDQ2ODc1IEMgMjYuMzI4MTI1IDE3LjgyMDMxMiAyNS4zMzIwMzEgMjAuNTg5ODQ0IDIzLjM0Mzc1IDIyLjM1OTM3NSBDIDIxLjM1MTU2MiAyNC4xMjEwOTQgMTguMjUgMjUgMTQuMDMxMjUgMjUgTCA3LjkzNzUgMjUgWiBNIDQ0Ljk2MDkzOCAxNi4xMjUgTCA0NC45NjA5MzggMTcuNDM3NSBMIDMyLjU3MDMxMiAxNy40Mzc1IEMgMzIuNjgzNTk0IDE5LjI5Mjk2OSAzMy4yNDIxODggMjAuNzEwOTM4IDM0LjI0MjE4OCAyMS42ODc1IEMgMzUuMjQyMTg4IDIyLjY1NjI1IDM2LjYzNjcxOSAyMy4xNDA2MjUgMzguNDI5Njg4IDIzLjE0MDYyNSBDIDM5LjQ2MDkzOCAyMy4xNDA2MjUgNDAuNDYwOTM4IDIzLjAxNTYyNSA0MS40Mjk2ODggMjIuNzY1NjI1IEMgNDIuNDA2MjUgMjIuNTA3ODEyIDQzLjM3NSAyMi4xMjEwOTQgNDQuMzM1OTM4IDIxLjYwOTM3NSBMIDQ0LjMzNTkzOCAyNC4xNzE4NzUgQyA0My4zNjcxODggMjQuNTc4MTI1IDQyLjM3MTA5NCAyNC44ODY3MTkgNDEuMzUxNTYyIDI1LjA5Mzc1IEMgNDAuMzM5ODQ0IDI1LjMxMjUgMzkuMzEyNSAyNS40MjE4NzUgMzguMjczNDM4IDI1LjQyMTg3NSBDIDM1LjY0ODQzOCAyNS40MjE4NzUgMzMuNTcwMzEyIDI0LjY2NDA2MiAzMi4wMzkwNjIgMjMuMTQwNjI1IEMgMzAuNTE1NjI1IDIxLjYyMTA5NCAyOS43NTc4MTIgMTkuNTU4NTk0IDI5Ljc1NzgxMiAxNi45NTMxMjUgQyAyOS43NTc4MTIgMTQuMjY1NjI1IDMwLjQ4MDQ2OSAxMi4xMzY3MTkgMzEuOTI5Njg4IDEwLjU2MjUgQyAzMy4zNzUgOC45OTIxODggMzUuMzM1OTM4IDguMjAzMTI1IDM3LjgwNDY4OCA4LjIwMzEyNSBDIDQwLjAxMTcxOSA4LjIwMzEyNSA0MS43NTc4MTIgOC45MTQwNjIgNDMuMDM5MDYyIDEwLjMyODEyNSBDIDQ0LjMyMDMxMiAxMS43NDYwOTQgNDQuOTYwOTM4IDEzLjY3OTY4OCA0NC45NjA5MzggMTYuMTI1IFogTSA0Mi4yNzM0MzggMTUuMzI4MTI1IEMgNDIuMjUgMTMuODU5Mzc1IDQxLjgzNTkzOCAxMi42ODc1IDQxLjAyMzQzOCAxMS44MTI1IEMgNDAuMjE4NzUgMTAuOTI5Njg4IDM5LjE1NjI1IDEwLjQ4NDM3NSAzNy44MzU5MzggMTAuNDg0Mzc1IEMgMzYuMzI0MjE5IDEwLjQ4NDM3NSAzNS4xMTcxODggMTAuOTE0MDYyIDM0LjIxMDkzOCAxMS43NjU2MjUgQyAzMy4zMTI1IDEyLjYwOTM3NSAzMi43OTY4NzUgMTMuODA0Njg4IDMyLjY2NDA2MiAxNS4zNDM3NSBaIE0gNTcuNjk5MjE5IDIuMjAzMTI1IEwgNTcuNjk5MjE5IDQuNDUzMTI1IEwgNTUuMTIxMDk0IDQuNDUzMTI1IEMgNTQuMTUyMzQ0IDQuNDUzMTI1IDUzLjQ4MDQ2OSA0LjY1MjM0NCA1My4xMDU0NjkgNS4wNDY4NzUgQyA1Mi43MzA0NjkgNS40MzM1OTQgNTIuNTQyOTY5IDYuMTMyODEyIDUyLjU0Mjk2OSA3LjE0MDYyNSBMIDUyLjU0Mjk2OSA4LjU5Mzc1IEwgNTYuOTgwNDY5IDguNTkzNzUgTCA1Ni45ODA0NjkgMTAuNjg3NSBMIDUyLjU0Mjk2OSAxMC42ODc1IEwgNTIuNTQyOTY5IDI1IEwgNDkuODI0MjE5IDI1IEwgNDkuODI0MjE5IDEwLjY4NzUgTCA0Ny4yNDYwOTQgMTAuNjg3NSBMIDQ3LjI0NjA5NCA4LjU5Mzc1IEwgNDkuODI0MjE5IDguNTkzNzUgTCA0OS44MjQyMTkgNy40NTMxMjUgQyA0OS44MjQyMTkgNS42MzI4MTIgNTAuMjQ2MDk0IDQuMzA0Njg4IDUxLjA4OTg0NCAzLjQ2ODc1IEMgNTEuOTQxNDA2IDIuNjI1IDUzLjI5Mjk2OSAyLjIwMzEyNSA1NS4xMzY3MTkgMi4yMDMxMjUgWiBNIDY3LjM5ODQzOCAxNi43NSBDIDY1LjIxODc1IDE2Ljc1IDYzLjcxMDkzOCAxNyA2Mi44NjcxODggMTcuNSBDIDYyLjAzMTI1IDE4IDYxLjYxNzE4OCAxOC44NTE1NjIgNjEuNjE3MTg4IDIwLjA0Njg3NSBDIDYxLjYxNzE4OCAyMS4wMDc4MTIgNjEuOTI5Njg4IDIxLjc2NTYyNSA2Mi41NTQ2ODggMjIuMzI4MTI1IEMgNjMuMTg3NSAyMi44OTA2MjUgNjQuMDQ2ODc1IDIzLjE3MTg3NSA2NS4xMzI4MTIgMjMuMTcxODc1IEMgNjYuNjIxMDk0IDIzLjE3MTg3NSA2Ny44MjAzMTIgMjIuNjQwNjI1IDY4LjcyNjU2MiAyMS41NzgxMjUgQyA2OS42MzI4MTIgMjAuNTE1NjI1IDcwLjA4NTkzOCAxOS4xMDkzNzUgNzAuMDg1OTM4IDE3LjM1OTM3NSBMIDcwLjA4NTkzOCAxNi43NSBaIE0gNzIuNzczNDM4IDE1LjY0MDYyNSBMIDcyLjc3MzQzOCAyNSBMIDcwLjA4NTkzOCAyNSBMIDcwLjA4NTkzOCAyMi41MTU2MjUgQyA2OS40Njg3NSAyMy41MDc4MTIgNjguNjk5MjE5IDI0LjI0MjE4OCA2Ny43NzM0MzggMjQuNzE4NzUgQyA2Ni44NTU0NjkgMjUuMTg3NSA2NS43MzQzNzUgMjUuNDIxODc1IDY0LjQxNDA2MiAyNS40MjE4NzUgQyA2Mi43MzQzNzUgMjUuNDIxODc1IDYxLjM5ODQzOCAyNC45NTMxMjUgNjAuMzk4NDM4IDI0LjAxNTYyNSBDIDU5LjQwNjI1IDIzLjA3MDMxMiA1OC45MTQwNjIgMjEuODA0Njg4IDU4LjkxNDA2MiAyMC4yMTg3NSBDIDU4LjkxNDA2MiAxOC4zNzUgNTkuNTMxMjUgMTYuOTg0Mzc1IDYwLjc3MzQzOCAxNi4wNDY4NzUgQyA2Mi4wMTE3MTkgMTUuMTA5Mzc1IDYzLjg1NTQ2OSAxNC42NDA2MjUgNjYuMzA0Njg4IDE0LjY0MDYyNSBMIDcwLjA4NTkzOCAxNC42NDA2MjUgTCA3MC4wODU5MzggMTQuMzc1IEMgNzAuMDg1OTM4IDEzLjEzNjcxOSA2OS42NzE4NzUgMTIuMTc5Njg4IDY4Ljg1MTU2MiAxMS41IEMgNjguMDM5MDYyIDEwLjgyNDIxOSA2Ni44OTg0MzggMTAuNDg0Mzc1IDY1LjQyOTY4OCAxMC40ODQzNzUgQyA2NC40OTIxODggMTAuNDg0Mzc1IDYzLjU3NDIxOSAxMC42MDE1NjIgNjIuNjc5Njg4IDEwLjgyODEyNSBDIDYxLjc5Mjk2OSAxMS4wNDY4NzUgNjAuOTM3NSAxMS4zODI4MTIgNjAuMTE3MTg4IDExLjgyODEyNSBMIDYwLjExNzE4OCA5LjM0Mzc1IEMgNjEuMTA1NDY5IDguOTYwOTM4IDYyLjA2MjUgOC42NzE4NzUgNjIuOTkyMTg4IDguNDg0Mzc1IEMgNjMuOTE3OTY5IDguMjk2ODc1IDY0LjgyMDMxMiA4LjIwMzEyNSA2NS42OTUzMTIgOC4yMDMxMjUgQyA2OC4wNzAzMTIgOC4yMDMxMjUgNjkuODM5ODQ0IDguODIwMzEyIDcxLjAwNzgxMiAxMC4wNDY4NzUgQyA3Mi4xODM1OTQgMTEuMjc3MzQ0IDcyLjc3MzQzOCAxMy4xNDA2MjUgNzIuNzczNDM4IDE1LjY0MDYyNSBaIE0gNzguMDUwNzgxIDE4LjUzMTI1IEwgNzguMDUwNzgxIDguNTkzNzUgTCA4MC43NTM5MDYgOC41OTM3NSBMIDgwLjc1MzkwNiAxOC40MjE4NzUgQyA4MC43NTM5MDYgMTkuOTc2NTYyIDgxLjA1NDY4OCAyMS4xNDA2MjUgODEuNjYwMTU2IDIxLjkyMTg3NSBDIDgyLjI2MTcxOSAyMi42OTUzMTIgODMuMTY3OTY5IDIzLjA3ODEyNSA4NC4zNzg5MDYgMjMuMDc4MTI1IEMgODUuODM1OTM4IDIzLjA3ODEyNSA4Ni45ODgyODEgMjIuNjE3MTg4IDg3LjgzMjAzMSAyMS42ODc1IEMgODguNjc1NzgxIDIwLjc2MTcxOSA4OS4wOTc2NTYgMTkuNDk2MDk0IDg5LjA5NzY1NiAxNy44OTA2MjUgTCA4OS4wOTc2NTYgOC41OTM3NSBMIDkxLjgwMDc4MSA4LjU5Mzc1IEwgOTEuODAwNzgxIDI1IEwgODkuMDk3NjU2IDI1IEwgODkuMDk3NjU2IDIyLjQ4NDM3NSBDIDg4LjQ0MTQwNiAyMy40NzY1NjIgODcuNjc5Njg4IDI0LjIxNDg0NCA4Ni44MTY0MDYgMjQuNzAzMTI1IEMgODUuOTQ5MjE5IDI1LjE3OTY4OCA4NC45NDkyMTkgMjUuNDIxODc1IDgzLjgxNjQwNiAyNS40MjE4NzUgQyA4MS45Mjk2ODggMjUuNDIxODc1IDgwLjQ5NjA5NCAyNC44Mzk4NDQgNzkuNTE5NTMxIDIzLjY3MTg3NSBDIDc4LjUzOTA2MiAyMi40OTYwOTQgNzguMDUwNzgxIDIwLjc4MTI1IDc4LjA1MDc4MSAxOC41MzEyNSBaIE0gODQuODMyMDMxIDguMjAzMTI1IFogTSA5Ny4zNDM3NSAyLjIwMzEyNSBMIDEwMC4wMzEyNSAyLjIwMzEyNSBMIDEwMC4wMzEyNSAyNSBMIDk3LjM0Mzc1IDI1IFogTSAxMDguMzUxNTYyIDMuOTM3NSBMIDEwOC4zNTE1NjIgOC41OTM3NSBMIDExMy44OTg0MzggOC41OTM3NSBMIDExMy44OTg0MzggMTAuNjg3NSBMIDEwOC4zNTE1NjIgMTAuNjg3NSBMIDEwOC4zNTE1NjIgMTkuNTkzNzUgQyAxMDguMzUxNTYyIDIwLjkyOTY4OCAxMDguNTMxMjUgMjEuNzg5MDYyIDEwOC44OTg0MzggMjIuMTcxODc1IEMgMTA5LjI2MTcxOSAyMi41NTg1OTQgMTEwLjAwNzgxMiAyMi43NSAxMTEuMTMyODEyIDIyLjc1IEwgMTEzLjg5ODQzOCAyMi43NSBMIDExMy44OTg0MzggMjUgTCAxMTEuMTMyODEyIDI1IEMgMTA5LjA0Njg3NSAyNSAxMDcuNjA5Mzc1IDI0LjYxNzE4OCAxMDYuODIwMzEyIDIzLjg0Mzc1IEMgMTA2LjAyNzM0NCAyMy4wNjI1IDEwNS42MzI4MTIgMjEuNjQ4NDM4IDEwNS42MzI4MTIgMTkuNTkzNzUgTCAxMDUuNjMyODEyIDEwLjY4NzUgTCAxMDMuNjY0MDYyIDEwLjY4NzUgTCAxMDMuNjY0MDYyIDguNTkzNzUgTCAxMDUuNjMyODEyIDguNTkzNzUgTCAxMDUuNjMyODEyIDMuOTM3NSBaIE0gNSAtMi44NDc2NTYgIi8+CjxwYXRoIGZpbGwtcnVsZT0ibm9uemVybyIgZmlsbD0icmdiKDAlLCAwJSwgMCUpIiBmaWxsLW9wYWNpdHk9IjEiIGQ9Ik0gMTAuOTA2MjUgNDUuNTYyNSBMIDEwLjkwNjI1IDYyLjU2MjUgTCAxNC40ODQzNzUgNjIuNTYyNSBDIDE3LjQ5MjE4OCA2Mi41NjI1IDE5LjY5NTMxMiA2MS44ODI4MTIgMjEuMDkzNzUgNjAuNTE1NjI1IEMgMjIuNSA1OS4xNTIzNDQgMjMuMjAzMTI1IDU2Ljk5NjA5NCAyMy4yMDMxMjUgNTQuMDQ2ODc1IEMgMjMuMjAzMTI1IDUxLjEwOTM3NSAyMi41IDQ4Ljk2NDg0NCAyMS4wOTM3NSA0Ny42MDkzNzUgQyAxOS42OTUzMTIgNDYuMjQ2MDk0IDE3LjQ5MjE4OCA0NS41NjI1IDE0LjQ4NDM3NSA0NS41NjI1IFogTSA3LjkzNzUgNDMuMTI1IEwgMTQuMDMxMjUgNDMuMTI1IEMgMTguMjU3ODEyIDQzLjEyNSAyMS4zNjMyODEgNDQuMDExNzE5IDIzLjM0Mzc1IDQ1Ljc4MTI1IEMgMjUuMzMyMDMxIDQ3LjU0Mjk2OSAyNi4zMjgxMjUgNTAuMjk2ODc1IDI2LjMyODEyNSA1NC4wNDY4NzUgQyAyNi4zMjgxMjUgNTcuODIwMzEyIDI1LjMzMjAzMSA2MC41ODk4NDQgMjMuMzQzNzUgNjIuMzU5Mzc1IEMgMjEuMzUxNTYyIDY0LjEyMTA5NCAxOC4yNSA2NSAxNC4wMzEyNSA2NSBMIDcuOTM3NSA2NSBaIE0gNDQuOTYwOTM4IDU2LjEyNSBMIDQ0Ljk2MDkzOCA1Ny40Mzc1IEwgMzIuNTcwMzEyIDU3LjQzNzUgQyAzMi42ODM1OTQgNTkuMjkyOTY5IDMzLjI0MjE4OCA2MC43MTA5MzggMzQuMjQyMTg4IDYxLjY4NzUgQyAzNS4yNDIxODggNjIuNjU2MjUgMzYuNjM2NzE5IDYzLjE0MDYyNSAzOC40Mjk2ODggNjMuMTQwNjI1IEMgMzkuNDYwOTM4IDYzLjE0MDYyNSA0MC40NjA5MzggNjMuMDE1NjI1IDQxLjQyOTY4OCA2Mi43NjU2MjUgQyA0Mi40MDYyNSA2Mi41MDc4MTIgNDMuMzc1IDYyLjEyMTA5NCA0NC4zMzU5MzggNjEuNjA5Mzc1IEwgNDQuMzM1OTM4IDY0LjE3MTg3NSBDIDQzLjM2NzE4OCA2NC41NzgxMjUgNDIuMzcxMDk0IDY0Ljg4NjcxOSA0MS4zNTE1NjIgNjUuMDkzNzUgQyA0MC4zMzk4NDQgNjUuMzEyNSAzOS4zMTI1IDY1LjQyMTg3NSAzOC4yNzM0MzggNjUuNDIxODc1IEMgMzUuNjQ4NDM4IDY1LjQyMTg3NSAzMy41NzAzMTIgNjQuNjY0MDYyIDMyLjAzOTA2MiA2My4xNDA2MjUgQyAzMC41MTU2MjUgNjEuNjIxMDk0IDI5Ljc1NzgxMiA1OS41NTg1OTQgMjkuNzU3ODEyIDU2Ljk1MzEyNSBDIDI5Ljc1NzgxMiA1NC4yNjU2MjUgMzAuNDgwNDY5IDUyLjEzNjcxOSAzMS45Mjk2ODggNTAuNTYyNSBDIDMzLjM3NSA0OC45OTIxODggMzUuMzM1OTM4IDQ4LjIwMzEyNSAzNy44MDQ2ODggNDguMjAzMTI1IEMgNDAuMDExNzE5IDQ4LjIwMzEyNSA0MS43NTc4MTIgNDguOTE0MDYyIDQzLjAzOTA2MiA1MC4zMjgxMjUgQyA0NC4zMjAzMTIgNTEuNzQ2MDk0IDQ0Ljk2MDkzOCA1My42Nzk2ODggNDQuOTYwOTM4IDU2LjEyNSBaIE0gNDIuMjczNDM4IDU1LjMyODEyNSBDIDQyLjI1IDUzLjg1OTM3NSA0MS44MzU5MzggNTIuNjg3NSA0MS4wMjM0MzggNTEuODEyNSBDIDQwLjIxODc1IDUwLjkyOTY4OCAzOS4xNTYyNSA1MC40ODQzNzUgMzcuODM1OTM4IDUwLjQ4NDM3NSBDIDM2LjMyNDIxOSA1MC40ODQzNzUgMzUuMTE3MTg4IDUwLjkxNDA2MiAzNC4yMTA5MzggNTEuNzY1NjI1IEMgMzMuMzEyNSA1Mi42MDkzNzUgMzIuNzk2ODc1IDUzLjgwNDY4OCAzMi42NjQwNjIgNTUuMzQzNzUgWiBNIDQ5LjM4NjcxOSA0OC41OTM3NSBMIDUyLjA3NDIxOSA0OC41OTM3NSBMIDUyLjA3NDIxOSA2NS4yOTY4NzUgQyA1Mi4wNzQyMTkgNjcuMzc4OTA2IDUxLjY3NTc4MSA2OC44OTA2MjUgNTAuODg2NzE5IDY5LjgyODEyNSBDIDUwLjA5Mzc1IDcwLjc2NTYyNSA0OC44MTI1IDcxLjIzNDM3NSA0Ny4wNDI5NjkgNzEuMjM0Mzc1IEwgNDYuMDExNzE5IDcxLjIzNDM3NSBMIDQ2LjAxMTcxOSA2OC45NTMxMjUgTCA0Ni43MzA0NjkgNjguOTUzMTI1IEMgNDcuNzYxNzE5IDY4Ljk1MzEyNSA0OC40NTcwMzEgNjguNzEwOTM4IDQ4LjgyNDIxOSA2OC4yMzQzNzUgQyA0OS4xOTkyMTkgNjcuNzY1NjI1IDQ5LjM4NjcxOSA2Ni43ODUxNTYgNDkuMzg2NzE5IDY1LjI5Njg3NSBaIE0gNDkuMzg2NzE5IDQyLjIwMzEyNSBMIDUyLjA3NDIxOSA0Mi4yMDMxMjUgTCA1Mi4wNzQyMTkgNDUuNjI1IEwgNDkuMzg2NzE5IDQ1LjYyNSBaIE0gNjUuMTcxODc1IDU2Ljc1IEMgNjIuOTkyMTg4IDU2Ljc1IDYxLjQ4NDM3NSA1NyA2MC42NDA2MjUgNTcuNSBDIDU5LjgwNDY4OCA1OCA1OS4zOTA2MjUgNTguODUxNTYyIDU5LjM5MDYyNSA2MC4wNDY4NzUgQyA1OS4zOTA2MjUgNjEuMDA3ODEyIDU5LjcwMzEyNSA2MS43NjU2MjUgNjAuMzI4MTI1IDYyLjMyODEyNSBDIDYwLjk2MDkzOCA2Mi44OTA2MjUgNjEuODIwMzEyIDYzLjE3MTg3NSA2Mi45MDYyNSA2My4xNzE4NzUgQyA2NC4zOTQ1MzEgNjMuMTcxODc1IDY1LjU5Mzc1IDYyLjY0MDYyNSA2Ni41IDYxLjU3ODEyNSBDIDY3LjQwNjI1IDYwLjUxNTYyNSA2Ny44NTkzNzUgNTkuMTA5Mzc1IDY3Ljg1OTM3NSA1Ny4zNTkzNzUgTCA2Ny44NTkzNzUgNTYuNzUgWiBNIDcwLjU0Njg3NSA1NS42NDA2MjUgTCA3MC41NDY4NzUgNjUgTCA2Ny44NTkzNzUgNjUgTCA2Ny44NTkzNzUgNjIuNTE1NjI1IEMgNjcuMjQyMTg4IDYzLjUwNzgxMiA2Ni40NzI2NTYgNjQuMjQyMTg4IDY1LjU0Njg3NSA2NC43MTg3NSBDIDY0LjYyODkwNiA2NS4xODc1IDYzLjUwNzgxMiA2NS40MjE4NzUgNjIuMTg3NSA2NS40MjE4NzUgQyA2MC41MDc4MTIgNjUuNDIxODc1IDU5LjE3MTg3NSA2NC45NTMxMjUgNTguMTcxODc1IDY0LjAxNTYyNSBDIDU3LjE3OTY4OCA2My4wNzAzMTIgNTYuNjg3NSA2MS44MDQ2ODggNTYuNjg3NSA2MC4yMTg3NSBDIDU2LjY4NzUgNTguMzc1IDU3LjMwNDY4OCA1Ni45ODQzNzUgNTguNTQ2ODc1IDU2LjA0Njg3NSBDIDU5Ljc4NTE1NiA1NS4xMDkzNzUgNjEuNjI4OTA2IDU0LjY0MDYyNSA2NC4wNzgxMjUgNTQuNjQwNjI1IEwgNjcuODU5Mzc1IDU0LjY0MDYyNSBMIDY3Ljg1OTM3NSA1NC4zNzUgQyA2Ny44NTkzNzUgNTMuMTM2NzE5IDY3LjQ0NTMxMiA1Mi4xNzk2ODggNjYuNjI1IDUxLjUgQyA2NS44MTI1IDUwLjgyNDIxOSA2NC42NzE4NzUgNTAuNDg0Mzc1IDYzLjIwMzEyNSA1MC40ODQzNzUgQyA2Mi4yNjU2MjUgNTAuNDg0Mzc1IDYxLjM0NzY1NiA1MC42MDE1NjIgNjAuNDUzMTI1IDUwLjgyODEyNSBDIDU5LjU2NjQwNiA1MS4wNDY4NzUgNTguNzEwOTM4IDUxLjM4MjgxMiA1Ny44OTA2MjUgNTEuODI4MTI1IEwgNTcuODkwNjI1IDQ5LjM0Mzc1IEMgNTguODc4OTA2IDQ4Ljk2MDkzOCA1OS44MzU5MzggNDguNjcxODc1IDYwLjc2NTYyNSA0OC40ODQzNzUgQyA2MS42OTE0MDYgNDguMjk2ODc1IDYyLjU5Mzc1IDQ4LjIwMzEyNSA2My40Njg3NSA0OC4yMDMxMjUgQyA2NS44NDM3NSA0OC4yMDMxMjUgNjcuNjEzMjgxIDQ4LjgyMDMxMiA2OC43ODEyNSA1MC4wNDY4NzUgQyA2OS45NTcwMzEgNTEuMjc3MzQ0IDcwLjU0Njg3NSA1My4xNDA2MjUgNzAuNTQ2ODc1IDU1LjY0MDYyNSBaIE0gODEuODU1NDY5IDY1IEwgNzMuNTExNzE5IDQzLjEyNSBMIDc2LjYwNTQ2OSA0My4xMjUgTCA4My41MjczNDQgNjEuNTQ2ODc1IEwgOTAuNDgwNDY5IDQzLjEyNSBMIDkzLjU1ODU5NCA0My4xMjUgTCA4NS4yMTQ4NDQgNjUgWiBNIDk0LjMwODU5NCA1OC41MzEyNSBMIDk0LjMwODU5NCA0OC41OTM3NSBMIDk3LjAxMTcxOSA0OC41OTM3NSBMIDk3LjAxMTcxOSA1OC40MjE4NzUgQyA5Ny4wMTE3MTkgNTkuOTc2NTYyIDk3LjMxMjUgNjEuMTQwNjI1IDk3LjkxNzk2OSA2MS45MjE4NzUgQyA5OC41MTk1MzEgNjIuNjk1MzEyIDk5LjQyNTc4MSA2My4wNzgxMjUgMTAwLjYzNjcxOSA2My4wNzgxMjUgQyAxMDIuMDkzNzUgNjMuMDc4MTI1IDEwMy4yNDYwOTQgNjIuNjE3MTg4IDEwNC4wODk4NDQgNjEuNjg3NSBDIDEwNC45MzM1OTQgNjAuNzYxNzE5IDEwNS4zNTU0NjkgNTkuNDk2MDk0IDEwNS4zNTU0NjkgNTcuODkwNjI1IEwgMTA1LjM1NTQ2OSA0OC41OTM3NSBMIDEwOC4wNTg1OTQgNDguNTkzNzUgTCAxMDguMDU4NTk0IDY1IEwgMTA1LjM1NTQ2OSA2NSBMIDEwNS4zNTU0NjkgNjIuNDg0Mzc1IEMgMTA0LjY5OTIxOSA2My40NzY1NjIgMTAzLjkzNzUgNjQuMjE0ODQ0IDEwMy4wNzQyMTkgNjQuNzAzMTI1IEMgMTAyLjIwNzAzMSA2NS4xNzk2ODggMTAxLjIwNzAzMSA2NS40MjE4NzUgMTAwLjA3NDIxOSA2NS40MjE4NzUgQyA5OC4xODc1IDY1LjQyMTg3NSA5Ni43NTM5MDYgNjQuODM5ODQ0IDk1Ljc3NzM0NCA2My42NzE4NzUgQyA5NC43OTY4NzUgNjIuNDk2MDk0IDk0LjMwODU5NCA2MC43ODEyNSA5NC4zMDg1OTQgNTguNTMxMjUgWiBNIDEwMS4wODk4NDQgNDguMjAzMTI1IFogTSAxMzYuMzc1IDQzLjg0Mzc1IEwgMTM2LjM3NSA0Ni43MzQzNzUgQyAxMzUuMjUgNDYuMTk1MzEyIDEzNC4xODc1IDQ1Ljc5Mjk2OSAxMzMuMTg3NSA0NS41MzEyNSBDIDEzMi4xODc1IDQ1LjI3MzQzOCAxMzEuMjIyNjU2IDQ1LjE0MDYyNSAxMzAuMjk2ODc1IDQ1LjE0MDYyNSBDIDEyOC42OTE0MDYgNDUuMTQwNjI1IDEyNy40NTMxMjUgNDUuNDUzMTI1IDEyNi41NzgxMjUgNDYuMDc4MTI1IEMgMTI1LjcwMzEyNSA0Ni43MDMxMjUgMTI1LjI2NTYyNSA0Ny41ODk4NDQgMTI1LjI2NTYyNSA0OC43MzQzNzUgQyAxMjUuMjY1NjI1IDQ5LjcwMzEyNSAxMjUuNTUwNzgxIDUwLjQzNzUgMTI2LjEyNSA1MC45Mzc1IEMgMTI2LjcwNzAzMSA1MS40Mjk2ODggMTI3LjgxMjUgNTEuODI0MjE5IDEyOS40Mzc1IDUyLjEyNSBMIDEzMS4yMTg3NSA1Mi40ODQzNzUgQyAxMzMuNDI1NzgxIDUyLjkxNDA2MiAxMzUuMDU0Njg4IDUzLjY1NjI1IDEzNi4xMDkzNzUgNTQuNzE4NzUgQyAxMzcuMTYwMTU2IDU1Ljc3MzQzOCAxMzcuNjg3NSA1Ny4xODc1IDEzNy42ODc1IDU4Ljk2ODc1IEMgMTM3LjY4NzUgNjEuMDg1OTM4IDEzNi45NzI2NTYgNjIuNjg3NSAxMzUuNTQ2ODc1IDYzLjc4MTI1IEMgMTM0LjEyODkwNiA2NC44NzUgMTMyLjA1MDc4MSA2NS40MjE4NzUgMTI5LjMxMjUgNjUuNDIxODc1IEMgMTI4LjI2OTUzMSA2NS40MjE4NzUgMTI3LjE2NDA2MiA2NS4zMDA3ODEgMTI2IDY1LjA2MjUgQyAxMjQuODMyMDMxIDY0LjgzNTkzOCAxMjMuNjI1IDY0LjQ5MjE4OCAxMjIuMzc1IDY0LjAzMTI1IEwgMTIyLjM3NSA2MC45ODQzNzUgQyAxMjMuNTgyMDMxIDYxLjY2NDA2MiAxMjQuNzU3ODEyIDYyLjE3MTg3NSAxMjUuOTA2MjUgNjIuNTE1NjI1IEMgMTI3LjA2MjUgNjIuODUxNTYyIDEyOC4xOTUzMTIgNjMuMDE1NjI1IDEyOS4zMTI1IDYzLjAxNTYyNSBDIDEzMSA2My4wMTU2MjUgMTMyLjMwMDc4MSA2Mi42ODc1IDEzMy4yMTg3NSA2Mi4wMzEyNSBDIDEzNC4xMzI4MTIgNjEuMzY3MTg4IDEzNC41OTM3NSA2MC40MTc5NjkgMTM0LjU5Mzc1IDU5LjE4NzUgQyAxMzQuNTkzNzUgNTguMTE3MTg4IDEzNC4yNjU2MjUgNTcuMjc3MzQ0IDEzMy42MDkzNzUgNTYuNjcxODc1IEMgMTMyLjk1MzEyNSA1Ni4wNTg1OTQgMTMxLjg2NzE4OCA1NS42MDE1NjIgMTMwLjM1OTM3NSA1NS4yOTY4NzUgTCAxMjguNTYyNSA1NC45NTMxMjUgQyAxMjYuMzUxNTYyIDU0LjUxNTYyNSAxMjQuNzUzOTA2IDUzLjgyODEyNSAxMjMuNzY1NjI1IDUyLjg5MDYyNSBDIDEyMi43ODUxNTYgNTEuOTUzMTI1IDEyMi4yOTY4NzUgNTAuNjQ4NDM4IDEyMi4yOTY4NzUgNDguOTY4NzUgQyAxMjIuMjk2ODc1IDQ3LjA0Mjk2OSAxMjIuOTcyNjU2IDQ1LjUyMzQzOCAxMjQuMzI4MTI1IDQ0LjQwNjI1IEMgMTI1LjY5MTQwNiA0My4yOTI5NjkgMTI3LjU3MDMxMiA0Mi43MzQzNzUgMTI5Ljk2ODc1IDQyLjczNDM3NSBDIDEzMC45ODgyODEgNDIuNzM0Mzc1IDEzMi4wMzEyNSA0Mi44MjgxMjUgMTMzLjA5Mzc1IDQzLjAxNTYyNSBDIDEzNC4xNjQwNjIgNDMuMjAzMTI1IDEzNS4yNTc4MTIgNDMuNDgwNDY5IDEzNi4zNzUgNDMuODQzNzUgWiBNIDE0OS42MzY3MTkgNTYuNzUgQyAxNDcuNDU3MDMxIDU2Ljc1IDE0NS45NDkyMTkgNTcgMTQ1LjEwNTQ2OSA1Ny41IEMgMTQ0LjI2OTUzMSA1OCAxNDMuODU1NDY5IDU4Ljg1MTU2MiAxNDMuODU1NDY5IDYwLjA0Njg3NSBDIDE0My44NTU0NjkgNjEuMDA3ODEyIDE0NC4xNjc5NjkgNjEuNzY1NjI1IDE0NC43OTI5NjkgNjIuMzI4MTI1IEMgMTQ1LjQyNTc4MSA2Mi44OTA2MjUgMTQ2LjI4NTE1NiA2My4xNzE4NzUgMTQ3LjM3MTA5NCA2My4xNzE4NzUgQyAxNDguODU5Mzc1IDYzLjE3MTg3NSAxNTAuMDU4NTk0IDYyLjY0MDYyNSAxNTAuOTY0ODQ0IDYxLjU3ODEyNSBDIDE1MS44NzEwOTQgNjAuNTE1NjI1IDE1Mi4zMjQyMTkgNTkuMTA5Mzc1IDE1Mi4zMjQyMTkgNTcuMzU5Mzc1IEwgMTUyLjMyNDIxOSA1Ni43NSBaIE0gMTU1LjAxMTcxOSA1NS42NDA2MjUgTCAxNTUuMDExNzE5IDY1IEwgMTUyLjMyNDIxOSA2NSBMIDE1Mi4zMjQyMTkgNjIuNTE1NjI1IEMgMTUxLjcwNzAzMSA2My41MDc4MTIgMTUwLjkzNzUgNjQuMjQyMTg4IDE1MC4wMTE3MTkgNjQuNzE4NzUgQyAxNDkuMDkzNzUgNjUuMTg3NSAxNDcuOTcyNjU2IDY1LjQyMTg3NSAxNDYuNjUyMzQ0IDY1LjQyMTg3NSBDIDE0NC45NzI2NTYgNjUuNDIxODc1IDE0My42MzY3MTkgNjQuOTUzMTI1IDE0Mi42MzY3MTkgNjQuMDE1NjI1IEMgMTQxLjY0NDUzMSA2My4wNzAzMTIgMTQxLjE1MjM0NCA2MS44MDQ2ODggMTQxLjE1MjM0NCA2MC4yMTg3NSBDIDE0MS4xNTIzNDQgNTguMzc1IDE0MS43Njk1MzEgNTYuOTg0Mzc1IDE0My4wMTE3MTkgNTYuMDQ2ODc1IEMgMTQ0LjI1IDU1LjEwOTM3NSAxNDYuMDkzNzUgNTQuNjQwNjI1IDE0OC41NDI5NjkgNTQuNjQwNjI1IEwgMTUyLjMyNDIxOSA1NC42NDA2MjUgTCAxNTIuMzI0MjE5IDU0LjM3NSBDIDE1Mi4zMjQyMTkgNTMuMTM2NzE5IDE1MS45MTAxNTYgNTIuMTc5Njg4IDE1MS4wODk4NDQgNTEuNSBDIDE1MC4yNzczNDQgNTAuODI0MjE5IDE0OS4xMzY3MTkgNTAuNDg0Mzc1IDE0Ny42Njc5NjkgNTAuNDg0Mzc1IEMgMTQ2LjczMDQ2OSA1MC40ODQzNzUgMTQ1LjgxMjUgNTAuNjAxNTYyIDE0NC45MTc5NjkgNTAuODI4MTI1IEMgMTQ0LjAzMTI1IDUxLjA0Njg3NSAxNDMuMTc1NzgxIDUxLjM4MjgxMiAxNDIuMzU1NDY5IDUxLjgyODEyNSBMIDE0Mi4zNTU0NjkgNDkuMzQzNzUgQyAxNDMuMzQzNzUgNDguOTYwOTM4IDE0NC4zMDA3ODEgNDguNjcxODc1IDE0NS4yMzA0NjkgNDguNDg0Mzc1IEMgMTQ2LjE1NjI1IDQ4LjI5Njg3NSAxNDcuMDU4NTk0IDQ4LjIwMzEyNSAxNDcuOTMzNTk0IDQ4LjIwMzEyNSBDIDE1MC4zMDg1OTQgNDguMjAzMTI1IDE1Mi4wNzgxMjUgNDguODIwMzEyIDE1My4yNDYwOTQgNTAuMDQ2ODc1IEMgMTU0LjQyMTg3NSA1MS4yNzczNDQgMTU1LjAxMTcxOSA1My4xNDA2MjUgMTU1LjAxMTcxOSA1NS42NDA2MjUgWiBNIDE3NC4yMDcwMzEgNTUuMDkzNzUgTCAxNzQuMjA3MDMxIDY1IEwgMTcxLjUwMzkwNiA2NSBMIDE3MS41MDM5MDYgNTUuMTg3NSBDIDE3MS41MDM5MDYgNTMuNjM2NzE5IDE3MS4xOTkyMTkgNTIuNDc2NTYyIDE3MC41OTc2NTYgNTEuNzAzMTI1IEMgMTY5Ljk5MjE4OCA1MC45MzM1OTQgMTY5LjA4NTkzOCA1MC41NDY4NzUgMTY3Ljg3ODkwNiA1MC41NDY4NzUgQyAxNjYuNDE3OTY5IDUwLjU0Njg3NSAxNjUuMjY5NTMxIDUxLjAxMTcxOSAxNjQuNDI1NzgxIDUxLjkzNzUgQyAxNjMuNTg5ODQ0IDUyLjg2NzE4OCAxNjMuMTc1NzgxIDU0LjEzMjgxMiAxNjMuMTc1NzgxIDU1LjczNDM3NSBMIDE2My4xNzU3ODEgNjUgTCAxNjAuNDU3MDMxIDY1IEwgMTYwLjQ1NzAzMSA0OC41OTM3NSBMIDE2My4xNzU3ODEgNDguNTkzNzUgTCAxNjMuMTc1NzgxIDUxLjE0MDYyNSBDIDE2My44MjAzMTIgNTAuMTUyMzQ0IDE2NC41ODIwMzEgNDkuNDE3OTY5IDE2NS40NTcwMzEgNDguOTM3NSBDIDE2Ni4zMzIwMzEgNDguNDQ5MjE5IDE2Ny4zMzU5MzggNDguMjAzMTI1IDE2OC40NzI2NTYgNDguMjAzMTI1IEMgMTcwLjM1NTQ2OSA0OC4yMDMxMjUgMTcxLjc4NTE1NiA0OC43ODkwNjIgMTcyLjc1MzkwNiA0OS45NTMxMjUgQyAxNzMuNzIyNjU2IDUxLjEyMTA5NCAxNzQuMjA3MDMxIDUyLjgzNTkzOCAxNzQuMjA3MDMxIDU1LjA5Mzc1IFogTSAxOTAuMDM1MTU2IDQ5LjA3ODEyNSBMIDE5MC4wMzUxNTYgNTEuNjI1IEMgMTg5LjI3MzQzOCA1MS4yNDIxODggMTg4LjQ4MDQ2OSA1MC45NDkyMTkgMTg3LjY2MDE1NiA1MC43NSBDIDE4Ni44NDc2NTYgNTAuNTU0Njg4IDE4NS45OTYwOTQgNTAuNDUzMTI1IDE4NS4xMTMyODEgNTAuNDUzMTI1IEMgMTgzLjc3NzM0NCA1MC40NTMxMjUgMTgyLjc3MzQzOCA1MC42NjQwNjIgMTgyLjA5NzY1NiA1MS4wNzgxMjUgQyAxODEuNDI5Njg4IDUxLjQ4NDM3NSAxODEuMDk3NjU2IDUyLjEwMTU2MiAxODEuMDk3NjU2IDUyLjkyMTg3NSBDIDE4MS4wOTc2NTYgNTMuNTQ2ODc1IDE4MS4zMzU5MzggNTQuMDM5MDYyIDE4MS44MTY0MDYgNTQuMzkwNjI1IEMgMTgyLjI5Mjk2OSA1NC43NDYwOTQgMTgzLjI1NzgxMiA1NS4wODU5MzggMTg0LjcwNzAzMSA1NS40MDYyNSBMIDE4NS42Mjg5MDYgNTUuNjA5Mzc1IEMgMTg3LjU0Mjk2OSA1Ni4wMTU2MjUgMTg4LjkwMjM0NCA1Ni41OTM3NSAxODkuNzA3MDMxIDU3LjM0Mzc1IEMgMTkwLjUxOTUzMSA1OC4wOTM3NSAxOTAuOTI1NzgxIDU5LjEzNjcxOSAxOTAuOTI1NzgxIDYwLjQ2ODc1IEMgMTkwLjkyNTc4MSA2MiAxOTAuMzIwMzEyIDYzLjIxMDkzOCAxODkuMTEzMjgxIDY0LjA5Mzc1IEMgMTg3LjkwMjM0NCA2NC45ODA0NjkgMTg2LjI0NjA5NCA2NS40MjE4NzUgMTg0LjE0NDUzMSA2NS40MjE4NzUgQyAxODMuMjU3ODEyIDY1LjQyMTg3NSAxODIuMzM1OTM4IDY1LjMzMjAzMSAxODEuMzc4OTA2IDY1LjE1NjI1IEMgMTgwLjQyOTY4OCA2NC45OTIxODggMTc5LjQyOTY4OCA2NC43NDIxODggMTc4LjM3ODkwNiA2NC40MDYyNSBMIDE3OC4zNzg5MDYgNjEuNjA5Mzc1IEMgMTc5LjM3ODkwNiA2Mi4xMzI4MTIgMTgwLjM1NTQ2OSA2Mi41MjM0MzggMTgxLjMxNjQwNiA2Mi43ODEyNSBDIDE4Mi4yODUxNTYgNjMuMDQyOTY5IDE4My4yNDIxODggNjMuMTcxODc1IDE4NC4xOTE0MDYgNjMuMTcxODc1IEMgMTg1LjQ2MDkzOCA2My4xNzE4NzUgMTg2LjQzMzU5NCA2Mi45NTMxMjUgMTg3LjExMzI4MSA2Mi41MTU2MjUgQyAxODcuODAwNzgxIDYyLjA3ODEyNSAxODguMTQ0NTMxIDYxLjQ2NDg0NCAxODguMTQ0NTMxIDYwLjY3MTg3NSBDIDE4OC4xNDQ1MzEgNTkuOTQ1MzEyIDE4Ny44OTg0MzggNTkuMzg2NzE5IDE4Ny40MTAxNTYgNTkgQyAxODYuOTE3OTY5IDU4LjYwNTQ2OSAxODUuODM1OTM4IDU4LjIyNjU2MiAxODQuMTYwMTU2IDU3Ljg1OTM3NSBMIDE4My4yMjI2NTYgNTcuNjQwNjI1IEMgMTgxLjU1NDY4OCA1Ny4yOTY4NzUgMTgwLjM1MTU2MiA1Ni43NjE3MTkgMTc5LjYxMzI4MSA1Ni4wMzEyNSBDIDE3OC44NzEwOTQgNTUuMzA0Njg4IDE3OC41MDM5MDYgNTQuMzA0Njg4IDE3OC41MDM5MDYgNTMuMDMxMjUgQyAxNzguNTAzOTA2IDUxLjQ5MjE4OCAxNzkuMDUwNzgxIDUwLjMwNDY4OCAxODAuMTQ0NTMxIDQ5LjQ2ODc1IEMgMTgxLjIzODI4MSA0OC42MjUgMTgyLjc4OTA2MiA0OC4yMDMxMjUgMTg0LjgwMDc4MSA0OC4yMDMxMjUgQyAxODUuNzg5MDYyIDQ4LjIwMzEyNSAxODYuNzIyNjU2IDQ4LjI3NzM0NCAxODcuNTk3NjU2IDQ4LjQyMTg3NSBDIDE4OC40ODA0NjkgNDguNTcwMzEyIDE4OS4yOTI5NjkgNDguNzg5MDYyIDE5MC4wMzUxNTYgNDkuMDc4MTI1IFogTSA1IDM3LjE1MjM0NCAiLz4KPHBhdGggZmlsbC1ydWxlPSJub256ZXJvIiBmaWxsPSJyZ2IoMCUsIDAlLCAwJSkiIGZpbGwtb3BhY2l0eT0iMSIgZD0iTSAxMy4zOTA2MjUgNzcuMzkwNjI1IEwgMTMuMzkwNjI1IDkwLjczNDM3NSBMIDE1LjQyMTg3NSA5MC43MzQzNzUgQyAxNy43MjI2NTYgOTAuNzM0Mzc1IDE5LjQ3NjU2MiA5MC4xNjc5NjkgMjAuNjg3NSA4OS4wMzEyNSBDIDIxLjkwNjI1IDg3Ljg4NjcxOSAyMi41MTU2MjUgODYuMjI2NTYyIDIyLjUxNTYyNSA4NC4wNDY4NzUgQyAyMi41MTU2MjUgODEuODgyODEyIDIxLjkxMDE1NiA4MC4yMzA0NjkgMjAuNzAzMTI1IDc5LjA5Mzc1IEMgMTkuNDkyMTg4IDc3Ljk2MDkzOCAxNy43MzQzNzUgNzcuMzkwNjI1IDE1LjQyMTg3NSA3Ny4zOTA2MjUgWiBNIDcuNzUgNzMuMTI1IEwgMTMuNzAzMTI1IDczLjEyNSBDIDE3LjAyMzQzOCA3My4xMjUgMTkuNSA3My4zNjcxODggMjEuMTI1IDczLjg0Mzc1IEMgMjIuNzUgNzQuMzEyNSAyNC4xNDA2MjUgNzUuMTE3MTg4IDI1LjI5Njg3NSA3Ni4yNSBDIDI2LjMyODEyNSA3Ny4yNDIxODggMjcuMDg1OTM4IDc4LjM4MjgxMiAyNy41NzgxMjUgNzkuNjcxODc1IEMgMjguMDc4MTI1IDgwLjk1MzEyNSAyOC4zMjgxMjUgODIuNDE0MDYyIDI4LjMyODEyNSA4NC4wNDY4NzUgQyAyOC4zMjgxMjUgODUuNjk1MzEyIDI4LjA3ODEyNSA4Ny4xNjc5NjkgMjcuNTc4MTI1IDg4LjQ2ODc1IEMgMjcuMDg1OTM4IDg5Ljc2MTcxOSAyNi4zMjgxMjUgOTAuODk4NDM4IDI1LjI5Njg3NSA5MS44NzUgQyAyNC4xMjg5MDYgOTMuMDExNzE5IDIyLjcyMjY1NiA5My44MjAzMTIgMjEuMDc4MTI1IDk0LjI5Njg3NSBDIDE5LjQ0MTQwNiA5NC43NjU2MjUgMTYuOTg0Mzc1IDk1IDEzLjcwMzEyNSA5NSBMIDcuNzUgOTUgWiBNIDQ4Ljc5Mjk2OSA4Ni43NSBMIDQ4Ljc5Mjk2OSA4OC4yNSBMIDM2LjU0Mjk2OSA4OC4yNSBDIDM2LjY2Nzk2OSA4OS40ODA0NjkgMzcuMTA5Mzc1IDkwLjQwMjM0NCAzNy44NzEwOTQgOTEuMDE1NjI1IEMgMzguNjI4OTA2IDkxLjYzMjgxMiAzOS42OTE0MDYgOTEuOTM3NSA0MS4wNTg1OTQgOTEuOTM3NSBDIDQyLjE2MDE1NiA5MS45Mzc1IDQzLjI5Mjk2OSA5MS43NzczNDQgNDQuNDQ5MjE5IDkxLjQ1MzEyNSBDIDQ1LjYxMzI4MSA5MS4xMjEwOTQgNDYuODA4NTk0IDkwLjYyMTA5NCA0OC4wMjczNDQgODkuOTUzMTI1IEwgNDguMDI3MzQ0IDk0IEMgNDYuNzg1MTU2IDk0LjQ2ODc1IDQ1LjU0Njg3NSA5NC44MjQyMTkgNDQuMzA4NTk0IDk1LjA2MjUgQyA0My4wNjY0MDYgOTUuMzAwNzgxIDQxLjgyNDIxOSA5NS40MjE4NzUgNDAuNTc0MjE5IDk1LjQyMTg3NSBDIDM3LjYwNTQ2OSA5NS40MjE4NzUgMzUuMjk2ODc1IDk0LjY2Nzk2OSAzMy42NTIzNDQgOTMuMTU2MjUgQyAzMi4wMTU2MjUgOTEuNjQ4NDM4IDMxLjE5OTIxOSA4OS41MzEyNSAzMS4xOTkyMTkgODYuODEyNSBDIDMxLjE5OTIxOSA4NC4xMzY3MTkgMzIuMDAzOTA2IDgyLjAzMTI1IDMzLjYyMTA5NCA4MC41IEMgMzUuMjM0Mzc1IDc4Ljk2ODc1IDM3LjQ1NzAzMSA3OC4yMDMxMjUgNDAuMjkyOTY5IDc4LjIwMzEyNSBDIDQyLjg2MzI4MSA3OC4yMDMxMjUgNDQuOTIxODc1IDc4Ljk4MDQ2OSA0Ni40NjQ4NDQgODAuNTMxMjUgQyA0OC4wMTU2MjUgODIuMDg1OTM4IDQ4Ljc5Mjk2OSA4NC4xNTYyNSA0OC43OTI5NjkgODYuNzUgWiBNIDQzLjQwMjM0NCA4NS4wMTU2MjUgQyA0My40MDIzNDQgODQuMDE1NjI1IDQzLjEwOTM3NSA4My4yMTQ4NDQgNDIuNTI3MzQ0IDgyLjYwOTM3NSBDIDQxLjk1MzEyNSA4MS45OTYwOTQgNDEuMTk5MjE5IDgxLjY4NzUgNDAuMjYxNzE5IDgxLjY4NzUgQyAzOS4yMzgyODEgODEuNjg3NSAzOC40MTAxNTYgODEuOTc2NTYyIDM3Ljc3NzM0NCA4Mi41NDY4NzUgQyAzNy4xNDA2MjUgODMuMTA5Mzc1IDM2Ljc0NjA5NCA4My45MzM1OTQgMzYuNTg5ODQ0IDg1LjAxNTYyNSBaIE0gNTIuNzY1NjI1IDc4LjU5Mzc1IEwgNTguMDE1NjI1IDc4LjU5Mzc1IEwgNTguMDE1NjI1IDk0LjcwMzEyNSBDIDU4LjAxNTYyNSA5Ni44OTg0MzggNTcuNDg0Mzc1IDk4LjU3ODEyNSA1Ni40MjE4NzUgOTkuNzM0Mzc1IEMgNTUuMzY3MTg4IDEwMC44OTA2MjUgNTMuODQzNzUgMTAxLjQ2ODc1IDUxLjg0Mzc1IDEwMS40Njg3NSBMIDQ5LjI1IDEwMS40Njg3NSBMIDQ5LjI1IDk4LjAzMTI1IEwgNTAuMTU2MjUgOTguMDMxMjUgQyA1MS4xNTYyNSA5OC4wMzEyNSA1MS44MzU5MzggOTcuODA0Njg4IDUyLjIwMzEyNSA5Ny4zNTkzNzUgQyA1Mi41NzgxMjUgOTYuOTEwMTU2IDUyLjc2NTYyNSA5Ni4wMjM0MzggNTIuNzY1NjI1IDk0LjcwMzEyNSBaIE0gNTIuNzY1NjI1IDcyLjIwMzEyNSBMIDU4LjAxNTYyNSA3Mi4yMDMxMjUgTCA1OC4wMTU2MjUgNzYuNDg0Mzc1IEwgNTIuNzY1NjI1IDc2LjQ4NDM3NSBaIE0gNzAuNDA2MjUgODcuNjA5Mzc1IEMgNjkuMzEyNSA4Ny42MDkzNzUgNjguNDg4MjgxIDg3Ljc5Njg3NSA2Ny45Mzc1IDg4LjE3MTg3NSBDIDY3LjM4MjgxMiA4OC41NDY4NzUgNjcuMTA5Mzc1IDg5LjA5Mzc1IDY3LjEwOTM3NSA4OS44MTI1IEMgNjcuMTA5Mzc1IDkwLjQ4MDQ2OSA2Ny4zMjgxMjUgOTEgNjcuNzY1NjI1IDkxLjM3NSBDIDY4LjIxMDkzOCA5MS43NSA2OC44MzIwMzEgOTEuOTM3NSA2OS42MjUgOTEuOTM3NSBDIDcwLjYxMzI4MSA5MS45Mzc1IDcxLjQ0MTQwNiA5MS41ODU5MzggNzIuMTA5Mzc1IDkwLjg3NSBDIDcyLjc4NTE1NiA5MC4xNjc5NjkgNzMuMTI1IDg5LjI4MTI1IDczLjEyNSA4OC4yMTg3NSBMIDczLjEyNSA4Ny42MDkzNzUgWiBNIDc4LjQyMTg3NSA4NS42NDA2MjUgTCA3OC40MjE4NzUgOTUgTCA3My4xMjUgOTUgTCA3My4xMjUgOTIuNTYyNSBDIDcyLjQyNTc4MSA5My41NjI1IDcxLjYzMjgxMiA5NC4yOTI5NjkgNzAuNzUgOTQuNzUgQyA2OS44NzUgOTUuMTk1MzEyIDY4LjgwNDY4OCA5NS40MjE4NzUgNjcuNTQ2ODc1IDk1LjQyMTg3NSBDIDY1Ljg0NzY1NiA5NS40MjE4NzUgNjQuNDY4NzUgOTQuOTI5Njg4IDYzLjQwNjI1IDkzLjkzNzUgQyA2Mi4zNTE1NjIgOTIuOTQ5MjE5IDYxLjgyODEyNSA5MS42NjQwNjIgNjEuODI4MTI1IDkwLjA3ODEyNSBDIDYxLjgyODEyNSA4OC4xNTIzNDQgNjIuNDg4MjgxIDg2Ljc0MjE4OCA2My44MTI1IDg1Ljg0Mzc1IEMgNjUuMTMyODEyIDg0Ljk0OTIxOSA2Ny4yMDcwMzEgODQuNSA3MC4wMzEyNSA4NC41IEwgNzMuMTI1IDg0LjUgTCA3My4xMjUgODQuMDkzNzUgQyA3My4xMjUgODMuMjYxNzE5IDcyLjc5Njg3NSA4Mi42NTIzNDQgNzIuMTQwNjI1IDgyLjI2NTYyNSBDIDcxLjQ5MjE4OCA4MS44ODI4MTIgNzAuNDc2NTYyIDgxLjY4NzUgNjkuMDkzNzUgODEuNjg3NSBDIDY3Ljk2ODc1IDgxLjY4NzUgNjYuOTIxODc1IDgxLjgwNDY4OCA2NS45NTMxMjUgODIuMDMxMjUgQyA2NC45ODQzNzUgODIuMjUgNjQuMDgyMDMxIDgyLjU4NTkzOCA2My4yNSA4My4wMzEyNSBMIDYzLjI1IDc5LjAzMTI1IEMgNjQuMzc1IDc4Ljc2MTcxOSA2NS41MDM5MDYgNzguNTU4NTk0IDY2LjY0MDYyNSA3OC40MjE4NzUgQyA2Ny43NzM0MzggNzguMjc3MzQ0IDY4LjkwNjI1IDc4LjIwMzEyNSA3MC4wMzEyNSA3OC4yMDMxMjUgQyA3MyA3OC4yMDMxMjUgNzUuMTQwNjI1IDc4Ljc4OTA2MiA3Ni40NTMxMjUgNzkuOTUzMTI1IEMgNzcuNzY1NjI1IDgxLjEyMTA5NCA3OC40MjE4NzUgODMuMDE1NjI1IDc4LjQyMTg3NSA4NS42NDA2MjUgWiBNIDgwLjkxNzk2OSA3My4xMjUgTCA4Ni41ODk4NDQgNzMuMTI1IEwgOTIuMzg2NzE5IDg5LjI2NTYyNSBMIDk4LjE4MzU5NCA3My4xMjUgTCAxMDMuODU1NDY5IDczLjEyNSBMIDk1Ljc0NjA5NCA5NSBMIDg5LjAyNzM0NCA5NSBaIE0gMTA1LjI2OTUzMSA4OC42MDkzNzUgTCAxMDUuMjY5NTMxIDc4LjU5Mzc1IEwgMTEwLjU1MDc4MSA3OC41OTM3NSBMIDExMC41NTA3ODEgODAuMjM0Mzc1IEMgMTEwLjU1MDc4MSA4MS4xMjEwOTQgMTEwLjU0Mjk2OSA4Mi4yMzQzNzUgMTEwLjUzNTE1NiA4My41NzgxMjUgQyAxMTAuNTIzNDM4IDg0LjkyMTg3NSAxMTAuNTE5NTMxIDg1LjgyMDMxMiAxMTAuNTE5NTMxIDg2LjI2NTYyNSBDIDExMC41MTk1MzEgODcuNTg5ODQ0IDExMC41NTA3ODEgODguNTQyOTY5IDExMC42MTMyODEgODkuMTI1IEMgMTEwLjY4MzU5NCA4OS42OTkyMTkgMTEwLjgwNDY4OCA5MC4xMjEwOTQgMTEwLjk3MjY1NiA5MC4zOTA2MjUgQyAxMTEuMTc5Njg4IDkwLjcyNjU2MiAxMTEuNDU3MDMxIDkwLjk4NDM3NSAxMTEuODAwNzgxIDkxLjE3MTg3NSBDIDExMi4xNTIzNDQgOTEuMzU5Mzc1IDExMi41NTQ2ODggOTEuNDUzMTI1IDExMy4wMDM5MDYgOTEuNDUzMTI1IEMgMTE0LjA5NzY1NiA5MS40NTMxMjUgMTE0Ljk1NzAzMSA5MS4wMzkwNjIgMTE1LjU4MjAzMSA5MC4yMDMxMjUgQyAxMTYuMjA3MDMxIDg5LjM1OTM3NSAxMTYuNTE5NTMxIDg4LjE4NzUgMTE2LjUxOTUzMSA4Ni42ODc1IEwgMTE2LjUxOTUzMSA3OC41OTM3NSBMIDEyMS43Njk1MzEgNzguNTkzNzUgTCAxMjEuNzY5NTMxIDk1IEwgMTE2LjUxOTUzMSA5NSBMIDExNi41MTk1MzEgOTIuNjI1IEMgMTE1LjcyNjU2MiA5My41ODU5MzggMTE0Ljg4NjcxOSA5NC4yOTI5NjkgMTE0LjAwMzkwNiA5NC43NSBDIDExMy4xMTcxODggOTUuMTk1MzEyIDExMi4xNDQ1MzEgOTUuNDIxODc1IDExMS4wODIwMzEgOTUuNDIxODc1IEMgMTA5LjE4MzU5NCA5NS40MjE4NzUgMTA3Ljc0MjE4OCA5NC44NDM3NSAxMDYuNzUzOTA2IDkzLjY4NzUgQyAxMDUuNzYxNzE5IDkyLjUyMzQzOCAxMDUuMjY5NTMxIDkwLjgyODEyNSAxMDUuMjY5NTMxIDg4LjYwOTM3NSBaIE0gMTUyLjY5NTMxMiA3My44MTI1IEwgMTUyLjY5NTMxMiA3OC40NTMxMjUgQyAxNTEuNDk2MDk0IDc3LjkxNDA2MiAxNTAuMzI0MjE5IDc3LjUwNzgxMiAxNDkuMTc5Njg4IDc3LjIzNDM3NSBDIDE0OC4wNDI5NjkgNzYuOTY0ODQ0IDE0Ni45NjQ4NDQgNzYuODI4MTI1IDE0NS45NDUzMTIgNzYuODI4MTI1IEMgMTQ0LjYwMTU2MiA3Ni44MjgxMjUgMTQzLjYwNTQ2OSA3Ny4wMTU2MjUgMTQyLjk2MDkzOCA3Ny4zOTA2MjUgQyAxNDIuMzEyNSA3Ny43NTc4MTIgMTQxLjk5MjE4OCA3OC4zMjgxMjUgMTQxLjk5MjE4OCA3OS4xMDkzNzUgQyAxNDEuOTkyMTg4IDc5LjY5NTMxMiAxNDIuMjAzMTI1IDgwLjE1MjM0NCAxNDIuNjMyODEyIDgwLjQ4NDM3NSBDIDE0My4wNzAzMTIgODAuODA4NTk0IDE0My44NTkzNzUgODEuMDg1OTM4IDE0NS4wMDc4MTIgODEuMzEyNSBMIDE0Ny40MTQwNjIgODEuNzk2ODc1IEMgMTQ5LjgzOTg0NCA4Mi4yODkwNjIgMTUxLjU2MjUgODMuMDMxMjUgMTUyLjU4NTkzOCA4NC4wMzEyNSBDIDE1My42MTcxODggODUuMDIzNDM4IDE1NC4xMzI4MTIgODYuNDM3NSAxNTQuMTMyODEyIDg4LjI4MTI1IEMgMTU0LjEzMjgxMiA5MC42ODc1IDE1My40MTc5NjkgOTIuNDgwNDY5IDE1MS45OTIxODggOTMuNjU2MjUgQyAxNTAuNTYyNSA5NC44MzU5MzggMTQ4LjM3NSA5NS40MjE4NzUgMTQ1LjQyOTY4OCA5NS40MjE4NzUgQyAxNDQuMDQyOTY5IDk1LjQyMTg3NSAxNDIuNjUyMzQ0IDk1LjI4OTA2MiAxNDEuMjU3ODEyIDk1LjAzMTI1IEMgMTM5Ljg1OTM3NSA5NC43NzM0MzggMTM4LjQ2NDg0NCA5NC4zODI4MTIgMTM3LjA3MDMxMiA5My44NTkzNzUgTCAxMzcuMDcwMzEyIDg5LjA5Mzc1IEMgMTM4LjQ2NDg0NCA4OS44MzU5MzggMTM5LjgxMjUgOTAuMzk4NDM4IDE0MS4xMTcxODggOTAuNzgxMjUgQyAxNDIuNDE3OTY5IDkxLjE1NjI1IDE0My42Nzk2ODggOTEuMzQzNzUgMTQ0Ljg5ODQzOCA5MS4zNDM3NSBDIDE0Ni4xMjUgOTEuMzQzNzUgMTQ3LjA2MjUgOTEuMTQwNjI1IDE0Ny43MTA5MzggOTAuNzM0Mzc1IEMgMTQ4LjM2NzE4OCA5MC4zMjAzMTIgMTQ4LjY5NTMxMiA4OS43MzA0NjkgMTQ4LjY5NTMxMiA4OC45Njg3NSBDIDE0OC42OTUzMTIgODguMjgxMjUgMTQ4LjQ2ODc1IDg3Ljc1NzgxMiAxNDguMDIzNDM4IDg3LjM5MDYyNSBDIDE0Ny41ODU5MzggODcuMDE1NjI1IDE0Ni43MDMxMjUgODYuNjgzNTk0IDE0NS4zODI4MTIgODYuMzkwNjI1IEwgMTQzLjE5NTMxMiA4NS45MDYyNSBDIDE0MS4wMDc4MTIgODUuNDM3NSAxMzkuNDA2MjUgODQuNjk1MzEyIDEzOC4zOTg0MzggODMuNjcxODc1IEMgMTM3LjM4NjcxOSA4Mi42NDA2MjUgMTM2Ljg4MjgxMiA4MS4yNTc4MTIgMTM2Ljg4MjgxMiA3OS41MTU2MjUgQyAxMzYuODgyODEyIDc3LjMzOTg0NCAxMzcuNTg1OTM4IDc1LjY2Nzk2OSAxMzguOTkyMTg4IDc0LjUgQyAxNDAuMzk4NDM4IDczLjMyNDIxOSAxNDIuNDE3OTY5IDcyLjczNDM3NSAxNDUuMDU0Njg4IDcyLjczNDM3NSBDIDE0Ni4yNSA3Mi43MzQzNzUgMTQ3LjQ4NDM3NSA3Mi44MjgxMjUgMTQ4Ljc1NzgxMiA3My4wMTU2MjUgQyAxNTAuMDI3MzQ0IDczLjE5NTMxMiAxNTEuMzM5ODQ0IDczLjQ2MDkzOCAxNTIuNjk1MzEyIDczLjgxMjUgWiBNIDE2Ni4yMDcwMzEgODcuNjA5Mzc1IEMgMTY1LjExMzI4MSA4Ny42MDkzNzUgMTY0LjI4OTA2MiA4Ny43OTY4NzUgMTYzLjczODI4MSA4OC4xNzE4NzUgQyAxNjMuMTgzNTk0IDg4LjU0Njg3NSAxNjIuOTEwMTU2IDg5LjA5Mzc1IDE2Mi45MTAxNTYgODkuODEyNSBDIDE2Mi45MTAxNTYgOTAuNDgwNDY5IDE2My4xMjg5MDYgOTEgMTYzLjU2NjQwNiA5MS4zNzUgQyAxNjQuMDExNzE5IDkxLjc1IDE2NC42MzI4MTIgOTEuOTM3NSAxNjUuNDI1NzgxIDkxLjkzNzUgQyAxNjYuNDE0MDYyIDkxLjkzNzUgMTY3LjI0MjE4OCA5MS41ODU5MzggMTY3LjkxMDE1NiA5MC44NzUgQyAxNjguNTg1OTM4IDkwLjE2Nzk2OSAxNjguOTI1NzgxIDg5LjI4MTI1IDE2OC45MjU3ODEgODguMjE4NzUgTCAxNjguOTI1NzgxIDg3LjYwOTM3NSBaIE0gMTc0LjIyMjY1NiA4NS42NDA2MjUgTCAxNzQuMjIyNjU2IDk1IEwgMTY4LjkyNTc4MSA5NSBMIDE2OC45MjU3ODEgOTIuNTYyNSBDIDE2OC4yMjY1NjIgOTMuNTYyNSAxNjcuNDMzNTk0IDk0LjI5Mjk2OSAxNjYuNTUwNzgxIDk0Ljc1IEMgMTY1LjY3NTc4MSA5NS4xOTUzMTIgMTY0LjYwNTQ2OSA5NS40MjE4NzUgMTYzLjM0NzY1NiA5NS40MjE4NzUgQyAxNjEuNjQ4NDM4IDk1LjQyMTg3NSAxNjAuMjY5NTMxIDk0LjkyOTY4OCAxNTkuMjA3MDMxIDkzLjkzNzUgQyAxNTguMTUyMzQ0IDkyLjk0OTIxOSAxNTcuNjI4OTA2IDkxLjY2NDA2MiAxNTcuNjI4OTA2IDkwLjA3ODEyNSBDIDE1Ny42Mjg5MDYgODguMTUyMzQ0IDE1OC4yODkwNjIgODYuNzQyMTg4IDE1OS42MTMyODEgODUuODQzNzUgQyAxNjAuOTMzNTk0IDg0Ljk0OTIxOSAxNjMuMDA3ODEyIDg0LjUgMTY1LjgzMjAzMSA4NC41IEwgMTY4LjkyNTc4MSA4NC41IEwgMTY4LjkyNTc4MSA4NC4wOTM3NSBDIDE2OC45MjU3ODEgODMuMjYxNzE5IDE2OC41OTc2NTYgODIuNjUyMzQ0IDE2Ny45NDE0MDYgODIuMjY1NjI1IEMgMTY3LjI5Mjk2OSA4MS44ODI4MTIgMTY2LjI3NzM0NCA4MS42ODc1IDE2NC44OTQ1MzEgODEuNjg3NSBDIDE2My43Njk1MzEgODEuNjg3NSAxNjIuNzIyNjU2IDgxLjgwNDY4OCAxNjEuNzUzOTA2IDgyLjAzMTI1IEMgMTYwLjc4NTE1NiA4Mi4yNSAxNTkuODgyODEyIDgyLjU4NTkzOCAxNTkuMDUwNzgxIDgzLjAzMTI1IEwgMTU5LjA1MDc4MSA3OS4wMzEyNSBDIDE2MC4xNzU3ODEgNzguNzYxNzE5IDE2MS4zMDQ2ODggNzguNTU4NTk0IDE2Mi40NDE0MDYgNzguNDIxODc1IEMgMTYzLjU3NDIxOSA3OC4yNzczNDQgMTY0LjcwNzAzMSA3OC4yMDMxMjUgMTY1LjgzMjAzMSA3OC4yMDMxMjUgQyAxNjguODAwNzgxIDc4LjIwMzEyNSAxNzAuOTQxNDA2IDc4Ljc4OTA2MiAxNzIuMjUzOTA2IDc5Ljk1MzEyNSBDIDE3My41NjY0MDYgODEuMTIxMDk0IDE3NC4yMjI2NTYgODMuMDE1NjI1IDE3NC4yMjI2NTYgODUuNjQwNjI1IFogTSAxOTUuNTkzNzUgODUuMDE1NjI1IEwgMTk1LjU5Mzc1IDk1IEwgMTkwLjMxMjUgOTUgTCAxOTAuMzEyNSA4Ny4zNTkzNzUgQyAxOTAuMzEyNSA4NS45NDUzMTIgMTkwLjI4MTI1IDg0Ljk2ODc1IDE5MC4yMTg3NSA4NC40Mzc1IEMgMTkwLjE1NjI1IDgzLjg5ODQzOCAxOTAuMDQ2ODc1IDgzLjQ5NjA5NCAxODkuODkwNjI1IDgzLjIzNDM3NSBDIDE4OS42OTE0MDYgODIuODkwNjI1IDE4OS40MTQwNjIgODIuNjI1IDE4OS4wNjI1IDgyLjQzNzUgQyAxODguNzA3MDMxIDgyLjI1IDE4OC4zMDQ2ODggODIuMTU2MjUgMTg3Ljg1OTM3NSA4Mi4xNTYyNSBDIDE4Ni43NjU2MjUgODIuMTU2MjUgMTg1LjkwNjI1IDgyLjU3ODEyNSAxODUuMjgxMjUgODMuNDIxODc1IEMgMTg0LjY1NjI1IDg0LjI2NTYyNSAxODQuMzQzNzUgODUuNDMzNTk0IDE4NC4zNDM3NSA4Ni45MjE4NzUgTCAxODQuMzQzNzUgOTUgTCAxNzkuMDkzNzUgOTUgTCAxNzkuMDkzNzUgNzguNTkzNzUgTCAxODQuMzQzNzUgNzguNTkzNzUgTCAxODQuMzQzNzUgODEgQyAxODUuMTMyODEyIDgwLjA0Mjk2OSAxODUuOTcyNjU2IDc5LjMzOTg0NCAxODYuODU5Mzc1IDc4Ljg5MDYyNSBDIDE4Ny43NDIxODggNzguNDMzNTk0IDE4OC43MjY1NjIgNzguMjAzMTI1IDE4OS44MTI1IDc4LjIwMzEyNSBDIDE5MS42OTUzMTIgNzguMjAzMTI1IDE5My4xMjg5MDYgNzguNzg5MDYyIDE5NC4xMDkzNzUgNzkuOTUzMTI1IEMgMTk1LjA5NzY1NiA4MS4xMDkzNzUgMTk1LjU5Mzc1IDgyLjc5Njg3NSAxOTUuNTkzNzUgODUuMDE1NjI1IFogTSAyMTMuMjc3MzQ0IDc5LjEwOTM3NSBMIDIxMy4yNzczNDQgODMuMDkzNzUgQyAyMTIuMTUyMzQ0IDgyLjYyNSAyMTEuMDYyNSA4Mi4yNzczNDQgMjEwLjAxMTcxOSA4Mi4wNDY4NzUgQyAyMDguOTY4NzUgODEuODA4NTk0IDIwNy45ODQzNzUgODEuNjg3NSAyMDcuMDU4NTk0IDgxLjY4NzUgQyAyMDYuMDU4NTk0IDgxLjY4NzUgMjA1LjMxNjQwNiA4MS44MTI1IDIwNC44Mzk4NDQgODIuMDYyNSBDIDIwNC4zNTkzNzUgODIuMzEyNSAyMDQuMTIxMDk0IDgyLjY5NTMxMiAyMDQuMTIxMDk0IDgzLjIwMzEyNSBDIDIwNC4xMjEwOTQgODMuNjMyODEyIDIwNC4zMDA3ODEgODMuOTYwOTM4IDIwNC42Njc5NjkgODQuMTg3NSBDIDIwNS4wMzEyNSA4NC40MDYyNSAyMDUuNjg3NSA4NC41NzAzMTIgMjA2LjYzNjcxOSA4NC42NzE4NzUgTCAyMDcuNTU4NTk0IDg0Ljc5Njg3NSBDIDIxMC4yNDYwOTQgODUuMTQwNjI1IDIxMi4wNTA3ODEgODUuNzAzMTI1IDIxMi45ODA0NjkgODYuNDg0Mzc1IEMgMjEzLjkwNjI1IDg3LjI2NTYyNSAyMTQuMzcxMDk0IDg4LjQ5NjA5NCAyMTQuMzcxMDk0IDkwLjE3MTg3NSBDIDIxNC4zNzEwOTQgOTEuOTE0MDYyIDIxMy43MjI2NTYgOTMuMjI2NTYyIDIxMi40MzM1OTQgOTQuMTA5Mzc1IEMgMjExLjE0MDYyNSA5NC45ODQzNzUgMjA5LjIxODc1IDk1LjQyMTg3NSAyMDYuNjY3OTY5IDk1LjQyMTg3NSBDIDIwNS41ODIwMzEgOTUuNDIxODc1IDIwNC40NjQ4NDQgOTUuMzMyMDMxIDIwMy4zMDg1OTQgOTUuMTU2MjUgQyAyMDIuMTUyMzQ0IDk0Ljk5MjE4OCAyMDAuOTU3MDMxIDk0Ljc0MjE4OCAxOTkuNzMwNDY5IDk0LjQwNjI1IEwgMTk5LjczMDQ2OSA5MC40MjE4NzUgQyAyMDAuNzgxMjUgOTAuOTIxODc1IDIwMS44NTU0NjkgOTEuMzA0Njg4IDIwMi45NDkyMTkgOTEuNTYyNSBDIDIwNC4wNTA3ODEgOTEuODEyNSAyMDUuMTY3OTY5IDkxLjkzNzUgMjA2LjI5Mjk2OSA5MS45Mzc1IEMgMjA3LjMyNDIxOSA5MS45Mzc1IDIwOC4wOTM3NSA5MS43OTY4NzUgMjA4LjYwNTQ2OSA5MS41MTU2MjUgQyAyMDkuMTI1IDkxLjIzNDM3NSAyMDkuMzg2NzE5IDkwLjgxMjUgMjA5LjM4NjcxOSA5MC4yNSBDIDIwOS4zODY3MTkgODkuNzgxMjUgMjA5LjIwNzAzMSA4OS40MzM1OTQgMjA4Ljg1NTQ2OSA4OS4yMDMxMjUgQyAyMDguNSA4OC45NzY1NjIgMjA3Ljc5Mjk2OSA4OC43OTY4NzUgMjA2LjczMDQ2OSA4OC42NzE4NzUgTCAyMDUuNzkyOTY5IDg4LjU0Njg3NSBDIDIwMy40NTcwMzEgODguMjU3ODEyIDIwMS44MjQyMTkgODcuNzE0ODQ0IDIwMC44ODY3MTkgODYuOTIxODc1IEMgMTk5Ljk0OTIxOSA4Ni4xMzI4MTIgMTk5LjQ4MDQ2OSA4NC45MzM1OTQgMTk5LjQ4MDQ2OSA4My4zMjgxMjUgQyAxOTkuNDgwNDY5IDgxLjU4OTg0NCAyMDAuMDc0MjE5IDgwLjMwNDY4OCAyMDEuMjYxNzE5IDc5LjQ2ODc1IEMgMjAyLjQ1NzAzMSA3OC42MjUgMjA0LjI4NTE1NiA3OC4yMDMxMjUgMjA2Ljc0NjA5NCA3OC4yMDMxMjUgQyAyMDcuNzE0ODQ0IDc4LjIwMzEyNSAyMDguNzMwNDY5IDc4LjI3NzM0NCAyMDkuNzkyOTY5IDc4LjQyMTg3NSBDIDIxMC44NjMyODEgNzguNTcwMzEyIDIxMi4wMjczNDQgNzguNzk2ODc1IDIxMy4yNzczNDQgNzkuMTA5Mzc1IFogTSAyMzcuNzUgODEuNTkzNzUgQyAyMzguNjMyODEyIDgxLjU5Mzc1IDIzOS4zMDQ2ODggODEuNDAyMzQ0IDIzOS43NjU2MjUgODEuMDE1NjI1IEMgMjQwLjIyMjY1NiA4MC42MjEwOTQgMjQwLjQ1MzEyNSA4MC4wNDI5NjkgMjQwLjQ1MzEyNSA3OS4yODEyNSBDIDI0MC40NTMxMjUgNzguNTMxMjUgMjQwLjIyMjY1NiA3Ny45NjA5MzggMjM5Ljc2NTYyNSA3Ny41NjI1IEMgMjM5LjMwNDY4OCA3Ny4xNjc5NjkgMjM4LjYzMjgxMiA3Ni45Njg3NSAyMzcuNzUgNzYuOTY4NzUgTCAyMzQuNjI1IDc2Ljk2ODc1IEwgMjM0LjYyNSA4MS41OTM3NSBaIE0gMjM3LjkzNzUgOTEuMTU2MjUgQyAyMzkuMDcwMzEyIDkxLjE1NjI1IDIzOS45MjU3ODEgOTAuOTE3OTY5IDI0MC41IDkwLjQzNzUgQyAyNDEuMDcwMzEyIDg5Ljk2MDkzOCAyNDEuMzU5Mzc1IDg5LjI0MjE4OCAyNDEuMzU5Mzc1IDg4LjI4MTI1IEMgMjQxLjM1OTM3NSA4Ny4zMzU5MzggMjQxLjA3MDMxMiA4Ni42MjUgMjQwLjUgODYuMTU2MjUgQyAyMzkuOTM3NSA4NS42Nzk2ODggMjM5LjA4MjAzMSA4NS40Mzc1IDIzNy45Mzc1IDg1LjQzNzUgTCAyMzQuNjI1IDg1LjQzNzUgTCAyMzQuNjI1IDkxLjE1NjI1IFogTSAyNDMuMTg3NSA4My4yOTY4NzUgQyAyNDQuMzk0NTMxIDgzLjY1MjM0NCAyNDUuMzI4MTI1IDg0LjMwNDY4OCAyNDUuOTg0Mzc1IDg1LjI1IEMgMjQ2LjY0ODQzOCA4Ni4xOTkyMTkgMjQ2Ljk4NDM3NSA4Ny4zNTkzNzUgMjQ2Ljk4NDM3NSA4OC43MzQzNzUgQyAyNDYuOTg0Mzc1IDkwLjgzOTg0NCAyNDYuMjY5NTMxIDkyLjQxNDA2MiAyNDQuODQzNzUgOTMuNDUzMTI1IEMgMjQzLjQyNTc4MSA5NC40ODQzNzUgMjQxLjI1NzgxMiA5NSAyMzguMzQzNzUgOTUgTCAyMjguOTg0Mzc1IDk1IEwgMjI4Ljk4NDM3NSA3My4xMjUgTCAyMzcuNDUzMTI1IDczLjEyNSBDIDI0MC40OTIxODggNzMuMTI1IDI0Mi42OTE0MDYgNzMuNTg5ODQ0IDI0NC4wNDY4NzUgNzQuNTE1NjI1IEMgMjQ1LjQxMDE1NiA3NS40MzM1OTQgMjQ2LjA5Mzc1IDc2LjkwMjM0NCAyNDYuMDkzNzUgNzguOTIxODc1IEMgMjQ2LjA5Mzc1IDc5Ljk4NDM3NSAyNDUuODQzNzUgODAuODkwNjI1IDI0NS4zNDM3NSA4MS42NDA2MjUgQyAyNDQuODUxNTYyIDgyLjM4MjgxMiAyNDQuMTMyODEyIDgyLjkzMzU5NCAyNDMuMTg3NSA4My4yOTY4NzUgWiBNIDI1OS40Mjk2ODggODEuOTUzMTI1IEMgMjU4LjI2MTcxOSA4MS45NTMxMjUgMjU3LjM3MTA5NCA4Mi4zNzEwOTQgMjU2Ljc1NzgxMiA4My4yMDMxMjUgQyAyNTYuMTUyMzQ0IDg0LjAzOTA2MiAyNTUuODUxNTYyIDg1LjI0MjE4OCAyNTUuODUxNTYyIDg2LjgxMjUgQyAyNTUuODUxNTYyIDg4LjM4NjcxOSAyNTYuMTUyMzQ0IDg5LjU4OTg0NCAyNTYuNzU3ODEyIDkwLjQyMTg3NSBDIDI1Ny4zNzEwOTQgOTEuMjU3ODEyIDI1OC4yNjE3MTkgOTEuNjcxODc1IDI1OS40Mjk2ODggOTEuNjcxODc1IEMgMjYwLjU3NDIxOSA5MS42NzE4NzUgMjYxLjQ0OTIxOSA5MS4yNTc4MTIgMjYyLjA1NDY4OCA5MC40MjE4NzUgQyAyNjIuNjU2MjUgODkuNTg5ODQ0IDI2Mi45NjA5MzggODguMzg2NzE5IDI2Mi45NjA5MzggODYuODEyNSBDIDI2Mi45NjA5MzggODUuMjQyMTg4IDI2Mi42NTYyNSA4NC4wMzkwNjIgMjYyLjA1NDY4OCA4My4yMDMxMjUgQyAyNjEuNDQ5MjE5IDgyLjM3MTA5NCAyNjAuNTc0MjE5IDgxLjk1MzEyNSAyNTkuNDI5Njg4IDgxLjk1MzEyNSBaIE0gMjU5LjQyOTY4OCA3OC4yMDMxMjUgQyAyNjIuMjUgNzguMjAzMTI1IDI2NC40NTMxMjUgNzguOTY0ODQ0IDI2Ni4wMzkwNjIgODAuNDg0Mzc1IEMgMjY3LjYzMjgxMiA4Mi4wMDc4MTIgMjY4LjQyOTY4OCA4NC4xMTcxODggMjY4LjQyOTY4OCA4Ni44MTI1IEMgMjY4LjQyOTY4OCA4OS41MTE3MTkgMjY3LjYzMjgxMiA5MS42MjEwOTQgMjY2LjAzOTA2MiA5My4xNDA2MjUgQyAyNjQuNDUzMTI1IDk0LjY2NDA2MiAyNjIuMjUgOTUuNDIxODc1IDI1OS40Mjk2ODggOTUuNDIxODc1IEMgMjU2LjU5Mzc1IDk1LjQyMTg3NSAyNTQuMzgyODEyIDk0LjY2NDA2MiAyNTIuNzg5MDYyIDkzLjE0MDYyNSBDIDI1MS4xOTUzMTIgOTEuNjIxMDk0IDI1MC4zOTg0MzggODkuNTExNzE5IDI1MC4zOTg0MzggODYuODEyNSBDIDI1MC4zOTg0MzggODQuMTE3MTg4IDI1MS4xOTUzMTIgODIuMDA3ODEyIDI1Mi43ODkwNjIgODAuNDg0Mzc1IEMgMjU0LjM4MjgxMiA3OC45NjQ4NDQgMjU2LjU5Mzc1IDc4LjIwMzEyNSAyNTkuNDI5Njg4IDc4LjIwMzEyNSBaIE0gMjcyLjIyNjU2MiA3Mi4yMDMxMjUgTCAyNzcuNDc2NTYyIDcyLjIwMzEyNSBMIDI3Ny40NzY1NjIgOTUgTCAyNzIuMjI2NTYyIDk1IFogTSAyOTMuNjgzNTk0IDgxIEwgMjkzLjY4MzU5NCA3Mi4yMDMxMjUgTCAyOTguOTQ5MjE5IDcyLjIwMzEyNSBMIDI5OC45NDkyMTkgOTUgTCAyOTMuNjgzNTk0IDk1IEwgMjkzLjY4MzU5NCA5Mi42MjUgQyAyOTIuOTUzMTI1IDkzLjU5Mzc1IDI5Mi4xNTIzNDQgOTQuMzA0Njg4IDI5MS4yNzczNDQgOTQuNzUgQyAyOTAuNDEwMTU2IDk1LjE5NTMxMiAyODkuNDEwMTU2IDk1LjQyMTg3NSAyODguMjc3MzQ0IDk1LjQyMTg3NSBDIDI4Ni4yNTM5MDYgOTUuNDIxODc1IDI4NC41OTM3NSA5NC42MjEwOTQgMjgzLjI5Mjk2OSA5My4wMTU2MjUgQyAyODEuOTg4MjgxIDkxLjQxNDA2MiAyODEuMzM5ODQ0IDg5LjM0Mzc1IDI4MS4zMzk4NDQgODYuODEyNSBDIDI4MS4zMzk4NDQgODQuMjgxMjUgMjgxLjk4ODI4MSA4Mi4yMTQ4NDQgMjgzLjI5Mjk2OSA4MC42MDkzNzUgQyAyODQuNTkzNzUgNzkuMDA3ODEyIDI4Ni4yNTM5MDYgNzguMjAzMTI1IDI4OC4yNzczNDQgNzguMjAzMTI1IEMgMjg5LjQwMjM0NCA3OC4yMDMxMjUgMjkwLjQwMjM0NCA3OC40MzM1OTQgMjkxLjI3NzM0NCA3OC44OTA2MjUgQyAyOTIuMTUyMzQ0IDc5LjMzOTg0NCAyOTIuOTUzMTI1IDgwLjA0Mjk2OSAyOTMuNjgzNTk0IDgxIFogTSAyOTAuMjE0ODQ0IDkxLjYwOTM3NSBDIDI5MS4zMzk4NDQgOTEuNjA5Mzc1IDI5Mi4xOTkyMTkgOTEuMjAzMTI1IDI5Mi43OTI5NjkgOTAuMzkwNjI1IEMgMjkzLjM4NjcxOSA4OS41NzAzMTIgMjkzLjY4MzU5NCA4OC4zNzUgMjkzLjY4MzU5NCA4Ni44MTI1IEMgMjkzLjY4MzU5NCA4NS4yNSAyOTMuMzg2NzE5IDg0LjA1ODU5NCAyOTIuNzkyOTY5IDgzLjIzNDM3NSBDIDI5Mi4xOTkyMTkgODIuNDE0MDYyIDI5MS4zMzk4NDQgODIgMjkwLjIxNDg0NCA4MiBDIDI4OS4xMDkzNzUgODIgMjg4LjI2MTcxOSA4Mi40MTQwNjIgMjg3LjY2Nzk2OSA4My4yMzQzNzUgQyAyODcuMDc0MjE5IDg0LjA1ODU5NCAyODYuNzc3MzQ0IDg1LjI1IDI4Ni43NzczNDQgODYuODEyNSBDIDI4Ni43NzczNDQgODguMzc1IDI4Ny4wNzQyMTkgODkuNTcwMzEyIDI4Ny42Njc5NjkgOTAuMzkwNjI1IEMgMjg4LjI2MTcxOSA5MS4yMDMxMjUgMjg5LjEwOTM3NSA5MS42MDkzNzUgMjkwLjIxNDg0NCA5MS42MDkzNzUgWiBNIDUgNjcuMTUyMzQ0ICIvPgo8L3N2Zz4K");
20 | })
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/nodejs/test/chart-line.js:
--------------------------------------------------------------------------------
1 | let { registerFont, createCanvas } = require('canvas');
2 | let { CategoryScale, Chart, LinearScale, LineController, LineElement, PointElement } = require('chart.js');
3 | var assert = require('assert');
4 |
5 | describe('Chart', function () {
6 | describe('#drawLineGraph', function () {
7 | it('should draw a line graph', function () {
8 | Chart.register([
9 | CategoryScale,
10 | LineController,
11 | LineElement,
12 | LinearScale,
13 | PointElement
14 | ]);
15 |
16 | const canvas = createCanvas(400, 300);
17 | const chart = new Chart(
18 | canvas, // TypeScript needs "as any" here
19 | {
20 | type: 'line',
21 | data: {
22 | labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
23 | datasets: [{
24 | label: '# of Votes',
25 | data: [12, 19, 3, 5, 2, 3],
26 | borderColor: 'red'
27 | }]
28 | }
29 | }
30 | );
31 | const dataURL = canvas.toDataURL();
32 | // console.log(dataURL);
33 | chart.destroy();
34 | });
35 | })
36 | });
--------------------------------------------------------------------------------
/nodejs/test/fabric-rectangle.js:
--------------------------------------------------------------------------------
1 | let fabric = require('fabric/node');
2 | var assert = require('assert');
3 |
4 | describe('Fabric', function() {
5 | describe('#drawRectangle', function() {
6 | it('should draw a red rectangle', function() {
7 | const canvas = new fabric.Canvas(null, { width: 100, height: 100 });
8 | const rect = new fabric.Rect({ width: 20, height: 50, fill: '#ff0000' });
9 | const text = new fabric.Text('fabric.js', { fill: 'blue', fontSize: 24 });
10 | canvas.add(rect, text);
11 | canvas.renderAll();
12 | // console.log(canvas.toDataURL());
13 | assert.strictEqual(canvas.toDataURL(), 'data:image/png;base64,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');
14 | });
15 | })
16 | });
--------------------------------------------------------------------------------
/nodejs/test/konva-circle.js:
--------------------------------------------------------------------------------
1 | let Konva = require('konva');
2 | var assert = require('assert');
3 | const semver = require('semver');
4 |
5 | describe('Konva', function () {
6 | describe('#drawCircle', function () {
7 | it('should draw a red circle', function () {
8 | const stage = new Konva.Stage({
9 | width: 500,
10 | height: 500
11 | });
12 | // then create layer
13 | var layer = new Konva.Layer();
14 |
15 | // create our shape
16 | var circle = new Konva.Circle({
17 | x: stage.width() / 2,
18 | y: stage.height() / 2,
19 | radius: 70,
20 | fill: 'red',
21 | stroke: 'black',
22 | strokeWidth: 4
23 | });
24 |
25 | // add the shape to the layer
26 | layer.add(circle);
27 |
28 | // add the layer to the stage
29 | stage.add(layer);
30 |
31 | // draw the image
32 | layer.draw();
33 |
34 | if (semver.lt(process.version, '20.0.0')) {
35 | assert.strictEqual(stage.toDataURL({pixelRatio: 1}), 'data:image/png;base64,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');
36 | } else {
37 | assert.strictEqual(stage.toDataURL({pixelRatio: 1}), 'data:image/png;base64,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');
38 | }
39 | });
40 | })
41 | });
--------------------------------------------------------------------------------
/package-sam.yml:
--------------------------------------------------------------------------------
1 | AWSTemplateFormatVersion : '2010-09-09'
2 | Transform: AWS::Serverless-2016-10-31
3 | Resources:
4 | NodeCanvasLayer:
5 | Type: AWS::Serverless::LayerVersion
6 | Properties:
7 | LayerName: canvas-nodejs
8 | Description: canvas@
9 | ContentUri: s3:///canvas-nodejs_v.zip
10 | CompatibleRuntimes:
11 | - nodejs
12 | RetentionPolicy: Retain
13 | LicenseInfo: MIT
14 |
15 | Outputs:
16 | LayerVersion:
17 | Description: Layer ARN Reference
18 | Value: !Ref NodeCanvasLayer
19 |
--------------------------------------------------------------------------------