shoreditch 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +148 -0
- data/Gemfile +5 -0
- data/LICENSE.md +9 -0
- data/README.md +230 -0
- data/bridgetown.automation.rb +277 -0
- data/components/shoreditch/comments.erb +25 -0
- data/components/shoreditch/comments.rb +49 -0
- data/components/shoreditch/details.erb +52 -0
- data/components/shoreditch/details.rb +83 -0
- data/components/shoreditch/head_icons.erb +12 -0
- data/components/shoreditch/head_icons.rb +48 -0
- data/components/shoreditch/post_summary.erb +19 -0
- data/components/shoreditch/post_summary.rb +37 -0
- data/components/shoreditch/sidebar.erb +64 -0
- data/components/shoreditch/sidebar.rb +67 -0
- data/content/shoreditch/shoreditch.css +991 -0
- data/content/shoreditch/shoreditch.js +102 -0
- data/layouts/shoreditch/default.erb +89 -0
- data/layouts/shoreditch/page.erb +27 -0
- data/layouts/shoreditch/post.erb +72 -0
- data/lib/shoreditch/icons.rb +32 -0
- data/lib/shoreditch/version.rb +5 -0
- data/lib/shoreditch.rb +70 -0
- data/shoreditch.gemspec +41 -0
- metadata +112 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 2afe1ffff65e9ece59afc75378470a72fcafc495f74d1a9b3f25396c03452a70
|
|
4
|
+
data.tar.gz: 6990c1918011c9a5b60660e737e438964a52fe511180bbdbf0bc59ca30f50f21
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 6a3f2dbac7af5e77dc3b06a55c79edca5b630201bee92d74240ae4a4f87522dcfafc1571f606ba765b1d532197dfb695f0dd93b2fabe2d0c5650efb5cd1130ca
|
|
7
|
+
data.tar.gz: 7e848819d28f74639dc9732f0f9211402ce4400c7f4d64c23b635392b48107fdf33c2bc954dbe798dbbe6ae0c2be4d30ee4428d9fb7f1fa72ddd8cbf8ad5cff9
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.1.0
|
|
4
|
+
|
|
5
|
+
First version published to RubyGems. Restores features the 1.0.0 rewrite
|
|
6
|
+
dropped without recording, and fixes a set of defects that only showed up once
|
|
7
|
+
the demo rendered the theme correctly.
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **The `accent` option did nothing.** `--sd-accent` was hardcoded in the
|
|
12
|
+
stylesheet and the configured value was never emitted. It is now applied from
|
|
13
|
+
the initializer, after the theme's CSS and before the site's own, and
|
|
14
|
+
validated so a site's config cannot inject CSS.
|
|
15
|
+
- **Index listings reserved a thumbnail column whether or not there was a
|
|
16
|
+
thumbnail**, squeezing every title and excerpt of a post without one into a
|
|
17
|
+
128px ribbon.
|
|
18
|
+
- **Syntax highlighting is now owned by the theme.** It sets the code
|
|
19
|
+
background, so a site shipping the light-only Rouge palette that
|
|
20
|
+
`bridgetown new` generates rendered keywords black on near-black in dark
|
|
21
|
+
mode.
|
|
22
|
+
- `aria-current` was HTML-escaped, so the current nav item was never
|
|
23
|
+
highlighted.
|
|
24
|
+
- `<body>` carried `HashWithDotAccess::Hash`, from `data.class` resolving to
|
|
25
|
+
Ruby's `Object#class` rather than the front-matter `class` key.
|
|
26
|
+
- Excerpts were the first *source line*, so hard-wrapped markdown was cut
|
|
27
|
+
mid-sentence. `<!--more-->` is honoured, otherwise the first paragraph.
|
|
28
|
+
- Every generated tag page shared one `<title>`.
|
|
29
|
+
- Code blocks were padded twice, Rouge nesting `pre.highlight` inside
|
|
30
|
+
`div.highlight` and both matching the same rule.
|
|
31
|
+
- Pagination rendered an empty nav, and its margin, when there was one page.
|
|
32
|
+
- **An automation-installed site never rendered as the theme.** The scaffold's
|
|
33
|
+
starter layouts beat the theme's for every page whose front matter named
|
|
34
|
+
them — including the scaffold's own welcome post, whose explicit `layout:
|
|
35
|
+
post` also defeated the automation's `_defaults.yml` — and the starter
|
|
36
|
+
stylesheet trampled what remained. The automation now retires a starter
|
|
37
|
+
layout or stylesheet only when it is *exactly* the untouched scaffold
|
|
38
|
+
(whitespace aside), points the pages that named a retired layout at the
|
|
39
|
+
theme's — editing only their front matter, never a `layout:` line in body
|
|
40
|
+
text — and leaves anything a site has changed in place with a note.
|
|
41
|
+
- **The automation could execute a prompt answer as code.** Answers were
|
|
42
|
+
interpolated into the generated `config/initializers.rb` verbatim, so an
|
|
43
|
+
answer such as `#{`…`}` ran as Ruby every time the site loaded, and one
|
|
44
|
+
containing a quote produced a file that would not parse. Answers carrying a
|
|
45
|
+
quote, a backslash, a newline or a Ruby interpolation are now rejected with
|
|
46
|
+
a note to set that option by hand — escaping was not enough, because
|
|
47
|
+
Bridgetown's initializer insertion rewrites backslashes.
|
|
48
|
+
|
|
49
|
+
### Added
|
|
50
|
+
|
|
51
|
+
- `--sd-rule-strong`, a heavier companion to `--sd-rule`. A hairline separator
|
|
52
|
+
can afford to be almost invisible; a border drawn around something so it reads
|
|
53
|
+
as one object cannot. Index entries use it.
|
|
54
|
+
- **Comments**, off unless configured. Giscus ships as the default provider;
|
|
55
|
+
overriding `components/shoreditch/comments.erb` swaps in any other. Replaces
|
|
56
|
+
the Disqus support removed in 1.0.0, without the third-party trackers.
|
|
57
|
+
- **The contact panel**, restored from the Jekyll `details.html` include. Brand
|
|
58
|
+
marks are vendored from Simple Icons (CC0) and inlined, rather than loading a
|
|
59
|
+
Font Awesome kit from a CDN on every page.
|
|
60
|
+
- **Per-page sidebar overrides** — `include_sticky`, `include_details`,
|
|
61
|
+
`include_logo`, `logo_location`, `logo_shape`, `logo_legend_shape` and
|
|
62
|
+
`flashy_logo`, as the Jekyll version had them.
|
|
63
|
+
- **CV styling**, opted into with `class: cv`. Not a layout: a CV is an
|
|
64
|
+
ordinary page whose front matter reshapes the sidebar and whose body class
|
|
65
|
+
tightens the type.
|
|
66
|
+
- `.pullquote` and `.code-title` styling, both of which the documentation
|
|
67
|
+
demonstrated but the stylesheet never defined.
|
|
68
|
+
- `.sd-archive` styling for a flat post archive — titles left, dates right in
|
|
69
|
+
tabular figures, a hairline rule between entries. The page supplies the
|
|
70
|
+
markup (the demo's Posts page groups by year); the theme ships the style.
|
|
71
|
+
|
|
72
|
+
### Changed
|
|
73
|
+
|
|
74
|
+
- **The sidebar becomes a compact header band on narrow screens.** Below 60rem
|
|
75
|
+
it had been the desktop column rendered at phone width with nothing resized —
|
|
76
|
+
a 128px logo, a centred stack, the theme toggle and the copyright all ahead of
|
|
77
|
+
the article. On a 390px phone that was 439px of chrome, putting a post's title
|
|
78
|
+
at 80% of the first screen and its copyright notice above the headline. The
|
|
79
|
+
logo now sits inline with the site title, the navigation runs beneath it, and
|
|
80
|
+
the toggle and copyright drop to the foot of the page: 137px, with the title
|
|
81
|
+
at 45%. No menu to open and no JavaScript — the parts are promoted to items of
|
|
82
|
+
the page shell with `display: contents` and reordered.
|
|
83
|
+
- **Index entries are framed again**, as they were up to 0.9.0, rather than
|
|
84
|
+
separated by a hairline rule. The frame is what gives the listing a single
|
|
85
|
+
left edge: a post with no thumbnail began its title at the content edge while
|
|
86
|
+
its neighbours began an image-column in, so the stack read as ragged.
|
|
87
|
+
Thumbnails now sit flush to the frame and fill the card's height instead of
|
|
88
|
+
floating inside it with their own rounded corners, excerpts are clamped to
|
|
89
|
+
three lines at a line boundary, and the date moves above the title, set in the
|
|
90
|
+
mono face.
|
|
91
|
+
- **Index excerpts are set as plain text** whatever block the post opens with.
|
|
92
|
+
A post beginning with `{:.message}` or a blockquote put a filled, accent-barred
|
|
93
|
+
box in the listing while its neighbours stayed plain.
|
|
94
|
+
- **The sidebar splits top and bottom.** The logo, badge, site title and
|
|
95
|
+
tagline stay at the top of the column; the navigation and footer drop to the
|
|
96
|
+
bottom. Previously everything stacked from the top, leaving the empty space
|
|
97
|
+
below the nav with nothing to do.
|
|
98
|
+
- **Node 22 is now required** for the frontend build. Bridgetown's esbuild
|
|
99
|
+
configuration calls `fs.globSync`, added in Node 22; on Node 20 the build
|
|
100
|
+
fails while the site still serves, so CSS changes silently never appear.
|
|
101
|
+
Pinned in `demo/.nvmrc`.
|
|
102
|
+
|
|
103
|
+
## 1.0.0
|
|
104
|
+
|
|
105
|
+
First Bridgetown release. Shoreditch was a Jekyll theme up to 0.9.0; this is a
|
|
106
|
+
rewrite rather than a port, so nothing upgrades in place from the Jekyll
|
|
107
|
+
version.
|
|
108
|
+
|
|
109
|
+
### Changed
|
|
110
|
+
|
|
111
|
+
- Distributed as a gem-based Bridgetown plugin. Previously the only way to use
|
|
112
|
+
it was to clone or fork the repo and edit in place; now `bundle add
|
|
113
|
+
shoreditch` and `init :shoreditch` is enough, and updates arrive through
|
|
114
|
+
`bundle update`.
|
|
115
|
+
- Templates are ERB rather than Liquid, as components and layouts served
|
|
116
|
+
through a source manifest.
|
|
117
|
+
- Stylesheet rewritten. The inherited `hyde.sass` and `poole.sass` layers are
|
|
118
|
+
gone, along with the Sass dependency; it is now one plain CSS file driven by
|
|
119
|
+
custom properties.
|
|
120
|
+
- The sidebar is flexbox, finishing the rewrite announced but abandoned in the
|
|
121
|
+
Jekyll version's final week.
|
|
122
|
+
- Fonts are the system stack. The Jekyll version loaded Roboto and Rosario from
|
|
123
|
+
Google Fonts over plain HTTP, which was both a privacy leak and mixed
|
|
124
|
+
content.
|
|
125
|
+
- Favicon links are emitted only for files that exist. The Jekyll version
|
|
126
|
+
hard-coded seventeen icon links whether or not the site had them.
|
|
127
|
+
|
|
128
|
+
### Added
|
|
129
|
+
|
|
130
|
+
- Light and dark themes, from `prefers-color-scheme` plus a sidebar toggle that
|
|
131
|
+
remembers the reader's choice. Applied before first paint, so no flash.
|
|
132
|
+
- Configuration through the initializer: `accent`, `sidebar_side`,
|
|
133
|
+
`logo_legend`, `logo_shape`.
|
|
134
|
+
- `bridgetown.automation.rb`, so `bin/bridgetown apply` installs and configures
|
|
135
|
+
the theme in one step.
|
|
136
|
+
- Open Graph and Twitter card metadata.
|
|
137
|
+
- A skip link, `aria-current` on the active nav item, and visible focus rings.
|
|
138
|
+
- `prefers-reduced-motion` support.
|
|
139
|
+
|
|
140
|
+
### Removed
|
|
141
|
+
|
|
142
|
+
- Disqus comments. Add them from your own layout override if you want them.
|
|
143
|
+
- The Google Analytics hook. Use a privacy-preserving analytics script from
|
|
144
|
+
your site's own head if you need it.
|
|
145
|
+
- The `jekyll-paginate-v2` and `classifier-reborn` dependencies — Bridgetown
|
|
146
|
+
paginates natively, and related-posts is a site concern rather than a theme
|
|
147
|
+
one.
|
|
148
|
+
- The version badge in the sidebar.
|
data/Gemfile
ADDED
data/LICENSE.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Released under MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2013 Mark Otto.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# Shoreditch
|
|
2
|
+
|
|
3
|
+
A two-column [Bridgetown](https://www.bridgetownrb.com) theme built for
|
|
4
|
+
technical blogging: a fixed sidebar, optional cover images, and a content
|
|
5
|
+
column deliberately wide enough that 80-character code samples do not wrap.
|
|
6
|
+
|
|
7
|
+
See it at [shoreditch.mehcoleman.com](https://shoreditch.mehcoleman.com).
|
|
8
|
+
|
|
9
|
+
Shoreditch is adapted from the excellent [Hyde](http://hyde.getpoole.com) theme
|
|
10
|
+
by [@mdo](https://github.com/mdo), and was also inspired by [Flexible
|
|
11
|
+
Jekyll](https://github.com/artemsheludko/flexible-jekyll) by Artem Sheludko.
|
|
12
|
+
Both are worth a look.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
bin/bridgetown apply https://github.com/MEHColeman/shoreditch
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The automation asks for an accent colour and a badge text, installs the gem,
|
|
21
|
+
and points your posts and pages at the theme's layouts. On a fresh site it
|
|
22
|
+
also retires the scaffold's starter stylesheet and layouts, which would
|
|
23
|
+
otherwise override the theme — but only files that are *exactly* the untouched
|
|
24
|
+
`bridgetown new` scaffold; anything you have edited is left alone with a note.
|
|
25
|
+
An accent or badge answer that contains a quote, a backslash or a `#{…}` is
|
|
26
|
+
declined rather than written into your config, since it would otherwise land
|
|
27
|
+
in generated Ruby — set those options by hand if you need such characters.
|
|
28
|
+
|
|
29
|
+
Or by hand:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
bundle add shoreditch
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
then in `config/initializers.rb`:
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
init :shoreditch
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
There is nothing to add to your esbuild entry points. The theme's stylesheet
|
|
42
|
+
and script ship as static files through the gem's source manifest, so
|
|
43
|
+
`bundle update shoreditch` is all it takes to move to a new version.
|
|
44
|
+
|
|
45
|
+
## Options
|
|
46
|
+
|
|
47
|
+
```ruby
|
|
48
|
+
init :shoreditch do
|
|
49
|
+
accent "#c7254e" # any CSS colour; drives links, tags, focus rings
|
|
50
|
+
sidebar_side "right" # "left" (default) or "right"
|
|
51
|
+
logo_legend "For hire" # badge under the logo; omit for none
|
|
52
|
+
logo_shape "square" # "round" (default) or "square"
|
|
53
|
+
logo_legend_shape "straight" # "round" (default) or "straight"
|
|
54
|
+
end
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`accent` is validated before it reaches the stylesheet — a value that is not a
|
|
58
|
+
recognisable CSS colour falls back to the default rather than emitting broken
|
|
59
|
+
CSS.
|
|
60
|
+
|
|
61
|
+
## Comments
|
|
62
|
+
|
|
63
|
+
Off unless configured. The theme ships [Giscus](https://giscus.app), which
|
|
64
|
+
stores comments as GitHub Discussions:
|
|
65
|
+
|
|
66
|
+
```ruby
|
|
67
|
+
init :shoreditch do
|
|
68
|
+
comments({
|
|
69
|
+
repo: "you/your-repo", repo_id: "R_...",
|
|
70
|
+
category: "Comments", category_id: "DIC_...",
|
|
71
|
+
})
|
|
72
|
+
end
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The four values come from giscus.app once Discussions is enabled on the
|
|
76
|
+
repository. A single post opts out with `comments: false` in its front matter.
|
|
77
|
+
|
|
78
|
+
For any other provider, override `components/shoreditch/comments.erb` in your
|
|
79
|
+
own site — your files take precedence over the gem's, so there is no need to
|
|
80
|
+
fork the theme or copy the post layout. The thread follows the reader's theme
|
|
81
|
+
toggle, not just their OS setting.
|
|
82
|
+
|
|
83
|
+
## Site metadata
|
|
84
|
+
|
|
85
|
+
In `src/_data/site_metadata.yml`:
|
|
86
|
+
|
|
87
|
+
```yaml
|
|
88
|
+
title: Your Site
|
|
89
|
+
tagline: Shown under the title in the sidebar
|
|
90
|
+
description: Used for meta description and the feed
|
|
91
|
+
logo: /images/you.png
|
|
92
|
+
logo_link: /about/
|
|
93
|
+
author:
|
|
94
|
+
name: Your Name
|
|
95
|
+
|
|
96
|
+
# All optional, and all used only by the contact panel — see below.
|
|
97
|
+
github: yourhandle
|
|
98
|
+
mastodon: https://example.social/@you # a full URL, unlike the others
|
|
99
|
+
linkedin: yourhandle
|
|
100
|
+
twitter: yourhandle
|
|
101
|
+
instagram: yourhandle
|
|
102
|
+
reddit: yourhandle
|
|
103
|
+
youtube: https://youtube.com/@you # a full URL
|
|
104
|
+
tiktok: yourhandle
|
|
105
|
+
lastfm: yourhandle
|
|
106
|
+
deviantart: yourhandle
|
|
107
|
+
artstation: yourhandle
|
|
108
|
+
phone: "+44 20 7946 0000"
|
|
109
|
+
file_url: /files/cv.pdf
|
|
110
|
+
file_link_text: Download as PDF
|
|
111
|
+
|
|
112
|
+
# Split in two on purpose. The halves are only joined in the browser, so the
|
|
113
|
+
# address never appears whole in the HTML for a crawler to lift.
|
|
114
|
+
email_1: hello@examp
|
|
115
|
+
email_2: le.com
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## The contact panel
|
|
119
|
+
|
|
120
|
+
A page opts in with `include_details: true`. It lists whichever of the author
|
|
121
|
+
fields above are filled in, with an inline icon each — brand marks are vendored
|
|
122
|
+
from [Simple Icons](https://simpleicons.org) (CC0), so the theme still loads
|
|
123
|
+
nothing from a third party.
|
|
124
|
+
|
|
125
|
+
It is off by default because a blog post has no use for a phone number; a CV or
|
|
126
|
+
an about page does.
|
|
127
|
+
|
|
128
|
+
## Layouts
|
|
129
|
+
|
|
130
|
+
| Layout | Use |
|
|
131
|
+
| --- | --- |
|
|
132
|
+
| `shoreditch/default` | Wraps everything. Index pages use it directly. |
|
|
133
|
+
| `shoreditch/post` | Posts. Adds dates, tags, related posts and image credits. |
|
|
134
|
+
| `shoreditch/page` | Standalone pages. |
|
|
135
|
+
|
|
136
|
+
## Front matter
|
|
137
|
+
|
|
138
|
+
| Key | Effect |
|
|
139
|
+
| --- | --- |
|
|
140
|
+
| `cover` | Full-width image above the content |
|
|
141
|
+
| `thumbnail` | Image in index listings |
|
|
142
|
+
| `last_updated` | Shown in the post header |
|
|
143
|
+
| `last_verified` | Shown in the post header — for saying how stale a technical post may be |
|
|
144
|
+
| `credits` | List of `label` / `name` / `via` / `via_link` for image attribution |
|
|
145
|
+
| `nav_order` | Puts a page in the sidebar nav, in this order |
|
|
146
|
+
| `exclude` | Keeps a page out of the sidebar nav |
|
|
147
|
+
| `noindex` | Emits `robots: noindex, nofollow` |
|
|
148
|
+
| `class` | Extra CSS class on `<body>` — `class: cv` opts into the CV styling |
|
|
149
|
+
| `comments` | `false` turns comments off for one post |
|
|
150
|
+
|
|
151
|
+
These reshape the sidebar for a single page — useful when one page should
|
|
152
|
+
introduce a person rather than the site:
|
|
153
|
+
|
|
154
|
+
| Key | Effect |
|
|
155
|
+
| --- | --- |
|
|
156
|
+
| `include_sticky` | `false` drops the site title, tagline and navigation |
|
|
157
|
+
| `include_details` | `true` shows the contact panel |
|
|
158
|
+
| `include_logo` | `false` hides the logo entirely |
|
|
159
|
+
| `logo_location` | A different logo image for this page |
|
|
160
|
+
| `logo_shape` | `round` or `square`, overriding the site setting |
|
|
161
|
+
| `logo_legend` | Overrides the badge; `false` hides it |
|
|
162
|
+
| `logo_legend_shape` | `round` or `straight` — the badge, shaped independently |
|
|
163
|
+
| `flashy_logo` | `true` gives the logo a pulsing accent glow |
|
|
164
|
+
|
|
165
|
+
## Customising
|
|
166
|
+
|
|
167
|
+
Every colour and dimension is a custom property on `:root`, and your site's own
|
|
168
|
+
stylesheet loads after the theme's. To restyle, override what you need:
|
|
169
|
+
|
|
170
|
+
```css
|
|
171
|
+
:root {
|
|
172
|
+
--sd-accent: rebeccapurple;
|
|
173
|
+
--sd-measure: 52rem;
|
|
174
|
+
--sd-sidebar-width: 20rem;
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Syntax highlighting is one of those properties. The theme sets the code
|
|
179
|
+
background, so it also sets the token colours — otherwise a light-only Rouge
|
|
180
|
+
palette renders keywords black on near-black as soon as dark mode flips the
|
|
181
|
+
background. Override `--sd-code-keyword`, `--sd-code-string`,
|
|
182
|
+
`--sd-code-comment`, `--sd-code-number`, `--sd-code-fn`, `--sd-code-tag` and
|
|
183
|
+
`--sd-code-punct` to use your own.
|
|
184
|
+
|
|
185
|
+
Rules come in two weights. `--sd-rule` is the hairline used for separators and
|
|
186
|
+
table borders; `--sd-rule-strong` is the heavier one used where a border encloses
|
|
187
|
+
something that has to read as a single object, as an index entry does. Override
|
|
188
|
+
them together if you are changing the palette.
|
|
189
|
+
|
|
190
|
+
Do not style `body`, `main` or bare `a` from your site's stylesheet — those
|
|
191
|
+
belong to the theme, and because your CSS loads last you will win by accident.
|
|
192
|
+
Override custom properties instead.
|
|
193
|
+
|
|
194
|
+
Light and dark both come from `prefers-color-scheme`, with a toggle in the
|
|
195
|
+
sidebar that stores the reader's choice and wins over the OS setting. The
|
|
196
|
+
choice is applied by an inline script before first paint, so there is no flash
|
|
197
|
+
of the wrong scheme.
|
|
198
|
+
|
|
199
|
+
Below 60rem the two columns stack, and the sidebar becomes a compact header
|
|
200
|
+
band: the logo shrinks and sits inline with the site title, the navigation runs
|
|
201
|
+
along under it, and the theme toggle and copyright move to the foot of the page
|
|
202
|
+
so a reader arriving on a post meets the masthead rather than the small print.
|
|
203
|
+
There is no menu to open — everything stays on screen, and no JavaScript is
|
|
204
|
+
involved.
|
|
205
|
+
|
|
206
|
+
The markdown classes the Jekyll version defined — `.message`, `.callout`,
|
|
207
|
+
`.alert`, `.alarm` — still work, so posts carrying them keep rendering.
|
|
208
|
+
|
|
209
|
+
## Development
|
|
210
|
+
|
|
211
|
+
The `demo/` directory is a Bridgetown site that uses the theme from the parent
|
|
212
|
+
directory. It is what gets published to
|
|
213
|
+
[shoreditch.mehcoleman.com](https://shoreditch.mehcoleman.com), and it is the
|
|
214
|
+
quickest way to see a change:
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
cd demo
|
|
218
|
+
bundle install
|
|
219
|
+
bin/bridgetown start
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Ruby 3.3+ and **Node 22 or newer** — Bridgetown's esbuild configuration calls
|
|
223
|
+
`fs.globSync`, which does not exist before Node 22. On an older Node the
|
|
224
|
+
frontend build fails while the site itself still serves, so stylesheet changes
|
|
225
|
+
silently never reach the browser. `demo/.nvmrc` pins it.
|
|
226
|
+
|
|
227
|
+
## Licence
|
|
228
|
+
|
|
229
|
+
MIT. See [LICENSE.md](LICENSE.md) — the original copyright is Mark Otto's and
|
|
230
|
+
stays.
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# Installs Shoreditch into an existing Bridgetown site.
|
|
2
|
+
#
|
|
3
|
+
# bin/bridgetown apply https://github.com/MEHColeman/shoreditch
|
|
4
|
+
#
|
|
5
|
+
# The theme's stylesheet and script ship as static files through the gem's
|
|
6
|
+
# source manifest, so there is nothing to add to esbuild entry points and no
|
|
7
|
+
# NPM package to install.
|
|
8
|
+
#
|
|
9
|
+
# This can run against a site with real content, so every destructive step is
|
|
10
|
+
# gated on the file being *exactly* the untouched `bridgetown new` scaffold
|
|
11
|
+
# (whitespace aside). Anything a site has edited is left alone with a note.
|
|
12
|
+
# The gate is deliberately strict: a newer Bridgetown scaffold this does not
|
|
13
|
+
# recognise is treated as "not ours to touch", so the automation degrades to
|
|
14
|
+
# advice rather than deleting someone's work.
|
|
15
|
+
|
|
16
|
+
add_gem "shoreditch"
|
|
17
|
+
|
|
18
|
+
# Both answers are written into the generated initializer as Ruby string
|
|
19
|
+
# literals (`accent "…"`). Reject any answer that could break out of the
|
|
20
|
+
# literal or smuggle interpolation (`#{…}`, `#@…`, `#$…`) rather than trying
|
|
21
|
+
# to escape it: Bridgetown's initializer insertion rewrites backslashes, so an
|
|
22
|
+
# escaped answer can be un-escaped on its way into the file — but an answer
|
|
23
|
+
# carrying none of these characters needs no escaping and cannot be reactived.
|
|
24
|
+
# A colour and a short badge never need them; anything that does is set by hand.
|
|
25
|
+
unsafe = ->(text) { text.match?(/["\\\r\n]|#[{@$]/) }
|
|
26
|
+
|
|
27
|
+
accent = ask("Accent colour (hex, blank for the default slate blue)?").to_s.strip
|
|
28
|
+
if unsafe.call(accent)
|
|
29
|
+
say "Ignoring the accent — it contained characters not allowed in a colour. " \
|
|
30
|
+
"Set `accent` by hand in config/initializers.rb.", :yellow
|
|
31
|
+
accent = ""
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
legend = ask("Badge text under the logo (blank for none)?").to_s.strip
|
|
35
|
+
if unsafe.call(legend)
|
|
36
|
+
say "Ignoring the badge text — it contained characters that aren't allowed. " \
|
|
37
|
+
"Set `logo_legend` by hand in config/initializers.rb.", :yellow
|
|
38
|
+
legend = ""
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
add_initializer :shoreditch do
|
|
42
|
+
settings = []
|
|
43
|
+
settings << %(accent "#{accent}") unless accent.empty?
|
|
44
|
+
settings << %(logo_legend "#{legend}") unless legend.empty?
|
|
45
|
+
|
|
46
|
+
if settings.empty?
|
|
47
|
+
""
|
|
48
|
+
else
|
|
49
|
+
<<~RUBY
|
|
50
|
+
do
|
|
51
|
+
#{settings.join("\n ")}
|
|
52
|
+
end
|
|
53
|
+
RUBY
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Collapse whitespace so indentation and line-ending differences do not read
|
|
58
|
+
# as edits; any real change to the content does.
|
|
59
|
+
normalise = ->(text) { text.gsub(/\s+/, " ").strip }
|
|
60
|
+
|
|
61
|
+
pristine_default = <<~'ERB'
|
|
62
|
+
<!doctype html>
|
|
63
|
+
<html lang="<%= site.locale %>">
|
|
64
|
+
<head>
|
|
65
|
+
<%= render "head", metadata: site.metadata, title: data.title %>
|
|
66
|
+
</head>
|
|
67
|
+
<body class="<%= data.layout %> <%= data.page_class %>">
|
|
68
|
+
<%= render Shared::Navbar.new(metadata: site.metadata, resource: resource) %>
|
|
69
|
+
|
|
70
|
+
<main>
|
|
71
|
+
<%= yield %>
|
|
72
|
+
</main>
|
|
73
|
+
|
|
74
|
+
<%= render "footer", metadata: site.metadata %>
|
|
75
|
+
</body>
|
|
76
|
+
</html>
|
|
77
|
+
ERB
|
|
78
|
+
|
|
79
|
+
# `bridgetown new` generates page.erb and post.erb identically.
|
|
80
|
+
pristine_page_post = <<~'ERB'
|
|
81
|
+
---
|
|
82
|
+
layout: default
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
<h1><%= data.title %></h1>
|
|
86
|
+
|
|
87
|
+
<%= yield %>
|
|
88
|
+
ERB
|
|
89
|
+
|
|
90
|
+
pristine_css = <<~'CSS'
|
|
91
|
+
:root {
|
|
92
|
+
--body-background: #f2f2f2;
|
|
93
|
+
--body-color: #444;
|
|
94
|
+
--heading-color: black;
|
|
95
|
+
--action-color: #d64045;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
body {
|
|
99
|
+
background: var(--body-background);
|
|
100
|
+
color: var(--body-color);
|
|
101
|
+
font-family: BlinkMacSystemFont, -apple-system, "Segoe UI", "Roboto", "Oxygen",
|
|
102
|
+
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
|
103
|
+
"Helvetica", "Arial", sans-serif;
|
|
104
|
+
margin: 0 8px;
|
|
105
|
+
font-size: 108%;
|
|
106
|
+
line-height: 1.5;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
a {
|
|
110
|
+
color: var(--action-color);
|
|
111
|
+
text-decoration: underline;
|
|
112
|
+
text-decoration-color: #ffb088;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
h1 {
|
|
116
|
+
margin: 1rem 0 3rem;
|
|
117
|
+
text-align: center;
|
|
118
|
+
font-weight: 900;
|
|
119
|
+
font-size: 2.5rem;
|
|
120
|
+
color: var(--heading-color);
|
|
121
|
+
line-height: 1.2;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
body > header {
|
|
125
|
+
margin: 1rem;
|
|
126
|
+
text-align: center;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
body > header img {
|
|
130
|
+
display: inline-block;
|
|
131
|
+
width: 400px;
|
|
132
|
+
max-width: 100%;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
body > nav ul {
|
|
136
|
+
margin: 2rem 0;
|
|
137
|
+
padding: 0;
|
|
138
|
+
list-style-type: none;
|
|
139
|
+
display: flex;
|
|
140
|
+
justify-content: center;
|
|
141
|
+
gap: 1.5rem;
|
|
142
|
+
font-size: 1.3rem;
|
|
143
|
+
font-weight: bold;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
body > nav a {
|
|
147
|
+
text-decoration: none;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
main {
|
|
151
|
+
margin: 2rem auto 4rem;
|
|
152
|
+
max-width: 65rem;
|
|
153
|
+
min-height: calc(100vh - 200px);
|
|
154
|
+
padding: 25px 25px 50px;
|
|
155
|
+
background: white;
|
|
156
|
+
box-shadow: 2px 3px 3px #ddd;
|
|
157
|
+
border-radius: 3px;
|
|
158
|
+
|
|
159
|
+
@media (max-width: 500px) {
|
|
160
|
+
padding: 16px 16px 50px;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
footer {
|
|
165
|
+
text-align: center;
|
|
166
|
+
margin-bottom: 4rem;
|
|
167
|
+
font-size: 1em;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
hr {
|
|
171
|
+
border: none;
|
|
172
|
+
border-top: 2px dotted #bbb;
|
|
173
|
+
margin: 3rem 0;
|
|
174
|
+
}
|
|
175
|
+
CSS
|
|
176
|
+
|
|
177
|
+
# The starter stylesheet styles body and main directly, and a site's own CSS
|
|
178
|
+
# loads after the theme's — so left in place it pulls the theme apart (it once
|
|
179
|
+
# cost the demo its entire appearance). Replace it only when it is exactly the
|
|
180
|
+
# untouched starter.
|
|
181
|
+
starter_css = "frontend/styles/index.css"
|
|
182
|
+
if File.exist?(starter_css)
|
|
183
|
+
if normalise.call(File.read(starter_css)) == normalise.call(pristine_css)
|
|
184
|
+
say "Clearing the starter stylesheet — its body/main rules override the theme…", :green
|
|
185
|
+
create_file starter_css, <<~CSS, force: true
|
|
186
|
+
/* Your site's styles load after the theme's, so anything here overrides
|
|
187
|
+
Shoreditch. Prefer overriding the theme's custom properties (see the
|
|
188
|
+
README) to styling body, main, or bare a directly. */
|
|
189
|
+
CSS
|
|
190
|
+
else
|
|
191
|
+
say "Left frontend/styles/index.css alone — it differs from the starter. " \
|
|
192
|
+
"Your CSS loads after the theme's, so remove any rules on body, main " \
|
|
193
|
+
"or bare a that fight it.", :yellow
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
say "Pointing your layouts at the theme…", :green
|
|
198
|
+
|
|
199
|
+
# The scaffold's own layouts beat the theme's for every page whose front
|
|
200
|
+
# matter names them — including the scaffold's welcome post — so a fresh site
|
|
201
|
+
# would not render as the theme anywhere. Retire each starter layout only when
|
|
202
|
+
# it is exactly the untouched scaffold; an edited layout is the site's own and
|
|
203
|
+
# stays, with a note.
|
|
204
|
+
layouts = {
|
|
205
|
+
"default" => [pristine_default, "shoreditch/default"],
|
|
206
|
+
"page" => [pristine_page_post, "shoreditch/page"],
|
|
207
|
+
"post" => [pristine_page_post, "shoreditch/post"],
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
retired = {}
|
|
211
|
+
layouts.each do |name, (pristine, replacement)|
|
|
212
|
+
file = "src/_layouts/#{name}.erb"
|
|
213
|
+
next unless File.exist?(file)
|
|
214
|
+
|
|
215
|
+
if normalise.call(File.read(file)) == normalise.call(pristine)
|
|
216
|
+
remove_file file
|
|
217
|
+
retired[name] = replacement
|
|
218
|
+
else
|
|
219
|
+
say "Left src/_layouts/#{name}.erb alone — it differs from the starter. " \
|
|
220
|
+
"Point pages that use it at #{replacement} yourself.", :yellow
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# Repoint the pages that named a retired layout — but only inside the leading
|
|
225
|
+
# `---`…`---` front matter, so a `layout:` line in a post's body or a fenced
|
|
226
|
+
# code block is never touched, and tolerant of quoted values (layout: "post").
|
|
227
|
+
unless retired.empty?
|
|
228
|
+
Dir.glob("src/**/*.{md,markdown,erb,serb,liquid,html}").each do |page|
|
|
229
|
+
next unless File.file?(page)
|
|
230
|
+
|
|
231
|
+
text = File.read(page)
|
|
232
|
+
# A non-UTF-8 source would raise on the match below, aborting mid-way with
|
|
233
|
+
# layouts already removed; skip it so the pass is all-or-nothing.
|
|
234
|
+
next unless text.valid_encoding?
|
|
235
|
+
next unless text =~ /\A(---[ \t]*\r?\n)(.*?\r?\n)(---[ \t]*\r?\n)(.*)\z/m
|
|
236
|
+
|
|
237
|
+
open_fence, front, close_fence, body = $1, $2, $3, $4
|
|
238
|
+
changed = false
|
|
239
|
+
retired.each do |name, replacement|
|
|
240
|
+
# The `\r?` before the anchor keeps CRLF front matter matching, and the
|
|
241
|
+
# captured trailing group is re-emitted so the line ending is preserved.
|
|
242
|
+
front = front.sub(/^(layout:[ \t]*)["']?#{Regexp.escape(name)}["']?([ \t]*\r?)$/) do
|
|
243
|
+
changed = true
|
|
244
|
+
"#{$1}#{replacement}#{$2}"
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
File.write(page, open_fence + front + close_fence + body) if changed
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# Posts and pages need to reference the theme's layouts. A site that already
|
|
252
|
+
# has its own layouts keeps them; these defaults only apply where there is
|
|
253
|
+
# nothing already.
|
|
254
|
+
create_file "src/_posts/_defaults.yml", force: false do
|
|
255
|
+
<<~YAML
|
|
256
|
+
layout: shoreditch/post
|
|
257
|
+
YAML
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
say <<~TEXT, :green
|
|
261
|
+
|
|
262
|
+
Shoreditch installed.
|
|
263
|
+
|
|
264
|
+
Next steps:
|
|
265
|
+
|
|
266
|
+
1. Set `layout: shoreditch/page` on your standalone pages.
|
|
267
|
+
2. Add these to src/_data/site_metadata.yml:
|
|
268
|
+
|
|
269
|
+
logo: /images/your-logo.png
|
|
270
|
+
logo_link: /about/
|
|
271
|
+
tagline: Your tagline
|
|
272
|
+
|
|
273
|
+
3. Give pages a `nav_order:` to put them in the sidebar. Pages with
|
|
274
|
+
`exclude: true` never appear there.
|
|
275
|
+
|
|
276
|
+
The full option list is in the theme README.
|
|
277
|
+
TEXT
|