├── .circleci └── config.yml ├── .editorconfig ├── .eslintrc.js ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .nvmrc ├── .prettierrc ├── .versionrc ├── CHANGELOG.md ├── LICENSE ├── README.md ├── babel.config.js ├── commitlint.config.js ├── docs ├── .gitignore ├── README.md ├── content │ ├── en │ │ ├── helpers │ │ │ └── generate-sitemap.md │ │ ├── index.md │ │ ├── quick-start.md │ │ └── usage │ │ │ └── javascript-client.md │ └── settings.json ├── nuxt.config.js ├── package.json ├── static │ ├── icon.png │ ├── logo-dark.svg │ ├── logo-light.svg │ ├── preview-dark.png │ ├── preview.png │ └── sw.js └── yarn.lock ├── example ├── components │ ├── card.vue │ └── navbar.vue ├── layouts │ └── default.vue ├── modules │ └── generate.js ├── nuxt.config.js ├── pages │ ├── _slug.vue │ ├── index.vue │ ├── page │ │ └── _page.vue │ └── tag │ │ ├── _tag.vue │ │ └── _tag │ │ └── page │ │ └── _page.vue ├── static │ └── _redirects └── store │ └── index.js ├── husky.config.js ├── jest.config.js ├── lib ├── module.js └── plugin.js ├── package.json ├── test └── system │ └── ghost-module.test.js ├── tsconfig.json ├── types ├── index.d.ts └── vuex.d.ts └── yarn.lock /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | jobs: 3 | test: 4 | docker: 5 | - image: circleci/node:latest 6 | steps: 7 | - checkout 8 | - run: yarn 9 | - run: yarn test 10 | 11 | workflows: 12 | version: 2 13 | test: 14 | jobs: 15 | - test 16 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_size = 2 6 | indent_style = space 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 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parserOptions: { 4 | parser: 'babel-eslint', 5 | sourceType: 'module', 6 | ecmaVersion: 2018, 7 | }, 8 | env: { 9 | browser: true, 10 | jest: true, 11 | node: true, 12 | }, 13 | extends: ['prettier',], 14 | plugins: ['prettier', 'vue'], 15 | }; 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn commitlint --edit $1 5 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn test 5 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 14 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "es5", 4 | "printWidth": 100 5 | } 6 | -------------------------------------------------------------------------------- /.versionrc: -------------------------------------------------------------------------------- 1 | { 2 | "types": [ 3 | { "type": "feat", "section": "Features" }, 4 | { "type": "fix", "section": "Bug Fixes" }, 5 | { "type": "chore", "section": "Chore" }, 6 | { "type": "docs", "section": "Documentation" }, 7 | { "type": "style", "section": "Styling" }, 8 | { "type": "refactor", "section": "Internal" }, 9 | { "type": "perf", "section": "Internal" }, 10 | { "type": "test", "section": "Internal"} 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [2.1.5](https://github.com/Gomah/nuxt-ghost/compare/v2.1.4...v2.1.5) (2022-10-24) 6 | 7 | 8 | ### Chore 9 | 10 | * **deps:** bump @tryghost/content-api to 1.11.4 ([b65744e](https://github.com/Gomah/nuxt-ghost/commit/b65744e69ff9ef32ef65d141a32b85cbd3932d98)) 11 | 12 | ### [2.1.4](https://github.com/Gomah/nuxt-ghost/compare/v2.1.3...v2.1.4) (2022-08-29) 13 | 14 | 15 | ### Chore 16 | 17 | * **deps:** bump @tryghost/content-api to 1.11.1 ([1807a8b](https://github.com/Gomah/nuxt-ghost/commit/1807a8b55c9b3b97ccdfdf581f01a17addead79b)) 18 | 19 | ### [2.1.3](https://github.com/Gomah/nuxt-ghost/compare/v2.1.2...v2.1.3) (2022-06-18) 20 | 21 | 22 | ### Chore 23 | 24 | * **deps:** bump @tryghost/content-api to 1.11.0 ([ce75c62](https://github.com/Gomah/nuxt-ghost/commit/ce75c62eb544975fc052fa00c3bdac66752535b8)) 25 | 26 | ### [2.1.2](https://github.com/Gomah/nuxt-ghost/compare/v2.1.1...v2.1.2) (2022-05-29) 27 | 28 | 29 | ### Chore 30 | 31 | * **deps:** bump @tryghost/content-api to 1.10.0 ([8916492](https://github.com/Gomah/nuxt-ghost/commit/89164920b8a4ff439f56700617ff180ba693ea45)) 32 | 33 | ### [2.1.1](https://github.com/Gomah/nuxt-ghost/compare/v2.1.0...v2.1.1) (2022-04-24) 34 | 35 | 36 | ### Chore 37 | 38 | * **deps:** bump @tryghost/content-api to 1.9.1 ([9ae569c](https://github.com/Gomah/nuxt-ghost/commit/9ae569c0f597b029107a53764003962ad5a23813)) 39 | 40 | ## [2.1.0](https://github.com/Gomah/nuxt-ghost/compare/v2.0.20...v2.1.0) (2022-04-17) 41 | 42 | ### [2.0.20](https://github.com/Gomah/nuxt-ghost/compare/v2.0.19...v2.0.20) (2022-04-05) 43 | 44 | 45 | ### Chore 46 | 47 | * **deps:** bump @tryghost/content-api to 1.7.2 ([6451ea2](https://github.com/Gomah/nuxt-ghost/commit/6451ea296a48f1e647cf70975b18bb13be0e819c)) 48 | 49 | ### [2.0.19](https://github.com/Gomah/nuxt-ghost/compare/v2.0.18...v2.0.19) (2022-03-13) 50 | 51 | 52 | ### Chore 53 | 54 | * **deps:** bump @tryghost/content-api to 1.7.0 ([83385c6](https://github.com/Gomah/nuxt-ghost/commit/83385c663845a3d25af2b85731508e4397bd4383)) 55 | 56 | ### [2.0.18](https://github.com/Gomah/nuxt-ghost/compare/v2.0.17...v2.0.18) (2022-03-07) 57 | 58 | 59 | ### Chore 60 | 61 | * **deps:** bump @tryghost/content-api to 1.6.2 ([e571705](https://github.com/Gomah/nuxt-ghost/commit/e5717056b08967b8489f0fb9fe9f1752896607ec)) 62 | 63 | ### [2.0.17](https://github.com/Gomah/nuxt-ghost/compare/v2.0.16...v2.0.17) (2022-02-02) 64 | 65 | 66 | ### Chore 67 | 68 | * **deps:** bump @tryghost/content-api to 1.6.0 ([5609b06](https://github.com/Gomah/nuxt-ghost/commit/5609b06086aa3a22f5e78c99676a1f60141c0313)) 69 | 70 | ### [2.0.16](https://github.com/Gomah/nuxt-ghost/compare/v2.0.15...v2.0.16) (2022-01-21) 71 | 72 | 73 | ### Chore 74 | 75 | * **deps:** bump @tryghost/content-api to 1.5.17 ([38a7579](https://github.com/Gomah/nuxt-ghost/commit/38a757953601220ec84fa3724f01ba1155557ef1)) 76 | 77 | ### [2.0.15](https://github.com/Gomah/nuxt-ghost/compare/v2.0.14...v2.0.15) (2022-01-19) 78 | 79 | 80 | ### Bug Fixes 81 | 82 | * yarn.lock dependencies ([a052d19](https://github.com/Gomah/nuxt-ghost/commit/a052d197d3c2cbbbceb5f67d6f91687518089b20)) 83 | 84 | ### [2.0.14](https://github.com/Gomah/nuxt-ghost/compare/v2.0.13...v2.0.14) (2022-01-07) 85 | 86 | ### [2.0.13](https://github.com/Gomah/nuxt-ghost/compare/v2.0.12...v2.0.13) (2021-11-22) 87 | 88 | 89 | ### Chore 90 | 91 | * **deps:** bump @tryghost/content-api to 1.5.16 ([d55d337](https://github.com/Gomah/nuxt-ghost/commit/d55d337bc215fd430826b9f0a0542ba9da867eae)) 92 | 93 | ### [2.0.12](https://github.com/Gomah/nuxt-ghost/compare/v2.0.11...v2.0.12) (2021-11-18) 94 | 95 | 96 | ### Chore 97 | 98 | * **deps:** bump @tryghost/content-api to 1.5.15 ([408670a](https://github.com/Gomah/nuxt-ghost/commit/408670a33d2eee0b2f0c2b127a3659d06dd88eb0)) 99 | 100 | ### [2.0.11](https://github.com/Gomah/nuxt-ghost/compare/v2.0.10...v2.0.11) (2021-11-11) 101 | 102 | 103 | ### Chore 104 | 105 | * **deps:** bump @tryghost/content-api to 1.5.14 ([a9dad88](https://github.com/Gomah/nuxt-ghost/commit/a9dad884c89f2bb59b97dc2a5a8bd2a6db2f5149)) 106 | 107 | ### [2.0.10](https://github.com/Gomah/nuxt-ghost/compare/v2.0.9...v2.0.10) (2021-09-02) 108 | 109 | 110 | ### Chore 111 | 112 | * **deps:** bump @tryghost/content-api to 1.5.13 ([867c76d](https://github.com/Gomah/nuxt-ghost/commit/867c76d497415a0e62e016a0999a2d99e4e05a5f)) 113 | 114 | ### [2.0.9](https://github.com/Gomah/nuxt-ghost/compare/v2.0.8...v2.0.9) (2021-08-12) 115 | 116 | 117 | ### Chore 118 | 119 | * **deps:** bump @tryghost/content-api to 1.5.12 ([cec58c7](https://github.com/Gomah/nuxt-ghost/commit/cec58c7b877fd0a724ae2a919f2e0828768a71b9)) 120 | 121 | ### [2.0.8](https://github.com/Gomah/nuxt-ghost/compare/v2.0.7...v2.0.8) (2021-07-31) 122 | 123 | 124 | ### Chore 125 | 126 | * export GhostContentAPI ([8335f4e](https://github.com/Gomah/nuxt-ghost/commit/8335f4e9eb1ea2f302e33095ebf9593918c674ed)) 127 | 128 | 129 | ### Documentation 130 | 131 | * adjust generate example ([bb56f1f](https://github.com/Gomah/nuxt-ghost/commit/bb56f1f07a0abec445857e31fd81b14b379efb0b)) 132 | 133 | ### [2.0.7](https://github.com/Gomah/nuxt-ghost/compare/v2.0.6...v2.0.7) (2021-07-31) 134 | 135 | 136 | ### Chore 137 | 138 | * **deps:** bump @tryghost/content-api to 1.5.11 ([1d557ad](https://github.com/Gomah/nuxt-ghost/commit/1d557ad72c75dd2ff24d520e55549c5034ee8903)) 139 | * bump husky ([bd8bca2](https://github.com/Gomah/nuxt-ghost/commit/bd8bca21fe5a6d86b701970d855b16e53f509fde)) 140 | 141 | ### [2.0.6](https://github.com/Gomah/nuxt-ghost/compare/v2.0.5...v2.0.6) (2021-07-05) 142 | 143 | 144 | ### Chore 145 | 146 | * **deps:** update @tryghost/content-api to 1.5.10 ([9748f1d](https://github.com/Gomah/nuxt-ghost/commit/9748f1dabb6c1e6af98844e191aa39415b44e707)) 147 | 148 | ### [2.0.5](https://github.com/Gomah/nuxt-ghost/compare/v2.0.4...v2.0.5) (2021-06-26) 149 | 150 | 151 | ### Chore 152 | 153 | * **deps:** update @tryghost/content-api ([f768799](https://github.com/Gomah/nuxt-ghost/commit/f76879958452ab70500d9ea3d97e858bb9f3eeaa)) 154 | 155 | ### [2.0.4](https://github.com/Gomah/nuxt-ghost/compare/v2.0.3...v2.0.4) (2021-06-20) 156 | 157 | 158 | ### Chore 159 | 160 | * **deps:** update @tryghost/content-api ([9ea60a6](https://github.com/Gomah/nuxt-ghost/commit/9ea60a6c9acec5267207a6c9e10c47346e59e66b)) 161 | 162 | ### [2.0.3](https://github.com/Gomah/nuxt-ghost/compare/v2.0.2...v2.0.3) (2021-06-15) 163 | 164 | 165 | ### Chore 166 | 167 | * **deps:** bump @tryghost/content-api to 1.5.7 ([0d59b17](https://github.com/Gomah/nuxt-ghost/commit/0d59b17bddc315f61f3bb0ddf6c0d6d3a8a51e11)) 168 | 169 | ### [2.0.2](https://github.com/Gomah/nuxt-ghost/compare/v2.0.1...v2.0.2) (2021-05-14) 170 | 171 | 172 | ### Chore 173 | 174 | * **deps:** upgrade dependencies ([b09b11d](https://github.com/Gomah/nuxt-ghost/commit/b09b11d92de0e79dde809393aa064aee217dfa8c)) 175 | 176 | ### [2.0.1](https://github.com/Gomah/nuxt-ghost/compare/v2.0.0...v2.0.1) (2021-04-23) 177 | 178 | 179 | ### Chore 180 | 181 | * **deps:** bump @tryghost/content-api to v1.5.4 ([f11902a](https://github.com/Gomah/nuxt-ghost/commit/f11902a6be02e00e41a0fd8b13f92ab26c16e17f)) 182 | 183 | ## [2.0.0](https://github.com/Gomah/nuxt-ghost/compare/v1.0.17...v2.0.0) (2021-04-09) 184 | 185 | 186 | ### Features 187 | 188 | * **core:** use v4 by default ([e96b0db](https://github.com/Gomah/nuxt-ghost/commit/e96b0db82ed26b235c1f063e2a3f681346f36deb)) 189 | 190 | 191 | ### Documentation 192 | 193 | * update docs for v4 ([579463c](https://github.com/Gomah/nuxt-ghost/commit/579463cddcbe9816f5c9a3dfc3c0ec398c982aac)) 194 | 195 | ### [1.0.17](https://github.com/Gomah/nuxt-ghost/compare/v1.0.16...v1.0.17) (2021-04-09) 196 | 197 | 198 | ### Chore 199 | 200 | * **deps:** update @tryghost/content-api ([d0df945](https://github.com/Gomah/nuxt-ghost/commit/d0df945d0b2519f28acfd14f56ceecb8b32cbbae)) 201 | 202 | ### [1.0.16](https://github.com/Gomah/nuxt-ghost/compare/v1.0.15...v1.0.16) (2021-03-15) 203 | 204 | 205 | ### Chore 206 | 207 | * **deps:** upgrade dependencies ([a4ce05d](https://github.com/Gomah/nuxt-ghost/commit/a4ce05d65b9207ea13c8237a2b55f97adac42045)) 208 | 209 | ### [1.0.15](https://github.com/Gomah/nuxt-ghost/compare/v1.0.14...v1.0.15) (2021-03-07) 210 | 211 | 212 | ### Chore 213 | 214 | * **deps:** upgrade dependencies ([27d5999](https://github.com/Gomah/nuxt-ghost/commit/27d59996587f74ffac87391fe31756ec2c035af7)) 215 | * fix eslint config ([19badb5](https://github.com/Gomah/nuxt-ghost/commit/19badb5f4b487834eab0794a5def949ebf773746)) 216 | 217 | ### [1.0.14](https://github.com/Gomah/nuxt-ghost/compare/v1.0.13...v1.0.14) (2021-03-04) 218 | 219 | 220 | ### Chore 221 | 222 | * **deps:** upgrade dependencies ([aed0386](https://github.com/Gomah/nuxt-ghost/commit/aed0386b07c749a79375b77d698631203cdce652)) 223 | 224 | ### [1.0.13](https://github.com/Gomah/nuxt-ghost/compare/v1.0.12...v1.0.13) (2021-02-11) 225 | 226 | 227 | ### Documentation 228 | 229 | * Init docs ([0aafd0e](https://github.com/Gomah/nuxt-ghost/commit/0aafd0e425a119f232fee223635cce8741148fb4)) 230 | 231 | 232 | ### Chore 233 | 234 | * **deps:** upgrade dependencies ([0f3f8d9](https://github.com/Gomah/nuxt-ghost/commit/0f3f8d9aaba2fd878cf34549b83963a6e5482514)) 235 | 236 | ### [1.0.12](https://github.com/Gomah/nuxt-ghost/compare/v1.0.11...v1.0.12) (2021-01-27) 237 | 238 | 239 | ### Chore 240 | 241 | * **deps:** bump @types/tryghost__content-api ([ff4ea11](https://github.com/Gomah/nuxt-ghost/commit/ff4ea11849ecf9fc7566d170f2e027a3503e1e36)) 242 | 243 | ### [1.0.11](https://github.com/Gomah/nuxt-ghost/compare/v1.0.10...v1.0.11) (2021-01-21) 244 | 245 | 246 | ### Chore 247 | 248 | * **deps:** upgrade dependencies ([87b5e12](https://github.com/Gomah/nuxt-ghost/commit/87b5e12f51e9163c551faed78c2ac500dbd87d92)) 249 | 250 | ### [1.0.10](https://github.com/Gomah/nuxt-ghost/compare/v1.0.9...v1.0.10) (2021-01-10) 251 | 252 | 253 | ### Chore 254 | 255 | * **deps:** upgrade dependencies ([c9482c5](https://github.com/Gomah/nuxt-ghost/commit/c9482c5bb4797c842cf082ce2b81dcd878951796)) 256 | 257 | ### [1.0.9](https://github.com/Gomah/nuxt-ghost/compare/v1.0.8...v1.0.9) (2020-12-20) 258 | 259 | 260 | ### Chore 261 | 262 | * **deps:** upgrade dependencies ([5f0c58b](https://github.com/Gomah/nuxt-ghost/commit/5f0c58b6445a4fda956ffbe38bf0d7a665332383)) 263 | 264 | ### [1.0.8](https://github.com/Gomah/nuxt-ghost/compare/v1.0.7...v1.0.8) (2020-11-11) 265 | 266 | 267 | ### Chore 268 | 269 | * **deps:** update @tryghost/content-api ([4e197ce](https://github.com/Gomah/nuxt-ghost/commit/4e197cebb12f5987f6c22c373fd7108177fb4433)) 270 | * **example:** use typescript ([3fa0815](https://github.com/Gomah/nuxt-ghost/commit/3fa0815d367d597163000d3bd6aa9c023cdd4104)) 271 | 272 | ### [1.0.7](https://github.com/Gomah/nuxt-ghost/compare/v1.0.6...v1.0.7) (2020-10-29) 273 | 274 | ### [1.0.6](https://github.com/Gomah/nuxt-ghost/compare/v1.0.5...v1.0.6) (2020-10-29) 275 | 276 | 277 | ### Chore 278 | 279 | * **deps:** update @tryghost/content-api to 1.4.4 ([67f6190](https://github.com/Gomah/nuxt-ghost/commit/67f61905b950b6bb64289d9141f6db4a334286ef)) 280 | * **deps:** upgrade dependencies ([84b75d6](https://github.com/Gomah/nuxt-ghost/commit/84b75d65feab7939eaf7464f2d59965858f50643)) 281 | * **deps:** upgrade dependencies ([166816e](https://github.com/Gomah/nuxt-ghost/commit/166816e0a2d0d47308b1061b4f6d93aedf67dab8)) 282 | 283 | 284 | ### Internal 285 | 286 | * use @babel/preset-env preset ([e3ddf3b](https://github.com/Gomah/nuxt-ghost/commit/e3ddf3b0247a0035b9fd165e2efb1e9f65f042a0)) 287 | 288 | ### [1.0.5](https://github.com/Gomah/nuxt-ghost/compare/v1.0.4...v1.0.5) (2020-04-17) 289 | 290 | 291 | ### Chore 292 | 293 | * **deps:** upgrade dependencies ([2fe4aea](https://github.com/Gomah/nuxt-ghost/commit/2fe4aea98a862002203f968974ae697d99ae8dfd)) 294 | 295 | ### [1.0.4](https://github.com/Gomah/nuxt-ghost/compare/v1.0.3...v1.0.4) (2020-04-01) 296 | 297 | 298 | ### Chore 299 | 300 | * **deps:** upgrade dependencies ([2b7f82f](https://github.com/Gomah/nuxt-ghost/commit/2b7f82f4bebe2250a143321c123bb3a17bb7777c)) 301 | 302 | ### [1.0.3](https://github.com/Gomah/nuxt-ghost/compare/v1.0.2...v1.0.3) (2020-03-23) 303 | 304 | 305 | ### Chore 306 | 307 | * **deps:** upgrade dependencies ([cb0b483](https://github.com/Gomah/nuxt-ghost/commit/cb0b48356ecf51872ff273894eef9ccd22bac457)) 308 | 309 | ### [1.0.2](https://github.com/Gomah/nuxt-ghost/compare/v1.0.1...v1.0.2) (2020-01-24) 310 | 311 | 312 | ### Chore 313 | 314 | * **deps:** update Ghost SDK ([ad0a36f](https://github.com/Gomah/nuxt-ghost/commit/ad0a36f2f67b717cffa793410aeacf6d3e67ee37)) 315 | 316 | ### [1.0.1](https://github.com/Gomah/nuxt-ghost/compare/v1.0.0...v1.0.1) (2020-01-18) 317 | 318 | 319 | ### Chore 320 | 321 | * **deps:** bump dependencies ([f2fd710](https://github.com/Gomah/nuxt-ghost/commit/f2fd71052093bc932fb613c191d369accef7d61f)) 322 | * **example:** add _redirects ([ebac4e5](https://github.com/Gomah/nuxt-ghost/commit/ebac4e56db4fa9250c299fec719c97d4b7b59e62)) 323 | 324 | ## 1.0.0 (2019-12-29) 325 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Thomas Marrec 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-ghost](https://nuxt-ghost.vercel.app/preview.png)](https://nuxt-ghost.vercel.app) 2 | 3 | # 👻 Ghost Module 4 | 5 | [![circleci][circleci-src]][circleci-href] 6 | [![npm version][npm-version-src]][npm-version-href] 7 | [![Dependencies][david-dm-src]][david-dm-href] 8 | [![npm downloads][npm-downloads-src]][npm-downloads-href] 9 | [![code style: prettier](https://img.shields.io/badge/code_style-prettier-1a2b34.svg?style=flat-square)](https://prettier.io) 10 | [![License: MIT](https://img.shields.io/badge/License-MIT-black.svg?style=flat-square)](https://opensource.org/licenses/MIT) 11 | 12 | > Easy Ghost content API integration with Nuxt.js. 13 | 14 | [📖 **Release Notes**](./CHANGELOG.md) 15 | 16 | [🌎 **Demo**](https://nuxt-ghost.netlify.com) 17 | 18 | ## Setup 19 | 20 | Install with yarn: 21 | 22 | ```bash 23 | yarn add nuxt-ghost 24 | ``` 25 | 26 | Install with npm: 27 | 28 | ```bash 29 | npm install nuxt-ghost 30 | ``` 31 | 32 | **nuxt.config.js** 33 | 34 | ```ts 35 | module.exports = { 36 | modules: ['nuxt-ghost'], 37 | 38 | ghost: { 39 | /** 40 | * Your Ghost url 41 | */ 42 | url: 'https://demo.ghost.io/ghost', 43 | 44 | /** 45 | * Your content api key 46 | */ 47 | key: '22444f78447824223cefc48062', 48 | 49 | /** 50 | * Version 51 | * default: v4 52 | */ 53 | version: 'v4', 54 | }, 55 | }; 56 | ``` 57 | 58 | ### Hook for generating ghost routes (nuxt generate & sitemap) 59 | 60 | Create another module file in `modules/`: 61 | 62 | ```ts 63 | // modules/sitemap.js 64 | import { GhostContentAPI } from 'nuxt-ghost'; 65 | 66 | export default async function (ctx) { 67 | const config = { 68 | blogPrefix: '', 69 | tagPrefix: 'tag', 70 | perPage: 3, 71 | }; 72 | 73 | this.nuxt.hook('generate:before', async (nuxt, generateOptions, ...oi) => { 74 | const $ghost = new GhostContentAPI({ 75 | ...nuxt.options.ghost, 76 | }); 77 | 78 | const [posts, tags] = await Promise.all([ 79 | $ghost.posts.browse({ 80 | limit: 'all', 81 | }), 82 | $ghost.tags.browse({ order: 'slug ASC', limit: 'all', include: 'count.posts' }), 83 | ]); 84 | 85 | // Post routes 86 | const postsRoutes = posts.map((post) => `${config.blogPrefix}/${post.slug}`); 87 | 88 | // Blog routes 89 | const blogPagesRoutes = []; 90 | const totalPages = Math.ceil(posts.length / config.perPage); 91 | 92 | if (totalPages > 1) { 93 | for (let page = 2; page <= totalPages; page += 1) { 94 | const route = `${config.blogPrefix}/page/${page}`; 95 | blogPagesRoutes.push(route); 96 | } 97 | } 98 | 99 | // Tag routes 100 | const tagRoutes = tags.reduce((arr, tag) => { 101 | const tagRoute = `${config.blogPrefix}${config.tagPrefix}/${tag.slug}`; 102 | arr.push(tagRoute); 103 | 104 | const maxPage = Math.ceil(tag.count.posts / config.perPage); 105 | 106 | if (maxPage > 1) { 107 | for (let page = 2; page <= maxPage; page += 1) { 108 | const route = `${config.blogPrefix}${config.tagPrefix}/${tag.slug}/page/${page}`; 109 | arr.push(route); 110 | } 111 | } 112 | 113 | return arr; 114 | }, []); 115 | 116 | const extraRoutes = [...postsRoutes, ...blogPagesRoutes, ...tagRoutes]; 117 | 118 | generateOptions.routes = generateOptions.routes 119 | ? generateOptions.routes.concat(extraRoutes) 120 | : extraRoutes; 121 | 122 | // Add to the sitemap 123 | if (nuxt.sitemap) { 124 | Object.assign(nuxt.sitemap, { 125 | routes: [...(nuxt.sitemap.routes && [...nuxt.sitemap.routes]), ...extraRoutes], 126 | }); 127 | } 128 | }); 129 | } 130 | ``` 131 | 132 | Then add it to the nuxt.config: 133 | 134 | ```ts 135 | module.exports = { 136 | modules: ['nuxt-ghost', './modules/sitemap.js'], 137 | 138 | ghost: { 139 | /** 140 | * Your Ghost url 141 | */ 142 | url: 'https://demo.ghost.io/ghost', 143 | 144 | /** 145 | * Your content api key 146 | */ 147 | key: '22444f78447824223cefc48062', 148 | 149 | /** 150 | * Version 151 | * default: v4 152 | */ 153 | version: 'v4', 154 | }, 155 | }; 156 | ``` 157 | 158 | ## Development 159 | 160 | 1. Clone this repository 161 | 2. Install dependencies using `yarn install` or `npm install` 162 | 3. Start development server using `npm run dev` 163 | 164 | ## 📑 License 165 | 166 | [MIT License](./LICENSE) 167 | 168 | 169 | 170 | [circleci-src]: https://circleci.com/gh/Gomah/nuxt-ghost.svg?style=shield 171 | [circleci-href]: https://circleci.com/gh/Gomah/nuxt-ghost 172 | [npm-version-src]: https://img.shields.io/npm/dt/nuxt-ghost.svg?style=flat-square 173 | [npm-version-href]: https://npmjs.com/package/nuxt-ghost 174 | [npm-downloads-src]: https://img.shields.io/npm/v/nuxt-ghost/latest.svg?style=flat-square 175 | [npm-downloads-href]: https://npmjs.com/package/nuxt-ghost 176 | [david-dm-src]: https://david-dm.org/gomah/nuxt-ghost/status.svg?style=flat-square 177 | [david-dm-href]: https://david-dm.org/gomah/nuxt-ghost 178 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | test: { 4 | presets: [ 5 | [ 6 | '@babel/preset-env', 7 | { 8 | targets: { 9 | node: 'current', 10 | }, 11 | }, 12 | ], 13 | ], 14 | }, 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | .vercel 2 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Nuxt Ghost Docs 2 | 3 | ## Setup 4 | 5 | Install dependencies: 6 | 7 | ```bash 8 | yarn install 9 | ``` 10 | 11 | ## Development 12 | 13 | ```bash 14 | yarn dev 15 | ``` 16 | 17 | ## Static Generation 18 | 19 | This will create the `dist/` directory for publishing to static hosting: 20 | 21 | ```bash 22 | yarn generate 23 | ``` 24 | 25 | To preview the static generated app, run `yarn start` 26 | 27 | For detailed explanation on how things work, checkout [nuxt/content](https://content.nuxtjs.org) and [@nuxt/content theme docs](https://content.nuxtjs.org/themes-docs). 28 | -------------------------------------------------------------------------------- /docs/content/en/helpers/generate-sitemap.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Nuxt Generate & Sitemap 3 | description: 'Easy Ghost content API integration with Nuxt.js' 4 | position: 3 5 | category: 'Helpers' 6 | --- 7 | 8 | ### Hook for generating ghost routes (nuxt generate & sitemap) 9 | 10 | Create another module file in `modules/`: 11 | 12 | ```ts 13 | // modules/sitemap.js 14 | import { GhostContentAPI } from 'nuxt-ghost'; 15 | 16 | export default async function (ctx) { 17 | const config = { 18 | blogPrefix: '', 19 | tagPrefix: 'tag', 20 | perPage: 3, 21 | }; 22 | 23 | this.nuxt.hook('generate:before', async (nuxt, generateOptions, ...oi) => { 24 | const $ghost = new GhostContentAPI({ 25 | ...nuxt.options.ghost, 26 | }); 27 | 28 | const [posts, tags] = await Promise.all([ 29 | $ghost.posts.browse({ 30 | limit: 'all', 31 | }), 32 | $ghost.tags.browse({ order: 'slug ASC', limit: 'all', include: 'count.posts' }), 33 | ]); 34 | 35 | // Post routes 36 | const postsRoutes = posts.map((post) => `${config.blogPrefix}/${post.slug}`); 37 | 38 | // Blog routes 39 | const blogPagesRoutes = []; 40 | const totalPages = Math.ceil(posts.length / config.perPage); 41 | 42 | if (totalPages > 1) { 43 | for (let page = 2; page <= totalPages; page += 1) { 44 | const route = `${config.blogPrefix}/page/${page}`; 45 | blogPagesRoutes.push(route); 46 | } 47 | } 48 | 49 | // Tag routes 50 | const tagRoutes = tags.reduce((arr, tag) => { 51 | const tagRoute = `${config.blogPrefix}${config.tagPrefix}/${tag.slug}`; 52 | arr.push(tagRoute); 53 | 54 | const maxPage = Math.ceil(tag.count.posts / config.perPage); 55 | 56 | if (maxPage > 1) { 57 | for (let page = 2; page <= maxPage; page += 1) { 58 | const route = `${config.blogPrefix}${config.tagPrefix}/${tag.slug}/page/${page}`; 59 | arr.push(route); 60 | } 61 | } 62 | 63 | return arr; 64 | }, []); 65 | 66 | const extraRoutes = [...postsRoutes, ...blogPagesRoutes, ...tagRoutes]; 67 | 68 | generateOptions.routes = generateOptions.routes 69 | ? generateOptions.routes.concat(extraRoutes) 70 | : extraRoutes; 71 | 72 | // Add to the sitemap 73 | if (nuxt.sitemap) { 74 | Object.assign(nuxt.sitemap, { 75 | routes: [...(nuxt.sitemap.routes && [...nuxt.sitemap.routes]), ...extraRoutes], 76 | }); 77 | } 78 | }); 79 | } 80 | ``` 81 | 82 | Then add it to the nuxt.config: 83 | 84 | ```ts 85 | module.exports = { 86 | modules: ['nuxt-ghost', './modules/sitemap.js'], 87 | 88 | ghost: { 89 | /** 90 | * Your Ghost url 91 | */ 92 | url: 'https://demo.ghost.io/ghost', 93 | 94 | /** 95 | * Your content api key 96 | */ 97 | key: '22444f78447824223cefc48062', 98 | 99 | /** 100 | * Version 101 | * default: v4 102 | */ 103 | version: 'v4', 104 | }, 105 | }; 106 | ``` 107 | -------------------------------------------------------------------------------- /docs/content/en/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction 3 | description: 'Easy Ghost content API integration with Nuxt.js' 4 | position: 1 5 | category: '' 6 | features: 7 | - Add Ghost Content API client to your Nuxt app in seconds 8 | - Access Ghost Content API SDK with $ghost 9 | - TypeScript support 10 | --- 11 | 12 | 13 | 14 | 15 | Easy Ghost content API integration with [Nuxt.js](https://nuxtjs.org). 16 | 17 | ## Features 18 | 19 | 20 | -------------------------------------------------------------------------------- /docs/content/en/quick-start.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Setup 3 | description: 'Easy Ghost content API integration with Nuxt.js' 4 | position: 2 5 | category: 'Guide' 6 | --- 7 | 8 | Check the [Nuxt.js documentation](https://nuxtjs.org/api/configuration-modules#the-modules-property) for more information about installing and using modules in Nuxt.js. 9 | 10 | ## Setup 11 | 12 | Add `nuxt-ghost` as a dependency to your project: 13 | 14 | 15 | 16 | 17 | ```bash 18 | yarn add nuxt-ghost 19 | ``` 20 | 21 | 22 | 23 | 24 | ```bash 25 | npm install nuxt-ghost 26 | ``` 27 | 28 | 29 | 30 | 31 | ## nuxt.config.js 32 | 33 | ```ts 34 | module.exports = { 35 | modules: ['nuxt-ghost'], 36 | 37 | ghost: { 38 | /** 39 | * Your Ghost url 40 | */ 41 | url: 'https://demo.ghost.io/ghost', 42 | 43 | /** 44 | * Your content api key 45 | */ 46 | key: '22444f78447824223cefc48062', 47 | 48 | /** 49 | * Version 50 | * default: v4 51 | */ 52 | version: 'v4', 53 | }, 54 | }; 55 | ``` 56 | 57 | ## TypeScript 58 | 59 | `nuxt-ghost` offers type definitions. Just add an entry in `tsconfig.json`. 60 | 61 | 62 | 63 | 64 | ```json{}[tsconfig.json] 65 | { 66 | "compilerOptions": { 67 | "types": ["@nuxt/types", "nuxt-ghost"] 68 | } 69 | } 70 | ``` 71 | 72 | 73 | 74 | 75 | ```json{}[tsconfig.json] 76 | { 77 | "compilerOptions": { 78 | "types": ["@nuxt/vue-app", "nuxt-ghost"] 79 | } 80 | } 81 | ``` 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /docs/content/en/usage/javascript-client.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Content API Client 3 | description: 'Ghost provides a flexible promise-based JavaScript library for accessing the Content API. The library can be used in any JavaScript project, client or server side and abstracts away all the pain points of working with API data' 4 | position: 2 5 | category: 'Usage' 6 | --- 7 | 8 | ## Content API JavaScript Client 9 | 10 | Ghost provides a flexible promise-based JavaScript library for accessing the Content API. The library can be used in any JavaScript project, client or server side and abstracts away all the pain points of working with API data. 11 | 12 | ## Example 13 | 14 | ```vue 15 | 34 | ``` 35 | 36 | ## Authentication 37 | 38 | The client requires the host address of your Ghost API, a Content API key, and a version string in order to authenticate. 39 | 40 | The Content API URL and key can be obtained by creating a new `Custom Integration` under the **Integrations** screen in Ghost Admin. 41 | 42 | 43 | 44 | See the documentation on [Content API authentication](https://ghost.org/docs/content-api/#authentication) for more explanation. 45 | 46 | ## Endpoints 47 | 48 | All endpoints & parameters provided by the [Content API](https://ghost.org/docs/content-api/) are supported. 49 | 50 | ```ts 51 | // Browsing posts returns Promise([Post...]); 52 | // The resolved array will have a meta property 53 | this.$ghost.posts.browse({ limit: 2, include: 'tags,authors' }); 54 | this.$ghost.posts.browse(); 55 | 56 | // Reading posts returns Promise(Post); 57 | this.$ghost.posts.read({ id: 'abcd1234' }); 58 | this.$ghost.posts.read({ slug: 'something' }, { formats: ['html', 'plaintext'] }); 59 | 60 | // Browsing authors returns Promise([Author...]) 61 | // The resolved array will have a meta property 62 | this.$ghost.authors.browse({ page: 2 }); 63 | this.$ghost.authors.browse(); 64 | 65 | // Reading authors returns Promise(Author); 66 | this.$ghost.authors.read({ id: 'abcd1234' }); 67 | this.$ghost.authors.read({ slug: 'something' }, { include: 'count.posts' }); // include can be array for any of these 68 | 69 | // Browsing tags returns Promise([Tag...]) 70 | // The resolved array will have a meta property 71 | this.$ghost.tags.browse({ order: 'slug ASC' }); 72 | this.$ghost.tags.browse(); 73 | 74 | // Reading tags returns Promise(Tag); 75 | this.$ghost.tags.read({ id: 'abcd1234' }); 76 | this.$ghost.tags.read({ slug: 'something' }, { include: 'count.posts' }); 77 | 78 | // Browsing pages returns Promise([Page...]) 79 | // The resolved array will have a meta property 80 | this.$ghost.pages.browse({ limit: 2 }); 81 | this.$ghost.pages.browse(); 82 | 83 | // Reading pages returns Promise(Page); 84 | this.$ghost.pages.read({ id: 'abcd1234' }); 85 | this.$ghost.pages.read({ slug: 'something' }, { fields: ['title'] }); 86 | 87 | // Browsing settings returns Promise(Settings...) 88 | // The resolved object has each setting as a key value pair 89 | this.$ghost.settings.browse(); 90 | ``` 91 | 92 | For all resources except settings, the browse() method will return an array of objects, and the read() method will return a single object. The settings.browse() endpoint always returns a single object with all the available key-value pairs. 93 | 94 | See the documentation on [Content API resources](https://ghost.org/docs/content-api/#resources) for a full description of the response for each resource. 95 | 96 | ## Filtering 97 | 98 | Ghost provides the `filter` parameter to fetch your content with endless possibilities! Especially useful for retrieving posts according to their tags, authors or other properties. 99 | 100 | Ghost uses the NQL query language to create filters in a simple yet powerful string format. See the [NQL Syntax Reference](https://ghost.org/docs/content-api/#filtering) for full details. 101 | 102 | Filters are provided to client libraries via the `filter` property of any `browse` method. 103 | 104 | ```ts 105 | this.$ghost.posts.browse({ filter: 'featured:true' }); 106 | ``` 107 | 108 | Incorrectly formatted filters will result in a 400 Bad Request Error. Filters that don’t match any data will return an empty array. 109 | 110 | ### Example 111 | 112 | ```vue 113 | 134 | ``` 135 | 136 | ### Common Filters 137 | 138 | - `featured:true` - all resources with a field `featured` that is set to `true`. 139 | - `featured:true+feature_image:null` - looks for featured posts which don’t have a feature image set by using `+` (and). 140 | - `tag:hash-noimg` - `tag` is an alias for `tags.slug` and `hash-noimg` would be the slug for an internal tag called `#NoImg`. This filter would allow us to find any post that has this internal tag. 141 | - `tags:[photo, video, audio]` - filters posts which have any one of the listed tags, `[]` (grouping) is more efficient than using or when querying the same field. 142 | - `primary_author:my-author` - `primary_author` is an alias for the first author, allowing for filtering based on the first author. 143 | - `published_at:>'2017-06-03 23:43:12'` - looks for posts published after a date, using a date string wrapped in single quotes and the `>` operator 144 | 145 | ## JavaScript SDK 146 | 147 | A collection of packages for common API usecases 148 | 149 | ### Helpers 150 | 151 | - Package: `@tryghost/helpers` 152 | - Builds: CJS, ES, UMD 153 | The shared helpers are designed for performing data formatting tasks, usually when creating custom frontends. 154 | 155 | #### Tags 156 | 157 | Filters and outputs tags. By default, the helper will output a comma separated list of tag names, excluding any internal tags. 158 | 159 | ```ts 160 | import { tags } from '@tryghost/helpers'; 161 | 162 | const posts = await this.$ghost.posts.browse({ 163 | filter: 'tag:fiction+tag:-fables', 164 | }); 165 | 166 | // Outputs e.g. Posted in: New Things, Releases, Features. 167 | posts.forEach((post) => { 168 | tags(post, { prefix: 'Posted in: ', suffix: '.' }); 169 | }); 170 | ``` 171 | 172 | The first argument must be a post object, or any object that has a `tags` array. 173 | 174 | ##### Options 175 | 176 | The tag helper supports multiple options so that you can control exactly what is output, without having to write any logic. 177 | 178 | - `limit` {integer} - limits the number of tags to be returned 179 | - `from` {integer, default:1} - index of the tag to start iterating from 180 | - `to` {integer} - index of the last tag to iterate over 181 | - `separator` {string, default:","} - string used between each tag 182 | - `prefix` {string} - string to output before each tag 183 | - `suffix` {string} - string to output after each tag 184 | - `visibility` {string, default:“public”} - change to “all” to include internal tags 185 | - `fallback` {object} - a fallback tag to output if there are none 186 | - `fn` {function} - function to call on each tag, default returns tag.name 187 | Reading 188 | 189 | #### Reading Time 190 | 191 | Calculates the estimated reading time based on the HTML for a post & available images. 192 | 193 | ```ts 194 | import { readingTime } from '@tryghost/helpers'; 195 | 196 | const posts = await this.$ghost.posts.browse(); 197 | 198 | // Outputs e.g. A 5 minute read. 199 | posts.forEach((post) => { 200 | readingTime(post, { minute: 'A 1 minute read.', minutes: 'A % minute read.' }); 201 | }); 202 | ``` 203 | 204 | The first argument must be a post object, or any object that has an `html` string. If a `feature_image` is present, this is taken into account. 205 | 206 | ##### Options 207 | 208 | The output of the reading time helper can be customised through format strings. 209 | 210 | - `minute` {string, default:“1 min read”} - format for reading times <= 1 minute 211 | - `minutes` {string, default:"% min read"} - format for reading times > 1 minute 212 | 213 | ### String 214 | 215 | - Package: `@tryghost/string` 216 | - Builds: CJS 217 | 218 | Utilities for processing strings. 219 | 220 | #### Slugify 221 | 222 | The function Ghost uses to turn a post title or tag name into a slug for use in URLs. 223 | 224 | ```ts 225 | const { slugify } = require('@tryghost/string'); 226 | const slug = slugify('你好 👋!'); // slug === "ni-hao" 227 | ``` 228 | 229 | The first argument is the string to transform. The second argument is an optional options object. 230 | 231 | ##### Options 232 | 233 | The output can be customised by passing options 234 | 235 | - `requiredChangesOnly` {boolean, default:false} - don’t perform optional cleanup, e.g. removing extra dashes 236 | -------------------------------------------------------------------------------- /docs/content/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Nuxt Ghost", 3 | "url": "https://nuxt-ghost.vercel.app/", 4 | "logo": { 5 | "light": "/logo-light.svg", 6 | "dark": "/logo-dark.svg" 7 | }, 8 | "github": "Gomah/nuxt-ghost", 9 | "twitter": "@gomah", 10 | "defaultBranch": "master" 11 | } 12 | -------------------------------------------------------------------------------- /docs/nuxt.config.js: -------------------------------------------------------------------------------- 1 | import theme from '@nuxt/content-theme-docs'; 2 | 3 | export default theme({ 4 | docs: { 5 | primaryColor: '#828486', 6 | }, 7 | }); 8 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-ghost-docs", 3 | "version": "1.0.12", 4 | "description": "Docs for nuxt-ghost", 5 | "private": true, 6 | "author": { 7 | "name": "Gomah " 8 | }, 9 | "scripts": { 10 | "dev": "nuxt", 11 | "start": "nuxt start", 12 | "generate": "nuxt generate" 13 | }, 14 | "dependencies": { 15 | "@nuxt/content-theme-docs": "^0.9.0", 16 | "nuxt": "^2.14.12" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /docs/static/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gomah/nuxt-ghost/4ed4b4f26796c96a624bfb4398620ed86cca9565/docs/static/icon.png -------------------------------------------------------------------------------- /docs/static/logo-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ghost Logo Dark 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/static/logo-light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ghost Logo Light 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/static/preview-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gomah/nuxt-ghost/4ed4b4f26796c96a624bfb4398620ed86cca9565/docs/static/preview-dark.png -------------------------------------------------------------------------------- /docs/static/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gomah/nuxt-ghost/4ed4b4f26796c96a624bfb4398620ed86cca9565/docs/static/preview.png -------------------------------------------------------------------------------- /docs/static/sw.js: -------------------------------------------------------------------------------- 1 | // THIS FILE SHOULD NOT BE VERSION CONTROLLED 2 | 3 | // https://github.com/NekR/self-destroying-sw 4 | 5 | self.addEventListener('install', function (e) { 6 | self.skipWaiting() 7 | }) 8 | 9 | self.addEventListener('activate', function (e) { 10 | self.registration.unregister() 11 | .then(function () { 12 | return self.clients.matchAll() 13 | }) 14 | .then(function (clients) { 15 | clients.forEach(client => client.navigate(client.url)) 16 | }) 17 | }) 18 | -------------------------------------------------------------------------------- /example/components/card.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 46 | -------------------------------------------------------------------------------- /example/components/navbar.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 40 | -------------------------------------------------------------------------------- /example/layouts/default.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 17 | -------------------------------------------------------------------------------- /example/modules/generate.js: -------------------------------------------------------------------------------- 1 | import { GhostContentAPI } from '../../lib/module'; 2 | 3 | export default async function (ctx) { 4 | const config = { 5 | blogPrefix: '', 6 | tagPrefix: 'tag', 7 | perPage: 3, 8 | }; 9 | 10 | this.nuxt.hook('generate:before', async (nuxt, generateOptions, ...oi) => { 11 | const $ghost = new GhostContentAPI({ 12 | ...nuxt.options.ghost, 13 | }); 14 | 15 | const [posts, tags] = await Promise.all([ 16 | $ghost.posts.browse({ 17 | limit: 'all', 18 | }), 19 | $ghost.tags.browse({ order: 'slug ASC', limit: 'all', include: 'count.posts' }), 20 | ]); 21 | 22 | // Post routes 23 | const postsRoutes = posts.map((post) => `${config.blogPrefix}/${post.slug}`); 24 | 25 | // Blog routes 26 | const blogPagesRoutes = []; 27 | const totalPages = Math.ceil(posts.length / config.perPage); 28 | 29 | if (totalPages > 1) { 30 | for (let page = 2; page <= totalPages; page += 1) { 31 | const route = `${config.blogPrefix}/page/${page}`; 32 | blogPagesRoutes.push(route); 33 | } 34 | } 35 | 36 | // Tag routes 37 | const tagRoutes = tags.reduce((arr, tag) => { 38 | const tagRoute = `${config.blogPrefix}${config.tagPrefix}/${tag.slug}`; 39 | arr.push(tagRoute); 40 | 41 | const maxPage = Math.ceil(tag.count.posts / config.perPage); 42 | 43 | if (maxPage > 1) { 44 | for (let page = 2; page <= maxPage; page += 1) { 45 | const route = `${config.blogPrefix}${config.tagPrefix}/${tag.slug}/page/${page}`; 46 | arr.push(route); 47 | } 48 | } 49 | 50 | return arr; 51 | }, []); 52 | 53 | const extraRoutes = [...postsRoutes, ...blogPagesRoutes, ...tagRoutes]; 54 | 55 | generateOptions.routes = generateOptions.routes 56 | ? generateOptions.routes.concat(extraRoutes) 57 | : extraRoutes; 58 | 59 | // Add to the sitemap 60 | if (nuxt.sitemap) { 61 | Object.assign(nuxt.sitemap, { 62 | routes: [...(nuxt.sitemap.routes && [...nuxt.sitemap.routes]), ...extraRoutes], 63 | }); 64 | } 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /example/nuxt.config.js: -------------------------------------------------------------------------------- 1 | const resolve = require('path').resolve; 2 | 3 | module.exports = { 4 | rootDir: resolve(__dirname, '../'), 5 | srcDir: __dirname, 6 | render: { 7 | resourceHints: false, 8 | }, 9 | target: 'static', 10 | buildModules: [ 11 | [ 12 | '@nuxt/typescript-build', 13 | { 14 | typeCheck: false, 15 | ignoreNotFoundWarnings: true, 16 | }, 17 | ], 18 | ], 19 | modules: ['../lib/module', './modules/generate', 'nuxt-buefy'], 20 | ghost: { 21 | url: 'https://demo.ghost.io', 22 | key: '22444f78447824223cefc48062', 23 | version: 'v4', 24 | }, 25 | dev: process.env.NODE_ENV !== 'test' && process.env.NODE_ENV === 'production', 26 | }; 27 | -------------------------------------------------------------------------------- /example/pages/_slug.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 44 | -------------------------------------------------------------------------------- /example/pages/index.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 78 | -------------------------------------------------------------------------------- /example/pages/page/_page.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /example/pages/tag/_tag.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 83 | -------------------------------------------------------------------------------- /example/pages/tag/_tag/page/_page.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /example/static/_redirects: -------------------------------------------------------------------------------- 1 | /* /200.html 200 2 | -------------------------------------------------------------------------------- /example/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | 3 | export const state = () => ({ 4 | tags: [], 5 | }); 6 | 7 | export const mutations = { 8 | SET_TAGS(state, tags) { 9 | Vue.set(state, 'tags', tags); 10 | }, 11 | }; 12 | 13 | export const actions = { 14 | async nuxtServerInit({ commit }) { 15 | const tags = await this.$ghost.tags.browse({ order: 'slug ASC', include: 'count.posts' }); 16 | commit('SET_TAGS', tags); 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /husky.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | hooks: { 3 | 'commit-msg': 'commitlint -E HUSKY_GIT_PARAMS', 4 | 'pre-commit': 'yarn test', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testEnvironment: 'node', 3 | collectCoverage: true, 4 | collectCoverageFrom: ['lib/**/*.js', '!lib/plugin.js'], 5 | moduleNameMapper: { 6 | '^~/(.*)$': '/lib/$1', 7 | '^~~$': '', 8 | '^@@$': '', 9 | '^@/(.*)$': '/lib/$1', 10 | }, 11 | transform: { 12 | '^.+\\.js$': 'babel-jest', 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /lib/module.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import GhostContentAPI from '@tryghost/content-api'; 3 | 4 | function ghostModule(_moduleOptions = {}) { 5 | const { ghost = {} } = this.options; 6 | 7 | // Combine options 8 | const moduleOptions = { 9 | version: 'v4', 10 | ...ghost, 11 | ..._moduleOptions, 12 | }; 13 | 14 | if (!moduleOptions.url || !moduleOptions.key) { 15 | throw new Error(`[Ghost Module] URL & Key must be provided.`); 16 | } 17 | 18 | // Add plugin 19 | this.addPlugin({ 20 | src: path.resolve(__dirname, 'plugin.js'), 21 | fileName: 'ghost.js', 22 | options: moduleOptions, 23 | }); 24 | } 25 | 26 | module.exports = ghostModule; 27 | module.exports.GhostContentAPI = GhostContentAPI; 28 | module.exports.meta = require('../package.json'); 29 | -------------------------------------------------------------------------------- /lib/plugin.js: -------------------------------------------------------------------------------- 1 | import GhostContentAPI from '@tryghost/content-api'; 2 | 3 | export default async (ctx, inject) => { 4 | const client = new GhostContentAPI({ 5 | url: '<%= options.url %>', 6 | key: '<%= options.key %>', 7 | version: '<%= options.version %>', 8 | }); 9 | 10 | // Inject ghost to the context as $ghost 11 | ctx.$ghost = client; 12 | inject('ghost', client); 13 | }; 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-ghost", 3 | "version": "2.1.5", 4 | "description": "Nuxt Ghost Module", 5 | "author": { 6 | "name": "Gomah " 7 | }, 8 | "keywords": [ 9 | "vue", 10 | "nuxt", 11 | "nuxtjs", 12 | "nuxt.js", 13 | "ghost", 14 | "ghost-content-api", 15 | "nuxt-ghost" 16 | ], 17 | "typings": "types/index.d.ts", 18 | "main": "lib/module.js", 19 | "files": [ 20 | "lib", 21 | "types/*.d.ts" 22 | ], 23 | "repository": "https://github.com/Gomah/nuxt-ghost", 24 | "homepage": "https://github.com/Gomah/nuxt-ghost", 25 | "publishConfig": { 26 | "access": "public" 27 | }, 28 | "license": "MIT", 29 | "scripts": { 30 | "dev": "nuxt example", 31 | "generate": "nuxt generate example", 32 | "test:system": "NODE_ENV=test jest --testRegex \"/test/system/(.+)\\.test\\.ts$\"", 33 | "prepare": "husky install", 34 | "release": "yarn test && standard-version && git push --follow-tags && npm publish", 35 | "test": "yarn test:lint && NODE_ENV=test jest", 36 | "test:lint": "eslint --ext .js, lib/module.js" 37 | }, 38 | "dependencies": { 39 | "@tryghost/content-api": "1.11.4", 40 | "@types/tryghost__content-api": "1.3.11" 41 | }, 42 | "devDependencies": { 43 | "@commitlint/cli": "^16.2.3", 44 | "@commitlint/config-conventional": "^16.2.1", 45 | "@nuxt/types": "^2.15.8", 46 | "@nuxt/typescript-build": "^2.1.0", 47 | "@nuxtjs/sitemap": "^2.4.0", 48 | "@types/jest": "^27.4.1", 49 | "@types/jsdom": "^16.2.14", 50 | "@types/node": "^17.0.25", 51 | "babel-eslint": "^10.1.0", 52 | "babel-jest": "^27.5.1", 53 | "eslint": "^8.14.0", 54 | "eslint-config-prettier": "^8.5.0", 55 | "eslint-plugin-prettier": "^4.0.0", 56 | "eslint-plugin-vue": "^8.7.1", 57 | "husky": "^7.0.4", 58 | "jest": "^27.5.1", 59 | "nuxt": "^2.15.8", 60 | "nuxt-buefy": "^0.4.22", 61 | "prettier": "^2.6.2", 62 | "request": "^2.88.2", 63 | "request-promise-native": "^1.0.9", 64 | "standard-version": "^9.3.2", 65 | "ts-loader": "8.3.0" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /test/system/ghost-module.test.js: -------------------------------------------------------------------------------- 1 | const config = require('../../example/nuxt.config.js'); 2 | const request = require('request-promise-native'); 3 | const { Nuxt, Builder } = require('nuxt'); 4 | 5 | const url = path => `http://localhost:3000${path}`; 6 | const get = path => request(url(path)); 7 | 8 | let nuxt; 9 | let addTemplate; 10 | 11 | const setupNuxt = async config => { 12 | nuxt = new Nuxt(config); 13 | 14 | // Spy addTemplate 15 | addTemplate = nuxt.moduleContainer.addTemplate = jest.fn(nuxt.moduleContainer.addTemplate); 16 | 17 | const build = new Builder(nuxt); 18 | 19 | await build.validatePages(); 20 | await build.generateRoutesAndFiles(); 21 | await nuxt.listen(3000); 22 | }; 23 | 24 | jest.setTimeout(10000); 25 | 26 | describe('Nuxt Ghost Module', () => { 27 | beforeAll(async () => { 28 | nuxt = new Nuxt(config); 29 | 30 | // Spy addTemplate 31 | addTemplate = nuxt.moduleContainer.addTemplate = jest.fn(nuxt.moduleContainer.addTemplate); 32 | 33 | await new Builder(nuxt).build(); 34 | await nuxt.listen(3000); 35 | }, 60000); 36 | 37 | afterAll(async () => { 38 | await nuxt.close(); 39 | }); 40 | 41 | test('SSR', async () => { 42 | const html = await get('/'); 43 | expect(html).toContain('Start here for a quick overview of everything you need to know'); 44 | }); 45 | 46 | test('CSR', async () => { 47 | const window = await nuxt.renderAndGetWindow(url('/')); 48 | 49 | window.onNuxtReady(() => { 50 | const html = window.document.body.innerHTML; 51 | expect(html).toContain('Start here for a quick overview of everything you need to know'); 52 | }); 53 | }); 54 | }); 55 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2018", 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "lib": [ 7 | "ESNext", 8 | "ESNext.AsyncIterable", 9 | "DOM" 10 | ], 11 | "esModuleInterop": true, 12 | "allowJs": true, 13 | "sourceMap": true, 14 | "strict": true, 15 | "noEmit": true, 16 | "baseUrl": ".", 17 | "paths": { 18 | "~/*": [ 19 | "./*" 20 | ], 21 | "@/*": [ 22 | "./*" 23 | ] 24 | }, 25 | "types": [ 26 | "@types/node", 27 | "@nuxt/types", 28 | "./types" 29 | ] 30 | }, 31 | "exclude": [ 32 | "node_modules" 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /types/index.d.ts: -------------------------------------------------------------------------------- 1 | import { GhostAPI } from '@tryghost/content-api'; 2 | import Vue from 'vue'; 3 | import './vuex'; 4 | 5 | declare module '@nuxt/vue-app' { 6 | interface Context { 7 | $ghost: GhostAPI; 8 | } 9 | 10 | interface NuxtAppOptions { 11 | $ghost: GhostAPI; 12 | } 13 | } 14 | 15 | // Nuxt 2.9+ 16 | declare module '@nuxt/types' { 17 | interface Context { 18 | $ghost: GhostAPI; 19 | } 20 | 21 | interface NuxtAppOptions { 22 | $ghost: GhostAPI; 23 | } 24 | } 25 | 26 | declare module 'vue/types/vue' { 27 | interface Vue { 28 | $ghost: GhostAPI; 29 | } 30 | } 31 | 32 | declare module 'vuex' { 33 | interface Store { 34 | $ghost: GhostAPI; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /types/vuex.d.ts: -------------------------------------------------------------------------------- 1 | import { GhostAPI } from '@tryghost/content-api'; 2 | 3 | declare module 'vuex/types/index' { 4 | interface Store { 5 | $ghost: GhostAPI; 6 | } 7 | } 8 | --------------------------------------------------------------------------------