docs-kit 1.0.1 → 1.0.3
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 +4 -4
- data/CHANGELOG.md +21 -8
- data/README.md +53 -12
- data/app/components/docs_ui/meta_tags.rb +33 -30
- data/lib/docs_kit/seo_config.rb +9 -7
- data/lib/docs_kit/templates/new_site.rb +11 -40
- data/lib/docs_kit/version.rb +1 -1
- data/lib/generators/docs_kit/install/install_generator.rb +100 -10
- data/lib/generators/docs_kit/install/sync_report.rb +28 -2
- data/lib/generators/docs_kit/install/templates/Dockerfile.tt +96 -0
- data/lib/generators/docs_kit/install/templates/dockerignore +57 -0
- data/lib/generators/docs_kit/install/templates/docs_kit.rb.erb +6 -4
- metadata +3 -3
- data/app/assets/images/og/og.png +0 -0
- data/app/assets/images/og/og.svg +0 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4ede4d90b3f6ca240a59c5f13d14967a29cf8a806fa041a3c7edfe65adf1ed2c
|
|
4
|
+
data.tar.gz: 015f6f05b3d3b09581679810ae41b3486c2428dc219d2d47f32775a40b449759
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2b315f74f9de60f0e02354b3e8e093a85d06c99dc6bc8e9d1f96ad9ac0abc0bf7fe0d5db37f716b68e1fac2daabcafae1bd69b5c22cf587d7068cfc3b27c3050
|
|
7
|
+
data.tar.gz: f7868334e630ce1ab3ec99c9fbcfd91fbb6302c0f999c4b87dfc1c04959cbd8aac7cfecb49623ba2e4f2557665dcd844439f1d69211c97d5baa2ba55ad7efd6e
|
data/CHANGELOG.md
CHANGED
|
@@ -2,20 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **SEO `og:image` 404.** The og:image tag pointed at the raw config path
|
|
8
|
+
(`https://site/og/og.png`), which isn't a served URL — Propshaft serves the
|
|
9
|
+
digested asset under `/assets`. A relative `og_image` is now resolved through
|
|
10
|
+
the site's asset pipeline (`image_url`) to the digested `/assets/og/og-<digest>.png`
|
|
11
|
+
URL, and the image is treated as **site content**: the gem ships none,
|
|
12
|
+
`c.seo.og_image` defaults to **nil** (unset → no og:image tag, never a 404), and
|
|
13
|
+
the `docs_kit:og` task writes into the *site's* `app/assets/images/`. Added a
|
|
14
|
+
booted-app integration test in the dogfood site
|
|
15
|
+
(`docs/test/integration/seo_meta_tags_test.rb`) that asserts og:image resolves
|
|
16
|
+
to a `/assets` URL that actually returns 200 — the coverage isolated component
|
|
17
|
+
specs can't provide.
|
|
18
|
+
|
|
5
19
|
### Added
|
|
6
20
|
|
|
7
21
|
- **SEO + social sharing.** Every page now emits a complete SEO `<head>` —
|
|
8
22
|
meta description, Open Graph, Twitter Card, canonical, favicon, robots, and
|
|
9
23
|
theme-color — via the new `DocsUI::MetaTags` component, driven entirely by a
|
|
10
24
|
new `c.seo` config block (`DocsKit::SeoConfig`). Pages carry an authorable
|
|
11
|
-
`description "..."` (falling back to the page's `#lead`).
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
`docs-kit new` reminds the owner to run it. (#48)
|
|
25
|
+
`description "..."` (falling back to the page's `#lead`). The social-share image
|
|
26
|
+
is site content (not shipped by the gem): the `docs_kit:og` rake task screenshots
|
|
27
|
+
a site's OWN landing page into its `app/assets/images/og/` (host-side headless
|
|
28
|
+
browser; never a gem runtime dependency), and `c.seo.og_image` points at it.
|
|
29
|
+
Backwards-compatible: a site that sets no `c.seo` renders a valid minimal card
|
|
30
|
+
and its `<head>` is a strict superset of before. The install generator documents
|
|
31
|
+
`c.seo` and installs the task; `docs-kit new` reminds the owner to run it. (#48)
|
|
19
32
|
- Release tooling matching the sibling gems (daisyui/phlex-reactive/pgbus): a
|
|
20
33
|
`rake release[X.Y.Z]` task (version bump → lockfile update → build-verify →
|
|
21
34
|
commit → push → GitHub Release; `pre`/`force` supported, `main`-only, clean-tree
|
data/README.md
CHANGED
|
@@ -92,6 +92,39 @@ generators:
|
|
|
92
92
|
| `ApplicationController#render_page` defined by hand | `DocsKit::Controller#render_page` is included (the generator injects `include DocsKit::Controller`) | Delete the method — keep the `include`. |
|
|
93
93
|
| `app/helpers/icon_helper.rb` | docs-kit renders icons via rails_icons (`DocsUI::Icon`) | Delete the file. |
|
|
94
94
|
| Hand-pinned docs-kit lines in `config/importmap.rb` | the engine auto-pins the `docs-nav` controller and its assets | Delete the manual `pin`/`pin_all_from` lines for docs-kit. |
|
|
95
|
+
| `Dockerfile` stamped by an older docs-kit (`# docs-kit Dockerfile vX.Y.Z`) | docs-kit ships an optimized, multi-stage Dockerfile; a stale copy misses image-size wins | Diff yours against the current template (`lib/generators/docs_kit/install/templates/Dockerfile.tt` in the gem), adopt the changes or replace it. See [Upgrading your Dockerfile](#upgrading-your-dockerfile). |
|
|
96
|
+
|
|
97
|
+
### Upgrading your Dockerfile
|
|
98
|
+
|
|
99
|
+
The generator ships two Docker files:
|
|
100
|
+
|
|
101
|
+
- **`.dockerignore`** is gem-owned — every `docs_kit:install` (or `--sync`) run
|
|
102
|
+
**refreshes** it, so you always get the current build-context excludes
|
|
103
|
+
(`node_modules`, `.git`, `log`, `tmp`, `spec`, `coverage`, …). It carries no
|
|
104
|
+
site-specific content, so overwriting it is safe.
|
|
105
|
+
- **`Dockerfile`** is site-owned — the generator **never clobbers** it (you tune
|
|
106
|
+
packages, the `CMD`, extra build steps). Instead it stamps a version marker
|
|
107
|
+
(`# docs-kit Dockerfile v<VERSION>`) so `--sync` can tell you when yours is
|
|
108
|
+
stale relative to the gem's current template.
|
|
109
|
+
|
|
110
|
+
When the site bundles `thruster` (a Rails 8 default), the generated Dockerfile
|
|
111
|
+
fronts Puma with Thruster (`CMD ["./bin/thrust", "./bin/rails", "server"]`) for
|
|
112
|
+
HTTP caching, compression, and X-Sendfile — and the generator scaffolds the
|
|
113
|
+
`bin/thrust` binstub if the app lacks one, since the exec-form CMD needs the
|
|
114
|
+
file to exist in the image. Thruster listens on the routed port
|
|
115
|
+
(`HTTP_PORT=3000` — Kamal's `app_port`) and proxies to Puma on `TARGET_PORT=3001`.
|
|
116
|
+
Without thruster in the *production* bundle (absent, or only in a
|
|
117
|
+
development/test group that `BUNDLE_WITHOUT` excludes) the CMD falls back to
|
|
118
|
+
plain `rails server` — never a thrust CMD that would crash at boot.
|
|
119
|
+
|
|
120
|
+
When `--sync` reports your Dockerfile is behind, compare it against the shipped
|
|
121
|
+
template and pull in the improvements (or replace it wholesale if you never
|
|
122
|
+
customized it):
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# The template path is printed by the generator; it lives in the installed gem:
|
|
126
|
+
diff Dockerfile "$(bundle show docs-kit)/lib/generators/docs_kit/install/templates/Dockerfile.tt"
|
|
127
|
+
```
|
|
95
128
|
|
|
96
129
|
## Configure (per site)
|
|
97
130
|
|
|
@@ -180,9 +213,9 @@ nothing still gets a valid minimal card, so this is fully backwards-compatible.
|
|
|
180
213
|
```ruby
|
|
181
214
|
# config/initializers/docs_kit.rb
|
|
182
215
|
c.seo.description = "What these docs cover, in one sentence."
|
|
183
|
-
c.seo.og_image = "og/og.png" #
|
|
216
|
+
c.seo.og_image = "og/og.png" # a path in YOUR app/assets/images/
|
|
184
217
|
c.seo.twitter_site = "@your_handle"
|
|
185
|
-
c.seo.site_url = "https://docs.example.com" #
|
|
218
|
+
c.seo.site_url = "https://docs.example.com" # your canonical base URL
|
|
186
219
|
# c.seo.robots = "noindex, nofollow" # keep a staging/private site out of search
|
|
187
220
|
# c.seo.theme_color = "#0f172a" # tints mobile browser chrome
|
|
188
221
|
```
|
|
@@ -199,19 +232,26 @@ class Views::Docs::Pages::Installation < DocsUI::Page
|
|
|
199
232
|
end
|
|
200
233
|
```
|
|
201
234
|
|
|
202
|
-
**The social-share image.** docs-kit ships
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
page
|
|
235
|
+
**The social-share image is your content, not the gem's.** docs-kit ships no OG
|
|
236
|
+
image — your landing page isn't docs-kit's to render. Until you set `c.seo.og_image`,
|
|
237
|
+
**no `og:image` tag is emitted** (a valid card, never a broken-image 404). Generate
|
|
238
|
+
one from your **own** landing page — it screenshots `/` into
|
|
239
|
+
`app/assets/images/og/{og,twitter,square}.png` — then point `og_image` at it:
|
|
206
240
|
|
|
207
241
|
```bash
|
|
208
242
|
bin/rails docs_kit:og # needs a headless browser: shot-scraper or chromium/chrome
|
|
209
243
|
```
|
|
210
244
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
`
|
|
245
|
+
`og_image` is a **logical asset path in your pipeline** (`"og/og.png"`), resolved
|
|
246
|
+
through `image_url` to the digested `/assets/og/og-<digest>.png` URL Propshaft
|
|
247
|
+
serves — never the raw path, which 404s. So the image must be **precompiled**
|
|
248
|
+
(your Dockerfile's `assets:precompile` handles this at deploy); a configured
|
|
249
|
+
`og_image` that isn't in the pipeline fails loudly at deploy, not silently in
|
|
250
|
+
production. An absolute URL (`"https://cdn.example.com/card.png"`) is used verbatim.
|
|
251
|
+
|
|
252
|
+
`docs_kit:og` is a documented, manual routine (never run at deploy time), so a
|
|
253
|
+
machine without a browser is never blocked. Set `DOCS_KIT_OG_URL` to shoot a
|
|
254
|
+
deployed URL instead of booting locally, or `DOCS_KIT_SHOT` to force a browser CLI.
|
|
215
255
|
|
|
216
256
|
### Custom nav (advanced)
|
|
217
257
|
|
|
@@ -744,8 +784,9 @@ and applies docs-kit's application template, which:
|
|
|
744
784
|
- runs `rails g docs_kit:install` (initializers, controllers, a Doc registry, a
|
|
745
785
|
sample guide page, the Bun/Tailwind build, the docs-nav Stimulus wiring),
|
|
746
786
|
- syncs the lucide icons and builds the CSS,
|
|
747
|
-
- scaffolds Kamal (`config/deploy.yml`, `.kamal/secrets`,
|
|
748
|
-
|
|
787
|
+
- scaffolds Kamal (`config/deploy.yml`, `.kamal/secrets`, an optimized
|
|
788
|
+
multi-stage `Dockerfile` + a `.dockerignore`) and a thin
|
|
789
|
+
`.github/workflows/deploy-docs.yml` that calls the reusable workflow.
|
|
749
790
|
|
|
750
791
|
Then `cd my-docs && bin/dev`. Already have a Rails app? Run the install generator
|
|
751
792
|
instead:
|
|
@@ -11,12 +11,15 @@ module DocsUI
|
|
|
11
11
|
#
|
|
12
12
|
# All free text (title, description, brand) is emitted as normal Phlex
|
|
13
13
|
# attribute values, so Phlex escapes it — config free text is never trusted
|
|
14
|
-
# markup. og:image
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
# an
|
|
14
|
+
# markup. The og:image is SITE content (nil by default → no og:image tag): a
|
|
15
|
+
# relative og_image is resolved through the SITE'S asset pipeline (image_url) to
|
|
16
|
+
# the DIGESTED /assets URL Propshaft serves — NOT the raw config path, which
|
|
17
|
+
# 404s; an absolute URL passes through. canonical/og:url come from
|
|
18
|
+
# config.seo.site_url, else the request URL; both are omitted off a request
|
|
19
|
+
# (guarded like Shell#csp_nonce, so an isolated render never raises).
|
|
18
20
|
class MetaTags < Phlex::HTML
|
|
19
21
|
include Phlex::Rails::Helpers::Request
|
|
22
|
+
include Phlex::Rails::Helpers::ImageURL
|
|
20
23
|
|
|
21
24
|
# title: the page title (nil on a page that sets none, e.g. the home
|
|
22
25
|
# page) — combined with config.title_suffix for og:title.
|
|
@@ -108,17 +111,37 @@ module DocsUI
|
|
|
108
111
|
meta(name: "theme-color", content: seo.theme_color)
|
|
109
112
|
end
|
|
110
113
|
|
|
111
|
-
# The og:image as an absolute
|
|
112
|
-
#
|
|
113
|
-
#
|
|
114
|
-
# the
|
|
114
|
+
# The og:image as an absolute URL a crawler can fetch, or nil to emit NO
|
|
115
|
+
# og:image (a valid card without an image — never a 404). nil when og_image is
|
|
116
|
+
# unset (the default). An already-absolute og_image passes through. A relative
|
|
117
|
+
# path is a logical asset in the SITE'S pipeline, resolved through image_url to
|
|
118
|
+
# the DIGESTED, host-qualified /assets URL Propshaft actually serves
|
|
119
|
+
# (https://host/assets/og/og-<digest>.png) — never the raw config path, which
|
|
120
|
+
# 404s. Off a request (an isolated render / static build) there is no asset
|
|
121
|
+
# pipeline to resolve a relative path, so we emit nothing rather than a
|
|
122
|
+
# guessed-and-wrong URL; a real app always renders with a view context.
|
|
115
123
|
def og_image_url
|
|
116
124
|
image = seo.og_image
|
|
117
125
|
return if image.to_s.empty?
|
|
118
126
|
return image if absolute?(image)
|
|
119
127
|
|
|
120
|
-
|
|
121
|
-
|
|
128
|
+
resolve_asset(image)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Resolve a logical asset path to its served (digested, host-qualified) URL via
|
|
132
|
+
# the Rails asset helper. nil when there's no view context (image_url delegates
|
|
133
|
+
# to view_context, which raises without one — the same seam Shell#csp_nonce
|
|
134
|
+
# guards), so an isolated render emits no og:image rather than raising.
|
|
135
|
+
#
|
|
136
|
+
# A configured-but-unresolvable og_image (asset missing / not precompiled)
|
|
137
|
+
# raises the pipeline's MissingAssetError — intended, NOT rescued: a broken
|
|
138
|
+
# og_image is a real misconfiguration that must surface at deploy time
|
|
139
|
+
# (assets:precompile runs before the app serves), not ship silently-broken
|
|
140
|
+
# social cards. A site with no card image leaves og_image nil (see #og_image_url).
|
|
141
|
+
def resolve_asset(path)
|
|
142
|
+
return unless view_context
|
|
143
|
+
|
|
144
|
+
image_url(path)
|
|
122
145
|
end
|
|
123
146
|
|
|
124
147
|
# The canonical/og:url for this page. From config.seo.site_url when set (its
|
|
@@ -132,28 +155,8 @@ module DocsUI
|
|
|
132
155
|
request.original_url
|
|
133
156
|
end
|
|
134
157
|
|
|
135
|
-
# The base URL for absolutizing a relative og:image: config.seo.site_url's
|
|
136
|
-
# origin, else the request base URL, else nil. site_url may include a path
|
|
137
|
-
# (for canonical); strip it to an origin so the image path joins cleanly.
|
|
138
|
-
def base_url
|
|
139
|
-
return origin_of(seo.site_url) if seo.site_url
|
|
140
|
-
return unless request?
|
|
141
|
-
|
|
142
|
-
request.base_url
|
|
143
|
-
end
|
|
144
|
-
|
|
145
158
|
def absolute?(url) = url.to_s.match?(%r{\Ahttps?://}i)
|
|
146
159
|
|
|
147
|
-
# Just the scheme+host(+port) of a URL, dropping any path — so joining an
|
|
148
|
-
# image path onto it never doubles a path segment.
|
|
149
|
-
def origin_of(url)
|
|
150
|
-
uri = URI.parse(url)
|
|
151
|
-
port = uri.port && uri.default_port != uri.port ? ":#{uri.port}" : ""
|
|
152
|
-
"#{uri.scheme}://#{uri.host}#{port}"
|
|
153
|
-
rescue URI::InvalidURIError
|
|
154
|
-
url
|
|
155
|
-
end
|
|
156
|
-
|
|
157
160
|
# True only when there's a live Rails view context AND a request on it — the
|
|
158
161
|
# phlex-rails #request helper delegates to view_context, which raises without
|
|
159
162
|
# one. Mirrors Shell#csp_nonce's guard so an isolated Phlex render (the specs,
|
data/lib/docs_kit/seo_config.rb
CHANGED
|
@@ -22,18 +22,20 @@ module DocsKit
|
|
|
22
22
|
# (DocsUI::Page derives a per-page value from #lead when a page sets none).
|
|
23
23
|
attr_accessor :description
|
|
24
24
|
|
|
25
|
-
# The social-share image
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
25
|
+
# The social-share image → og:image / twitter:image. Either a logical asset
|
|
26
|
+
# path in the SITE'S OWN pipeline (e.g. "og/og.png", resolved through
|
|
27
|
+
# image_url to the digested /assets URL Propshaft serves) or an absolute URL.
|
|
28
|
+
# The image is SITE content, not shipped by the gem — nil by default, so a
|
|
29
|
+
# site with no card image emits NO og:image (a valid card, never a 404).
|
|
30
|
+
# Generate one into app/assets/images/ with `bin/rails docs_kit:og`, then set
|
|
31
|
+
# this to its path.
|
|
29
32
|
attr_accessor :og_image
|
|
30
33
|
|
|
31
34
|
# The og:type. "website" for a docs site; a page could override to "article".
|
|
32
35
|
attr_accessor :og_type
|
|
33
36
|
|
|
34
37
|
# The twitter:card style. "summary_large_image" renders a full-width banner
|
|
35
|
-
# (
|
|
36
|
-
# square card.
|
|
38
|
+
# (size your og:image 1200×630 for it); "summary" is the small square card.
|
|
37
39
|
attr_accessor :twitter_card
|
|
38
40
|
|
|
39
41
|
# The site's @handle → twitter:site, and the content author's → twitter:creator.
|
|
@@ -64,7 +66,7 @@ module DocsKit
|
|
|
64
66
|
|
|
65
67
|
def initialize
|
|
66
68
|
@description = nil
|
|
67
|
-
@og_image =
|
|
69
|
+
@og_image = nil
|
|
68
70
|
@og_type = "website"
|
|
69
71
|
@twitter_card = "summary_large_image"
|
|
70
72
|
@twitter_site = nil
|
|
@@ -4,7 +4,10 @@ require "securerandom"
|
|
|
4
4
|
|
|
5
5
|
# Rails application template for a docs-kit docs site. Run via:
|
|
6
6
|
#
|
|
7
|
-
# rails new my-docs
|
|
7
|
+
# rails new my-docs -a propshaft -j importmap --skip-... -m new_site.rb
|
|
8
|
+
#
|
|
9
|
+
# (NOT --minimal — that strips JS the shell needs AND the thruster gem the
|
|
10
|
+
# generated Dockerfile fronts Puma with; exe/docs-kit passes the right flags.)
|
|
8
11
|
#
|
|
9
12
|
# or, more simply, via the `docs-kit new` CLI (exe/docs-kit) which supplies the
|
|
10
13
|
# right `rails new` flags. It:
|
|
@@ -101,45 +104,13 @@ after_bundle do
|
|
|
101
104
|
KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD
|
|
102
105
|
SH
|
|
103
106
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
ENV PATH="/usr/local/bun/bin:$PATH"
|
|
112
|
-
WORKDIR /rails
|
|
113
|
-
ENV BUNDLE_WITHOUT="development:test" RAILS_ENV="production"
|
|
114
|
-
|
|
115
|
-
RUN apt-get update -qq && \\
|
|
116
|
-
apt-get install --no-install-recommends -y curl libjemalloc2 && \\
|
|
117
|
-
rm -rf /var/lib/apt/lists /var/cache/apt/archives
|
|
118
|
-
RUN gem update --system --no-document && gem install -N bundler
|
|
119
|
-
|
|
120
|
-
FROM base AS build
|
|
121
|
-
RUN apt-get update -qq && \\
|
|
122
|
-
apt-get install --no-install-recommends -y build-essential git libyaml-dev pkg-config unzip
|
|
123
|
-
RUN curl -fsSL https://bun.sh/install | bash -s "bun-v${BUN_VERSION}"
|
|
124
|
-
COPY Gemfile Gemfile.lock ./
|
|
125
|
-
RUN bundle install && rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache
|
|
126
|
-
COPY . .
|
|
127
|
-
RUN bun install --frozen-lockfile
|
|
128
|
-
# assets:precompile runs bun run build:css via the css:build rake enhance.
|
|
129
|
-
RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
|
|
130
|
-
|
|
131
|
-
FROM base
|
|
132
|
-
# Kamal verifies this label on --skip-push deploy; must equal `service:`.
|
|
133
|
-
LABEL service="#{service}"
|
|
134
|
-
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
|
|
135
|
-
COPY --from=build /rails /rails
|
|
136
|
-
RUN groupadd --system --gid 1000 rails && \\
|
|
137
|
-
useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash && \\
|
|
138
|
-
chown -R 1000:1000 /rails/log /rails/tmp
|
|
139
|
-
USER 1000:1000
|
|
140
|
-
EXPOSE 3000
|
|
141
|
-
CMD ["./bin/rails", "server", "-b", "0.0.0.0"]
|
|
142
|
-
DOCKER
|
|
107
|
+
# The Dockerfile + .dockerignore are written by `docs_kit:install` (run above in
|
|
108
|
+
# after_bundle) so a scaffolded site and an upgrading site share ONE optimized,
|
|
109
|
+
# version-stamped Dockerfile — no divergent copy to maintain here. The generator
|
|
110
|
+
# derives the LABEL service from the app dir basename (= app_name); if the site
|
|
111
|
+
# deploys under a DIFFERENT Kamal service (`--service`), correct the label to
|
|
112
|
+
# match config/deploy.yml so Kamal's --skip-push validate_image passes.
|
|
113
|
+
gsub_file "Dockerfile", /LABEL service=".*"/, %(LABEL service="#{service}") if service != app_name
|
|
143
114
|
|
|
144
115
|
create_file ".github/workflows/deploy-docs.yml", <<~YAML
|
|
145
116
|
name: Deploy docs
|
data/lib/docs_kit/version.rb
CHANGED
|
@@ -4,6 +4,7 @@ require "erb"
|
|
|
4
4
|
require "yaml"
|
|
5
5
|
require "rails/generators/base"
|
|
6
6
|
require_relative "sync_report"
|
|
7
|
+
require_relative "../../../docs_kit/version"
|
|
7
8
|
|
|
8
9
|
module DocsKit
|
|
9
10
|
module Generators
|
|
@@ -168,18 +169,57 @@ module DocsKit
|
|
|
168
169
|
create_file "app/assets/builds/.keep", ""
|
|
169
170
|
end
|
|
170
171
|
|
|
171
|
-
#
|
|
172
|
-
#
|
|
173
|
-
#
|
|
174
|
-
#
|
|
175
|
-
#
|
|
176
|
-
#
|
|
172
|
+
# Install the `docs_kit:og` rake task — gem-owned wiring, refreshed on every
|
|
173
|
+
# run so a site picks up task fixes. It does NOT ship an OG image: the
|
|
174
|
+
# social-share image is SITE content, generated into the site's OWN
|
|
175
|
+
# app/assets/images/ by `bin/rails docs_kit:og`. Until a site runs it (and
|
|
176
|
+
# sets c.seo.og_image), no og:image tag is emitted — a valid card, never a
|
|
177
|
+
# 404 for an image the gem can't provide.
|
|
177
178
|
def create_og_task
|
|
178
179
|
template "docs_kit_og.rake", "lib/tasks/docs_kit_og.rake"
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# The production Dockerfile — a lean multi-stage build for a standalone
|
|
183
|
+
# docs site. Site-customizable (a site tunes packages/CMD), so skip when it
|
|
184
|
+
# exists and point an upgrader at the current template for a manual diff.
|
|
185
|
+
# The template stamps a `# docs-kit Dockerfile vX.Y.Z` marker so a `--sync`
|
|
186
|
+
# upgrade (SyncReport) can flag a stale copy. (create_initializer follows
|
|
187
|
+
# this same skip-if-exists + template-hint pattern.)
|
|
188
|
+
def create_dockerfile
|
|
189
|
+
dockerfile = "Dockerfile"
|
|
190
|
+
if File.exist?(File.join(destination_root, dockerfile))
|
|
191
|
+
template_path = File.join(self.class.source_root, "Dockerfile.tt")
|
|
192
|
+
return say_status(:skip, "#{dockerfile} exists — compare with #{template_path} if upgrading", :blue)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
template "Dockerfile.tt", dockerfile
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# The .dockerignore — gem-owned build-context trimming (node_modules, .git,
|
|
199
|
+
# logs, specs, coverage). Refreshed on every run (like create_og_task): it
|
|
200
|
+
# carries no site-specific content, so a re-run always ships the current
|
|
201
|
+
# excludes rather than fossilizing an old list.
|
|
202
|
+
def create_dockerignore
|
|
203
|
+
copy_file "dockerignore", ".dockerignore", force: true
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# When the site bundles thruster but lacks the binstub, create it — the
|
|
207
|
+
# Dockerfile's exec-form `CMD ["./bin/thrust", ...]` needs the file to EXIST
|
|
208
|
+
# in the image (`bundle install` installs the gem, not app binstubs, and
|
|
209
|
+
# `COPY . .` can't ship a file the repo doesn't have). Without this, the
|
|
210
|
+
# image builds green and the container crashes at boot. Skip-if-exists: a
|
|
211
|
+
# hand-tuned binstub is never touched.
|
|
212
|
+
def create_thrust_binstub
|
|
213
|
+
return unless gemfile_bundles_thruster? && !thrust_binstub?
|
|
214
|
+
|
|
215
|
+
create_file "bin/thrust", <<~RUBY
|
|
216
|
+
#!/usr/bin/env ruby
|
|
217
|
+
require "rubygems"
|
|
218
|
+
require "bundler/setup"
|
|
219
|
+
|
|
220
|
+
load Gem.bin_path("thruster", "thrust")
|
|
221
|
+
RUBY
|
|
222
|
+
chmod "bin/thrust", 0o755
|
|
183
223
|
end
|
|
184
224
|
|
|
185
225
|
def wire_assets_and_package_json
|
|
@@ -456,6 +496,56 @@ module DocsKit
|
|
|
456
496
|
name = defined?(Rails) && Rails.respond_to?(:application) && Rails.application&.class&.module_parent_name
|
|
457
497
|
(name || File.basename(destination_root)).to_s.underscore.humanize
|
|
458
498
|
end
|
|
499
|
+
|
|
500
|
+
# The Kamal `service` name stamped as the Dockerfile's LABEL — the app dir
|
|
501
|
+
# basename (a docs site's repo name), matching the `docs-kit new` default.
|
|
502
|
+
# Used in Dockerfile.tt via <%= docker_service %>.
|
|
503
|
+
def docker_service
|
|
504
|
+
File.basename(destination_root)
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
# The RUBY_VERSION build ARG default: the host's running Ruby (X.Y.Z), so a
|
|
508
|
+
# site's image matches its dev Ruby. Used in Dockerfile.tt.
|
|
509
|
+
def ruby_version_arg
|
|
510
|
+
RUBY_VERSION[/\d+\.\d+\.\d+/] || "3.4.2"
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
# True when the site bundles Thruster (HTTP caching + compression +
|
|
514
|
+
# X-Sendfile in front of Puma) — a Rails 8 `rails new` ships bin/thrust +
|
|
515
|
+
# the gem, but docs_kit:install also runs on older apps where a thrust CMD
|
|
516
|
+
# would crash the container at boot (Gem.bin_path raises). Decides which
|
|
517
|
+
# CMD Dockerfile.tt emits. A committed binstub is authoritative; otherwise
|
|
518
|
+
# the Gemfile decides (and create_thrust_binstub scaffolds the binstub).
|
|
519
|
+
def thruster?
|
|
520
|
+
thrust_binstub? || gemfile_bundles_thruster?
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
def thrust_binstub?
|
|
524
|
+
File.exist?(File.join(destination_root, "bin/thrust"))
|
|
525
|
+
end
|
|
526
|
+
|
|
527
|
+
# True when the Gemfile declares thruster where the PRODUCTION bundle sees
|
|
528
|
+
# it. The Dockerfile sets BUNDLE_WITHOUT="development:test", so a
|
|
529
|
+
# `group :development do ... end` entry (or an inline `group:` kwarg) must
|
|
530
|
+
# NOT count — the gem wouldn't be installed and thrust would raise at boot.
|
|
531
|
+
# Line-level block tracking: any `... do` pushes, `end` pops; a gem line
|
|
532
|
+
# counts only outside every group block (nested non-group blocks are fine).
|
|
533
|
+
def gemfile_bundles_thruster?
|
|
534
|
+
gemfile = File.join(destination_root, "Gemfile")
|
|
535
|
+
return false unless File.exist?(gemfile)
|
|
536
|
+
|
|
537
|
+
block_stack = []
|
|
538
|
+
File.foreach(gemfile) do |line|
|
|
539
|
+
if line.match?(/\bdo\s*(\|[^|]*\|)?\s*$/)
|
|
540
|
+
block_stack.push(line.match?(/^\s*group\b/))
|
|
541
|
+
elsif line.match?(/^\s*end\b/)
|
|
542
|
+
block_stack.pop
|
|
543
|
+
elsif block_stack.none? && line.match?(/^\s*gem\s+["']thruster["']/) && !line.match?(/\bgroup:/)
|
|
544
|
+
return true
|
|
545
|
+
end
|
|
546
|
+
end
|
|
547
|
+
false
|
|
548
|
+
end
|
|
459
549
|
end
|
|
460
550
|
end
|
|
461
551
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../../../docs_kit/version"
|
|
4
|
+
|
|
3
5
|
module DocsKit
|
|
4
6
|
module Generators
|
|
5
7
|
# Detects manual drift in an existing docs site that the install generator
|
|
@@ -9,13 +11,21 @@ module DocsKit
|
|
|
9
11
|
# generator prints these as a checklist during a `--sync` upgrade; the site
|
|
10
12
|
# owner deletes the flagged code by hand.
|
|
11
13
|
#
|
|
12
|
-
#
|
|
14
|
+
# Drift items, from the consumer audits:
|
|
13
15
|
# - ApplicationController hand-defines `render_page` — DocsKit::Controller
|
|
14
16
|
# (included by the generator for months) already provides it.
|
|
15
17
|
# - a dead IconHelper copy — the gem renders icons via rails_icons.
|
|
18
|
+
# - a Dockerfile stamped by an OLDER docs-kit than the gem now ships — the
|
|
19
|
+
# site should diff against the current template and adopt the improvements.
|
|
16
20
|
class SyncReport
|
|
17
21
|
APPLICATION_CONTROLLER = "app/controllers/application_controller.rb"
|
|
18
22
|
ICON_HELPER = "app/helpers/icon_helper.rb"
|
|
23
|
+
DOCKERFILE = "Dockerfile"
|
|
24
|
+
|
|
25
|
+
# Matches the version stamp the Dockerfile template writes, e.g.
|
|
26
|
+
# `# docs-kit Dockerfile v1.0.2`. Absent on a hand-written Dockerfile a site
|
|
27
|
+
# brought itself — which we deliberately leave alone (no marker → no warning).
|
|
28
|
+
DOCKERFILE_MARKER = /docs-kit Dockerfile v(\d+\.\d+\.\d+)/
|
|
19
29
|
|
|
20
30
|
def initialize(destination_root)
|
|
21
31
|
@root = destination_root
|
|
@@ -24,7 +34,7 @@ module DocsKit
|
|
|
24
34
|
# The drift messages, in the order a site should act on them. Empty when
|
|
25
35
|
# the site is clean.
|
|
26
36
|
def items
|
|
27
|
-
[render_page_drift, icon_helper_drift].compact
|
|
37
|
+
[render_page_drift, icon_helper_drift, dockerfile_drift].compact
|
|
28
38
|
end
|
|
29
39
|
|
|
30
40
|
def clean?
|
|
@@ -53,6 +63,22 @@ module DocsKit
|
|
|
53
63
|
"rails_icons (DocsUI::Icon); delete it."
|
|
54
64
|
end
|
|
55
65
|
|
|
66
|
+
# The site's Dockerfile carries a docs-kit version stamp OLDER than the gem
|
|
67
|
+
# now ships. We never rewrite the site's Dockerfile (it's tuned per site) —
|
|
68
|
+
# we point the owner at the current template to diff or replace. A file with
|
|
69
|
+
# no marker (a hand-written Dockerfile) is left alone: no stamp, no warning.
|
|
70
|
+
def dockerfile_drift
|
|
71
|
+
source = read(DOCKERFILE)
|
|
72
|
+
stamped = source&.match(DOCKERFILE_MARKER)
|
|
73
|
+
return unless stamped
|
|
74
|
+
|
|
75
|
+
site_version = stamped[1]
|
|
76
|
+
return if site_version == DocsKit::VERSION
|
|
77
|
+
|
|
78
|
+
"#{DOCKERFILE} is v#{site_version}, docs-kit now ships v#{DocsKit::VERSION} — " \
|
|
79
|
+
"diff against the template (bin/rails g docs_kit:install shows the path) and adopt the changes."
|
|
80
|
+
end
|
|
81
|
+
|
|
56
82
|
def read(rel)
|
|
57
83
|
path = File.join(@root, rel)
|
|
58
84
|
File.exist?(path) ? File.read(path) : nil
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# syntax = docker/dockerfile:1
|
|
2
|
+
# docs-kit Dockerfile v<%= DocsKit::VERSION %> — regenerate/diff: bin/rails g docs_kit:install
|
|
3
|
+
#
|
|
4
|
+
# A standalone docs-kit site: a lean, multi-stage production image. The final
|
|
5
|
+
# stage carries only the runtime (Ruby + the installed bundle + the app), never
|
|
6
|
+
# the build toolchain (build-essential, git, bun) — those live in the throwaway
|
|
7
|
+
# `build` stage. Pair it with the shipped .dockerignore so the build context
|
|
8
|
+
# stays small (no node_modules, .git, logs, specs, coverage).
|
|
9
|
+
#
|
|
10
|
+
# Build context is the app root; `docker build .` (Kamal: context: ".").
|
|
11
|
+
|
|
12
|
+
ARG RUBY_VERSION=<%= ruby_version_arg %>
|
|
13
|
+
FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base
|
|
14
|
+
|
|
15
|
+
# Rails app lives here.
|
|
16
|
+
WORKDIR /rails
|
|
17
|
+
|
|
18
|
+
ARG BUN_VERSION=1.3.2
|
|
19
|
+
ENV BUN_INSTALL="/usr/local/bun" \
|
|
20
|
+
PATH="/usr/local/bun/bin:$PATH" \
|
|
21
|
+
BUNDLE_DEPLOYMENT="1" \
|
|
22
|
+
BUNDLE_PATH="/usr/local/bundle" \
|
|
23
|
+
BUNDLE_WITHOUT="development:test" \
|
|
24
|
+
RAILS_ENV="production"
|
|
25
|
+
|
|
26
|
+
# Base packages the RUNTIME needs (jemalloc for a smaller/faster heap, curl for
|
|
27
|
+
# the container healthcheck). Anything only the build needs goes in `build`.
|
|
28
|
+
RUN apt-get update -qq && \
|
|
29
|
+
apt-get install --no-install-recommends -y curl libjemalloc2 && \
|
|
30
|
+
rm -rf /var/lib/apt/lists /var/cache/apt/archives
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# --- Build stage (throwaway — its layers never reach the final image) ---------
|
|
34
|
+
FROM base AS build
|
|
35
|
+
|
|
36
|
+
# Toolchain to compile native gems + fetch bun. Skip the apt cleanup: this whole
|
|
37
|
+
# stage is discarded.
|
|
38
|
+
RUN apt-get update -qq && \
|
|
39
|
+
apt-get install --no-install-recommends -y build-essential git libyaml-dev pkg-config unzip
|
|
40
|
+
RUN curl -fsSL https://bun.sh/install | bash -s -- "bun-v${BUN_VERSION}"
|
|
41
|
+
|
|
42
|
+
# Install gems first (cached until Gemfile/Gemfile.lock change), then prune the
|
|
43
|
+
# bundler cache + any git-sourced gem checkouts so they don't bloat the layer.
|
|
44
|
+
COPY Gemfile Gemfile.lock ./
|
|
45
|
+
RUN bundle install && \
|
|
46
|
+
rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git
|
|
47
|
+
|
|
48
|
+
# Install JS deps (the Tailwind/daisyUI CLI), then the app.
|
|
49
|
+
COPY package.json bun.lock* ./
|
|
50
|
+
RUN bun install --frozen-lockfile
|
|
51
|
+
COPY . .
|
|
52
|
+
|
|
53
|
+
# assets:precompile runs `bun run build:css` via the css:build rake enhance.
|
|
54
|
+
# Drop the node_modules + bun cache afterwards — the built CSS is all we keep.
|
|
55
|
+
RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile && \
|
|
56
|
+
rm -rf node_modules .bun tmp/cache
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# --- Final stage --------------------------------------------------------------
|
|
60
|
+
FROM base
|
|
61
|
+
|
|
62
|
+
# Kamal's validate_image greps this label on a --skip-push deploy; it must equal
|
|
63
|
+
# `service:` in config/deploy.yml. The reusable deploy workflow also stamps it,
|
|
64
|
+
# but keeping it here means `docker build` alone produces a Kamal-valid image.
|
|
65
|
+
LABEL service="<%= docker_service %>"
|
|
66
|
+
|
|
67
|
+
# Copy ONLY the built artifacts from the build stage: the installed bundle and
|
|
68
|
+
# the app (with precompiled assets). No toolchain, no node_modules.
|
|
69
|
+
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
|
|
70
|
+
COPY --from=build /rails /rails
|
|
71
|
+
|
|
72
|
+
# Run as a non-root user; own only the runtime dirs it writes.
|
|
73
|
+
RUN groupadd --system --gid 1000 rails && \
|
|
74
|
+
useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash && \
|
|
75
|
+
chown -R 1000:1000 /rails/log /rails/tmp
|
|
76
|
+
USER 1000:1000
|
|
77
|
+
|
|
78
|
+
EXPOSE 3000
|
|
79
|
+
<% if thruster? -%>
|
|
80
|
+
# Thruster fronts Puma (HTTP caching + compression + X-Sendfile). It listens on
|
|
81
|
+
# HTTP_PORT and proxies to Puma on TARGET_PORT (it sets PORT for the child, which
|
|
82
|
+
# config/puma.rb reads). HTTP_PORT MUST be the port traffic is routed to (Kamal's
|
|
83
|
+
# `app_port`, the EXPOSE above) — Thruster's default is 80, which the non-root
|
|
84
|
+
# user can't reliably bind AND which kamal-proxy (app_port: 3000) would never
|
|
85
|
+
# route to, silently bypassing Thruster straight into Puma.
|
|
86
|
+
ENV HTTP_PORT="3000" \
|
|
87
|
+
TARGET_PORT="3001"
|
|
88
|
+
CMD ["./bin/thrust", "./bin/rails", "server"]
|
|
89
|
+
<% else -%>
|
|
90
|
+
# No Thruster in this app's bundle — plain Puma. To front it with Thruster
|
|
91
|
+
# (HTTP caching/compression/X-Sendfile): add `gem "thruster"`, then delete this
|
|
92
|
+
# file and re-run `bin/rails g docs_kit:install` — the generator never
|
|
93
|
+
# overwrites an existing Dockerfile, so a re-run alone won't update it. (It
|
|
94
|
+
# also scaffolds the bin/thrust binstub the thrust CMD needs.)
|
|
95
|
+
CMD ["./bin/rails", "server", "-b", "0.0.0.0"]
|
|
96
|
+
<% end -%>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# docs-kit .dockerignore — keep the build context (and image layers) small.
|
|
2
|
+
# Gem-owned: `bin/rails g docs_kit:install` refreshes this on every run.
|
|
3
|
+
# See https://docs.docker.com/build/building/context/#dockerignore-files
|
|
4
|
+
|
|
5
|
+
# Git metadata — the app build never needs it (a released gem carries its files).
|
|
6
|
+
/.git/
|
|
7
|
+
/.gitignore
|
|
8
|
+
/.gitattributes
|
|
9
|
+
|
|
10
|
+
# Bundler config (BUNDLE_* env in the Dockerfile drives the install instead).
|
|
11
|
+
/.bundle
|
|
12
|
+
|
|
13
|
+
# Environment files and credentials — never bake secrets into an image.
|
|
14
|
+
/.env*
|
|
15
|
+
!/.env*.erb
|
|
16
|
+
/config/master.key
|
|
17
|
+
/config/credentials/*.key
|
|
18
|
+
|
|
19
|
+
# Logs and tempfiles (keep the dirs, drop the contents).
|
|
20
|
+
/log/*
|
|
21
|
+
!/log/.keep
|
|
22
|
+
/tmp/*
|
|
23
|
+
!/tmp/.keep
|
|
24
|
+
/tmp/pids/*
|
|
25
|
+
!/tmp/pids/.keep
|
|
26
|
+
|
|
27
|
+
# JS deps + generated assets: `bun install` + `assets:precompile` rebuild them.
|
|
28
|
+
/node_modules/
|
|
29
|
+
/app/assets/builds/*
|
|
30
|
+
!/app/assets/builds/.keep
|
|
31
|
+
# Generated by bin/build-css — Tailwind resolves the gem @source globs at build.
|
|
32
|
+
/app/assets/stylesheets/tailwind.sources.css
|
|
33
|
+
/public/assets
|
|
34
|
+
|
|
35
|
+
# Tests + coverage — not needed to run the site in production.
|
|
36
|
+
/spec/
|
|
37
|
+
/.rspec
|
|
38
|
+
/coverage/
|
|
39
|
+
/spec/examples.txt
|
|
40
|
+
|
|
41
|
+
# CI / deploy / Docker meta — not part of the runtime image.
|
|
42
|
+
/.github/
|
|
43
|
+
/.kamal/
|
|
44
|
+
/Dockerfile*
|
|
45
|
+
/.dockerignore
|
|
46
|
+
|
|
47
|
+
# Editor + AI-assistant configs.
|
|
48
|
+
/.claude/
|
|
49
|
+
/.cursor/
|
|
50
|
+
/.vscode/
|
|
51
|
+
/.idea/
|
|
52
|
+
/.ruby-lsp/
|
|
53
|
+
/.solargraph.yml
|
|
54
|
+
|
|
55
|
+
# Docs-kit's own tooling snapshots (harmless if absent in a consuming site).
|
|
56
|
+
/codedb.snapshot
|
|
57
|
+
/.worktrees/
|
|
@@ -36,19 +36,21 @@ Rails.application.config.to_prepare do
|
|
|
36
36
|
# that sets none still gets a valid minimal card. Per-page descriptions come
|
|
37
37
|
# from each page's `description "..."` (falling back to its lead paragraph).
|
|
38
38
|
# c.seo.description = "What these docs cover, in one sentence."
|
|
39
|
-
# c.seo.og_image = "og/og.png" # generated by `bin/rails docs_kit:og`
|
|
40
39
|
# c.seo.twitter_card = "summary_large_image" # default; "summary" = small card
|
|
41
40
|
# c.seo.twitter_site = "@your_handle"
|
|
42
41
|
# c.seo.twitter_creator = "@author_handle"
|
|
43
|
-
# c.seo.site_url = "https://docs.example.com" #
|
|
42
|
+
# c.seo.site_url = "https://docs.example.com" # your canonical base URL
|
|
44
43
|
# c.seo.locale = "en_US"
|
|
45
44
|
# c.seo.robots = "noindex, nofollow" # keep a staging/private site out of search
|
|
46
45
|
# c.seo.favicon = "/favicon.ico"
|
|
47
46
|
# c.seo.theme_color = "#0f172a" # tints mobile browser chrome
|
|
48
47
|
#
|
|
49
|
-
#
|
|
50
|
-
# "/" into app/assets/images/og/)
|
|
48
|
+
# The social-share image is YOUR content, not shipped by the gem. Generate one
|
|
49
|
+
# from your landing page (screenshots "/" into app/assets/images/og/) and point
|
|
50
|
+
# og_image at it — it's resolved through YOUR asset pipeline to the digested
|
|
51
|
+
# /assets URL. Until you set it, no og:image is emitted (a valid card, no 404).
|
|
51
52
|
# bin/rails docs_kit:og
|
|
53
|
+
# c.seo.og_image = "og/og.png" # a path in app/assets/images/
|
|
52
54
|
|
|
53
55
|
# Code blocks use one Rouge theme by default. To keep them readable in BOTH
|
|
54
56
|
# light and dark daisyUI themes, set a light base + a dark override — the dark
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: docs-kit
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mikael Henriksson
|
|
@@ -164,8 +164,6 @@ files:
|
|
|
164
164
|
- CHANGELOG.md
|
|
165
165
|
- LICENSE.txt
|
|
166
166
|
- README.md
|
|
167
|
-
- app/assets/images/og/og.png
|
|
168
|
-
- app/assets/images/og/og.svg
|
|
169
167
|
- app/components/docs_ui/brand_mark.rb
|
|
170
168
|
- app/components/docs_ui/callout.rb
|
|
171
169
|
- app/components/docs_ui/code.rb
|
|
@@ -235,11 +233,13 @@ files:
|
|
|
235
233
|
- lib/generators/docs_kit/install/USAGE
|
|
236
234
|
- lib/generators/docs_kit/install/install_generator.rb
|
|
237
235
|
- lib/generators/docs_kit/install/sync_report.rb
|
|
236
|
+
- lib/generators/docs_kit/install/templates/Dockerfile.tt
|
|
238
237
|
- lib/generators/docs_kit/install/templates/agents_md.erb
|
|
239
238
|
- lib/generators/docs_kit/install/templates/application.tailwind.css.erb
|
|
240
239
|
- lib/generators/docs_kit/install/templates/build-css
|
|
241
240
|
- lib/generators/docs_kit/install/templates/build_css.rake
|
|
242
241
|
- lib/generators/docs_kit/install/templates/doc.rb.erb
|
|
242
|
+
- lib/generators/docs_kit/install/templates/dockerignore
|
|
243
243
|
- lib/generators/docs_kit/install/templates/docs_controller.rb.erb
|
|
244
244
|
- lib/generators/docs_kit/install/templates/docs_kit.rb.erb
|
|
245
245
|
- lib/generators/docs_kit/install/templates/docs_kit_og.rake
|
data/app/assets/images/og/og.png
DELETED
|
Binary file
|
data/app/assets/images/og/og.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg height="630" viewBox="0 0 1200 630" width="1200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" x1="0" x2="1" y1="0" y2="1"><stop offset="0" stop-color="#0f172a"/><stop offset="1" stop-color="#1e293b"/></linearGradient><linearGradient id="b" x1="0" x2="1" y1="0" y2="0"><stop offset="0" stop-color="#38bdf8"/><stop offset="1" stop-color="#818cf8"/></linearGradient><path d="m0 0h1200v630h-1200z" fill="url(#a)"/><path d="m0 0h1200v8h-1200z" fill="url(#b)"/><path d="m80 470h240m-240 40h180m-180 40h220" fill="none" opacity=".5" stroke="#334155" stroke-width="2"/><g transform="translate(80 150)"><rect fill="url(#b)" height="96" rx="20" width="96"/><path d="m28 32h40m-40 16h40m-40 16h28" stroke="#0f172a" stroke-linecap="round" stroke-width="7"/></g><g font-family="Helvetica, Arial, sans-serif"><text fill="#f8fafc" font-size="88" font-weight="700" x="80" y="330">Documentation</text><text fill="#94a3b8" font-size="34" font-weight="400" x="82" y="392">Built with docs-kit</text></g></svg>
|