├── .editorconfig
├── .gitignore
├── .prettierrc
├── LICENSE
├── README.md
├── lib
├── css
│ ├── a1.css
│ ├── a2.css
│ ├── a3.css
│ ├── a4.css
│ ├── a5.css
│ ├── legal.css
│ ├── letter.css
│ ├── pdf.css
│ └── tabloid.css
├── module.defaults.js
└── module.js
├── package.json
├── playground
├── .eslintrc.js
├── .gitignore
├── assets
│ └── css
│ │ └── tailwind.css
├── content
│ └── article.md
├── jsconfig.json
├── layout
│ └── default.vue
├── nuxt.config.js
├── package.json
├── pages
│ ├── README.md
│ ├── article.vue
│ ├── docs.vue
│ └── index.vue
├── tailwind.config.js
└── yarn.lock
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Node template
3 | # Logs
4 | /logs
5 | *.log
6 | npm-debug.log*
7 | yarn-debug.log*
8 | yarn-error.log*
9 |
10 | # Runtime data
11 | pids
12 | *.pid
13 | *.seed
14 | *.pid.lock
15 |
16 | # Directory for instrumented libs generated by jscoverage/JSCover
17 | lib-cov
18 |
19 | # Coverage directory used by tools like istanbul
20 | coverage
21 |
22 | # nyc test coverage
23 | .nyc_output
24 |
25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
26 | .grunt
27 |
28 | # Bower dependency directory (https://bower.io/)
29 | bower_components
30 |
31 | # node-waf configuration
32 | .lock-wscript
33 |
34 | # Compiled binary addons (https://nodejs.org/api/addons.html)
35 | build/Release
36 |
37 | # Dependency directories
38 | node_modules/
39 | jspm_packages/
40 |
41 | # TypeScript v1 declaration files
42 | typings/
43 |
44 | # Optional npm cache directory
45 | .npm
46 |
47 | # Optional eslint cache
48 | .eslintcache
49 |
50 | # Optional REPL history
51 | .node_repl_history
52 |
53 | # Output of 'npm pack'
54 | *.tgz
55 |
56 | # Yarn Integrity file
57 | .yarn-integrity
58 |
59 | # dotenv environment variables file
60 | .env
61 |
62 | # parcel-bundler cache (https://parceljs.org/)
63 | .cache
64 |
65 | # next.js build output
66 | .next
67 |
68 | # nuxt.js build output
69 | .nuxt
70 |
71 | # Nuxt generate
72 | dist
73 |
74 | # vuepress build output
75 | .vuepress/dist
76 |
77 | # Serverless directories
78 | .serverless
79 |
80 | # IDE / Editor
81 | .idea
82 |
83 | # Service worker
84 | sw.*
85 |
86 | # macOS
87 | .DS_Store
88 |
89 | # Vim swap files
90 | *.swp
91 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false,
3 | "singleQuote": true
4 | }
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2020 Christian Hansen
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 | # Nuxt PDF [WIP]
2 |
3 | > **Looking for new maintainer.** Since i don't work in the nuxt universe as much anymore, please write to me if you wish to take over this project.
4 |
5 | [](https://npmjs.com/package/nuxt-pdf)
6 | [](https://npmjs.com/package/nuxt-pdf)
7 | [](http://standardjs.com)
8 |
9 | > Generate PDF files directly from your content on your website, can be used for offline downloadable documentation pages.
10 |
11 | ## Features
12 |
13 | - Create PDF from Vue template
14 | - Automatic PDF Generation
15 | - Customizable Metadata
16 | - Supports (A1, A2, A3, A4, A5, Letter, Legal, Tabloid)
17 | - Support dynamic routes (Nuxt Generate)
18 | - Support dynamic titles (from
tag)
19 | - I18n support for specific languages
20 | - Generates as you edit (Automatic PDF regeneration)
21 | - For **NUXT 2.x** and higher
22 |
23 | ## Table of Contents
24 |
25 | - [Installation](#installation)
26 | - [Usage](#usage)
27 | - [Configuration](#configuration)
28 | - [Development](#development)
29 | - [License](#license)
30 |
31 | ## Installation
32 |
33 | ```shell
34 | npm install nuxt-pdf --save-dev
35 | ```
36 |
37 | or
38 |
39 | ```shell
40 | yarn add -D nuxt-pdf
41 | ```
42 |
43 | ## Usage
44 |
45 | - Add the class `.page` to your page to display when printing, for formatting, add classes: `.a1`, `.a2`, `.a3`, `.a4`, `.a5`, `.letter`, `.legal`, or `.tabloid`
46 |
47 | - Add `nuxt-pdf` to the `buildModules` section of your `nuxt.config.js` file:
48 |
49 | ```js
50 | buildModules: ['nuxt-pdf']
51 | ```
52 |
53 | - Add a custom configuration with the `pdf` property.
54 |
55 | You can see the available options in the example [configuration](#configuration)
56 |
57 | ```js
58 | // nuxt.config.js
59 |
60 | {
61 | buildModules: [
62 | 'nuxt-pdf'
63 | ],
64 | pdf: {
65 | // custom configuration
66 | }
67 | }
68 | ```
69 |
70 | ## Configuration
71 |
72 | ```javascript
73 | // nuxt.config.js
74 |
75 | {
76 | pdf: {
77 | /*
78 | * Output folder for generated pdf.
79 | */
80 | dir: "static",
81 |
82 | /*
83 | * Function options for page.pdf([options])
84 | * Read more: https://pptr.dev/#?product=Puppeteer&version=v2.0.0&show=api-pagepdfoptions
85 | */
86 | pdf: {
87 | // Change the format of the pdfs.
88 | format: "A4", // This is optional
89 | printBackground: true // Include background in pdf.
90 | }
91 |
92 | /*
93 | * Function options for page.setViewport([options])
94 | * Read more: https://pptr.dev/#?product=Puppeteer&version=v2.0.0&show=api-pagesetviewportviewport
95 | */
96 | viewport: {
97 | // override the default viewport
98 | width: 1280,
99 | height: 800
100 | },
101 |
102 | /*
103 | * Enable i18n support.
104 | */
105 | i18n: false,
106 |
107 | /*
108 | * Add options to the puppeteer launch.
109 | * Read more: https://pptr.dev/#?product=Puppeteer&version=v2.0.0&show=api-puppeteerlaunchoptions
110 | */
111 | puppeteer: {
112 | // Puppeteer options here... E.g. env: {}
113 | },
114 |
115 | /*
116 | * PDF Meta configuration. (inspired by vue-meta)
117 | */
118 | meta: {
119 | title: "My Module",
120 | titleTemplate: "Documentation ─ %s",
121 |
122 | author: "Christian Hansen",
123 | subject: "Example",
124 |
125 | producer: "Example Inc.",
126 |
127 | // Control the date the file is created.
128 | creationDate: new Date(),
129 |
130 | keywords: ["pdf", "nuxt"]
131 | },
132 |
133 | /*
134 | * PDF generation routes. (expanding nuxt.generate)
135 | */
136 | routes: [
137 | {
138 | // Output file inside output folder.
139 | file: "downloads/documentation.pdf",
140 |
141 | // Route to content that should be converted into pdf.
142 | route: "docs",
143 |
144 | // Default option is to remove the route after generation so it is not accessible
145 | keep: true, // defaults to false
146 |
147 | // Specifify language for pdf. (Only when i18n is enabled!)
148 | locale: 'da',
149 |
150 | // Override global meta with individual meta for each pdf.
151 | meta: {
152 | title: "Home"
153 | },
154 | pdf: {
155 | // route specific pdf options
156 | landscape: true // Include background in pdf.
157 | },
158 | viewport: {
159 | // route specific viewport
160 | width: 1280,
161 | height: 800
162 | },
163 | },
164 | {
165 | // Output: static/downloads/documentation-vue.pdf
166 | file: "downloads/documentation-vue.pdf",
167 |
168 | // Will generate route https://localhost:3000/docs/vue
169 | route: "docs/vue",
170 |
171 | // Title will be Documentation - Vue
172 | meta: {
173 | title: "Vue"
174 | }
175 | }
176 | ]
177 | }
178 | }
179 | ```
180 |
181 | - PDF generation
182 |
183 | PDFs will be generated when running `nuxt build`, `nuxt generate` or in development `nuxt dev`
184 |
185 | ## Development
186 |
187 | ```bash
188 | $ git clone https://github.com/ch99q/nuxt-pdf.git
189 |
190 | $ cd nuxt-pdf
191 |
192 | $ yarn
193 | ```
194 |
195 | ## License
196 |
197 | [MIT License](./LICENSE)
198 |
--------------------------------------------------------------------------------
/lib/css/a1.css:
--------------------------------------------------------------------------------
1 | @page {
2 | format: A1;
3 | size: 594mm 841mm;
4 | margin: 0mm 0mm;
5 | }
6 |
7 | @media print {
8 | .page {
9 | width: 594mm !important;
10 | height: 840.75mm !important;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/lib/css/a2.css:
--------------------------------------------------------------------------------
1 | @page {
2 | format: A2;
3 | size: 420mm 594mm;
4 | margin: 0mm 0mm;
5 | }
6 |
7 | @media print {
8 | .page {
9 | width: 420mm !important;
10 | height: 594mm !important;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/lib/css/a3.css:
--------------------------------------------------------------------------------
1 | @page {
2 | format: A3;
3 | size: 297mm 420mm;
4 | margin: 0mm 0mm;
5 | }
6 |
7 | @media print {
8 | .page {
9 | width: 297mm !important;
10 | height: 420mm !important;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/lib/css/a4.css:
--------------------------------------------------------------------------------
1 | @page {
2 | format: A4;
3 | size: 210mm 297mm;
4 | margin: 0mm 0mm;
5 | }
6 |
7 | @media print {
8 | .page {
9 | width: 210mm !important;
10 | height: 296.75mm !important;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/lib/css/a5.css:
--------------------------------------------------------------------------------
1 | @page {
2 | format: A5;
3 | size: 148mm 210mm;
4 | margin: 0mm 0mm;
5 | }
6 |
7 | @media print {
8 | .page {
9 | width: 148mm !important;
10 | height: 209.75mm !important;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/lib/css/legal.css:
--------------------------------------------------------------------------------
1 | @page {
2 | format: Legal;
3 | size: 8.5in 14in;
4 | margin: 0in 0in;
5 | }
6 |
7 | @media print {
8 | .page {
9 | width: 8.5in !important;
10 | height: 13.97in !important;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/lib/css/letter.css:
--------------------------------------------------------------------------------
1 | @page {
2 | format: Letter;
3 | size: 8.5in 11in;
4 | margin: 0in 0in;
5 | }
6 |
7 | @media print {
8 | .page {
9 | width: 8.5in !important;
10 | height: 10.97in !important;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/lib/css/pdf.css:
--------------------------------------------------------------------------------
1 | @media print {
2 | html,
3 | body {
4 | margin: 0 !important;
5 | padding: 0 !important;
6 | visibility: hidden;
7 | }
8 |
9 | .page {
10 | position: relative;
11 | overflow: hidden;
12 |
13 | visibility: visible;
14 |
15 | padding: 0 !important;
16 | margin: 0 !important;
17 |
18 | page-break-after: auto;
19 | page-break-inside: avoid !important;
20 |
21 | border: none !important;
22 | border-radius: 0 !important;
23 | box-shadow: none !important;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/css/tabloid.css:
--------------------------------------------------------------------------------
1 | @page {
2 | format: Tabloid;
3 | size: 11in 17in;
4 | margin: 0in 0in;
5 | }
6 |
7 | @media print {
8 | .page {
9 | width: 11in !important;
10 | height: 16.97in !important;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/lib/module.defaults.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | dir: 'static',
3 |
4 | pdf: {
5 | format: 'A4',
6 | },
7 |
8 | i18n: false,
9 |
10 | meta: {
11 | title: '',
12 | titleTemplate: '%s',
13 | subject: '',
14 | author: '',
15 | producer: '',
16 | keywords: [],
17 | },
18 |
19 | routes: [],
20 | }
21 |
--------------------------------------------------------------------------------
/lib/module.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const path = require('path')
3 |
4 | const {
5 | PDFDocument: Document
6 | } = require('pdf-lib')
7 |
8 | const chalk = require('chalk')
9 | const puppeteer = require('puppeteer')
10 |
11 | const defaults = require('./module.defaults')
12 |
13 | const supportedFormats = ['a1', 'a2', 'a3', 'a4', 'a5', 'letter', 'legal', 'tabloid']
14 |
15 | export const promisifyRoute = function promisifyRoute(fn, ...args) {
16 | // If routes is an array
17 | if (Array.isArray(fn)) {
18 | return Promise.resolve(fn)
19 | }
20 | // If routes is a function expecting a callback
21 | if (fn.length === arguments.length) {
22 | return new Promise((resolve, reject) => {
23 | fn((err, routeParams) => {
24 | if (err) {
25 | reject(err)
26 | }
27 | resolve(routeParams)
28 | }, ...args)
29 | })
30 | }
31 | let promise = fn(...args)
32 | if (
33 | !promise ||
34 | (!(promise instanceof Promise) && typeof promise.then !== 'function')
35 | ) {
36 | promise = Promise.resolve(promise)
37 | }
38 | return promise
39 | }
40 |
41 | async function timeout(ms) {
42 | return new Promise(resolve => setTimeout(resolve, ms));
43 | }
44 |
45 | module.exports = async function PDF(moduleOptions) {
46 |
47 | const options = Object.assign({}, defaults, moduleOptions, this.options.pdf)
48 |
49 | const i18n = {
50 | enabled: options.i18n,
51 | domains: {},
52 | options: {}
53 | }
54 |
55 | if (i18n.enabled) {
56 | i18n.options = Object.assign({},
57 | this.options.i18n,
58 | (this.options.modules.find(
59 | x => Array.isArray(x) && x[0] === 'nuxt-i18n'
60 | ) || [('', {})])[1],
61 | (this.options.buildModules.find(
62 | x => Array.isArray(x) && x[0] === 'nuxt-i18n'
63 | ) || [('', {})])[1]
64 | )
65 |
66 | for (const locale of i18n.options.locales) {
67 | if ('domain' in locale && 'code' in locale) {
68 | i18n.domains[locale.code] = locale.domain
69 | }
70 | }
71 | }
72 |
73 | var routeMap
74 | var url
75 |
76 | /*
77 | * Add pdf styling to render.
78 | */
79 | this.options.css.push(path.resolve(__dirname, 'css/pdf.css'))
80 |
81 | if (options.pdf.format) {
82 | const format = options.pdf.format.toLowerCase()
83 |
84 | if (supportedFormats.includes(format)) {
85 | this.options.css.push(path.resolve(__dirname, 'css/' + format + '.css'))
86 | } else {
87 | console.error(
88 | chalk.bgRed.black(' ERROR ') +
89 | " Unable to find format ('" +
90 | options.pdf.format +
91 | "')"
92 | )
93 | return
94 | }
95 | }
96 |
97 | this.nuxt.hook('listen', (_, router) => (url = router.url.toString()))
98 | this.nuxt.hook('build:compile', () => {
99 | routeMap = require(path.resolve(this.options.buildDir, 'routes.json'))
100 | })
101 |
102 | /*
103 | * Extending the generated routes with pdf requested routes.
104 | */
105 | this.nuxt.hook('generate:extendRoutes', async routes => {
106 |
107 | const generatedRoutes = await promisifyRoute(options.routes || [])
108 |
109 | for (let i = 0; i < generatedRoutes.length; i++) {
110 | const route = generatedRoutes[i]
111 |
112 | if (routes.filter(r => r.route === route.route).length > 0) {
113 | continue
114 | }
115 |
116 | routes.push({
117 | route: route.route,
118 | payload: null
119 | })
120 | }
121 | })
122 |
123 | const getUrl = (path, locale) => {
124 |
125 | const chunk = routeMap.find(
126 | route => route.path == path.split('?')[0].split('#')[0]
127 | )
128 |
129 | //if (chunk === undefined && path != '/*/') {
130 | // return getUrl('/*/', locale)
131 | //}
132 |
133 | if (chunk === undefined)
134 | throw new Error(
135 | 'Unable to find route at ' + path.split('?')[0].split('#')[0]
136 | )
137 |
138 | const routes = routeMap.filter(route => route.chunkName == chunk.chunkName)
139 |
140 | var uri = ''
141 | var protocol = new URL(url).protocol
142 |
143 | if (i18n.enabled && typeof locale !== 'undefined') {
144 | const routesNameSeparator = i18n.options.routesNameSeparator || '___'
145 | const route = routes.find(
146 | route =>
147 | route.name.endsWith(
148 | routesNameSeparator + locale + routesNameSeparator + 'default'
149 | ) || route.name.endsWith(routesNameSeparator + locale)
150 | )
151 |
152 | if (i18n.options.differentDomains) {
153 | if (locale in i18n.domains) {
154 | uri =
155 | protocol +
156 | '//' +
157 | i18n.domains[locale].replace(/\/$/, '') +
158 | path
159 | } else {
160 | uri = url.replace(/\/$/, '') + path
161 | }
162 | } else {
163 | uri = url.replace(/\/$/, '') + path
164 | }
165 | } else {
166 | uri = url.replace(/\/$/, '') + path
167 | }
168 | return uri
169 | }
170 |
171 | async function build(buildArgs) {
172 |
173 | var nuxt
174 | var listener
175 | try {
176 | if (buildArgs.generated) {
177 | console.log('nuxt-pdf: Starting nuxt instance')
178 | let nuxt = require.resolve("nuxt-edge") ? 'nuxt-edge' : 'nuxt';
179 | const {
180 | loadNuxt
181 | } = require(nuxt);
182 | nuxt = await loadNuxt('start')
183 | listener = await nuxt.server.listen()
184 | }
185 |
186 | url = listener.url;
187 | } catch (e) {
188 | console.error("nuxt-pdf: If this is part of npm run generate be sure to run 'npm run build first'")
189 | }
190 |
191 | const routes = await promisifyRoute(options.routes || [])
192 |
193 | for (let i = 0; i < routes.length; i++) {
194 | const route = routes[i]
195 | console.log(chalk.cyan('↻') + ` Generating PDF ${i+1}:${routes.length} at route ` + route.route)
196 |
197 | try {
198 | // Merge route meta with defaults from config.
199 | const meta = Object.assign({}, options.meta, route.meta)
200 |
201 | let browser = await puppeteer.launch(
202 | Object.assign({
203 | headless: true
204 | }, options.puppeteer)
205 | )
206 |
207 | let page = await browser.newPage();
208 | await page.goto(`${url.replace(/\/$/, "")}${route.route}`, {
209 | waitUntil: 'networkidle2'
210 | });
211 |
212 | if (options.viewport || route.viewport) {
213 | console.log("setting viewport", Object.assign({}, {
214 | ...options.viewport,
215 | ...route.viewport
216 | }))
217 | page.setViewport(Object.assign({}, {
218 | ...options.viewport,
219 | ...route.viewport
220 | }));
221 | }
222 | // Generate pdf based on dom content. (result by bytes)
223 | const bytes = await page.pdf(Object.assign({}, {
224 | ...options.pdf,
225 | ...route.pdf
226 | }))
227 |
228 | // Load bytes into pdf document, used for manipulating meta of file.
229 | const document = await Document.load(bytes)
230 |
231 | // Set the correct meta for pdf document.
232 | if ('title' in meta && meta.title !== '') {
233 | document.setTitle(
234 | (meta.titleTemplate || '%s').replace('%s', meta.title)
235 | )
236 | } else {
237 | document.setTitle(await page.title())
238 | }
239 |
240 | document.setAuthor(meta.author || '')
241 | document.setSubject(meta.subject || '')
242 | document.setProducer(meta.producer || '')
243 | document.setCreationDate(meta.creationDate || new Date())
244 | document.setKeywords(meta.keywords || [])
245 |
246 | const file = path.resolve(buildArgs.generated ? 'dist' : options.dir, route.file)
247 |
248 | // Create folder where file will be stored.
249 | fs.mkdirSync(file.substring(0, file.lastIndexOf('/')), {
250 | recursive: true
251 | })
252 |
253 | // Write document to file.
254 | const ws = fs.createWriteStream(file)
255 | ws.write(await document.save())
256 | ws.end()
257 | console.log(`${chalk.green('✔')} Generated PDF ${i+1}:${routes.length} at file '${file} (${document.getTitle()})`);
258 | if (buildArgs.generated && !route.keep) {
259 | await fs.unlinkSync(`./dist${route.route}/index.html`)
260 | console.log(`${chalk.green('✔')} Removed route index file used for PDF at ${route.route}`);
261 | await fs.rmdirSync(`./dist${route.route}`)
262 | console.log(`${chalk.green('✔')} Removed route directory used for PDF at ${route.route}`);
263 | }
264 | await page.close();
265 | await browser.close()
266 |
267 | } catch (e) {
268 | console.log(`${chalk.red('𐄂')} Failed to generated PDF ${i+1}:${routes.length} at route ${route.route} error: ${e.message}`);
269 | }
270 | }
271 |
272 |
273 | if (nuxt) {
274 | await listener.close()
275 | }
276 | }
277 |
278 | if (process.env.NODE_ENV !== "production") {
279 | this.nuxt.hook('build:compiled', async ({
280 | name
281 | }) => {
282 | if (name !== 'server') return
283 | await build({
284 | generated: false
285 | })
286 | })
287 | } else {
288 | this.nuxt.hook('generate:done', async ({
289 | builder
290 | }) => {
291 | await build({
292 | generated: true
293 | })
294 | })
295 | }
296 |
297 | }
298 |
299 | module.exports.meta = require('../package.json')
300 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nuxt-pdf",
3 | "version": "2.0.1",
4 | "description": "NuxtJS module to generate PDF files and manage PDF in your Nuxt application",
5 | "repository": "https://github.com/ch99q/nuxt-pdf",
6 | "homepage": "https://github.com/ch99q/nuxt-pdf",
7 | "author": {
8 | "name": "Christian Hansen"
9 | },
10 | "keywords": [
11 | "vue",
12 | "nuxt",
13 | "nuxt.js"
14 | ],
15 | "main": "lib/module.js",
16 | "files": [
17 | "lib"
18 | ],
19 | "license": "MIT",
20 | "dependencies": {
21 | "chalk": "^4.1.0",
22 | "pdf-lib": "^1.10.0"
23 | },
24 | "peerDependencies": {
25 | "nuxt": "^2.0.0",
26 | "puppeteer": "^5.0.0"
27 | },
28 | "devDependencies": {
29 | "nuxt": "^2.14.1",
30 | "puppeteer": "^5.2.1"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/playground/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | browser: true,
5 | node: true,
6 | },
7 | parserOptions: {
8 | parser: 'babel-eslint',
9 | },
10 | extends: [
11 | '@nuxtjs',
12 | 'prettier',
13 | 'prettier/vue',
14 | 'plugin:prettier/recommended',
15 | 'plugin:nuxt/recommended',
16 | ],
17 | plugins: ['prettier'],
18 | // add your custom rules here
19 | rules: {},
20 | }
21 |
--------------------------------------------------------------------------------
/playground/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Node template
3 | # Logs
4 | /logs
5 | *.log
6 | npm-debug.log*
7 | yarn-debug.log*
8 | yarn-error.log*
9 |
10 | # Runtime data
11 | pids
12 | *.pid
13 | *.seed
14 | *.pid.lock
15 |
16 | # Directory for instrumented libs generated by jscoverage/JSCover
17 | lib-cov
18 |
19 | # Coverage directory used by tools like istanbul
20 | coverage
21 |
22 | # nyc test coverage
23 | .nyc_output
24 |
25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
26 | .grunt
27 |
28 | # Bower dependency directory (https://bower.io/)
29 | bower_components
30 |
31 | # node-waf configuration
32 | .lock-wscript
33 |
34 | # Compiled binary addons (https://nodejs.org/api/addons.html)
35 | build/Release
36 |
37 | # Dependency directories
38 | node_modules/
39 | jspm_packages/
40 |
41 | # TypeScript v1 declaration files
42 | typings/
43 |
44 | # Optional npm cache directory
45 | .npm
46 |
47 | # Optional eslint cache
48 | .eslintcache
49 |
50 | *.pdf
51 |
52 | # Optional REPL history
53 | .node_repl_history
54 |
55 | # Output of 'npm pack'
56 | *.tgz
57 |
58 | # Yarn Integrity file
59 | .yarn-integrity
60 |
61 | # dotenv environment variables file
62 | .env
63 |
64 | # parcel-bundler cache (https://parceljs.org/)
65 | .cache
66 |
67 | # next.js build output
68 | .next
69 |
70 | # nuxt.js build output
71 | .nuxt
72 |
73 | # Nuxt generate
74 | dist
75 |
76 | # vuepress build output
77 | .vuepress/dist
78 |
79 | # Serverless directories
80 | .serverless
81 |
82 | # IDE / Editor
83 | .idea
84 |
85 | # Service worker
86 | sw.*
87 |
88 | # macOS
89 | .DS_Store
90 |
91 | # Vim swap files
92 | *.swp
93 |
--------------------------------------------------------------------------------
/playground/assets/css/tailwind.css:
--------------------------------------------------------------------------------
1 | @import 'tailwindcss/base';
2 | @import 'tailwindcss/components';
3 | @import 'tailwindcss/utilities';
4 |
--------------------------------------------------------------------------------
/playground/content/article.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Getting started
3 | description: 'Empower your NuxtJS application with @nuxt/content module: write in a content/ directory and fetch your Markdown, JSON, YAML and CSV files through a MongoDB like API, acting as a Git-based Headless CMS.'
4 | ---
5 |
6 | Empower your NuxtJS application with `@nuxtjs/content` module: write in a `content/` directory and fetch your Markdown, JSON, YAML and CSV files through a MongoDB like API, acting as a **Git-based Headless CMS**.
7 |
8 | ## Writing content
9 |
10 | Learn how to write your `content/`, supporting Markdown, YAML, CSV and JSON: https://content.nuxtjs.org/writing.
11 |
12 | ## Fetching content
13 |
14 | Learn how to fetch your content with `$content`: https://content.nuxtjs.org/fetching.
15 |
16 | ## Displaying content
17 |
18 | Learn how to display your Markdown content with the `` component directly in your template: https://content.nuxtjs.org/displaying.
19 |
--------------------------------------------------------------------------------
/playground/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": ".",
4 | "paths": {
5 | "~/*": ["./*"],
6 | "@/*": ["./*"],
7 | "~~/*": ["./*"],
8 | "@@/*": ["./*"]
9 | }
10 | },
11 | "exclude": ["node_modules", ".nuxt", "dist"]
12 | }
13 |
--------------------------------------------------------------------------------
/playground/layout/default.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 |
--------------------------------------------------------------------------------
/playground/nuxt.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | /*
3 | ** Nuxt rendering mode
4 | ** See https://nuxtjs.org/api/configuration-mode
5 | */
6 | mode: 'universal',
7 | /*
8 | ** Nuxt target
9 | ** See https://nuxtjs.org/api/configuration-target
10 | */
11 | // target: 'static',
12 | /*
13 | ** Headers of the page
14 | ** See https://nuxtjs.org/api/configuration-head
15 | */
16 | head: {
17 | title: process.env.npm_package_name || '',
18 | meta: [
19 | { charset: 'utf-8' },
20 | { name: 'viewport', content: 'width=device-width, initial-scale=1' },
21 | {
22 | hid: 'description',
23 | name: 'description',
24 | content: process.env.npm_package_description || '',
25 | },
26 | ],
27 | link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
28 | },
29 | /*
30 | ** Global CSS
31 | */
32 | css: [],
33 | /*
34 | ** Plugins to load before mounting the App
35 | ** https://nuxtjs.org/guide/plugins
36 | */
37 | plugins: [],
38 | /*
39 | ** Auto import components
40 | ** See https://nuxtjs.org/api/configuration-components
41 | */
42 | components: true,
43 | /*
44 | ** Nuxt.js dev-modules
45 | */
46 | buildModules: [
47 | // Doc: https://github.com/nuxt-community/eslint-module
48 | '@nuxtjs/eslint-module',
49 | // Doc: https://github.com/nuxt-community/nuxt-tailwindcss
50 | '@nuxtjs/tailwindcss',
51 | 'nuxt-pdf',
52 | ],
53 | /*
54 | ** Nuxt.js modules
55 | */
56 | modules: [
57 | // Doc: https://github.com/nuxt/content
58 | '@nuxt/content',
59 | // https://i18n.nuxtjs.org
60 | 'nuxt-i18n',
61 | ],
62 | /*
63 | ** PDF module configuration
64 | */
65 | pdf: {
66 | i18n: true,
67 |
68 | routes: [
69 | {
70 | file: 'documentation.pdf',
71 |
72 | route: '/docs',
73 |
74 | meta: {
75 | title: 'Documentation',
76 | },
77 | },
78 | {
79 | file: 'dokumentation.pdf',
80 |
81 | route: '/docs?test=true',
82 |
83 | locale: 'da',
84 | },
85 | {
86 | file: 'article.pdf',
87 |
88 | route: '/article',
89 | },
90 | ],
91 | },
92 | /*
93 | ** I18n module configuration
94 | */
95 | i18n: {
96 | locales: [
97 | {
98 | name: 'English',
99 | code: 'en',
100 | iso: 'en-US',
101 | file: 'en-US',
102 | domain: process.env.DOMAIN_EN || 'localhost:3000',
103 | },
104 | {
105 | name: 'Dansk',
106 | code: 'da',
107 | iso: 'da-DK',
108 | file: 'da-DK',
109 | domain: process.env.DOMAIN_DA || 'localhost.dk:3000',
110 | },
111 | ],
112 |
113 | // differentDomains: true,
114 |
115 | defaultLocale: 'en',
116 |
117 | strategy: 'prefix_and_default',
118 |
119 | seo: true,
120 |
121 | vueI18n: {
122 | fallbackLocale: 'en',
123 | messages: {
124 | en: {
125 | welcome: 'Welcome',
126 | },
127 | da: {
128 | welcome: 'Velkommen',
129 | },
130 | },
131 | },
132 | },
133 | /*
134 | ** Content module configuration
135 | ** See https://content.nuxtjs.org/configuration
136 | */
137 | content: {},
138 | /*
139 | ** Build configuration
140 | ** See https://nuxtjs.org/api/configuration-build/
141 | */
142 | build: {},
143 | }
144 |
--------------------------------------------------------------------------------
/playground/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "playground",
3 | "version": "1.0.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "nuxt",
7 | "build": "nuxt build",
8 | "start": "nuxt start",
9 | "generate": "nuxt generate",
10 | "lint:js": "eslint --ext .js,.vue --ignore-path .gitignore .",
11 | "lint": "yarn lint:js"
12 | },
13 | "lint-staged": {
14 | "*.{js,vue}": "eslint"
15 | },
16 | "husky": {
17 | "hooks": {
18 | "pre-commit": "lint-staged"
19 | }
20 | },
21 | "dependencies": {
22 | "@nuxt/content": "^1.6.0",
23 | "nuxt": "^2.14.1",
24 | "nuxt-i18n": "^6.15.4"
25 | },
26 | "devDependencies": {
27 | "@nuxtjs/eslint-config": "^3.1.0",
28 | "@nuxtjs/eslint-module": "^2.0.0",
29 | "@nuxtjs/tailwindcss": "^3.0.0",
30 | "babel-eslint": "^10.1.0",
31 | "eslint": "^7.6.0",
32 | "eslint-config-prettier": "^6.11.0",
33 | "eslint-plugin-nuxt": "^1.0.0",
34 | "eslint-plugin-prettier": "^3.1.4",
35 | "husky": "^4.2.5",
36 | "lint-staged": "^10.2.11",
37 | "nuxt-pdf": "link:../",
38 | "prettier": "^2.0.5"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/playground/pages/README.md:
--------------------------------------------------------------------------------
1 | # PAGES
2 |
3 | This directory contains your Application Views and Routes.
4 | The framework reads all the `*.vue` files inside this directory and creates the router of your application.
5 |
6 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing).
7 |
--------------------------------------------------------------------------------
/playground/pages/article.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ page.title }}
4 | {{ page.title }}
5 |
6 |
7 |
8 |
9 |
20 |
--------------------------------------------------------------------------------
/playground/pages/docs.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Text above is generated dynamicly by i18n
6 |
7 |
8 | Section 2 | Query: {{ test }}
9 |
10 |
11 |
12 |
13 |
34 |
--------------------------------------------------------------------------------
/playground/pages/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
9 |
12 |
13 |
14 |
15 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/playground/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /*
2 | ** TailwindCSS Configuration File
3 | **
4 | ** Docs: https://tailwindcss.com/docs/configuration
5 | ** Default: https://github.com/tailwindcss/tailwindcss/blob/master/stubs/defaultConfig.stub.js
6 | */
7 | module.exports = {
8 | theme: {},
9 | variants: {},
10 | plugins: [],
11 | purge: {
12 | // Learn more on https://tailwindcss.com/docs/controlling-file-size/#removing-unused-css
13 | enabled: process.env.NODE_ENV === 'production',
14 | content: [
15 | 'components/**/*.vue',
16 | 'layouts/**/*.vue',
17 | 'pages/**/*.vue',
18 | 'plugins/**/*.js',
19 | 'nuxt.config.js'
20 | ]
21 | }
22 | }
23 |
--------------------------------------------------------------------------------