Skip to content

Commit

Permalink
refactor(docs): overall dx (#4055)
Browse files Browse the repository at this point in the history
* refactor(docs): revise code block (#3922)

* refactor(docs): revise code block

* chore(docs): resolve pr comments

* refactor(docs): autocomplete dx (#3934)

* feat(docs): add *.js?raw module

* feat(docs): change to react-jsx and add **/*.js

* chore(root): include js and jsx

* refactor(docs): autocomplete dx

* chore(docs): rollback overrides

* chore(autocomplete): lint

* fix(autocomplete): incorrect import path

* fix(docs): autocomplete dx

* chore(docs): remove highlightedLines

* refactor(docs): breadcrumbs dx (#3968)

* refactor(docs): breadcrumbs dx

* fix(docs): export issue

* chore(docs): use preserve for jsx

* fix(docs): support multiline import

* fix(docs): support multiple export

* chore(docs): add back export

* refactor(docs): avatar dx (#3951)

* refactor(docs): badge dx (#3960)

* refactor(docs): badge dx

* chore(docs): incorrect import path

* refactor(docs): button dx (#3981)

* refactor(docs): calendar dx (#4022)

* refactor(docs): calendar dx

* fix(docs): incorrect import path

* refactor(docs): switch dx (#4037)

* refactor(docs): switch dx

* chore(docs): remove highlightedLines

* refactor(docs): tooltip (#4035)

* refactor(docs): usage dx (#4036)

* refactor(docs): circular-progress dx (#4029)

* refactor(docs): chip-dx (#4028)

* refactor(docs): checkbox-group dx (#4027)

* refactor(docs): checkbox dx (#4024)

* refactor(docs): checkbox dx

* fix(docs): incorrect import path

* refactor(docs): card dx (#4023)

* refactor(docs): skeleton dx (#4042)

* refactor(docs): spacer dx (#4043)

* refactor(docs): snippet dx (#4044)

* refactor(docs): scroll-shadow dx (#4045)

* refactor(docs): code dx (#4046)

* refactor(docs): kbd dx (#4047)

* refactor(docs): link dx (#4048)

* refactor(docs): progress dx (#4049)

* refactor(docs): divider dx (#4050)

* refactor(docs): listbox dx (#4051)

* refactor(docs): listbox dx

* fix(docs): import path

* fix(docs): import path

* chore(docs): remove highlightedLines

* fix(docs): indentation

* chore(docs): replace the props of autocomplete from value to key (#4129)

* refactor(docs): alert dx (#4108)

* refactor(docs): alert dx

* refactor(docs): alert dx

* refactor(docs): image dx (#4061)

* refactor(docs): textarea dx (#4063)

* refactor(docs): spinner dx (#4088)

* refactor(docs): radio-group dx (#4064)

* refactor(docs): pagination dx (#4062)

* refactor(docs): pagination dx

* refactor(docs): pagination dx

* refactor(docs): time-input dx (#4065)

* refactor(docs): time-input dx

* refactor(docs): time-input dx

* refactor(docs): slider dx (#4066)

* refactor(docs): slider dx

* refactor(docs): slider dx

* refactor(docs): move SliderValue to type

* refactor(docs): slider dx

* refactor(docs): make icon code collapsible

* refactor(docs): specify versions for date packages (#4138)

* refactor(docs): specify versions for date packages

* fix(docs): correct RA i18n version

* chore(deps): sync version from package

* refactor(docs): tabs dx (#4067)

* refactor(docs): tab dx

* refactor(docs): tabs dx

* refactor(docs): input dx (#4102)

* refactor(docs): input dx

* refactor(docs): input dx

* refactor(docs): navbar dx (#4076)

* refactor(docs): navbar dx

* refactor(docs): navbar dx

* refactor(docs): navbar dx

* refactor(docs): modal dx (#4077)

* refactor(docs): modal dx

* refactor(docs): modal dx

* refactor(docs): select dx (#4078)

* refactor(docs): select dx

* refactor(docs): select dx

* refactor(docs): select dx

* refactor(docs): select dx

* refactor(docs): select dx

* refactor(docs): table dx (#4079)

* refactor(docs): table dx

* fix(docs): import path

* refactor(docs): table dx

* refactor(docs): table dx

* refactor(docs): popover dx (#4090)

* refactor(docs): range-calendar dx (#4089)

* refactor(docs): range-calendar dx

* fix(docs): import path

* refactor(docs): date input dx (#4100)

* refactor(docs): dropdown dx (#4101)

* refactor(docs): dropdown dx

* refactor(docs): remove highlightedLines

* refactor(docs): dropdown dx

* refactor(docs): dropdown dx

* refactor(docs): date-picker dx (#4103)

* refactor(docs): date-picker dx

* fix(docs): import paths

* refactor(docs): date-range-picker dx (#4104)

* refactor(docs): date-range-picker dx

* fix(docs): date-range-picker dx

* refactor(docs): drawer dx (#4109)

* refactor(docs): drawer dx

* fix(docs): indentation

* refactor(docs): make icon collapsible

---------

Co-authored-by: աӄա <wingkwong.code@gmail.com>
Co-authored-by: Ryo Matsukawa <76232929+ryo-manba@users.noreply.github.com>
  • Loading branch information
3 people authored Nov 28, 2024
1 parent 8b28f79 commit 93f1c6f
Show file tree
Hide file tree
Showing 1,167 changed files with 29,114 additions and 27,039 deletions.
4 changes: 0 additions & 4 deletions apps/docs/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}
4 changes: 2 additions & 2 deletions apps/docs/components/docs/components/code-demo/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {FileCode} from "./types";

const importRegex = /^(import)\s(?!type(of\s|\s)(?!from)).*?$/gm;
const importRegex = /^(import\s+(?!type\s+\{)[\s\S]*?;)/gm;

const exportDefaultRegex = /export\s+default\s+function\s+\w+\s*\(\s*\)\s*\{/;

Expand Down Expand Up @@ -31,7 +31,7 @@ export const transformCode = (
// replace match with const Name = () => (
return `const ${compName} = () => {`;
})
.replace("export", "");
.replace(/export/g, "");

// add render(<App/>) to cleanedCode if has const App = () => {
if (cleanedCode.includes(`const App = () => {`)) {
Expand Down
106 changes: 84 additions & 22 deletions apps/docs/components/docs/components/codeblock.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import type {Language, PrismTheme} from "prism-react-renderer";
import type {TransformTokensTypes} from "./helper";

import React, {forwardRef, useEffect} from "react";
import {clsx, dataAttr, getUniqueID} from "@nextui-org/shared-utils";
import BaseHighlight, {Language, PrismTheme, defaultProps} from "prism-react-renderer";
import {debounce, omit} from "@nextui-org/shared-utils";
import {cn} from "@nextui-org/react";

import {transformTokens} from "./helper";

import defaultTheme from "@/libs/prism-theme";

Expand Down Expand Up @@ -142,21 +148,36 @@ const Codeblock = forwardRef<HTMLPreElement, CodeblockProps>(
{...props}
>
{({className, style, tokens, getLineProps, getTokenProps}) => (
<div className="w-full" data-language={language}>
<pre
ref={ref}
className={clsx(className, classNameProp, "flex max-w-full", {
<pre
ref={ref}
className={clsx(
className,
classNameProp,
`language-${codeLang}`,
"max-w-full contents",
{
"flex-col": isMultiLine,
"scrollbar-hide overflow-x-scroll": hideScrollBar,
})}
style={style}
translate="no"
>
{tokens.map((line, i) => {
"overflow-x-scroll scrollbar-hide": hideScrollBar,
},
)}
data-language={language}
style={style}
>
{transformTokens(tokens).map((line) => {
const folderLine = line[0] as TransformTokensTypes;

const isFolder = folderLine.types?.includes("folderStart");

const renderLine = (
line: TransformTokensTypes[],
i: number,
as: "div" | "span" = "div",
) => {
const Tag = as;
const lineProps = getLineProps({line, key: i});

return (
<div
<Tag
{...omit(lineProps, ["key"])}
key={`${i}-${getUniqueID("line-wrapper")}`}
className={clsx(
Expand All @@ -167,25 +188,48 @@ const Codeblock = forwardRef<HTMLPreElement, CodeblockProps>(
"px-2": showLines,
},
{
"before:content-[''] before:w-full before:h-full before:absolute before:z-0 before:left-0 before:bg-gradient-to-r before:from-white/10 before:to-code-background":
shouldHighlightLine(i),
"before:to-code-background before:absolute before:left-0 before:z-0 before:h-full before:w-full before:bg-gradient-to-r before:from-white/10 before:content-['']":
isFolder ? false : shouldHighlightLine(i),
},
)}
data-deleted={dataAttr(highlightStyle?.[i] === "deleted")}
data-inserted={dataAttr(highlightStyle?.[i] === "inserted")}
>
{showLines && (
<span className="select-none text-xs mr-6 opacity-30">{i + 1}</span>
<span
className={cn(
"mr-6 select-none text-xs opacity-30",
i + 1 >= 10 ? "mr-4" : "",
i + 1 >= 100 ? "mr-2" : "",
i + 1 >= 1000 ? "mr-0" : "",
)}
>
{i + 1}
</span>
)}

{line.map((token, key) => {
// Bun has no color style by default in the code block, so hack add in here
const props = getTokenProps({token, key}) || {};

return (
const isCopy = token.types.includes("copy");

return isCopy ? (
<span key={key} className="copy-token" style={{whiteSpace: "inherit"}}>
{token.folderContent?.map((folderTokens) => {
return folderTokens.map((token, index) => {
// Hack for wrap line
return token.content === "" ? (
<div key={`${index}-${getUniqueID("line")}`} />
) : (
<span key={`${index}-${getUniqueID("line")}`}>{token.content}</span>
);
});
})}
</span>
) : (
<span
{...omit(props, ["key"])}
key={`${key}-${getUniqueID("line")}`}
className={className}
className={cn(className, token.class)}
style={{
...props.style,
...(highlightStyleToken.some((t) => {
Expand All @@ -201,11 +245,29 @@ const Codeblock = forwardRef<HTMLPreElement, CodeblockProps>(
/>
);
})}
</div>
</Tag>
);
})}
</pre>
</div>
};
const renderFolderTokens = (tokens: TransformTokensTypes[][]) => {
return tokens.map((token, key) => {
const index = key + folderLine.index! + 1;

return renderLine(token, index);
});
};

return isFolder ? (
<details key={`${folderLine.index}`} open={folderLine.open ? true : undefined}>
<summary className="cursor-pointer">
{renderLine(folderLine.summaryContent as any, folderLine.index!, "span")}
</summary>
{renderFolderTokens(folderLine.folderContent as any)}
</details>
) : (
renderLine(line, folderLine.index!)
);
})}
</pre>
)}
</BaseHighlight>
);
Expand Down
189 changes: 189 additions & 0 deletions apps/docs/components/docs/components/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import type Highlight from "prism-react-renderer";

export type TransformTokens = Parameters<Highlight["props"]["children"]>[0]["tokens"];

export type TransformTokensTypes = TransformTokens[0][0] & {
folderContent?: TransformTokens;
summaryContent?: TransformTokens[0];
class?: string;
index?: number;
open?: boolean;
};

const startFlag = ["{", "["];
const endFlag = ["}", "]"];
const specialStartFlag = ["("];
const specialEndFlag = [")"];
const defaultFoldFlagList = ["cn", "HTMLAttributes"];
const defaultShowFlagList = ["Component", "forwardRef", "App"];

/**
* Transform tokens from `prism-react-renderer` to wrap them in folder structure
*
* @example
* transformTokens(tokens) -> wrap tokens in folder structure
*/
export function transformTokens(tokens: TransformTokens, folderLine = 10) {
const result: TransformTokens = [];
let lastIndex = 0;
let isShowFolder = false;
let fold = false;

tokens.forEach((token, index) => {
if (index < lastIndex) {
return;
}

let startToken: TransformTokens[0][0] = null as any;
let mergedStartFlagList = [...startFlag];

token.forEach((t) => {
if (defaultFoldFlagList.some((text) => t.content.includes(text))) {
// If cn then need to judge whether it is import token
if (t.content.includes("cn") && token.some((t) => t.content === "import")) {
return;
}

// If HTMLAttributes then need to judge whether it have start flag
if (
t.content.includes("HTMLAttributes") &&
!token.some((t) => startFlag.includes(t.content))
) {
return;
}

fold = true;
mergedStartFlagList.push(...specialStartFlag);
}

if (mergedStartFlagList.includes(t.content)) {
startToken = t;
}

if (defaultShowFlagList.some((text) => t.content.includes(text))) {
isShowFolder = true;
}
});

const mergedOptions = fold
? {
specialEndFlag,
specialStartFlag,
}
: undefined;
const isFolder = checkIsFolder(token, mergedOptions);

if (isFolder && startToken) {
const endIndex = findEndIndex(tokens, index + 1, mergedOptions);

// Greater than or equal to folderLine then will folder otherwise it will show directly
if (endIndex !== -1 && (endIndex - index >= folderLine || isShowFolder || fold)) {
lastIndex = endIndex;
const folder = tokens.slice(index + 1, endIndex);
const endToken = tokens[endIndex];
const ellipsisToken: TransformTokensTypes = {
types: ["ellipsis"],
content: "",
class: "custom-folder ellipsis-token",
};
const copyContent: TransformTokensTypes = {
types: ["copy"],
content: "",
folderContent: folder,
class: "custom-folder copy-token",
};

endToken.forEach((t, _, arr) => {
let className = "";

className += "custom-folder";
if (t.content.trim() === "" && (arr.length === 3 || arr.length === 4)) {
// Add length check to sure it's added to } token
className += " empty-token";
}
(t as TransformTokensTypes).class = className;
});

startToken.types = ["folderStart"];
(startToken as TransformTokensTypes).folderContent = folder;
(startToken as TransformTokensTypes).summaryContent = [
...token,
ellipsisToken,
copyContent,
...endToken,
];
(startToken as TransformTokensTypes).index = index;
if (isShowFolder && !fold) {
(startToken as TransformTokensTypes).open = true;
}

result.push([startToken]);

isShowFolder = false;
fold = false;

return;
}
}
token.forEach((t) => {
(t as TransformTokensTypes).index = index;
});
result.push(token);
});

return result;
}

interface SpecialOptions {
specialStartFlag?: string[];
specialEndFlag?: string[];
}

function checkIsFolder(
token: TransformTokens[0],
{specialStartFlag, specialEndFlag}: SpecialOptions = {},
) {
const stack: string[] = [];
const mergedStartFlagList = specialStartFlag ? [...startFlag, ...specialStartFlag] : startFlag;
const mergedEndFlagList = specialEndFlag ? [...endFlag, ...specialEndFlag] : endFlag;

for (const t of token) {
if (mergedStartFlagList.includes(t.content)) {
stack.push(t.content);
} else if (mergedEndFlagList.includes(t.content)) {
stack.pop();
}
}

return stack.length !== 0;
}

function findEndIndex(
tokens: TransformTokens,
startIndex: number,
{specialStartFlag, specialEndFlag}: SpecialOptions = {},
) {
const stack: string[] = ["flag"];
const mergedStartFlagList = specialStartFlag ? [...startFlag, ...specialStartFlag] : startFlag;
const mergedEndFlagList = specialEndFlag ? [...endFlag, ...specialEndFlag] : endFlag;

for (let i = startIndex; i < tokens.length; i++) {
const token = tokens[i];

for (const line of token) {
const transformLine = line.content.replace(/\$/g, "");

if (mergedStartFlagList.includes(transformLine)) {
stack.push("flag");
} else if (mergedEndFlagList.includes(transformLine)) {
stack.pop();
}

if (stack.length === 0) {
return i;
}
}
}

return -1;
}
7 changes: 6 additions & 1 deletion apps/docs/components/mdx-components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,12 @@ const Code = ({
});
}}
>
<Codeblock codeString={codeString} language={language} metastring={meta} />
<Codeblock
className="sp-editor"
codeString={codeString}
language={language}
metastring={meta}
/>
</Components.Snippet>
);
};
Expand Down
Loading

0 comments on commit 93f1c6f

Please sign in to comment.