diff --git a/packages/embed/README.md b/packages/embed/README.md index e36d3007..4908ef02 100644 --- a/packages/embed/README.md +++ b/packages/embed/README.md @@ -64,7 +64,7 @@ save. The URL follows this pattern: `http://localhost:7502/snippets/:id`. Run the command below: ```shell -yarn preview +yarn iframe:preview ``` Navigate to the URL `http://localhost:7503` to see the result. diff --git a/packages/embed/package.json b/packages/embed/package.json index fe198e3a..4a2d0d36 100644 --- a/packages/embed/package.json +++ b/packages/embed/package.json @@ -13,7 +13,7 @@ "clean": "rm -rf .turbo dist build", "dev": "nodemon --watch \"*.ts\" --exec \"ts-node\" ./src/server/index.ts", "lint": "eslint src", - "preview": "serve ./src/server/static -l 7503", + "iframe:preview": "serve ./src/server/static -l 7503", "push": "cp package.publish.json build/package.json && cd build && npm publish --access=public", "test": "jest" }, diff --git a/packages/embed/package.publish.json b/packages/embed/package.publish.json index 9cd64e78..18bdffea 100644 --- a/packages/embed/package.publish.json +++ b/packages/embed/package.publish.json @@ -1,6 +1,6 @@ { "name": "sharingan-embed", - "version": "1.0.2", + "version": "1.1.0", "repository": "https://github.com/tericcabrel/sharingan.git", "author": "Eric Cabrel TIOGO ", "license": "MIT" diff --git a/packages/embed/src/renderer/content/html-generator.ts b/packages/embed/src/renderer/content/html-generator.ts new file mode 100644 index 00000000..043dd707 --- /dev/null +++ b/packages/embed/src/renderer/content/html-generator.ts @@ -0,0 +1,41 @@ +import { Snippet } from '@sharingan/database'; +import { Lang } from 'shiki'; + +import { Shiki } from '../types'; +import { addWhitespaceForEmptyLine, generateLineHighlightOptions } from './utils'; + +export const generateNoSnippetHtmlContent = (webAppUrl: string) => { + return `
+

Oops! Snippet not found!

+
Go to Sharingan to ensure it exists and is accessible
+
`; +}; + +export const generateSnippetHtmlContent = async ({ shiki, snippet }: { shiki: Shiki; snippet: Snippet }) => { + const highlighter = await shiki.getHighlighter({ + langs: [snippet.language] as Lang[], + theme: snippet.theme, + themes: [snippet.theme], + }); + + const snippetCodeHtml = highlighter.codeToHtml(snippet.content.trim(), { + lang: snippet.language, + lineOptions: generateLineHighlightOptions(snippet.lineHighlight), + }); + + const backgroundColor = highlighter.getBackgroundColor(); + + const html = snippetCodeHtml + .replace(/
/, '')
+    .replace('
', '') + .split('\n') + .map((line: string, i: number) => { + return `${i + 1}${addWhitespaceForEmptyLine(line)}`; + }) + .join('\n'); + + return { + backgroundColor, + html, + }; +}; diff --git a/packages/embed/src/renderer/html-preview.ts b/packages/embed/src/renderer/content/preview-template.ts similarity index 75% rename from packages/embed/src/renderer/html-preview.ts rename to packages/embed/src/renderer/content/preview-template.ts index de8461cf..af3a3d09 100644 --- a/packages/embed/src/renderer/html-preview.ts +++ b/packages/embed/src/renderer/content/preview-template.ts @@ -7,12 +7,22 @@ type Args = { scriptUrl?: string; styleUrl: string; title: string; + webAppUrl: string; }; const DEFAULT_COLOR = '#22272e'; -export const generateHtmlPreview = ({ code, color = DEFAULT_COLOR, rawCode, scriptUrl, styleUrl, title }: Args) => { +export const generateHTMLPreview = ({ + code, + color = DEFAULT_COLOR, + rawCode, + scriptUrl, + styleUrl, + title, + webAppUrl, +}: Args) => { const id = generateRandomString(6); + const isEmpty = !rawCode; return ` @@ -28,11 +38,11 @@ export const generateHtmlPreview = ({ code, color = DEFAULT_COLOR, rawCode, scri
${title}
-
view on Sharingan
+
view on Sharingan
- -
${code}
+ ${isEmpty ? `${code}` : `
${code}
`}
- ${scriptUrl ? `` : ''} + ${scriptUrl && !isEmpty ? `` : ''} `; diff --git a/packages/embed/src/renderer/utils.ts b/packages/embed/src/renderer/content/utils.ts similarity index 75% rename from packages/embed/src/renderer/utils.ts rename to packages/embed/src/renderer/content/utils.ts index 4914cc65..5f5d899c 100644 --- a/packages/embed/src/renderer/utils.ts +++ b/packages/embed/src/renderer/content/utils.ts @@ -4,6 +4,14 @@ export const generateLineHighlightOptions = (lineHighlight: string | null) => { return lines.map(([key, value]) => ({ classes: [`line-diff line-diff-${value}`], line: key })); }; +/** + * Adding two spaces in an empty span makes it counted as a code line + * + * Convert to + * Convert to + * + * @param line + */ export const addWhitespaceForEmptyLine = (line: string) => { if (/<\/span>/.test(line)) { const [openingBracket] = line.split(''); diff --git a/packages/embed/src/renderer/index.ts b/packages/embed/src/renderer/index.ts index eee6d79d..c6630b8a 100644 --- a/packages/embed/src/renderer/index.ts +++ b/packages/embed/src/renderer/index.ts @@ -1,17 +1,14 @@ import { Snippet } from '@sharingan/database'; -import { Highlighter, HighlighterOptions, Lang } from 'shiki'; -import { generateHtmlPreview } from './html-preview'; -import { addWhitespaceForEmptyLine, generateLineHighlightOptions } from './utils'; - -type Shiki = { - getHighlighter: (options: HighlighterOptions) => Promise; -}; +import { generateNoSnippetHtmlContent, generateSnippetHtmlContent } from './content/html-generator'; +import { generateHTMLPreview } from './content/preview-template'; +import { Shiki } from './types'; type Args = { options: { scriptUrl: string; styleUrl: string; + webAppUrl: string; }; shiki: Shiki; snippet: Snippet | null; @@ -20,47 +17,30 @@ type Args = { export const renderSnippetToHtml = async ({ options, shiki, snippet }: Args): Promise => { const STYLE_URL = options.styleUrl; const SCRIPT_URL = options.scriptUrl; + const WEBAPP_URL = options.webAppUrl; if (!snippet) { - const code = 'No content'; + const code = generateNoSnippetHtmlContent(WEBAPP_URL); - return generateHtmlPreview({ + return generateHTMLPreview({ code, - rawCode: 'No content', + rawCode: '', scriptUrl: SCRIPT_URL, styleUrl: STYLE_URL, title: 'Not found', + webAppUrl: WEBAPP_URL, }); } - const highlighter = await shiki.getHighlighter({ - langs: [snippet.language] as Lang[], - theme: snippet.theme, - themes: [snippet.theme], - }); - - const snippetCodeHtml = highlighter.codeToHtml(snippet.content.trim(), { - lang: snippet.language, - lineOptions: generateLineHighlightOptions(snippet.lineHighlight), - }); - - const backgroundColor = highlighter.getBackgroundColor(); - - const html = snippetCodeHtml - .replace(/
/, '')
-    .replace('
', '') - .split('\n') - .map((line: string, i: number) => { - return `${i + 1}${addWhitespaceForEmptyLine(line)}`; - }) - .join('\n'); + const { backgroundColor, html } = await generateSnippetHtmlContent({ shiki, snippet }); - return generateHtmlPreview({ + return generateHTMLPreview({ code: html, color: backgroundColor, rawCode: snippet.content, scriptUrl: SCRIPT_URL, styleUrl: STYLE_URL, title: snippet.name, + webAppUrl: WEBAPP_URL, }); }; diff --git a/packages/embed/src/renderer/types.ts b/packages/embed/src/renderer/types.ts new file mode 100644 index 00000000..46c7e2dc --- /dev/null +++ b/packages/embed/src/renderer/types.ts @@ -0,0 +1,5 @@ +import { Highlighter, HighlighterOptions } from 'shiki'; + +export type Shiki = { + getHighlighter: (options: HighlighterOptions) => Promise; +}; diff --git a/packages/embed/src/server/index.ts b/packages/embed/src/server/index.ts index 9ebe0ff0..f1a3901e 100644 --- a/packages/embed/src/server/index.ts +++ b/packages/embed/src/server/index.ts @@ -35,6 +35,7 @@ export const startServer = async () => { options: { scriptUrl: process.env.EMBED_JS_URL, styleUrl: process.env.EMBED_STYLE_URL, + webAppUrl: process.env.WEB_APP_URL, }, shiki, snippet, diff --git a/packages/embed/src/styles/index.css b/packages/embed/src/styles/index.css index f1feb523..073ddfa8 100644 --- a/packages/embed/src/styles/index.css +++ b/packages/embed/src/styles/index.css @@ -87,3 +87,16 @@ .show { display: block; } +.no-content { + font-family: 'Inter', monospace !important; + display: flex; + flex-direction: column; + align-items: center; + color: white; + margin-top: 15px; + margin-bottom: 40px; +} +.no-content a { + text-decoration: none; + color: aquamarine; +}