abqari 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +889 -0
- data/LICENSE +21 -0
- data/README.md +2739 -0
- data/SECURITY.md +73 -0
- data/THIRD_PARTY_NOTICES.md +46 -0
- data/app/assets/css/_common.css +3125 -0
- data/app/assets/js/carousel.js +39 -0
- data/app/assets/js/contact-button.js +28 -0
- data/app/assets/js/random-pool.js +44 -0
- data/app/assets/js/search-init.js +11 -0
- data/app/assets/js/theme-toggle.js +39 -0
- data/app/assets/js/viz-tag-bubble.js +108 -0
- data/app/assets/js/viz-tag-cooccurrence.js +125 -0
- data/app/assets/js/viz-topic-constellation.js +142 -0
- data/app/icons/bluesky.svg +3 -0
- data/app/icons/github.svg +3 -0
- data/app/icons/linkedin.svg +3 -0
- data/app/icons/mail.svg +4 -0
- data/app/icons/mastodon.svg +3 -0
- data/app/icons/moon.svg +3 -0
- data/app/icons/rss.svg +3 -0
- data/app/icons/sun.svg +4 -0
- data/app/icons/x.svg +3 -0
- data/app/views/layouts/about.html.erb +70 -0
- data/app/views/layouts/application.html.erb +65 -0
- data/app/views/layouts/book_series_index.html.erb +43 -0
- data/app/views/layouts/bundle.html.erb +111 -0
- data/app/views/layouts/bundles_index.html.erb +46 -0
- data/app/views/layouts/country_index.html.erb +59 -0
- data/app/views/layouts/gallery_index.html.erb +126 -0
- data/app/views/layouts/home.html.erb +107 -0
- data/app/views/layouts/photo.html.erb +100 -0
- data/app/views/layouts/photos_archive.html.erb +101 -0
- data/app/views/layouts/photos_index.html.erb +204 -0
- data/app/views/layouts/post.html.erb +153 -0
- data/app/views/layouts/posts_archive.html.erb +98 -0
- data/app/views/layouts/posts_index.html.erb +80 -0
- data/app/views/layouts/publication.html.erb +116 -0
- data/app/views/layouts/publications_archive.html.erb +89 -0
- data/app/views/layouts/publications_index.html.erb +246 -0
- data/app/views/layouts/related_index.html.erb +48 -0
- data/app/views/layouts/series.html.erb +110 -0
- data/app/views/layouts/series_index.html.erb +202 -0
- data/app/views/layouts/tag.html.erb +16 -0
- data/app/views/layouts/visualization.html.erb +32 -0
- data/app/views/layouts/workshop.html.erb +163 -0
- data/app/views/layouts/workshops_index.html.erb +209 -0
- data/app/views/partials/_back_link.html.erb +27 -0
- data/app/views/partials/_back_to_index.html.erb +25 -0
- data/app/views/partials/_book_grid.html.erb +76 -0
- data/app/views/partials/_book_jsonld.html.erb +72 -0
- data/app/views/partials/_book_related.html.erb +87 -0
- data/app/views/partials/_breadcrumb_jsonld.html.erb +60 -0
- data/app/views/partials/_bundle_cta.html.erb +26 -0
- data/app/views/partials/_carousel.html.erb +64 -0
- data/app/views/partials/_collection_page_jsonld.html.erb +81 -0
- data/app/views/partials/_contact_button.html.erb +42 -0
- data/app/views/partials/_course_jsonld.html.erb +95 -0
- data/app/views/partials/_draft_banner.html.erb +20 -0
- data/app/views/partials/_event_jsonld.html.erb +122 -0
- data/app/views/partials/_footer.html.erb +88 -0
- data/app/views/partials/_future_banner.html.erb +25 -0
- data/app/views/partials/_head.html.erb +440 -0
- data/app/views/partials/_image_gallery.html.erb +64 -0
- data/app/views/partials/_image_object_jsonld.html.erb +61 -0
- data/app/views/partials/_nav.html.erb +63 -0
- data/app/views/partials/_newsletter_subscribe.html.erb +85 -0
- data/app/views/partials/_next_in_series.html.erb +27 -0
- data/app/views/partials/_next_item.html.erb +38 -0
- data/app/views/partials/_pagination.html.erb +15 -0
- data/app/views/partials/_person_jsonld.html.erb +46 -0
- data/app/views/partials/_plausible.html.erb +24 -0
- data/app/views/partials/_post_list.html.erb +101 -0
- data/app/views/partials/_post_series_previews.html.erb +92 -0
- data/app/views/partials/_publication_card.html.erb +75 -0
- data/app/views/partials/_publication_header.html.erb +61 -0
- data/app/views/partials/_related_item.html.erb +68 -0
- data/app/views/partials/_related_items.html.erb +105 -0
- data/app/views/partials/_search.html.erb +26 -0
- data/app/views/partials/_series_pager.html.erb +48 -0
- data/app/views/partials/_skip_link.html.erb +12 -0
- data/app/views/partials/_taxonomy_row.html.erb +62 -0
- data/app/views/partials/_testimonials.html.erb +149 -0
- data/app/views/partials/_theme_toggle.html.erb +19 -0
- data/app/views/partials/_toc.html.erb +136 -0
- data/app/views/partials/_webmentions.html.erb +131 -0
- data/app/views/partials/_website_jsonld.html.erb +39 -0
- data/app/views/partials/home/_contact.html.erb +19 -0
- data/app/views/partials/home/_featured_publication.html.erb +107 -0
- data/app/views/partials/home/_latest_photo.html.erb +95 -0
- data/app/views/partials/home/_latest_post.html.erb +48 -0
- data/app/views/partials/home/_latest_publication.html.erb +89 -0
- data/app/views/partials/home/_next_workshop.html.erb +119 -0
- data/app/views/partials/home/_photo_gallery.html.erb +71 -0
- data/app/views/partials/home/_random_photo.html.erb +106 -0
- data/app/views/partials/home/_random_post.html.erb +64 -0
- data/exe/abqari +37 -0
- data/lib/abqari/artifact_writer.rb +196 -0
- data/lib/abqari/asset_pipeline.rb +235 -0
- data/lib/abqari/audit/a11y.rb +80 -0
- data/lib/abqari/audit/content.rb +154 -0
- data/lib/abqari/audit/dependencies.rb +127 -0
- data/lib/abqari/audit/links.rb +120 -0
- data/lib/abqari/audit/performance.rb +120 -0
- data/lib/abqari/audit/privacy.rb +42 -0
- data/lib/abqari/audit/rule.rb +56 -0
- data/lib/abqari/audit/seo.rb +105 -0
- data/lib/abqari/audit.rb +149 -0
- data/lib/abqari/bundle_assets.rb +127 -0
- data/lib/abqari/cli/new.rb +541 -0
- data/lib/abqari/cli/theme.rb +181 -0
- data/lib/abqari/cli.rb +130 -0
- data/lib/abqari/erbi_template.rb +72 -0
- data/lib/abqari/feed.rb +159 -0
- data/lib/abqari/folio.rb +195 -0
- data/lib/abqari/font_pipeline.rb +104 -0
- data/lib/abqari/headers_file.rb +324 -0
- data/lib/abqari/helpers.rb +308 -0
- data/lib/abqari/hooks.rb +136 -0
- data/lib/abqari/http_safe.rb +222 -0
- data/lib/abqari/image_pipeline.rb +800 -0
- data/lib/abqari/importers/base.rb +351 -0
- data/lib/abqari/importers/cli.rb +169 -0
- data/lib/abqari/importers/ghost.rb +113 -0
- data/lib/abqari/importers/jekyll.rb +256 -0
- data/lib/abqari/importers/substack.rb +204 -0
- data/lib/abqari/importers/support/html_to_markdown.rb +126 -0
- data/lib/abqari/importers/support/image_downloader.rb +170 -0
- data/lib/abqari/importers/support/report.rb +87 -0
- data/lib/abqari/importers/support/slug_normalizer.rb +53 -0
- data/lib/abqari/importers.rb +64 -0
- data/lib/abqari/indieweb.rb +551 -0
- data/lib/abqari/llms_txt.rb +110 -0
- data/lib/abqari/log.rb +61 -0
- data/lib/abqari/manifest.rb +58 -0
- data/lib/abqari/minifier.rb +108 -0
- data/lib/abqari/og_image_generator.rb +223 -0
- data/lib/abqari/page/bundle.rb +152 -0
- data/lib/abqari/page/incremental.rb +74 -0
- data/lib/abqari/page/parser.rb +129 -0
- data/lib/abqari/page/path.rb +153 -0
- data/lib/abqari/page.rb +424 -0
- data/lib/abqari/paginated_shard.rb +109 -0
- data/lib/abqari/paginator.rb +35 -0
- data/lib/abqari/path_safe.rb +62 -0
- data/lib/abqari/plausible_script.rb +20 -0
- data/lib/abqari/publication_normaliser.rb +111 -0
- data/lib/abqari/publisher_pages.rb +342 -0
- data/lib/abqari/redirects.rb +134 -0
- data/lib/abqari/related_index_page.rb +79 -0
- data/lib/abqari/render_context/cover_helpers.rb +338 -0
- data/lib/abqari/render_context/picture_helpers.rb +178 -0
- data/lib/abqari/render_context/publication_helpers.rb +120 -0
- data/lib/abqari/render_context.rb +251 -0
- data/lib/abqari/renderer.rb +788 -0
- data/lib/abqari/robots.rb +93 -0
- data/lib/abqari/search.rb +68 -0
- data/lib/abqari/security_txt.rb +44 -0
- data/lib/abqari/server.rb +508 -0
- data/lib/abqari/site.rb +952 -0
- data/lib/abqari/site_config.rb +212 -0
- data/lib/abqari/site_loader.rb +265 -0
- data/lib/abqari/sitemap.rb +87 -0
- data/lib/abqari/speculation_rules_guard.rb +26 -0
- data/lib/abqari/syndication.rb +466 -0
- data/lib/abqari/syntax_highlighter.rb +146 -0
- data/lib/abqari/taxonomy_page.rb +129 -0
- data/lib/abqari/templates/site_skeleton/.github/dependabot.yml +53 -0
- data/lib/abqari/templates/site_skeleton/.github/workflows/deploy-cloudflare.yml +107 -0
- data/lib/abqari/templates/site_skeleton/.github/workflows/deploy-github-pages.yml +107 -0
- data/lib/abqari/templates/site_skeleton/.github/workflows/deploy-render.yml +87 -0
- data/lib/abqari/templates/site_skeleton/.gitignore +24 -0
- data/lib/abqari/templates/site_skeleton/.ruby-version.tt +1 -0
- data/lib/abqari/templates/site_skeleton/Gemfile.tt +20 -0
- data/lib/abqari/templates/site_skeleton/README.md.tt +60 -0
- data/lib/abqari/templates/site_skeleton/app/assets/css/site.css +9 -0
- data/lib/abqari/templates/site_skeleton/bin/audit +46 -0
- data/lib/abqari/templates/site_skeleton/bin/build +32 -0
- data/lib/abqari/templates/site_skeleton/bin/fetch-folio +32 -0
- data/lib/abqari/templates/site_skeleton/bin/fetch-fonts +20 -0
- data/lib/abqari/templates/site_skeleton/bin/import +31 -0
- data/lib/abqari/templates/site_skeleton/bin/index +30 -0
- data/lib/abqari/templates/site_skeleton/bin/new +235 -0
- data/lib/abqari/templates/site_skeleton/bin/serve +30 -0
- data/lib/abqari/templates/site_skeleton/config/site.blank.yml.tt +65 -0
- data/lib/abqari/templates/site_skeleton/config/site.yml.tt +266 -0
- data/lib/abqari/templates/site_skeleton/content/404.md +17 -0
- data/lib/abqari/templates/site_skeleton/content/about.blank.md.tt +12 -0
- data/lib/abqari/templates/site_skeleton/content/about.md.tt +18 -0
- data/lib/abqari/templates/site_skeleton/content/index.blank.md.tt +11 -0
- data/lib/abqari/templates/site_skeleton/content/index.md.tt +34 -0
- data/lib/abqari/templates/site_skeleton/content/photos/index.md.tt +12 -0
- data/lib/abqari/templates/site_skeleton/content/posts/index.md +12 -0
- data/lib/abqari/templates/site_skeleton/content/posts/welcome/index.md.tt +50 -0
- data/lib/abqari/templates/site_skeleton/content/publications/index.md.tt +13 -0
- data/lib/abqari/templates/site_skeleton/content/workshops/index.md.tt +13 -0
- data/lib/abqari/templates/site_skeleton/public/robots.txt +6 -0
- data/lib/abqari/templates/site_skeleton/themes/.gitkeep +0 -0
- data/lib/abqari/templates/site_skeleton/vendor/folio/.gitkeep +0 -0
- data/lib/abqari/templates/site_skeleton/vendor/fonts/.gitkeep +0 -0
- data/lib/abqari/theme_bootstrap.rb +19 -0
- data/lib/abqari/theme_fonts.rb +51 -0
- data/lib/abqari/version.rb +18 -0
- data/lib/abqari/visualizations.rb +215 -0
- data/lib/abqari.rb +154 -0
- data/themes/bootstrap/css/app.css +97 -0
- data/themes/bootstrap/public/LICENSE +21 -0
- data/themes/bootstrap/public/css/bootstrap.min.css +6 -0
- data/themes/bootstrap/public/css/bootstrap.min.css.map +1 -0
- data/themes/bootstrap/public/js/bootstrap.bundle.min.js +7 -0
- data/themes/bootstrap/public/js/bootstrap.bundle.min.js.map +1 -0
- data/themes/custom/css/app.css +176 -0
- data/themes/magazine/css/app.css +242 -0
- data/themes/minimal/css/app.css +151 -0
- data/themes/notebook/css/app.css +205 -0
- data/themes/sand/css/app.css +179 -0
- data/vendor/d3/d3.v7.min.js +2 -0
- data/vendor/heroicons/16/solid/academic-cap.svg +4 -0
- data/vendor/heroicons/16/solid/adjustments-horizontal.svg +3 -0
- data/vendor/heroicons/16/solid/adjustments-vertical.svg +3 -0
- data/vendor/heroicons/16/solid/archive-box-arrow-down.svg +4 -0
- data/vendor/heroicons/16/solid/archive-box-x-mark.svg +4 -0
- data/vendor/heroicons/16/solid/archive-box.svg +4 -0
- data/vendor/heroicons/16/solid/arrow-down-circle.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-down-left.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-down-on-square-stack.svg +4 -0
- data/vendor/heroicons/16/solid/arrow-down-on-square.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-down-right.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-down-tray.svg +4 -0
- data/vendor/heroicons/16/solid/arrow-down.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-left-circle.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-left-end-on-rectangle.svg +4 -0
- data/vendor/heroicons/16/solid/arrow-left-start-on-rectangle.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-left.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-long-down.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-long-left.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-long-right.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-long-up.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-path-rounded-square.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-path.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-right-circle.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-right-end-on-rectangle.svg +4 -0
- data/vendor/heroicons/16/solid/arrow-right-start-on-rectangle.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-right.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-top-right-on-square.svg +4 -0
- data/vendor/heroicons/16/solid/arrow-trending-down.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-trending-up.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-turn-down-left.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-turn-down-right.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-turn-left-down.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-turn-left-up.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-turn-right-down.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-turn-right-up.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-turn-up-left.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-turn-up-right.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-up-circle.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-up-left.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-up-on-square-stack.svg +4 -0
- data/vendor/heroicons/16/solid/arrow-up-on-square.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-up-right.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-up-tray.svg +4 -0
- data/vendor/heroicons/16/solid/arrow-up.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-uturn-down.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-uturn-left.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-uturn-right.svg +3 -0
- data/vendor/heroicons/16/solid/arrow-uturn-up.svg +3 -0
- data/vendor/heroicons/16/solid/arrows-pointing-in.svg +3 -0
- data/vendor/heroicons/16/solid/arrows-pointing-out.svg +3 -0
- data/vendor/heroicons/16/solid/arrows-right-left.svg +3 -0
- data/vendor/heroicons/16/solid/arrows-up-down.svg +3 -0
- data/vendor/heroicons/16/solid/at-symbol.svg +3 -0
- data/vendor/heroicons/16/solid/backspace.svg +3 -0
- data/vendor/heroicons/16/solid/backward.svg +3 -0
- data/vendor/heroicons/16/solid/banknotes.svg +4 -0
- data/vendor/heroicons/16/solid/bars-2.svg +3 -0
- data/vendor/heroicons/16/solid/bars-3-bottom-left.svg +3 -0
- data/vendor/heroicons/16/solid/bars-3-bottom-right.svg +3 -0
- data/vendor/heroicons/16/solid/bars-3-center-left.svg +3 -0
- data/vendor/heroicons/16/solid/bars-3.svg +3 -0
- data/vendor/heroicons/16/solid/bars-4.svg +3 -0
- data/vendor/heroicons/16/solid/bars-arrow-down.svg +3 -0
- data/vendor/heroicons/16/solid/bars-arrow-up.svg +3 -0
- data/vendor/heroicons/16/solid/battery-0.svg +3 -0
- data/vendor/heroicons/16/solid/battery-100.svg +4 -0
- data/vendor/heroicons/16/solid/battery-50.svg +4 -0
- data/vendor/heroicons/16/solid/beaker.svg +3 -0
- data/vendor/heroicons/16/solid/bell-alert.svg +4 -0
- data/vendor/heroicons/16/solid/bell-slash.svg +4 -0
- data/vendor/heroicons/16/solid/bell-snooze.svg +3 -0
- data/vendor/heroicons/16/solid/bell.svg +3 -0
- data/vendor/heroicons/16/solid/bold.svg +3 -0
- data/vendor/heroicons/16/solid/bolt-slash.svg +3 -0
- data/vendor/heroicons/16/solid/bolt.svg +3 -0
- data/vendor/heroicons/16/solid/book-open.svg +3 -0
- data/vendor/heroicons/16/solid/bookmark-slash.svg +3 -0
- data/vendor/heroicons/16/solid/bookmark-square.svg +3 -0
- data/vendor/heroicons/16/solid/bookmark.svg +3 -0
- data/vendor/heroicons/16/solid/briefcase.svg +4 -0
- data/vendor/heroicons/16/solid/bug-ant.svg +3 -0
- data/vendor/heroicons/16/solid/building-library.svg +3 -0
- data/vendor/heroicons/16/solid/building-office-2.svg +3 -0
- data/vendor/heroicons/16/solid/building-office.svg +3 -0
- data/vendor/heroicons/16/solid/building-storefront.svg +3 -0
- data/vendor/heroicons/16/solid/cake.svg +3 -0
- data/vendor/heroicons/16/solid/calculator.svg +3 -0
- data/vendor/heroicons/16/solid/calendar-date-range.svg +4 -0
- data/vendor/heroicons/16/solid/calendar-days.svg +4 -0
- data/vendor/heroicons/16/solid/calendar.svg +3 -0
- data/vendor/heroicons/16/solid/camera.svg +4 -0
- data/vendor/heroicons/16/solid/chart-bar-square.svg +3 -0
- data/vendor/heroicons/16/solid/chart-bar.svg +3 -0
- data/vendor/heroicons/16/solid/chart-pie.svg +4 -0
- data/vendor/heroicons/16/solid/chat-bubble-bottom-center-text.svg +3 -0
- data/vendor/heroicons/16/solid/chat-bubble-bottom-center.svg +3 -0
- data/vendor/heroicons/16/solid/chat-bubble-left-ellipsis.svg +3 -0
- data/vendor/heroicons/16/solid/chat-bubble-left-right.svg +4 -0
- data/vendor/heroicons/16/solid/chat-bubble-left.svg +3 -0
- data/vendor/heroicons/16/solid/chat-bubble-oval-left-ellipsis.svg +3 -0
- data/vendor/heroicons/16/solid/chat-bubble-oval-left.svg +3 -0
- data/vendor/heroicons/16/solid/check-badge.svg +3 -0
- data/vendor/heroicons/16/solid/check-circle.svg +3 -0
- data/vendor/heroicons/16/solid/check.svg +3 -0
- data/vendor/heroicons/16/solid/chevron-double-down.svg +3 -0
- data/vendor/heroicons/16/solid/chevron-double-left.svg +3 -0
- data/vendor/heroicons/16/solid/chevron-double-right.svg +3 -0
- data/vendor/heroicons/16/solid/chevron-double-up.svg +3 -0
- data/vendor/heroicons/16/solid/chevron-down.svg +3 -0
- data/vendor/heroicons/16/solid/chevron-left.svg +3 -0
- data/vendor/heroicons/16/solid/chevron-right.svg +3 -0
- data/vendor/heroicons/16/solid/chevron-up-down.svg +3 -0
- data/vendor/heroicons/16/solid/chevron-up.svg +3 -0
- data/vendor/heroicons/16/solid/circle-stack.svg +5 -0
- data/vendor/heroicons/16/solid/clipboard-document-check.svg +4 -0
- data/vendor/heroicons/16/solid/clipboard-document-list.svg +4 -0
- data/vendor/heroicons/16/solid/clipboard-document.svg +4 -0
- data/vendor/heroicons/16/solid/clipboard.svg +3 -0
- data/vendor/heroicons/16/solid/clock.svg +3 -0
- data/vendor/heroicons/16/solid/cloud-arrow-down.svg +3 -0
- data/vendor/heroicons/16/solid/cloud-arrow-up.svg +3 -0
- data/vendor/heroicons/16/solid/cloud.svg +3 -0
- data/vendor/heroicons/16/solid/code-bracket-square.svg +3 -0
- data/vendor/heroicons/16/solid/code-bracket.svg +3 -0
- data/vendor/heroicons/16/solid/cog-6-tooth.svg +3 -0
- data/vendor/heroicons/16/solid/cog-8-tooth.svg +3 -0
- data/vendor/heroicons/16/solid/cog.svg +3 -0
- data/vendor/heroicons/16/solid/command-line.svg +3 -0
- data/vendor/heroicons/16/solid/computer-desktop.svg +3 -0
- data/vendor/heroicons/16/solid/cpu-chip.svg +4 -0
- data/vendor/heroicons/16/solid/credit-card.svg +4 -0
- data/vendor/heroicons/16/solid/cube-transparent.svg +3 -0
- data/vendor/heroicons/16/solid/cube.svg +3 -0
- data/vendor/heroicons/16/solid/currency-bangladeshi.svg +3 -0
- data/vendor/heroicons/16/solid/currency-dollar.svg +4 -0
- data/vendor/heroicons/16/solid/currency-euro.svg +3 -0
- data/vendor/heroicons/16/solid/currency-pound.svg +3 -0
- data/vendor/heroicons/16/solid/currency-rupee.svg +3 -0
- data/vendor/heroicons/16/solid/currency-yen.svg +3 -0
- data/vendor/heroicons/16/solid/cursor-arrow-rays.svg +3 -0
- data/vendor/heroicons/16/solid/cursor-arrow-ripple.svg +5 -0
- data/vendor/heroicons/16/solid/device-phone-mobile.svg +4 -0
- data/vendor/heroicons/16/solid/device-tablet.svg +4 -0
- data/vendor/heroicons/16/solid/divide.svg +4 -0
- data/vendor/heroicons/16/solid/document-arrow-down.svg +3 -0
- data/vendor/heroicons/16/solid/document-arrow-up.svg +3 -0
- data/vendor/heroicons/16/solid/document-chart-bar.svg +3 -0
- data/vendor/heroicons/16/solid/document-check.svg +3 -0
- data/vendor/heroicons/16/solid/document-currency-bangladeshi.svg +3 -0
- data/vendor/heroicons/16/solid/document-currency-dollar.svg +4 -0
- data/vendor/heroicons/16/solid/document-currency-euro.svg +3 -0
- data/vendor/heroicons/16/solid/document-currency-pound.svg +3 -0
- data/vendor/heroicons/16/solid/document-currency-rupee.svg +3 -0
- data/vendor/heroicons/16/solid/document-currency-yen.svg +3 -0
- data/vendor/heroicons/16/solid/document-duplicate.svg +4 -0
- data/vendor/heroicons/16/solid/document-magnifying-glass.svg +4 -0
- data/vendor/heroicons/16/solid/document-minus.svg +3 -0
- data/vendor/heroicons/16/solid/document-plus.svg +3 -0
- data/vendor/heroicons/16/solid/document-text.svg +3 -0
- data/vendor/heroicons/16/solid/document.svg +3 -0
- data/vendor/heroicons/16/solid/ellipsis-horizontal-circle.svg +3 -0
- data/vendor/heroicons/16/solid/ellipsis-horizontal.svg +3 -0
- data/vendor/heroicons/16/solid/ellipsis-vertical.svg +3 -0
- data/vendor/heroicons/16/solid/envelope-open.svg +3 -0
- data/vendor/heroicons/16/solid/envelope.svg +4 -0
- data/vendor/heroicons/16/solid/equals.svg +3 -0
- data/vendor/heroicons/16/solid/exclamation-circle.svg +3 -0
- data/vendor/heroicons/16/solid/exclamation-triangle.svg +3 -0
- data/vendor/heroicons/16/solid/eye-dropper.svg +3 -0
- data/vendor/heroicons/16/solid/eye-slash.svg +4 -0
- data/vendor/heroicons/16/solid/eye.svg +4 -0
- data/vendor/heroicons/16/solid/face-frown.svg +3 -0
- data/vendor/heroicons/16/solid/face-smile.svg +3 -0
- data/vendor/heroicons/16/solid/film.svg +3 -0
- data/vendor/heroicons/16/solid/finger-print.svg +3 -0
- data/vendor/heroicons/16/solid/fire.svg +3 -0
- data/vendor/heroicons/16/solid/flag.svg +3 -0
- data/vendor/heroicons/16/solid/folder-arrow-down.svg +3 -0
- data/vendor/heroicons/16/solid/folder-minus.svg +3 -0
- data/vendor/heroicons/16/solid/folder-open.svg +3 -0
- data/vendor/heroicons/16/solid/folder-plus.svg +3 -0
- data/vendor/heroicons/16/solid/folder.svg +3 -0
- data/vendor/heroicons/16/solid/forward.svg +3 -0
- data/vendor/heroicons/16/solid/funnel.svg +3 -0
- data/vendor/heroicons/16/solid/gif.svg +3 -0
- data/vendor/heroicons/16/solid/gift-top.svg +4 -0
- data/vendor/heroicons/16/solid/gift.svg +4 -0
- data/vendor/heroicons/16/solid/globe-alt.svg +3 -0
- data/vendor/heroicons/16/solid/globe-americas.svg +3 -0
- data/vendor/heroicons/16/solid/globe-asia-australia.svg +3 -0
- data/vendor/heroicons/16/solid/globe-europe-africa.svg +3 -0
- data/vendor/heroicons/16/solid/h1.svg +3 -0
- data/vendor/heroicons/16/solid/h2.svg +3 -0
- data/vendor/heroicons/16/solid/h3.svg +3 -0
- data/vendor/heroicons/16/solid/hand-raised.svg +3 -0
- data/vendor/heroicons/16/solid/hand-thumb-down.svg +3 -0
- data/vendor/heroicons/16/solid/hand-thumb-up.svg +3 -0
- data/vendor/heroicons/16/solid/hashtag.svg +3 -0
- data/vendor/heroicons/16/solid/heart.svg +3 -0
- data/vendor/heroicons/16/solid/home-modern.svg +3 -0
- data/vendor/heroicons/16/solid/home.svg +3 -0
- data/vendor/heroicons/16/solid/identification.svg +3 -0
- data/vendor/heroicons/16/solid/inbox-arrow-down.svg +4 -0
- data/vendor/heroicons/16/solid/inbox-stack.svg +4 -0
- data/vendor/heroicons/16/solid/inbox.svg +3 -0
- data/vendor/heroicons/16/solid/information-circle.svg +3 -0
- data/vendor/heroicons/16/solid/italic.svg +3 -0
- data/vendor/heroicons/16/solid/key.svg +3 -0
- data/vendor/heroicons/16/solid/language.svg +3 -0
- data/vendor/heroicons/16/solid/lifebuoy.svg +3 -0
- data/vendor/heroicons/16/solid/light-bulb.svg +3 -0
- data/vendor/heroicons/16/solid/link-slash.svg +3 -0
- data/vendor/heroicons/16/solid/link.svg +4 -0
- data/vendor/heroicons/16/solid/list-bullet.svg +3 -0
- data/vendor/heroicons/16/solid/lock-closed.svg +3 -0
- data/vendor/heroicons/16/solid/lock-open.svg +3 -0
- data/vendor/heroicons/16/solid/magnifying-glass-circle.svg +4 -0
- data/vendor/heroicons/16/solid/magnifying-glass-minus.svg +4 -0
- data/vendor/heroicons/16/solid/magnifying-glass-plus.svg +4 -0
- data/vendor/heroicons/16/solid/magnifying-glass.svg +3 -0
- data/vendor/heroicons/16/solid/map-pin.svg +3 -0
- data/vendor/heroicons/16/solid/map.svg +3 -0
- data/vendor/heroicons/16/solid/megaphone.svg +3 -0
- data/vendor/heroicons/16/solid/microphone.svg +4 -0
- data/vendor/heroicons/16/solid/minus-circle.svg +3 -0
- data/vendor/heroicons/16/solid/minus.svg +3 -0
- data/vendor/heroicons/16/solid/moon.svg +3 -0
- data/vendor/heroicons/16/solid/musical-note.svg +3 -0
- data/vendor/heroicons/16/solid/newspaper.svg +4 -0
- data/vendor/heroicons/16/solid/no-symbol.svg +3 -0
- data/vendor/heroicons/16/solid/numbered-list.svg +3 -0
- data/vendor/heroicons/16/solid/paint-brush.svg +3 -0
- data/vendor/heroicons/16/solid/paper-airplane.svg +3 -0
- data/vendor/heroicons/16/solid/paper-clip.svg +3 -0
- data/vendor/heroicons/16/solid/pause-circle.svg +3 -0
- data/vendor/heroicons/16/solid/pause.svg +3 -0
- data/vendor/heroicons/16/solid/pencil-square.svg +4 -0
- data/vendor/heroicons/16/solid/pencil.svg +3 -0
- data/vendor/heroicons/16/solid/percent-badge.svg +3 -0
- data/vendor/heroicons/16/solid/phone-arrow-down-left.svg +4 -0
- data/vendor/heroicons/16/solid/phone-arrow-up-right.svg +4 -0
- data/vendor/heroicons/16/solid/phone-x-mark.svg +4 -0
- data/vendor/heroicons/16/solid/phone.svg +3 -0
- data/vendor/heroicons/16/solid/photo.svg +3 -0
- data/vendor/heroicons/16/solid/play-circle.svg +3 -0
- data/vendor/heroicons/16/solid/play-pause.svg +3 -0
- data/vendor/heroicons/16/solid/play.svg +3 -0
- data/vendor/heroicons/16/solid/plus-circle.svg +3 -0
- data/vendor/heroicons/16/solid/plus.svg +3 -0
- data/vendor/heroicons/16/solid/power.svg +3 -0
- data/vendor/heroicons/16/solid/presentation-chart-bar.svg +3 -0
- data/vendor/heroicons/16/solid/presentation-chart-line.svg +3 -0
- data/vendor/heroicons/16/solid/printer.svg +3 -0
- data/vendor/heroicons/16/solid/puzzle-piece.svg +3 -0
- data/vendor/heroicons/16/solid/qr-code.svg +9 -0
- data/vendor/heroicons/16/solid/question-mark-circle.svg +3 -0
- data/vendor/heroicons/16/solid/queue-list.svg +3 -0
- data/vendor/heroicons/16/solid/radio.svg +3 -0
- data/vendor/heroicons/16/solid/receipt-percent.svg +3 -0
- data/vendor/heroicons/16/solid/receipt-refund.svg +3 -0
- data/vendor/heroicons/16/solid/rectangle-group.svg +3 -0
- data/vendor/heroicons/16/solid/rectangle-stack.svg +3 -0
- data/vendor/heroicons/16/solid/rocket-launch.svg +4 -0
- data/vendor/heroicons/16/solid/rss.svg +3 -0
- data/vendor/heroicons/16/solid/scale.svg +3 -0
- data/vendor/heroicons/16/solid/scissors.svg +4 -0
- data/vendor/heroicons/16/solid/server-stack.svg +4 -0
- data/vendor/heroicons/16/solid/server.svg +4 -0
- data/vendor/heroicons/16/solid/share.svg +3 -0
- data/vendor/heroicons/16/solid/shield-check.svg +3 -0
- data/vendor/heroicons/16/solid/shield-exclamation.svg +3 -0
- data/vendor/heroicons/16/solid/shopping-bag.svg +3 -0
- data/vendor/heroicons/16/solid/shopping-cart.svg +3 -0
- data/vendor/heroicons/16/solid/signal-slash.svg +3 -0
- data/vendor/heroicons/16/solid/signal.svg +5 -0
- data/vendor/heroicons/16/solid/slash.svg +3 -0
- data/vendor/heroicons/16/solid/sparkles.svg +3 -0
- data/vendor/heroicons/16/solid/speaker-wave.svg +4 -0
- data/vendor/heroicons/16/solid/speaker-x-mark.svg +3 -0
- data/vendor/heroicons/16/solid/square-2-stack.svg +4 -0
- data/vendor/heroicons/16/solid/square-3-stack-3d.svg +5 -0
- data/vendor/heroicons/16/solid/squares-2x2.svg +3 -0
- data/vendor/heroicons/16/solid/squares-plus.svg +3 -0
- data/vendor/heroicons/16/solid/star.svg +3 -0
- data/vendor/heroicons/16/solid/stop-circle.svg +3 -0
- data/vendor/heroicons/16/solid/stop.svg +3 -0
- data/vendor/heroicons/16/solid/strikethrough.svg +3 -0
- data/vendor/heroicons/16/solid/sun.svg +3 -0
- data/vendor/heroicons/16/solid/swatch.svg +4 -0
- data/vendor/heroicons/16/solid/table-cells.svg +3 -0
- data/vendor/heroicons/16/solid/tag.svg +3 -0
- data/vendor/heroicons/16/solid/ticket.svg +3 -0
- data/vendor/heroicons/16/solid/trash.svg +3 -0
- data/vendor/heroicons/16/solid/trophy.svg +3 -0
- data/vendor/heroicons/16/solid/truck.svg +5 -0
- data/vendor/heroicons/16/solid/tv.svg +4 -0
- data/vendor/heroicons/16/solid/underline.svg +3 -0
- data/vendor/heroicons/16/solid/user-circle.svg +3 -0
- data/vendor/heroicons/16/solid/user-group.svg +3 -0
- data/vendor/heroicons/16/solid/user-minus.svg +3 -0
- data/vendor/heroicons/16/solid/user-plus.svg +3 -0
- data/vendor/heroicons/16/solid/user.svg +3 -0
- data/vendor/heroicons/16/solid/users.svg +3 -0
- data/vendor/heroicons/16/solid/variable.svg +3 -0
- data/vendor/heroicons/16/solid/video-camera-slash.svg +3 -0
- data/vendor/heroicons/16/solid/video-camera.svg +3 -0
- data/vendor/heroicons/16/solid/view-columns.svg +3 -0
- data/vendor/heroicons/16/solid/viewfinder-circle.svg +3 -0
- data/vendor/heroicons/16/solid/wallet.svg +3 -0
- data/vendor/heroicons/16/solid/wifi.svg +3 -0
- data/vendor/heroicons/16/solid/window.svg +3 -0
- data/vendor/heroicons/16/solid/wrench-screwdriver.svg +4 -0
- data/vendor/heroicons/16/solid/wrench.svg +3 -0
- data/vendor/heroicons/16/solid/x-circle.svg +3 -0
- data/vendor/heroicons/16/solid/x-mark.svg +3 -0
- data/vendor/heroicons/20/solid/academic-cap.svg +3 -0
- data/vendor/heroicons/20/solid/adjustments-horizontal.svg +3 -0
- data/vendor/heroicons/20/solid/adjustments-vertical.svg +3 -0
- data/vendor/heroicons/20/solid/archive-box-arrow-down.svg +3 -0
- data/vendor/heroicons/20/solid/archive-box-x-mark.svg +4 -0
- data/vendor/heroicons/20/solid/archive-box.svg +4 -0
- data/vendor/heroicons/20/solid/arrow-down-circle.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-down-left.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-down-on-square-stack.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-down-on-square.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-down-right.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-down-tray.svg +4 -0
- data/vendor/heroicons/20/solid/arrow-down.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-left-circle.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-left-end-on-rectangle.svg +4 -0
- data/vendor/heroicons/20/solid/arrow-left-on-rectangle.svg +4 -0
- data/vendor/heroicons/20/solid/arrow-left-start-on-rectangle.svg +4 -0
- data/vendor/heroicons/20/solid/arrow-left.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-long-down.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-long-left.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-long-right.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-long-up.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-path-rounded-square.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-path.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-right-circle.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-right-end-on-rectangle.svg +4 -0
- data/vendor/heroicons/20/solid/arrow-right-on-rectangle.svg +4 -0
- data/vendor/heroicons/20/solid/arrow-right-start-on-rectangle.svg +4 -0
- data/vendor/heroicons/20/solid/arrow-right.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-small-down.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-small-left.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-small-right.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-small-up.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-top-right-on-square.svg +4 -0
- data/vendor/heroicons/20/solid/arrow-trending-down.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-trending-up.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-turn-down-left.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-turn-down-right.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-turn-left-down.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-turn-left-up.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-turn-right-down.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-turn-right-up.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-turn-up-left.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-turn-up-right.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-up-circle.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-up-left.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-up-on-square-stack.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-up-on-square.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-up-right.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-up-tray.svg +4 -0
- data/vendor/heroicons/20/solid/arrow-up.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-uturn-down.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-uturn-left.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-uturn-right.svg +3 -0
- data/vendor/heroicons/20/solid/arrow-uturn-up.svg +3 -0
- data/vendor/heroicons/20/solid/arrows-pointing-in.svg +3 -0
- data/vendor/heroicons/20/solid/arrows-pointing-out.svg +3 -0
- data/vendor/heroicons/20/solid/arrows-right-left.svg +3 -0
- data/vendor/heroicons/20/solid/arrows-up-down.svg +3 -0
- data/vendor/heroicons/20/solid/at-symbol.svg +3 -0
- data/vendor/heroicons/20/solid/backspace.svg +3 -0
- data/vendor/heroicons/20/solid/backward.svg +3 -0
- data/vendor/heroicons/20/solid/banknotes.svg +3 -0
- data/vendor/heroicons/20/solid/bars-2.svg +3 -0
- data/vendor/heroicons/20/solid/bars-3-bottom-left.svg +3 -0
- data/vendor/heroicons/20/solid/bars-3-bottom-right.svg +3 -0
- data/vendor/heroicons/20/solid/bars-3-center-left.svg +3 -0
- data/vendor/heroicons/20/solid/bars-3.svg +3 -0
- data/vendor/heroicons/20/solid/bars-4.svg +3 -0
- data/vendor/heroicons/20/solid/bars-arrow-down.svg +3 -0
- data/vendor/heroicons/20/solid/bars-arrow-up.svg +3 -0
- data/vendor/heroicons/20/solid/battery-0.svg +3 -0
- data/vendor/heroicons/20/solid/battery-100.svg +4 -0
- data/vendor/heroicons/20/solid/battery-50.svg +4 -0
- data/vendor/heroicons/20/solid/beaker.svg +3 -0
- data/vendor/heroicons/20/solid/bell-alert.svg +4 -0
- data/vendor/heroicons/20/solid/bell-slash.svg +3 -0
- data/vendor/heroicons/20/solid/bell-snooze.svg +3 -0
- data/vendor/heroicons/20/solid/bell.svg +3 -0
- data/vendor/heroicons/20/solid/bold.svg +3 -0
- data/vendor/heroicons/20/solid/bolt-slash.svg +4 -0
- data/vendor/heroicons/20/solid/bolt.svg +3 -0
- data/vendor/heroicons/20/solid/book-open.svg +3 -0
- data/vendor/heroicons/20/solid/bookmark-slash.svg +3 -0
- data/vendor/heroicons/20/solid/bookmark-square.svg +3 -0
- data/vendor/heroicons/20/solid/bookmark.svg +3 -0
- data/vendor/heroicons/20/solid/briefcase.svg +4 -0
- data/vendor/heroicons/20/solid/bug-ant.svg +3 -0
- data/vendor/heroicons/20/solid/building-library.svg +3 -0
- data/vendor/heroicons/20/solid/building-office-2.svg +3 -0
- data/vendor/heroicons/20/solid/building-office.svg +3 -0
- data/vendor/heroicons/20/solid/building-storefront.svg +3 -0
- data/vendor/heroicons/20/solid/cake.svg +3 -0
- data/vendor/heroicons/20/solid/calculator.svg +3 -0
- data/vendor/heroicons/20/solid/calendar-date-range.svg +4 -0
- data/vendor/heroicons/20/solid/calendar-days.svg +4 -0
- data/vendor/heroicons/20/solid/calendar.svg +3 -0
- data/vendor/heroicons/20/solid/camera.svg +3 -0
- data/vendor/heroicons/20/solid/chart-bar-square.svg +3 -0
- data/vendor/heroicons/20/solid/chart-bar.svg +3 -0
- data/vendor/heroicons/20/solid/chart-pie.svg +4 -0
- data/vendor/heroicons/20/solid/chat-bubble-bottom-center-text.svg +3 -0
- data/vendor/heroicons/20/solid/chat-bubble-bottom-center.svg +3 -0
- data/vendor/heroicons/20/solid/chat-bubble-left-ellipsis.svg +3 -0
- data/vendor/heroicons/20/solid/chat-bubble-left-right.svg +4 -0
- data/vendor/heroicons/20/solid/chat-bubble-left.svg +3 -0
- data/vendor/heroicons/20/solid/chat-bubble-oval-left-ellipsis.svg +3 -0
- data/vendor/heroicons/20/solid/chat-bubble-oval-left.svg +3 -0
- data/vendor/heroicons/20/solid/check-badge.svg +3 -0
- data/vendor/heroicons/20/solid/check-circle.svg +3 -0
- data/vendor/heroicons/20/solid/check.svg +3 -0
- data/vendor/heroicons/20/solid/chevron-double-down.svg +3 -0
- data/vendor/heroicons/20/solid/chevron-double-left.svg +3 -0
- data/vendor/heroicons/20/solid/chevron-double-right.svg +3 -0
- data/vendor/heroicons/20/solid/chevron-double-up.svg +3 -0
- data/vendor/heroicons/20/solid/chevron-down.svg +3 -0
- data/vendor/heroicons/20/solid/chevron-left.svg +3 -0
- data/vendor/heroicons/20/solid/chevron-right.svg +3 -0
- data/vendor/heroicons/20/solid/chevron-up-down.svg +3 -0
- data/vendor/heroicons/20/solid/chevron-up.svg +3 -0
- data/vendor/heroicons/20/solid/circle-stack.svg +3 -0
- data/vendor/heroicons/20/solid/clipboard-document-check.svg +4 -0
- data/vendor/heroicons/20/solid/clipboard-document-list.svg +4 -0
- data/vendor/heroicons/20/solid/clipboard-document.svg +4 -0
- data/vendor/heroicons/20/solid/clipboard.svg +3 -0
- data/vendor/heroicons/20/solid/clock.svg +3 -0
- data/vendor/heroicons/20/solid/cloud-arrow-down.svg +3 -0
- data/vendor/heroicons/20/solid/cloud-arrow-up.svg +3 -0
- data/vendor/heroicons/20/solid/cloud.svg +3 -0
- data/vendor/heroicons/20/solid/code-bracket-square.svg +3 -0
- data/vendor/heroicons/20/solid/code-bracket.svg +3 -0
- data/vendor/heroicons/20/solid/cog-6-tooth.svg +3 -0
- data/vendor/heroicons/20/solid/cog-8-tooth.svg +3 -0
- data/vendor/heroicons/20/solid/cog.svg +4 -0
- data/vendor/heroicons/20/solid/command-line.svg +3 -0
- data/vendor/heroicons/20/solid/computer-desktop.svg +3 -0
- data/vendor/heroicons/20/solid/cpu-chip.svg +4 -0
- data/vendor/heroicons/20/solid/credit-card.svg +3 -0
- data/vendor/heroicons/20/solid/cube-transparent.svg +3 -0
- data/vendor/heroicons/20/solid/cube.svg +3 -0
- data/vendor/heroicons/20/solid/currency-bangladeshi.svg +3 -0
- data/vendor/heroicons/20/solid/currency-dollar.svg +4 -0
- data/vendor/heroicons/20/solid/currency-euro.svg +3 -0
- data/vendor/heroicons/20/solid/currency-pound.svg +3 -0
- data/vendor/heroicons/20/solid/currency-rupee.svg +3 -0
- data/vendor/heroicons/20/solid/currency-yen.svg +3 -0
- data/vendor/heroicons/20/solid/cursor-arrow-rays.svg +3 -0
- data/vendor/heroicons/20/solid/cursor-arrow-ripple.svg +5 -0
- data/vendor/heroicons/20/solid/device-phone-mobile.svg +4 -0
- data/vendor/heroicons/20/solid/device-tablet.svg +3 -0
- data/vendor/heroicons/20/solid/divide.svg +3 -0
- data/vendor/heroicons/20/solid/document-arrow-down.svg +3 -0
- data/vendor/heroicons/20/solid/document-arrow-up.svg +3 -0
- data/vendor/heroicons/20/solid/document-chart-bar.svg +3 -0
- data/vendor/heroicons/20/solid/document-check.svg +3 -0
- data/vendor/heroicons/20/solid/document-currency-bangladeshi.svg +3 -0
- data/vendor/heroicons/20/solid/document-currency-dollar.svg +3 -0
- data/vendor/heroicons/20/solid/document-currency-euro.svg +3 -0
- data/vendor/heroicons/20/solid/document-currency-pound.svg +3 -0
- data/vendor/heroicons/20/solid/document-currency-rupee.svg +3 -0
- data/vendor/heroicons/20/solid/document-currency-yen.svg +3 -0
- data/vendor/heroicons/20/solid/document-duplicate.svg +4 -0
- data/vendor/heroicons/20/solid/document-magnifying-glass.svg +4 -0
- data/vendor/heroicons/20/solid/document-minus.svg +3 -0
- data/vendor/heroicons/20/solid/document-plus.svg +3 -0
- data/vendor/heroicons/20/solid/document-text.svg +3 -0
- data/vendor/heroicons/20/solid/document.svg +3 -0
- data/vendor/heroicons/20/solid/ellipsis-horizontal-circle.svg +3 -0
- data/vendor/heroicons/20/solid/ellipsis-horizontal.svg +3 -0
- data/vendor/heroicons/20/solid/ellipsis-vertical.svg +3 -0
- data/vendor/heroicons/20/solid/envelope-open.svg +3 -0
- data/vendor/heroicons/20/solid/envelope.svg +4 -0
- data/vendor/heroicons/20/solid/equals.svg +3 -0
- data/vendor/heroicons/20/solid/exclamation-circle.svg +3 -0
- data/vendor/heroicons/20/solid/exclamation-triangle.svg +3 -0
- data/vendor/heroicons/20/solid/eye-dropper.svg +3 -0
- data/vendor/heroicons/20/solid/eye-slash.svg +4 -0
- data/vendor/heroicons/20/solid/eye.svg +4 -0
- data/vendor/heroicons/20/solid/face-frown.svg +3 -0
- data/vendor/heroicons/20/solid/face-smile.svg +3 -0
- data/vendor/heroicons/20/solid/film.svg +3 -0
- data/vendor/heroicons/20/solid/finger-print.svg +3 -0
- data/vendor/heroicons/20/solid/fire.svg +3 -0
- data/vendor/heroicons/20/solid/flag.svg +3 -0
- data/vendor/heroicons/20/solid/folder-arrow-down.svg +3 -0
- data/vendor/heroicons/20/solid/folder-minus.svg +3 -0
- data/vendor/heroicons/20/solid/folder-open.svg +3 -0
- data/vendor/heroicons/20/solid/folder-plus.svg +3 -0
- data/vendor/heroicons/20/solid/folder.svg +3 -0
- data/vendor/heroicons/20/solid/forward.svg +3 -0
- data/vendor/heroicons/20/solid/funnel.svg +3 -0
- data/vendor/heroicons/20/solid/gif.svg +3 -0
- data/vendor/heroicons/20/solid/gift-top.svg +3 -0
- data/vendor/heroicons/20/solid/gift.svg +4 -0
- data/vendor/heroicons/20/solid/globe-alt.svg +3 -0
- data/vendor/heroicons/20/solid/globe-americas.svg +3 -0
- data/vendor/heroicons/20/solid/globe-asia-australia.svg +3 -0
- data/vendor/heroicons/20/solid/globe-europe-africa.svg +3 -0
- data/vendor/heroicons/20/solid/h1.svg +3 -0
- data/vendor/heroicons/20/solid/h2.svg +3 -0
- data/vendor/heroicons/20/solid/h3.svg +3 -0
- data/vendor/heroicons/20/solid/hand-raised.svg +3 -0
- data/vendor/heroicons/20/solid/hand-thumb-down.svg +3 -0
- data/vendor/heroicons/20/solid/hand-thumb-up.svg +3 -0
- data/vendor/heroicons/20/solid/hashtag.svg +3 -0
- data/vendor/heroicons/20/solid/heart.svg +3 -0
- data/vendor/heroicons/20/solid/home-modern.svg +3 -0
- data/vendor/heroicons/20/solid/home.svg +3 -0
- data/vendor/heroicons/20/solid/identification.svg +3 -0
- data/vendor/heroicons/20/solid/inbox-arrow-down.svg +4 -0
- data/vendor/heroicons/20/solid/inbox-stack.svg +4 -0
- data/vendor/heroicons/20/solid/inbox.svg +3 -0
- data/vendor/heroicons/20/solid/information-circle.svg +3 -0
- data/vendor/heroicons/20/solid/italic.svg +3 -0
- data/vendor/heroicons/20/solid/key.svg +3 -0
- data/vendor/heroicons/20/solid/language.svg +4 -0
- data/vendor/heroicons/20/solid/lifebuoy.svg +3 -0
- data/vendor/heroicons/20/solid/light-bulb.svg +3 -0
- data/vendor/heroicons/20/solid/link-slash.svg +3 -0
- data/vendor/heroicons/20/solid/link.svg +4 -0
- data/vendor/heroicons/20/solid/list-bullet.svg +3 -0
- data/vendor/heroicons/20/solid/lock-closed.svg +3 -0
- data/vendor/heroicons/20/solid/lock-open.svg +3 -0
- data/vendor/heroicons/20/solid/magnifying-glass-circle.svg +4 -0
- data/vendor/heroicons/20/solid/magnifying-glass-minus.svg +4 -0
- data/vendor/heroicons/20/solid/magnifying-glass-plus.svg +4 -0
- data/vendor/heroicons/20/solid/magnifying-glass.svg +3 -0
- data/vendor/heroicons/20/solid/map-pin.svg +3 -0
- data/vendor/heroicons/20/solid/map.svg +3 -0
- data/vendor/heroicons/20/solid/megaphone.svg +3 -0
- data/vendor/heroicons/20/solid/microphone.svg +4 -0
- data/vendor/heroicons/20/solid/minus-circle.svg +3 -0
- data/vendor/heroicons/20/solid/minus-small.svg +3 -0
- data/vendor/heroicons/20/solid/minus.svg +3 -0
- data/vendor/heroicons/20/solid/moon.svg +3 -0
- data/vendor/heroicons/20/solid/musical-note.svg +3 -0
- data/vendor/heroicons/20/solid/newspaper.svg +4 -0
- data/vendor/heroicons/20/solid/no-symbol.svg +3 -0
- data/vendor/heroicons/20/solid/numbered-list.svg +3 -0
- data/vendor/heroicons/20/solid/paint-brush.svg +3 -0
- data/vendor/heroicons/20/solid/paper-airplane.svg +3 -0
- data/vendor/heroicons/20/solid/paper-clip.svg +3 -0
- data/vendor/heroicons/20/solid/pause-circle.svg +3 -0
- data/vendor/heroicons/20/solid/pause.svg +3 -0
- data/vendor/heroicons/20/solid/pencil-square.svg +4 -0
- data/vendor/heroicons/20/solid/pencil.svg +3 -0
- data/vendor/heroicons/20/solid/percent-badge.svg +3 -0
- data/vendor/heroicons/20/solid/phone-arrow-down-left.svg +3 -0
- data/vendor/heroicons/20/solid/phone-arrow-up-right.svg +3 -0
- data/vendor/heroicons/20/solid/phone-x-mark.svg +3 -0
- data/vendor/heroicons/20/solid/phone.svg +3 -0
- data/vendor/heroicons/20/solid/photo.svg +3 -0
- data/vendor/heroicons/20/solid/play-circle.svg +3 -0
- data/vendor/heroicons/20/solid/play-pause.svg +3 -0
- data/vendor/heroicons/20/solid/play.svg +3 -0
- data/vendor/heroicons/20/solid/plus-circle.svg +3 -0
- data/vendor/heroicons/20/solid/plus-small.svg +3 -0
- data/vendor/heroicons/20/solid/plus.svg +3 -0
- data/vendor/heroicons/20/solid/power.svg +3 -0
- data/vendor/heroicons/20/solid/presentation-chart-bar.svg +3 -0
- data/vendor/heroicons/20/solid/presentation-chart-line.svg +3 -0
- data/vendor/heroicons/20/solid/printer.svg +3 -0
- data/vendor/heroicons/20/solid/puzzle-piece.svg +3 -0
- data/vendor/heroicons/20/solid/qr-code.svg +3 -0
- data/vendor/heroicons/20/solid/question-mark-circle.svg +3 -0
- data/vendor/heroicons/20/solid/queue-list.svg +3 -0
- data/vendor/heroicons/20/solid/radio.svg +3 -0
- data/vendor/heroicons/20/solid/receipt-percent.svg +3 -0
- data/vendor/heroicons/20/solid/receipt-refund.svg +3 -0
- data/vendor/heroicons/20/solid/rectangle-group.svg +3 -0
- data/vendor/heroicons/20/solid/rectangle-stack.svg +3 -0
- data/vendor/heroicons/20/solid/rocket-launch.svg +4 -0
- data/vendor/heroicons/20/solid/rss.svg +4 -0
- data/vendor/heroicons/20/solid/scale.svg +3 -0
- data/vendor/heroicons/20/solid/scissors.svg +4 -0
- data/vendor/heroicons/20/solid/server-stack.svg +4 -0
- data/vendor/heroicons/20/solid/server.svg +4 -0
- data/vendor/heroicons/20/solid/share.svg +3 -0
- data/vendor/heroicons/20/solid/shield-check.svg +3 -0
- data/vendor/heroicons/20/solid/shield-exclamation.svg +3 -0
- data/vendor/heroicons/20/solid/shopping-bag.svg +3 -0
- data/vendor/heroicons/20/solid/shopping-cart.svg +3 -0
- data/vendor/heroicons/20/solid/signal-slash.svg +3 -0
- data/vendor/heroicons/20/solid/signal.svg +4 -0
- data/vendor/heroicons/20/solid/slash.svg +3 -0
- data/vendor/heroicons/20/solid/sparkles.svg +3 -0
- data/vendor/heroicons/20/solid/speaker-wave.svg +4 -0
- data/vendor/heroicons/20/solid/speaker-x-mark.svg +3 -0
- data/vendor/heroicons/20/solid/square-2-stack.svg +4 -0
- data/vendor/heroicons/20/solid/square-3-stack-3d.svg +5 -0
- data/vendor/heroicons/20/solid/squares-2x2.svg +3 -0
- data/vendor/heroicons/20/solid/squares-plus.svg +3 -0
- data/vendor/heroicons/20/solid/star.svg +3 -0
- data/vendor/heroicons/20/solid/stop-circle.svg +3 -0
- data/vendor/heroicons/20/solid/stop.svg +3 -0
- data/vendor/heroicons/20/solid/strikethrough.svg +3 -0
- data/vendor/heroicons/20/solid/sun.svg +3 -0
- data/vendor/heroicons/20/solid/swatch.svg +3 -0
- data/vendor/heroicons/20/solid/table-cells.svg +3 -0
- data/vendor/heroicons/20/solid/tag.svg +3 -0
- data/vendor/heroicons/20/solid/ticket.svg +3 -0
- data/vendor/heroicons/20/solid/trash.svg +3 -0
- data/vendor/heroicons/20/solid/trophy.svg +3 -0
- data/vendor/heroicons/20/solid/truck.svg +4 -0
- data/vendor/heroicons/20/solid/tv.svg +4 -0
- data/vendor/heroicons/20/solid/underline.svg +3 -0
- data/vendor/heroicons/20/solid/user-circle.svg +3 -0
- data/vendor/heroicons/20/solid/user-group.svg +3 -0
- data/vendor/heroicons/20/solid/user-minus.svg +3 -0
- data/vendor/heroicons/20/solid/user-plus.svg +3 -0
- data/vendor/heroicons/20/solid/user.svg +3 -0
- data/vendor/heroicons/20/solid/users.svg +3 -0
- data/vendor/heroicons/20/solid/variable.svg +3 -0
- data/vendor/heroicons/20/solid/video-camera-slash.svg +3 -0
- data/vendor/heroicons/20/solid/video-camera.svg +3 -0
- data/vendor/heroicons/20/solid/view-columns.svg +3 -0
- data/vendor/heroicons/20/solid/viewfinder-circle.svg +3 -0
- data/vendor/heroicons/20/solid/wallet.svg +3 -0
- data/vendor/heroicons/20/solid/wifi.svg +3 -0
- data/vendor/heroicons/20/solid/window.svg +3 -0
- data/vendor/heroicons/20/solid/wrench-screwdriver.svg +4 -0
- data/vendor/heroicons/20/solid/wrench.svg +3 -0
- data/vendor/heroicons/20/solid/x-circle.svg +3 -0
- data/vendor/heroicons/20/solid/x-mark.svg +3 -0
- data/vendor/heroicons/24/outline/academic-cap.svg +3 -0
- data/vendor/heroicons/24/outline/adjustments-horizontal.svg +3 -0
- data/vendor/heroicons/24/outline/adjustments-vertical.svg +3 -0
- data/vendor/heroicons/24/outline/archive-box-arrow-down.svg +3 -0
- data/vendor/heroicons/24/outline/archive-box-x-mark.svg +3 -0
- data/vendor/heroicons/24/outline/archive-box.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-down-circle.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-down-left.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-down-on-square-stack.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-down-on-square.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-down-right.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-down-tray.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-down.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-left-circle.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-left-end-on-rectangle.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-left-on-rectangle.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-left-start-on-rectangle.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-left.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-long-down.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-long-left.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-long-right.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-long-up.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-path-rounded-square.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-path.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-right-circle.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-right-end-on-rectangle.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-right-on-rectangle.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-right-start-on-rectangle.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-right.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-small-down.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-small-left.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-small-right.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-small-up.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-top-right-on-square.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-trending-down.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-trending-up.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-turn-down-left.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-turn-down-right.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-turn-left-down.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-turn-left-up.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-turn-right-down.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-turn-right-up.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-turn-up-left.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-turn-up-right.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-up-circle.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-up-left.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-up-on-square-stack.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-up-on-square.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-up-right.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-up-tray.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-up.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-uturn-down.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-uturn-left.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-uturn-right.svg +3 -0
- data/vendor/heroicons/24/outline/arrow-uturn-up.svg +3 -0
- data/vendor/heroicons/24/outline/arrows-pointing-in.svg +3 -0
- data/vendor/heroicons/24/outline/arrows-pointing-out.svg +3 -0
- data/vendor/heroicons/24/outline/arrows-right-left.svg +3 -0
- data/vendor/heroicons/24/outline/arrows-up-down.svg +3 -0
- data/vendor/heroicons/24/outline/at-symbol.svg +3 -0
- data/vendor/heroicons/24/outline/backspace.svg +3 -0
- data/vendor/heroicons/24/outline/backward.svg +3 -0
- data/vendor/heroicons/24/outline/banknotes.svg +3 -0
- data/vendor/heroicons/24/outline/bars-2.svg +3 -0
- data/vendor/heroicons/24/outline/bars-3-bottom-left.svg +3 -0
- data/vendor/heroicons/24/outline/bars-3-bottom-right.svg +3 -0
- data/vendor/heroicons/24/outline/bars-3-center-left.svg +3 -0
- data/vendor/heroicons/24/outline/bars-3.svg +3 -0
- data/vendor/heroicons/24/outline/bars-4.svg +3 -0
- data/vendor/heroicons/24/outline/bars-arrow-down.svg +3 -0
- data/vendor/heroicons/24/outline/bars-arrow-up.svg +3 -0
- data/vendor/heroicons/24/outline/battery-0.svg +3 -0
- data/vendor/heroicons/24/outline/battery-100.svg +3 -0
- data/vendor/heroicons/24/outline/battery-50.svg +3 -0
- data/vendor/heroicons/24/outline/beaker.svg +3 -0
- data/vendor/heroicons/24/outline/bell-alert.svg +3 -0
- data/vendor/heroicons/24/outline/bell-slash.svg +3 -0
- data/vendor/heroicons/24/outline/bell-snooze.svg +3 -0
- data/vendor/heroicons/24/outline/bell.svg +3 -0
- data/vendor/heroicons/24/outline/bold.svg +3 -0
- data/vendor/heroicons/24/outline/bolt-slash.svg +3 -0
- data/vendor/heroicons/24/outline/bolt.svg +3 -0
- data/vendor/heroicons/24/outline/book-open.svg +3 -0
- data/vendor/heroicons/24/outline/bookmark-slash.svg +3 -0
- data/vendor/heroicons/24/outline/bookmark-square.svg +3 -0
- data/vendor/heroicons/24/outline/bookmark.svg +3 -0
- data/vendor/heroicons/24/outline/briefcase.svg +3 -0
- data/vendor/heroicons/24/outline/bug-ant.svg +3 -0
- data/vendor/heroicons/24/outline/building-library.svg +3 -0
- data/vendor/heroicons/24/outline/building-office-2.svg +3 -0
- data/vendor/heroicons/24/outline/building-office.svg +3 -0
- data/vendor/heroicons/24/outline/building-storefront.svg +3 -0
- data/vendor/heroicons/24/outline/cake.svg +3 -0
- data/vendor/heroicons/24/outline/calculator.svg +3 -0
- data/vendor/heroicons/24/outline/calendar-date-range.svg +3 -0
- data/vendor/heroicons/24/outline/calendar-days.svg +3 -0
- data/vendor/heroicons/24/outline/calendar.svg +3 -0
- data/vendor/heroicons/24/outline/camera.svg +4 -0
- data/vendor/heroicons/24/outline/chart-bar-square.svg +3 -0
- data/vendor/heroicons/24/outline/chart-bar.svg +3 -0
- data/vendor/heroicons/24/outline/chart-pie.svg +4 -0
- data/vendor/heroicons/24/outline/chat-bubble-bottom-center-text.svg +3 -0
- data/vendor/heroicons/24/outline/chat-bubble-bottom-center.svg +3 -0
- data/vendor/heroicons/24/outline/chat-bubble-left-ellipsis.svg +3 -0
- data/vendor/heroicons/24/outline/chat-bubble-left-right.svg +3 -0
- data/vendor/heroicons/24/outline/chat-bubble-left.svg +3 -0
- data/vendor/heroicons/24/outline/chat-bubble-oval-left-ellipsis.svg +3 -0
- data/vendor/heroicons/24/outline/chat-bubble-oval-left.svg +3 -0
- data/vendor/heroicons/24/outline/check-badge.svg +3 -0
- data/vendor/heroicons/24/outline/check-circle.svg +3 -0
- data/vendor/heroicons/24/outline/check.svg +3 -0
- data/vendor/heroicons/24/outline/chevron-double-down.svg +3 -0
- data/vendor/heroicons/24/outline/chevron-double-left.svg +3 -0
- data/vendor/heroicons/24/outline/chevron-double-right.svg +3 -0
- data/vendor/heroicons/24/outline/chevron-double-up.svg +4 -0
- data/vendor/heroicons/24/outline/chevron-down.svg +3 -0
- data/vendor/heroicons/24/outline/chevron-left.svg +3 -0
- data/vendor/heroicons/24/outline/chevron-right.svg +3 -0
- data/vendor/heroicons/24/outline/chevron-up-down.svg +3 -0
- data/vendor/heroicons/24/outline/chevron-up.svg +3 -0
- data/vendor/heroicons/24/outline/circle-stack.svg +3 -0
- data/vendor/heroicons/24/outline/clipboard-document-check.svg +3 -0
- data/vendor/heroicons/24/outline/clipboard-document-list.svg +3 -0
- data/vendor/heroicons/24/outline/clipboard-document.svg +3 -0
- data/vendor/heroicons/24/outline/clipboard.svg +3 -0
- data/vendor/heroicons/24/outline/clock.svg +3 -0
- data/vendor/heroicons/24/outline/cloud-arrow-down.svg +3 -0
- data/vendor/heroicons/24/outline/cloud-arrow-up.svg +3 -0
- data/vendor/heroicons/24/outline/cloud.svg +3 -0
- data/vendor/heroicons/24/outline/code-bracket-square.svg +3 -0
- data/vendor/heroicons/24/outline/code-bracket.svg +3 -0
- data/vendor/heroicons/24/outline/cog-6-tooth.svg +4 -0
- data/vendor/heroicons/24/outline/cog-8-tooth.svg +4 -0
- data/vendor/heroicons/24/outline/cog.svg +3 -0
- data/vendor/heroicons/24/outline/command-line.svg +3 -0
- data/vendor/heroicons/24/outline/computer-desktop.svg +3 -0
- data/vendor/heroicons/24/outline/cpu-chip.svg +3 -0
- data/vendor/heroicons/24/outline/credit-card.svg +3 -0
- data/vendor/heroicons/24/outline/cube-transparent.svg +3 -0
- data/vendor/heroicons/24/outline/cube.svg +3 -0
- data/vendor/heroicons/24/outline/currency-bangladeshi.svg +3 -0
- data/vendor/heroicons/24/outline/currency-dollar.svg +3 -0
- data/vendor/heroicons/24/outline/currency-euro.svg +3 -0
- data/vendor/heroicons/24/outline/currency-pound.svg +3 -0
- data/vendor/heroicons/24/outline/currency-rupee.svg +3 -0
- data/vendor/heroicons/24/outline/currency-yen.svg +3 -0
- data/vendor/heroicons/24/outline/cursor-arrow-rays.svg +3 -0
- data/vendor/heroicons/24/outline/cursor-arrow-ripple.svg +3 -0
- data/vendor/heroicons/24/outline/device-phone-mobile.svg +3 -0
- data/vendor/heroicons/24/outline/device-tablet.svg +3 -0
- data/vendor/heroicons/24/outline/divide.svg +3 -0
- data/vendor/heroicons/24/outline/document-arrow-down.svg +3 -0
- data/vendor/heroicons/24/outline/document-arrow-up.svg +3 -0
- data/vendor/heroicons/24/outline/document-chart-bar.svg +3 -0
- data/vendor/heroicons/24/outline/document-check.svg +3 -0
- data/vendor/heroicons/24/outline/document-currency-bangladeshi.svg +3 -0
- data/vendor/heroicons/24/outline/document-currency-dollar.svg +3 -0
- data/vendor/heroicons/24/outline/document-currency-euro.svg +3 -0
- data/vendor/heroicons/24/outline/document-currency-pound.svg +3 -0
- data/vendor/heroicons/24/outline/document-currency-rupee.svg +3 -0
- data/vendor/heroicons/24/outline/document-currency-yen.svg +3 -0
- data/vendor/heroicons/24/outline/document-duplicate.svg +3 -0
- data/vendor/heroicons/24/outline/document-magnifying-glass.svg +3 -0
- data/vendor/heroicons/24/outline/document-minus.svg +3 -0
- data/vendor/heroicons/24/outline/document-plus.svg +3 -0
- data/vendor/heroicons/24/outline/document-text.svg +3 -0
- data/vendor/heroicons/24/outline/document.svg +3 -0
- data/vendor/heroicons/24/outline/ellipsis-horizontal-circle.svg +3 -0
- data/vendor/heroicons/24/outline/ellipsis-horizontal.svg +3 -0
- data/vendor/heroicons/24/outline/ellipsis-vertical.svg +3 -0
- data/vendor/heroicons/24/outline/envelope-open.svg +3 -0
- data/vendor/heroicons/24/outline/envelope.svg +3 -0
- data/vendor/heroicons/24/outline/equals.svg +3 -0
- data/vendor/heroicons/24/outline/exclamation-circle.svg +3 -0
- data/vendor/heroicons/24/outline/exclamation-triangle.svg +3 -0
- data/vendor/heroicons/24/outline/eye-dropper.svg +3 -0
- data/vendor/heroicons/24/outline/eye-slash.svg +3 -0
- data/vendor/heroicons/24/outline/eye.svg +4 -0
- data/vendor/heroicons/24/outline/face-frown.svg +3 -0
- data/vendor/heroicons/24/outline/face-smile.svg +3 -0
- data/vendor/heroicons/24/outline/film.svg +3 -0
- data/vendor/heroicons/24/outline/finger-print.svg +3 -0
- data/vendor/heroicons/24/outline/fire.svg +4 -0
- data/vendor/heroicons/24/outline/flag.svg +3 -0
- data/vendor/heroicons/24/outline/folder-arrow-down.svg +3 -0
- data/vendor/heroicons/24/outline/folder-minus.svg +3 -0
- data/vendor/heroicons/24/outline/folder-open.svg +3 -0
- data/vendor/heroicons/24/outline/folder-plus.svg +3 -0
- data/vendor/heroicons/24/outline/folder.svg +3 -0
- data/vendor/heroicons/24/outline/forward.svg +3 -0
- data/vendor/heroicons/24/outline/funnel.svg +3 -0
- data/vendor/heroicons/24/outline/gif.svg +3 -0
- data/vendor/heroicons/24/outline/gift-top.svg +3 -0
- data/vendor/heroicons/24/outline/gift.svg +3 -0
- data/vendor/heroicons/24/outline/globe-alt.svg +3 -0
- data/vendor/heroicons/24/outline/globe-americas.svg +3 -0
- data/vendor/heroicons/24/outline/globe-asia-australia.svg +3 -0
- data/vendor/heroicons/24/outline/globe-europe-africa.svg +3 -0
- data/vendor/heroicons/24/outline/h1.svg +3 -0
- data/vendor/heroicons/24/outline/h2.svg +3 -0
- data/vendor/heroicons/24/outline/h3.svg +3 -0
- data/vendor/heroicons/24/outline/hand-raised.svg +3 -0
- data/vendor/heroicons/24/outline/hand-thumb-down.svg +3 -0
- data/vendor/heroicons/24/outline/hand-thumb-up.svg +3 -0
- data/vendor/heroicons/24/outline/hashtag.svg +3 -0
- data/vendor/heroicons/24/outline/heart.svg +3 -0
- data/vendor/heroicons/24/outline/home-modern.svg +3 -0
- data/vendor/heroicons/24/outline/home.svg +3 -0
- data/vendor/heroicons/24/outline/identification.svg +3 -0
- data/vendor/heroicons/24/outline/inbox-arrow-down.svg +3 -0
- data/vendor/heroicons/24/outline/inbox-stack.svg +3 -0
- data/vendor/heroicons/24/outline/inbox.svg +3 -0
- data/vendor/heroicons/24/outline/information-circle.svg +3 -0
- data/vendor/heroicons/24/outline/italic.svg +3 -0
- data/vendor/heroicons/24/outline/key.svg +3 -0
- data/vendor/heroicons/24/outline/language.svg +3 -0
- data/vendor/heroicons/24/outline/lifebuoy.svg +3 -0
- data/vendor/heroicons/24/outline/light-bulb.svg +3 -0
- data/vendor/heroicons/24/outline/link-slash.svg +3 -0
- data/vendor/heroicons/24/outline/link.svg +3 -0
- data/vendor/heroicons/24/outline/list-bullet.svg +3 -0
- data/vendor/heroicons/24/outline/lock-closed.svg +3 -0
- data/vendor/heroicons/24/outline/lock-open.svg +3 -0
- data/vendor/heroicons/24/outline/magnifying-glass-circle.svg +3 -0
- data/vendor/heroicons/24/outline/magnifying-glass-minus.svg +3 -0
- data/vendor/heroicons/24/outline/magnifying-glass-plus.svg +3 -0
- data/vendor/heroicons/24/outline/magnifying-glass.svg +3 -0
- data/vendor/heroicons/24/outline/map-pin.svg +4 -0
- data/vendor/heroicons/24/outline/map.svg +3 -0
- data/vendor/heroicons/24/outline/megaphone.svg +3 -0
- data/vendor/heroicons/24/outline/microphone.svg +3 -0
- data/vendor/heroicons/24/outline/minus-circle.svg +3 -0
- data/vendor/heroicons/24/outline/minus-small.svg +3 -0
- data/vendor/heroicons/24/outline/minus.svg +3 -0
- data/vendor/heroicons/24/outline/moon.svg +3 -0
- data/vendor/heroicons/24/outline/musical-note.svg +3 -0
- data/vendor/heroicons/24/outline/newspaper.svg +3 -0
- data/vendor/heroicons/24/outline/no-symbol.svg +3 -0
- data/vendor/heroicons/24/outline/numbered-list.svg +3 -0
- data/vendor/heroicons/24/outline/paint-brush.svg +3 -0
- data/vendor/heroicons/24/outline/paper-airplane.svg +3 -0
- data/vendor/heroicons/24/outline/paper-clip.svg +3 -0
- data/vendor/heroicons/24/outline/pause-circle.svg +3 -0
- data/vendor/heroicons/24/outline/pause.svg +3 -0
- data/vendor/heroicons/24/outline/pencil-square.svg +3 -0
- data/vendor/heroicons/24/outline/pencil.svg +3 -0
- data/vendor/heroicons/24/outline/percent-badge.svg +3 -0
- data/vendor/heroicons/24/outline/phone-arrow-down-left.svg +3 -0
- data/vendor/heroicons/24/outline/phone-arrow-up-right.svg +3 -0
- data/vendor/heroicons/24/outline/phone-x-mark.svg +3 -0
- data/vendor/heroicons/24/outline/phone.svg +3 -0
- data/vendor/heroicons/24/outline/photo.svg +3 -0
- data/vendor/heroicons/24/outline/play-circle.svg +4 -0
- data/vendor/heroicons/24/outline/play-pause.svg +3 -0
- data/vendor/heroicons/24/outline/play.svg +3 -0
- data/vendor/heroicons/24/outline/plus-circle.svg +3 -0
- data/vendor/heroicons/24/outline/plus-small.svg +3 -0
- data/vendor/heroicons/24/outline/plus.svg +3 -0
- data/vendor/heroicons/24/outline/power.svg +3 -0
- data/vendor/heroicons/24/outline/presentation-chart-bar.svg +3 -0
- data/vendor/heroicons/24/outline/presentation-chart-line.svg +3 -0
- data/vendor/heroicons/24/outline/printer.svg +3 -0
- data/vendor/heroicons/24/outline/puzzle-piece.svg +3 -0
- data/vendor/heroicons/24/outline/qr-code.svg +4 -0
- data/vendor/heroicons/24/outline/question-mark-circle.svg +3 -0
- data/vendor/heroicons/24/outline/queue-list.svg +3 -0
- data/vendor/heroicons/24/outline/radio.svg +3 -0
- data/vendor/heroicons/24/outline/receipt-percent.svg +3 -0
- data/vendor/heroicons/24/outline/receipt-refund.svg +3 -0
- data/vendor/heroicons/24/outline/rectangle-group.svg +3 -0
- data/vendor/heroicons/24/outline/rectangle-stack.svg +3 -0
- data/vendor/heroicons/24/outline/rocket-launch.svg +3 -0
- data/vendor/heroicons/24/outline/rss.svg +3 -0
- data/vendor/heroicons/24/outline/scale.svg +3 -0
- data/vendor/heroicons/24/outline/scissors.svg +3 -0
- data/vendor/heroicons/24/outline/server-stack.svg +3 -0
- data/vendor/heroicons/24/outline/server.svg +3 -0
- data/vendor/heroicons/24/outline/share.svg +3 -0
- data/vendor/heroicons/24/outline/shield-check.svg +3 -0
- data/vendor/heroicons/24/outline/shield-exclamation.svg +3 -0
- data/vendor/heroicons/24/outline/shopping-bag.svg +3 -0
- data/vendor/heroicons/24/outline/shopping-cart.svg +3 -0
- data/vendor/heroicons/24/outline/signal-slash.svg +3 -0
- data/vendor/heroicons/24/outline/signal.svg +3 -0
- data/vendor/heroicons/24/outline/slash.svg +3 -0
- data/vendor/heroicons/24/outline/sparkles.svg +3 -0
- data/vendor/heroicons/24/outline/speaker-wave.svg +3 -0
- data/vendor/heroicons/24/outline/speaker-x-mark.svg +3 -0
- data/vendor/heroicons/24/outline/square-2-stack.svg +3 -0
- data/vendor/heroicons/24/outline/square-3-stack-3d.svg +3 -0
- data/vendor/heroicons/24/outline/squares-2x2.svg +3 -0
- data/vendor/heroicons/24/outline/squares-plus.svg +3 -0
- data/vendor/heroicons/24/outline/star.svg +3 -0
- data/vendor/heroicons/24/outline/stop-circle.svg +4 -0
- data/vendor/heroicons/24/outline/stop.svg +3 -0
- data/vendor/heroicons/24/outline/strikethrough.svg +3 -0
- data/vendor/heroicons/24/outline/sun.svg +3 -0
- data/vendor/heroicons/24/outline/swatch.svg +3 -0
- data/vendor/heroicons/24/outline/table-cells.svg +3 -0
- data/vendor/heroicons/24/outline/tag.svg +4 -0
- data/vendor/heroicons/24/outline/ticket.svg +3 -0
- data/vendor/heroicons/24/outline/trash.svg +3 -0
- data/vendor/heroicons/24/outline/trophy.svg +3 -0
- data/vendor/heroicons/24/outline/truck.svg +3 -0
- data/vendor/heroicons/24/outline/tv.svg +3 -0
- data/vendor/heroicons/24/outline/underline.svg +3 -0
- data/vendor/heroicons/24/outline/user-circle.svg +3 -0
- data/vendor/heroicons/24/outline/user-group.svg +3 -0
- data/vendor/heroicons/24/outline/user-minus.svg +3 -0
- data/vendor/heroicons/24/outline/user-plus.svg +3 -0
- data/vendor/heroicons/24/outline/user.svg +3 -0
- data/vendor/heroicons/24/outline/users.svg +3 -0
- data/vendor/heroicons/24/outline/variable.svg +3 -0
- data/vendor/heroicons/24/outline/video-camera-slash.svg +3 -0
- data/vendor/heroicons/24/outline/video-camera.svg +3 -0
- data/vendor/heroicons/24/outline/view-columns.svg +3 -0
- data/vendor/heroicons/24/outline/viewfinder-circle.svg +3 -0
- data/vendor/heroicons/24/outline/wallet.svg +3 -0
- data/vendor/heroicons/24/outline/wifi.svg +3 -0
- data/vendor/heroicons/24/outline/window.svg +3 -0
- data/vendor/heroicons/24/outline/wrench-screwdriver.svg +3 -0
- data/vendor/heroicons/24/outline/wrench.svg +4 -0
- data/vendor/heroicons/24/outline/x-circle.svg +3 -0
- data/vendor/heroicons/24/outline/x-mark.svg +3 -0
- data/vendor/heroicons/24/solid/academic-cap.svg +5 -0
- data/vendor/heroicons/24/solid/adjustments-horizontal.svg +3 -0
- data/vendor/heroicons/24/solid/adjustments-vertical.svg +3 -0
- data/vendor/heroicons/24/solid/archive-box-arrow-down.svg +4 -0
- data/vendor/heroicons/24/solid/archive-box-x-mark.svg +4 -0
- data/vendor/heroicons/24/solid/archive-box.svg +4 -0
- data/vendor/heroicons/24/solid/arrow-down-circle.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-down-left.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-down-on-square-stack.svg +4 -0
- data/vendor/heroicons/24/solid/arrow-down-on-square.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-down-right.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-down-tray.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-down.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-left-circle.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-left-end-on-rectangle.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-left-on-rectangle.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-left-start-on-rectangle.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-left.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-long-down.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-long-left.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-long-right.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-long-up.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-path-rounded-square.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-path.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-right-circle.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-right-end-on-rectangle.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-right-on-rectangle.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-right-start-on-rectangle.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-right.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-small-down.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-small-left.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-small-right.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-small-up.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-top-right-on-square.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-trending-down.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-trending-up.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-turn-down-left.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-turn-down-right.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-turn-left-down.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-turn-left-up.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-turn-right-down.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-turn-right-up.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-turn-up-left.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-turn-up-right.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-up-circle.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-up-left.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-up-on-square-stack.svg +4 -0
- data/vendor/heroicons/24/solid/arrow-up-on-square.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-up-right.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-up-tray.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-up.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-uturn-down.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-uturn-left.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-uturn-right.svg +3 -0
- data/vendor/heroicons/24/solid/arrow-uturn-up.svg +3 -0
- data/vendor/heroicons/24/solid/arrows-pointing-in.svg +3 -0
- data/vendor/heroicons/24/solid/arrows-pointing-out.svg +3 -0
- data/vendor/heroicons/24/solid/arrows-right-left.svg +3 -0
- data/vendor/heroicons/24/solid/arrows-up-down.svg +3 -0
- data/vendor/heroicons/24/solid/at-symbol.svg +3 -0
- data/vendor/heroicons/24/solid/backspace.svg +3 -0
- data/vendor/heroicons/24/solid/backward.svg +3 -0
- data/vendor/heroicons/24/solid/banknotes.svg +5 -0
- data/vendor/heroicons/24/solid/bars-2.svg +3 -0
- data/vendor/heroicons/24/solid/bars-3-bottom-left.svg +3 -0
- data/vendor/heroicons/24/solid/bars-3-bottom-right.svg +3 -0
- data/vendor/heroicons/24/solid/bars-3-center-left.svg +3 -0
- data/vendor/heroicons/24/solid/bars-3.svg +3 -0
- data/vendor/heroicons/24/solid/bars-4.svg +3 -0
- data/vendor/heroicons/24/solid/bars-arrow-down.svg +3 -0
- data/vendor/heroicons/24/solid/bars-arrow-up.svg +3 -0
- data/vendor/heroicons/24/solid/battery-0.svg +3 -0
- data/vendor/heroicons/24/solid/battery-100.svg +3 -0
- data/vendor/heroicons/24/solid/battery-50.svg +4 -0
- data/vendor/heroicons/24/solid/beaker.svg +3 -0
- data/vendor/heroicons/24/solid/bell-alert.svg +4 -0
- data/vendor/heroicons/24/solid/bell-slash.svg +4 -0
- data/vendor/heroicons/24/solid/bell-snooze.svg +3 -0
- data/vendor/heroicons/24/solid/bell.svg +3 -0
- data/vendor/heroicons/24/solid/bold.svg +3 -0
- data/vendor/heroicons/24/solid/bolt-slash.svg +3 -0
- data/vendor/heroicons/24/solid/bolt.svg +3 -0
- data/vendor/heroicons/24/solid/book-open.svg +3 -0
- data/vendor/heroicons/24/solid/bookmark-slash.svg +3 -0
- data/vendor/heroicons/24/solid/bookmark-square.svg +3 -0
- data/vendor/heroicons/24/solid/bookmark.svg +3 -0
- data/vendor/heroicons/24/solid/briefcase.svg +4 -0
- data/vendor/heroicons/24/solid/bug-ant.svg +3 -0
- data/vendor/heroicons/24/solid/building-library.svg +5 -0
- data/vendor/heroicons/24/solid/building-office-2.svg +3 -0
- data/vendor/heroicons/24/solid/building-office.svg +3 -0
- data/vendor/heroicons/24/solid/building-storefront.svg +4 -0
- data/vendor/heroicons/24/solid/cake.svg +3 -0
- data/vendor/heroicons/24/solid/calculator.svg +3 -0
- data/vendor/heroicons/24/solid/calendar-date-range.svg +4 -0
- data/vendor/heroicons/24/solid/calendar-days.svg +4 -0
- data/vendor/heroicons/24/solid/calendar.svg +3 -0
- data/vendor/heroicons/24/solid/camera.svg +4 -0
- data/vendor/heroicons/24/solid/chart-bar-square.svg +3 -0
- data/vendor/heroicons/24/solid/chart-bar.svg +3 -0
- data/vendor/heroicons/24/solid/chart-pie.svg +4 -0
- data/vendor/heroicons/24/solid/chat-bubble-bottom-center-text.svg +3 -0
- data/vendor/heroicons/24/solid/chat-bubble-bottom-center.svg +3 -0
- data/vendor/heroicons/24/solid/chat-bubble-left-ellipsis.svg +3 -0
- data/vendor/heroicons/24/solid/chat-bubble-left-right.svg +4 -0
- data/vendor/heroicons/24/solid/chat-bubble-left.svg +3 -0
- data/vendor/heroicons/24/solid/chat-bubble-oval-left-ellipsis.svg +3 -0
- data/vendor/heroicons/24/solid/chat-bubble-oval-left.svg +3 -0
- data/vendor/heroicons/24/solid/check-badge.svg +3 -0
- data/vendor/heroicons/24/solid/check-circle.svg +3 -0
- data/vendor/heroicons/24/solid/check.svg +3 -0
- data/vendor/heroicons/24/solid/chevron-double-down.svg +4 -0
- data/vendor/heroicons/24/solid/chevron-double-left.svg +4 -0
- data/vendor/heroicons/24/solid/chevron-double-right.svg +4 -0
- data/vendor/heroicons/24/solid/chevron-double-up.svg +4 -0
- data/vendor/heroicons/24/solid/chevron-down.svg +3 -0
- data/vendor/heroicons/24/solid/chevron-left.svg +3 -0
- data/vendor/heroicons/24/solid/chevron-right.svg +3 -0
- data/vendor/heroicons/24/solid/chevron-up-down.svg +3 -0
- data/vendor/heroicons/24/solid/chevron-up.svg +3 -0
- data/vendor/heroicons/24/solid/circle-stack.svg +6 -0
- data/vendor/heroicons/24/solid/clipboard-document-check.svg +4 -0
- data/vendor/heroicons/24/solid/clipboard-document-list.svg +4 -0
- data/vendor/heroicons/24/solid/clipboard-document.svg +5 -0
- data/vendor/heroicons/24/solid/clipboard.svg +3 -0
- data/vendor/heroicons/24/solid/clock.svg +3 -0
- data/vendor/heroicons/24/solid/cloud-arrow-down.svg +3 -0
- data/vendor/heroicons/24/solid/cloud-arrow-up.svg +3 -0
- data/vendor/heroicons/24/solid/cloud.svg +3 -0
- data/vendor/heroicons/24/solid/code-bracket-square.svg +3 -0
- data/vendor/heroicons/24/solid/code-bracket.svg +3 -0
- data/vendor/heroicons/24/solid/cog-6-tooth.svg +3 -0
- data/vendor/heroicons/24/solid/cog-8-tooth.svg +3 -0
- data/vendor/heroicons/24/solid/cog.svg +4 -0
- data/vendor/heroicons/24/solid/command-line.svg +3 -0
- data/vendor/heroicons/24/solid/computer-desktop.svg +3 -0
- data/vendor/heroicons/24/solid/cpu-chip.svg +4 -0
- data/vendor/heroicons/24/solid/credit-card.svg +4 -0
- data/vendor/heroicons/24/solid/cube-transparent.svg +3 -0
- data/vendor/heroicons/24/solid/cube.svg +3 -0
- data/vendor/heroicons/24/solid/currency-bangladeshi.svg +3 -0
- data/vendor/heroicons/24/solid/currency-dollar.svg +4 -0
- data/vendor/heroicons/24/solid/currency-euro.svg +3 -0
- data/vendor/heroicons/24/solid/currency-pound.svg +3 -0
- data/vendor/heroicons/24/solid/currency-rupee.svg +3 -0
- data/vendor/heroicons/24/solid/currency-yen.svg +3 -0
- data/vendor/heroicons/24/solid/cursor-arrow-rays.svg +3 -0
- data/vendor/heroicons/24/solid/cursor-arrow-ripple.svg +3 -0
- data/vendor/heroicons/24/solid/device-phone-mobile.svg +4 -0
- data/vendor/heroicons/24/solid/device-tablet.svg +4 -0
- data/vendor/heroicons/24/solid/divide.svg +3 -0
- data/vendor/heroicons/24/solid/document-arrow-down.svg +4 -0
- data/vendor/heroicons/24/solid/document-arrow-up.svg +4 -0
- data/vendor/heroicons/24/solid/document-chart-bar.svg +4 -0
- data/vendor/heroicons/24/solid/document-check.svg +4 -0
- data/vendor/heroicons/24/solid/document-currency-bangladeshi.svg +3 -0
- data/vendor/heroicons/24/solid/document-currency-dollar.svg +3 -0
- data/vendor/heroicons/24/solid/document-currency-euro.svg +4 -0
- data/vendor/heroicons/24/solid/document-currency-pound.svg +3 -0
- data/vendor/heroicons/24/solid/document-currency-rupee.svg +3 -0
- data/vendor/heroicons/24/solid/document-currency-yen.svg +3 -0
- data/vendor/heroicons/24/solid/document-duplicate.svg +4 -0
- data/vendor/heroicons/24/solid/document-magnifying-glass.svg +5 -0
- data/vendor/heroicons/24/solid/document-minus.svg +4 -0
- data/vendor/heroicons/24/solid/document-plus.svg +4 -0
- data/vendor/heroicons/24/solid/document-text.svg +4 -0
- data/vendor/heroicons/24/solid/document.svg +4 -0
- data/vendor/heroicons/24/solid/ellipsis-horizontal-circle.svg +3 -0
- data/vendor/heroicons/24/solid/ellipsis-horizontal.svg +3 -0
- data/vendor/heroicons/24/solid/ellipsis-vertical.svg +3 -0
- data/vendor/heroicons/24/solid/envelope-open.svg +4 -0
- data/vendor/heroicons/24/solid/envelope.svg +4 -0
- data/vendor/heroicons/24/solid/equals.svg +3 -0
- data/vendor/heroicons/24/solid/exclamation-circle.svg +3 -0
- data/vendor/heroicons/24/solid/exclamation-triangle.svg +3 -0
- data/vendor/heroicons/24/solid/eye-dropper.svg +3 -0
- data/vendor/heroicons/24/solid/eye-slash.svg +5 -0
- data/vendor/heroicons/24/solid/eye.svg +4 -0
- data/vendor/heroicons/24/solid/face-frown.svg +3 -0
- data/vendor/heroicons/24/solid/face-smile.svg +3 -0
- data/vendor/heroicons/24/solid/film.svg +3 -0
- data/vendor/heroicons/24/solid/finger-print.svg +3 -0
- data/vendor/heroicons/24/solid/fire.svg +3 -0
- data/vendor/heroicons/24/solid/flag.svg +3 -0
- data/vendor/heroicons/24/solid/folder-arrow-down.svg +3 -0
- data/vendor/heroicons/24/solid/folder-minus.svg +3 -0
- data/vendor/heroicons/24/solid/folder-open.svg +3 -0
- data/vendor/heroicons/24/solid/folder-plus.svg +3 -0
- data/vendor/heroicons/24/solid/folder.svg +3 -0
- data/vendor/heroicons/24/solid/forward.svg +3 -0
- data/vendor/heroicons/24/solid/funnel.svg +3 -0
- data/vendor/heroicons/24/solid/gif.svg +3 -0
- data/vendor/heroicons/24/solid/gift-top.svg +4 -0
- data/vendor/heroicons/24/solid/gift.svg +3 -0
- data/vendor/heroicons/24/solid/globe-alt.svg +3 -0
- data/vendor/heroicons/24/solid/globe-americas.svg +3 -0
- data/vendor/heroicons/24/solid/globe-asia-australia.svg +4 -0
- data/vendor/heroicons/24/solid/globe-europe-africa.svg +3 -0
- data/vendor/heroicons/24/solid/h1.svg +3 -0
- data/vendor/heroicons/24/solid/h2.svg +3 -0
- data/vendor/heroicons/24/solid/h3.svg +3 -0
- data/vendor/heroicons/24/solid/hand-raised.svg +3 -0
- data/vendor/heroicons/24/solid/hand-thumb-down.svg +3 -0
- data/vendor/heroicons/24/solid/hand-thumb-up.svg +3 -0
- data/vendor/heroicons/24/solid/hashtag.svg +3 -0
- data/vendor/heroicons/24/solid/heart.svg +3 -0
- data/vendor/heroicons/24/solid/home-modern.svg +4 -0
- data/vendor/heroicons/24/solid/home.svg +4 -0
- data/vendor/heroicons/24/solid/identification.svg +3 -0
- data/vendor/heroicons/24/solid/inbox-arrow-down.svg +4 -0
- data/vendor/heroicons/24/solid/inbox-stack.svg +4 -0
- data/vendor/heroicons/24/solid/inbox.svg +3 -0
- data/vendor/heroicons/24/solid/information-circle.svg +3 -0
- data/vendor/heroicons/24/solid/italic.svg +3 -0
- data/vendor/heroicons/24/solid/key.svg +3 -0
- data/vendor/heroicons/24/solid/language.svg +3 -0
- data/vendor/heroicons/24/solid/lifebuoy.svg +3 -0
- data/vendor/heroicons/24/solid/light-bulb.svg +4 -0
- data/vendor/heroicons/24/solid/link-slash.svg +3 -0
- data/vendor/heroicons/24/solid/link.svg +3 -0
- data/vendor/heroicons/24/solid/list-bullet.svg +3 -0
- data/vendor/heroicons/24/solid/lock-closed.svg +3 -0
- data/vendor/heroicons/24/solid/lock-open.svg +3 -0
- data/vendor/heroicons/24/solid/magnifying-glass-circle.svg +4 -0
- data/vendor/heroicons/24/solid/magnifying-glass-minus.svg +3 -0
- data/vendor/heroicons/24/solid/magnifying-glass-plus.svg +3 -0
- data/vendor/heroicons/24/solid/magnifying-glass.svg +3 -0
- data/vendor/heroicons/24/solid/map-pin.svg +3 -0
- data/vendor/heroicons/24/solid/map.svg +3 -0
- data/vendor/heroicons/24/solid/megaphone.svg +3 -0
- data/vendor/heroicons/24/solid/microphone.svg +4 -0
- data/vendor/heroicons/24/solid/minus-circle.svg +3 -0
- data/vendor/heroicons/24/solid/minus-small.svg +3 -0
- data/vendor/heroicons/24/solid/minus.svg +3 -0
- data/vendor/heroicons/24/solid/moon.svg +3 -0
- data/vendor/heroicons/24/solid/musical-note.svg +3 -0
- data/vendor/heroicons/24/solid/newspaper.svg +4 -0
- data/vendor/heroicons/24/solid/no-symbol.svg +3 -0
- data/vendor/heroicons/24/solid/numbered-list.svg +3 -0
- data/vendor/heroicons/24/solid/paint-brush.svg +3 -0
- data/vendor/heroicons/24/solid/paper-airplane.svg +3 -0
- data/vendor/heroicons/24/solid/paper-clip.svg +3 -0
- data/vendor/heroicons/24/solid/pause-circle.svg +3 -0
- data/vendor/heroicons/24/solid/pause.svg +3 -0
- data/vendor/heroicons/24/solid/pencil-square.svg +4 -0
- data/vendor/heroicons/24/solid/pencil.svg +3 -0
- data/vendor/heroicons/24/solid/percent-badge.svg +3 -0
- data/vendor/heroicons/24/solid/phone-arrow-down-left.svg +4 -0
- data/vendor/heroicons/24/solid/phone-arrow-up-right.svg +4 -0
- data/vendor/heroicons/24/solid/phone-x-mark.svg +3 -0
- data/vendor/heroicons/24/solid/phone.svg +3 -0
- data/vendor/heroicons/24/solid/photo.svg +3 -0
- data/vendor/heroicons/24/solid/play-circle.svg +3 -0
- data/vendor/heroicons/24/solid/play-pause.svg +3 -0
- data/vendor/heroicons/24/solid/play.svg +3 -0
- data/vendor/heroicons/24/solid/plus-circle.svg +3 -0
- data/vendor/heroicons/24/solid/plus-small.svg +3 -0
- data/vendor/heroicons/24/solid/plus.svg +3 -0
- data/vendor/heroicons/24/solid/power.svg +3 -0
- data/vendor/heroicons/24/solid/presentation-chart-bar.svg +3 -0
- data/vendor/heroicons/24/solid/presentation-chart-line.svg +3 -0
- data/vendor/heroicons/24/solid/printer.svg +3 -0
- data/vendor/heroicons/24/solid/puzzle-piece.svg +3 -0
- data/vendor/heroicons/24/solid/qr-code.svg +3 -0
- data/vendor/heroicons/24/solid/question-mark-circle.svg +3 -0
- data/vendor/heroicons/24/solid/queue-list.svg +3 -0
- data/vendor/heroicons/24/solid/radio.svg +3 -0
- data/vendor/heroicons/24/solid/receipt-percent.svg +3 -0
- data/vendor/heroicons/24/solid/receipt-refund.svg +3 -0
- data/vendor/heroicons/24/solid/rectangle-group.svg +3 -0
- data/vendor/heroicons/24/solid/rectangle-stack.svg +3 -0
- data/vendor/heroicons/24/solid/rocket-launch.svg +4 -0
- data/vendor/heroicons/24/solid/rss.svg +3 -0
- data/vendor/heroicons/24/solid/scale.svg +3 -0
- data/vendor/heroicons/24/solid/scissors.svg +4 -0
- data/vendor/heroicons/24/solid/server-stack.svg +4 -0
- data/vendor/heroicons/24/solid/server.svg +4 -0
- data/vendor/heroicons/24/solid/share.svg +3 -0
- data/vendor/heroicons/24/solid/shield-check.svg +3 -0
- data/vendor/heroicons/24/solid/shield-exclamation.svg +3 -0
- data/vendor/heroicons/24/solid/shopping-bag.svg +3 -0
- data/vendor/heroicons/24/solid/shopping-cart.svg +3 -0
- data/vendor/heroicons/24/solid/signal-slash.svg +3 -0
- data/vendor/heroicons/24/solid/signal.svg +3 -0
- data/vendor/heroicons/24/solid/slash.svg +3 -0
- data/vendor/heroicons/24/solid/sparkles.svg +3 -0
- data/vendor/heroicons/24/solid/speaker-wave.svg +4 -0
- data/vendor/heroicons/24/solid/speaker-x-mark.svg +3 -0
- data/vendor/heroicons/24/solid/square-2-stack.svg +4 -0
- data/vendor/heroicons/24/solid/square-3-stack-3d.svg +5 -0
- data/vendor/heroicons/24/solid/squares-2x2.svg +3 -0
- data/vendor/heroicons/24/solid/squares-plus.svg +3 -0
- data/vendor/heroicons/24/solid/star.svg +3 -0
- data/vendor/heroicons/24/solid/stop-circle.svg +3 -0
- data/vendor/heroicons/24/solid/stop.svg +3 -0
- data/vendor/heroicons/24/solid/strikethrough.svg +3 -0
- data/vendor/heroicons/24/solid/sun.svg +3 -0
- data/vendor/heroicons/24/solid/swatch.svg +4 -0
- data/vendor/heroicons/24/solid/table-cells.svg +3 -0
- data/vendor/heroicons/24/solid/tag.svg +3 -0
- data/vendor/heroicons/24/solid/ticket.svg +3 -0
- data/vendor/heroicons/24/solid/trash.svg +3 -0
- data/vendor/heroicons/24/solid/trophy.svg +3 -0
- data/vendor/heroicons/24/solid/truck.svg +5 -0
- data/vendor/heroicons/24/solid/tv.svg +4 -0
- data/vendor/heroicons/24/solid/underline.svg +3 -0
- data/vendor/heroicons/24/solid/user-circle.svg +3 -0
- data/vendor/heroicons/24/solid/user-group.svg +4 -0
- data/vendor/heroicons/24/solid/user-minus.svg +3 -0
- data/vendor/heroicons/24/solid/user-plus.svg +3 -0
- data/vendor/heroicons/24/solid/user.svg +3 -0
- data/vendor/heroicons/24/solid/users.svg +3 -0
- data/vendor/heroicons/24/solid/variable.svg +3 -0
- data/vendor/heroicons/24/solid/video-camera-slash.svg +3 -0
- data/vendor/heroicons/24/solid/video-camera.svg +3 -0
- data/vendor/heroicons/24/solid/view-columns.svg +3 -0
- data/vendor/heroicons/24/solid/viewfinder-circle.svg +3 -0
- data/vendor/heroicons/24/solid/wallet.svg +3 -0
- data/vendor/heroicons/24/solid/wifi.svg +3 -0
- data/vendor/heroicons/24/solid/window.svg +3 -0
- data/vendor/heroicons/24/solid/wrench-screwdriver.svg +5 -0
- data/vendor/heroicons/24/solid/wrench.svg +3 -0
- data/vendor/heroicons/24/solid/x-circle.svg +3 -0
- data/vendor/heroicons/24/solid/x-mark.svg +3 -0
- data/vendor/heroicons/LICENSE +21 -0
- data/vendor/heroicons/VERSION +5 -0
- metadata +1664 -0
|
@@ -0,0 +1,788 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'etc'
|
|
4
|
+
|
|
5
|
+
module Abqari
|
|
6
|
+
# Page-rendering collaborator. Owns:
|
|
7
|
+
#
|
|
8
|
+
# - Generators that produce virtual pages BEFORE render
|
|
9
|
+
# (tag pages, paginated shards, visualizations, Folio pages,
|
|
10
|
+
# related-index pages).
|
|
11
|
+
# - The render loop itself, with parallel execution and per-page
|
|
12
|
+
# error collection.
|
|
13
|
+
# - ERB template caching (shared across threads via a mutex).
|
|
14
|
+
# - The shared-deps mtime used by incremental rendering.
|
|
15
|
+
# - HTML post-processing (bundle-URL rewrite, syntax highlighting,
|
|
16
|
+
# responsive image rewrites, minification, livereload injection).
|
|
17
|
+
class Renderer
|
|
18
|
+
# Below this many pages, parallelism hurts more than it helps.
|
|
19
|
+
PARALLEL_THRESHOLD = 16
|
|
20
|
+
|
|
21
|
+
# Default page-size for `paginate: true`. Overridable per-site via
|
|
22
|
+
# `pagination.per_page` config.
|
|
23
|
+
PAGINATION_DEFAULT = 10
|
|
24
|
+
|
|
25
|
+
# Slow-page detection. When a single page's `write` (render +
|
|
26
|
+
# post-process + file write) takes longer than this, the renderer
|
|
27
|
+
# logs a warning with the URL, elapsed time, and a short list of
|
|
28
|
+
# heuristic causes (output size, image count, code-block count,
|
|
29
|
+
# TOC presence). End-of-build summary surfaces the slowest few.
|
|
30
|
+
#
|
|
31
|
+
# Default 500ms — high enough to ignore the normal per-page
|
|
32
|
+
# baseline (~5–50ms), low enough to catch real outliers. Override
|
|
33
|
+
# with `ABQARI_SLOW_PAGE_MS=N` (set to 0 to disable detection).
|
|
34
|
+
SLOW_PAGE_THRESHOLD_MS = (ENV['ABQARI_SLOW_PAGE_MS'] || '500').to_i
|
|
35
|
+
|
|
36
|
+
# Files whose mtime invalidates every cached page render.
|
|
37
|
+
# `app/views/layouts/` is NOT here — layout files are handled
|
|
38
|
+
# per-layout via `layout_deps_mtime(name)` so editing one layout
|
|
39
|
+
# only invalidates the pages that use it.
|
|
40
|
+
#
|
|
41
|
+
# Partials stay in the global bucket: statically tracking which
|
|
42
|
+
# partials each layout chain renders would require scanning ERB
|
|
43
|
+
# source for `render '...'` calls and is more complexity than the
|
|
44
|
+
# win is worth at the scale Abqari targets. Edits to a partial
|
|
45
|
+
# therefore still invalidate every cached render.
|
|
46
|
+
#
|
|
47
|
+
# `themes/**/*` is NOT in this list — it's resolved per-site at
|
|
48
|
+
# `compute_shared_deps_mtime` time so we only walk the active
|
|
49
|
+
# theme's directory, not every theme that happens to ship with
|
|
50
|
+
# the gem.
|
|
51
|
+
GLOBAL_DEP_GLOBS = [
|
|
52
|
+
'app/views/partials/**/*',
|
|
53
|
+
'app/icons/**/*',
|
|
54
|
+
'app/assets/**/*',
|
|
55
|
+
'lib/**/*',
|
|
56
|
+
'config/**/*',
|
|
57
|
+
'data/**/*'
|
|
58
|
+
].freeze
|
|
59
|
+
|
|
60
|
+
# The renderer only needs the frontmatter block (no body), but
|
|
61
|
+
# reusing `Abqari::FRONTMATTER_RE` and discarding `match[2]` keeps
|
|
62
|
+
# the three call sites in lockstep — the old duplicate-with-drift
|
|
63
|
+
# was finding a `---` pair that the page parser wouldn't.
|
|
64
|
+
LAYOUT_FRONTMATTER_RE = Abqari::FRONTMATTER_RE
|
|
65
|
+
|
|
66
|
+
def initialize(site)
|
|
67
|
+
@site = site
|
|
68
|
+
@template_cache = {}
|
|
69
|
+
@template_mutex = Mutex.new
|
|
70
|
+
# Separate mutex for the mtime / layout-chain caches. Different
|
|
71
|
+
# contention profile from the template cache (computed once per
|
|
72
|
+
# layout name, then read-only for the rest of the build), and
|
|
73
|
+
# keeping the mutex separate means a slow first-miss on the
|
|
74
|
+
# mtime side doesn't block template compilation.
|
|
75
|
+
@deps_mutex = Mutex.new
|
|
76
|
+
@layout_chains = {}
|
|
77
|
+
@layout_mtimes = {}
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Reset between builds (incremental dev server keeps the Site
|
|
81
|
+
# around across rebuilds; the template cache must clear so layout
|
|
82
|
+
# edits take effect). Layout-chain caches are reset too — a new
|
|
83
|
+
# layout file or a frontmatter `layout:` edit changes the chain.
|
|
84
|
+
def clear_template_cache
|
|
85
|
+
@template_mutex.synchronize { @template_cache = {} }
|
|
86
|
+
@deps_mutex.synchronize do
|
|
87
|
+
@shared_deps_mtime = nil
|
|
88
|
+
@layout_chains = {}
|
|
89
|
+
@layout_mtimes = {}
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Lazily compile and cache a template. Safe to call from threads.
|
|
94
|
+
# Uses Erubi with `escape: true` so every `<%= %>` interpolation is
|
|
95
|
+
# auto-escaped; partials emit raw markup via `<%== %>`. See
|
|
96
|
+
# ErbiTemplate for the rationale.
|
|
97
|
+
def compiled_template(path)
|
|
98
|
+
@template_mutex.synchronize do
|
|
99
|
+
@template_cache[path] ||= ErbiTemplate.new(File.read(path, encoding: 'UTF-8'), path)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Most-recent mtime across the global dep set (everything except
|
|
104
|
+
# layout files). When this is newer than a page's output, that
|
|
105
|
+
# output is stale regardless of which layout the page uses.
|
|
106
|
+
#
|
|
107
|
+
# Mutex-protected. `Page#needs_render?` runs inside the parallel
|
|
108
|
+
# render loop, so concurrent threads can race on the first miss —
|
|
109
|
+
# without the mutex they'd each pay the (expensive) directory-
|
|
110
|
+
# walk cost. With it, one thread computes, the rest wait.
|
|
111
|
+
def shared_deps_mtime
|
|
112
|
+
@deps_mutex.synchronize do
|
|
113
|
+
@shared_deps_mtime ||= compute_shared_deps_mtime
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Most-recent mtime across `layout_name`'s file plus every ancestor
|
|
118
|
+
# in its `layout:` chain. Memoised per layout name. Page#needs_render?
|
|
119
|
+
# combines this with `shared_deps_mtime` so editing `layouts/post.html.erb`
|
|
120
|
+
# only invalidates pages that resolve to the `post` layout (or
|
|
121
|
+
# something that extends it), not photo / publication / workshop
|
|
122
|
+
# pages.
|
|
123
|
+
#
|
|
124
|
+
# Mutex-protected for the same reason as `shared_deps_mtime`:
|
|
125
|
+
# called from the parallel render loop, and a torn write of the
|
|
126
|
+
# underlying hash would be observable on Ruby implementations
|
|
127
|
+
# without GIL serialisation (TruffleRuby, JRuby).
|
|
128
|
+
def layout_deps_mtime(layout_name)
|
|
129
|
+
key = layout_name.to_s
|
|
130
|
+
@deps_mutex.synchronize do
|
|
131
|
+
@layout_mtimes[key] ||= compute_layout_deps_mtime(key)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# ----------------------------------------------------------------
|
|
136
|
+
# Generators
|
|
137
|
+
# ----------------------------------------------------------------
|
|
138
|
+
|
|
139
|
+
# Two phases, and the order between them is load-bearing.
|
|
140
|
+
#
|
|
141
|
+
# CONTRIBUTE — generators that add pages which JOIN a collection.
|
|
142
|
+
# `PublisherShowPage` is the case that exists today: Folio
|
|
143
|
+
# publications, bundles and series expose `#collection`, so
|
|
144
|
+
# `Site#collection` merges them with the manual content pages.
|
|
145
|
+
#
|
|
146
|
+
# DERIVE — generators that READ collections and freeze what they
|
|
147
|
+
# find. Pagination slices a collection into `Paginator` objects at
|
|
148
|
+
# generation time; whatever isn't in the collection when that runs
|
|
149
|
+
# is absent from the archive and every shard, permanently.
|
|
150
|
+
#
|
|
151
|
+
# Pagination used to run before publisher pages, so on a Folio site
|
|
152
|
+
# with more manual publications than `per_page`, every Folio-sourced
|
|
153
|
+
# publication silently vanished from the archive — no warning, no
|
|
154
|
+
# error, just missing entries. `Site#finalise_collections!` makes a
|
|
155
|
+
# repeat of that a hard failure instead of a silent one: after the
|
|
156
|
+
# barrier, adding a page that joins a collection raises.
|
|
157
|
+
#
|
|
158
|
+
# Tag pages sit in DERIVE for ordering hygiene, though they read
|
|
159
|
+
# `@pages` (source pages only, see `Site#taxonomy_pages`) and so
|
|
160
|
+
# were never affected by this.
|
|
161
|
+
def generate_all
|
|
162
|
+
generate_publisher_pages
|
|
163
|
+
|
|
164
|
+
@site.finalise_collections!
|
|
165
|
+
|
|
166
|
+
generate_tag_pages
|
|
167
|
+
generate_paginated_pages
|
|
168
|
+
generate_visualizations
|
|
169
|
+
generate_related_pages
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def generate_tag_pages
|
|
173
|
+
@site.taxonomies.each_key do |name|
|
|
174
|
+
@site.posts_by_term(name).each do |term, term_posts|
|
|
175
|
+
@site.add_generated_page(TaxonomyPage.new(name, term, term_posts, @site))
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def generate_visualizations
|
|
181
|
+
@site.visualizations.pages.each { |page| @site.add_generated_page(page) }
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Auto-generate /books/, /bundles/, /series/ index + show pages
|
|
185
|
+
# from an external publisher's data (currently Folio — see
|
|
186
|
+
# `folio:` config). No-op when no publisher is configured. Pages
|
|
187
|
+
# already defined via content/ markdown files take precedence.
|
|
188
|
+
def generate_publisher_pages
|
|
189
|
+
PublisherPages.new(@site).pages.each { |page| @site.add_generated_page(page) }
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Generate `/<source url>related/` index pages for any show-view page
|
|
193
|
+
# whose related list is longer than its visible `limit`.
|
|
194
|
+
def generate_related_pages
|
|
195
|
+
@site.pages.select { |p| p.respond_to?(:collection) && p.collection }.each do |page|
|
|
196
|
+
cfg = @site.collection_config(page.collection).dig('show', 'related') || {}
|
|
197
|
+
next if cfg['enabled'] == false
|
|
198
|
+
|
|
199
|
+
all = @site.related(page)
|
|
200
|
+
visible_limit = cfg.fetch('limit', 3)
|
|
201
|
+
next if all.size <= visible_limit
|
|
202
|
+
|
|
203
|
+
@site.add_generated_page(RelatedIndexPage.new(page, @site, all))
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def generate_paginated_pages
|
|
208
|
+
@site.pages.each do |page|
|
|
209
|
+
# Skip cheaply BEFORE resolving the collection — pages with no
|
|
210
|
+
# `paginate:` key (or `paginate: false`) don't paginate and
|
|
211
|
+
# don't need the collection lookup.
|
|
212
|
+
raw = page.frontmatter['paginate']
|
|
213
|
+
next if raw.nil? || raw == false
|
|
214
|
+
|
|
215
|
+
# Resolve which collection this page paginates. Four signals,
|
|
216
|
+
# first match wins:
|
|
217
|
+
# 1. Pages inside a collection paginate that collection.
|
|
218
|
+
# 2. The index page OF a collection paginates its own collection.
|
|
219
|
+
# 3. Frontmatter `paginate_collection:`.
|
|
220
|
+
# 4. Final fallback: posts.
|
|
221
|
+
coll_name = page.collection ||
|
|
222
|
+
@site.collection_index_name(page) ||
|
|
223
|
+
page.frontmatter['paginate_collection'] ||
|
|
224
|
+
'posts'
|
|
225
|
+
|
|
226
|
+
# Now resolve per_page WITH the collection in scope so
|
|
227
|
+
# `paginate: true` can pick up a per-collection default.
|
|
228
|
+
per_page = resolve_per_page(page, coll_name)
|
|
229
|
+
next unless per_page
|
|
230
|
+
|
|
231
|
+
items = @site.collection(coll_name)
|
|
232
|
+
|
|
233
|
+
slices = items.each_slice(per_page).to_a
|
|
234
|
+
next if slices.size <= 1
|
|
235
|
+
|
|
236
|
+
page.paginator = Paginator.new(
|
|
237
|
+
posts: slices.first,
|
|
238
|
+
page: 1,
|
|
239
|
+
total_pages: slices.size,
|
|
240
|
+
base_url: page.url
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
slices[1..].each_with_index do |slice, idx|
|
|
244
|
+
shard_paginator = Paginator.new(
|
|
245
|
+
posts: slice,
|
|
246
|
+
page: idx + 2,
|
|
247
|
+
total_pages: slices.size,
|
|
248
|
+
base_url: page.url
|
|
249
|
+
)
|
|
250
|
+
@site.add_generated_page(PaginatedShard.new(page, shard_paginator))
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
# ----------------------------------------------------------------
|
|
256
|
+
# Render
|
|
257
|
+
# ----------------------------------------------------------------
|
|
258
|
+
|
|
259
|
+
# Render pages in parallel across CPU cores. ERB rendering does
|
|
260
|
+
# enough I/O (template reads, asset_path lookups, write to disk)
|
|
261
|
+
# that threading helps despite the GIL. For tiny sites the
|
|
262
|
+
# thread-spawn overhead exceeds the benefit, so fall through to a
|
|
263
|
+
# serial loop below the threshold.
|
|
264
|
+
#
|
|
265
|
+
# In incremental mode, pages whose output is up to date are
|
|
266
|
+
# skipped via Page#needs_render?.
|
|
267
|
+
#
|
|
268
|
+
# Scheduling: a `Thread::Queue` work-stealing pool. Earlier slices-
|
|
269
|
+
# based partitioning evenly split the page list, but render cost
|
|
270
|
+
# varies wildly (a post with a TOC, bundle picture, syntax
|
|
271
|
+
# highlighting, and minified output costs far more than a flat tag
|
|
272
|
+
# page) so the slowest slice dominated total time. With a queue,
|
|
273
|
+
# whichever thread finishes its current page picks the next one up
|
|
274
|
+
# immediately.
|
|
275
|
+
def render_pages
|
|
276
|
+
detect_output_collisions!
|
|
277
|
+
|
|
278
|
+
pages = @site.incremental? ? @site.all_pages.select(&:needs_render?) : @site.all_pages
|
|
279
|
+
return if pages.empty?
|
|
280
|
+
|
|
281
|
+
errors = []
|
|
282
|
+
errors_mutex = Mutex.new
|
|
283
|
+
slow_pages = []
|
|
284
|
+
slow_mutex = Mutex.new
|
|
285
|
+
|
|
286
|
+
if pages.size < PARALLEL_THRESHOLD
|
|
287
|
+
pages.each { |page| render_one(page, errors, errors_mutex, slow_pages, slow_mutex) }
|
|
288
|
+
report_slow_pages!(slow_pages)
|
|
289
|
+
return report_render_errors!(errors)
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
queue = Thread::Queue.new
|
|
293
|
+
pages.each { |page| queue << page }
|
|
294
|
+
|
|
295
|
+
thread_count = [Etc.nprocessors, pages.size].min
|
|
296
|
+
threads = Array.new(thread_count) do
|
|
297
|
+
Thread.new do
|
|
298
|
+
loop do
|
|
299
|
+
# `pop(true)` is non-blocking — it raises ThreadError when the
|
|
300
|
+
# queue is empty, which is the worker's signal to exit. This
|
|
301
|
+
# is the work-stealing primitive: every worker keeps pulling
|
|
302
|
+
# until there's nothing left, regardless of how many pages
|
|
303
|
+
# other workers have already finished.
|
|
304
|
+
page = begin
|
|
305
|
+
queue.pop(true)
|
|
306
|
+
rescue ThreadError
|
|
307
|
+
break
|
|
308
|
+
end
|
|
309
|
+
render_one(page, errors, errors_mutex, slow_pages, slow_mutex)
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
threads.each(&:join)
|
|
314
|
+
|
|
315
|
+
report_slow_pages!(slow_pages)
|
|
316
|
+
report_render_errors!(errors)
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
# ----------------------------------------------------------------
|
|
320
|
+
# Post-process
|
|
321
|
+
# ----------------------------------------------------------------
|
|
322
|
+
|
|
323
|
+
def post_process(html, page: nil)
|
|
324
|
+
# `rewrite_bundle_urls` runs before `images.post_process_html` so
|
|
325
|
+
# the latter sees absolute paths (`/posts/foo/hero.jpg`) and can
|
|
326
|
+
# match them against the URL → source registry.
|
|
327
|
+
html = rewrite_bundle_urls(html, page) if page&.respond_to?(:post?) && page.post?
|
|
328
|
+
html = SyntaxHighlighter.process(html) if @site.config['syntax_highlighting']
|
|
329
|
+
html = @site.images.post_process_html(html, page: page) if @site.images.enabled?
|
|
330
|
+
# Plugin filter — runs after the engine's built-in post-processing
|
|
331
|
+
# so plugin output sees the same shape browsers will. Runs BEFORE
|
|
332
|
+
# livereload injection + minification so plugin transformations
|
|
333
|
+
# are minified along with the rest of the page.
|
|
334
|
+
html = Hooks.run_filter(:post_process, html, @site, page)
|
|
335
|
+
html = inject_livereload(html) if @site.env == :development
|
|
336
|
+
html = Minifier.minify(html) if minify_html?
|
|
337
|
+
html
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
# Minify rendered HTML in production by default; disable with
|
|
341
|
+
# `minify: false` in site.yml. Off in development so livereload +
|
|
342
|
+
# view-source stay readable.
|
|
343
|
+
def minify_html?
|
|
344
|
+
return @site.config['minify'] if @site.config.key?('minify')
|
|
345
|
+
|
|
346
|
+
@site.env == :production
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
private
|
|
350
|
+
|
|
351
|
+
# Fail the build when two pages resolve to the same output file.
|
|
352
|
+
# Without this, whichever page the (parallel) render loop writes
|
|
353
|
+
# last silently wins — nondeterministically build-to-build — and
|
|
354
|
+
# the sitemap emits a duplicate <loc>. Common causes: two post
|
|
355
|
+
# directories whose names differ only by the stripped `YYYY-MM-DD-`
|
|
356
|
+
# date prefix, two pages sharing a `permalink:`, or two taxonomy
|
|
357
|
+
# terms that slugify to the same value. Runs over the FULL page set
|
|
358
|
+
# (not just `needs_render?`) so a collision is caught even on an
|
|
359
|
+
# incremental rebuild that only touches one side of it.
|
|
360
|
+
def detect_output_collisions!
|
|
361
|
+
by_path = Hash.new { |h, k| h[k] = [] }
|
|
362
|
+
@site.all_pages.each do |page|
|
|
363
|
+
next unless page.respond_to?(:output_path)
|
|
364
|
+
|
|
365
|
+
by_path[page.output_path] << page
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
collisions = by_path.select { |_, pages| pages.size > 1 }
|
|
369
|
+
return if collisions.empty?
|
|
370
|
+
|
|
371
|
+
details = collisions.map do |path, pages|
|
|
372
|
+
sources = pages.map { |p| page_identifier(p) }.sort
|
|
373
|
+
" #{path}\n <- #{sources.join("\n <- ")}"
|
|
374
|
+
end.join("\n")
|
|
375
|
+
raise "output path collision: #{collisions.size} output file(s) claimed by more than " \
|
|
376
|
+
"one page. Rename or re-slug the sources:\n#{details}"
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def page_identifier(page)
|
|
380
|
+
if page.respond_to?(:source_path) && page.source_path
|
|
381
|
+
page.source_path
|
|
382
|
+
elsif page.respond_to?(:url) && page.url
|
|
383
|
+
page.url
|
|
384
|
+
else
|
|
385
|
+
page.class.name
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
# Render a single page, collecting any exception into `errors` so a
|
|
390
|
+
# failure in one page doesn't silently kill an entire slice. The
|
|
391
|
+
# default Thread behaviour is to re-raise on join — but only for the
|
|
392
|
+
# FIRST thread that raised; later threads' errors disappear.
|
|
393
|
+
# Collecting explicitly gives us a full report at the end.
|
|
394
|
+
#
|
|
395
|
+
# Also times each render and surfaces a warning when it crosses
|
|
396
|
+
# `SLOW_PAGE_THRESHOLD_MS`. Slow pages are collected for the
|
|
397
|
+
# end-of-build summary.
|
|
398
|
+
def render_one(page, errors, mutex, slow_pages = nil, slow_mutex = nil)
|
|
399
|
+
t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
400
|
+
page.write
|
|
401
|
+
elapsed_ms = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - t0) * 1000).round
|
|
402
|
+
|
|
403
|
+
return unless slow_page?(elapsed_ms) && slow_pages && slow_mutex
|
|
404
|
+
|
|
405
|
+
causes = infer_slow_causes(page)
|
|
406
|
+
Log.warn(slow_page_note(page, elapsed_ms, causes))
|
|
407
|
+
slow_mutex.synchronize { slow_pages << { page: page, ms: elapsed_ms, causes: causes } }
|
|
408
|
+
rescue StandardError, PathSafe::Error => e
|
|
409
|
+
# Generated pages (TaxonomyPage, PaginatedShard, PublisherShowPage)
|
|
410
|
+
# don't have a `source_path` — they synthesise URLs without a
|
|
411
|
+
# backing markdown file. Fall back to the URL (or class name) so
|
|
412
|
+
# the error report is still attributable.
|
|
413
|
+
identifier = if page.respond_to?(:source_path) && page.source_path
|
|
414
|
+
page.source_path
|
|
415
|
+
elsif page.respond_to?(:url) && page.url
|
|
416
|
+
page.url
|
|
417
|
+
else
|
|
418
|
+
page.class.name
|
|
419
|
+
end
|
|
420
|
+
mutex.synchronize { errors << [identifier, e] }
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
# Did this page cross the slow threshold? Disabled when the
|
|
424
|
+
# threshold is set to 0 (operator opted out via env var).
|
|
425
|
+
def slow_page?(elapsed_ms)
|
|
426
|
+
SLOW_PAGE_THRESHOLD_MS.positive? && elapsed_ms >= SLOW_PAGE_THRESHOLD_MS
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
# Cause catalogue. Each entry has:
|
|
430
|
+
#
|
|
431
|
+
# label: short string for the inline warning + summary header
|
|
432
|
+
# impact: one-sentence explanation of WHY this signal causes
|
|
433
|
+
# slow renders — what work the engine does proportional
|
|
434
|
+
# to it.
|
|
435
|
+
# advice: one-sentence suggestion the operator can act on.
|
|
436
|
+
#
|
|
437
|
+
# The point is to turn a generic "your page is slow" into a
|
|
438
|
+
# specific "here's why, and here's what to try." The summary at
|
|
439
|
+
# end-of-build prints one impact + advice block per cause type
|
|
440
|
+
# that fired across the slow page set (deduped, so the operator
|
|
441
|
+
# reads each explanation once even if ten pages share the same
|
|
442
|
+
# cause).
|
|
443
|
+
SLOW_PAGE_CAUSES = {
|
|
444
|
+
large_output: {
|
|
445
|
+
label: ->(meta) { "#{meta[:kb]} KB output" },
|
|
446
|
+
impact: 'HTML minification and any plugin `:post_process` filters scan the whole document — cost scales with output size.',
|
|
447
|
+
advice: 'Trim the body, split into multiple pages, or set `minify: false` if the site doesn\'t need minified output.'
|
|
448
|
+
},
|
|
449
|
+
many_images: {
|
|
450
|
+
label: ->(meta) { "#{meta[:count]} inline images" },
|
|
451
|
+
impact: 'Every `<img>` is matched against the image-pipeline URL registry and rewritten to a responsive `<picture>` block. Per-tag cost is small; it adds up.',
|
|
452
|
+
advice: 'Reduce images on this page, move large galleries to their own page, or set `images.optimise: false` site-wide if the pipeline isn\'t needed.'
|
|
453
|
+
},
|
|
454
|
+
many_code_blocks: {
|
|
455
|
+
label: ->(meta) { "#{meta[:count]} code blocks" },
|
|
456
|
+
impact: 'Rouge tokenises every `<pre>` block separately — long examples and many small blocks both add measurable time.',
|
|
457
|
+
advice: 'Shorten code examples, link to a gist for the long ones, or set `syntax_highlighting: false` site-wide if you don\'t need it.'
|
|
458
|
+
},
|
|
459
|
+
toc: {
|
|
460
|
+
label: ->(_) { 'TOC' },
|
|
461
|
+
impact: 'The TOC partial scans the rendered body for h2/h3 headings on every render. Small per page; meaningful when the body is long.',
|
|
462
|
+
advice: 'Set `toc: false` in the page\'s frontmatter to skip the TOC for one page, or raise `posts.show.toc.min_headings` to skip shorter pages globally.'
|
|
463
|
+
},
|
|
464
|
+
plugin_filter: {
|
|
465
|
+
label: ->(_) { 'plugin filter' },
|
|
466
|
+
impact: 'A plugin registered against the `:post_process` hook transforms the rendered HTML — the engine can\'t see inside the plugin code.',
|
|
467
|
+
advice: 'Profile the offending plugin in `plugins/*.rb`, or temporarily disable it (rename to `*.rb.off`) to confirm it\'s the bottleneck.'
|
|
468
|
+
}
|
|
469
|
+
}.freeze
|
|
470
|
+
|
|
471
|
+
# Human-readable slow-page warning emitted in real-time. Stays
|
|
472
|
+
# one line so it scans cleanly in CI logs; the end-of-build
|
|
473
|
+
# summary is where the rich impact + advice goes.
|
|
474
|
+
def slow_page_note(page, elapsed_ms, causes)
|
|
475
|
+
url = page.respond_to?(:url) && page.url ? page.url : page.source_path.to_s
|
|
476
|
+
cause_str = causes.empty? ? '' : " — #{causes.map { |c| c[:label] }.join(' · ')}"
|
|
477
|
+
"Slow page: #{url} took #{format_ms(elapsed_ms)}#{cause_str}"
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
# Sample cheap heuristics that often correlate with slow renders.
|
|
481
|
+
# Re-reads the just-written output once (only fires for pages
|
|
482
|
+
# that already crossed the threshold, so cost is bounded by the
|
|
483
|
+
# slow-page count, not the build size).
|
|
484
|
+
#
|
|
485
|
+
# Returns an array of `{type:, label:}` hashes — `type` is the
|
|
486
|
+
# cause-catalogue key, `label` is the populated short string for
|
|
487
|
+
# the inline warning. The summary uses `type` to look up the
|
|
488
|
+
# full impact + advice from `SLOW_PAGE_CAUSES`.
|
|
489
|
+
def infer_slow_causes(page)
|
|
490
|
+
causes = []
|
|
491
|
+
return causes unless page.respond_to?(:output_path)
|
|
492
|
+
path = page.output_path
|
|
493
|
+
return causes unless File.exist?(path)
|
|
494
|
+
|
|
495
|
+
size_kb = (File.size(path) / 1024.0).round
|
|
496
|
+
causes << build_cause(:large_output, kb: size_kb) if size_kb >= 200
|
|
497
|
+
|
|
498
|
+
html = File.read(path, encoding: 'UTF-8')
|
|
499
|
+
img_count = html.scan(/<img\b/i).size
|
|
500
|
+
causes << build_cause(:many_images, count: img_count) if img_count >= 20
|
|
501
|
+
code_count = html.scan(/<pre\b/i).size
|
|
502
|
+
causes << build_cause(:many_code_blocks, count: code_count) if code_count >= 10
|
|
503
|
+
causes << build_cause(:toc) if html.include?('class="toc"') || html.include?("class='toc'")
|
|
504
|
+
causes << build_cause(:plugin_filter) if Hooks.registered_events.include?(:post_process)
|
|
505
|
+
causes
|
|
506
|
+
rescue StandardError
|
|
507
|
+
# Cause inference is best-effort — never let a probe failure
|
|
508
|
+
# mask the slow-page warning itself.
|
|
509
|
+
causes
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
def build_cause(type, **meta)
|
|
513
|
+
{ type: type, label: SLOW_PAGE_CAUSES[type][:label].call(meta) }
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
# End-of-build slow-page summary. Three parts:
|
|
517
|
+
#
|
|
518
|
+
# 1. Header — count of slow pages and the threshold that fired.
|
|
519
|
+
# 2. Per-page list (slowest first, top 5) — URL, time,
|
|
520
|
+
# cause labels.
|
|
521
|
+
# 3. "What this means + what to try" block — one entry per
|
|
522
|
+
# unique cause type, deduped across all slow pages, so the
|
|
523
|
+
# operator sees each explanation once.
|
|
524
|
+
#
|
|
525
|
+
# Goal: when the operator reads the summary they know exactly
|
|
526
|
+
# what's expensive on which pages AND what knob to turn.
|
|
527
|
+
def report_slow_pages!(slow_pages)
|
|
528
|
+
return if slow_pages.empty?
|
|
529
|
+
|
|
530
|
+
slow_pages.sort_by! { |sp| -sp[:ms] }
|
|
531
|
+
Log.info("Slow pages (>#{SLOW_PAGE_THRESHOLD_MS}ms): #{slow_pages.size}")
|
|
532
|
+
slow_pages.first(5).each do |sp|
|
|
533
|
+
url = sp[:page].respond_to?(:url) && sp[:page].url ? sp[:page].url : sp[:page].source_path
|
|
534
|
+
cause_str = sp[:causes].empty? ? '' : " (#{sp[:causes].map { |c| c[:label] }.join(' · ')})"
|
|
535
|
+
Log.info(" #{format_ms(sp[:ms]).rjust(7)} #{url}#{cause_str}")
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
report_slow_page_explanations!(slow_pages)
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
# Unique cause types across the slow set, each printed with its
|
|
542
|
+
# impact + advice from SLOW_PAGE_CAUSES. Order follows
|
|
543
|
+
# SLOW_PAGE_CAUSES declaration order (broadest causes first, then
|
|
544
|
+
# narrower ones). Silent when no causes were inferred.
|
|
545
|
+
def report_slow_page_explanations!(slow_pages)
|
|
546
|
+
triggered_types = slow_pages.flat_map { |sp| sp[:causes].map { |c| c[:type] } }.uniq
|
|
547
|
+
ordered_types = SLOW_PAGE_CAUSES.keys & triggered_types
|
|
548
|
+
return if ordered_types.empty?
|
|
549
|
+
|
|
550
|
+
Log.info('')
|
|
551
|
+
Log.info('What this means and what to try:')
|
|
552
|
+
ordered_types.each do |type|
|
|
553
|
+
entry = SLOW_PAGE_CAUSES[type]
|
|
554
|
+
Log.info(" #{type}:")
|
|
555
|
+
Log.info(" #{entry[:impact]}")
|
|
556
|
+
Log.info(" Try: #{entry[:advice]}")
|
|
557
|
+
end
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
# Compact ms / s formatter. `850ms`, `1.2s`, `12.4s`.
|
|
561
|
+
def format_ms(ms)
|
|
562
|
+
ms < 1000 ? "#{ms}ms" : format('%.1fs', ms / 1000.0)
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
def report_render_errors!(errors)
|
|
566
|
+
return if errors.empty?
|
|
567
|
+
|
|
568
|
+
errors.each do |path, e|
|
|
569
|
+
Log.error "render failed: #{path} — #{e.class}: #{e.message}"
|
|
570
|
+
e.backtrace&.first(5)&.each { |line| Log.error " #{line}" }
|
|
571
|
+
end
|
|
572
|
+
raise "#{errors.size} page(s) failed to render"
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
def compute_shared_deps_mtime
|
|
576
|
+
roots = [@site.site_root, @site.engine_root].uniq
|
|
577
|
+
|
|
578
|
+
# Static globs (anchored, no per-site resolution).
|
|
579
|
+
patterns = GLOBAL_DEP_GLOBS.dup
|
|
580
|
+
|
|
581
|
+
# Active-theme glob — only walk the theme this site is actually
|
|
582
|
+
# using. Without scoping, every build walks every theme the gem
|
|
583
|
+
# ships (bootstrap, magazine, notebook, sand, …), most of which
|
|
584
|
+
# have nothing to do with the current site's rendered output.
|
|
585
|
+
theme = @site.config['theme'].to_s
|
|
586
|
+
patterns << File.join('themes', theme, '**', '*') unless theme.empty? || theme == 'none'
|
|
587
|
+
|
|
588
|
+
mtimes = patterns.flat_map do |pattern|
|
|
589
|
+
roots.flat_map do |root|
|
|
590
|
+
# No `.sort` — we feed every entry into `.max` below, which is
|
|
591
|
+
# order-invariant. Sorting would just add overhead.
|
|
592
|
+
Dir.glob(File.join(root, pattern)).map do |path|
|
|
593
|
+
File.mtime(path)
|
|
594
|
+
rescue StandardError
|
|
595
|
+
Time.at(0)
|
|
596
|
+
end
|
|
597
|
+
end
|
|
598
|
+
end
|
|
599
|
+
mtimes.compact.max || Time.at(0)
|
|
600
|
+
end
|
|
601
|
+
|
|
602
|
+
# Most-recent mtime across the layout file plus every ancestor
|
|
603
|
+
# layout it chains into. Returns Time.at(0) when the layout file
|
|
604
|
+
# can't be found — Page#needs_render? then falls through to the
|
|
605
|
+
# global mtime and source mtime checks.
|
|
606
|
+
def compute_layout_deps_mtime(layout_name)
|
|
607
|
+
chain = layout_chain(layout_name)
|
|
608
|
+
return Time.at(0) if chain.empty?
|
|
609
|
+
|
|
610
|
+
chain.map do |path|
|
|
611
|
+
File.mtime(path)
|
|
612
|
+
rescue StandardError
|
|
613
|
+
Time.at(0)
|
|
614
|
+
end.max
|
|
615
|
+
end
|
|
616
|
+
|
|
617
|
+
# Walk the `layout:` chain starting at `layout_name`, returning the
|
|
618
|
+
# absolute paths of every layout file in the chain. Memoised per
|
|
619
|
+
# name. Cycle-safe — a layout that (illegally) extends itself
|
|
620
|
+
# transitively stops at the second visit.
|
|
621
|
+
#
|
|
622
|
+
# No internal locking — the only caller is
|
|
623
|
+
# `compute_layout_deps_mtime`, which runs under `@deps_mutex` (see
|
|
624
|
+
# `layout_deps_mtime`). Adding a lock here would deadlock.
|
|
625
|
+
def layout_chain(layout_name)
|
|
626
|
+
@layout_chains[layout_name] ||= build_layout_chain(layout_name)
|
|
627
|
+
end
|
|
628
|
+
|
|
629
|
+
def build_layout_chain(layout_name)
|
|
630
|
+
chain = []
|
|
631
|
+
current = layout_name
|
|
632
|
+
seen = {}
|
|
633
|
+
|
|
634
|
+
while current && !seen[current]
|
|
635
|
+
seen[current] = true
|
|
636
|
+
path = @site.find_in_paths(File.join('app', 'views', 'layouts', "#{current}.html.erb"))
|
|
637
|
+
break unless File.exist?(path)
|
|
638
|
+
|
|
639
|
+
chain << path
|
|
640
|
+
current = parent_layout_of(path)
|
|
641
|
+
end
|
|
642
|
+
|
|
643
|
+
chain
|
|
644
|
+
end
|
|
645
|
+
|
|
646
|
+
# Read just the YAML frontmatter from a layout file (if any) and
|
|
647
|
+
# return its `layout:` key — the parent in the chain — or nil.
|
|
648
|
+
# Layouts without frontmatter, or with empty `layout:`, terminate
|
|
649
|
+
# the chain.
|
|
650
|
+
#
|
|
651
|
+
# Failures are not silently swallowed. A YAML syntax error in a
|
|
652
|
+
# layout's frontmatter used to be treated as "no parent" — the
|
|
653
|
+
# page rendered against the wrong outer layout, and the operator
|
|
654
|
+
# got no signal that the chain was broken. Re-raise so the build
|
|
655
|
+
# fails loudly with a clear message; the layout path is wrapped
|
|
656
|
+
# into the exception so the operator can find the offending file
|
|
657
|
+
# without grepping.
|
|
658
|
+
def parent_layout_of(path)
|
|
659
|
+
raw = File.read(path, encoding: 'UTF-8')
|
|
660
|
+
match = raw.match(LAYOUT_FRONTMATTER_RE)
|
|
661
|
+
return nil unless match
|
|
662
|
+
|
|
663
|
+
fm = YAML.safe_load(match[1], permitted_classes: Abqari::YAML_PERMITTED_CLASSES) || {}
|
|
664
|
+
parent = fm['layout']
|
|
665
|
+
parent && !parent.to_s.empty? ? parent.to_s : nil
|
|
666
|
+
rescue Psych::SyntaxError => e
|
|
667
|
+
raise "invalid YAML frontmatter in layout #{path}: #{e.message}"
|
|
668
|
+
rescue StandardError => e
|
|
669
|
+
raise "failed to read layout frontmatter in #{path}: #{e.class}: #{e.message}"
|
|
670
|
+
end
|
|
671
|
+
|
|
672
|
+
# Resolve the page-size for a paginating page, or nil for "don't paginate."
|
|
673
|
+
#
|
|
674
|
+
# Frontmatter:
|
|
675
|
+
# paginate: 25 → 25 posts per page (explicit override)
|
|
676
|
+
# paginate: true → fall back through the config chain
|
|
677
|
+
# paginate: false → no pagination (overrides any default)
|
|
678
|
+
# paginate: <0/nil> → no pagination
|
|
679
|
+
#
|
|
680
|
+
# Fallback chain when `paginate: true` (in priority order):
|
|
681
|
+
# 1. `collections.<coll_name>.pagination.per_page` — per-collection
|
|
682
|
+
# override for the collection this page paginates. Lets a site
|
|
683
|
+
# use 12 photos per page but 10 posts without setting
|
|
684
|
+
# `paginate: N` on every archive file.
|
|
685
|
+
# 2. `pagination.per_page` — site-wide global default.
|
|
686
|
+
# 3. PAGINATION_DEFAULT (10) — engine fallback.
|
|
687
|
+
#
|
|
688
|
+
# `coll_name` is optional for back-compat — when omitted (or nil),
|
|
689
|
+
# the lookup skips the per-collection layer and goes straight to
|
|
690
|
+
# the global default. The build's main path
|
|
691
|
+
# (`generate_paginated_pages`) always supplies it.
|
|
692
|
+
def resolve_per_page(page, coll_name = nil)
|
|
693
|
+
raw = page.frontmatter['paginate']
|
|
694
|
+
return nil if raw == false
|
|
695
|
+
return nil if raw.nil?
|
|
696
|
+
|
|
697
|
+
if raw.is_a?(Integer)
|
|
698
|
+
raw.positive? ? raw : nil
|
|
699
|
+
elsif raw == true
|
|
700
|
+
configured_per_page(coll_name)
|
|
701
|
+
else
|
|
702
|
+
# A quoted `paginate: "10"` (String) or any other non-Integer,
|
|
703
|
+
# non-boolean value silently disabled pagination. Warn so the
|
|
704
|
+
# typo is visible.
|
|
705
|
+
src = page.respond_to?(:source_path) ? page.source_path : page
|
|
706
|
+
Log.warn "Ignoring `paginate: #{raw.inspect}` in #{src} — expected true, false, or a positive integer."
|
|
707
|
+
nil
|
|
708
|
+
end
|
|
709
|
+
end
|
|
710
|
+
|
|
711
|
+
def configured_per_page(coll_name = nil)
|
|
712
|
+
if coll_name
|
|
713
|
+
per_coll = @site.config.dig('collections', coll_name, 'pagination', 'per_page')
|
|
714
|
+
return per_coll if per_coll.is_a?(Integer) && per_coll.positive?
|
|
715
|
+
end
|
|
716
|
+
|
|
717
|
+
configured = @site.config.dig('pagination', 'per_page')
|
|
718
|
+
configured.is_a?(Integer) && configured.positive? ? configured : PAGINATION_DEFAULT
|
|
719
|
+
end
|
|
720
|
+
|
|
721
|
+
# Rewrite relative <img>/<a> URLs in a post bundle to absolute paths
|
|
722
|
+
# under the post's URL. So `<img src="hero.jpg">` in a bundle for
|
|
723
|
+
# /posts/foo/ becomes `<img src="/posts/foo/hero.jpg">`.
|
|
724
|
+
def rewrite_bundle_urls(html, page)
|
|
725
|
+
base = page.url
|
|
726
|
+
|
|
727
|
+
html.gsub(/(<(?:img|a)\s+[^>]*?(?:src|href)=")([^"]+)/) do
|
|
728
|
+
prefix = ::Regexp.last_match(1)
|
|
729
|
+
url = ::Regexp.last_match(2)
|
|
730
|
+
|
|
731
|
+
if url.start_with?('http://', 'https://', '/', '#', 'mailto:', 'tel:', 'data:')
|
|
732
|
+
"#{prefix}#{url}"
|
|
733
|
+
else
|
|
734
|
+
"#{prefix}#{base}#{url}"
|
|
735
|
+
end
|
|
736
|
+
end
|
|
737
|
+
end
|
|
738
|
+
|
|
739
|
+
# Livereload client. Uses Server-Sent Events to receive rebuild
|
|
740
|
+
# events from the dev server as they happen — sub-50 ms latency
|
|
741
|
+
# vs the ~250 ms median of the old polling implementation. The
|
|
742
|
+
# browser opens a single persistent EventSource connection per
|
|
743
|
+
# tab; the server holds it open and pushes a `{version, scope}`
|
|
744
|
+
# JSON payload on every rebuild.
|
|
745
|
+
#
|
|
746
|
+
# Reconnect logic is provided by EventSource itself — if the
|
|
747
|
+
# server restarts the client auto-reconnects after a short delay.
|
|
748
|
+
LIVERELOAD_SCRIPT = <<~SCRIPT
|
|
749
|
+
<script>
|
|
750
|
+
(function() {
|
|
751
|
+
let firstVersion = null;
|
|
752
|
+
async function swapCss() {
|
|
753
|
+
const html = await fetch(location.pathname, { cache: 'no-store' }).then(r => r.text());
|
|
754
|
+
const matches = [...html.matchAll(/<link\\s+rel="stylesheet"\\s+href="([^"]+)"/gi)].map(m => m[1]);
|
|
755
|
+
document.querySelectorAll('link[rel="stylesheet"]').forEach((link, i) => {
|
|
756
|
+
if (matches[i] && link.getAttribute('href') !== matches[i]) {
|
|
757
|
+
link.setAttribute('href', matches[i]);
|
|
758
|
+
}
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
const sse = new EventSource('/__reload__');
|
|
762
|
+
sse.onmessage = (e) => {
|
|
763
|
+
try {
|
|
764
|
+
const { version, scope } = JSON.parse(e.data);
|
|
765
|
+
if (firstVersion === null) { firstVersion = version; return; }
|
|
766
|
+
if (version === firstVersion) return;
|
|
767
|
+
firstVersion = version;
|
|
768
|
+
scope === 'css' ? swapCss() : location.reload();
|
|
769
|
+
} catch (err) {}
|
|
770
|
+
};
|
|
771
|
+
})();
|
|
772
|
+
</script>
|
|
773
|
+
SCRIPT
|
|
774
|
+
|
|
775
|
+
# Insert the livereload poller just before the closing body tag.
|
|
776
|
+
# HTML is case-insensitive, so the match has to be too — a layout
|
|
777
|
+
# that closes with `</Body>` is legal markup and should still
|
|
778
|
+
# hot-reload in dev. The substitution preserves the original
|
|
779
|
+
# casing of the matched tag.
|
|
780
|
+
CLOSING_BODY_RE = %r{</body>}i.freeze
|
|
781
|
+
|
|
782
|
+
def inject_livereload(html)
|
|
783
|
+
return html unless html.match?(CLOSING_BODY_RE)
|
|
784
|
+
|
|
785
|
+
html.sub(CLOSING_BODY_RE) { |match| "#{LIVERELOAD_SCRIPT}#{match}" }
|
|
786
|
+
end
|
|
787
|
+
end
|
|
788
|
+
end
|