Repository: jxnblk/contrast-swatch
Branch: master
Commit: 5302fe5f0f3b
Files: 5
Total size: 6.8 KB
Directory structure:
gitextract_uiug9yv8/
├── .gitignore
├── README.md
├── index.js
├── now.json
└── package.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.cache
public
================================================
FILE: README.md
================================================
[![][hero]][hero]
[hero]: https://contrast.now.sh/cff/40f?size=256
# Contrast Swatch
Image microservice for color contrast information
[![][a]][a]
[![][b]][b]
[![][c]][c]
[a]: https://contrast.now.sh/bcf/409
[b]: https://contrast.now.sh/98f/206
[c]: https://contrast.now.sh/fff/40f
## Usage
Contrast swatch images can be used in any place an image is rendered.
The URL accepts a foreground and background color.
[`https://contrast.now.sh/cff/40f`][example]
[example]: https://contrast.now.sh/cff/40f
**HTML**
```html
<img src="https://contrast.now.sh/cff/07c" alt="color contrast indicator" />
```
**Markdown**
```md

```
## React
You can wrap the image in a React component (or any templating engine) for generating documentation.
```js
import React from 'react'
export default ({
foreground,
background,
...props
}) =>
<img
{...props}
src={`https://contrast.now.sh/${foreground}/${background}`}
alt='color contrast indicator'
/>
```
## RGB
Compare two `rgb` values, or an `rgb` and a hex value:
```
https://contrast.now.sh/rgb(204,255,255)/40f
```
[![][rgb]][rgb]
[rgb]: https://contrast.now.sh/rgb(204,255,255)/40f
## Customization
Use URL queries to customize the styles.
```
https://contrast.now.sh/cff/40f?width=256&height=96&fontSize=1.25
```
**Pass/Fail Label**
[![][pass]][pass]
[![][fail]][fail]
[pass]: https://contrast.now.sh/cff/40f?width=256&height=128&label=1
[fail]: https://contrast.now.sh/a6f/40f?width=256&height=128&label=1
**Font Size**
[![][smallfont]][smallfont]
[![][largefont]][largefont]
[smallfont]: https://contrast.now.sh/cff/40f?width=256&height=128&fontSize=0.5
[largefont]: https://contrast.now.sh/cff/40f?width=256&height=128&fontSize=2
**Size**
[![][large]][large]
[![][small]][small]
[large]: https://contrast.now.sh/cff/40f?size=320
[small]: https://contrast.now.sh/cff/40f?size=48
**Width & Height**
[![][wide]][wide]
[![][tall]][tall]
[wide]: https://contrast.now.sh/cff/40f?width=256&height=48
[tall]: https://contrast.now.sh/cff/40f?width=32&height=48
**Custom Text**
[![][text]][text]
[text]: https://contrast.now.sh/cff/40f?width=256&text=Aa
**Font Weight**
[![][weight]][weight]
[weight]: https://contrast.now.sh/cff/40f?fontWeight=900&width=256
**Radius**
[![][rounded]][rounded]
[![][circle]][circle]
[rounded]: https://contrast.now.sh/cff/40f?radius=8
[circle]: https://contrast.now.sh/cff/40f?radius=48
## Options
Option | Description
---|---
`size` | Width & height in pixels
`width` | Width of image in pixels
`height` | Height of image in pixels (font size will scale based on height)
`fontSize` | Relative font size (default 1)
`fontWeight`| Font weight (default 1)
`label` | Show a pass/fail label based on the [WCAG Criteria][wcag]
`radius` | Border radius
`baseline` | Shift text baseline down
`text` | Render any custom text
## Metadata
A JSON response with color contrast information can be fetched by adding the `type=json` query to the URL.
```
https://contrast.now.sh/cff/40f?type=json
```
**Note:** the returned JSON schema might change in a future version
[wcag]: https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html
## Related
- [Colorable](https://colorable.jxnblk.com)
- [Use Contrast](https://usecontrast.com/)
MIT License
================================================
FILE: index.js
================================================
const Color = require('color')
const { createElement: h } = require('react')
const { renderToStaticMarkup } = require('react-dom/server')
const homepage = 'https://github.com/jxnblk/contrast-swatch'
const parseURL = (req) => {
const { foreground, background, ...query } = req.query
if (!foreground || !background) return null
return {
foreground,
background,
query,
}
}
const HEX = /^[A-Fa-f0-9]{3,6}$/
const getColor = (raw) => {
if (HEX.test(raw)) raw = '#' + raw
try {
return Color(raw)
} catch (e) {
return null
}
}
const getLabel = contrast => {
if (contrast >= 7) return 'AAA'
if (contrast >= 4.5) return 'AA'
if (contrast >= 3) return 'lg'
return 'Fail'
}
const parseColors = (data) => {
const foreground = getColor(data.foreground)
const background = getColor(data.background)
const contrast = foreground.contrast(background)
const label = getLabel(contrast)
return {
foreground,
background,
raw: data,
hex: {
foreground: foreground.hex(),
background: background.hex(),
},
rgb: {
foreground: foreground.rgb().array(),
background: background.rgb().array(),
},
contrast,
label,
}
}
const round = n => Math.floor(100 * n) / 100
const svg = req => {
const data = parseURL(req)
if (!data) return null
const colors = parseColors(data)
const opts = Object.assign({
width: 128,
height: 128,
font: 'system-ui,sans-serif',
fontSize: 1,
fontWeight: 700,
baseline: 0,
label: false,
radius: 0,
}, data.query)
const width = Number(opts.size || opts.width)
const height = Number(opts.size || opts.height)
const xwidth = 32 * (width / height)
const fontSize = Number(opts.fontSize) * 8
let text = [ round(colors.contrast) ]
if (Boolean(opts.label)) {
text.push(colors.label)
}
if (opts.text) text = [opts.text]
const el = h('svg', {
xmlns: 'http://www.w3.org/2000/svg',
width,
height,
viewBox: `0 0 ${xwidth} 32`,
fill: colors.hex.foreground,
style: {
fontFamily: opts.font,
fontWeight: opts.fontWeight,
fontSize,
},
},
h('rect', {
width: xwidth,
height: 32,
fill: colors.hex.background,
rx: opts.radius,
}),
h('text', {
textAnchor: 'middle',
x: xwidth / 2,
y: 16 + Number(opts.baseline),
dominantBaseline: 'middle',
},
text.join(' ')
)
)
const svg = renderToStaticMarkup(el)
return {
...data,
colors,
svg,
}
}
module.exports = async (req, res) => {
const data = svg(req)
if (!data) return
switch (data.query.type) {
case 'json':
return res.send(data)
}
res.setHeader('Content-Type', 'image/svg+xml;charset=utf-8')
res.send(data.svg)
}
================================================
FILE: now.json
================================================
{
"version": 2,
"alias": "contrast.now.sh",
"public": true,
"builds": [
{
"src": "index.js",
"use": "@now/node"
}
],
"routes": [
{
"src": "/",
"status": 302,
"headers": {
"Location": "https://github.com/jxnblk/contrast-swatch"
},
"continue": true
},
{
"src": "/(?<fg>[^/]+)/(?<bg>[^/]+)",
"dest": "/index.js?foreground=$fg&background=$bg",
"headers": {
"Cache-Control": "max-age=604800"
}
}
]
}
================================================
FILE: package.json
================================================
{
"private": true,
"name": "server",
"version": "0.0.1",
"main": "index.js",
"scripts": {
"dev": "now dev"
},
"dependencies": {
"color": "^3.1.2",
"react": "^16.8.6",
"react-dom": "^16.8.6"
}
}
gitextract_uiug9yv8/ ├── .gitignore ├── README.md ├── index.js ├── now.json └── package.json
SYMBOL INDEX (1 symbols across 1 files)
FILE: index.js
constant HEX (line 19) | const HEX = /^[A-Fa-f0-9]{3,6}$/
Condensed preview — 5 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (8K chars).
[
{
"path": ".gitignore",
"chars": 14,
"preview": ".cache\npublic\n"
},
{
"path": "README.md",
"chars": 3381,
"preview": "\n[![][hero]][hero]\n\n[hero]: https://contrast.now.sh/cff/40f?size=256\n\n# Contrast Swatch\n\nImage microservice for color co"
},
{
"path": "index.js",
"chars": 2793,
"preview": "const Color = require('color')\nconst { createElement: h } = require('react')\nconst { renderToStaticMarkup } = require('r"
},
{
"path": "now.json",
"chars": 515,
"preview": "{\n \"version\": 2,\n \"alias\": \"contrast.now.sh\",\n \"public\": true,\n \"builds\": [\n {\n \"src\": \"index.js\",\n \"us"
},
{
"path": "package.json",
"chars": 226,
"preview": "{\n \"private\": true,\n \"name\": \"server\",\n \"version\": \"0.0.1\",\n \"main\": \"index.js\",\n \"scripts\": {\n \"dev\": \"now dev\""
}
]
About this extraction
This page contains the full source code of the jxnblk/contrast-swatch GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 5 files (6.8 KB), approximately 2.2k tokens, and a symbol index with 1 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.