Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(embed): handle snippet not found #53

Merged
merged 6 commits into from
Oct 17, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat(embed): render html content for snippet not found
  • Loading branch information
tericcabrel committed Oct 13, 2022
commit a06956120f0235c3431a082e37eca5e2ab06a7b2
2 changes: 1 addition & 1 deletion packages/embed/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ save. The URL follows this pattern: `http:https://localhost:7502/snippets/:id`.

Run the command below:
```shell
yarn preview
yarn iframe:preview
```
Navigate to the URL `http:https://localhost:7503` to see the result.

Expand Down
2 changes: 1 addition & 1 deletion packages/embed/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/embed/package.publish.json
Original file line number Diff line number Diff line change
@@ -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 <[email protected]>",
"license": "MIT"
Expand Down
41 changes: 41 additions & 0 deletions packages/embed/src/renderer/content/html-generator.ts
Original file line number Diff line number Diff line change
@@ -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 `<div class="no-content">
<h3>Oops! Snippet not found!</h3>
<div>Go to <a href="${webAppUrl}" target="_blank">Sharingan</a> to ensure it exists and is accessible</div>
</div>`;
};

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(/<pre class="shiki" style="background-color: \#[\w]{6}">/, '')
.replace('</pre>', '')
.split('\n')
.map((line: string, i: number) => {
return `<span class='line-number'>${i + 1}</span>${addWhitespaceForEmptyLine(line)}`;
})
.join('\n');

return {
backgroundColor,
html,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -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 `
<!DOCTYPE html>
Expand All @@ -28,22 +38,22 @@ export const generateHtmlPreview = ({ code, color = DEFAULT_COLOR, rawCode, scri
<div class="ctner">
<div class="ctner-header">
<div>${title}</div>
<div>view on <a href="">Sharingan</a></div>
<div>view on <a href="${webAppUrl}" target="_blank">Sharingan</a></div>
</div>
<textarea id="raw-code-${id}" class="hidden" rows="1" cols="1">${rawCode}</textarea>
<div class="code-editor-container" id="code-${id}" style="border: solid 1px ${color}; background-color: ${color}">
<button id="btn-copy-${id}" class="btn-copy hidden">
<button id="btn-copy-${id}" class="btn-copy hidden" style="${isEmpty ? 'display: none' : ''}">
<svg class="ic show" id="ic-copy-${id}" fill="none" stroke="#fff" viewBox="0 0 24 24" xmlns="http:https://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"></path>
</svg>
<svg class="ic hidden" id="ic-copied-${id}" fill="none" stroke="#10B981" viewBox="0 0 24 24" xmlns="http:https://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
</button>
<pre>${code}</pre>
${isEmpty ? `${code}` : `<pre>${code}</pre>`}
</div>
</div>
${scriptUrl ? `<script type="text/javascript" src="${scriptUrl}"></script>` : ''}
${scriptUrl && !isEmpty ? `<script type="text/javascript" src="${scriptUrl}"></script>` : ''}
</body>
</html>
`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 <span class="line"></span> to <span class="line"> </span>
* Convert <span class="line line-diff-add"></span> to <span class="line line-diff-add"> </span>
*
* @param line
*/
export const addWhitespaceForEmptyLine = (line: string) => {
if (/<span class="line (line-diff-?[a-z ]*)*"><\/span>/.test(line)) {
const [openingBracket] = line.split('</span>');
Expand Down
44 changes: 12 additions & 32 deletions packages/embed/src/renderer/index.ts
Original file line number Diff line number Diff line change
@@ -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<Highlighter>;
};
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;
Expand All @@ -20,47 +17,30 @@ type Args = {
export const renderSnippetToHtml = async ({ options, shiki, snippet }: Args): Promise<string> => {
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(/<pre class="shiki" style="background-color: \#[\w]{6}">/, '')
.replace('</pre>', '')
.split('\n')
.map((line: string, i: number) => {
return `<span class='line-number'>${i + 1}</span>${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,
});
};
5 changes: 5 additions & 0 deletions packages/embed/src/renderer/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Highlighter, HighlighterOptions } from 'shiki';

export type Shiki = {
getHighlighter: (options: HighlighterOptions) => Promise<Highlighter>;
};
1 change: 1 addition & 0 deletions packages/embed/src/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
13 changes: 13 additions & 0 deletions packages/embed/src/styles/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}