diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..e44cd35 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +.git +*Dockerfile* +npm-debug.log +node_modules +.env \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..701e2ac --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,29 @@ +# Automate, customize, and execute your software development workflows right in your repository with GitHub Actions. +# Documentation: https://docs.github.com/en/actions + +name: deploy + +on: + workflow_dispatch: + push: + branches: + - main + - development + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - name: Trigger build + shell: bash + run: | + curl \ + --fail \ + --silent \ + --request POST \ + --form token=${{ secrets.CI_TOKEN }} \ + --form ref=main \ + --form 'variables[GITHUB_COMMIT_REF_NAME]'=$GITHUB_REF_NAME \ + ${{ secrets.CI_WEBHOOK_URL }} \ + &> /dev/null \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 05a458b..2ecd726 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,28 @@ FROM node:20-alpine AS base +ARG BASE_PATH + +ARG NEXT_PUBLIC_ENVIRONMENT +ARG NEXT_PUBLIC_DOMAIN +ARG NEXT_PUBLIC_BASE_PATH +ARG NEXT_PUBLIC_REPO +ARG NEXT_PUBLIC_REPO_BASE +ARG NEXT_PUBLIC_DEMO_URL +ARG NEXT_PUBLIC_DEMO_URL_PRO + +ARG NEXT_PUBLIC_DOCSEARCH_HOST +ARG NEXT_PUBLIC_DOCSEARCH_PORT +ARG NEXT_PUBLIC_DOCSEARCH_PROTOCOL +ARG NEXT_PUBLIC_DOCSEARCH_INDEX +ARG NEXT_PUBLIC_DOCSEARCH_API_KEY + +ARG NEXT_PUBLIC_GTM_ID +ARG NEXT_PUBLIC_COOKIEBOT_ID + +ARG NEXT_TELEMETRY_DISABLED + +RUN apk add --no-cache curl + # 1. Install dependencies only when needed FROM base AS deps # Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. @@ -57,4 +80,4 @@ EXPOSE 3000 ENV PORT 3000 ENV HOSTNAME 0.0.0.0 -CMD ["node", "server.js"] \ No newline at end of file +CMD ["node", "server.js"] diff --git a/docsearch.config.json b/docsearch.config.json index 9991395..66d3f84 100644 --- a/docsearch.config.json +++ b/docsearch.config.json @@ -1,19 +1,15 @@ { "index_name": "tiptap_v2", - "start_urls": [ - "https://tiptap.dev/docs" - ], - "sitemap_urls": [ - "https://tiptap.dev/docs/sitemap.xml" - ], + "start_urls": ["https://tiptap.dev/docs"], + "sitemap_urls": ["https://tiptap.dev/docs/sitemap.xml"], "sitemap_alternate_links": true, "stop_urls": [], "selectors": { "default": { "lvl0": { - "selector": "a[data-breadcrumb=\"0\"]", - "global": true, - "default_value": "All docs" + "selector": "a[data-breadcrumb=\"0\"]", + "global": true, + "default_value": "All docs" }, "lvl1": "h1", "lvl2": "h2", @@ -21,21 +17,17 @@ "lvl4": "h4", "lvl5": "h5", "lvl6": "h6", - "text": "p, li, pre, td" + "text": "p, li, pre, td", + "code": { + "selector": "pre > code", + "global": true + } } }, "strip_chars": " .,;:#", "custom_settings": { "separatorsToIndex": "_", - "attributesForFaceting": [ - "type", - "lang" - ], - "attributesToRetrieve": [ - "hierarchy", - "text", - "anchor", - "url" - ] + "attributesForFaceting": ["type", "lang"], + "attributesToRetrieve": ["hierarchy", "text", "anchor", "url"] } } diff --git a/next.config.mjs b/next.config.mjs index 7665915..0739956 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,16 +1,15 @@ -import createMdx from "@next/mdx"; -import remarkFrontmatter from "remark-frontmatter"; -import remarkMdxFrontmatter from "remark-mdx-frontmatter"; -import rehypeHighlight from "rehype-highlight"; -import remarkGfm from "remark-gfm"; +import createMdx from '@next/mdx' +import remarkFrontmatter from 'remark-frontmatter' +import remarkMdxFrontmatter from 'remark-mdx-frontmatter' +import rehypeHighlight from 'rehype-highlight' +import remarkGfm from 'remark-gfm' /** @type {import('next').NextConfig} */ const nextConfig = { + output: 'standalone', webpack(config) { // Grab the existing rule that handles SVG imports - const fileLoaderRule = config.module.rules.find((rule) => - rule.test?.test?.(".svg"), - ); + const fileLoaderRule = config.module.rules.find((rule) => rule.test?.test?.('.svg')) config.module.rules.push( // Reapply the existing rule, but only for svg imports ending in ?url @@ -24,18 +23,18 @@ const nextConfig = { test: /\.svg$/i, issuer: fileLoaderRule.issuer, resourceQuery: { not: [...fileLoaderRule.resourceQuery.not, /url/] }, // exclude if *.svg?url - use: ["@svgr/webpack"], + use: ['@svgr/webpack'], }, - ); + ) // Modify the file loader rule to ignore *.svg, since we have it handled now. - fileLoaderRule.exclude = /\.svg$/i; + fileLoaderRule.exclude = /\.svg$/i - return config; + return config }, - pageExtensions: ["js", "jsx", "mdx", "ts", "tsx"], + pageExtensions: ['js', 'jsx', 'mdx', 'ts', 'tsx'], images: { unoptimized: true }, - basePath: process.env.BASE_PATH ?? "", + basePath: process.env.BASE_PATH ?? '', async redirects() { return [ { @@ -45,13 +44,13 @@ const nextConfig = { }, ] }, -}; +} const withMDX = createMdx({ options: { remarkPlugins: [remarkFrontmatter, remarkMdxFrontmatter, remarkGfm], rehypePlugins: [rehypeHighlight], }, -}); +}) -export default withMDX(nextConfig); +export default withMDX(nextConfig) diff --git a/package-lock.json b/package-lock.json index 2e085a7..5c64d33 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "tiptap-docs", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "tiptap-docs", - "version": "1.0.0", + "version": "1.0.1", "dependencies": { "@codesandbox/sandpack-react": "^2.13.5", "@codesandbox/sandpack-themes": "^2.0.21", @@ -32,6 +32,7 @@ "remark-frontmatter": "^5.0.0", "remark-gfm": "^4.0.0", "remark-mdx-frontmatter": "^4.0.0", + "sharp": "^0.33.4", "short-uuid": "^4.2.2", "slugify": "^1.6.6", "sonner": "^1.4.3", @@ -3052,6 +3053,15 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@emnapi/runtime": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", + "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -3166,6 +3176,437 @@ "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.4.tgz", + "integrity": "sha512-p0suNqXufJs9t3RqLBO6vvrgr5OhgbWp76s5gTRvdmxmuv9E1rcaqGUsl3l4mKVmXPkTkTErXediAui4x+8PSA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "glibc": ">=2.26", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.2" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.4.tgz", + "integrity": "sha512-0l7yRObwtTi82Z6ebVI2PnHT8EB2NxBgpK2MiKJZJ7cz32R4lxd001ecMhzzsZig3Yv9oclvqqdV93jo9hy+Dw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "glibc": ">=2.26", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.0.2" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.2.tgz", + "integrity": "sha512-tcK/41Rq8IKlSaKRCCAuuY3lDJjQnYIW1UXU1kxcEKrfL8WR7N6+rzNoOxoQRJWTAECuKwgAHnPvqXGN8XfkHA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "macos": ">=11", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.2.tgz", + "integrity": "sha512-Ofw+7oaWa0HiiMiKWqqaZbaYV3/UGL2wAPeLuJTx+9cXpCRdvQhCLG0IH8YGwM0yGWGLpsF4Su9vM1o6aer+Fw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "macos": ">=10.13", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.2.tgz", + "integrity": "sha512-iLWCvrKgeFoglQxdEwzu1eQV04o8YeYGFXtfWU26Zr2wWT3q3MTzC+QTCO3ZQfWd3doKHT4Pm2kRmLbupT+sZw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.28", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.2.tgz", + "integrity": "sha512-x7kCt3N00ofFmmkkdshwj3vGPCnmiDh7Gwnd4nUwZln2YjqPxV1NlTyZOvoDWdKQVDL911487HOueBvrpflagw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.26", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.2.tgz", + "integrity": "sha512-cmhQ1J4qVhfmS6szYW7RT+gLJq9dH2i4maq+qyXayUSn9/3iY2ZeWpbAgSpSVbV2E1JUL2Gg7pwnYQ1h8rQIog==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.28", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.2.tgz", + "integrity": "sha512-E441q4Qdb+7yuyiADVi5J+44x8ctlrqn8XgkDTwr4qPJzWkaHwD489iZ4nGDgcuya4iMN3ULV6NwbhRZJ9Z7SQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.26", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.2.tgz", + "integrity": "sha512-3CAkndNpYUrlDqkCM5qhksfE+qSIREVpyoeHIU6jd48SJZViAmznoQQLAv4hVXF7xyUB9zf+G++e2v1ABjCbEQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "musl": ">=1.2.2", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.2.tgz", + "integrity": "sha512-VI94Q6khIHqHWNOh6LLdm9s2Ry4zdjWJwH56WoiJU7NTeDwyApdZZ8c+SADC8OH98KWNQXnE01UdJ9CSfZvwZw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "musl": ">=1.2.2", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.4.tgz", + "integrity": "sha512-RUgBD1c0+gCYZGCCe6mMdTiOFS0Zc/XrN0fYd6hISIKcDUbAW5NtSQW9g/powkrXYm6Vzwd6y+fqmExDuCdHNQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.28", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.2" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.4.tgz", + "integrity": "sha512-2800clwVg1ZQtxwSoTlHvtm9ObgAax7V6MTAB/hDT945Tfyy3hVkmiHpeLPCKYqYR1Gcmv1uDZ3a4OFwkdBL7Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.26", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.0.2" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.4.tgz", + "integrity": "sha512-h3RAL3siQoyzSoH36tUeS0PDmb5wINKGYzcLB5C6DIiAn2F3udeFAum+gj8IbA/82+8RGCTn7XW8WTFnqag4tQ==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.31", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.0.2" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.4.tgz", + "integrity": "sha512-GoR++s0XW9DGVi8SUGQ/U4AeIzLdNjHka6jidVwapQ/JebGVQIpi52OdyxCNVRE++n1FCLzjDovJNozif7w/Aw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.26", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.2" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.4.tgz", + "integrity": "sha512-nhr1yC3BlVrKDTl6cO12gTpXMl4ITBUZieehFvMntlCXFzH2bvKG76tBL2Y/OqhupZt81pR7R+Q5YhJxW0rGgQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "musl": ">=1.2.2", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.2" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.4.tgz", + "integrity": "sha512-uCPTku0zwqDmZEOi4ILyGdmW76tH7dm8kKlOIV1XC5cLyJ71ENAAqarOHQh0RLfpIpbV5KOpXzdU6XkJtS0daw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "musl": ">=1.2.2", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.0.2" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.4.tgz", + "integrity": "sha512-Bmmauh4sXUsUqkleQahpdNXKvo+wa1V9KhT2pDA4VJGKwnKMJXiSTGphn0gnJrlooda0QxCtXc6RX1XAU6hMnQ==", + "cpu": [ + "wasm32" + ], + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.1.1" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.4.tgz", + "integrity": "sha512-99SJ91XzUhYHbx7uhK3+9Lf7+LjwMGQZMDlO/E/YVJ7Nc3lyDFZPGhjwiYdctoH2BOzW9+TnfqcaMKt0jHLdqw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.4.tgz", + "integrity": "sha512-3QLocdTRVIrFNye5YocZl+KKpYKP+fksi1QhmOArgx7GyhIbQp/WrJRu176jm8IxromS7RIkzMiMINVdBtC8Aw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -6288,11 +6729,22 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -6303,8 +6755,16 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } }, "node_modules/combined-stream": { "version": "1.0.8", @@ -6785,6 +7245,14 @@ "node": ">=8" } }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } + }, "node_modules/detect-node-es": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", @@ -13285,7 +13753,6 @@ "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -13300,7 +13767,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -13355,6 +13821,45 @@ "node": ">= 0.4" } }, + "node_modules/sharp": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.4.tgz", + "integrity": "sha512-7i/dt5kGl7qR4gwPRD2biwD2/SvBn3O04J77XKFgL2OnZtQw+AG9wnuS/csmu80nPRHLYE9E41fyEiG8nhH6/Q==", + "hasInstallScript": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.3", + "semver": "^7.6.0" + }, + "engines": { + "libvips": ">=8.15.2", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.33.4", + "@img/sharp-darwin-x64": "0.33.4", + "@img/sharp-libvips-darwin-arm64": "1.0.2", + "@img/sharp-libvips-darwin-x64": "1.0.2", + "@img/sharp-libvips-linux-arm": "1.0.2", + "@img/sharp-libvips-linux-arm64": "1.0.2", + "@img/sharp-libvips-linux-s390x": "1.0.2", + "@img/sharp-libvips-linux-x64": "1.0.2", + "@img/sharp-libvips-linuxmusl-arm64": "1.0.2", + "@img/sharp-libvips-linuxmusl-x64": "1.0.2", + "@img/sharp-linux-arm": "0.33.4", + "@img/sharp-linux-arm64": "0.33.4", + "@img/sharp-linux-s390x": "0.33.4", + "@img/sharp-linux-x64": "0.33.4", + "@img/sharp-linuxmusl-arm64": "0.33.4", + "@img/sharp-linuxmusl-x64": "0.33.4", + "@img/sharp-wasm32": "0.33.4", + "@img/sharp-win32-ia32": "0.33.4", + "@img/sharp-win32-x64": "0.33.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -13418,6 +13923,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -15478,8 +15996,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yaml": { "version": "2.4.1", diff --git a/package.json b/package.json index 2848f3d..1683cb9 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "remark-frontmatter": "^5.0.0", "remark-gfm": "^4.0.0", "remark-mdx-frontmatter": "^4.0.0", + "sharp": "^0.33.4", "short-uuid": "^4.2.2", "slugify": "^1.6.6", "sonner": "^1.4.3", diff --git a/src/app/[...markdownPath]/page.tsx b/src/app/[...markdownPath]/page.tsx index cce1bc3..efbe988 100644 --- a/src/app/[...markdownPath]/page.tsx +++ b/src/app/[...markdownPath]/page.tsx @@ -5,7 +5,7 @@ import { Layout } from '@/components/layouts/Layout' import { createMetadata } from '@/server/createMetadata' import { PageFrontmatter, SidebarConfig } from '@/types' import { PageHeader } from '@/components/PageHeader' -import { createCanonicalPath } from '@/server/createCanonicalPath' +import { createCanonicalUrl } from '@/server/createCanonicalUrl' import { FULL_DOMAIN } from '@/utils/constants' type Props = { @@ -19,7 +19,7 @@ export async function generateMetadata({ params }: Props) { const directPath = `${params.markdownPath.join('/')}.mdx` const indexPath = `${params.markdownPath.join('/')}/index.mdx` - const canonicalPath = createCanonicalPath(params.markdownPath) + const canonicalUrl = createCanonicalUrl(params.markdownPath) const hasDirectMdx = fs.existsSync(path.join(process.cwd(), 'src/content', directPath)) const hasIndexMdx = fs.existsSync(path.join(process.cwd(), 'src/content', indexPath)) @@ -40,7 +40,7 @@ export async function generateMetadata({ params }: Props) { description: pageMdx.frontmatter?.meta?.description ?? pageMdx.frontmatter?.description ?? '', category: pageMdx.frontmatter?.meta?.category, ogTitle: pageMdx.frontmatter?.title ?? '', - canonicalPath, + canonicalUrl, }) } @@ -51,6 +51,8 @@ export default async function MarkdownPage({ params }: Props) { let sidebar: SidebarConfig | null = null let steppedSegments = [] + const canonicalUrl = createCanonicalUrl(params.markdownPath) + ;['', ...params.markdownPath].forEach((segment) => { steppedSegments.push(segment) @@ -86,7 +88,7 @@ export default async function MarkdownPage({ params }: Props) { '@type': 'TechArticle', headline: pageMdx.frontmatter?.meta?.title ?? pageMdx.frontmatter?.title ?? '', description: pageMdx.frontmatter?.meta?.description ?? pageMdx.frontmatter?.description ?? '', - url: `${FULL_DOMAIN}${(hasDirectMdx ? directPath : indexPath).replace('.mdx', '').replace('index', '')}`, + url: canonicalUrl, datePublished: new Date(Date.now()).toISOString(), dateModified: new Date(Date.now()).toISOString(), publisher: { @@ -95,7 +97,7 @@ export default async function MarkdownPage({ params }: Props) { url: 'https://tiptap.dev', logo: { '@type': 'ImageObject', - url: `${FULL_DOMAIN}assets/images/tiptap-logo.png`, + url: `${FULL_DOMAIN}/assets/images/tiptap-logo.png`, }, }, } diff --git a/src/app/api/health/route.tsx b/src/app/api/health/route.tsx new file mode 100644 index 0000000..d176822 --- /dev/null +++ b/src/app/api/health/route.tsx @@ -0,0 +1,5 @@ +import { NextResponse } from 'next/server' + +export async function GET() { + return NextResponse.json({ status: 'ok' }, { status: 200 }) +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index c578c94..412f896 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -5,7 +5,7 @@ import { cn } from '@/utils' import { Providers } from '@/components/Providers' import { createMetadata } from '@/server/createMetadata' import { Search } from '@/components/Search' -import { createCanonicalPath } from '@/server/createCanonicalPath' +import { createCanonicalUrl } from '@/server/createCanonicalUrl' import { FULL_DOMAIN, GTM_ID } from '@/utils/constants' const inter = Inter({ subsets: ['latin'] }) @@ -15,7 +15,7 @@ export async function getMetadata() { title: 'Tiptap Suite Documentation', description: 'Documentation for Tiptap and all Tiptap products', ogTitle: 'Tiptap Suite Documentation', - canonicalPath: createCanonicalPath([]), + canonicalUrl: createCanonicalUrl([]), }) } diff --git a/src/app/page.tsx b/src/app/page.tsx index 4b6d22a..caf2dfe 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -3,7 +3,7 @@ import { createMetadata } from '@/server/createMetadata' import { PageFrontmatter } from '@/types' import { PageHeader } from '@/components/PageHeader' import { sidebarConfig } from '@/content/sidebar' -import { createCanonicalPath } from '@/server/createCanonicalPath' +import { createCanonicalUrl } from '@/server/createCanonicalUrl' import { FULL_DOMAIN } from '@/utils/constants' export async function generateMetadata() { @@ -12,13 +12,13 @@ export async function generateMetadata() { frontmatter?: PageFrontmatter } - const canonicalPath = createCanonicalPath([]) + const canonicalUrl = createCanonicalUrl([]) return await createMetadata({ title: pageMdx.frontmatter?.meta?.title ?? pageMdx.frontmatter?.title ?? '', description: pageMdx.frontmatter?.meta?.description ?? pageMdx.frontmatter?.description ?? '', ogTitle: pageMdx.frontmatter?.title ?? '', - canonicalPath, + canonicalUrl, }) } @@ -42,7 +42,7 @@ export default async function HomePage() { url: 'https://tiptap.dev', logo: { '@type': 'ImageObject', - url: `${FULL_DOMAIN}assets/images/tiptap-logo.png`, + url: `${FULL_DOMAIN}/assets/images/tiptap-logo.png`, }, }, } diff --git a/src/components/layouts/Layout.tsx b/src/components/layouts/Layout.tsx index a27c0c7..c939314 100644 --- a/src/components/layouts/Layout.tsx +++ b/src/components/layouts/Layout.tsx @@ -166,7 +166,7 @@ export type LayoutContentProps = {} & React.HTMLAttributes export const LayoutContent = forwardRef( ({ children, className, ...rest }, ref) => { return ( -
(
Copyright © 2024 Tiptap
- + ) }, ) diff --git a/src/components/ui/Sidebar.tsx b/src/components/ui/Sidebar.tsx index ef4bf1c..ccc6ffd 100644 --- a/src/components/ui/Sidebar.tsx +++ b/src/components/ui/Sidebar.tsx @@ -8,9 +8,9 @@ export type SidebarTrack = {} & React.HTMLAttributes export const SidebarTrack = forwardRef( ({ children, className, ...rest }, ref) => { return ( -
+
+ ) }, ) diff --git a/src/content/collaboration/documents/rest-api.mdx b/src/content/collaboration/documents/rest-api.mdx index e66cec1..aa85695 100644 --- a/src/content/collaboration/documents/rest-api.mdx +++ b/src/content/collaboration/documents/rest-api.mdx @@ -94,7 +94,7 @@ If you choose the `yjs` format, you'll get the binary Yjs update message created with `Y.encodeStateAsUpdate`. `fragment` can be an array (`fragment=a&fragment=b`) of or a single fragment that you want to -export. By default we'll export all fragments. Note that this is only taken into account when using +export. By default we only export the `default` fragment. Note that this is only taken into account when using the `json` format, otherwise you'll always get the whole Yjs document. ```bash diff --git a/src/content/collaboration/getting-started/install.mdx b/src/content/collaboration/getting-started/install.mdx index dcfe097..0b9a557 100644 --- a/src/content/collaboration/getting-started/install.mdx +++ b/src/content/collaboration/getting-started/install.mdx @@ -141,12 +141,12 @@ export default () => { // Connect to your Collaboration server useEffect(() => { const provider = new TiptapCollabProvider({ - name: encodeURIComponent('document.name'), // Unique document identifier for syncing. This is your document name. + name: 'document.name', // Unique document identifier for syncing. This is your document name. appId: '7j9y6m10', // Your Cloud Dashboard AppID or `baseURL` for on-premises token: 'notoken', // Your JWT token document: doc, }) - }) + }, []) return } @@ -192,7 +192,7 @@ export default () => { useEffect(() => { const provider = new TiptapCollabProvider({ - name: encodeURIComponent('document.name'), // Unique document identifier for syncing. This is your document name. + name: 'document.name', // Unique document identifier for syncing. This is your document name. appId: '7j9y6m10', // Your Cloud Dashboard AppID or `baseURL` for on-premises token: 'notoken', // Your JWT token document: doc, @@ -209,7 +209,7 @@ export default () => { } }, }) - }) + }, []) return } diff --git a/src/content/collaboration/operations/configure.mdx b/src/content/collaboration/operations/configure.mdx index c80cfaa..f6f038e 100644 --- a/src/content/collaboration/operations/configure.mdx +++ b/src/content/collaboration/operations/configure.mdx @@ -29,6 +29,8 @@ Several `key` settings can be adjusted dynamically: - `webhook_version`: The webhook version - `default_auto_versioning`: Turn auto versioning on or off by default (1 for enabled, 0 for off). - `default_auto_versioning_interval`: Default versioning interval (default is 30 seconds) +- `webhook_log_errors_only`: turn off webhook success logs (from v3.9.8) +- `allowed_origins`: If set, this will validate `Origin` headers from clients to match with one of the provided values (comma separated). Example value: `https://test.tiptap.dev,https://prod.tiptap.dev` ; if not set, origin header validation is turned off. (from 3.11.0) ## Managing Settings via API diff --git a/src/content/collaboration/provider/events.mdx b/src/content/collaboration/provider/events.mdx index 7b22491..91166a9 100644 --- a/src/content/collaboration/provider/events.mdx +++ b/src/content/collaboration/provider/events.mdx @@ -34,7 +34,7 @@ To ensure immediate event tracking, you can pass event listeners directly to the ```ts const provider = new TiptapCollabProvider({ appId: '', // Use for cloud setups, replace with baseUrl in case of on-prem - name: encodeURIComponent('example-document'), // Document identifier + name: 'example-document', // Document identifier token: '', // Your authentication JWT token document: ydoc, onOpen() { diff --git a/src/content/content-ai/capabilities/text-generation/built-in-commands.mdx b/src/content/content-ai/capabilities/text-generation/built-in-commands.mdx index 094bcb9..9b0f2b8 100644 --- a/src/content/content-ai/capabilities/text-generation/built-in-commands.mdx +++ b/src/content/content-ai/capabilities/text-generation/built-in-commands.mdx @@ -10,32 +10,32 @@ The Content AI for Tiptap Editor includes a set of preconfigured commands that y To see how these commands are used, check out the examples on the [overview](/content-ai/getting-started/overview) page. -| Command | Description | -| ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | -| [`aiAdjustTone(tone: Tone, options: TextOptions)`](#aiadjusttone) | Adjusts the tone of voice of the selected text to the specified [TONE](#aitone). | -| [`aiBloggify(options: TextOptions)`](#most-text-commands) | Rewrite the text into a blog format | -| [`aiComplete(options: TextOptions)`](#most-text-commands) | Completes the selected text | -| [`aiDeEmojify(options: TextOptions)`](#most-text-commands) | Removes emojis from the selected text | -| [`aiEmojify(options: TextOptions)`](#most-text-commands) | Adds emojis ✨ to your text | -| [`aiExtend(options: TextOptions)`](#most-text-commands) | Extends your text | -| [`aiFixSpellingAndGrammar(options: TextOptions)`](#most-text-commands) | Fixes spelling & grammar | -| [`aiKeypoints(options: TextOptions)`](#most-text-commands) | Summarizes your text to a list of key points | -| [`aiRephrase(options: TextOptions)`](#most-text-commands) | Rephrases the selected text | -| [`aiRestructure(options: TextOptions)`](#most-text-commands) | Restructures the selected text to use rich text formatting | -| [`aiShorten(options: TextOptions)`](#most-text-commands) | Shortens the selected text | -| [`aiSimplify(options: TextOptions)`](#most-text-commands) | Rephrases your text in simplified words | -| [`aiSummarize(options: TextOptions)`](#most-text-commands) | Summarizes your text | -| [`aiTextPrompt(options: TextOptions)`](#most-text-commands) | Runs your custom prompt | -| [`aiTldr(options: TextOptions)`](#most-text-commands) | Creates a "Too Long; Didn't Read" version text | -| [`aiTranslate(language: Language, options: TextOptions)`](#aitranslate) | Translates the selected text into the specified language | -| **Utility** | +| Command | Description | +| -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | +| [`aiAdjustTone(tone: Tone, options: TextOptions)`](#aiadjusttone) | Adjusts the tone of voice of the selected text to the specified [TONE](#aitone). | +| [`aiBloggify(options: TextOptions)`](#most-text-commands) | Rewrite the text into a blog format | +| [`aiComplete(options: TextOptions)`](#most-text-commands) | Completes the selected text | +| [`aiDeEmojify(options: TextOptions)`](#most-text-commands) | Removes emojis from the selected text | +| [`aiEmojify(options: TextOptions)`](#most-text-commands) | Adds emojis ✨ to your text | +| [`aiExtend(options: TextOptions)`](#most-text-commands) | Extends your text | +| [`aiFixSpellingAndGrammar(options: TextOptions)`](#most-text-commands) | Fixes spelling & grammar | +| [`aiKeypoints(options: TextOptions)`](#most-text-commands) | Summarizes your text to a list of key points | +| [`aiRephrase(options: TextOptions)`](#most-text-commands) | Rephrases the selected text | +| [`aiRestructure(options: TextOptions)`](#most-text-commands) | Restructures the selected text to use rich text formatting | +| [`aiShorten(options: TextOptions)`](#most-text-commands) | Shortens the selected text | +| [`aiSimplify(options: TextOptions)`](#most-text-commands) | Rephrases your text in simplified words | +| [`aiSummarize(options: TextOptions)`](#most-text-commands) | Summarizes your text | +| [`aiTextPrompt(options: TextOptions)`](#most-text-commands) | Runs your custom prompt | +| [`aiTldr(options: TextOptions)`](#most-text-commands) | Creates a "Too Long; Didn't Read" version text | +| [`aiTranslate(language: Language, options: TextOptions)`](#aitranslate) | Translates the selected text into the specified language | +| **Utility** | | [`aiAccept(options: AcceptOptions)`](/content-ai/capabilities/text-generation/manage-responses#aiaccept) | [Accept the generated response](/content-ai/capabilities/text-generation/manage-responses), and insert it into the editor | -| [`aiReject(options: RejectOptions)`](/content-ai/capabilities/text-generation/manage-responses#aireject) | [Reject the generated Response](content-ai/capabilities/text-generation/manage-responses), resetting ai.storage state | +| [`aiReject(options: RejectOptions)`](/content-ai/capabilities/text-generation/manage-responses#aireject) | [Reject the generated Response](/content-ai/capabilities/text-generation/manage-responses), resetting ai.storage state | | [`aiRegenerate(options: RegenerateOptions)`](/content-ai/capabilities/text-generation/manage-responses#airegenerate) | [Regenerate a response](/content-ai/capabilities/text-generation/manage-responses) using the same parameters | ### Most text commands -Most of the text commands accept the same options and their usage is similar. The following example demonstrates how to use the `aiComplete` command: +Most of the text commands accept the same options and their usage is similar. The following example demonstrates how to use the `aiBloggify` command: ```js editor.chain().focus().aiBloggify(options: TextOptions) @@ -65,7 +65,7 @@ On every command which supports `TextOptions`, you’re able to specify the foll | Setting | Type | Default | Definition | | ---------------- | ---------------------------------------------------------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -| `modelName` | see [Supported text models](#supported-text-models) | `gpt-3.5-turbo` | The model used at OpenAI | +| `modelName` | see [Supported text models](#supported-text-models) | `gpt-3.5-turbo` | The model used at OpenAI | | `language` | `string` (e.g. `en`, `de`) | `null` | Although we do our best to prompt OpenAI for a response in the language of the input, sometimes it’s better to define it yourself. | | `tone` | `string` | `null` | A [voice of tone](#ai-adjust-tone) the response should be transformed to | | `textLength` | `number` | `undefined` | The number of `textLengthUnit`s the AI should respond with (e.g. the `3` in "3 paragraphs") | diff --git a/src/content/editor/extensions/custom-extensions/extend-existing.mdx b/src/content/editor/extensions/custom-extensions/extend-existing.mdx index 3f037a1..a0ef404 100644 --- a/src/content/editor/extensions/custom-extensions/extend-existing.mdx +++ b/src/content/editor/extensions/custom-extensions/extend-existing.mdx @@ -36,13 +36,13 @@ new Editor({ The same applies to every aspect of an existing extension, except to the name. Let’s look at all the things that you can change through the extend method. We focus on one aspect in every example, but you can combine all those examples and change multiple aspects in one `extend()` call too. -### Name +## Name The extension name is used in a whole lot of places and changing it isn’t too easy. If you want to change the name of an existing extension, you can copy the whole extension and change the name in all occurrences. The extension name is also part of the JSON. If you [store your content as JSON](/guides/output-json-html#option-1-json), you need to change the name there too. -### Priority +## Priority The priority defines the order in which extensions are registered. The default priority is `100`, that’s what most extension have. Extensions with a higher priority will be loaded earlier. @@ -56,15 +56,15 @@ const CustomLink = Link.extend({ The order in which extensions are loaded influences two things: -1. #### Plugin order +1. ### Plugin order ProseMirror plugins of extensions with a higher priority will run first. -2. #### Schema order +2. ### Schema order The [`Link`](/editor/extensions/marks/link) mark for example has a higher priority, which means it will be rendered as `Example` instead of `Example`. -### Settings +## Settings All settings can be configured through the extension anyway, but if you want to change the default settings, for example to provide a library on top of Tiptap for other developers, you can do it like this: @@ -81,7 +81,7 @@ const CustomHeading = Heading.extend({ }) ``` -### Storage +## Storage At some point you probably want to save some data within your extension instance. This data is mutable. You can access it within the extension under `this.storage`. @@ -113,7 +113,7 @@ const editor = new Editor({ const awesomeness = editor.storage.customExtension.awesomeness ``` -### Schema +## Schema Tiptap works with a strict schema, which configures how the content can be structured, nested, how it behaves and many more things. You [can change all aspects of the schema](/editor/core-concepts/schema) for existing extensions. Let’s walk through a few common use cases. @@ -141,7 +141,7 @@ const CustomParagraph = Paragraph.extend({ That’s just two tiny examples, but [the underlying ProseMirror schema](https://prosemirror.net/docs/ref/#model.SchemaSpec) is really powerful. -### Attributes +## Attributes You can use attributes to store additional information in the content. Let’s say you want to extend the default `Paragraph` node to have different colors: @@ -217,7 +217,7 @@ const CustomParagraph = Paragraph.extend({ You can completely disable the rendering of attributes with `rendered: false`. -#### Extend existing attributes +### Extend existing attributes If you want to add an attribute to an extension and keep existing attributes, you can access them through `this.parent()`. @@ -236,7 +236,7 @@ const CustomTableCell = TableCell.extend({ }) ``` -### Global attributes +## Global attributes Attributes can be applied to multiple extensions at once. That’s useful for text alignment, line height, color, font family, and other styling related attributes. @@ -267,7 +267,7 @@ const TextAlign = Extension.create({ }) ``` -### Render HTML +## Render HTML With the `renderHTML` function you can control how an extension is rendered to HTML. We pass an attributes object to it, with all local attributes, global attributes, and configured CSS classes. Here is an example from the `Bold` extension: @@ -299,7 +299,7 @@ renderHTML({ HTMLAttributes }) { }, ``` -### Parse HTML +## Parse HTML The `parseHTML()` function tries to load the editor document from HTML. The function gets the HTML DOM element passed as a parameter, and is expected to return an object with attributes and their values. Here is a simplified example from the [`Bold`](/editor/extensions/marks/bold) mark: @@ -344,7 +344,7 @@ You are wondering what’s that `&& null` doing? [ProseMirror expects `null` or [Pass `priority` to a rule](https://prosemirror.net/docs/ref/version/0.18.0.html#model.ParseRule.priority) to resolve conflicts with other extensions, for example if you build a custom extension which looks for paragraphs with a class attribute, but you already use the default paragraph extension. -#### Using getAttrs +### Using getAttrs The `getAttrs` function you’ve probably noticed in the example has two purposes: @@ -384,7 +384,7 @@ addAttributes() { Read more about `getAttrs` and all other `ParseRule` properties in the [ProseMirror reference](https://prosemirror.net/docs/ref/#model.ParseRule). -### Commands +## Commands ```js import Paragraph from '@tiptap/extension-paragraph' @@ -406,7 +406,7 @@ const CustomParagraph = Paragraph.extend({ To access other commands inside `addCommands` use the `commands` parameter that’s passed to it. -### Keyboard shortcuts +## Keyboard shortcuts Most core extensions come with sensible keyboard shortcut defaults. Depending on what you want to build, you’ll likely want to change them though. With the `addKeyboardShortcuts()` method you can overwrite the predefined shortcut map: @@ -423,7 +423,7 @@ const CustomBulletList = BulletList.extend({ }) ``` -### Input rules +## Input rules With input rules you can define regular expressions to listen for user inputs. They are used for markdown shortcuts, or for example to convert text like `(c)` to a `©` (and many more) with the [`Typography`](/editor/extensions/functionality/typography) extension. Use the `markInputRule` helper function for marks, and the `nodeInputRule` for nodes. @@ -452,7 +452,7 @@ const CustomStrike = Strike.extend({ }) ``` -### Paste rules +## Paste rules Paste rules work like input rules (see above) do. But instead of listening to what the user types, they are applied to pasted content. @@ -483,7 +483,7 @@ const CustomStrike = Strike.extend({ }) ``` -### Events +## Events You can even move your [event listeners](/editor/api/events) to a separate extension. Here is an example with listeners for all events: @@ -515,7 +515,7 @@ const CustomExtension = Extension.create({ }) ``` -### What’s available in this? +## What’s available in this? Those extensions aren’t classes, but you still have a few important things available in `this` everywhere in the extension. @@ -536,11 +536,11 @@ this.options this.parent ``` -### ProseMirror Plugins (Advanced) +## ProseMirror Plugins (Advanced) After all, Tiptap is built on ProseMirror and ProseMirror has a pretty powerful plugin API, too. To access that directly, use `addProseMirrorPlugins()`. -#### Existing plugins +### Existing plugins You can wrap existing ProseMirror plugins in Tiptap extensions like shown in the example below. @@ -557,7 +557,7 @@ const History = Extension.create({ }) ``` -#### Access the ProseMirror API +### Access the ProseMirror API To hook into events, for example a click, double click or when content is pasted, you can pass [event handlers](https://prosemirror.net/docs/ref/#view.EditorProps) to `editorProps` on the [editor](/editor/api/events). @@ -593,7 +593,7 @@ export const EventHandler = Extension.create({ }) ``` -### Node views (Advanced) +## Node views (Advanced) For advanced use cases, where you need to execute JavaScript inside your nodes, for example to render a sophisticated interface around an image, you need to learn about node views. diff --git a/src/content/editor/getting-started/install/react.mdx b/src/content/editor/getting-started/install/react.mdx index 9b65adb..a7739a7 100644 --- a/src/content/editor/getting-started/install/react.mdx +++ b/src/content/editor/getting-started/install/react.mdx @@ -8,7 +8,7 @@ meta: import { CodeDemo } from '@/components/CodeDemo' -The following guide describes how to integrate Tiptap with your React project. We’re using Create React App here, but the workflow should be similar with other setups. +The following guide describes how to integrate Tiptap with your React project. We’re using Vite here, but the workflow should be similar with other setups. diff --git a/src/server/createCanonicalPath.ts b/src/server/createCanonicalPath.ts deleted file mode 100644 index 8eb19a7..0000000 --- a/src/server/createCanonicalPath.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { FULL_DOMAIN } from '@/utils/constants' - -export const createCanonicalPath = (path: string[]) => { - const canonicalPath = `${FULL_DOMAIN}/${path.join('/')}` - return canonicalPath -} diff --git a/src/server/createCanonicalUrl.ts b/src/server/createCanonicalUrl.ts new file mode 100644 index 0000000..7178dcb --- /dev/null +++ b/src/server/createCanonicalUrl.ts @@ -0,0 +1,9 @@ +import { DOMAIN, BASE_PATH } from '@/utils/constants' + +export const createCanonicalUrl = (path: string[]) => { + const urlPath = [BASE_PATH, ...path].join('/') + const canonicalUrl = new URL(urlPath, DOMAIN) + const href = canonicalUrl.href + + return href +} diff --git a/src/server/createMetadata.ts b/src/server/createMetadata.ts index fbf23c5..0c479c1 100644 --- a/src/server/createMetadata.ts +++ b/src/server/createMetadata.ts @@ -7,13 +7,13 @@ export async function createMetadata({ description, category, ogTitle, - canonicalPath, + canonicalUrl, }: { title: string description: string ogTitle: string category?: string - canonicalPath: string + canonicalUrl: string }): Promise { return { title, @@ -29,7 +29,7 @@ export async function createMetadata({ height: 630, }, ], - url: process.env.NEXT_PUBLIC_DOMAIN ?? '', + url: canonicalUrl, type: 'website', locale: 'en_US', }, @@ -42,7 +42,7 @@ export async function createMetadata({ ], }, alternates: { - canonical: canonicalPath, + canonical: canonicalUrl, }, } }