jekyll-theme-zer0 1.21.0 → 1.22.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.
@@ -0,0 +1,509 @@
1
+ #!/bin/bash
2
+
3
+ # giscus-discussions — read, draft, and post the GitHub Discussions that back
4
+ # the site's Giscus comment threads. This is the engine the Claude Code
5
+ # `giscus-conversation` skill drives to build conversations from page comments.
6
+ #
7
+ # Subcommands:
8
+ # categories List the repo's discussion categories + node IDs (setup helper)
9
+ # list List discussions in the configured Giscus category
10
+ # thread Print a discussion's full conversation (comments + replies)
11
+ # draft Write a Markdown draft scaffold (thread context + reply slot)
12
+ # seed Create a new discussion for a page (starts a conversation)
13
+ # post Add a comment or reply to an existing discussion
14
+ #
15
+ # Reads owner/repo from `gh repo view` and the Giscus category from
16
+ # _config.yml (giscus.data-category-id). Both are overridable via flags/env.
17
+ #
18
+ # Usage: ./scripts/bin/giscus-discussions <subcommand> [options]
19
+ # Requires: gh (authenticated). Writes (seed/post) honor --dry-run.
20
+
21
+ set -euo pipefail
22
+
23
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
24
+ LIB_DIR="$SCRIPT_DIR/../lib"
25
+ REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
26
+
27
+ # shellcheck source=/dev/null
28
+ source "$LIB_DIR/common.sh"
29
+
30
+ # ---------------------------------------------------------------------------
31
+ # Configuration resolution
32
+ # ---------------------------------------------------------------------------
33
+
34
+ CONFIG_FILE="$REPO_ROOT/_config.yml"
35
+
36
+ # Owner/repo: env GISCUS_REPO or --repo override; else derive from gh.
37
+ REPO_NWO="${GISCUS_REPO:-}"
38
+ # Giscus category node id: env GISCUS_CATEGORY_ID or --category-id; else config.
39
+ CATEGORY_ID="${GISCUS_CATEGORY_ID:-}"
40
+
41
+ resolve_repo() {
42
+ if [[ -n "$REPO_NWO" ]]; then
43
+ return 0
44
+ fi
45
+ require_command gh "install: https://cli.github.com/"
46
+ REPO_NWO="$(gh repo view --json nameWithOwner -q .nameWithOwner 2>/dev/null || true)"
47
+ if [[ -z "$REPO_NWO" ]]; then
48
+ error "Could not determine repository. Pass --repo owner/name or set GISCUS_REPO."
49
+ fi
50
+ }
51
+
52
+ # Extract giscus.data-category-id from _config.yml (block-scoped).
53
+ config_category_id() {
54
+ [[ -f "$CONFIG_FILE" ]] || return 0
55
+ awk '/^giscus:/{f=1;next} f&&/^[^[:space:]#]/{f=0} f' "$CONFIG_FILE" \
56
+ | grep -E '^[[:space:]]+data-category-id:' \
57
+ | head -1 \
58
+ | sed -E 's/^[[:space:]]+data-category-id:[[:space:]]*//; s/^"//; s/"[[:space:]]*$//; s/^'"'"'//; s/'"'"'[[:space:]]*$//'
59
+ }
60
+
61
+ resolve_category() {
62
+ if [[ -n "$CATEGORY_ID" ]]; then
63
+ return 0
64
+ fi
65
+ CATEGORY_ID="$(config_category_id)"
66
+ if [[ -z "$CATEGORY_ID" ]]; then
67
+ error "No category id. Pass --category-id, set GISCUS_CATEGORY_ID, or fix giscus.data-category-id in _config.yml (see: $0 categories)."
68
+ fi
69
+ }
70
+
71
+ owner_of() { printf '%s' "${1%%/*}"; }
72
+ name_of() { printf '%s' "${1##*/}"; }
73
+
74
+ # Normalize a page path so it matches a Giscus pathname-mapped discussion title.
75
+ normalize_page() {
76
+ local p="$1"
77
+ if [[ "$p" == *"://"* ]]; then
78
+ p="${p#*://}" # strip scheme
79
+ p="/${p#*/}" # strip host, keep path with a leading slash
80
+ fi
81
+ [[ "$p" != /* ]] && p="/$p"
82
+ printf '%s' "$p"
83
+ }
84
+
85
+ # ---------------------------------------------------------------------------
86
+ # GraphQL helpers
87
+ # ---------------------------------------------------------------------------
88
+
89
+ repo_node_id() {
90
+ gh api graphql -f query='
91
+ query($owner:String!,$name:String!){
92
+ repository(owner:$owner,name:$name){ id }
93
+ }' -F owner="$(owner_of "$REPO_NWO")" -F name="$(name_of "$REPO_NWO")" \
94
+ --jq '.data.repository.id'
95
+ }
96
+
97
+ # Find a discussion number whose title equals the (normalized) page path.
98
+ # Echoes the number, or nothing if not found.
99
+ discussion_number_for_page() {
100
+ local page; page="$(normalize_page "$1")"
101
+ local page_noslash="${page%/}"
102
+ gh api graphql -f query='
103
+ query($owner:String!,$name:String!,$categoryId:ID,$after:String){
104
+ repository(owner:$owner,name:$name){
105
+ discussions(first:100,after:$after,categoryId:$categoryId){
106
+ nodes{ number title }
107
+ pageInfo{ hasNextPage endCursor }
108
+ }
109
+ }
110
+ }' -F owner="$(owner_of "$REPO_NWO")" -F name="$(name_of "$REPO_NWO")" \
111
+ -f categoryId="$CATEGORY_ID" \
112
+ --jq ".data.repository.discussions.nodes[]
113
+ | select(.title == \"$page\" or .title == \"$page_noslash\")
114
+ | .number" | head -1
115
+ }
116
+
117
+ discussion_node_id() {
118
+ local number="$1"
119
+ gh api graphql -f query='
120
+ query($owner:String!,$name:String!,$number:Int!){
121
+ repository(owner:$owner,name:$name){ discussion(number:$number){ id } }
122
+ }' -F owner="$(owner_of "$REPO_NWO")" -F name="$(name_of "$REPO_NWO")" \
123
+ -F number="$number" \
124
+ --jq '.data.repository.discussion.id'
125
+ }
126
+
127
+ # ---------------------------------------------------------------------------
128
+ # Subcommand: categories
129
+ # ---------------------------------------------------------------------------
130
+
131
+ cmd_categories() {
132
+ resolve_repo
133
+ info "Discussion categories for $REPO_NWO:"
134
+ gh api graphql -f query='
135
+ query($owner:String!,$name:String!){
136
+ repository(owner:$owner,name:$name){
137
+ hasDiscussionsEnabled
138
+ discussionCategories(first:30){ nodes{ id name slug } }
139
+ }
140
+ }' -F owner="$(owner_of "$REPO_NWO")" -F name="$(name_of "$REPO_NWO")" \
141
+ --jq '.data.repository as $r
142
+ | if $r.hasDiscussionsEnabled then empty
143
+ else "WARNING: Discussions are NOT enabled on this repo." end,
144
+ ($r.discussionCategories.nodes[] | " \(.id)\t\(.name)")'
145
+ }
146
+
147
+ # ---------------------------------------------------------------------------
148
+ # Subcommand: list
149
+ # ---------------------------------------------------------------------------
150
+
151
+ cmd_list() {
152
+ local as_json=false
153
+ while [[ $# -gt 0 ]]; do
154
+ case "$1" in
155
+ --repo) REPO_NWO="$2"; shift 2 ;;
156
+ --category-id) CATEGORY_ID="$2"; shift 2 ;;
157
+ --json) as_json=true; shift ;;
158
+ *) error "list: unknown option '$1'" ;;
159
+ esac
160
+ done
161
+ resolve_repo; resolve_category
162
+ local owner name; owner="$(owner_of "$REPO_NWO")"; name="$(name_of "$REPO_NWO")"
163
+ local query='
164
+ query($owner:String!,$name:String!,$categoryId:ID){
165
+ repository(owner:$owner,name:$name){
166
+ discussions(first:100,categoryId:$categoryId,orderBy:{field:UPDATED_AT,direction:DESC}){
167
+ nodes{ number title url updatedAt comments{ totalCount } author{ login } }
168
+ }
169
+ }
170
+ }'
171
+ if [[ "$as_json" == true ]]; then
172
+ gh api graphql -f query="$query" -F owner="$owner" -F name="$name" \
173
+ -f categoryId="$CATEGORY_ID" --jq '.data.repository.discussions.nodes'
174
+ return 0
175
+ fi
176
+ local out
177
+ out="$(gh api graphql -f query="$query" -F owner="$owner" -F name="$name" \
178
+ -f categoryId="$CATEGORY_ID" \
179
+ --jq '.data.repository.discussions.nodes[]
180
+ | "#\(.number)\t\(.comments.totalCount) comment(s)\t\(.title)\n\t\(.url)"')"
181
+ if [[ -z "$out" ]]; then
182
+ info "No discussions yet in the Giscus category for $REPO_NWO."
183
+ info "Giscus creates one on the first visitor comment, or seed one:"
184
+ info " $0 seed --page /path/ --title ... --body ..."
185
+ return 0
186
+ fi
187
+ info "Discussions in the Giscus category for $REPO_NWO:"
188
+ printf '%s\n' "$out"
189
+ }
190
+
191
+ # ---------------------------------------------------------------------------
192
+ # Subcommand: thread
193
+ # ---------------------------------------------------------------------------
194
+
195
+ THREAD_QUERY='
196
+ query($owner:String!,$name:String!,$number:Int!){
197
+ repository(owner:$owner,name:$name){
198
+ discussion(number:$number){
199
+ number title url body createdAt id
200
+ author{ login }
201
+ comments(first:100){
202
+ totalCount
203
+ nodes{
204
+ id body createdAt author{ login }
205
+ replies(first:100){ nodes{ id body createdAt author{ login } } }
206
+ }
207
+ }
208
+ }
209
+ }
210
+ }'
211
+
212
+ # jq program that renders a discussion thread as readable Markdown.
213
+ THREAD_MD_JQ='
214
+ .data.repository.discussion as $d
215
+ | "# \($d.title)\n\n- URL: \($d.url)\n- Discussion: #\($d.number) (node: \($d.id))\n- Opened by: @\($d.author.login // "unknown") on \($d.createdAt)\n\n## Original post\n\n\($d.body)\n\n## Comments (\($d.comments.totalCount))\n"
216
+ + ( [ $d.comments.nodes[]
217
+ | "\n### @\(.author.login // "unknown") — \(.createdAt)\n_comment id: `\(.id)`_\n\n\(.body)\n"
218
+ + ( if (.replies.nodes | length) > 0
219
+ then "\n" + ( [ .replies.nodes[]
220
+ | " - **@\(.author.login // "unknown")** (\(.createdAt)) _reply id: `\(.id)`_\n\n \(.body | gsub("\n"; "\n "))" ] | join("\n") ) + "\n"
221
+ else "" end )
222
+ ] | join("\n---\n") )'
223
+
224
+ # Render a thread as Markdown (uses gh's bundled jq — no external jq needed).
225
+ fetch_thread_md() {
226
+ local number="$1"
227
+ gh api graphql -f query="$THREAD_QUERY" \
228
+ -F owner="$(owner_of "$REPO_NWO")" -F name="$(name_of "$REPO_NWO")" \
229
+ -F number="$number" --jq "$THREAD_MD_JQ"
230
+ }
231
+
232
+ # Fetch the raw discussion JSON.
233
+ fetch_thread_raw() {
234
+ local number="$1"
235
+ gh api graphql -f query="$THREAD_QUERY" \
236
+ -F owner="$(owner_of "$REPO_NWO")" -F name="$(name_of "$REPO_NWO")" \
237
+ -F number="$number"
238
+ }
239
+
240
+ resolve_number_arg() {
241
+ # Sets NUMBER from --number, --url, or --page. Used by thread/draft/post.
242
+ local number="" url="" page=""
243
+ REMAINING_ARGS=()
244
+ while [[ $# -gt 0 ]]; do
245
+ case "$1" in
246
+ --number) number="$2"; shift 2 ;;
247
+ --url) url="$2"; shift 2 ;;
248
+ --page) page="$2"; shift 2 ;;
249
+ --repo) REPO_NWO="$2"; shift 2 ;;
250
+ --category-id) CATEGORY_ID="$2"; shift 2 ;;
251
+ *) REMAINING_ARGS+=("$1"); shift ;;
252
+ esac
253
+ done
254
+ resolve_repo
255
+ if [[ -n "$number" ]]; then
256
+ NUMBER="$number"
257
+ elif [[ -n "$url" ]]; then
258
+ NUMBER="${url##*/}"
259
+ elif [[ -n "$page" ]]; then
260
+ resolve_category
261
+ NUMBER="$(discussion_number_for_page "$page")"
262
+ [[ -z "$NUMBER" ]] && error "No discussion found for page '$page'. Seed one with: $0 seed --page '$page' --title ... --body ..."
263
+ else
264
+ error "Provide --number N, --url URL, or --page PATH."
265
+ fi
266
+ }
267
+
268
+ cmd_thread() {
269
+ local as_json=false
270
+ local args=()
271
+ for a in "$@"; do
272
+ [[ "$a" == "--json" ]] && { as_json=true; continue; }
273
+ args+=("$a")
274
+ done
275
+ resolve_number_arg "${args[@]}"
276
+ if [[ "$as_json" == true ]]; then
277
+ fetch_thread_raw "$NUMBER"
278
+ else
279
+ fetch_thread_md "$NUMBER"
280
+ fi
281
+ }
282
+
283
+ # ---------------------------------------------------------------------------
284
+ # Subcommand: draft
285
+ # ---------------------------------------------------------------------------
286
+
287
+ cmd_draft() {
288
+ local out=""
289
+ local args=()
290
+ while [[ $# -gt 0 ]]; do
291
+ case "$1" in
292
+ --out) out="$2"; shift 2 ;;
293
+ *) args+=("$1"); shift ;;
294
+ esac
295
+ done
296
+ resolve_number_arg "${args[@]}"
297
+ [[ -z "$out" ]] && out="$REPO_ROOT/giscus-draft-${NUMBER}.md"
298
+ {
299
+ echo "<!-- Giscus reply draft. Edit the REPLY section, then post with:"
300
+ echo " ./scripts/bin/giscus-discussions post --number $NUMBER --body-file \"$out\" [--reply-to <comment id>] [--dry-run]"
301
+ echo " Everything above the REPLY marker is context and is NOT posted. -->"
302
+ echo
303
+ echo "## Conversation context"
304
+ echo
305
+ fetch_thread_md "$NUMBER"
306
+ echo
307
+ echo "<!-- ===== REPLY (everything below this line is your draft) ===== -->"
308
+ echo
309
+ echo "_Draft your reply here._"
310
+ echo
311
+ } > "$out"
312
+ success "Draft scaffold written: $out"
313
+ info "Fill in the REPLY section, then: $0 post --number $NUMBER --body-file \"$out\" --reply-to <id> --dry-run"
314
+ }
315
+
316
+ # Extract just the reply portion (everything below the REPLY marker) from a
317
+ # draft file produced by `draft`, dropping leading blank lines.
318
+ extract_reply_body() {
319
+ awk 'f{print} /===== REPLY/{f=1}' "$1" | sed '/./,$!d'
320
+ }
321
+
322
+ # ---------------------------------------------------------------------------
323
+ # Subcommand: seed (create a new discussion for a page)
324
+ # ---------------------------------------------------------------------------
325
+
326
+ cmd_seed() {
327
+ local page="" title="" body="" body_file=""
328
+ while [[ $# -gt 0 ]]; do
329
+ case "$1" in
330
+ --page) page="$2"; shift 2 ;;
331
+ --title) title="$2"; shift 2 ;;
332
+ --body) body="$2"; shift 2 ;;
333
+ --body-file) body_file="$2"; shift 2 ;;
334
+ --repo) REPO_NWO="$2"; shift 2 ;;
335
+ --category-id) CATEGORY_ID="$2"; shift 2 ;;
336
+ --dry-run) DRY_RUN=true; shift ;;
337
+ *) error "seed: unknown option '$1'" ;;
338
+ esac
339
+ done
340
+ resolve_repo; resolve_category
341
+ [[ -z "$page" ]] && error "seed: --page PATH is required (Giscus maps the discussion title to the page path)."
342
+ page="$(normalize_page "$page")"
343
+ [[ -z "$title" ]] && title="$page"
344
+ if [[ -n "$body_file" ]]; then
345
+ require_file "$body_file" "body file"
346
+ body="$(cat "$body_file")"
347
+ fi
348
+ [[ -z "$body" ]] && error "seed: provide --body TEXT or --body-file FILE."
349
+
350
+ local existing; existing="$(discussion_number_for_page "$page" || true)"
351
+ if [[ -n "$existing" ]]; then
352
+ error "A discussion already exists for '$page' (#$existing). Use: $0 post --number $existing ..."
353
+ fi
354
+
355
+ if [[ "$DRY_RUN" == "true" ]]; then
356
+ info "[DRY RUN] Would create discussion in $REPO_NWO (category $CATEGORY_ID):"
357
+ info " title: $title"
358
+ info " body: $(printf '%s' "$body" | head -c 200)"
359
+ return 0
360
+ fi
361
+
362
+ local repo_id; repo_id="$(repo_node_id)"
363
+ gh api graphql -f query='
364
+ mutation($repoId:ID!,$categoryId:ID!,$title:String!,$body:String!){
365
+ createDiscussion(input:{repositoryId:$repoId,categoryId:$categoryId,title:$title,body:$body}){
366
+ discussion{ number url }
367
+ }
368
+ }' -F repoId="$repo_id" -F categoryId="$CATEGORY_ID" \
369
+ -F title="$title" -F body="$body" \
370
+ --jq '.data.createDiscussion.discussion | "Created discussion #\(.number): \(.url)"'
371
+ success "Discussion created for $page"
372
+ }
373
+
374
+ # ---------------------------------------------------------------------------
375
+ # Subcommand: post (comment on / reply to an existing discussion)
376
+ # ---------------------------------------------------------------------------
377
+
378
+ cmd_post() {
379
+ local number="" url="" page="" body="" body_file="" reply_to=""
380
+ while [[ $# -gt 0 ]]; do
381
+ case "$1" in
382
+ --number) number="$2"; shift 2 ;;
383
+ --url) url="$2"; shift 2 ;;
384
+ --page) page="$2"; shift 2 ;;
385
+ --body) body="$2"; shift 2 ;;
386
+ --body-file) body_file="$2"; shift 2 ;;
387
+ --reply-to) reply_to="$2"; shift 2 ;;
388
+ --repo) REPO_NWO="$2"; shift 2 ;;
389
+ --category-id) CATEGORY_ID="$2"; shift 2 ;;
390
+ --dry-run) DRY_RUN=true; shift ;;
391
+ *) error "post: unknown option '$1'" ;;
392
+ esac
393
+ done
394
+ resolve_repo
395
+ # Resolve the target discussion number.
396
+ if [[ -n "$number" ]]; then
397
+ NUMBER="$number"
398
+ elif [[ -n "$url" ]]; then
399
+ NUMBER="${url##*/}"
400
+ elif [[ -n "$page" ]]; then
401
+ resolve_category
402
+ NUMBER="$(discussion_number_for_page "$page")"
403
+ [[ -z "$NUMBER" ]] && error "No discussion for page '$page'. Seed one first: $0 seed --page '$page' ..."
404
+ else
405
+ error "post: provide --number N, --url URL, or --page PATH."
406
+ fi
407
+
408
+ if [[ -n "$body_file" ]]; then
409
+ require_file "$body_file" "body file"
410
+ # If it's a draft scaffold, post only the REPLY section; else the whole file.
411
+ if grep -q '===== REPLY' "$body_file"; then
412
+ body="$(extract_reply_body "$body_file")"
413
+ else
414
+ body="$(cat "$body_file")"
415
+ fi
416
+ fi
417
+ # Trim leading/trailing blank lines.
418
+ body="$(printf '%s' "$body" | sed -e 's/[[:space:]]*$//')"
419
+ [[ -z "${body//[[:space:]]/}" ]] && error "post: empty body. Provide --body TEXT or --body-file FILE with content under the REPLY marker."
420
+
421
+ if [[ "$DRY_RUN" == "true" ]]; then
422
+ info "[DRY RUN] Would post to $REPO_NWO discussion #$NUMBER${reply_to:+ (reply to $reply_to)}:"
423
+ printf '%s\n' "$body" | sed 's/^/ | /'
424
+ return 0
425
+ fi
426
+
427
+ local disc_id; disc_id="$(discussion_node_id "$NUMBER")"
428
+ [[ -z "$disc_id" || "$disc_id" == "null" ]] && error "Could not resolve discussion #$NUMBER on $REPO_NWO."
429
+
430
+ if [[ -n "$reply_to" ]]; then
431
+ gh api graphql -f query='
432
+ mutation($discussionId:ID!,$body:String!,$replyToId:ID!){
433
+ addDiscussionComment(input:{discussionId:$discussionId,body:$body,replyToId:$replyToId}){
434
+ comment{ url }
435
+ }
436
+ }' -F discussionId="$disc_id" -F body="$body" -F replyToId="$reply_to" \
437
+ --jq '"Posted reply: \(.data.addDiscussionComment.comment.url)"'
438
+ else
439
+ gh api graphql -f query='
440
+ mutation($discussionId:ID!,$body:String!){
441
+ addDiscussionComment(input:{discussionId:$discussionId,body:$body}){
442
+ comment{ url }
443
+ }
444
+ }' -F discussionId="$disc_id" -F body="$body" \
445
+ --jq '"Posted comment: \(.data.addDiscussionComment.comment.url)"'
446
+ fi
447
+ success "Comment posted to discussion #$NUMBER"
448
+ }
449
+
450
+ # ---------------------------------------------------------------------------
451
+ # Usage / dispatch
452
+ # ---------------------------------------------------------------------------
453
+
454
+ show_usage() {
455
+ cat << 'EOF'
456
+ giscus-discussions — read, draft, and post the GitHub Discussions behind Giscus comments
457
+
458
+ USAGE:
459
+ ./scripts/bin/giscus-discussions <subcommand> [options]
460
+
461
+ SUBCOMMANDS:
462
+ categories List discussion categories + node IDs (setup helper)
463
+ list [--json] List discussions in the Giscus category
464
+ thread <target> [--json] Show a discussion's full conversation
465
+ draft <target> [--out F] Write a Markdown reply-draft scaffold
466
+ seed --page P --title T (--body B | --body-file F) [--dry-run]
467
+ Create a new discussion for a page
468
+ post <target> (--body B | --body-file F) [--reply-to ID] [--dry-run]
469
+ Add a comment / reply to an existing discussion
470
+
471
+ <target> is one of: --number N | --url URL | --page /path/
472
+
473
+ COMMON OPTIONS:
474
+ --repo owner/name Override repository (default: gh repo view)
475
+ --category-id ID Override Giscus category (default: _config.yml)
476
+ --dry-run Preview writes (seed/post) without calling the API
477
+
478
+ ENVIRONMENT:
479
+ GISCUS_REPO Default --repo
480
+ GISCUS_CATEGORY_ID Default --category-id
481
+
482
+ EXAMPLES:
483
+ ./scripts/bin/giscus-discussions categories
484
+ ./scripts/bin/giscus-discussions list
485
+ ./scripts/bin/giscus-discussions thread --page /posts/2025/01/21/remote-work-revolution/
486
+ ./scripts/bin/giscus-discussions draft --number 7 --out /tmp/reply.md
487
+ ./scripts/bin/giscus-discussions post --number 7 --body-file /tmp/reply.md --reply-to DC_xxx --dry-run
488
+ ./scripts/bin/giscus-discussions seed --page /posts/new/ --title "/posts/new/" --body "Discussion thread." --dry-run
489
+
490
+ Requires an authenticated GitHub CLI (`gh auth login`).
491
+ EOF
492
+ }
493
+
494
+ main() {
495
+ local sub="${1:-}"
496
+ [[ $# -gt 0 ]] && shift || true
497
+ case "$sub" in
498
+ categories) cmd_categories "$@" ;;
499
+ list) cmd_list "$@" ;;
500
+ thread) cmd_thread "$@" ;;
501
+ draft) cmd_draft "$@" ;;
502
+ seed) cmd_seed "$@" ;;
503
+ post) cmd_post "$@" ;;
504
+ -h|--help|help|"") show_usage ;;
505
+ *) error "Unknown subcommand '$sub' (try: $0 --help)" ;;
506
+ esac
507
+ }
508
+
509
+ main "$@"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-theme-zer0
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.21.0
4
+ version: 1.22.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amr Abdel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-06-26 00:00:00.000000000 Z
11
+ date: 2026-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
@@ -376,6 +376,7 @@ files:
376
376
  - scripts/analyze-commits.sh
377
377
  - scripts/bin/audit-consumer
378
378
  - scripts/bin/build
379
+ - scripts/bin/giscus-discussions
379
380
  - scripts/bin/install
380
381
  - scripts/bin/manifest
381
382
  - scripts/bin/release