Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
44 changes: 44 additions & 0 deletions .github/workflows/website.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Website
on:
push:
branches:
- main
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: true
jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
name: deploy website
steps:
- name: Checkout the repository
uses: actions/checkout@v7
- name: Install pnpm
uses: pnpm/action-setup@v6
with:
version: 11
- name: Install Node.js
uses: actions/setup-node@v7
with:
node-version: 24
cache: 'pnpm'
- name: Install dependencies
run: pnpm install
- name: Build website
run: pnpm docs:build
- name: Setup Pages
uses: actions/configure-pages@v6
- name: Upload artifact
uses: actions/upload-pages-artifact@v5
with:
path: './website/dist'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v5
3,977 changes: 3,880 additions & 97 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

145 changes: 145 additions & 0 deletions website/astro.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { defineConfig } from 'astro/config'
import { unified } from '@astrojs/markdown-remark'
import starlight from '@astrojs/starlight'
import llmsTxt from 'starlight-llms-txt'
import { viewTransitions } from 'astro-vtbot/starlight-view-transitions'
import { rehypeNormalizeContent } from './rehype.js'

export default defineConfig({
site: 'https://srcset.js.org',
markdown: {
processor: unified({
rehypePlugins: [rehypeNormalizeContent]
})
},
integrations: [
starlight({
title: 'srcset',
description: 'Highly customizable tools for generating responsive images: build-time generation, image proxy adapters and framework components - without vendor and server lock-in.',
favicon: '/favicon.svg',
head: [
{
// GitHub Pages can't set COOP/COEP headers, which StackBlitz
// WebContainers embeds require; this service worker injects them
tag: 'script',
attrs: {
src: '/coi-serviceworker.js'
}
},
{
tag: 'meta',
attrs: {
name: 'format-detection',
content: 'telephone=no'
}
},
{
tag: 'meta',
attrs: {
property: 'og:image',
content: 'https://srcset.js.org/og-image.jpg'
}
},
{
tag: 'meta',
attrs: {
property: 'og:image:width',
content: '1200'
}
},
{
tag: 'meta',
attrs: {
property: 'og:image:height',
content: '630'
}
},
{
tag: 'meta',
attrs: {
property: 'og:image:type',
content: 'image/jpeg'
}
},
{
tag: 'meta',
attrs: {
name: 'twitter:card',
content: 'summary_large_image'
}
},
{
tag: 'meta',
attrs: {
name: 'twitter:image',
content: 'https://srcset.js.org/og-image.jpg'
}
}
],
social: [
{
label: 'GitHub',
icon: 'github',
href: 'https://github.com/TrigenSoftware/srcset'
}
],
editLink: {
baseUrl: 'https://github.com/TrigenSoftware/srcset/edit/main/website/'
},
plugins: [llmsTxt(), viewTransitions()],
sidebar: [
{
label: 'Getting Started',
items: [{
autogenerate: {
directory: 'getting-started'
}
}]
},
{
label: 'Integrations',
items: [{
autogenerate: {
directory: 'integrations'
}
}]
},
{
label: 'Components',
link: '/components/'
},
{
label: 'Proxies',
items: [{
autogenerate: {
directory: 'proxies'
}
}]
},
{
label: 'API',
items: [{
autogenerate: {
directory: 'api'
}
}]
},
{
label: 'Examples',
items: [{
autogenerate: {
directory: 'examples'
}
}]
}
],
customCss: ['./src/styles/global.css'],
expressiveCode: {
themes: ['github-dark-high-contrast', 'github-light-default'],
frames: {
extractFileNameFromCode: false
}
}
})
]
})
34 changes: 34 additions & 0 deletions website/oxlint.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { defineConfig } from '@trigen/oxlint'
import moduleConfig from '@trigen/oxlint-config/module'
import tsTypeCheckedConfig from '@trigen/oxlint-config/typescript-type-checked'
import rootConfig from '../oxlint.config.ts'

export default defineConfig({
ignorePatterns: [
'.astro/',
'dist/',
'src/content.config.ts',
'src/env.d.ts'
],
extends: [
rootConfig,
moduleConfig,
tsTypeCheckedConfig
],
env: {
node: true
},
overrides: [
{
// Classic script served as a static asset, not a module
files: ['public/**'],
env: {
browser: true,
serviceworker: true
},
rules: {
'import/unambiguous': 'off'
}
}
]
})
37 changes: 37 additions & 0 deletions website/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "website",
"type": "module",
"private": true,
"version": "0.0.0",
"description": "Documentation website for srcset.",
"author": "dangreen",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/TrigenSoftware/srcset.git",
"directory": "website"
},
"bugs": {
"url": "https://github.com/TrigenSoftware/srcset/issues"
},
"scripts": {
"clear": "del ./.astro ./dist",
"dev": "astro dev",
"build": "run [ astro check ] [ astro build ]",
"preview": "astro preview",
"astro": "astro",
"lint": "oxlint"
},
"dependencies": {
"@astrojs/check": "^0.9.9",
"@astrojs/markdown-remark": "^7.2.0",
"@astrojs/starlight": "^0.41.1",
"astro": "^7.0.4",
"astro-vtbot": "^3.0.0",
"starlight-llms-txt": "^0.11.0"
},
"devDependencies": {
"sharp": "^0.35.0",
"typescript": "^6.0.0"
}
}
47 changes: 47 additions & 0 deletions website/public/coi-serviceworker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
const pagesWithEmbeds = /^\/examples(?:\/|$)/

if (typeof window === 'undefined') {
self.addEventListener('install', () => self.skipWaiting())
self.addEventListener('activate', event => event.waitUntil(self.clients.claim()))

self.addEventListener('fetch', (event) => {
const request = event.request

if (request.mode !== 'navigate' || !pagesWithEmbeds.test(new URL(request.url).pathname)) {
return
}

event.respondWith(
fetch(request).then((response) => {
if (response.status === 0) {
return response
}

const newHeaders = new Headers(response.headers)

newHeaders.set('Cross-Origin-Embedder-Policy', 'require-corp')
newHeaders.set('Cross-Origin-Opener-Policy', 'same-origin')

return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: newHeaders
})
})
)
})
} else if (window.crossOriginIsolated === false && window.isSecureContext && navigator.serviceWorker) {
void navigator.serviceWorker.register(window.document.currentScript.src).then((registration) => {
if (!pagesWithEmbeds.test(window.location.pathname)) {
return
}

if (registration.active && !navigator.serviceWorker.controller) {
window.location.reload()
} else {
navigator.serviceWorker.addEventListener('controllerchange', () => window.location.reload(), {
once: true
})
}
})
}
1 change: 1 addition & 0 deletions website/public/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added website/public/og-image.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions website/public/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
User-agent: *
Allow: /

Sitemap: https://srcset.js.org/sitemap-index.xml
73 changes: 73 additions & 0 deletions website/rehype.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
function visitElements(node, callback) {
const children = node.children

if (!Array.isArray(children)) {
return
}

for (let index = 0; index < children.length; index++) {
const child = children[index]

if (child.type === 'element') {
callback(child, index, node)
}

visitElements(child, callback)
}
}

function normalizeInternalHref(href) {
if (
typeof href !== 'string'
|| !href
|| href.startsWith('#')
|| href.startsWith('//')
|| /^[a-z][a-z\d+.-]*:/i.test(href)
) {
return undefined
}

const match = href.match(/^([^?#]*)([?#].*)?$/)
const pathname = match?.[1] || ''

if (
!pathname
|| pathname === '/'
|| pathname.endsWith('/')
|| /(?:^|\/)[^/]+\.[^/]+$/.test(pathname)
) {
return undefined
}

return `${pathname}/${match?.[2] || ''}`
}

export function rehypeNormalizeContent() {
return (tree) => {
visitElements(tree, (node, index, parent) => {
if (node.tagName === 'a') {
const href = normalizeInternalHref(node.properties?.href)

if (href) {
node.properties.href = href
}
}

if (
node.tagName !== 'table'
|| parent?.properties?.className?.includes('sr-table-wrapper')
) {
return
}

parent.children[index] = {
type: 'element',
tagName: 'div',
properties: {
className: ['sr-table-wrapper']
},
children: [node]
}
})
}
}
Loading