Skip to content

Commit

Permalink
docs: optimize code fold (#4202)
Browse files Browse the repository at this point in the history
* docs: optimize code fold

* fix: code review
  • Loading branch information
winchesHe authored Dec 1, 2024
1 parent 54793bf commit 7599c33
Showing 1 changed file with 128 additions and 108 deletions.
236 changes: 128 additions & 108 deletions apps/docs/components/docs/components/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ export type TransformTokensTypes = TransformTokens[0][0] & {

const startFlag = ["{", "["];
const endFlag = ["}", "]"];
const specialStartFlag = ["("];
const specialEndFlag = [")"];
const defaultFoldFlagList = ["cn", "HTMLAttributes"];
const defaultShowFlagList = ["Component", "forwardRef", "App", "Example", "AddForm", "SignupForm"];
const isElementStartRegex = /^\s*</;
const isElementEndRegex = /^\s*<\//;

/**
* Transform tokens from `prism-react-renderer` to wrap them in folder structure
Expand All @@ -26,156 +24,141 @@ const defaultShowFlagList = ["Component", "forwardRef", "App", "Example", "AddFo
export function transformTokens(tokens: TransformTokens, folderLine = 10) {
const result: TransformTokens = [];
let lastIndex = 0;
let isShowFolder = false;
let fold = false;
let startElementName = "";

tokens.forEach((token, index) => {
if (index < lastIndex) {
return;
}
token.forEach((t) => {
(t as TransformTokensTypes).index = index;
});
result.push(token);

let startToken: TransformTokens[0][0] = null as any;
let mergedStartFlagList = [...startFlag];
const lineContent = getLineContent(token);
const {isStartTag, isEndTag} = checkIsElement(lineContent);

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 it has startElementName means it is within the element range
if (startElementName) {
if (isEndTag) {
// Judge whether it is the end tag of the element then reset startElementName
const {endElementName} = getElementName(lineContent);

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

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

if (mergedStartFlagList.includes(t.content)) {
startToken = t;
return;
} else if (isStartTag) {
const {startElementName: elementName, endElementName} = getElementName(lineContent);

if (!endElementName) {
startElementName = elementName;

return;
}
}

if (defaultShowFlagList.some((text) => t.content.includes(text))) {
isShowFolder = true;
let startToken: TransformTokens[0][0] = null as any;

token.forEach((t) => {
if (startFlag.includes(t.content)) {
startToken = t;
}
});

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

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;
const nextLineContent = tokens.slice(index + 1, index + 2).reduce((acc, line) => {
return acc + getLineContent(line);
}, "");
const isNextLineObjectFolder = checkIsObjectContent(nextLineContent);
const isArrayFolder = lineContent.trim().endsWith("[");

if (isNextLineObjectFolder || isArrayFolder) {
const endIndex = findEndIndex(tokens, index + 1);

// Greater than or equal to folderLine then will folder otherwise it will show directly
if (endIndex !== -1 && endIndex - index >= folderLine) {
lastIndex = endIndex;
const folder = tokens.slice(index + 1, endIndex);
const endToken = tokens[endIndex];

(endToken[0] as TransformTokensTypes).class = "first-custom-folder";

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 = (t as TransformTokensTypes).class || "";

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;
// isShowFolder && ((startToken as TransformTokensTypes).open = true);

result.splice(result.length - 1, 1, [startToken]);

return;
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 = {},
) {
function checkIsFolder(token: TransformTokens[0]) {
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)) {
if (startFlag.includes(t.content)) {
stack.push(t.content);
} else if (mergedEndFlagList.includes(t.content)) {
} else if (endFlag.includes(t.content)) {
stack.pop();
}
}

return stack.length !== 0;
}

function findEndIndex(
tokens: TransformTokens,
startIndex: number,
{specialStartFlag, specialEndFlag}: SpecialOptions = {},
) {
function findEndIndex(tokens: TransformTokens, startIndex: number) {
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)) {
if (startFlag.includes(transformLine)) {
stack.push("flag");
} else if (mergedEndFlagList.includes(transformLine)) {
} else if (endFlag.includes(transformLine)) {
stack.pop();
}

Expand All @@ -187,3 +170,40 @@ function findEndIndex(

return -1;
}

function checkIsElement(lineContent: string) {
return {
isStartTag: isElementStartRegex.test(lineContent),
isEndTag: isElementEndRegex.test(lineContent),
};
}

function getElementName(lineContent: string) {
const startElementName = lineContent.match(/^\s*<([a-zA-Z.]+)/);
const endElementName = lineContent.match(/^\s*<\/([a-zA-Z.]+)>/);

return {
startElementName: startElementName?.[1] || (lineContent.includes("<>") ? "<>" : ""),
endElementName: endElementName?.[1] || (lineContent.includes("</>") ? "</>" : ""),
};
}

function getLineContent(token: TransformTokens[0]) {
return token.reduce((acc, t) => acc + t.content, "");
}

function checkIsObjectContent(lineContent: string) {
lineContent = lineContent.trim();
// first: match { a }
// second: match { a: b }
// third: match { a (b) }
// fourth: match /** */
const isObjectContent = /^([\w]+,?$)|([\w\[.\]]+:)|([\w]+\s?\(.*?\)$)|(^\/\*\*)/.test(
lineContent,
);
const hasEqual = /\s=\s/.test(lineContent);
const hasFunction = lineContent.includes("function");
const hasVariable = /var|let|const/.test(lineContent);

return isObjectContent && !hasEqual && !hasFunction && !hasVariable;
}

0 comments on commit 7599c33

Please sign in to comment.