Skip to content

Commit

Permalink
feat(docs): automatic links to Web IDE from all code blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
novusnota committed Oct 28, 2024
1 parent e7f6e17 commit cf260ea
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 1 deletion.
5 changes: 4 additions & 1 deletion docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import rehypeAutolinkHeadings from 'rehype-autolink-headings';
import remarkMath from 'remark-math';
import rehypeKatex from 'rehype-katex';

// Adds links to Web IDE from code blocks
import remarkLinksToWebIDE from './links-to-web-ide';

// Adds syntax highlighting for inline code blocks
import rehypeInlineCodeHighlighting from './inline-code-highlighting';

Expand All @@ -26,7 +29,7 @@ export default defineConfig({
outDir: './dist', // default, just to be sure
site: 'https://docs.tact-lang.org',
markdown: {
remarkPlugins: [remarkHeadingId, remarkMath],
remarkPlugins: [remarkHeadingId, remarkMath, remarkLinksToWebIDE],
rehypePlugins: [
rehypeHeadingIds,
[rehypeAutolinkHeadings, {
Expand Down
88 changes: 88 additions & 0 deletions docs/links-to-web-ide.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* @import {Root} from 'mdast'
*/
import { visit } from 'unist-util-visit';

/**
* Maximum allowed characters in a Chrome
* Firefox has more limit but we are using less for compatibility
*/
const maxAllowedCharacters = 32779;

/**
* Adds links to every code block, allowing to open its contents in the Web IDE
*
* @returns Transform.
*/
export default function remarkLinksToWebIDE() {
/**
* @param tree {Root}
* @return {undefined}
*/
return function(tree) {
// Specifying 'code' items guarantees non-inline code blocks
visit(tree, 'code', function(node, index, parent) {
// Only allow Tact code blocks
if (node.lang !== 'tact') { return undefined; }

// Only allow certain amount of characters
let src = node.value.trim();
if (src.length > maxAllowedCharacters) { return undefined; }

// Detect module-level items
let hasModuleItems = false;
const lines = src.split('\n');
for (let i = 0; i < lines.length; i += 1) {
// Same regex as in scripts/check-cookbook-examples.js
const matchRes = lines[i].match(/^\s*(?:import|primitive|const|asm|fun|extends|mutates|virtual|override|inline|abstract|@name|@interface|contract|trait|struct|message)\b/);
// TODO: Unite the regexes when Tact 2.0 arrives (or if some new module-level item arrives, or via try/catch and re-using compiler's parser)

if (matchRes !== null) {
hasModuleItems = true;
break;
}
}

// Adjust the source code if the module-level items are NOT present
if (!hasModuleItems) {
src = [
'fun fromTactDocs() {',
lines.map(line => ` ${line}`).join('\n'),
'}',
].join('\n');
}

// Encode to URL-friendly Base64
const encoded = Buffer.from(src).toString('base64url');

// Double-check the number of characters in the link
const link = `https://ide.ton.org?lang=tact&code=${encoded}`;
if (link.length > maxAllowedCharacters) { return undefined; }

/** @type import('mdast').Html */
const button = {
type: 'html',
value: [
// Constructing opening <a> tag
[
// Open the tag
'<a',
// Make links opened in new tab
'target="_blank"',
// Set styles
'class="web-ide-link"',
// Add hyperref with > to close the tag
`href="${link}">`,
].join(' '),
// The text to click on
'<span class="web-ide-link-span">▶️ Open in Web IDE</span>',
// Closing </a> tag
'</a>',
].join(''),
};

// Place the button after the code block
parent.children.splice(index + 1, 0, button);
});
}
}
31 changes: 31 additions & 0 deletions docs/src/starlight.custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,34 @@ td>a>code {
code:not(pre *) {
background-color: var(--sl-color-bg-inline-code) !important;
}

/* Stylizing <a> links to Web IDE */
.web-ide-link {
display: flex;
justify-content: right;
margin-top: 0.25rem;
margin-bottom: 1rem;
text-decoration: none;
}

/* Stylizing <span> tags inside <a> links to Web IDE */
.web-ide-link-span {
/* from .sl-badge */
display: inline-block;
border: 1px solid var(--sl-color-border-badge);
border-radius: 0.25rem;
font-family: var(--sl-font-system-mono);
line-height: normal;
color: var(--sl-color-text-badge);
background-color: var(--sl-color-bg-badge);
overflow-wrap: anywhere;

/* from .default */
--sl-color-bg-badge: var(--sl-badge-default-bg);
--sl-color-border-badge: var(--sl-badge-default-border);
--sl-color-text-badge: var(--sl-badge-default-text);

/* from .small */
font-size: var(--sl-text-xs);
padding: 0.125rem 0.25rem;
}

0 comments on commit cf260ea

Please sign in to comment.