Skip to content

Commit 95fe37f

Browse files
committed
ci(primitives): transition to new css primitives
GitHub no longer distributes primitives in JSON format. Also, the names of the values (CSS variables) have changed. Most of the new names correspond 1-to-1 with one of the old names. Some colors have also changed slightly (e.g. `fg-default`), but otherwise remain mostly the same. See https://primer.style/foundations/primitives/migrating
1 parent 4f44a5c commit 95fe37f

14 files changed

+473
-354
lines changed

.github/workflows/csstolua.lua

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
local res = {}
2+
3+
local function is_valid_ident(ident)
4+
local keyword = {
5+
['do'] = true,
6+
['end'] = true,
7+
['if'] = true,
8+
['then'] = true,
9+
['local'] = true,
10+
['function'] = true,
11+
['return'] = true,
12+
['while'] = true,
13+
['repeat'] = true,
14+
['until'] = true,
15+
['for'] = true,
16+
['in'] = true,
17+
['true'] = true,
18+
['false'] = true,
19+
['nil'] = true,
20+
}
21+
22+
if type(ident) ~= 'string' or keyword[ident] then
23+
return false
24+
end
25+
26+
return ident:find('^[_%a][_%w]*$') ~= nil
27+
end
28+
29+
local function set(cssvar, v)
30+
local before, last = cssvar:match('^(.+)%-+(.+)$')
31+
32+
-- Top-level key
33+
if not last then
34+
res[tonumber(cssvar) or cssvar] = v
35+
return
36+
end
37+
38+
last = tonumber(last) or last
39+
local cur = res
40+
for k in before:gmatch('[^%-_]+') do
41+
k = tonumber(k) or k
42+
cur[k] = cur[k] or {}
43+
cur = cur[k]
44+
end
45+
46+
-- Path is too short: append `default`
47+
if type(cur[last]) == 'table' then
48+
cur, last = cur[last], 'default'
49+
end
50+
51+
-- Check duplicates
52+
assert(cur[last] == nil or cur[last] == v)
53+
54+
cur[last] = v
55+
end
56+
57+
local function print_recur(value, _ind)
58+
_ind = _ind or 0
59+
60+
if type(value) == 'table' then
61+
io.write('m {')
62+
_ind = _ind + 2
63+
64+
for k, v in pairs(value) do
65+
local fmt = '[%q] = '
66+
if type(k) == 'number' then
67+
fmt = '[%s] = '
68+
elseif is_valid_ident(k) then
69+
fmt = '%s = '
70+
end
71+
io.write(('\n%s' .. fmt):format((' '):rep(_ind), k))
72+
print_recur(v, _ind)
73+
io.write(',')
74+
end
75+
76+
_ind = _ind - 2
77+
io.write(('\n%s}'):format((' '):rep(_ind)))
78+
else
79+
io.write(('%q'):format(value))
80+
end
81+
end
82+
83+
local defs = {}
84+
for ln in io.lines() do
85+
local k, v = ln:match('^%s*%-%-(%w.-)%s*:%s*(.-)%s*;%s*$')
86+
if k then
87+
table.insert(defs, { k, v })
88+
end
89+
end
90+
91+
-- Since we are un-flattening, ensure that longer keys (whose prefix could
92+
-- match another key) are visited first.
93+
table.sort(defs, function(a, b)
94+
return a[1] > b[1]
95+
end)
96+
97+
for _, kv in ipairs(defs) do
98+
set(unpack(kv))
99+
end
100+
101+
-- Add `scale` key for convenience and backwards-compatibility
102+
assert(res.scale == nil)
103+
res.scale = {}
104+
for color, scale in pairs(res.base.color) do
105+
if type(scale) == 'table' then
106+
res.scale[color] = {}
107+
for i, v in pairs(scale) do
108+
res.scale[color][i + 1] = v
109+
end
110+
else
111+
res.scale[color] = scale
112+
end
113+
end
114+
115+
-- NOTE: the metatable `mt` helps to catch errors (e.g. during CI tests)
116+
io.write([=[
117+
local mt = {
118+
__index = function(_, k)
119+
error('invalid index: ' .. k)
120+
end,
121+
}
122+
---@generic T
123+
---@param tbl T
124+
---@return T
125+
local function m(tbl)
126+
return setmetatable(tbl, mt)
127+
end
128+
local M = ]=])
129+
130+
print_recur(res)
131+
132+
io.write('\n')

.github/workflows/update-color-primitives.yml

+15-10
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
1-
name: Get/Update Primer Color Primitives
1+
name: Get/Update Primer Primitives
22

33
env:
44
_DEST_DIR: "${{ github.workspace }}/lua/github-theme/palette/primitives"
5-
_JSON_DIR: "${{ github.workspace }}/node_modules/@primer/primitives/dist/json/colors"
5+
_SRC_DIR: "${{ github.workspace }}/node_modules/@primer/primitives/dist/internalCss"
66
_LICENSE_GLOB: "${{ github.workspace }}/node_modules/@primer/primitives/[Ll][Ii][Cc][Ee][Nn][Ss][Ee]*"
77
_PRIMITIVES_PKGJSON: "${{ github.workspace }}/node_modules/@primer/primitives/package.json"
8+
_CSSTOLUA: "${{ github.workspace }}/.github/workflows/csstolua.lua"
89

910
on:
1011
workflow_dispatch:
1112
schedule:
12-
# 3x per week (every other day) at 12:40pm Pacific Time
13-
- cron: "40 19 * * 1,3,5"
13+
# once a week, every Monday at 12:40pm Pacific Time
14+
- cron: "40 19 * * 1"
1415

1516
jobs:
16-
get-colors:
17+
install-primitives:
1718
runs-on: ubuntu-latest
1819
permissions:
1920
checks: write
@@ -25,6 +26,9 @@ jobs:
2526

2627
steps:
2728
- uses: actions/checkout@v4
29+
- uses: rhysd/action-setup-vim@v1
30+
with:
31+
neovim: true
2832

2933
- uses: actions/setup-node@v4
3034
with:
@@ -34,21 +38,22 @@ jobs:
3438
- run: npm i @primer/primitives@latest
3539

3640
- run: |
37-
set -u +f
41+
set -eu +f
3842
shopt -s nocaseglob failglob
3943
license="$(<$_LICENSE_GLOB)"
4044
rm -r "$_DEST_DIR" || :
4145
mkdir -p "$_DEST_DIR"
42-
cd "$_JSON_DIR"
46+
cd "$_SRC_DIR"
4347
4448
if jq -e .version "$_PRIMITIVES_PKGJSON"; then
4549
version="M._VERSION = vim.json.decode([=[$(jq -e .version "$_PRIMITIVES_PKGJSON")]=], { luanil = { object = false, array = false } })"
4650
fi
4751
48-
for file in *.json; do
49-
cat >|"${_DEST_DIR}/${file%.json}.lua" <<EOF
52+
for file in *.css; do
53+
values="$(nvim -l "$_CSSTOLUA" < "$file")"
54+
cat >| "${_DEST_DIR}/$(tr '-' '_' <<< "${file%.css}.lua")" <<EOF
5055
-- NOTE: THIS IS AN AUTO-GENERATED FILE. DO NOT EDIT BY-HAND.
51-
local M = vim.json.decode([=[$(<"$file")]=], { luanil = { object = false, array = false } })
56+
${values}
5257
${version-}
5358
M._LICENSE = [=[
5459
$license]=]

lua/github-theme/group/modules/treesitter.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ function M.get(spec, config, opts)
1010
:gsub('^github_(.-)$', '%1')
1111
)
1212

13-
local pl = primitives.prettylights
13+
local pl = primitives.color.prettylights
1414
local syn = spec.syntax
1515
local stl = config.styles
1616
local P = spec.palette

lua/github-theme/palette/github_dark.lua

+30-30
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ local meta = {
88
local primitives =
99
require('github-theme.palette.primitives.' .. meta.name:gsub('^github%W*', '', 1))
1010

11-
local pl = primitives.prettylights
11+
local pl = primitives.color.prettylights
1212
local scale = primitives.scale
1313

1414
C.WHITE = C(scale.white)
1515
C.BLACK = C(scale.black)
16-
C.BG = C(scale.gray[7])
16+
C.BG = C(scale.neutral[7])
1717

1818
local function alpha(color, a)
1919
return color:alpha_blend(a):to_css()
@@ -24,40 +24,40 @@ local palette = {
2424

2525
orange = scale.orange[4],
2626

27-
black = { base = scale.gray[10], bright = scale.gray[9] },
28-
gray = { base = scale.gray[5], bright = scale.gray[5] },
27+
black = { base = scale.neutral[10], bright = scale.neutral[9] },
28+
gray = { base = scale.neutral[5], bright = scale.neutral[5] },
2929
blue = { base = scale.blue[4], bright = scale.blue[3] },
3030
green = { base = scale.green[4], bright = scale.green[3] },
3131
magenta = { base = scale.purple[4], bright = scale.purple[3] },
3232
pink = { base = scale.pink[4], bright = scale.pink[3] },
3333
red = { base = scale.red[4], bright = scale.red[3] },
34-
white = { base = scale.gray[3], bright = scale.gray[3] },
34+
white = { base = scale.neutral[3], bright = scale.neutral[3] },
3535
yellow = { base = scale.yellow[4], bright = scale.yellow[3] },
3636
cyan = { base = '#76e3ea', bright = '#b3f0ff' },
3737

3838
fg = {
3939
default = '#e6edf3',
4040
muted = '#7d8590',
41-
subtle = scale.gray[5],
41+
subtle = scale.neutral[5],
4242
on_emphasis = scale.white,
4343
},
4444

4545
canvas = {
46-
default = scale.gray[7],
47-
overlay = scale.gray[9],
48-
inset = scale.gray[8],
49-
subtle = scale.gray[9],
46+
default = scale.neutral[7],
47+
overlay = scale.neutral[9],
48+
inset = scale.neutral[8],
49+
subtle = scale.neutral[9],
5050
},
5151

5252
border = {
53-
default = scale.gray[9],
54-
muted = scale.gray[8],
53+
default = scale.neutral[9],
54+
muted = scale.neutral[8],
5555
subtle = alpha(C.from_rgba(240, 246, 252, 1), 0.1),
5656
},
5757

5858
neutral = {
59-
emphasis_plus = scale.gray[5],
60-
emphasis = scale.gray[5],
59+
emphasis_plus = scale.neutral[5],
60+
emphasis = scale.neutral[5],
6161
muted = alpha(C.from_rgba(110, 118, 129, 1), 0.4),
6262
subtle = alpha(C.from_rgba(110, 118, 129, 1), 0.1),
6363
},
@@ -129,16 +129,16 @@ local palette = {
129129
local function generate_spec(pal)
130130
-- stylua: ignore start
131131
local spec = {
132-
bg0 = alpha(C(pal.canvas.inset), 0.75), -- Dark bg (popup and float)
133-
bg1 = pal.canvas.default, -- Default bg
132+
bg0 = alpha(C(primitives.bgColor.inset), 0.75), -- Dark bg (popup and float)
133+
bg1 = primitives.bgColor.default, -- Default bg
134134
bg2 = alpha(C(pal.neutral.emphasis), 0.1), -- Lighter bg (colorcolumn Folds)
135-
bg3 = pal.scale.gray[6], -- Lighter bg (cursor line)
136-
bg4 = pal.scale.gray[4], -- Conceal
135+
bg3 = pal.scale.neutral[6], -- Lighter bg (cursor line)
136+
bg4 = pal.scale.neutral[4], -- Conceal
137137

138138
fg0 = pal.fg.subtle, -- Lighter fg
139-
fg1 = pal.fg.default, -- Default fg
139+
fg1 = primitives.fgColor.default, -- Default fg
140140
fg2 = pal.fg.muted, -- Darker fg (status line)
141-
fg3 = pal.scale.gray[5], -- Darker fg (line numbers, fold columns)
141+
fg3 = pal.scale.neutral[5], -- Darker fg (line numbers, fold columns)
142142

143143
sel0 = alpha(C(pal.accent.fg), 0.30), -- Visual selection bg
144144
sel1 = alpha(C(pal.accent.muted), 0.90), -- Popup sel bg
@@ -147,26 +147,26 @@ local function generate_spec(pal)
147147

148148
spec.syntax = {
149149
bracket = spec.fg1, -- Brackets and Punctuation
150-
builtin0 = pl.syntax.constant, -- Builtin variable
150+
builtin0 = pl.syntax.constant.default, -- Builtin variable
151151
builtin1 = pl.syntax.keyword, -- Builtin type
152-
builtin2 = pl.syntax.constant, -- Builtin const
152+
builtin2 = pl.syntax.constant.default, -- Builtin const
153153
comment = pl.syntax.comment, -- Comment
154154
conditional = pl.syntax.keyword, -- Conditional and loop
155-
const = pl.syntax.constant, -- Constants, imports and booleans
155+
const = pl.syntax.constant.default, -- Constants, imports and booleans
156156
dep = pal.scale.red[3], -- Deprecated
157-
field = pl.syntax.constant, -- Field
158-
func = pl.syntax.entity, -- Functions and Titles
157+
field = pl.syntax.constant.default, -- Field
158+
func = pl.syntax.entity.default, -- Functions and Titles
159159
ident = spec.fg1, -- Identifiers
160160
keyword = pl.syntax.keyword, -- Keywords
161-
number = pl.syntax.constant, -- Numbers
162-
operator = pl.syntax.constant, -- Operators
161+
number = pl.syntax.constant.default, -- Numbers
162+
operator = pl.syntax.constant.default, -- Operators
163163
param = spec.fg1, -- Parameters
164164
preproc = pl.syntax.keyword, -- PreProc
165-
regex = pl.syntax.string, -- Regex
165+
regex = pl.syntax.string.default, -- Regex
166166
statement = pl.syntax.keyword, -- Statements
167-
string = pl.syntax.string, -- Strings
167+
string = pl.syntax.string.default, -- Strings
168168
type = pl.syntax.variable, -- Types
169-
tag = pl.syntax.entityTag, -- Tags
169+
tag = pl.syntax.entity.tag, -- Tags
170170
variable = spec.fg1, -- Variables
171171
}
172172

0 commit comments

Comments
 (0)