Skip to content

Commit

Permalink
docs: fix layout
Browse files Browse the repository at this point in the history
  • Loading branch information
adrian-ub committed Oct 25, 2024
1 parent 40e4b9a commit 126b6c1
Show file tree
Hide file tree
Showing 18 changed files with 979 additions and 164 deletions.
122 changes: 83 additions & 39 deletions docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ import angular from '@analogjs/astro-angular'
import mdx from '@astrojs/mdx'
import sitemap from '@astrojs/sitemap'
import tailwind from '@astrojs/tailwind'
import { transformerMetaHighlight } from '@shikijs/transformers'
import { getHighlighter } from '@shikijs/compat'
import { defineConfig } from 'astro/config'

import rehypeAutolinkHeadings from 'rehype-autolink-headings'
import { rehypePrettyCode } from 'rehype-pretty-code'
import rehypeSlug from 'rehype-slug'
import { codeImport } from 'remark-code-import'
import { visit } from 'unist-util-visit'
import { rehypeNpmCommand } from './plugins/rehype-npm-command'
import { siteConfig } from './src/config/site'

// Función recursiva para extraer todos los valores de texto
function extractText(node) {
if (node.type === 'text') {
return node.value
Expand Down Expand Up @@ -46,56 +49,97 @@ export default defineConfig({
}),
],
markdown: {
shikiConfig: {
theme: 'github-dark',
transformers: [transformerMetaHighlight()],
},
syntaxHighlight: false,
remarkPlugins: [codeImport],
rehypePlugins: [
rehypeSlug,
[
rehypePrettyCode,
{
theme: 'github-dark',
getHighlighter,
onVisitLine(node) {
// Prevent lines from collapsing in `display: grid` mode, and allow empty
// lines to be copy/pasted
if (node.children.length === 0) {
node.children = [{ type: 'text', value: ' ' }]
}
},
onVisitHighlightedLine(node) {
node.properties.className = [
...(node.properties.className ?? []),
'line--highlighted',
]
},
onVisitHighlightedWord(node) {
node.properties.className = ['word--highlighted']
},
},
],
() => (tree) => {
visit(tree, 'element', (node) => {
if (node.tagName !== 'pre')
return

const [codeEl] = node.children

if (codeEl.tagName !== 'code')
return
visit(tree, (node) => {
if (node?.type === 'element' && node?.tagName === 'pre') {
const [codeEl] = node.children
if (codeEl.tagName !== 'code') {
return
}

const rawString = extractText(codeEl)
if (codeEl.data?.meta) {
// Extract event from meta and pass it down the tree.
const regex = /event="([^"]*)"/
const match = codeEl.data?.meta.match(regex)
if (match) {
node.__event__ = match ? match[1] : null
codeEl.data.meta = codeEl.data.meta.replace(regex, '')
}
}

node.properties = node.properties || {}
node.properties.rawString = rawString
const rawString = extractText(codeEl)
node.properties = node.properties || {}
node.properties.__rawString__ = rawString
}
})
},
() => (tree) => {
visit(tree, 'element', (node) => {
if (node.tagName !== 'pre')
return
visit(tree, (node) => {
if (node?.type === 'element' && node?.tagName === 'div') {
if (!('data-rehype-pretty-code-fragment' in node.properties)) {
return
}

const rawString = node.properties.rawString
const preElement = node.children.at(-1)
if (preElement.tagName !== 'pre') {
return
}

// npm install.
if (rawString?.startsWith('npm install')) {
node.properties.npmCommand = rawString
node.properties.yarnCommand = rawString.replace('npm install', 'yarn add')
node.properties.pnpmCommand = rawString.replace('npm install', 'pnpm add')
}
preElement.properties.__withMeta__
= node.children.at(0).tagName === 'div'
preElement.properties.__rawString__ = node.__rawString__

// npx create.
if (rawString?.startsWith('npx create-')) {
node.properties.npmCommand = rawString
node.properties.yarnCommand = rawString.replace('npx create-', 'yarn create ')
node.properties.pnpmCommand = rawString.replace('npx create-', 'pnpm create ')
}
if (node.__src__) {
preElement.properties.__src__ = node.__src__
}

// npx.
if (rawString?.startsWith('npx') && !rawString.startsWith('npx create-')) {
node.properties.npmCommand = rawString
node.properties.yarnCommand = rawString
node.properties.pnpmCommand = rawString.replace('npx', 'pnpm dlx')
if (node.__event__) {
preElement.properties.__event__ = node.__event__
}

if (node.__style__) {
preElement.properties.__style__ = node.__style__
}
}
})
},
rehypeNpmCommand,
[
rehypeAutolinkHeadings,
{
properties: {
className: ['subheading-anchor'],
ariaLabel: 'Link to section',
},
},
],
],
},
redirects: {
Expand Down
8 changes: 8 additions & 0 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,21 @@
"@ng-icons/lucide": "^29.5.0",
"@ng-icons/radix-icons": "^29.5.0",
"@radix-ng/primitives": "^0.15.0",
"@shikijs/compat": "^1.22.1",
"astro": "^4.16.6",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"ngx-sonner": "^2.0.2",
"rehype-autolink-headings": "^7.1.0",
"rehype-pretty-code": "^0.14.0",
"rehype-slug": "^6.0.0",
"remark-code-import": "^1.2.0",
"rxjs": "^7.8.1",
"tailwind-merge": "^2.5.2",
"tailwindcss": "^3.4.13",
"tailwindcss-animate": "^1.0.7",
"tslib": "^2.8.0",
"unist-builder": "3.0.0",
"unist-util-visit": "^5.0.0",
"zone.js": "~0.14.10"
},
Expand All @@ -50,6 +56,8 @@
"@shikijs/transformers": "^1.20.0",
"@types/lodash.template": "^4.5.3",
"lodash.template": "^4.5.0",
"mdast-util-toc": "^7.1.0",
"remark": "^15.0.1",
"typescript": "~5.5.0"
}
}
160 changes: 160 additions & 0 deletions docs/plugins/rehype-component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import fs from 'node:fs'
import path from 'node:path'
import process from 'node:process'
import { u } from 'unist-builder'
import { visit } from 'unist-util-visit'

import { Index } from '../src/__registry__'
import { styles } from '../src/registry/registry-styles'
import type { UnistNode, UnistTree } from '../types/unist'

export function rehypeComponent() {
return async (tree: UnistTree) => {
visit(tree, (node: UnistNode) => {
// src prop overrides both name and fileName.
const { value: srcPath }
= (getNodeAttributeByName(node, 'src') as {
name: string
value?: string
type?: string
}) || {}

if (node.name === 'ComponentSource') {
const name = getNodeAttributeByName(node, 'name')?.value as string
const fileName = getNodeAttributeByName(node, 'fileName')?.value as
| string
| undefined

if (!name && !srcPath) {
return null
}

try {
for (const style of styles) {
let src: string

if (srcPath) {
src = srcPath
}
else {
const component = Index[style.name][name]
src = fileName
? component.files.find((file: string) => {
return (
file.endsWith(`${fileName}.tsx`)
|| file.endsWith(`${fileName}.ts`)
)
}) || component.files[0]
: component.files[0]
}

// Read the source file.
const filePath = path.join(process.cwd(), src)
let source = fs.readFileSync(filePath, 'utf8')

// Replace imports.
// TODO: Use @swc/core and a visitor to replace this.
// For now a simple regex should do.
source = source.replaceAll(
`@/registry/${style.name}/`,
'@/components/',
)
source = source.replaceAll('export default', 'export')

// Add code as children so that rehype can take over at build time.
node.children?.push(
u('element', {
tagName: 'pre',
properties: {
__src__: src,
__style__: style.name,
},
attributes: [
{
name: 'styleName',
type: 'mdxJsxAttribute',
value: style.name,
},
],
children: [
u('element', {
tagName: 'code',
properties: {
className: ['language-tsx'],
},
children: [
{
type: 'text',
value: source,
},
],
}),
],
}),
)
}
}
catch (error) {
console.error(error)
}
}

if (node.name === 'ComponentPreview') {
const name = getNodeAttributeByName(node, 'name')?.value as string

if (!name) {
return null
}

try {
for (const style of styles) {
const component = Index[style.name][name]
const src = component.files[0]

// Read the source file.
const filePath = path.join(process.cwd(), src)
let source = fs.readFileSync(filePath, 'utf8')

// Replace imports.
source = source.replaceAll(
`@/registry/${style.name}/`,
'@/components/',
)
source = source.replaceAll('export default', 'export')

// Add code as children so that rehype can take over at build time.
node.children?.push(
u('element', {
tagName: 'pre',
properties: {
__src__: src,
},
children: [
u('element', {
tagName: 'code',
properties: {
className: ['language-tsx'],
},
children: [
{
type: 'text',
value: source,
},
],
}),
],
}),
)
}
}
catch (error) {
console.error(error)
}
}
})
}
}

function getNodeAttributeByName(node: UnistNode, name: string): { name: string, value: unknown, type?: string } | undefined {
return node.attributes?.find(attribute => attribute.name === name)
}
Loading

0 comments on commit 126b6c1

Please sign in to comment.