Compare commits
15 Commits
Author | SHA1 | Date |
---|---|---|
Matthias Kretschmann | c2914069da | |
Matthias Kretschmann | e259bd237e | |
Matthias Kretschmann | a036be8087 | |
dependabot[bot] | 83e2ae1daa | |
dependabot[bot] | 88f0481ed3 | |
dependabot[bot] | 094ec24f08 | |
Matthias Kretschmann | 8ab2e492f0 | |
Matthias Kretschmann | 475679419f | |
Matthias Kretschmann | b885ec26f0 | |
Matthias Kretschmann | 42f9f19f6b | |
Matthias Kretschmann | 035274ad07 | |
Matthias Kretschmann | 61d669235c | |
Matthias Kretschmann | 54dd077e8d | |
Matthias Kretschmann | fb8d6cfd17 | |
dependabot[bot] | 0fcca0c398 |
|
@ -10,6 +10,7 @@
|
|||
"env": {
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"es2020": true
|
||||
"es2020": true,
|
||||
"jest": true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
github: kremalicious
|
||||
patreon: kremalicious
|
||||
custom: ['https://kremalicious.com/thanks']
|
|
@ -18,25 +18,41 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
node: ['14']
|
||||
node: ['18', '20']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
cache: npm
|
||||
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
- run: npm run build
|
||||
|
||||
coverage:
|
||||
if: ${{ github.actor != 'dependabot[bot]' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
cache: npm
|
||||
- run: npm ci
|
||||
- uses: paambaati/codeclimate-action@v5.0.0
|
||||
env:
|
||||
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
||||
with:
|
||||
coverageCommand: npm test
|
||||
|
||||
publish:
|
||||
needs: test
|
||||
if: success() && startsWith(github.ref, 'refs/tags')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
node_modules
|
||||
/*.js
|
||||
coverage
|
|
@ -1,6 +1,6 @@
|
|||
node_modules
|
||||
src
|
||||
.babelrc
|
||||
test
|
||||
babel.config.json
|
||||
.editorconfig
|
||||
.eslintrc
|
||||
.travis.yml
|
||||
|
|
29
CHANGELOG.md
29
CHANGELOG.md
|
@ -4,10 +4,39 @@ All notable changes to this project will be documented in this file. Dates are d
|
|||
|
||||
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
||||
|
||||
#### [v1.1.0](https://github.com/kremalicious/gatsby-redirect-from/compare/v1.0.6...v1.1.0)
|
||||
|
||||
- refactor, more tests [`#444`](https://github.com/kremalicious/gatsby-redirect-from/pull/444)
|
||||
- Bump @babel/traverse from 7.23.0 to 7.23.2 [`#417`](https://github.com/kremalicious/gatsby-redirect-from/pull/417)
|
||||
- Bump postcss from 8.4.25 to 8.4.31 [`#413`](https://github.com/kremalicious/gatsby-redirect-from/pull/413)
|
||||
- Bump sharp from 0.32.1 to 0.32.6 [`#422`](https://github.com/kremalicious/gatsby-redirect-from/pull/422)
|
||||
- add unit test cases [`4756794`](https://github.com/kremalicious/gatsby-redirect-from/commit/475679419f284b6def8447daac64d34ce218c3da)
|
||||
- npm audit fix [`e259bd2`](https://github.com/kremalicious/gatsby-redirect-from/commit/e259bd237e6570c084e69878ad0e31cc82c91cc2)
|
||||
- test setup [`8ab2e49`](https://github.com/kremalicious/gatsby-redirect-from/commit/8ab2e492f0d79a39185686ddeca38d4b91d8727a)
|
||||
|
||||
#### [v1.0.6](https://github.com/kremalicious/gatsby-redirect-from/compare/v1.0.5...v1.0.6)
|
||||
|
||||
> 28 September 2023
|
||||
|
||||
- dependency updates, new package-lock [`61d6692`](https://github.com/kremalicious/gatsby-redirect-from/commit/61d669235c5387103be62384cd3f352710bae0f5)
|
||||
- Release 1.0.6 [`b885ec2`](https://github.com/kremalicious/gatsby-redirect-from/commit/b885ec26f096beccca491149bd7dd79316346ef6)
|
||||
- bump Node.js version in CI [`035274a`](https://github.com/kremalicious/gatsby-redirect-from/commit/035274ad07a2385b5bb86e45adf1fc8fdddfe12e)
|
||||
|
||||
#### [v1.0.5](https://github.com/kremalicious/gatsby-redirect-from/compare/v1.0.4...v1.0.5)
|
||||
|
||||
> 17 August 2023
|
||||
|
||||
- Bump release-it from 16.0.0 to 16.1.0 [`#389`](https://github.com/kremalicious/gatsby-redirect-from/pull/389)
|
||||
- dependency updates [`fb8d6cf`](https://github.com/kremalicious/gatsby-redirect-from/commit/fb8d6cfd1753ec793698b9302eaf2f113330c1a9)
|
||||
- Release 1.0.5 [`54dd077`](https://github.com/kremalicious/gatsby-redirect-from/commit/54dd077e8d4ffd791a914bc0f6c212839ca70c10)
|
||||
|
||||
#### [v1.0.4](https://github.com/kremalicious/gatsby-redirect-from/compare/v1.0.3...v1.0.4)
|
||||
|
||||
> 8 July 2023
|
||||
|
||||
- Bump eslint from 8.38.0 to 8.44.0 [`#387`](https://github.com/kremalicious/gatsby-redirect-from/pull/387)
|
||||
- package updates, remove eslint-plugin-prettier [`1bec87e`](https://github.com/kremalicious/gatsby-redirect-from/commit/1bec87e1b70b28011d8abb5b3f19dbf45dc31a3a)
|
||||
- Release 1.0.4 [`7703505`](https://github.com/kremalicious/gatsby-redirect-from/commit/770350593e3dbae1532f9b59cdcd3247450ba47b)
|
||||
|
||||
#### [v1.0.3](https://github.com/kremalicious/gatsby-redirect-from/compare/v1.0.2...v1.0.3)
|
||||
|
||||
|
|
15
README.md
15
README.md
|
@ -5,6 +5,7 @@
|
|||
[![npm package](https://img.shields.io/npm/v/gatsby-redirect-from.svg)](https://www.npmjs.com/package/gatsby-redirect-from)
|
||||
[![Build Status](https://github.com/kremalicious/gatsby-redirect-from/workflows/CI/badge.svg)](https://github.com/kremalicious/gatsby-redirect-from/actions)
|
||||
[![Maintainability](https://api.codeclimate.com/v1/badges/9643b2a038a7d338a73a/maintainability)](https://codeclimate.com/github/kremalicious/gatsby-redirect-from/maintainability)
|
||||
[![Test Coverage](https://api.codeclimate.com/v1/badges/9643b2a038a7d338a73a/test_coverage)](https://codeclimate.com/github/kremalicious/gatsby-redirect-from/test_coverage)
|
||||
|
||||
> 🎯 Set redirect urls in your YAML frontmatter within your [Gatsby](https://www.gatsbyjs.org) site's Markdown files. Mimics the behavior of [jekyll-redirect-from](https://github.com/jekyll/jekyll-redirect-from).
|
||||
> https://kremalicious.com/gatsby-redirect-from/
|
||||
|
@ -23,6 +24,7 @@ By combining this plugin with [gatsby-plugin-meta-redirect](https://github.com/g
|
|||
- [Documentation](#documentation)
|
||||
- [Plugin Development](#plugin-development)
|
||||
- [Changelog](#changelog)
|
||||
- [Sponsorship](#sponsorship)
|
||||
- [License](#license)
|
||||
|
||||
---
|
||||
|
@ -65,7 +67,6 @@ redirect_from:
|
|||
- /2008/04/aperture-file-types/
|
||||
# note: trailing slashes are required
|
||||
---
|
||||
|
||||
```
|
||||
|
||||
## [Documentation](https://kremalicious.com/gatsby-redirect-from/)
|
||||
|
@ -92,6 +93,12 @@ npm run release
|
|||
|
||||
See [CHANGELOG.md](CHANGELOG.md).
|
||||
|
||||
## Sponsorship
|
||||
|
||||
[![](https://img.shields.io/static/v1?label=Say%20Thanks%20With%20Web3&labelColor=%2343a699&message=%E2%9D%A4&logo=Ethereum&color=%23fe8e86&style=for-the-badge)](https://kremalicious.com/thanks)
|
||||
|
||||
[![](https://img.shields.io/static/v1?label=Say%20Thanks%20With%20GitHub&labelColor=%2343a699&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86&style=for-the-badge)](https://github.com/sponsors/kremalicious)
|
||||
|
||||
## License
|
||||
|
||||
The MIT License
|
||||
|
@ -107,9 +114,3 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
|||
---
|
||||
|
||||
Made with ♥ by [Matthias Kretschmann](https://matthiaskretschmann.com) ([@kremalicious](https://github.com/kremalicious))
|
||||
|
||||
Say thanks with BTC:
|
||||
`35UUssHexVK48jbiSgTxa4QihEoCqrwCTG`
|
||||
|
||||
Say thanks with ETH:
|
||||
`0x04354F554536DA108726829207958d3E277f0210`
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"presets": ["@babel/preset-env"]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
31
package.json
31
package.json
|
@ -1,16 +1,17 @@
|
|||
{
|
||||
"name": "gatsby-redirect-from",
|
||||
"version": "1.0.4",
|
||||
"version": "1.1.0",
|
||||
"author": "Matthias Kretschmann <m@kretschmann.io>",
|
||||
"description": "Set redirect urls in your YAML frontmatter within your Gatsby site's Markdown files. Mimics the behavior of jekyll-redirect-from.",
|
||||
"homepage": "https://kremalicious.com/gatsby-redirect-from/",
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "cross-env NODE_ENV=production babel src --out-dir . --ignore __tests__",
|
||||
"start": "babel -w src --out-dir . --ignore __tests__",
|
||||
"test": "eslint src/**/*.js",
|
||||
"format": "prettier --write 'src/**/*.{js,jsx}'",
|
||||
"build": "cross-env NODE_ENV=production babel src --out-dir .",
|
||||
"start": "babel -w src --out-dir .",
|
||||
"test": "npm run lint && jest --coverage --config ./test/jest.config.json",
|
||||
"lint": "eslint ./{src,test}/**/*.js",
|
||||
"format": "prettier --write '{src,test}/**/*.{js,jsx}'",
|
||||
"release": "release-it --non-interactive",
|
||||
"changelog": "auto-changelog -p",
|
||||
"prepublishOnly": "npm run build"
|
||||
|
@ -19,24 +20,24 @@
|
|||
"maintained node versions"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.22.6",
|
||||
"@babel/core": "^7.22.8",
|
||||
"@babel/helper-define-map": "^7.18.6",
|
||||
"@babel/preset-env": "^7.22.7",
|
||||
"@babel/cli": "^7.24.1",
|
||||
"@babel/core": "^7.24.4",
|
||||
"@babel/preset-env": "^7.24.4",
|
||||
"auto-changelog": "^2.4.0",
|
||||
"chalk": "^5.3.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^8.44.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"prettier": "^3.0.0",
|
||||
"release-it": "^16.0.0"
|
||||
"eslint": "^8.50.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"jest": "^29.7.0",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"prettier": "^3.2.5",
|
||||
"release-it": "^17.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"gatsby": "^4.0.0 || ^5.0.0",
|
||||
"gatsby-plugin-meta-redirect": ">=1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
"node": ">=18"
|
||||
},
|
||||
"repository": "github:kremalicious/gatsby-redirect-from",
|
||||
"bugs": {
|
||||
|
|
|
@ -1,67 +1,100 @@
|
|||
import chalk from 'chalk'
|
||||
exports.createSchemaCustomization = ({ actions }) => {
|
||||
const { createTypes } = actions
|
||||
|
||||
export function createPages({ graphql, actions }, pluginOptions) {
|
||||
// Define the type definitions for the `MarkdownRemark` node
|
||||
const typeDefs = `
|
||||
type MarkdownRemark implements Node {
|
||||
fields: MarkdownRemarkFields
|
||||
frontmatter: MarkdownRemarkFrontmatter
|
||||
}
|
||||
|
||||
type MarkdownRemarkFields {
|
||||
slug: String
|
||||
}
|
||||
|
||||
type MarkdownRemarkFrontmatter {
|
||||
slug: String
|
||||
}
|
||||
`
|
||||
|
||||
// Create the type definitions
|
||||
createTypes(typeDefs)
|
||||
}
|
||||
|
||||
export async function createPages({ graphql, actions }, pluginOptions) {
|
||||
const { createRedirect } = actions
|
||||
|
||||
const markdownQuery = pluginOptions.query || 'allMarkdownRemark'
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve(
|
||||
graphql(
|
||||
`
|
||||
{
|
||||
q: ${markdownQuery}(
|
||||
filter: { frontmatter: { redirect_from: { ne: null } } }
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
fields {
|
||||
slug
|
||||
}
|
||||
frontmatter {
|
||||
redirect_from
|
||||
}
|
||||
}
|
||||
try {
|
||||
const { data } = await graphql(`
|
||||
{
|
||||
q: ${markdownQuery}(filter: { frontmatter: { redirect_from: { ne: null } } }) {
|
||||
edges {
|
||||
node {
|
||||
fields {
|
||||
slug
|
||||
}
|
||||
frontmatter {
|
||||
slug
|
||||
redirect_from
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
).then((result) => {
|
||||
if (result.errors) {
|
||||
console.log(result.errors) // eslint-disable-line no-console
|
||||
reject(result.errors)
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
const allPosts = result.data.q.edges
|
||||
const allPosts = data?.q?.edges
|
||||
|
||||
const redirects = []
|
||||
if (!allPosts || allPosts.length === 0) {
|
||||
console.log(
|
||||
'%c %s %c %s',
|
||||
'color:orange',
|
||||
'warning',
|
||||
'color:none',
|
||||
'no posts with redirect_from found'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// For all posts with redirect_from frontmatter,
|
||||
// extract all values and push to redirects array
|
||||
allPosts.forEach((post) => {
|
||||
redirects.push({
|
||||
from: post.node.frontmatter.redirect_from,
|
||||
to: post.node.fields.slug
|
||||
})
|
||||
})
|
||||
const redirects = []
|
||||
|
||||
// Create redirects from the just constructed array
|
||||
redirects.forEach(({ from, to }) => {
|
||||
// iterate through all `from` array items
|
||||
from.forEach((from) => {
|
||||
createRedirect({
|
||||
fromPath: from,
|
||||
toPath: to,
|
||||
isPermanent: true,
|
||||
redirectInBrowser: true
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
resolve(
|
||||
console.log(`${chalk.green('success')} create redirects`) // eslint-disable-line no-console
|
||||
allPosts.forEach(({ node }) => {
|
||||
let _slug
|
||||
const { redirect_from, slug } = node.frontmatter
|
||||
if (!slug) _slug = node.fields?.slug
|
||||
if (!_slug) {
|
||||
console.log(
|
||||
'%c %s %c %s',
|
||||
'color:orange',
|
||||
'warning',
|
||||
'color:none',
|
||||
'no slug found in frontmatter or fields'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
redirect_from.forEach((from) => {
|
||||
redirects.push({ from, to: _slug })
|
||||
})
|
||||
})
|
||||
|
||||
redirects.forEach(({ from, to }) => {
|
||||
createRedirect({
|
||||
fromPath: from,
|
||||
toPath: to,
|
||||
isPermanent: true,
|
||||
redirectInBrowser: true
|
||||
})
|
||||
})
|
||||
console.log(
|
||||
'%c %s %c %s',
|
||||
'color:green',
|
||||
'success',
|
||||
'color:none',
|
||||
`created ${redirects.length} redirects`
|
||||
)
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error.message)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
* @jest-environment jsdom
|
||||
*/
|
||||
import { graphql } from 'gatsby'
|
||||
import { createPages } from '../src/gatsby-node.js'
|
||||
|
||||
jest.mock('gatsby', () => ({
|
||||
graphql: jest.fn(),
|
||||
actions: { createRedirect: jest.fn() }
|
||||
}))
|
||||
|
||||
describe('createPages', () => {
|
||||
let pluginOptions
|
||||
let actions
|
||||
let consoleLogSpy
|
||||
|
||||
const markdownQuery = 'allMarkdownRemark'
|
||||
const edges = [
|
||||
{
|
||||
node: {
|
||||
fields: { slug: '/post-1' },
|
||||
frontmatter: { redirect_from: ['/old-url-1', '/old-url-2'] }
|
||||
}
|
||||
},
|
||||
{
|
||||
node: {
|
||||
fields: { slug: '/post-2' },
|
||||
frontmatter: { redirect_from: ['/old-url-3'] }
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
beforeEach(() => {
|
||||
actions = { createRedirect: jest.fn() }
|
||||
pluginOptions = { query: 'allMarkdownRemark' }
|
||||
consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(() => {})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks()
|
||||
consoleLogSpy.mockRestore()
|
||||
})
|
||||
|
||||
it('should create redirects for each post with a redirect_from field', async () => {
|
||||
const data = { q: { edges } }
|
||||
graphql.mockReturnValueOnce(Promise.resolve({ data }))
|
||||
const createRedirectSpy = jest.spyOn(actions, 'createRedirect')
|
||||
|
||||
await createPages({ graphql, actions }, { query: markdownQuery })
|
||||
|
||||
expect(createRedirectSpy).toHaveBeenCalledTimes(3)
|
||||
expect(createRedirectSpy).toHaveBeenCalledWith({
|
||||
fromPath: '/old-url-1',
|
||||
toPath: '/post-1',
|
||||
isPermanent: true,
|
||||
redirectInBrowser: true
|
||||
})
|
||||
expect(createRedirectSpy).toHaveBeenCalledWith({
|
||||
fromPath: '/old-url-2',
|
||||
toPath: '/post-1',
|
||||
isPermanent: true,
|
||||
redirectInBrowser: true
|
||||
})
|
||||
expect(createRedirectSpy).toHaveBeenCalledWith({
|
||||
fromPath: '/old-url-3',
|
||||
toPath: '/post-2',
|
||||
isPermanent: true,
|
||||
redirectInBrowser: true
|
||||
})
|
||||
|
||||
createRedirectSpy.mockRestore()
|
||||
})
|
||||
|
||||
it('should use pluginOptions.query when defined', async () => {
|
||||
const customQuery = 'someCustomQuery'
|
||||
pluginOptions.query = customQuery
|
||||
|
||||
graphql.mockImplementation((queryString) => {
|
||||
expect(queryString).toContain(customQuery)
|
||||
return Promise.resolve({ data: { q: { edges: [] } } })
|
||||
})
|
||||
|
||||
await createPages({ graphql, actions }, pluginOptions)
|
||||
})
|
||||
|
||||
it('should default to allMarkdownRemark when pluginOptions.query is undefined', async () => {
|
||||
pluginOptions.query = undefined
|
||||
|
||||
graphql.mockImplementation((queryString) => {
|
||||
expect(queryString).toContain('allMarkdownRemark')
|
||||
return Promise.resolve({ data: { q: { edges: [] } } })
|
||||
})
|
||||
|
||||
await createPages({ graphql, actions }, pluginOptions)
|
||||
})
|
||||
|
||||
it('should log a success message when redirects are created', async () => {
|
||||
const data = { q: { edges } }
|
||||
graphql.mockReturnValueOnce(Promise.resolve({ data }))
|
||||
const createRedirectSpy = jest.spyOn(actions, 'createRedirect')
|
||||
|
||||
await createPages({ graphql, actions }, { query: markdownQuery })
|
||||
|
||||
expect(createRedirectSpy).toHaveBeenCalledTimes(3)
|
||||
expect(console.log).toHaveBeenCalledWith(
|
||||
'%c %s %c %s',
|
||||
'color:green',
|
||||
'success',
|
||||
'color:none',
|
||||
'created 3 redirects'
|
||||
)
|
||||
})
|
||||
|
||||
it('should log an error message when an error occurs', async () => {
|
||||
const error = new Error('GraphQL query failed')
|
||||
graphql.mockImplementationOnce(() => {
|
||||
throw error
|
||||
})
|
||||
|
||||
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
|
||||
|
||||
try {
|
||||
await createPages({ graphql, actions }, pluginOptions)
|
||||
} catch (error) {
|
||||
expect(console.error).toHaveBeenCalledWith('GraphQL query failed')
|
||||
}
|
||||
|
||||
consoleSpy.mockRestore()
|
||||
})
|
||||
})
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"rootDir": "../",
|
||||
"coverageDirectory": "<rootDir>/coverage/"
|
||||
}
|
Loading…
Reference in New Issue