Prepare @gitbook/icons package and use it as a replacement of geist/icons (#2404)

This commit is contained in:
Samy Pessé
2024-08-02 09:59:44 +02:00
committed by GitHub
parent d7ec2b57a4
commit 5c35f36b3a
85 changed files with 865 additions and 548 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': minor
---
Replace all icons, previously imported from Geist, by new package `@gitbook/icons`
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/icons': minor
---
Initial release for `@gitbook/icons`, a package of content icons to be used for pages, documents, etc.
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/react-math': minor
---
Export binary `gitbook-math` to copy assets to a directory
+3 -1
View File
@@ -7,7 +7,7 @@ runs:
- name: 🏗 Prepare Playwright env
shell: bash
run: |
PLAYWRIGHT_VERSION=$(npm ls --json @playwright/test | jq --raw-output '.dependencies["@playwright/test"].version')
PLAYWRIGHT_VERSION=$(npm ls --json @playwright/test | jq --raw-output '.dependencies["gitbook"].dependencies["@playwright/test"].version')
echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV
# Cache browser binaries, cache key is based on Playwright version and OS
@@ -24,6 +24,7 @@ runs:
- name: 🏗 Install Playwright browser binaries & OS dependencies
if: steps.playwright-cache.outputs.cache-hit != 'true'
shell: bash
working-directory: packages/gitbook
run: |
bun x playwright install --with-deps chromium
@@ -31,5 +32,6 @@ runs:
- name: 🏗 Install Playwright OS dependencies
if: steps.playwright-cache.outputs.cache-hit == 'true'
shell: bash
working-directory: packages/gitbook
run: |
bun x playwright install-deps
+2 -1
View File
@@ -4,7 +4,8 @@ on:
push:
branches:
- main
env:
NPMRC_FONT_AWESOME_TOKEN: ${{ secrets.NPMRC_FONT_AWESOME_TOKEN }}
jobs:
deploy:
name: Deploy to Cloudflare Pages
+2
View File
@@ -20,3 +20,5 @@ yarn-error.log*
# Vercel
.vercel
# Env files
.env.local
+4
View File
@@ -4,3 +4,7 @@
# Generated
packages/emoji-codepoints/index.ts
packages/gitbook/public/~gitbook/static/
packages/icons/src/data/*.json
# Build files
dist/
BIN
View File
Binary file not shown.
+2
View File
@@ -0,0 +1,2 @@
[install.scopes]
"awesome.me" = { token = "$NPMRC_FONT_AWESOME_TOKEN", url = "https://npm.fontawesome.com/" }
+3 -2
View File
@@ -8,13 +8,14 @@
"build": "turbo run build",
"build:cloudflare": "turbo run build:cloudflare",
"lint": "turbo run lint",
"lint:fix": "turbo run lint -- --fix",
"typecheck": "turbo run typecheck",
"format": "prettier ./ --ignore-unknown --write",
"format:check": "prettier ./ --ignore-unknown --list-different",
"unit": "turbo run unit",
"e2e": "turbo run e2e",
"changeset": "changeset",
"release": "turbo run build && changeset publish"
"release": "turbo run release && changeset publish"
},
"workspaces": [
"packages/*"
@@ -25,6 +26,6 @@
"turbo": "^2.0.9"
},
"patchedDependencies": {
"@vercel/next@4.0.15": "patches/@vercel%2Fnext@4.0.15.patch"
"@vercel/next@4.3.6": "patches/@vercel%2Fnext@4.3.6.patch"
}
}
+1 -1
View File
@@ -1 +1 @@
index.ts
dist/
+4 -2
View File
@@ -1,4 +1,5 @@
import fs from 'fs';
import fs from 'node:fs';
import path from 'node:path';
import emojisRaws from 'emoji-assets/emoji.json';
interface EmojiData {
@@ -20,7 +21,8 @@ Object.entries(emojis).forEach(([key, value]) => {
}
});
fs.mkdirSync(path.resolve(__dirname, 'dist'), { recursive: true });
fs.writeFileSync(
'index.ts',
path.resolve(__dirname, 'dist/index.ts'),
`export const emojiCodepoints: Record<string, string> = ${JSON.stringify(output, null, 4)};`,
);
+2 -2
View File
@@ -3,12 +3,12 @@
"description": "Optimized mapping of codepoints to the fully qualified emoji codepoints",
"version": "0.2.0",
"private": true,
"exports": "./index.ts",
"exports": "./dist/index.ts",
"dependencies": {},
"devDependencies": {
"emoji-assets": "^8.0.0"
},
"scripts": {
"postinstall": "bun ./build.ts"
"generate": "bun ./build.ts"
}
}
+5 -1
View File
@@ -349,6 +349,11 @@ const testCases: TestsCase[] = [
url: 'blocks/embeds',
fullPage: true,
},
{
name: 'Page links',
url: 'blocks/page-links',
fullPage: true,
},
{
name: 'Annotations',
url: 'blocks/annotations',
@@ -408,7 +413,6 @@ const testCases: TestsCase[] = [
{
name: 'Valid link',
url: 'TGs8PkF4GWVtbmPnWhYL/',
run: waitForCookiesDialog,
},
{
name: 'Invalid link',
+2
View File
@@ -7,6 +7,8 @@ module.exports = withSentryConfig(
SENTRY_DSN: process.env.SENTRY_DSN ?? '',
SENTRY_ENVIRONMENT: process.env.SENTRY_ENVIRONMENT ?? 'development',
GITBOOK_ASSETS_PREFIX: process.env.GITBOOK_ASSETS_PREFIX,
GITBOOK_ICONS_URL: process.env.GITBOOK_ICONS_URL,
GITBOOK_ICONS_TOKEN: process.env.GITBOOK_ICONS_TOKEN,
},
webpack(config, { dev, webpack }) {
+10 -7
View File
@@ -3,7 +3,7 @@
"version": "0.3.0",
"private": true,
"scripts": {
"dev": "next dev",
"dev": "env-cmd -f ../../.env.local next dev",
"build": "next build",
"build:cloudflare": "next-on-pages",
"start": "next start",
@@ -11,14 +11,16 @@
"typecheck": "tsc --noEmit",
"e2e": "playwright test",
"unit": "bun test {src,packages}",
"postinstall": "rm -rf ./public/~gitbook/static/mathjax@3.2.2 && mkdir -p ./public/~gitbook/static/ && cp -R ../../node_modules/mathjax/es5 ./public/~gitbook/static/mathjax@3.2.2"
"generate": "gitbook-icons ./public/~gitbook/static/icons custom-icons && gitbook-math ./public/~gitbook/static/math",
"copy:icons": "gitbook-icons ./public/~gitbook/static/icons"
},
"dependencies": {
"@geist-ui/icons": "^1.0.2",
"@gitbook/api": "^0.58.0",
"@gitbook/icons": "workspace:*",
"@gitbook/react-math": "workspace:*",
"@gitbook/react-openapi": "workspace:*",
"@gitbook/react-contentkit": "workspace:*",
"@gitbook/emoji-codepoints": "workspace:*",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-popover": "^1.0.7",
"@sentry/nextjs": "^7.94.1",
@@ -37,7 +39,7 @@
"katex": "^0.16.9",
"mathjax": "^3.2.2",
"memoizee": "^0.4.15",
"next": "^14.1.3",
"next": "^14.2.5",
"next-themes": "^0.2.1",
"nuqs": "^1.17.4",
"object-hash": "^3.0.0",
@@ -64,8 +66,8 @@
"devDependencies": {
"@argos-ci/playwright": "^2.0.0",
"@playwright/test": "^1.42.1",
"@cloudflare/next-on-pages": "^1.11.3",
"@cloudflare/workers-types": "^4.20231218.0",
"@cloudflare/next-on-pages": "^1.12.1",
"@cloudflare/workers-types": "^4.20240725.0",
"@types/js-cookie": "^3.0.6",
"@types/jsontoxml": "^1.0.5",
"@types/jsonwebtoken": "^9.0.6",
@@ -84,6 +86,7 @@
"postcss": "^8",
"psi": "^4.1.0",
"tailwindcss": "^3.4.0",
"typescript": "^5.5.3"
"typescript": "^5.5.3",
"env-cmd": "^10.1.0"
}
}
@@ -1,6 +1,6 @@
'use client';
import { AlertTriangle } from '@geist-ui/icons';
import { Icon } from '@gitbook/icons';
import React from 'react';
import { useScrollActiveId } from '@/components/hooks';
@@ -105,7 +105,10 @@ export function PageControlButtons(props: {
'max-w-sm',
)}
>
<AlertTriangle className={tcls('size-6', 'mr-3', 'mt-1')} />{' '}
<Icon
icon="triangle-exclamation"
className={tcls('size-6', 'mr-3', 'mt-1')}
/>{' '}
<div>
<div>{t(language, 'pdf_limit_reached', total, pageIds.length)}</div>
<div>
@@ -1,13 +1,12 @@
import { ArrowLeft, Printer } from '@geist-ui/icons';
import {
CustomizationSettings,
Revision,
RevisionPageDocument,
RevisionPageGroup,
RevisionPageLink,
SiteCustomizationSettings,
Space,
} from '@gitbook/api';
import { Icon } from '@gitbook/icons';
import { Metadata } from 'next';
import { notFound } from 'next/navigation';
import * as React from 'react';
@@ -116,7 +115,7 @@ export default async function PDFHTMLOutput(props: { searchParams: { [key: strin
'border',
)}
>
<ArrowLeft className={tcls('size-6')} />
<Icon icon="arrow-left" className={tcls('size-6')} />
</a>
</div>
) : null}
@@ -142,7 +141,7 @@ export default async function PDFHTMLOutput(props: { searchParams: { [key: strin
'border',
)}
>
<Printer className={tcls('size-6')} />
<Icon icon="print" className={tcls('size-6')} />
</PrintButton>
</div>
+15 -1
View File
@@ -5,6 +5,7 @@ import {
CustomizationSettings,
SiteCustomizationSettings,
} from '@gitbook/api';
import { IconsProvider, IconStyle } from '@gitbook/icons';
import assertNever from 'assert-never';
import colors from 'tailwindcss/colors';
@@ -12,11 +13,13 @@ import { emojiFontClassName } from '@/components/primitives';
import { fonts, ibmPlexMono } from '@/fonts';
import { getSpaceLanguage } from '@/intl/server';
import { getCurrentSiteLayoutData, getSpaceLayoutData } from '@/lib/api';
import { getStaticFileURL } from '@/lib/assets';
import { hexToRgb, shadesOfColor } from '@/lib/colors';
import { tcls } from '@/lib/tailwind';
import { ClientContexts } from './ClientContexts';
import './globals.css';
import '@gitbook/icons/style.css';
import { getContentPointer } from './fetch';
/**
@@ -105,7 +108,18 @@ export default async function SpaceRootLayout(props: { children: React.ReactNode
'dark:bg-dark',
)}
>
<ClientContexts language={language}>{children}</ClientContexts>
<IconsProvider
assetsURL={process.env.GITBOOK_ICONS_URL ?? getStaticFileURL('icons')}
assetsURLToken={process.env.GITBOOK_ICONS_TOKEN}
assetsByStyles={{
'custom-icons': {
assetsURL: getStaticFileURL('icons'),
},
}}
iconStyle={IconStyle.Light}
>
<ClientContexts language={language}>{children}</ClientContexts>
</IconsProvider>
</body>
</html>
);
+2 -2
View File
@@ -1,6 +1,6 @@
'use client';
import IconHeart from '@geist-ui/icons/heart';
import { Icon } from '@gitbook/icons';
import * as React from 'react';
import { ClassValue, tcls } from '@/lib/tailwind';
@@ -188,7 +188,7 @@ function AdBlockerPlaceholder() {
)}
>
<div className={tcls('flex', 'flex-row', 'gap-2', 'items-center')}>
<IconHeart className={tcls('w-4', 'h-4', 'text-primary-500')} />
<Icon icon="heart" className={tcls('size-4', 'text-primary-500')} />
<p className={tcls('text-xs', 'font-semibold')}>Ad disabled</p>
</div>
<p className={tcls('text-xs')}>
@@ -1,6 +1,6 @@
'use client';
import IconX from '@geist-ui/icons/x';
import { Icon } from '@gitbook/icons';
import * as React from 'react';
import { Button } from '@/components/primitives';
@@ -92,7 +92,7 @@ export function CookiesToast(props: { privacyPolicy?: string }) {
)}
title={tString(language, 'cookies_close')}
>
<IconX className={tcls('w-4')} />
<Icon icon="xmark" className={tcls('size-4')} />
</button>
<div className={tcls('mt-3', 'flex', 'flex-row', 'gap-2')}>
<Button
@@ -1,11 +1,11 @@
import { DocumentBlockContentRef } from '@gitbook/api';
import { LogoIcon } from '@/components/icons';
import { Card, Emoji } from '@/components/primitives';
import { getSpaceCustomization, ignoreAPIError } from '@/lib/api';
import { ResolvedContentRef } from '@/lib/references';
import { BlockProps } from './Block';
import { SpaceIcon } from '../Space/SpaceIcon';
export async function BlockContentRef(props: BlockProps<DocumentBlockContentRef>) {
const { block, context, style } = props;
@@ -55,7 +55,7 @@ async function SpaceRefCard(
return (
<Card
leadingIcon={
<LogoIcon
<SpaceIcon
icon={customIcon}
emoji={customEmoji}
alt=""
@@ -1,6 +1,5 @@
import ChevronRight from '@geist-ui/icons/chevronRight';
import IconHash from '@geist-ui/icons/hash';
import { DocumentBlockExpandable } from '@gitbook/api';
import { Icon } from '@gitbook/icons';
import { getNodeFragmentByType } from '@/lib/document';
import { tcls } from '@/lib/tailwind';
@@ -78,11 +77,11 @@ export function Expandable(props: BlockProps<DocumentBlockExpandable>) {
'[&::-webkit-details-marker]:hidden',
)}
>
<ChevronRight
<Icon
icon="chevron-right"
className={tcls(
'inline-block',
'w-4',
'h-4',
'size-3',
'mr-2',
'mb-1',
'transition-transform',
@@ -111,15 +110,15 @@ export function Expandable(props: BlockProps<DocumentBlockExpandable>) {
'dark:ring-0',
)}
>
<IconHash
<Icon
icon="hashtag"
className={tcls(
'inline-block',
'w-4',
'h-4',
'size-3',
'transition-colors',
'stroke-transparent',
'group-hover:stroke-dark/6',
'dark:group-hover:stroke-light/5',
'text-transparent',
'group-hover:text-dark/6',
'dark:group-hover:text-light/5',
)}
/>
</a>
@@ -66,8 +66,11 @@ export async function File(props: BlockProps<DocumentBlockFile>) {
'dark:border-light/2',
)}
>
<div className={tcls('*:w-5', '*:h-5', '*:stroke-primary')}>
<FileIcon contentType={contentType} />
<div>
<FileIcon
contentType={contentType}
className={tcls('size-5', 'text-primary')}
/>
</div>
<div
className={tcls(
@@ -1,24 +1,21 @@
import IconDownload from '@geist-ui/icons/download';
import IconFileText from '@geist-ui/icons/fileText';
import IconImage from '@geist-ui/icons/image';
import IconPaperClip from '@geist-ui/icons/paperclip';
import { Icon } from '@gitbook/icons';
import { SimplifiedFileType } from '@/lib/files';
/**
* Render an appropriate icon for a file.
*/
export function FileIcon(props: { contentType: SimplifiedFileType | null }) {
const { contentType } = props;
export function FileIcon(props: { contentType: SimplifiedFileType | null; className: string }) {
const { contentType, className } = props;
switch (contentType) {
case 'pdf':
return <IconFileText />;
return <Icon icon="file-pdf" className={className} />;
case 'image':
return <IconImage />;
return <Icon icon="file-image" className={className} />;
case 'archive':
return <IconPaperClip />;
return <Icon icon="file-archive" className={className} />;
default:
return <IconDownload />;
return <Icon icon="file-download" className={className} />;
}
}
@@ -1,5 +1,5 @@
import IconHash from '@geist-ui/icons/hash';
import { DocumentBlockHeading } from '@gitbook/api';
import { Icon } from '@gitbook/icons';
import { tcls } from '@/lib/tailwind';
@@ -48,14 +48,15 @@ export function Heading(props: BlockProps<DocumentBlockHeading>) {
textStyle.lineHeight,
)}
>
<IconHash
<Icon
icon="hashtag"
className={tcls(
'w-3.5',
'h-[1lh]',
'transition-colors',
'stroke-transparent',
'group-hover:stroke-dark/6',
'dark:group-hover:stroke-light/5',
'text-transparent',
'group-hover:text-dark/6',
'dark:group-hover:text-light/5',
'lg:w-4',
)}
/>
@@ -1,4 +1,5 @@
import { DocumentBlockHint } from '@gitbook/api';
import { Icon, IconName } from '@gitbook/icons';
import React from 'react';
import { ClassValue, tcls } from '@/lib/tailwind';
@@ -9,9 +10,8 @@ import { getBlockTextStyle } from './spacing';
export function Hint(props: BlockProps<DocumentBlockHint>) {
const { block, style, ancestorBlocks, ...contextProps } = props;
const hintStyle = HINT_STYLES[block.data.style];
const hintStyle = HINT_STYLES[block.data.style] ?? HINT_STYLES.info;
const firstLine = getBlockTextStyle(block.nodes[0]);
const RenderIcon = HINT_STYLES[block.data.style].icon;
return (
<div
@@ -34,17 +34,17 @@ export function Hint(props: BlockProps<DocumentBlockHint>) {
'pr-3',
'mt-0.5',
firstLine.lineHeight,
hintStyle.anchorColor,
hintStyle.iconColor,
)}
>
<RenderIcon />
<Icon icon={hintStyle.icon} className={tcls('size-4')} />
</div>
<Blocks
{...contextProps}
ancestorBlocks={[...ancestorBlocks, block]}
nodes={block.nodes}
blockStyle={tcls(
hintStyle.anchorColor,
hintStyle.bodyColor,
// render hash icon on the other side of the heading
'flip-heading-hash',
)}
@@ -57,14 +57,16 @@ export function Hint(props: BlockProps<DocumentBlockHint>) {
const HINT_STYLES: {
[style in DocumentBlockHint['data']['style']]: {
icon: () => React.ReactNode;
anchorColor: ClassValue;
icon: IconName;
iconColor: ClassValue;
bodyColor: ClassValue;
style: ClassValue;
};
} = {
info: {
icon: InfoIcon,
anchorColor: [
icon: 'circle-info',
iconColor: ['text-periwinkle-700', 'dark:text-periwinkle-400'],
bodyColor: [
'[&>a]:text-periwinkle-700',
'[&>a:hover]:text-periwinkle-800',
'[&>code]:bg-periwinkle-700/4',
@@ -72,8 +74,6 @@ const HINT_STYLES: {
'[&>code]:shadow-none',
'text-periwinkle-900',
'fill-periwinkle-700',
'stroke-periwinkle-700',
'dark:text-periwinkle-200',
'dark:[&>a]:text-periwinkle',
@@ -82,8 +82,6 @@ const HINT_STYLES: {
'dark:[&>code]:text-inherit',
'decoration-periwinkle-700/6',
'dark:decoration-periwinkle/6',
'dark:fill-periwinkle-400',
'dark:stroke-periwinkle-400',
],
style: [
'bg-gradient-to-b',
@@ -98,8 +96,9 @@ const HINT_STYLES: {
],
},
warning: {
icon: WarningIcon,
anchorColor: [
icon: 'circle-exclamation',
iconColor: ['text-yellow-800', 'dark:text-yellow'],
bodyColor: [
'[&>a]:text-yellow-700',
'[&>a:hover]:text-yellow-800',
'[&>code]:bg-yellow-600/5',
@@ -108,7 +107,6 @@ const HINT_STYLES: {
'text-yellow-900',
'fill-yellow-800',
'dark:text-yellow-200',
'dark:[&>a]:text-yellow',
'dark:[&>a:hover]:text-yellow-600',
@@ -116,7 +114,6 @@ const HINT_STYLES: {
'dark:[&>code]:text-inherit',
'decoration-yellow-700/6',
'dark:decoration-yellow/6',
'dark:fill-yellow',
],
style: [
'bg-gradient-to-b',
@@ -131,8 +128,9 @@ const HINT_STYLES: {
],
},
danger: {
icon: DangerIcon,
anchorColor: [
icon: 'triangle-exclamation',
iconColor: ['text-pomegranate-700', 'dark:text-pomegranate-400'],
bodyColor: [
'[&>a]:text-pomegranate-600/9',
'[&>a:hover]:text-pomegranate-800',
'[&>code]:bg-pomegranate-600/4',
@@ -141,7 +139,6 @@ const HINT_STYLES: {
'text-pomegranate-900',
'fill-pomegranate-700',
'dark:text-pomegranate-100',
'dark:[&>a]:text-pomegranate',
'dark:[&>a:hover]:text-pomegranate-600',
@@ -149,7 +146,6 @@ const HINT_STYLES: {
'dark:[&>code]:text-inherit',
'decoration-pomegranate-600/6',
'dark:decoration-pomegranate/6',
'dark:fill-pomegranate-400',
],
style: [
'bg-gradient-to-b',
@@ -164,8 +160,9 @@ const HINT_STYLES: {
],
},
success: {
icon: SuccessIcon,
anchorColor: [
icon: 'circle-check',
iconColor: ['text-teal-700', 'dark:text-teal-400'],
bodyColor: [
'[&>a]:text-teal-600',
'[&>a:hover]:text-teal-800',
'[&>code]:bg-teal-600/4',
@@ -173,8 +170,6 @@ const HINT_STYLES: {
'[&>code]:shadow-none',
'text-teal-800',
'fill-teal-700',
'stroke-teal-700',
'dark:text-teal-100',
'dark:[&>a]:text-teal-400',
@@ -183,8 +178,6 @@ const HINT_STYLES: {
'dark:[&>code]:text-inherit',
'decoration-teal/6',
'dark:decoration-teal/6',
'dark:fill-teal-400',
'dark:stroke-teal-300',
],
style: [
'bg-gradient-to-b',
@@ -199,131 +192,3 @@ const HINT_STYLES: {
],
},
};
function InfoIcon() {
return (
<svg
width="16"
height="16"
viewBox="0 0 16 16"
xmlns="http://www.w3.org/2000/svg"
className={tcls('overflow-visible')}
>
<circle cx="8" cy="4.5" r="1.5" fill="inherit" fillOpacity="1" stroke="none" />
<circle
cx="8"
cy="4.5"
r="1.5"
fill="inherit"
fillOpacity="0.2"
stroke="none"
className={tcls(
'animate-[pingAlt_8s_ease_infinite_forwards]',
'origin-[8px_4.5px]',
'w-[4px]',
'h-[4px]',
)}
/>
<rect
x="7"
y="7"
width="2"
rx="1"
height="6"
fill="inherit"
fillOpacity="1"
stroke="none"
/>
<circle cx="8" cy="8" r="8" fill="inherit" fillOpacity="0.16" stroke="none" />
</svg>
);
}
function DangerIcon() {
return (
<svg width="18" height="16" viewBox="0 0 18 16" xmlns="http://www.w3.org/2000/svg">
<path
d="M7.2546 1C8.03034 -0.333333 9.96967 -0.333333 10.7454 1L17.727 13C18.5027 14.3333 17.533 16 15.9816 16H2.01842C0.466953 16 -0.502711 14.3333 0.27302 13L7.2546 1Z"
fill="inherit"
fillOpacity="0.16"
stroke="none"
/>
<rect
x="8"
y="4"
width="2"
height="6"
rx="1"
fill="inherit"
fillOpacity="0.92"
stroke="none"
className={tcls(
'animate-[wag_4s_ease_infinite_forwards]',
'[animation-composition:accumulate]',
'origin-[9px_12.5px]',
'will-change-transform',
)}
/>
<circle cx="9" cy="12.5" r="1.5" fill="inherit" fillOpacity="0.92" stroke="none" />
</svg>
);
}
function WarningIcon() {
return (
<svg width="16" height="18" viewBox="0 0 16 18" xmlns="http://www.w3.org/2000/svg">
<path
d="M6.9736 0.277489C7.60874 -0.0924963 8.39126 -0.0924962 9.0264 0.277489L14.9736 3.74189C15.6087 4.11187 16 4.79563 16 5.5356V12.4644C16 13.2044 15.6087 13.8881 14.9736 14.2581L9.0264 17.7225C8.39126 18.0925 7.60874 18.0925 6.9736 17.7225L1.0264 14.2581C0.391261 13.8881 0 13.2044 0 12.4644V5.5356C0 4.79563 0.391262 4.11187 1.0264 3.74189L6.9736 0.277489Z"
fill="inherit"
fillOpacity="0.16"
stroke="none"
/>
<rect
x="7"
y="4"
width="2"
height="6"
rx="1"
fill="inherit"
fillOpacity="0.8"
stroke="none"
/>
<circle
cx="8"
cy="12.5"
r="1.5"
fill="inherit"
fillOpacity="1"
stroke="none"
className={tcls('animate-[pulse_1s_ease_infinite_forwards]')}
/>
</svg>
);
}
function SuccessIcon() {
return (
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<rect width="16" height="16" rx="3" fill="inherit" fillOpacity="0.16" stroke="none" />
<path
className={tcls('animate-[stroke_8s_ease_infinite_forwards]')}
d="M4 8.5L6.5 11L12 5.5"
stroke="inherit"
fill="none"
strokeOpacity="0.8"
strokeWidth="2"
strokeLinecap="round"
pathLength="100"
/>
<path
d="M4 8.5L6.5 11L12 5.5"
stroke="inherit"
fill="none"
strokeOpacity="0.16"
strokeWidth="2"
strokeLinecap="round"
pathLength="100"
/>
</svg>
);
}
@@ -1,20 +1,5 @@
import {
Edit,
Github,
Gitlab,
Maximize,
X,
Mail,
Settings,
Search,
Delete,
Star,
AlertTriangle,
Link,
Eye,
Lock,
} from '@geist-ui/icons';
import { ContentKitContext, DocumentBlockIntegration } from '@gitbook/api';
import { Icon } from '@gitbook/icons';
import { ContentKit, ContentKitOutput, ContentKitServerContext } from '@gitbook/react-contentkit';
import { ignoreAPIError, renderIntegrationUi } from '@/lib/api';
@@ -27,21 +12,21 @@ import { PlainCodeBlock } from '../CodeBlock';
const outputContext: ContentKitServerContext = {
icons: {
maximize: Maximize,
edit: Edit,
github: Github,
gitlab: Gitlab,
close: X,
email: Mail,
settings: Settings,
search: Search,
delete: Delete,
star: Star,
warning: AlertTriangle,
link: Link,
'link-external': Link,
eye: Eye,
lock: Lock,
maximize: (props) => <Icon icon="maximize" {...props} />,
edit: (props) => <Icon icon="edit" {...props} />,
github: (props) => <Icon icon="github" {...props} />,
gitlab: (props) => <Icon icon="gitlab" {...props} />,
close: (props) => <Icon icon="x" {...props} />,
email: (props) => <Icon icon="envelope" {...props} />,
settings: (props) => <Icon icon="gear" {...props} />,
search: (props) => <Icon icon="magnifying-glass" {...props} />,
delete: (props) => <Icon icon="trash" {...props} />,
star: (props) => <Icon icon="star" {...props} />,
warning: (props) => <Icon icon="triangle-exclamation" {...props} />,
link: (props) => <Icon icon="link" {...props} />,
'link-external': (props) => <Icon icon="arrow-up-right-from-square" {...props} />,
eye: (props) => <Icon icon="eye" {...props} />,
lock: (props) => <Icon icon="lock" {...props} />,
},
codeBlock: (props) => {
return <PlainCodeBlock code={props.code} syntax={props.syntax} />;
@@ -7,7 +7,7 @@ import { tcls } from '@/lib/tailwind';
import { BlockProps } from './Block';
import { InlineProps } from './Inline';
const mathJaxUrl = getStaticFileURL('mathjax@3.2.2/tex-chtml.js');
const assetsUrl = getStaticFileURL('math');
export async function BlockMath(props: BlockProps<DocumentBlockMath>) {
const { block, style } = props;
@@ -17,7 +17,7 @@ export async function BlockMath(props: BlockProps<DocumentBlockMath>) {
formula={block.data.formula}
inline={false}
className={tcls(style, 'overflow-x-auto')}
mathJaxUrl={mathJaxUrl}
assetsUrl={assetsUrl}
/>
);
}
@@ -25,5 +25,5 @@ export async function BlockMath(props: BlockProps<DocumentBlockMath>) {
export async function InlineMath(props: InlineProps<DocumentInlineMath>) {
const { inline } = props;
return <MathFormula formula={inline.data.formula} inline={true} mathJaxUrl={mathJaxUrl} />;
return <MathFormula formula={inline.data.formula} inline={true} assetsUrl={assetsUrl} />;
}
@@ -1,5 +1,5 @@
import { ChevronDown, ChevronRight } from '@geist-ui/icons';
import { DocumentBlockSwagger } from '@gitbook/api';
import { Icon } from '@gitbook/icons';
import { OpenAPIOperation } from '@gitbook/react-openapi';
import React from 'react';
@@ -55,8 +55,8 @@ async function OpenAPIBody(props: BlockProps<DocumentBlockSwagger>) {
data={data}
context={{
icons: {
chevronDown: <ChevronDown />,
chevronRight: <ChevronRight />,
chevronDown: <Icon icon="chevron-down" />,
chevronRight: <Icon icon="chevron-right" />,
},
CodeBlock: PlainCodeBlock,
defaultInteractiveOpened: context.mode === 'print',
@@ -346,7 +346,7 @@
}
.openapi-section-toggle svg {
@apply size-4;
@apply size-3;
}
/** Markdown */
@@ -1,5 +1,5 @@
import IconStar from '@geist-ui/icons/star';
import { ContentRef, DocumentBlockTable } from '@gitbook/api';
import { Icon } from '@gitbook/icons';
import assertNever from 'assert-never';
import { Checkbox, Emoji } from '@/components/primitives';
@@ -54,12 +54,13 @@ export async function RecordColumnValue<Tag extends React.ElementType = 'div'>(
<>
<span className={tcls('inline-flex', 'grid-area-1-1', 'gap-0.5')}>
{Array.from({ length: max }).map((_, i) => (
<IconStar
<Icon
key={i}
icon="star"
className={tcls(
'size-[15px]',
'stroke-primary-700/5',
'dark:stroke-primary-300/5',
'text-primary-700/5',
'dark:text-primary-300/5',
)}
/>
))}
@@ -73,9 +74,10 @@ export async function RecordColumnValue<Tag extends React.ElementType = 'div'>(
className={tcls('inline-flex', 'grid-area-1-1', 'gap-0.5')}
>
{Array.from({ length: rating }).map((_, i) => (
<IconStar
<Icon
key={i}
className={tcls('size-[15px]', 'stroke-primary')}
icon="star"
className={tcls('size-[15px]', 'text-primary')}
/>
))}
</span>
@@ -157,7 +159,10 @@ export async function RecordColumnValue<Tag extends React.ElementType = 'div'>(
priority="lazy"
/>
) : (
<FileIcon contentType={contentType} />
<FileIcon
contentType={contentType}
className={tcls('size-4')}
/>
)}
{ref.text}
</StyledLink>
@@ -1,4 +1,4 @@
import IconChevronDown from '@geist-ui/icons/chevronDown';
import { Icon } from '@gitbook/icons';
import { DetailedHTMLProps, HTMLAttributes, useId } from 'react';
import { tcls } from '@/lib/tailwind';
@@ -80,11 +80,11 @@ export function Dropdown<E extends HTMLElement>(props: {
*/
export function DropdownChevron(props: {}) {
return (
<IconChevronDown
<Icon
icon="chevron-down"
className={tcls(
'opacity-6',
'w-4',
'h-4',
'size-3',
'ms-1',
'transition-transform',
'group-hover/dropdown:rotate-180',
@@ -110,11 +110,11 @@ export function Header(props: {
'text-header-link/8',
'ring-header-background-200/5',
'[&>span]:text-header-link/7',
'[&_svg]:stroke-header-link',
'[&_svg]:text-header-link',
'dark:bg-header-link-600/3',
'dark:ring-header-link-600/2',
'dark:text-header-link/7',
'dark:[&_svg]:stroke-header-link/7',
'dark:[&_svg]:text-header-link/7',
]
: null
}
@@ -8,13 +8,13 @@ import {
} from '@gitbook/api';
import { HeaderMobileMenu } from '@/components/Header/HeaderMobileMenu';
import { LogoIcon } from '@/components/icons';
import { Image } from '@/components/utils';
import { absoluteHref } from '@/lib/links';
import { tcls } from '@/lib/tailwind';
import { getContentTitle } from '@/lib/utils';
import { Link } from '../primitives';
import { SpaceIcon } from '../Space/SpaceIcon';
interface HeaderLogoProps {
parent: Site | Collection | null;
@@ -30,7 +30,7 @@ export function HeaderLogo(props: HeaderLogoProps) {
const { customization } = props;
return (
<div className={tcls('flex', 'flex-row', 'gap-3')}>
<div className={tcls('flex', 'flex-row', 'gap-2')}>
<HeaderMobileMenu
className={tcls(
'lg:hidden',
@@ -100,7 +100,7 @@ function LogoFallback(props: HeaderLogoProps) {
const customEmoji = 'emoji' in customization.favicon ? customization.favicon.emoji : undefined;
return (
<>
<LogoIcon
<SpaceIcon
icon={customIcon}
emoji={customEmoji}
alt=""
@@ -1,9 +1,9 @@
'use client';
import { Icon } from '@gitbook/icons';
import { usePathname } from 'next/navigation';
import { useEffect, useState } from 'react';
import { IconMenu } from '@/components/icons/IconMenu';
import { useLanguage, tString } from '@/intl/client';
import { tcls } from '@/lib/tailwind';
@@ -53,19 +53,20 @@ export function HeaderMobileMenu(props: Partial<React.ButtonHTMLAttributes<HTMLB
{...props}
aria-label={tString(language, 'table_of_contents_button_label')}
onClick={toggleNavigation}
className={tcls(
'flex',
'flex-row',
'items-center',
'hover:bg-dark/3',
'py-1',
'px-2',
'dark:hover:bg-light/2',
'rounded',
'straight-corners:rounded-sm',
props.className,
)}
>
<IconMenu
className={tcls(
'w-7',
'h-7',
'rounded',
'straight-corners:rounded-sm',
'text-inherit',
'hover:bg-dark/3',
'p-[0.25rem]',
'dark:hover:bg-light/2',
)}
/>
<Icon icon="bars" className={tcls('size-4', 'text-inherit')} />
</button>
);
}
@@ -1,7 +1,3 @@
import { Menu } from '@geist-ui/icons';
import DownloadCloud from '@geist-ui/icons/downloadCloud';
import Github from '@geist-ui/icons/github';
import Gitlab from '@geist-ui/icons/gitlab';
import {
CustomizationSettings,
JSONDocument,
@@ -10,6 +6,7 @@ import {
SiteCustomizationSettings,
Space,
} from '@gitbook/api';
import { Icon } from '@gitbook/icons';
import React from 'react';
import urlJoin from 'url-join';
@@ -97,7 +94,7 @@ export async function PageAside(props: {
'py-2',
)}
>
<Menu className={tcls('size-4')} />
<Icon icon="bars" className={tcls('size-3')} />
{t(language, 'on_this_page')}
</div>
<div
@@ -147,11 +144,14 @@ export async function PageAside(props: {
'dark:text-light/5',
)}
>
{space.gitSync.installationProvider === 'gitlab' ? (
<Gitlab className={tcls('size-4', 'mr-1.5')} />
) : (
<Github className={tcls('size-4', 'mr-1.5')} />
)}
<Icon
icon={
space.gitSync.installationProvider === 'gitlab'
? 'gitlab'
: 'github'
}
className={tcls('size-4', 'mr-1.5')}
/>
{t(language, 'edit_on_git', getGitSyncName(space))}
</a>
</div>
@@ -176,7 +176,7 @@ export async function PageAside(props: {
'dark:text-light/5',
)}
>
<DownloadCloud className={tcls('size-4', 'mr-1.5')} />
<Icon icon="file-pdf" className={tcls('size-4', 'mr-1.5')} />
{t(language, 'pdf_download')}
</a>
</div>
@@ -1,5 +1,3 @@
import ChevronLeft from '@geist-ui/icons/chevronLeft';
import ChevronRight from '@geist-ui/icons/chevronRight';
import {
CustomizationSettings,
Revision,
@@ -7,6 +5,7 @@ import {
SiteCustomizationSettings,
Space,
} from '@gitbook/api';
import { Icon, IconName } from '@gitbook/icons';
import React from 'react';
import { t, getSpaceLanguage } from '@/intl/server';
@@ -44,7 +43,7 @@ export function PageFooterNavigation(props: {
>
{previous ? (
<NavigationCard
icon={ChevronLeft}
icon="chevron-left"
label={t(language, 'previous_page')}
title={previous.title}
href={pageHref(pages, previous)}
@@ -53,7 +52,7 @@ export function PageFooterNavigation(props: {
) : null}
{next ? (
<NavigationCard
icon={ChevronRight}
icon="chevron-right"
label={t(language, 'next_page')}
title={next.title}
href={pageHref(pages, next)}
@@ -64,13 +63,13 @@ export function PageFooterNavigation(props: {
}
function NavigationCard(props: {
icon: React.FunctionComponent<{ className?: string }>;
icon: IconName;
label: React.ReactNode;
title: string;
href: string;
reversed?: boolean;
}) {
const { icon: IconCo, label, title, href, reversed } = props;
const { icon, label, title, href, reversed } = props;
return (
<Link
@@ -111,14 +110,14 @@ function NavigationCard(props: {
{title}
</span>
</span>
<IconCo
<Icon
icon={icon}
className={tcls(
'hidden',
'w-5',
'h-5',
'stroke-dark/5',
'group-hover:stroke-primary',
'dark:stroke-light/4',
'size-4',
'text-dark/5',
'group-hover:text-primary',
'dark:text-light/4',
'md:block',
)}
/>
@@ -1,5 +1,4 @@
import IconBox from '@geist-ui/icons/box';
import IconSearch from '@geist-ui/icons/search';
import { Icon } from '@gitbook/icons';
import React from 'react';
import { atom, useRecoilState } from 'recoil';
@@ -187,14 +186,9 @@ function AnswerFollowupQuestions(props: { followupQuestions: string[] }) {
ask: true,
})}
>
<IconSearch
className={tcls(
'w-[15px]',
'h-[15px]',
'shrink-0',
'mt-0.5',
'[&>path]:[stroke-opacity:0.64]',
)}
<Icon
icon="magnifying-glass"
className={tcls('size-[15px]', 'shrink-0', 'mt-0.5', '[opacity:0.64]')}
/>
<span>{question}</span>
</Link>
@@ -242,15 +236,16 @@ function AnswerSources(props: {
href={source.href}
prefetch={false}
>
<IconBox
<Icon
icon="arrow-up-right"
className={tcls(
'stroke-dark/6',
'text-dark/6',
'w-[15px]',
'h-[15px]',
'shrink-0',
'mt-0.5',
'mr-0.5',
'dark:stroke-light/6',
'dark:text-light/6',
)}
/>
{source.title}
@@ -1,6 +1,6 @@
'use client';
import IconSearch from '@geist-ui/icons/search';
import { Icon } from '@gitbook/icons';
import { useEffect, useState } from 'react';
import { useLanguage, tString } from '@/intl/client';
@@ -65,7 +65,7 @@ export function SearchButton(props: { children?: React.ReactNode; style?: ClassV
)}
>
<div className={tcls('text-dark/7', 'pt-1.5', 'pb-2', 'dark:text-light/7')}>
<IconSearch className={tcls('shrink-0', 'w-5', 'h-5')} />
<Icon icon="magnifying-glass" className={tcls('shrink-0', 'size-4')} />
</div>
{children}
<Shortcut />
@@ -1,7 +1,7 @@
'use client';
import IconSearch from '@geist-ui/icons/search';
import { Collection, Site } from '@gitbook/api';
import { Icon } from '@gitbook/icons';
import { AnimatePresence, motion } from 'framer-motion';
import { useRouter } from 'next/navigation';
import React from 'react';
@@ -198,8 +198,11 @@ function SearchModalBody(
}}
>
<div className={tcls('flex', 'flex-row', 'items-center')}>
<div className={tcls('text-dark/4', 'p-3', 'dark:text-light/5')}>
<IconSearch className={tcls('w-6', 'h-6')} />
<div className={tcls('p-2', 'pl-4')}>
<Icon
icon="magnifying-glass"
className={tcls('size-4', 'text-dark/4', 'dark:text-light/5')}
/>
</div>
<div className={tcls('flex-1')}>
<input
@@ -1,4 +1,4 @@
import IconSearch from '@geist-ui/icons/search';
import { Icon } from '@gitbook/icons';
import React from 'react';
import { t, useLanguage } from '@/intl/client';
@@ -44,15 +44,16 @@ export const SearchQuestionResultItem = React.forwardRef(function SearchQuestion
query: question,
})}
>
<IconSearch
<Icon
icon="magnifying-glass"
className={tcls(
'w-[15px]',
'h-[15px]',
'shrink-0',
'mt-0.5',
'mr-2',
'stroke-dark/5',
'dark:stroke-light/5',
'mr-4',
'text-dark/5',
'dark:text-light/5',
)}
/>
{recommended ? question : t(language, 'search_ask', [question])}
@@ -5,7 +5,10 @@ import { absoluteHref } from '@/lib/links';
import { Emoji } from '../primitives';
export function LogoIcon(
/**
* Icon for a space.
*/
export function SpaceIcon(
props: { icon?: CustomizationThemedURL; emoji?: string } & Omit<
React.ComponentProps<typeof Image>,
'sources'
@@ -1,5 +1,5 @@
import IconExternal from '@geist-ui/icons/externalLink';
import { RevisionPageLink } from '@gitbook/api';
import { Icon } from '@gitbook/icons';
import { Emoji, Link } from '@/components/primitives';
import { ContentRefContext, resolveContentRef } from '@/lib/references';
@@ -37,19 +37,19 @@ export async function PageLinkItem(props: { page: RevisionPageLink; context: Con
>
{page.emoji ? <Emoji code={page.emoji} /> : null}
{page.title}
<IconExternal
<Icon
icon="arrow-up-right-from-square"
className={tcls(
'w-3',
'h-3',
'size-3',
'mr-1',
'mt-1',
'place-self-start',
'shrink-0',
'stroke-current',
'text-current',
'transition-colors',
'[&>path]:transition-[stroke-opacity]',
'[&>path]:[stroke-opacity:0.40]',
'group-hover:[&>path]:[stroke-opacity:1]',
'[&>path]:transition-[opacity]',
'[&>path]:[opacity:0.40]',
'group-hover:[&>path]:[opacity:1]',
)}
/>
</Link>
@@ -1,6 +1,6 @@
'use client';
import IconChevronRight from '@geist-ui/icons/chevronRight';
import { Icon } from '@gitbook/icons';
import { motion, stagger, useAnimate } from 'framer-motion';
import { useSelectedLayoutSegment } from 'next/navigation';
import React from 'react';
@@ -170,18 +170,18 @@ export function ToggleableLinkItem(props: {
setIsVisible((prev) => !prev);
}}
>
<IconChevronRight
<Icon
icon="chevron-right"
className={tcls(
'grid',
'flex-shrink-0',
'w-5',
'h-5',
'p-0.5',
'[&>path]:transition-[stroke-opacity]',
'size-3',
'm-1',
'transition-[opacity]',
'text-current',
'transition-transform',
'[&>path]:[stroke-opacity:0.40]',
'group-hover:[&>path]:[stroke-opacity:1]',
'[opacity:0.40]',
'group-hover:[opacity:1]',
isVisible ? ['rotate-90'] : ['rotate-0'],
)}
@@ -1,10 +1,9 @@
import { CustomizationSettings, SiteCustomizationSettings, Space } from '@gitbook/api';
import { Icon } from '@gitbook/icons';
import { t, getSpaceLanguage } from '@/intl/server';
import { tcls } from '@/lib/tailwind';
import { IconLogo } from '../icons/IconLogo';
/**
* Trademark link to the GitBook.
*/
@@ -100,7 +99,7 @@ export function TrademarkLink(props: {
'dark:border-light/2',
)}
>
<IconLogo className={tcls('w-5', 'h-5', 'mr-3')} />
<Icon icon="gitbook" className={tcls('size-5', 'mr-3')} />
{t(language, 'powered_by_gitbook')}
</a>
);
@@ -1,12 +1,9 @@
'use client';
import Monitor from '@geist-ui/icons/monitor';
import Moon from '@geist-ui/icons/moon';
import Sun from '@geist-ui/icons/sun';
import { Icon, IconName } from '@gitbook/icons';
import { useTheme } from 'next-themes';
import React from 'react';
import { IconComponent } from '@/components/icons';
import { tString, useLanguage } from '@/intl/client';
import { tcls } from '@/lib/tailwind';
@@ -44,19 +41,19 @@ export function ThemeToggler(props: {}) {
>
<ThemeButton
active={mounted && theme === 'light'}
icon={Sun}
icon="sun-bright"
onClick={() => onSwitchMode('light')}
title={tString(language, 'switch_to_light_theme')}
/>
<ThemeButton
active={mounted && theme === 'system'}
icon={Monitor}
icon="desktop"
onClick={() => onSwitchMode('system')}
title={tString(language, 'switch_to_system_theme')}
/>
<ThemeButton
active={mounted && theme === 'dark'}
icon={Moon}
icon="moon"
onClick={() => onSwitchMode('dark')}
title={tString(language, 'switch_to_dark_theme')}
/>
@@ -65,12 +62,12 @@ export function ThemeToggler(props: {}) {
}
function ThemeButton(props: {
icon: IconComponent;
icon: IconName;
onClick: () => void;
title: string;
active: boolean;
}) {
const { icon: Icon, onClick, title, active } = props;
const { icon, onClick, title, active } = props;
return (
<button
type="button"
@@ -90,10 +87,10 @@ function ThemeButton(props: {
)}
>
<Icon
icon={icon}
className={tcls(
'w-4',
'h-4',
active ? ['stroke-primary-600', 'dark:stroke-primary-400'] : null,
'size-4',
active ? ['text-primary-600', 'dark:text-primary-400'] : null,
)}
/>
</button>
@@ -1,20 +0,0 @@
import { SVGProps } from 'react';
export function IconArrowLeft(props: Partial<SVGProps<SVGSVGElement>>) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 16 16"
preserveAspectRatio="xMidYMid meet"
{...props}
>
<path
fill="currentColor"
fillRule="evenodd"
d="M6.924 3.576a.6.6 0 0 1 0 .848L3.95 7.4H13.5a.6.6 0 1 1 0 1.2H3.949l2.975 2.976a.6.6 0 0 1-.848.848l-4-4a.6.6 0 0 1 0-.848l4-4a.6.6 0 0 1 .848 0Z"
clipRule="evenodd"
/>
</svg>
);
}
@@ -1,20 +0,0 @@
import { SVGProps } from 'react';
export function IconArrowRight(props: Partial<SVGProps<SVGSVGElement>>) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 16 16"
preserveAspectRatio="xMidYMid meet"
{...props}
>
<path
fill="currentColor"
fillRule="evenodd"
d="M9.076 3.576a.6.6 0 0 1 .848 0l4 4a.6.6 0 0 1 0 .848l-4 4a.6.6 0 0 1-.848-.848L12.052 8.6H2.5a.6.6 0 0 1 0-1.2h9.552L9.076 4.424a.6.6 0 0 1 0-.848Z"
clipRule="evenodd"
/>
</svg>
);
}
@@ -1,20 +0,0 @@
import { SVGProps } from 'react';
export function IconChevronDown(props: Partial<SVGProps<SVGSVGElement>>) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 16 16"
preserveAspectRatio="xMidYMid meet"
{...props}
>
<path
fill="currentColor"
fillRule="evenodd"
d="M12.424 5.576a.6.6 0 0 1 0 .848l-4 4a.6.6 0 0 1-.848 0l-4-4a.6.6 0 0 1 .848-.848L8 9.15l3.576-3.575a.6.6 0 0 1 .848 0Z"
clipRule="evenodd"
/>
</svg>
);
}
@@ -1,20 +0,0 @@
import { SVGProps } from 'react';
export function IconChevronRight(props: Partial<SVGProps<SVGSVGElement>>) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 16 16"
preserveAspectRatio="xMidYMid meet"
{...props}
>
<path
fill="currentColor"
fillRule="evenodd"
d="M5.576 3.576a.6.6 0 0 1 .848 0l4 4a.6.6 0 0 1 0 .848l-4 4a.6.6 0 0 1-.848-.848L9.15 8 5.576 4.424a.6.6 0 0 1 0-.848Z"
clipRule="evenodd"
/>
</svg>
);
}
@@ -1,20 +0,0 @@
import { SVGProps } from 'react';
export function IconLogo(props: Partial<SVGProps<SVGSVGElement>>) {
return (
<svg
width="32"
height="32"
viewBox="0 0 32 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="xMidYMid meet"
{...props}
>
<path
d="M13.4107 16.7783C14.9704 17.6796 15.7503 18.1302 16.6069 18.131C17.4635 18.1317 18.2441 17.6824 19.8054 16.7839L29.7371 11.0678C30.1861 10.8093 30.4629 10.3306 30.4629 9.8125C30.4629 9.29436 30.1861 8.81569 29.7371 8.55723L19.8018 2.83907C18.2422 1.94146 17.4624 1.49265 16.6067 1.49298C15.7509 1.49332 14.9714 1.94273 13.4125 2.84156L4.87619 7.76347C4.80701 7.80336 4.77242 7.82331 4.74019 7.84222C1.82668 9.55246 0.0265912 12.6682 0.000290907 16.0465C0 16.0839 0 16.1238 0 16.2037C0 16.2834 0 16.3233 0.00029028 16.3606C0.0265326 19.7351 1.82261 22.848 4.73092 24.5595C4.76309 24.5785 4.79761 24.5984 4.86666 24.6384L10.2053 27.7246C13.3292 29.5305 14.8912 30.4334 16.6068 30.434C18.3224 30.4346 19.885 29.5327 23.0101 27.7289L28.6521 24.4724C30.2141 23.5708 30.9951 23.12 31.4239 22.3774C31.8528 21.6348 31.8528 20.733 31.8528 18.9294V16.225V15.435C31.8528 14.9349 31.5821 14.4741 31.1453 14.2305C30.722 13.9945 30.2058 13.998 29.7858 14.2397L18.2016 20.9069C17.423 21.3551 17.0337 21.5791 16.6064 21.5792C16.1791 21.5794 15.7897 21.3556 15.0108 20.9079L7.17309 16.4033C6.77918 16.1769 6.58223 16.0637 6.42404 16.0433C6.06444 15.997 5.71866 16.1984 5.58141 16.534C5.52103 16.6816 5.52225 16.9087 5.52469 17.3631C5.52648 17.6972 5.52738 17.8642 5.55865 18.0179C5.62846 18.3609 5.80888 18.6716 6.07224 18.9023C6.19019 19.0057 6.33483 19.0892 6.62409 19.2564L15.0064 24.1003C15.7873 24.5516 16.1777 24.7772 16.6065 24.7773C17.0354 24.7775 17.4259 24.552 18.2071 24.1012L28.4815 18.1713C28.7482 18.0174 28.8815 17.9404 28.9815 17.9982C29.0815 18.0559 29.0815 18.2098 29.0815 18.5177V20.1011C29.0815 20.552 29.0815 20.7774 28.9743 20.9631C28.867 21.1488 28.6718 21.2614 28.2813 21.4868L19.809 26.3766C18.2461 27.2787 17.4647 27.7297 16.6067 27.7293C15.7487 27.7289 14.9677 27.2772 13.4056 26.3737L5.48222 21.791C5.45373 21.7745 5.43949 21.7663 5.4262 21.7585C3.76652 20.786 2.74242 19.0106 2.73155 17.087C2.73146 17.0716 2.73146 17.0552 2.73146 17.0223V15.5668C2.73146 14.5041 3.29715 13.5217 4.21629 12.9883C5.02979 12.5161 6.03367 12.5152 6.84804 12.9858L13.4107 16.7783Z"
fill="currentColor"
/>
</svg>
);
}
@@ -1,19 +0,0 @@
import { SVGProps } from 'react';
export function IconMenu(props: Partial<SVGProps<SVGSVGElement>>) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
viewBox="0 0 24 24"
preserveAspectRatio="xMidYMid meet"
{...props}
>
<path d="M3 12h18M3 6h18M3 18h18"></path>
</svg>
);
}
@@ -1,26 +0,0 @@
import { SVGProps } from 'react';
export function IconSearch(props: Partial<SVGProps<SVGSVGElement>>) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
preserveAspectRatio="xMidYMid meet"
{...props}
>
<path
fill="currentColor"
fillRule="evenodd"
d="M10.5 4a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM2 10.5a8.5 8.5 0 1 1 17 0 8.5 8.5 0 0 1-17 0Z"
clipRule="evenodd"
/>
<path
fill="currentColor"
fillRule="evenodd"
d="M15.093 15.093a1 1 0 0 1 1.414 0l5.2 5.2a1 1 0 0 1-1.414 1.414l-5.2-5.2a1 1 0 0 1 0-1.414Z"
clipRule="evenodd"
/>
</svg>
);
}
@@ -1,2 +0,0 @@
export * from './types';
export * from './LogoIcon';
@@ -1,3 +0,0 @@
export type IconProps = React.SVGProps<SVGElement>;
export type IconComponent = React.FunctionComponent<IconProps>;
@@ -1,4 +1,4 @@
import ChevronRight from '@geist-ui/icons/chevronRight';
import { Icon } from '@gitbook/icons';
import { ClassValue, tcls } from '@/lib/tailwind';
@@ -61,15 +61,15 @@ export async function Card(props: {
</span>
) : null}
</span>
<ChevronRight
<Icon
icon="chevron-right"
className={tcls(
'w-4',
'h-4',
'stroke-dark/7',
'size-3',
'text-dark/7',
'transition-all',
'group-hover:translate-x-0.5',
'group-hover:stroke-primary/8',
'dark:stroke-light/6',
'group-hover:text-primary/8',
'dark:text-light/6',
)}
/>
</Link>
@@ -1,6 +1,6 @@
'use client';
import Check from '@geist-ui/icons/check';
import { Icon } from '@gitbook/icons';
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
import React from 'react';
@@ -19,7 +19,7 @@ export const Checkbox = React.forwardRef<
'shrink-0',
'rounded-sm',
'ring-1',
'bg-primary-300/3',
'bg-primary-300/1',
'ring-dark/3',
'ring-inset',
'grid',
@@ -46,7 +46,7 @@ export const Checkbox = React.forwardRef<
'dark:text-primary-200',
)}
>
<Check size={12} />
{props.checked ? <Icon icon="check" className={'size-3'} /> : null}
</CheckboxPrimitive.Indicator>
<div
className={tcls(
@@ -60,7 +60,7 @@ export const Checkbox = React.forwardRef<
'dark:text-light/2',
)}
>
<Check size={12} />
{props.checked ? <Icon icon="check" className={'size-3'} /> : null}
</div>
</CheckboxPrimitive.Root>
));
@@ -1,6 +1,6 @@
'use client';
import IconMinimize from '@geist-ui/icons/minimize';
import { Icon } from '@gitbook/icons';
import classNames from 'classnames';
import React from 'react';
import ReactDOM from 'react-dom';
@@ -257,7 +257,7 @@ function ZoomImageModal(props: {
)}
onClick={onClose}
>
<IconMinimize />
<Icon icon="compress-wide" className={tcls('size-5')} />
</button>
</div>
);
+6 -2
View File
@@ -29,6 +29,10 @@ export function createContentSecurityPolicyNonce(): string {
* Generate a Content Security Policy header for a space.
*/
export function getContentSecurityPolicy(scripts: SpaceIntegrationScript[], nonce: string): string {
const iconsAssetsSrc = process.env.GITBOOK_ICONS_URL
? new URL(process.env.GITBOOK_ICONS_URL).origin
: '';
// We need to allow loading any image or download any file
// to support image and OpenAPI blocks where the content reference could be external.
//
@@ -37,8 +41,8 @@ export function getContentSecurityPolicy(scripts: SpaceIntegrationScript[], nonc
default-src 'self' ${assetsDomain};
script-src 'self' 'nonce-${nonce}' 'strict-dynamic' 'unsafe-inline' 'unsafe-eval' ${assetsDomain} https://integrations.gitbook.com https://cdn.iframe.ly;
style-src 'self' ${assetsDomain} fonts.googleapis.com 'unsafe-inline';
img-src * 'self' blob: data: files.gitbook.com ${assetsDomain};
connect-src * 'self' integrations.gitbook.com app.gitbook.com api.gitbook.com srv.buysellads.com ${assetsDomain};
img-src * 'self' blob: data: files.gitbook.com ${assetsDomain} ${iconsAssetsSrc};
connect-src * 'self' integrations.gitbook.com app.gitbook.com api.gitbook.com srv.buysellads.com ${assetsDomain} ${iconsAssetsSrc};
font-src 'self' fonts.gstatic.com ${assetsDomain};
frame-src *;
object-src 'none';
+1 -1
View File
@@ -21,5 +21,5 @@ export function getContentTitle(
}
// Otherwise the legacy behavior is not changed to avoid regressions
return parent ? parent.title : customization.title ?? space.title;
return parent ? parent.title : (customization.title ?? space.title);
}
+2 -2
View File
@@ -443,10 +443,10 @@ async function lookupSpaceInMultiIdMode(request: NextRequest, url: URL): Promise
apiToken: url.searchParams.get(AUTH_TOKEN_QUERY) ?? '',
apiEndpoint: url.searchParams.get(API_ENDPOINT_QUERY) ?? undefined,
}
: decodeGitBookTokenCookie(spaceId, request.cookies.get(cookieName)?.value) ?? {
: (decodeGitBookTokenCookie(spaceId, request.cookies.get(cookieName)?.value) ?? {
apiToken: undefined,
apiEndpoint: undefined,
};
});
if (!apiToken) {
return {
+2
View File
@@ -0,0 +1,2 @@
dist/
src/data/*.json
+11
View File
@@ -0,0 +1,11 @@
# `@gitbook/icons`
Icon sets useed in GitBook content.
## Usage
```tsx
import { Icon } from '@gitbook/icons';
<Icon name="x" className={'size-5'} />;
```
+72
View File
@@ -0,0 +1,72 @@
import fs from 'fs/promises';
import { existsSync } from 'fs';
import path from 'path';
import url from 'url';
import { getKitPath } from './kit.js';
/**
* Scripts to generate the list of all icons.
*/
async function main() {
const source = getKitPath();
const icons = JSON.parse(
await fs.readFile(path.join(source, 'icons/metadata/icon-families.json'), 'utf8'),
);
// Only these families have exceptions
const potentialOnly = ['brands', 'custom-icons'];
const keyRename = {
// Font Awesome stores custom icons under "custom-icons"
// but indicates them as svg.kit.custom in the JSON data
'kit-custom': 'custom-icons',
};
const onlyStyles = {};
const result = [];
Object.entries(icons).forEach(([icon, iconSpec]) => {
const stylesCovered = [];
Object.entries(iconSpec.svgs).forEach(([family, familyEntries]) => {
Object.keys(familyEntries).forEach((style) => {
let key = family !== 'classic' ? `${family}-${style}` : style;
key = keyRename[key] ?? key;
stylesCovered.push(key);
});
});
potentialOnly.forEach((style) => {
if (stylesCovered.includes(style)) {
onlyStyles[style] = onlyStyles[style] || [];
onlyStyles[style].push(icon);
}
});
result.push({
icon,
label: iconSpec.label,
search: iconSpec.search?.terms,
});
});
await Promise.all([
writeDataFile('styles-map', JSON.stringify(onlyStyles, null, 2)),
writeDataFile('icons', JSON.stringify(result, null, 2)),
]);
console.log(`🎉 ${result.length} icons found`);
}
async function writeDataFile(name, content) {
const dirname = path.dirname(url.fileURLToPath(import.meta.url));
await Promise.all([
fs.writeFile(path.resolve(dirname, `../src/data/${name}.json`), content),
// Write to dist folder if it exists
existsSync(path.resolve(dirname, '../dist/'))
? fs.writeFile(path.resolve(dirname, `../dist/data/${name}.json`), content)
: null,
]);
}
main().catch(console.error);
+49
View File
@@ -0,0 +1,49 @@
#!/usr/bin/env node
import fs from 'fs/promises';
import path from 'path';
import { getKitPath } from './kit.js';
const allStyles = ['brands', 'duotone', 'solid', 'regular', 'light', 'thin', 'custom-icons'];
/**
* Scripts to copy the assets to a public folder.
*/
async function main() {
const outputFolder = path.resolve(process.cwd(), process.argv[2] ?? 'public/icons');
const stylesToCopy = (process.argv[3] ? process.argv[3].split(',') : allStyles).filter(
(style) => allStyles.includes(style),
);
const source = getKitPath();
// Create the output folder if it doesn't exist
await fs.mkdir(outputFolder, { recursive: true });
const printOutputFolder = path.relative(process.cwd(), outputFolder);
console.log(`🚚 Copying icons of styles ${stylesToCopy.join(', ')} to ${printOutputFolder}`);
// Copy the assets from
// source/sprites to outputFolder/sprites
// source/svgs to outputFolder/svgs
await Promise.all([
...stylesToCopy.map((style) =>
fs.cp(
path.join(source, `icons/svgs/${style}`),
path.join(outputFolder, 'svgs', style),
{
recursive: true,
},
),
),
...stylesToCopy.map((style) =>
fs.cp(
path.join(source, `icons/sprites/${style}.svg`),
path.join(outputFolder, 'sprites', style + '.svg'),
),
),
]);
console.log(`🎉 Icons copied to ${printOutputFolder}`);
}
main().catch(console.error);
+20
View File
@@ -0,0 +1,20 @@
import path from 'path';
import url from 'url';
/**
* Get the path to the kit, depending on the Pro or Free version.
*/
export function getKitPath() {
let source = path.dirname(
url.fileURLToPath(import.meta.resolve('@fortawesome/fontawesome-free/package.json')),
);
try {
source = path.dirname(
url.fileURLToPath(import.meta.resolve('@awesome.me/kit-a463935e93/package.json')),
);
} catch (error) {
console.warn('⚠️ Could not find the Pro kit, using the free kit instead');
}
return source;
}
+50
View File
@@ -0,0 +1,50 @@
{
"name": "@gitbook/icons",
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"development": "./src/index.ts",
"default": "./dist/index.js"
},
"./icons": {
"types": "./dist/icons.d.ts",
"development": "./src/icons.ts",
"default": "./dist/icons.js"
},
"./style.css": {
"default": "./src/style.css"
}
},
"version": "0.0.3",
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.6.0",
"@fortawesome/fontawesome-free": "^6.6.0"
},
"optionalDependencies": {
"@awesome.me/kit-a463935e93": "1.0.8"
},
"devDependencies": {
"typescript": "^5.5.3"
},
"peerDependencies": {
"react": "*"
},
"scripts": {
"generate": "node ./bin/gen-list.js",
"build": "tsc",
"typecheck": "tsc --noEmit",
"dev": "tsc -w"
},
"bin": {
"gitbook-icons": "./bin/gitbook-icons.js"
},
"files": [
"dist",
"src",
"bin",
"data",
"README.md",
"CHANGELOG.md"
]
}
+70
View File
@@ -0,0 +1,70 @@
'use client';
import * as React from 'react';
import { IconName, IconStyle } from './types';
import { getIconStyle } from './getIconStyle';
import { getIconAssetURL, useIcons } from './IconsProvider';
/**
* Props for the icon component.
*/
export type IconProps = React.SVGProps<SVGSVGElement> & {
/**
* Name of the icon to render.
*/
icon: IconName;
/**
* Style of the icon to render.
* @default 'solid'
*/
iconStyle?: IconStyle;
/**
* Class name to apply to the icon.
*/
className?: string;
/**
* Size of the icon.
* If none is defined, the size should be defined using CSS / class name.
*/
size?: number;
};
/**
* Renders an icon component from the library.
* The icon is loaded as a standalone image.
*/
export const Icon = React.forwardRef(function Icon(
props: IconProps,
ref: React.Ref<SVGSVGElement>,
) {
const context = useIcons();
const {
icon: propIcon,
iconStyle: propIconStyle = context.iconStyle,
className = '',
size,
...rest
} = props;
const [iconStyle, icon] = getIconStyle(propIconStyle, propIcon);
const url = getIconAssetURL(context, iconStyle, icon);
return (
<svg
ref={ref}
{...rest}
style={{
maskImage: `url(${url})`,
maskRepeat: 'no-repeat',
maskPosition: 'center',
...(size ? { width: size, height: size } : {}),
...rest.style,
}}
className={'gb-icon ' + className}
></svg>
);
});
+77
View File
@@ -0,0 +1,77 @@
'use client';
import * as React from 'react';
import { IconStyle } from './types';
const version = 1;
export interface IconsAssetsLocation {
/** Rroot url where the icon assets are served */
assetsURL: string;
/** Token to be passed in the URL for assets */
assetsURLToken?: string;
}
export type IconsContextType = Partial<IconsAssetsLocation> & {
/** Assets location for special styles */
assetsByStyles?: Record<string, IconsAssetsLocation>;
/** Current default style for icons */
iconStyle: IconStyle;
};
const IconsContext = React.createContext<IconsContextType>({
iconStyle: IconStyle.Regular,
});
/**
* Provider to control the loading of icons.
*/
export function IconsProvider(props: React.PropsWithChildren<Partial<IconsContextType>>) {
const parent = React.useContext(IconsContext);
const {
children,
assetsURL = parent.assetsURL,
assetsURLToken = parent.assetsURLToken,
iconStyle = parent.iconStyle,
assetsByStyles = parent.assetsByStyles,
} = props;
const value = React.useMemo(() => {
return { assetsURL, assetsURLToken, iconStyle, assetsByStyles };
}, [assetsURL, assetsURLToken, iconStyle, assetsByStyles]);
return <IconsContext.Provider value={value}>{children}</IconsContext.Provider>;
}
/**
* Hook to access the current icons context.
*/
export function useIcons(): IconsContextType {
return React.useContext(IconsContext);
}
/**
* Get the URL for an asset.
*/
export function getAssetURL(location: Partial<IconsAssetsLocation>, path: string): string {
if (!location.assetsURL) {
throw new Error('You first need to pass a assetsURL to <IconsProvider>');
}
const rawUrl =
location.assetsURL + (location.assetsURL.endsWith('/') ? '' : '/') + path + `?v=${version}`;
if (location.assetsURLToken) {
const url = new URL(rawUrl);
url.searchParams.set('token', location.assetsURLToken);
return url.toString();
} else {
return rawUrl;
}
}
/**
* Get the URL for the SVG of an icon.
*/
export function getIconAssetURL(context: IconsContextType, style: string, icon: string): string {
const location = context.assetsByStyles?.[style] ?? context;
return getAssetURL(location, `svgs/${style}/${icon}.svg`);
}
+1
View File
@@ -0,0 +1 @@
Files in this folder are generated in postinstall script.
+33
View File
@@ -0,0 +1,33 @@
import stylesMap from './data/styles-map.json';
import { IconName, IconStyle } from './types';
const cache = new Map<IconName, Map<IconStyle, [string, IconName]>>();
/**
* Return the style to load an icon from by its name.
* Some icons are only available for certain styles.
*/
export function getIconStyle(style: IconStyle, icon: IconName): [string, IconName] {
const cached = cache.get(icon)?.get(style);
if (cached) {
return cached;
}
// Check for exceptions
let result = [style, icon] as [string, IconName];
for (const [onlyStyle, icons] of Object.entries(stylesMap)) {
if (icons.includes(icon)) {
result = [onlyStyle, icon];
break;
}
}
if (!cache.has(icon)) {
cache.set(icon, new Map());
}
cache.get(icon)!.set(style, result);
return result;
}
+58
View File
@@ -0,0 +1,58 @@
import { IconName, IconStyle } from './types';
import rawIcons from './data/icons.json';
export interface IconStyleDefinition {
title: string;
style: IconStyle;
}
export interface IconDefinition {
icon: IconName;
label: string;
search?: string[];
}
/**
* List of all icon styles available in the library.
*/
export const iconStyles: IconStyleDefinition[] = [
{
title: 'Regular',
style: IconStyle.Regular,
},
{
title: 'Duotone',
style: IconStyle.Duotone,
},
{
title: 'Light',
style: IconStyle.Light,
},
{
title: 'Thin',
style: IconStyle.Thin,
},
{
title: 'Solid',
style: IconStyle.Solid,
},
];
/**
* List of all icons available in the library.
*/
// @ts-ignore
export const icons: IconDefinition[] = rawIcons;
let iconNamesSet: Set<string> | null = null;
/**
* Validate that the icon name is valid.
*/
export function validateIconName(icon: IconName | string): icon is IconName {
if (!iconNamesSet) {
iconNamesSet = new Set(icons.map((icon) => icon.icon));
}
return iconNamesSet.has(icon);
}
+3
View File
@@ -0,0 +1,3 @@
export * from './Icon';
export * from './types';
export * from './IconsProvider';
+11
View File
@@ -0,0 +1,11 @@
/* Normal */
svg.gb-icon {
background: currentColor;
}
/* Sprite */
svg.gb-icon-s path,
svg.gb-icon-s use {
fill: currentColor;
stroke: currentColor;
}
+23
View File
@@ -0,0 +1,23 @@
import type { IconName as BasicIconName } from '@fortawesome/fontawesome-svg-core';
export enum IconStyle {
// Regular
Regular = 'regular',
SharpRegular = 'sharp-regular',
// Solid
Solid = 'solid',
SharpSolid = 'sharp-solid',
// Duotone
Duotone = 'duotone',
SharpDuotoneSolid = 'sharp-duotone-solid',
// Light
Light = 'light',
SharpLight = 'sharp-light',
// Thin
Thin = 'thin',
SharpThin = 'sharp-thin',
}
type CustomIconName = 'gitbook';
export type IconName = BasicIconName | CustomIconName;
+21
View File
@@ -0,0 +1,21 @@
{
"compilerOptions": {
"target": "esnext",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": false,
"declaration": true,
"outDir": "dist",
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react",
"incremental": true
},
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["node_modules"]
}
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env node
import fs from 'fs/promises';
import path from 'path';
import url from 'url';
/**
* Scripts to copy the assets to a public folder.
*/
async function main() {
const outputFolder = path.resolve(process.cwd(), process.argv[2] ?? 'public/math');
const source = path.dirname(url.fileURLToPath(import.meta.resolve('mathjax/package.json')));
const packageJson = JSON.parse(await fs.readFile(path.join(source, 'package.json'), 'utf8'));
// Create the output folder if it doesn't exist
await fs.mkdir(outputFolder, { recursive: true });
// Copy the assets
await Promise.all([
fs.cp(path.join(source, 'es5'), path.join(outputFolder, 'mathjax@' + packageJson.version), {
recursive: true,
}),
]);
console.log(`🎉 MathJaX assets copied to ${outputFolder}`);
}
main().catch(console.error);
+4
View File
@@ -1,5 +1,6 @@
{
"name": "@gitbook/react-math",
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
@@ -23,6 +24,9 @@
"typecheck": "tsc --noEmit",
"dev": "tsc -w"
},
"bin": {
"gitbook-math": "./bin/gitbook-math.js"
},
"files": [
"dist",
"src",
+5 -3
View File
@@ -26,9 +26,9 @@ export interface MathFormulaProps {
fallback?: React.ReactNode;
/**
* URL to load MathJax from.
* URL to load assets from.
*/
mathJaxUrl: string;
assetsUrl: string;
}
/**
@@ -43,9 +43,11 @@ export function MathFormula(props: MathFormulaProps) {
className: props.className,
children: props.formula,
}),
mathJaxUrl,
assetsUrl,
} = props;
const mathJaxUrl = `${assetsUrl}/mathjax@3.2.2/tex-chtml.js`;
return (
<KaTeX
formula={formula}
+1
View File
@@ -1,5 +1,6 @@
{
"name": "@gitbook/react-openapi",
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
@@ -104,7 +104,7 @@ export function generateSchemaExample(
if (schema.properties) {
const example: { [key: string]: JSONValue } = {};
const props = onlyRequired ? schema.required ?? [] : Object.keys(schema.properties);
const props = onlyRequired ? (schema.required ?? []) : Object.keys(schema.properties);
for (const key of props) {
const property = noReference(schema.properties[key]);
-13
View File
@@ -1,13 +0,0 @@
diff --git a/dist/index.js b/dist/index.js
index 7f9eaa2526e5fad42420f590bb733e5670766e63..302274144d28dde2b9ba8f9018281d2867f79299 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -9484,7 +9484,7 @@ var import_path = require("path");
// src/constants.ts
var KIB = 1024;
var MIB = 1024 * KIB;
-var EDGE_FUNCTION_SIZE_LIMIT = 4 * MIB;
+var EDGE_FUNCTION_SIZE_LIMIT = 10 * MIB;
var MAX_UNCOMPRESSED_LAMBDA_SIZE = 250 * MIB;
var LAMBDA_RESERVED_UNCOMPRESSED_SIZE = 2.5 * MIB;
var LAMBDA_RESERVED_COMPRESSED_SIZE = 250 * KIB;
+13
View File
@@ -0,0 +1,13 @@
diff --git a/dist/index.js b/dist/index.js
index c5ea5e053c4e6be202914bdd2e0228bc7be8b976..31c24e146fdf50a806f8c1da7eedc1d941270fa9 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -10474,7 +10474,7 @@ var import_path = require("path");
// src/constants.ts
var KIB = 1024;
var MIB = 1024 * KIB;
-var EDGE_FUNCTION_SIZE_LIMIT = 4 * MIB;
+var EDGE_FUNCTION_SIZE_LIMIT = 10 * MIB;
var DEFAULT_MAX_UNCOMPRESSED_LAMBDA_SIZE = 250 * MIB;
var LAMBDA_RESERVED_UNCOMPRESSED_SIZE = 25 * MIB;
+25 -5
View File
@@ -2,29 +2,49 @@
"$schema": "https://turbo.build/schema.json",
"globalEnv": ["NODE_ENV", "CI", "ARGOS_*", "GITHUB_*"],
"tasks": {
// Prepare the package for all other tasks
"generate": {
"dependsOn": ["^generate"],
"outputs": ["dist"]
},
"@gitbook/icons#generate": {
"dependsOn": ["^generate"],
"outputs": ["data/*.json"]
},
// Build the package for publishing
"build": {
"dependsOn": ["^build"],
"dependsOn": ["^build", "generate"],
"outputs": [".next/**", "!.next/cache/**", "dist"]
},
// Build the package for Cloudflare Pages
"build:cloudflare": {
"dependsOn": ["^build"]
"dependsOn": ["^build", "generate"]
},
// Check the package for type errors
"typecheck": {
"dependsOn": ["^typecheck", "^build"]
"dependsOn": ["^typecheck", "^build", "generate"]
},
// Lint the package for style errors
"lint": {
"dependsOn": ["^lint"]
"dependsOn": ["^lint", "generate"]
},
// Run unit tests
"unit": {
"dependsOn": ["^unit", "^build"]
"dependsOn": ["^unit", "^build", "generate"]
},
// Run end-to-end tests
"e2e": {
"dependsOn": ["^e2e"],
"env": ["BASE_URL"]
},
// Start the package in development mode
"dev": {
"persistent": true,
"cache": false
},
// Script run when the package is deployed
"release": {
"dependsOn": ["^release", "build"]
}
}
}