-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
8 changed files
with
270 additions
and
2 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
<script lang="ts"> | ||
import type { PageData } from './$types'; | ||
import Spacing from '$lib/public/legacy/spacing.svelte'; | ||
import Color from './color.svelte'; | ||
export let data: PageData; | ||
</script> | ||
|
||
<Spacing --min="175px" --med="200px" --max="200px" /> | ||
|
||
<svelte:head> | ||
<title>Colors | ACM at CSUF</title> | ||
</svelte:head> | ||
|
||
<main class="responsive-width"> | ||
<section id="top"> | ||
<div class="header"> | ||
<h1 class="size-lg">Colors</h1> | ||
</div> | ||
<ul> | ||
{#each data.colors as color (color.id)} | ||
<li><Color data={color} /></li> | ||
{/each} | ||
</ul> | ||
</section> | ||
|
||
<p> | ||
<a href="#top">Back to top</a> | <a href="/global.css">global.css</a> | ||
</p> | ||
</main> | ||
|
||
<Spacing --min="40px" --med="95px" --max="120px" /> | ||
|
||
<style lang="scss"> | ||
.responsive-width { | ||
width: min(80ch, 80vw); | ||
margin: 0 auto; | ||
} | ||
h1 { | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
margin: 0; | ||
} | ||
main { | ||
width: 100%; | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
justify-content: center; | ||
section { | ||
width: min(800px, 80vw); | ||
max-width: 540px; | ||
margin: 0 auto; | ||
margin-bottom: 50px; | ||
p { | ||
margin: 1em 0; | ||
word-break: break-word; | ||
} | ||
a { | ||
transition: 0.25s ease-in-out; | ||
&:hover { | ||
color: var(--acm-blue); | ||
} | ||
} | ||
} | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import type { PageLoadEvent } from './$types'; | ||
import { parseGlobalCSS } from './colors'; | ||
|
||
export async function load({ fetch }: PageLoadEvent) { | ||
const globalCSS = await fetch('/global.css').then((r) => r.text()); | ||
return { colors: parseGlobalCSS(globalCSS) }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<script lang="ts"> | ||
import type { Color } from './colors'; | ||
export let data: Color; | ||
</script> | ||
|
||
<code class="color-id" style:--color={data.hex}>{data.id}</code> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<script lang="ts"> | ||
import type { Color } from './colors'; | ||
import { copy } from '$lib/public/copy/copy'; | ||
export let data: Color; | ||
function copyColor() { | ||
copy(`var(${data.id})`, 'Copied color to clipboard', 'Failed to copy color to clipboard'); | ||
} | ||
</script> | ||
|
||
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-noninteractive-element-to-interactive-role --> | ||
<code | ||
role="button" | ||
tabindex="0" | ||
class="color-pill" | ||
style:--color={data.hex} | ||
on:click={() => copyColor()}>{data.hex} ({data.rgb.join(', ')})</code | ||
> | ||
|
||
<style> | ||
.color-pill { | ||
text-decoration: underline; | ||
text-decoration-color: var(--color); | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<script lang="ts"> | ||
import type { Color } from './colors'; | ||
import ColorPill from './color-pill.svelte'; | ||
import ColorID from './color-id.svelte'; | ||
export let data: Color; | ||
</script> | ||
|
||
<div id={data.id} class="color-container size-md" style:--color={data.hex}> | ||
<ColorID {data} />: | ||
<ColorPill {data} /> | ||
</div> | ||
|
||
<style> | ||
.color-container { | ||
border-left: 5px solid var(--color); | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import type { Stylesheet, Declaration } from 'css'; | ||
import { parse } from 'css'; | ||
|
||
export interface Color { | ||
id: string; | ||
hex: string; | ||
rgb: [number, number, number]; | ||
} | ||
|
||
export function parseGlobalCSS(source: string): Color[] { | ||
const ast = parse(source); | ||
return fromAST(ast); | ||
} | ||
|
||
function fromAST(ast: Stylesheet): Color[] { | ||
const colors: Color[] = []; | ||
for (const rule of ast.stylesheet?.rules ?? []) { | ||
if (!('selectors' in rule)) { | ||
continue; | ||
} | ||
|
||
if (!rule.selectors?.find((s) => s.endsWith(':root'))) { | ||
continue; | ||
} | ||
|
||
for (const decl of rule?.declarations ?? []) { | ||
const color = fromDecl(decl); | ||
if (color) { | ||
colors.push(color); | ||
} | ||
} | ||
} | ||
|
||
return colors.toSorted((a, b) => a.id.localeCompare(b.id)); | ||
} | ||
|
||
function fromDecl({ property, value }: Declaration): Color | null { | ||
if (property === undefined || value === undefined) { | ||
return null; | ||
} | ||
|
||
switch (true) { | ||
case /^\d{1,3}, \d{1,3}, \d{1,3}$/.test(value): { | ||
const [r, g, b] = value.split(', ').map(Number); | ||
return { | ||
id: property, | ||
hex: rgb2hex(r, g, b), | ||
rgb: [r, g, b], | ||
}; | ||
} | ||
|
||
case /^#([0-9a-f]{3}){1,2}$/i.test(value): { | ||
const [r, g, b] = hex2rgb(value); | ||
return { | ||
id: property, | ||
hex: value, | ||
rgb: [r, g, b], | ||
}; | ||
} | ||
|
||
default: { | ||
return null; | ||
} | ||
} | ||
} | ||
|
||
function hex2rgb(hex: string): [number, number, number] { | ||
hex = hex.trim().replace(/^#/, ''); | ||
return [ | ||
parseInt(hex.slice(1, 3), 16), | ||
parseInt(hex.slice(3, 5), 16), | ||
parseInt(hex.slice(5, 7), 16), | ||
]; | ||
} | ||
|
||
function rgb2hex(r: number, g: number, b: number): string { | ||
return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b | ||
.toString(16) | ||
.padStart(2, '0')}`; | ||
} |