open_blog 0.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.
Files changed (257) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +52 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +101 -0
  5. data/app/assets/builds/open_blog/blog.css +2 -0
  6. data/app/assets/javascripts/open_blog/controllers/code_copy_controller.js +40 -0
  7. data/app/assets/javascripts/open_blog/controllers/reading_progress_controller.js +36 -0
  8. data/app/assets/javascripts/open_blog/controllers/search_controller.js +49 -0
  9. data/app/assets/javascripts/open_blog/controllers/share_controller.js +48 -0
  10. data/app/assets/javascripts/open_blog/controllers/theme_controller.js +51 -0
  11. data/app/assets/javascripts/open_blog/controllers/toc_controller.js +33 -0
  12. data/app/controllers/concerns/open_blog/reader_controller.rb +49 -0
  13. data/app/controllers/open_blog/api/v1/adoptions_controller.rb +27 -0
  14. data/app/controllers/open_blog/api/v1/approvals_controller.rb +15 -0
  15. data/app/controllers/open_blog/api/v1/authors_controller.rb +62 -0
  16. data/app/controllers/open_blog/api/v1/base_controller.rb +100 -0
  17. data/app/controllers/open_blog/api/v1/categories_controller.rb +33 -0
  18. data/app/controllers/open_blog/api/v1/connections_controller.rb +45 -0
  19. data/app/controllers/open_blog/api/v1/doctor_controller.rb +13 -0
  20. data/app/controllers/open_blog/api/v1/faq_extractions_controller.rb +13 -0
  21. data/app/controllers/open_blog/api/v1/findings_controller.rb +13 -0
  22. data/app/controllers/open_blog/api/v1/images_controller.rb +22 -0
  23. data/app/controllers/open_blog/api/v1/pages_controller.rb +67 -0
  24. data/app/controllers/open_blog/api/v1/posts_controller.rb +114 -0
  25. data/app/controllers/open_blog/api/v1/previews_controller.rb +13 -0
  26. data/app/controllers/open_blog/api/v1/records_controller.rb +13 -0
  27. data/app/controllers/open_blog/api/v1/redirects_controller.rb +51 -0
  28. data/app/controllers/open_blog/api/v1/report_controller.rb +20 -0
  29. data/app/controllers/open_blog/api/v1/resources_controller.rb +39 -0
  30. data/app/controllers/open_blog/api/v1/series_controller.rb +32 -0
  31. data/app/controllers/open_blog/api/v1/tags_controller.rb +12 -0
  32. data/app/controllers/open_blog/api/v1/views_controller.rb +19 -0
  33. data/app/controllers/open_blog/application_controller.rb +5 -0
  34. data/app/controllers/open_blog/authors_controller.rb +14 -0
  35. data/app/controllers/open_blog/categories_controller.rb +15 -0
  36. data/app/controllers/open_blog/errors_controller.rb +7 -0
  37. data/app/controllers/open_blog/feeds_controller.rb +22 -0
  38. data/app/controllers/open_blog/mcp_controller.rb +38 -0
  39. data/app/controllers/open_blog/media_controller.rb +20 -0
  40. data/app/controllers/open_blog/pages_controller.rb +12 -0
  41. data/app/controllers/open_blog/posts_controller.rb +57 -0
  42. data/app/controllers/open_blog/previews_controller.rb +35 -0
  43. data/app/controllers/open_blog/search_controller.rb +32 -0
  44. data/app/controllers/open_blog/series_controller.rb +15 -0
  45. data/app/controllers/open_blog/sitemaps_controller.rb +10 -0
  46. data/app/controllers/open_blog/tags_controller.rb +15 -0
  47. data/app/helpers/open_blog/content_helper.rb +79 -0
  48. data/app/helpers/open_blog/dates_helper.rb +18 -0
  49. data/app/helpers/open_blog/faq_helper.rb +59 -0
  50. data/app/helpers/open_blog/head_helper.rb +75 -0
  51. data/app/helpers/open_blog/icons_helper.rb +10 -0
  52. data/app/helpers/open_blog/notices_helper.rb +47 -0
  53. data/app/helpers/open_blog/pagination_helper.rb +18 -0
  54. data/app/helpers/open_blog/structured_data_helper.rb +63 -0
  55. data/app/helpers/open_blog/theme_helper.rb +52 -0
  56. data/app/helpers/open_blog/url_helper.rb +58 -0
  57. data/app/jobs/open_blog/publish_scheduled_post_job.rb +14 -0
  58. data/app/models/concerns/open_blog/immutable.rb +13 -0
  59. data/app/models/concerns/open_blog/immutable_image_attachment.rb +43 -0
  60. data/app/models/concerns/open_blog/previewable.rb +38 -0
  61. data/app/models/open_blog/api_token.rb +34 -0
  62. data/app/models/open_blog/application_record.rb +5 -0
  63. data/app/models/open_blog/approval.rb +19 -0
  64. data/app/models/open_blog/author.rb +11 -0
  65. data/app/models/open_blog/baseline.rb +26 -0
  66. data/app/models/open_blog/category.rb +10 -0
  67. data/app/models/open_blog/connection_declaration.rb +16 -0
  68. data/app/models/open_blog/faq.rb +22 -0
  69. data/app/models/open_blog/image.rb +45 -0
  70. data/app/models/open_blog/page.rb +23 -0
  71. data/app/models/open_blog/page_view.rb +7 -0
  72. data/app/models/open_blog/post.rb +132 -0
  73. data/app/models/open_blog/publication.rb +17 -0
  74. data/app/models/open_blog/redirect.rb +16 -0
  75. data/app/models/open_blog/revision.rb +12 -0
  76. data/app/models/open_blog/series.rb +10 -0
  77. data/app/models/open_blog/tag.rb +11 -0
  78. data/app/models/open_blog/tagging.rb +7 -0
  79. data/app/queries/open_blog/api_post_query.rb +54 -0
  80. data/app/serializers/open_blog/adoption_result_serializer.rb +9 -0
  81. data/app/serializers/open_blog/author_serializer.rb +10 -0
  82. data/app/serializers/open_blog/category_serializer.rb +7 -0
  83. data/app/serializers/open_blog/doctor_serializer.rb +7 -0
  84. data/app/serializers/open_blog/error_serializer.rb +7 -0
  85. data/app/serializers/open_blog/extraction_result_serializer.rb +7 -0
  86. data/app/serializers/open_blog/findings_serializer.rb +13 -0
  87. data/app/serializers/open_blog/image_serializer.rb +9 -0
  88. data/app/serializers/open_blog/page_serializer.rb +9 -0
  89. data/app/serializers/open_blog/post_serializer.rb +59 -0
  90. data/app/serializers/open_blog/preview_serializer.rb +11 -0
  91. data/app/serializers/open_blog/records_serializer.rb +28 -0
  92. data/app/serializers/open_blog/redirect_serializer.rb +7 -0
  93. data/app/serializers/open_blog/series_serializer.rb +7 -0
  94. data/app/serializers/open_blog/tag_serializer.rb +7 -0
  95. data/app/serializers/open_blog/write_result_serializer.rb +9 -0
  96. data/app/views/open_blog/attachments/_blob.html.erb +1 -0
  97. data/app/views/open_blog/feeds/atom.xml.builder +27 -0
  98. data/app/views/open_blog/sitemaps/show.xml.builder +9 -0
  99. data/config/locales/open_blog.en.yml +95 -0
  100. data/config/routes.rb +52 -0
  101. data/db/migrate/20261003012512_create_open_blog_authors.rb +16 -0
  102. data/db/migrate/20261003012513_create_open_blog_categories.rb +13 -0
  103. data/db/migrate/20261003012514_create_open_blog_series.rb +11 -0
  104. data/db/migrate/20261003012515_create_open_blog_images.rb +17 -0
  105. data/db/migrate/20261003012516_create_open_blog_posts.rb +47 -0
  106. data/db/migrate/20261003012517_create_open_blog_faqs.rb +13 -0
  107. data/db/migrate/20261003012518_create_open_blog_tags.rb +17 -0
  108. data/db/migrate/20261003012519_create_open_blog_redirects.rb +14 -0
  109. data/db/migrate/20261003012520_create_open_blog_revisions.rb +14 -0
  110. data/db/migrate/20261003012521_create_open_blog_approvals.rb +21 -0
  111. data/db/migrate/20261003012522_create_open_blog_publications.rb +18 -0
  112. data/db/migrate/20261003012523_create_open_blog_baselines.rb +24 -0
  113. data/db/migrate/20261003012524_create_open_blog_connection_declarations.rb +13 -0
  114. data/db/migrate/20261003031410_add_body_image_manifest_to_open_blog_posts.rb +7 -0
  115. data/db/migrate/20261003164418_create_open_blog_api_tokens.rb +15 -0
  116. data/db/migrate/20261003175454_create_open_blog_pages.rb +16 -0
  117. data/db/migrate/20261003182919_create_open_blog_page_views.rb +11 -0
  118. data/lib/generators/open_blog/admin_suite/admin_suite_generator.rb +27 -0
  119. data/lib/generators/open_blog/admin_suite/templates/author_resource.rb.tt +29 -0
  120. data/lib/generators/open_blog/admin_suite/templates/blog_portal.rb.tt +16 -0
  121. data/lib/generators/open_blog/admin_suite/templates/category_resource.rb.tt +28 -0
  122. data/lib/generators/open_blog/admin_suite/templates/initializer.rb.tt +19 -0
  123. data/lib/generators/open_blog/admin_suite/templates/page_resource.rb.tt +32 -0
  124. data/lib/generators/open_blog/admin_suite/templates/post_resource.rb.tt +58 -0
  125. data/lib/generators/open_blog/generator_support.rb +64 -0
  126. data/lib/generators/open_blog/install/install_generator.rb +188 -0
  127. data/lib/generators/open_blog/install/templates/initializer.rb.tt +16 -0
  128. data/lib/generators/open_blog/install/templates/sample_cover.png +0 -0
  129. data/lib/generators/open_blog/install/templates/sample_post.md +54 -0
  130. data/lib/generators/open_blog/install/templates/theme/blog.css +193 -0
  131. data/lib/generators/open_blog/install/templates/theme/open_blog_theme.css +82 -0
  132. data/lib/generators/open_blog/install/templates/theme/syntax.css +358 -0
  133. data/lib/generators/open_blog/install/templates/theme/theme.css +120 -0
  134. data/lib/generators/open_blog/install/templates/views/layouts/open_blog.html.erb +16 -0
  135. data/lib/generators/open_blog/install/templates/views/open_blog/authors/show.html.erb +17 -0
  136. data/lib/generators/open_blog/install/templates/views/open_blog/categories/show.html.erb +13 -0
  137. data/lib/generators/open_blog/install/templates/views/open_blog/errors/not_found.html.erb +11 -0
  138. data/lib/generators/open_blog/install/templates/views/open_blog/errors/preview_expired.html.erb +5 -0
  139. data/lib/generators/open_blog/install/templates/views/open_blog/icons/_check.svg.erb +1 -0
  140. data/lib/generators/open_blog/install/templates/views/open_blog/icons/_copy.svg.erb +1 -0
  141. data/lib/generators/open_blog/install/templates/views/open_blog/icons/_link.svg.erb +1 -0
  142. data/lib/generators/open_blog/install/templates/views/open_blog/icons/_monitor.svg.erb +1 -0
  143. data/lib/generators/open_blog/install/templates/views/open_blog/icons/_moon.svg.erb +1 -0
  144. data/lib/generators/open_blog/install/templates/views/open_blog/icons/_share.svg.erb +1 -0
  145. data/lib/generators/open_blog/install/templates/views/open_blog/icons/_sun.svg.erb +1 -0
  146. data/lib/generators/open_blog/install/templates/views/open_blog/pages/show.html.erb +5 -0
  147. data/lib/generators/open_blog/install/templates/views/open_blog/posts/_faq.html.erb +1 -0
  148. data/lib/generators/open_blog/install/templates/views/open_blog/posts/_highlights.html.erb +7 -0
  149. data/lib/generators/open_blog/install/templates/views/open_blog/posts/_preview_bar.html.erb +1 -0
  150. data/lib/generators/open_blog/install/templates/views/open_blog/posts/_series_nav.html.erb +12 -0
  151. data/lib/generators/open_blog/install/templates/views/open_blog/posts/_tags.html.erb +5 -0
  152. data/lib/generators/open_blog/install/templates/views/open_blog/posts/_toc.html.erb +1 -0
  153. data/lib/generators/open_blog/install/templates/views/open_blog/posts/index.html.erb +13 -0
  154. data/lib/generators/open_blog/install/templates/views/open_blog/posts/show.html.erb +29 -0
  155. data/lib/generators/open_blog/install/templates/views/open_blog/search/show.html.erb +13 -0
  156. data/lib/generators/open_blog/install/templates/views/open_blog/series/show.html.erb +13 -0
  157. data/lib/generators/open_blog/install/templates/views/open_blog/shared/_author_box.html.erb +6 -0
  158. data/lib/generators/open_blog/install/templates/views/open_blog/shared/_breadcrumbs.html.erb +1 -0
  159. data/lib/generators/open_blog/install/templates/views/open_blog/shared/_call_to_action.html.erb +7 -0
  160. data/lib/generators/open_blog/install/templates/views/open_blog/shared/_featured_card.html.erb +11 -0
  161. data/lib/generators/open_blog/install/templates/views/open_blog/shared/_footer.html.erb +11 -0
  162. data/lib/generators/open_blog/install/templates/views/open_blog/shared/_header.html.erb +7 -0
  163. data/lib/generators/open_blog/install/templates/views/open_blog/shared/_pagination.html.erb +1 -0
  164. data/lib/generators/open_blog/install/templates/views/open_blog/shared/_post_card.html.erb +9 -0
  165. data/lib/generators/open_blog/install/templates/views/open_blog/shared/_related_posts.html.erb +10 -0
  166. data/lib/generators/open_blog/install/templates/views/open_blog/shared/_search.html.erb +9 -0
  167. data/lib/generators/open_blog/install/templates/views/open_blog/shared/_share.html.erb +13 -0
  168. data/lib/generators/open_blog/install/templates/views/open_blog/shared/_sidebar.html.erb +38 -0
  169. data/lib/generators/open_blog/install/templates/views/open_blog/shared/_theme_toggle.html.erb +10 -0
  170. data/lib/generators/open_blog/install/templates/views/open_blog/tags/show.html.erb +13 -0
  171. data/lib/generators/open_blog/views/views_generator.rb +21 -0
  172. data/lib/open_blog/actor.rb +7 -0
  173. data/lib/open_blog/admin_suite.rb +73 -0
  174. data/lib/open_blog/adopt/contract.rb +152 -0
  175. data/lib/open_blog/adopt/snapshot.rb +35 -0
  176. data/lib/open_blog/adopt.rb +159 -0
  177. data/lib/open_blog/api_fields.rb +40 -0
  178. data/lib/open_blog/approve.rb +18 -0
  179. data/lib/open_blog/authentication.rb +18 -0
  180. data/lib/open_blog/build_css.rb +53 -0
  181. data/lib/open_blog/configuration.rb +185 -0
  182. data/lib/open_blog/configuration_error.rb +4 -0
  183. data/lib/open_blog/content_guard.rb +77 -0
  184. data/lib/open_blog/doctor/files.rb +61 -0
  185. data/lib/open_blog/doctor/javascript.rb +57 -0
  186. data/lib/open_blog/doctor.rb +177 -0
  187. data/lib/open_blog/engine.rb +45 -0
  188. data/lib/open_blog/errors.rb +40 -0
  189. data/lib/open_blog/faq_extraction.rb +184 -0
  190. data/lib/open_blog/findings/body_checks.rb +58 -0
  191. data/lib/open_blog/findings/check.rb +19 -0
  192. data/lib/open_blog/findings/link_check.rb +78 -0
  193. data/lib/open_blog/findings/record_checks.rb +94 -0
  194. data/lib/open_blog/findings/registry.rb +18 -0
  195. data/lib/open_blog/findings.rb +27 -0
  196. data/lib/open_blog/image_fetch.rb +115 -0
  197. data/lib/open_blog/image_import.rb +164 -0
  198. data/lib/open_blog/image_resolution.rb +171 -0
  199. data/lib/open_blog/instructions.rb +7 -0
  200. data/lib/open_blog/json_feed.rb +36 -0
  201. data/lib/open_blog/label_policy.rb +41 -0
  202. data/lib/open_blog/markdown_view.rb +57 -0
  203. data/lib/open_blog/mcp/definition.rb +28 -0
  204. data/lib/open_blog/mcp/dispatcher.rb +33 -0
  205. data/lib/open_blog/mcp/image_input.rb +30 -0
  206. data/lib/open_blog/mcp/registry.rb +139 -0
  207. data/lib/open_blog/mcp/schemas.rb +72 -0
  208. data/lib/open_blog/mcp.rb +24 -0
  209. data/lib/open_blog/not_found.rb +4 -0
  210. data/lib/open_blog/operation.rb +36 -0
  211. data/lib/open_blog/page_views.rb +72 -0
  212. data/lib/open_blog/pagination.rb +18 -0
  213. data/lib/open_blog/plain_text.rb +36 -0
  214. data/lib/open_blog/policy_url.rb +9 -0
  215. data/lib/open_blog/post_attributes.rb +172 -0
  216. data/lib/open_blog/post_identity.rb +28 -0
  217. data/lib/open_blog/publish.rb +7 -0
  218. data/lib/open_blog/reader_dates.rb +21 -0
  219. data/lib/open_blog/reader_page.rb +21 -0
  220. data/lib/open_blog/reader_queries.rb +90 -0
  221. data/lib/open_blog/record_release.rb +66 -0
  222. data/lib/open_blog/redirect_target.rb +58 -0
  223. data/lib/open_blog/remove.rb +43 -0
  224. data/lib/open_blog/renderer/highlighter.rb +44 -0
  225. data/lib/open_blog/renderer/markdown.rb +14 -0
  226. data/lib/open_blog/renderer/rich_text.rb +19 -0
  227. data/lib/open_blog/renderer/sanitizer.rb +72 -0
  228. data/lib/open_blog/renderer/scrubber.rb +35 -0
  229. data/lib/open_blog/renderer/transform.rb +115 -0
  230. data/lib/open_blog/renderer.rb +51 -0
  231. data/lib/open_blog/result.rb +11 -0
  232. data/lib/open_blog/revision_payload.rb +67 -0
  233. data/lib/open_blog/rich_text_guard.rb +26 -0
  234. data/lib/open_blog/sample.rb +56 -0
  235. data/lib/open_blog/save_draft.rb +7 -0
  236. data/lib/open_blog/search.rb +21 -0
  237. data/lib/open_blog/sitemap_entries.rb +66 -0
  238. data/lib/open_blog/surface_report/expected_content.rb +27 -0
  239. data/lib/open_blog/surface_report/http.rb +92 -0
  240. data/lib/open_blog/surface_report/page_checks.rb +303 -0
  241. data/lib/open_blog/surface_report/reach_checks.rb +141 -0
  242. data/lib/open_blog/surface_report/record_checks.rb +248 -0
  243. data/lib/open_blog/surface_report/robots.rb +49 -0
  244. data/lib/open_blog/surface_report.rb +223 -0
  245. data/lib/open_blog/syntax_css.rb +55 -0
  246. data/lib/open_blog/unpublish.rb +13 -0
  247. data/lib/open_blog/version.rb +3 -0
  248. data/lib/open_blog/write_post.rb +205 -0
  249. data/lib/open_blog.rb +91 -0
  250. data/lib/tasks/open_blog.rake +71 -0
  251. data/skills/open-blog-adopt/SKILL.md +12 -0
  252. data/skills/open-blog-install/SKILL.md +10 -0
  253. data/skills/open-blog-policy-pages/SKILL.md +10 -0
  254. data/skills/open-blog-publish/SKILL.md +14 -0
  255. data/skills/open-blog-report/SKILL.md +10 -0
  256. data/skills/open-blog-update/SKILL.md +16 -0
  257. metadata +515 -0
@@ -0,0 +1,358 @@
1
+ .ob-highlight table td { padding: 5px; }
2
+ .ob-highlight table pre { margin: 0; }
3
+ .ob-highlight, .ob-highlight .w {
4
+ color: #24292f;
5
+ background-color: #f6f8fa;
6
+ }
7
+ .ob-highlight .k, .ob-highlight .kd, .ob-highlight .kn, .ob-highlight .kp, .ob-highlight .kr, .ob-highlight .kt, .ob-highlight .kv {
8
+ color: #cf222e;
9
+ }
10
+ .ob-highlight .gr {
11
+ color: #f6f8fa;
12
+ }
13
+ .ob-highlight .gd {
14
+ color: #82071e;
15
+ background-color: #ffebe9;
16
+ }
17
+ .ob-highlight .nb {
18
+ color: #953800;
19
+ }
20
+ .ob-highlight .nc {
21
+ color: #953800;
22
+ }
23
+ .ob-highlight .no {
24
+ color: #953800;
25
+ }
26
+ .ob-highlight .nn {
27
+ color: #953800;
28
+ }
29
+ .ob-highlight .sr {
30
+ color: #116329;
31
+ }
32
+ .ob-highlight .na {
33
+ color: #116329;
34
+ }
35
+ .ob-highlight .nt {
36
+ color: #116329;
37
+ }
38
+ .ob-highlight .gi {
39
+ color: #116329;
40
+ background-color: #dafbe1;
41
+ }
42
+ .ob-highlight .ges {
43
+ font-weight: bold;
44
+ font-style: italic;
45
+ }
46
+ .ob-highlight .kc {
47
+ color: #0550ae;
48
+ }
49
+ .ob-highlight .l, .ob-highlight .ld, .ob-highlight .m, .ob-highlight .mb, .ob-highlight .mf, .ob-highlight .mh, .ob-highlight .mi, .ob-highlight .il, .ob-highlight .mo, .ob-highlight .mx {
50
+ color: #0550ae;
51
+ }
52
+ .ob-highlight .sb {
53
+ color: #0550ae;
54
+ }
55
+ .ob-highlight .bp {
56
+ color: #0550ae;
57
+ }
58
+ .ob-highlight .ne {
59
+ color: #0550ae;
60
+ }
61
+ .ob-highlight .nl {
62
+ color: #0550ae;
63
+ }
64
+ .ob-highlight .py {
65
+ color: #0550ae;
66
+ }
67
+ .ob-highlight .nv, .ob-highlight .vc, .ob-highlight .vg, .ob-highlight .vi, .ob-highlight .vm {
68
+ color: #0550ae;
69
+ }
70
+ .ob-highlight .o, .ob-highlight .ow {
71
+ color: #0550ae;
72
+ }
73
+ .ob-highlight .gh {
74
+ color: #0550ae;
75
+ font-weight: bold;
76
+ }
77
+ .ob-highlight .gu {
78
+ color: #0550ae;
79
+ font-weight: bold;
80
+ }
81
+ .ob-highlight .s, .ob-highlight .sa, .ob-highlight .sc, .ob-highlight .dl, .ob-highlight .sd, .ob-highlight .s2, .ob-highlight .se, .ob-highlight .sh, .ob-highlight .sx, .ob-highlight .s1, .ob-highlight .ss {
82
+ color: #0a3069;
83
+ }
84
+ .ob-highlight .nd {
85
+ color: #8250df;
86
+ }
87
+ .ob-highlight .nf, .ob-highlight .fm {
88
+ color: #8250df;
89
+ }
90
+ .ob-highlight .err {
91
+ color: #f6f8fa;
92
+ background-color: #82071e;
93
+ }
94
+ .ob-highlight .c, .ob-highlight .ch, .ob-highlight .cd, .ob-highlight .cm, .ob-highlight .cp, .ob-highlight .cpf, .ob-highlight .c1, .ob-highlight .cs {
95
+ color: #6e7781;
96
+ }
97
+ .ob-highlight .gl {
98
+ color: #6e7781;
99
+ }
100
+ .ob-highlight .gt {
101
+ color: #6e7781;
102
+ }
103
+ .ob-highlight .ni {
104
+ color: #24292f;
105
+ }
106
+ .ob-highlight .si {
107
+ color: #24292f;
108
+ }
109
+ .ob-highlight .ge {
110
+ color: #24292f;
111
+ font-style: italic;
112
+ }
113
+ .ob-highlight .gs {
114
+ color: #24292f;
115
+ font-weight: bold;
116
+ }
117
+
118
+ [data-theme="dark"] .ob-highlight table td { padding: 5px; }
119
+ [data-theme="dark"] .ob-highlight table pre { margin: 0; }
120
+ [data-theme="dark"] .ob-highlight, [data-theme="dark"] .ob-highlight .w {
121
+ color: #c9d1d9;
122
+ background-color: #161b22;
123
+ }
124
+ [data-theme="dark"] .ob-highlight .k, [data-theme="dark"] .ob-highlight .kd, [data-theme="dark"] .ob-highlight .kn, [data-theme="dark"] .ob-highlight .kp, [data-theme="dark"] .ob-highlight .kr, [data-theme="dark"] .ob-highlight .kt, [data-theme="dark"] .ob-highlight .kv {
125
+ color: #ff7b72;
126
+ }
127
+ [data-theme="dark"] .ob-highlight .gr {
128
+ color: #f0f6fc;
129
+ }
130
+ [data-theme="dark"] .ob-highlight .gd {
131
+ color: #ffdcd7;
132
+ background-color: #67060c;
133
+ }
134
+ [data-theme="dark"] .ob-highlight .nb {
135
+ color: #ffa657;
136
+ }
137
+ [data-theme="dark"] .ob-highlight .nc {
138
+ color: #ffa657;
139
+ }
140
+ [data-theme="dark"] .ob-highlight .no {
141
+ color: #ffa657;
142
+ }
143
+ [data-theme="dark"] .ob-highlight .nn {
144
+ color: #ffa657;
145
+ }
146
+ [data-theme="dark"] .ob-highlight .sr {
147
+ color: #7ee787;
148
+ }
149
+ [data-theme="dark"] .ob-highlight .na {
150
+ color: #7ee787;
151
+ }
152
+ [data-theme="dark"] .ob-highlight .nt {
153
+ color: #7ee787;
154
+ }
155
+ [data-theme="dark"] .ob-highlight .gi {
156
+ color: #aff5b4;
157
+ background-color: #033a16;
158
+ }
159
+ [data-theme="dark"] .ob-highlight .ges {
160
+ font-weight: bold;
161
+ font-style: italic;
162
+ }
163
+ [data-theme="dark"] .ob-highlight .kc {
164
+ color: #79c0ff;
165
+ }
166
+ [data-theme="dark"] .ob-highlight .l, [data-theme="dark"] .ob-highlight .ld, [data-theme="dark"] .ob-highlight .m, [data-theme="dark"] .ob-highlight .mb, [data-theme="dark"] .ob-highlight .mf, [data-theme="dark"] .ob-highlight .mh, [data-theme="dark"] .ob-highlight .mi, [data-theme="dark"] .ob-highlight .il, [data-theme="dark"] .ob-highlight .mo, [data-theme="dark"] .ob-highlight .mx {
167
+ color: #79c0ff;
168
+ }
169
+ [data-theme="dark"] .ob-highlight .sb {
170
+ color: #79c0ff;
171
+ }
172
+ [data-theme="dark"] .ob-highlight .bp {
173
+ color: #79c0ff;
174
+ }
175
+ [data-theme="dark"] .ob-highlight .ne {
176
+ color: #79c0ff;
177
+ }
178
+ [data-theme="dark"] .ob-highlight .nl {
179
+ color: #79c0ff;
180
+ }
181
+ [data-theme="dark"] .ob-highlight .py {
182
+ color: #79c0ff;
183
+ }
184
+ [data-theme="dark"] .ob-highlight .nv, [data-theme="dark"] .ob-highlight .vc, [data-theme="dark"] .ob-highlight .vg, [data-theme="dark"] .ob-highlight .vi, [data-theme="dark"] .ob-highlight .vm {
185
+ color: #79c0ff;
186
+ }
187
+ [data-theme="dark"] .ob-highlight .o, [data-theme="dark"] .ob-highlight .ow {
188
+ color: #79c0ff;
189
+ }
190
+ [data-theme="dark"] .ob-highlight .gh {
191
+ color: #1f6feb;
192
+ font-weight: bold;
193
+ }
194
+ [data-theme="dark"] .ob-highlight .gu {
195
+ color: #1f6feb;
196
+ font-weight: bold;
197
+ }
198
+ [data-theme="dark"] .ob-highlight .s, [data-theme="dark"] .ob-highlight .sa, [data-theme="dark"] .ob-highlight .sc, [data-theme="dark"] .ob-highlight .dl, [data-theme="dark"] .ob-highlight .sd, [data-theme="dark"] .ob-highlight .s2, [data-theme="dark"] .ob-highlight .se, [data-theme="dark"] .ob-highlight .sh, [data-theme="dark"] .ob-highlight .sx, [data-theme="dark"] .ob-highlight .s1, [data-theme="dark"] .ob-highlight .ss {
199
+ color: #a5d6ff;
200
+ }
201
+ [data-theme="dark"] .ob-highlight .nd {
202
+ color: #d2a8ff;
203
+ }
204
+ [data-theme="dark"] .ob-highlight .nf, [data-theme="dark"] .ob-highlight .fm {
205
+ color: #d2a8ff;
206
+ }
207
+ [data-theme="dark"] .ob-highlight .err {
208
+ color: #f0f6fc;
209
+ background-color: #8e1519;
210
+ }
211
+ [data-theme="dark"] .ob-highlight .c, [data-theme="dark"] .ob-highlight .ch, [data-theme="dark"] .ob-highlight .cd, [data-theme="dark"] .ob-highlight .cm, [data-theme="dark"] .ob-highlight .cp, [data-theme="dark"] .ob-highlight .cpf, [data-theme="dark"] .ob-highlight .c1, [data-theme="dark"] .ob-highlight .cs {
212
+ color: #8b949e;
213
+ }
214
+ [data-theme="dark"] .ob-highlight .gl {
215
+ color: #8b949e;
216
+ }
217
+ [data-theme="dark"] .ob-highlight .gt {
218
+ color: #8b949e;
219
+ }
220
+ [data-theme="dark"] .ob-highlight .ni {
221
+ color: #c9d1d9;
222
+ }
223
+ [data-theme="dark"] .ob-highlight .si {
224
+ color: #c9d1d9;
225
+ }
226
+ [data-theme="dark"] .ob-highlight .ge {
227
+ color: #c9d1d9;
228
+ font-style: italic;
229
+ }
230
+ [data-theme="dark"] .ob-highlight .gs {
231
+ color: #c9d1d9;
232
+ font-weight: bold;
233
+ }
234
+
235
+ @media (prefers-color-scheme: dark) {
236
+ html:not([data-theme="light"]) .ob-highlight table td { padding: 5px; }
237
+ html:not([data-theme="light"]) .ob-highlight table pre { margin: 0; }
238
+ html:not([data-theme="light"]) .ob-highlight, html:not([data-theme="light"]) .ob-highlight .w {
239
+ color: #c9d1d9;
240
+ background-color: #161b22;
241
+ }
242
+ html:not([data-theme="light"]) .ob-highlight .k, html:not([data-theme="light"]) .ob-highlight .kd, html:not([data-theme="light"]) .ob-highlight .kn, html:not([data-theme="light"]) .ob-highlight .kp, html:not([data-theme="light"]) .ob-highlight .kr, html:not([data-theme="light"]) .ob-highlight .kt, html:not([data-theme="light"]) .ob-highlight .kv {
243
+ color: #ff7b72;
244
+ }
245
+ html:not([data-theme="light"]) .ob-highlight .gr {
246
+ color: #f0f6fc;
247
+ }
248
+ html:not([data-theme="light"]) .ob-highlight .gd {
249
+ color: #ffdcd7;
250
+ background-color: #67060c;
251
+ }
252
+ html:not([data-theme="light"]) .ob-highlight .nb {
253
+ color: #ffa657;
254
+ }
255
+ html:not([data-theme="light"]) .ob-highlight .nc {
256
+ color: #ffa657;
257
+ }
258
+ html:not([data-theme="light"]) .ob-highlight .no {
259
+ color: #ffa657;
260
+ }
261
+ html:not([data-theme="light"]) .ob-highlight .nn {
262
+ color: #ffa657;
263
+ }
264
+ html:not([data-theme="light"]) .ob-highlight .sr {
265
+ color: #7ee787;
266
+ }
267
+ html:not([data-theme="light"]) .ob-highlight .na {
268
+ color: #7ee787;
269
+ }
270
+ html:not([data-theme="light"]) .ob-highlight .nt {
271
+ color: #7ee787;
272
+ }
273
+ html:not([data-theme="light"]) .ob-highlight .gi {
274
+ color: #aff5b4;
275
+ background-color: #033a16;
276
+ }
277
+ html:not([data-theme="light"]) .ob-highlight .ges {
278
+ font-weight: bold;
279
+ font-style: italic;
280
+ }
281
+ html:not([data-theme="light"]) .ob-highlight .kc {
282
+ color: #79c0ff;
283
+ }
284
+ html:not([data-theme="light"]) .ob-highlight .l, html:not([data-theme="light"]) .ob-highlight .ld, html:not([data-theme="light"]) .ob-highlight .m, html:not([data-theme="light"]) .ob-highlight .mb, html:not([data-theme="light"]) .ob-highlight .mf, html:not([data-theme="light"]) .ob-highlight .mh, html:not([data-theme="light"]) .ob-highlight .mi, html:not([data-theme="light"]) .ob-highlight .il, html:not([data-theme="light"]) .ob-highlight .mo, html:not([data-theme="light"]) .ob-highlight .mx {
285
+ color: #79c0ff;
286
+ }
287
+ html:not([data-theme="light"]) .ob-highlight .sb {
288
+ color: #79c0ff;
289
+ }
290
+ html:not([data-theme="light"]) .ob-highlight .bp {
291
+ color: #79c0ff;
292
+ }
293
+ html:not([data-theme="light"]) .ob-highlight .ne {
294
+ color: #79c0ff;
295
+ }
296
+ html:not([data-theme="light"]) .ob-highlight .nl {
297
+ color: #79c0ff;
298
+ }
299
+ html:not([data-theme="light"]) .ob-highlight .py {
300
+ color: #79c0ff;
301
+ }
302
+ html:not([data-theme="light"]) .ob-highlight .nv, html:not([data-theme="light"]) .ob-highlight .vc, html:not([data-theme="light"]) .ob-highlight .vg, html:not([data-theme="light"]) .ob-highlight .vi, html:not([data-theme="light"]) .ob-highlight .vm {
303
+ color: #79c0ff;
304
+ }
305
+ html:not([data-theme="light"]) .ob-highlight .o, html:not([data-theme="light"]) .ob-highlight .ow {
306
+ color: #79c0ff;
307
+ }
308
+ html:not([data-theme="light"]) .ob-highlight .gh {
309
+ color: #1f6feb;
310
+ font-weight: bold;
311
+ }
312
+ html:not([data-theme="light"]) .ob-highlight .gu {
313
+ color: #1f6feb;
314
+ font-weight: bold;
315
+ }
316
+ html:not([data-theme="light"]) .ob-highlight .s, html:not([data-theme="light"]) .ob-highlight .sa, html:not([data-theme="light"]) .ob-highlight .sc, html:not([data-theme="light"]) .ob-highlight .dl, html:not([data-theme="light"]) .ob-highlight .sd, html:not([data-theme="light"]) .ob-highlight .s2, html:not([data-theme="light"]) .ob-highlight .se, html:not([data-theme="light"]) .ob-highlight .sh, html:not([data-theme="light"]) .ob-highlight .sx, html:not([data-theme="light"]) .ob-highlight .s1, html:not([data-theme="light"]) .ob-highlight .ss {
317
+ color: #a5d6ff;
318
+ }
319
+ html:not([data-theme="light"]) .ob-highlight .nd {
320
+ color: #d2a8ff;
321
+ }
322
+ html:not([data-theme="light"]) .ob-highlight .nf, html:not([data-theme="light"]) .ob-highlight .fm {
323
+ color: #d2a8ff;
324
+ }
325
+ html:not([data-theme="light"]) .ob-highlight .err {
326
+ color: #f0f6fc;
327
+ background-color: #8e1519;
328
+ }
329
+ html:not([data-theme="light"]) .ob-highlight .c, html:not([data-theme="light"]) .ob-highlight .ch, html:not([data-theme="light"]) .ob-highlight .cd, html:not([data-theme="light"]) .ob-highlight .cm, html:not([data-theme="light"]) .ob-highlight .cp, html:not([data-theme="light"]) .ob-highlight .cpf, html:not([data-theme="light"]) .ob-highlight .c1, html:not([data-theme="light"]) .ob-highlight .cs {
330
+ color: #8b949e;
331
+ }
332
+ html:not([data-theme="light"]) .ob-highlight .gl {
333
+ color: #8b949e;
334
+ }
335
+ html:not([data-theme="light"]) .ob-highlight .gt {
336
+ color: #8b949e;
337
+ }
338
+ html:not([data-theme="light"]) .ob-highlight .ni {
339
+ color: #c9d1d9;
340
+ }
341
+ html:not([data-theme="light"]) .ob-highlight .si {
342
+ color: #c9d1d9;
343
+ }
344
+ html:not([data-theme="light"]) .ob-highlight .ge {
345
+ color: #c9d1d9;
346
+ font-style: italic;
347
+ }
348
+ html:not([data-theme="light"]) .ob-highlight .gs {
349
+ color: #c9d1d9;
350
+ font-weight: bold;
351
+ }
352
+ }
353
+ .ob-highlight .gr { color: #cf222e; }
354
+ .ob-highlight .c, .ob-highlight .ch, .ob-highlight .cd, .ob-highlight .cm, .ob-highlight .cp, .ob-highlight .cpf, .ob-highlight .c1, .ob-highlight .cs, .ob-highlight .gl, .ob-highlight .gt { color: #57606a; }
355
+ [data-theme="dark"] .ob-highlight .gh, [data-theme="dark"] .ob-highlight .gu { color: #79c0ff; }
356
+ @media (prefers-color-scheme: dark) {
357
+ html:not([data-theme="light"]) .ob-highlight .gh, html:not([data-theme="light"]) .ob-highlight .gu { color: #79c0ff; }
358
+ }
@@ -0,0 +1,120 @@
1
+ @import "./blog.css";
2
+ @import "./syntax.css";
3
+ @source "../../../views/open_blog";
4
+ @source "../../../views/layouts/open_blog.html.erb";
5
+
6
+ /* open-blog:tokens:start */
7
+ :root {
8
+ --ob-surface: #ffffff;
9
+ --ob-surface-raised: #f8fafc;
10
+ --ob-surface-sunken: #f1f5f9;
11
+ --ob-heading: #0f172a;
12
+ --ob-text: #334155;
13
+ --ob-text-muted: #475569;
14
+ --ob-text-subtle: #526176;
15
+ --ob-border: #cbd5e1;
16
+ --ob-border-strong: #64748b;
17
+ --ob-accent: #1d4ed8;
18
+ --ob-accent-hover: #1e40af;
19
+ --ob-accent-soft: #dbeafe;
20
+ --ob-accent-contrast: #ffffff;
21
+ --ob-code-bg: #f6f8fa;
22
+ --ob-code-border: #94a3b8;
23
+ --ob-notice-bg: #eff6ff;
24
+ --ob-notice-border: #60a5fa;
25
+ --ob-notice-text: #1e3a8a;
26
+ --ob-note: #1d4ed8;
27
+ --ob-tip: #166534;
28
+ --ob-warning: #854d0e;
29
+ --ob-shadow: 0 8px 24px #0f172a1a;
30
+ --ob-font-display: ui-sans-serif, system-ui, sans-serif;
31
+ --ob-font-body: ui-sans-serif, system-ui, sans-serif;
32
+ --ob-font-mono: ui-monospace, SFMono-Regular, Consolas, monospace;
33
+ --ob-radius-card: 1rem;
34
+ --ob-radius-media: 0.75rem;
35
+ --ob-radius-pill: 999px;
36
+ --ob-prose-size: 1.125rem;
37
+ --ob-prose-leading: 1.8;
38
+ --ob-content-width: 56rem;
39
+ --ob-page-width: 72rem;
40
+ }
41
+ :root[data-theme="dark"] {
42
+ --ob-surface: #0f172a;
43
+ --ob-surface-raised: #1e293b;
44
+ --ob-surface-sunken: #020617;
45
+ --ob-heading: #f8fafc;
46
+ --ob-text: #e2e8f0;
47
+ --ob-text-muted: #cbd5e1;
48
+ --ob-text-subtle: #94a3b8;
49
+ --ob-border: #475569;
50
+ --ob-border-strong: #94a3b8;
51
+ --ob-accent: #93c5fd;
52
+ --ob-accent-hover: #bfdbfe;
53
+ --ob-accent-soft: #172554;
54
+ --ob-accent-contrast: #0f172a;
55
+ --ob-code-bg: #161b22;
56
+ --ob-code-border: #64748b;
57
+ --ob-notice-bg: #172554;
58
+ --ob-notice-border: #60a5fa;
59
+ --ob-notice-text: #dbeafe;
60
+ --ob-note: #93c5fd;
61
+ --ob-tip: #86efac;
62
+ --ob-warning: #fde047;
63
+ }
64
+ @media (prefers-color-scheme: dark) {
65
+ :root:not([data-theme="light"]) {
66
+ --ob-surface: #0f172a;
67
+ --ob-surface-raised: #1e293b;
68
+ --ob-surface-sunken: #020617;
69
+ --ob-heading: #f8fafc;
70
+ --ob-text: #e2e8f0;
71
+ --ob-text-muted: #cbd5e1;
72
+ --ob-text-subtle: #94a3b8;
73
+ --ob-border: #475569;
74
+ --ob-border-strong: #94a3b8;
75
+ --ob-accent: #93c5fd;
76
+ --ob-accent-hover: #bfdbfe;
77
+ --ob-accent-soft: #172554;
78
+ --ob-accent-contrast: #0f172a;
79
+ --ob-code-bg: #161b22;
80
+ --ob-code-border: #64748b;
81
+ --ob-notice-bg: #172554;
82
+ --ob-notice-border: #60a5fa;
83
+ --ob-notice-text: #dbeafe;
84
+ --ob-note: #93c5fd;
85
+ --ob-tip: #86efac;
86
+ --ob-warning: #fde047;
87
+ }
88
+ }
89
+ /* open-blog:tokens:end */
90
+
91
+ :root { color-scheme: light dark; }
92
+ :root[data-theme="light"] { color-scheme: light; }
93
+ :root[data-theme="dark"] { color-scheme: dark; }
94
+
95
+ @theme inline {
96
+ --color-ob-surface: var(--ob-surface);
97
+ --color-ob-surface-raised: var(--ob-surface-raised);
98
+ --color-ob-surface-sunken: var(--ob-surface-sunken);
99
+ --color-ob-heading: var(--ob-heading);
100
+ --color-ob-text: var(--ob-text);
101
+ --color-ob-text-muted: var(--ob-text-muted);
102
+ --color-ob-text-subtle: var(--ob-text-subtle);
103
+ --color-ob-border: var(--ob-border);
104
+ --color-ob-border-strong: var(--ob-border-strong);
105
+ --color-ob-accent: var(--ob-accent);
106
+ --color-ob-accent-hover: var(--ob-accent-hover);
107
+ --color-ob-accent-soft: var(--ob-accent-soft);
108
+ --color-ob-accent-contrast: var(--ob-accent-contrast);
109
+ --color-ob-code-bg: var(--ob-code-bg);
110
+ --color-ob-code-border: var(--ob-code-border);
111
+ --color-ob-notice-bg: var(--ob-notice-bg);
112
+ --color-ob-notice-border: var(--ob-notice-border);
113
+ --color-ob-notice-text: var(--ob-notice-text);
114
+ --color-ob-note: var(--ob-note);
115
+ --color-ob-tip: var(--ob-tip);
116
+ --color-ob-warning: var(--ob-warning);
117
+ --font-ob-display: var(--ob-font-display);
118
+ --font-ob-body: var(--ob-font-body);
119
+ --font-ob-mono: var(--ob-font-mono);
120
+ }
@@ -0,0 +1,16 @@
1
+ <!DOCTYPE html>
2
+ <%= tag.html(lang: open_blog_lang, **open_blog_theme_attributes) do %>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <%= open_blog_head(@open_blog_page) %>
6
+ <%= open_blog_theme_script %>
7
+ <%= open_blog_stylesheets %>
8
+ <%= javascript_importmap_tags %>
9
+ <%= open_blog_structured_data(@open_blog_page) %>
10
+ </head>
11
+ <body class="ob-page">
12
+ <%= render "open_blog/shared/header" %>
13
+ <main id="open-blog-main" class="ob-main"><%= yield %></main>
14
+ <%= render "open_blog/shared/footer" %>
15
+ </body>
16
+ <% end %>
@@ -0,0 +1,17 @@
1
+ <% author = @open_blog_page.record %>
2
+ <%= render "open_blog/shared/breadcrumbs" %>
3
+ <header class="ob-author-heading">
4
+ <%= open_blog_avatar(author) %>
5
+ <h1><%= author.name %></h1>
6
+ <% if author.bio.present? %><p class="ob-author-bio"><%= author.bio %></p><% end %>
7
+ <% if author.profile_urls.any? %>
8
+ <ul class="ob-author-profiles">
9
+ <% author.profile_urls.each do |url| %>
10
+ <% if OpenBlog::Renderer::Sanitizer.safe_url?(url) %><li><%= link_to url, url, rel: "me noopener" %></li><% end %>
11
+ <% end %>
12
+ </ul>
13
+ <% end %>
14
+ </header>
15
+ <% if @posts.empty? %><p class="ob-empty"><%= open_blog_translate("lists.empty") %></p><% end %>
16
+ <div class="ob-post-grid"><%= render partial: "open_blog/shared/post_card", collection: @posts, as: :post %></div>
17
+ <%= render "open_blog/shared/pagination" %>
@@ -0,0 +1,13 @@
1
+ <%= render "open_blog/shared/breadcrumbs" %>
2
+ <header class="ob-list-heading">
3
+ <h1><%= @open_blog_page.record.name %></h1>
4
+ <p class="ob-list-description"><%= open_blog_page_description(@open_blog_page) %></p>
5
+ </header>
6
+ <div class="ob-list-layout">
7
+ <%= render "open_blog/shared/sidebar" %>
8
+ <div class="ob-list-main">
9
+ <% if @posts.empty? %><p class="ob-empty"><%= open_blog_translate("lists.empty") %></p><% end %>
10
+ <div class="ob-post-grid"><%= render partial: "open_blog/shared/post_card", collection: @posts, as: :post %></div>
11
+ <%= render "open_blog/shared/pagination" %>
12
+ </div>
13
+ </div>
@@ -0,0 +1,11 @@
1
+ <header class="ob-error-heading">
2
+ <h1><%= open_blog_translate("titles.#{@open_blog_page.kind}") %></h1>
3
+ <p><%= open_blog_translate("errors.#{@open_blog_page.kind}") %></p>
4
+ <%= link_to open_blog_translate("navigation.all_posts"), open_blog_index_path %>
5
+ </header>
6
+ <% if @posts.any? %>
7
+ <section class="ob-recent-posts" aria-labelledby="ob-recent-heading">
8
+ <h2 id="ob-recent-heading"><%= open_blog_translate("headings.recent") %></h2>
9
+ <div class="ob-post-grid"><%= render partial: "open_blog/shared/post_card", collection: @posts, as: :post, locals: { heading: :h3 } %></div>
10
+ </section>
11
+ <% end %>
@@ -0,0 +1,5 @@
1
+ <header class="ob-error-heading">
2
+ <h1><%= open_blog_translate("titles.preview_expired") %></h1>
3
+ <p><%= open_blog_translate("preview.stopped") %></p>
4
+ <%= link_to open_blog_translate("navigation.all_posts"), open_blog_index_path %>
5
+ </header>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="ob-icon"><path d="m4 12 5 5L20 6"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="ob-icon"><rect x="8" y="8" width="13" height="13" rx="2"/><path d="M16 5V3H3v13h2"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="ob-icon"><path d="m9 15 6-6M8 16l-1 1a4 4 0 0 1-6-6l4-4a4 4 0 0 1 6 0m2 10a4 4 0 0 0 6 0l4-4a4 4 0 0 0-6-6l-1 1" transform="translate(1 0) scale(.9 1)"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="ob-icon"><rect x="3" y="4" width="18" height="13" rx="2"/><path d="M8 21h8m-4-4v4"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="ob-icon"><path d="M20 15a8 8 0 0 1-11-11A9 9 0 1 0 20 15Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="ob-icon"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><path d="m9 10 6-4m-6 8 6 4"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="ob-icon"><circle cx="12" cy="12" r="4"/><path d="M12 2v2m0 16v2M2 12h2m16 0h2M5 5l1.5 1.5m11 11L19 19M5 19l1.5-1.5m11-11L19 5"/></svg>
@@ -0,0 +1,5 @@
1
+ <%= render "open_blog/shared/breadcrumbs" %>
2
+ <article class="ob-post">
3
+ <h1 class="ob-title"><%= @page.title %></h1>
4
+ <div class="ob-prose"><%= OpenBlog::Renderer.render_string(@page.body_markdown, format: :markdown) %></div>
5
+ </article>
@@ -0,0 +1,7 @@
1
+ <section class="ob-highlights" aria-labelledby="ob-highlights-heading">
2
+ <h2 id="ob-highlights-heading"><%= open_blog_translate("headings.highlights") %></h2>
3
+ <ul>
4
+ <li><%= open_blog_reading_time(post) %></li>
5
+ <% if OpenBlog::ReaderDates.published_at(post) || OpenBlog::ReaderDates.modified_at(post) %><li><%= open_blog_dates(post) %></li><% end %>
6
+ </ul>
7
+ </section>
@@ -0,0 +1 @@
1
+ <div class="ob-notice" data-open-blog-preview><%= open_blog_translate("preview.heading") %></div>
@@ -0,0 +1,12 @@
1
+ <% if post.series %>
2
+ <% neighbors = OpenBlog::ReaderQueries.series_neighbors(post) %>
3
+ <nav class="ob-series-nav" aria-label="<%= open_blog_translate("navigation.series") %>">
4
+ <h2><%= link_to post.series.name, open_blog_list_path(:series, post.series) %></h2>
5
+ <% if neighbors[:previous] %>
6
+ <p><%= link_to "#{open_blog_translate('navigation.previous_post')}: #{neighbors[:previous].title}", neighbors[:previous].path, rel: "prev" %></p>
7
+ <% end %>
8
+ <% if neighbors[:next] %>
9
+ <p><%= link_to "#{open_blog_translate('navigation.next_post')}: #{neighbors[:next].title}", neighbors[:next].path, rel: "next" %></p>
10
+ <% end %>
11
+ </nav>
12
+ <% end %>
@@ -0,0 +1,5 @@
1
+ <% if post.tags.any? %>
2
+ <nav class="ob-tags" aria-label="<%= open_blog_translate("navigation.tags") %>">
3
+ <ul><% post.tags.each do |tag| %><li><%= link_to tag.name, open_blog_list_path(:tag, tag) %></li><% end %></ul>
4
+ </nav>
5
+ <% end %>
@@ -0,0 +1,13 @@
1
+ <header class="ob-index-heading">
2
+ <h1><%= OpenBlog.config.blog_title %></h1>
3
+ <% if OpenBlog.config.blog_tagline.present? %><p class="ob-tagline"><%= OpenBlog.config.blog_tagline %></p><% end %>
4
+ </header>
5
+ <div class="ob-list-layout">
6
+ <%= render "open_blog/shared/sidebar" %>
7
+ <div class="ob-list-main">
8
+ <% if @featured %><%= render "open_blog/shared/featured_card", post: @featured %><% end %>
9
+ <% if @posts.empty? && !@featured %><p class="ob-empty"><%= open_blog_translate("lists.empty") %></p><% end %>
10
+ <div class="ob-post-grid"><%= render partial: "open_blog/shared/post_card", collection: @posts, as: :post %></div>
11
+ <%= render "open_blog/shared/pagination" %>
12
+ </div>
13
+ </div>
@@ -0,0 +1,29 @@
1
+ <% post = @open_blog_page.record %>
2
+ <%= render "open_blog/posts/preview_bar" if @open_blog_page.kind == :preview %>
3
+ <div class="ob-reading-progress" hidden aria-hidden="true" data-controller="open-blog--reading-progress">
4
+ <div class="ob-reading-progress-fill" data-open-blog--reading-progress-target="progress"></div>
5
+ </div>
6
+ <%= render "open_blog/shared/breadcrumbs" %>
7
+ <div class="ob-post">
8
+ <% if post.category %><%= link_to post.category.name, open_blog_list_path(:category, post.category), class: "ob-post-category" %><% end %>
9
+ <%= open_blog_post_content(post) do %>
10
+ <%= open_blog_title(post) %>
11
+ <% if post.description.present? %><p class="ob-lede"><%= post.description %></p><% end %>
12
+ <%= open_blog_notices(post) %>
13
+ <%= render "open_blog/posts/highlights", post: post %>
14
+ <%= open_blog_byline(post) %>
15
+ <%= open_blog_cover(post) %>
16
+ <%= render "open_blog/posts/toc", post: post %>
17
+ <%= open_blog_disclosure(post) %>
18
+ <%= open_blog_body(post) %>
19
+ <%= open_blog_corrections(post) %>
20
+ <%= render "open_blog/posts/faq", post: post %>
21
+ <% end %>
22
+ <%= render "open_blog/posts/tags", post: post %>
23
+ <%= render "open_blog/shared/share", post: post %>
24
+ <%= open_blog_responsible_party_link %>
25
+ <%= render "open_blog/shared/author_box", post: post %>
26
+ <%= render "open_blog/posts/series_nav", post: post %>
27
+ <%= render "open_blog/shared/call_to_action" %>
28
+ <%= render "open_blog/shared/related_posts" %>
29
+ </div>