diff --git a/apps/pink/src/helpers/code.ts b/apps/pink/src/helpers/code.ts index a668c7807c..a77cdd144a 100644 --- a/apps/pink/src/helpers/code.ts +++ b/apps/pink/src/helpers/code.ts @@ -1,15 +1,14 @@ -import Prism from "prismjs"; +import * as Prism from "prismjs"; import prettier from "prettier/standalone"; import parserHtml from "prettier/parser-html"; import parserBabel from "prettier/parser-babel"; - /** * Receives a string and returns a wrapped string, with max * n characters per line, and a given indentation before each line. */ function wrapStr(str: string, n: number, indent: string): string { - // remove line breaks and tabs - str = str.replaceAll(/[\r\n\t]/g, ""); + // Remove line breaks and tabs + str = str.replace(/[\r\n\t]/g, ""); const words = str.split(/\s/); const lines = words.reduce((acc, word) => { const lastLine = acc[acc.length - 1]; @@ -32,14 +31,14 @@ export function customFormat(html: string, maxLength = 100) { // Decrease indent if line is a closing tag if (element.match(/^\/\w/)) indent = indent.substring(2); - // Match opening tag, e.g.
button text
should match
and - // should match + // Match opening tag const openingTagMatch = element.match(/^(\w+)(.*?)(\/?>)/s); - const openingTag = openingTagMatch ? openingTagMatch : null; + const openingTag = openingTagMatch ? openingTagMatch[0] : null; - // By default, we just add the element with the current indent before it + // By default, add the element with the current indent let toConcatenate = indent + "<" + element + ">\r"; + // Match content inside tags const contentMatch = element.match(/(.*?>)(.*?)(<.*)/s); if (contentMatch && toConcatenate.length > maxLength) { const [_, left, content, right] = contentMatch; @@ -74,42 +73,47 @@ export function formatHtml(html: string, maxLength = 100) { printWidth: maxLength, htmlWhitespaceSensitivity: "ignore", }); - } catch { - console.error("Failed to format HTML, using custom formatter"); + } catch (error) { + console.error("Failed to format HTML using Prettier, falling back to custom formatter:", error); return customFormat(html, maxLength); } } -function formatJs(js: string, maxLength = 100) { - return prettier.format(js, { - parser: "babel", - plugins: [parserBabel], - printWidth: maxLength, - }); +export function formatJs(js: string, maxLength = 100) { + try { + return prettier.format(js, { + parser: "babel", + plugins: [parserBabel], + printWidth: maxLength, + }); + } catch (error) { + console.error("Failed to format JavaScript using Prettier:", error); + return js; // Return the original JS code if formatting fails + } } -type highlightConfig = { - language?: string; - maxLength?: number; - format?: boolean; -}; - -const defaultConfig: Required = { +const defaultConfig = { language: "html", maxLength: 100, format: true, }; -export function highlight(code: string, config?: highlightConfig) { - const c = { ...defaultConfig, ...config }; - const formattedCode = - c.language === "html" - ? formatHtml(code, c.maxLength) - : formatJs(code, c.maxLength); - - return Prism.highlight( - formattedCode, - Prism.languages[c.language], - c.language - ); +export function highlight(code: string, config?: Partial) { + const { language, maxLength, format } = { ...defaultConfig, ...config }; + let formattedCode = code; + + try { + if (format) { + formattedCode = language === "html" ? formatHtml(code, maxLength) : formatJs(code, maxLength); + } + } catch (error) { + console.error("Formatting failed:", error); + } + + try { + return Prism.highlight(formattedCode, Prism.languages[language], language); + } catch (error) { + console.error("Highlighting failed:", error); + return formattedCode; // Return the formatted code even if highlighting fails + } } diff --git a/apps/pink/src/prettier-extensions.d.ts b/apps/pink/src/prettier-extensions.d.ts new file mode 100644 index 0000000000..936aa7b22b --- /dev/null +++ b/apps/pink/src/prettier-extensions.d.ts @@ -0,0 +1,12 @@ +// E:/Projects/PR/Pink/pink/apps/pink/src/prettier-extensions.d.ts + +declare module 'prettier/parser-html' { + const parserHtml: any; + export default parserHtml; + } + + declare module 'prettier/parser-babel' { + const parserBabel: any; + export default parserBabel; + } + \ No newline at end of file diff --git a/apps/pink/tsconfig.json b/apps/pink/tsconfig.json index d75ba134c2..44237307c3 100644 --- a/apps/pink/tsconfig.json +++ b/apps/pink/tsconfig.json @@ -1,10 +1,16 @@ { - "extends": "astro/tsconfigs/strict", "compilerOptions": { "baseUrl": ".", "paths": { "@components/*": ["src/components/*"], - "@layouts/*": ["src/layouts/*"], - } - } -} \ No newline at end of file + "@layouts/*": ["src/layouts/*"] + }, + "typeRoots": [ + "node_modules/@types" + ] + }, + "include": [ + "src", + "src/prettier-extensions.d.ts" + ] +} diff --git a/package-lock.json b/package-lock.json index fbb4797f4b..186d5d8bfa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ ], "devDependencies": { "@changesets/cli": "^2.26.1", + "@types/prettier": "^3.0.0", "prettier": "^2.8.2", "sass": "^1.53.0", "turbo": "^1.7.0", @@ -29,8 +30,8 @@ "license": "ISC", "devDependencies": { "@appwrite.io/fonts": "*", - "@appwrite.io/pink": "0.16.0", - "@appwrite.io/pink-icons": "0.16.0", + "@appwrite.io/pink": "0.20.0", + "@appwrite.io/pink-icons": "0.20.0", "vite-plugin-handlebars": "^1.6.0" } }, @@ -55,8 +56,8 @@ }, "devDependencies": { "@appwrite.io/fonts": "*", - "@appwrite.io/pink": "0.16.0", - "@appwrite.io/pink-icons": "0.16.0", + "@appwrite.io/pink": "0.20.0", + "@appwrite.io/pink-icons": "0.20.0", "@types/prismjs": "^1.26.0", "glob": "^8.0.3", "sass": "^1.57.1" @@ -2823,6 +2824,16 @@ "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz", "integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==" }, + "node_modules/@types/prettier": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-3.0.0.tgz", + "integrity": "sha512-mFMBfMOz8QxhYVbuINtswBp9VL2b4Y0QqYHwqLz3YbgtfAcat2Dl6Y1o4e22S/OVE6Ebl9m7wWiMT2lSbAs1wA==", + "deprecated": "This is a stub types definition. prettier provides its own type definitions, so you do not need this installed.", + "dev": true, + "dependencies": { + "prettier": "*" + } + }, "node_modules/@types/prismjs": { "version": "1.26.3", "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.3.tgz", @@ -16561,7 +16572,7 @@ }, "packages/icons": { "name": "@appwrite.io/pink-icons", - "version": "0.16.0", + "version": "0.20.0", "license": "ISC", "devDependencies": { "oslllo-svg-fixer": "^3.0.0", @@ -16570,10 +16581,10 @@ }, "packages/ui": { "name": "@appwrite.io/pink", - "version": "0.16.0", + "version": "0.20.0", "license": "ISC", "dependencies": { - "@appwrite.io/pink-icons": "0.16.0", + "@appwrite.io/pink-icons": "0.20.0", "normalize.css": "^8.0.1", "the-new-css-reset": "^1.11.2" }, diff --git a/package.json b/package.json index b9fcd0d779..fbd2b55b83 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ }, "devDependencies": { "@changesets/cli": "^2.26.1", + "@types/prettier": "^3.0.0", "prettier": "^2.8.2", "sass": "^1.53.0", "turbo": "^1.7.0",