docs: generate open graph images for all pages
This commit is contained in:
2
docs/.gitignore
vendored
Normal file
2
docs/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
static/images/*
|
||||
!static/images/.gitkeep
|
||||
BIN
docs/fonts/Inter-Black.otf
Normal file
BIN
docs/fonts/Inter-Black.otf
Normal file
Binary file not shown.
BIN
docs/fonts/Inter-BlackItalic.otf
Normal file
BIN
docs/fonts/Inter-BlackItalic.otf
Normal file
Binary file not shown.
BIN
docs/fonts/Inter-Bold.otf
Normal file
BIN
docs/fonts/Inter-Bold.otf
Normal file
Binary file not shown.
BIN
docs/fonts/Inter-BoldItalic.otf
Normal file
BIN
docs/fonts/Inter-BoldItalic.otf
Normal file
Binary file not shown.
BIN
docs/fonts/Inter-ExtraBold.otf
Normal file
BIN
docs/fonts/Inter-ExtraBold.otf
Normal file
Binary file not shown.
BIN
docs/fonts/Inter-ExtraBoldItalic.otf
Normal file
BIN
docs/fonts/Inter-ExtraBoldItalic.otf
Normal file
Binary file not shown.
BIN
docs/fonts/Inter-ExtraLight.otf
Normal file
BIN
docs/fonts/Inter-ExtraLight.otf
Normal file
Binary file not shown.
BIN
docs/fonts/Inter-ExtraLightItalic.otf
Normal file
BIN
docs/fonts/Inter-ExtraLightItalic.otf
Normal file
Binary file not shown.
BIN
docs/fonts/Inter-Italic.otf
Normal file
BIN
docs/fonts/Inter-Italic.otf
Normal file
Binary file not shown.
BIN
docs/fonts/Inter-Light.otf
Normal file
BIN
docs/fonts/Inter-Light.otf
Normal file
Binary file not shown.
BIN
docs/fonts/Inter-LightItalic.otf
Normal file
BIN
docs/fonts/Inter-LightItalic.otf
Normal file
Binary file not shown.
BIN
docs/fonts/Inter-Medium.otf
Normal file
BIN
docs/fonts/Inter-Medium.otf
Normal file
Binary file not shown.
BIN
docs/fonts/Inter-MediumItalic.otf
Normal file
BIN
docs/fonts/Inter-MediumItalic.otf
Normal file
Binary file not shown.
BIN
docs/fonts/Inter-Regular.otf
Normal file
BIN
docs/fonts/Inter-Regular.otf
Normal file
Binary file not shown.
BIN
docs/fonts/Inter-SemiBold.otf
Normal file
BIN
docs/fonts/Inter-SemiBold.otf
Normal file
Binary file not shown.
BIN
docs/fonts/Inter-SemiBoldItalic.otf
Normal file
BIN
docs/fonts/Inter-SemiBoldItalic.otf
Normal file
Binary file not shown.
BIN
docs/fonts/Inter-Thin.otf
Normal file
BIN
docs/fonts/Inter-Thin.otf
Normal file
Binary file not shown.
BIN
docs/fonts/Inter-ThinItalic.otf
Normal file
BIN
docs/fonts/Inter-ThinItalic.otf
Normal file
Binary file not shown.
BIN
docs/fonts/Inter-V.ttf
Normal file
BIN
docs/fonts/Inter-V.ttf
Normal file
Binary file not shown.
@@ -1,5 +1,45 @@
|
||||
const fs = require('fs')
|
||||
const { createCanvas, registerFont } = require('canvas')
|
||||
const path = require('path')
|
||||
const globby = require('globby')
|
||||
|
||||
registerFont('fonts/Inter-Regular.otf', { family: 'InterRegular' })
|
||||
registerFont('fonts/Inter-Medium.otf', { family: 'InterMedium' })
|
||||
|
||||
const wrapText = function (context, text, x, y, maxWidth, lineHeight) {
|
||||
const words = text.split(' ')
|
||||
let line = ''
|
||||
|
||||
for (let n = 0; n < words.length; n += 1) {
|
||||
const testLine = `${line + words[n]} `
|
||||
const metrics = context.measureText(testLine)
|
||||
const testWidth = metrics.width
|
||||
if (testWidth > maxWidth && n > 0) {
|
||||
context.fillText(line, x, y)
|
||||
line = `${words[n]} `
|
||||
y += lineHeight
|
||||
} else {
|
||||
line = testLine
|
||||
}
|
||||
}
|
||||
context.fillText(line, x, y)
|
||||
}
|
||||
|
||||
const calculateReadingTime = function (text) {
|
||||
const wordsPerMinute = 200
|
||||
const textLength = text.split(' ').length
|
||||
|
||||
if (textLength > 0) {
|
||||
const value = Math.ceil(textLength / wordsPerMinute)
|
||||
|
||||
if (value === 1) {
|
||||
return `${value} minute`
|
||||
}
|
||||
|
||||
return `${value} minutes`
|
||||
}
|
||||
}
|
||||
|
||||
// const TypeDoc = require('typedoc')
|
||||
|
||||
// const packages = globby.sync('../packages/*', { onlyDirectories: true })
|
||||
@@ -142,4 +182,67 @@ module.exports = function (api) {
|
||||
.set(`@tiptap/${name}`, path.resolve(`../packages/${name}/src/index.ts`))
|
||||
})
|
||||
})
|
||||
|
||||
// Generate OpenGraph images for all pages
|
||||
api.onCreateNode(options => {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
return null
|
||||
}
|
||||
|
||||
if (options?.internal?.typeName !== 'DocPage') {
|
||||
return null
|
||||
}
|
||||
|
||||
const imagePath = `static/images${options.path}`
|
||||
const imageFile = `static/images${options.path}og-image.png`
|
||||
|
||||
// console.log(`Found Post “${options.title}” in ${options.internal.origin} …`)
|
||||
|
||||
const width = 1200
|
||||
const height = 630
|
||||
|
||||
const border = 40
|
||||
|
||||
const canvas = createCanvas(width, height)
|
||||
const context = canvas.getContext('2d')
|
||||
|
||||
// background
|
||||
context.fillStyle = '#000000'
|
||||
context.fillRect(0, 0, width, height)
|
||||
|
||||
// project
|
||||
const project = 'tiptap documentation'
|
||||
context.textBaseline = 'top'
|
||||
context.fillStyle = '#666666'
|
||||
context.font = '32pt InterRegular'
|
||||
context.fillText(project, border, border)
|
||||
|
||||
// title
|
||||
const { title } = options
|
||||
const lineHeight = 96
|
||||
context.textBaseline = 'top'
|
||||
context.fillStyle = '#ffffff'
|
||||
context.font = '58pt InterMedium'
|
||||
wrapText(context, title, border, border + 60 + border, width - border - border, lineHeight)
|
||||
|
||||
// reading time
|
||||
const readingTime = calculateReadingTime(options.content)
|
||||
context.textBaseline = 'bottom'
|
||||
context.fillStyle = '#666666'
|
||||
context.font = '32pt InterRegular'
|
||||
context.fillText(readingTime, border, height - border)
|
||||
|
||||
// store
|
||||
const buffer = canvas.toBuffer('image/png')
|
||||
|
||||
fs.mkdir(imagePath, { recursive: true }, error => {
|
||||
if (error) {
|
||||
throw error
|
||||
}
|
||||
|
||||
fs.writeFileSync(imageFile, buffer)
|
||||
|
||||
// console.log(`OpenGraph image generated (${imageFile}).`)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"@gridsome/transformer-json": "^0.2.1",
|
||||
"@gridsome/vue-remark": "^0.2.6",
|
||||
"@mvasilkov/outdent": "^1.0.4",
|
||||
"canvas": "^2.6.1",
|
||||
"collect.js": "^4.28.6",
|
||||
"d3": "^6.5.0",
|
||||
"globby": "^11.0.0",
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/*
|
||||
<static-query>
|
||||
query {
|
||||
packages: allPackage {
|
||||
@@ -34,8 +36,7 @@ query {
|
||||
}
|
||||
}
|
||||
</static-query>
|
||||
|
||||
<script>
|
||||
*/
|
||||
// import collect from 'collect.js'
|
||||
import { VueLive } from 'vue-live'
|
||||
import CustomLayout from './CustomLayout'
|
||||
|
||||
@@ -31,7 +31,7 @@ export default {
|
||||
},
|
||||
{
|
||||
property: 'og:image',
|
||||
content: 'https://next.tiptap.dev/og-image.png',
|
||||
content: this.getOpenGraphImage(),
|
||||
},
|
||||
/* Twitter */
|
||||
{
|
||||
@@ -44,7 +44,7 @@ export default {
|
||||
},
|
||||
{
|
||||
name: 'twitter:image',
|
||||
content: 'https://next.tiptap.dev/og-image.png',
|
||||
content: this.getOpenGraphImage(),
|
||||
},
|
||||
{
|
||||
name: 'twitter:site',
|
||||
@@ -53,6 +53,15 @@ export default {
|
||||
],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getOpenGraphImage() {
|
||||
const path = this.$route.path.replace(/\/$/, '')
|
||||
|
||||
return path === ''
|
||||
? 'https://next.tiptap.dev/og-image.png'
|
||||
: `/images${path}/og-image.png`
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
0
docs/static/images/.gitkeep
vendored
Normal file
0
docs/static/images/.gitkeep
vendored
Normal file
Reference in New Issue
Block a user