j1-template 2022.5.2 → 2022.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/_includes/themes/j1/layouts/content_generator_news_panel_posts.html +61 -40
- data/_includes/themes/j1/layouts/content_generator_page.html +22 -22
- data/_includes/themes/j1/layouts/content_generator_post.html +1 -1
- data/_includes/themes/j1/layouts/layout_metadata_generator.html +13 -79
- data/_includes/themes/j1/{blocks → procedures/blocks}/footer/boxes/about_box.proc +0 -0
- data/_includes/themes/j1/{blocks → procedures/blocks}/footer/boxes/contacts_box.proc +0 -0
- data/_includes/themes/j1/{blocks → procedures/blocks}/footer/boxes/issue.proc +0 -0
- data/_includes/themes/j1/{blocks → procedures/blocks}/footer/boxes/legal_statements.proc +0 -0
- data/_includes/themes/j1/{blocks → procedures/blocks}/footer/boxes/links_box.proc +0 -0
- data/_includes/themes/j1/{blocks → procedures/blocks}/footer/boxes/news_box.proc +0 -0
- data/_includes/themes/j1/{blocks → procedures/blocks}/footer/boxes/social_media_icons.proc +0 -0
- data/_includes/themes/j1/procedures/blocks/get_wave.proc +211 -0
- data/_includes/themes/j1/procedures/collections/create_collection_article_preview.proc +1 -1
- data/_includes/themes/j1/procedures/global/create_word_cloud.proc +1 -1
- data/_includes/themes/j1/procedures/posts/collate_timeline.proc +2 -2
- data/_includes/themes/j1/procedures/posts/pager.proc +9 -10
- data/_layouts/default.html +5 -1
- data/apps/private/README.txt +1 -0
- data/apps/protected/README.txt +1 -0
- data/apps/public/README.txt +1 -0
- data/assets/data/banner.html +38 -8
- data/assets/data/footer.html +31 -11
- data/assets/data/panel.html +118 -27
- data/assets/themes/j1/adapter/js/attic.js +4 -4
- data/assets/themes/j1/adapter/js/comments.js +18 -7
- data/assets/themes/j1/adapter/js/waves.js +227 -0
- data/assets/themes/j1/core/css/icon-fonts/fontawesome.min.css +1 -1
- data/assets/themes/j1/core/css/icon-fonts/mdi.min.css +1 -1
- data/assets/themes/j1/core/css/icon-fonts/mdil.min.css +1 -1
- data/assets/themes/j1/core/css/themes/bootstrap/bootstrap.css +92 -74
- data/assets/themes/j1/core/css/themes/bootstrap/bootstrap.min.css +5 -3
- data/assets/themes/j1/core/css/themes/theme_vapor/bootstrap.css +92 -74
- data/assets/themes/j1/core/css/themes/theme_vapor/bootstrap.min.css +5 -3
- data/assets/themes/j1/core/css/themes/unodark/bootstrap.css +105 -138
- data/assets/themes/j1/core/css/themes/unodark/bootstrap.min.css +5 -3
- data/assets/themes/j1/core/css/themes/unolight/bootstrap.css +457 -262
- data/assets/themes/j1/core/css/themes/unolight/bootstrap.min.css +26 -15
- data/assets/themes/j1/core/css/vendor.css +11 -8
- data/assets/themes/j1/core/css/vendor.min.css +1 -1
- data/assets/themes/j1/core/fonts/fontawesome_5/LICENSE.txt +34 -0
- data/assets/themes/j1/core/fonts/material_design_icons/LICENSE.txt +97 -0
- data/assets/themes/j1/core/fonts/material_design_icons_light/LICENSE.txt +92 -0
- data/assets/themes/j1/core/fonts/roboto/LICENSE.txt +11 -0
- data/assets/themes/j1/core/js/template.js +419 -746
- data/assets/themes/j1/core/js/template.min.js.map +1 -1
- data/assets/themes/j1/modules/backstretch/js/backstretch.js +1 -1
- data/assets/themes/j1/modules/backstretch/js/backstretch.min.js +1 -1
- data/assets/themes/j1/modules/bokeh/LICENSE.txt +28 -0
- data/assets/themes/j1/modules/jquery/js/extensions/hasClass.js +17 -0
- data/assets/themes/j1/modules/jquery/js/extensions/hasClass.min.js +17 -0
- data/assets/themes/j1/modules/jquery/js/extensions/removeClass.js +18 -0
- data/assets/themes/j1/modules/jquery/js/extensions/removeClass.min.js +17 -0
- data/assets/themes/j1/modules/later/LICENSE.txt +21 -0
- data/assets/themes/j1/modules/log4javascript/license.txt +201 -0
- data/assets/themes/j1/modules/lunr/stopwords/de.txt +229 -0
- data/assets/themes/j1/modules/lunr/stopwords/en.txt +119 -0
- data/assets/themes/j1/modules/masterslider/LICENSE.txt +621 -0
- data/assets/themes/j1/modules/masterslider/README.txt +531 -0
- data/assets/themes/j1/modules/msDropdown/LICENSE.txt +20 -0
- data/assets/themes/j1/modules/nbinteract-core/LICENSE.txt +60 -0
- data/assets/themes/j1/modules/rouge/css/themes.txt +46 -0
- data/assets/themes/j1/modules/vega/LICENSE.txt +27 -0
- data/lib/j1/version.rb +1 -1
- data/lib/starter_web/Gemfile +11 -7
- data/lib/starter_web/README.md +5 -5
- data/lib/starter_web/_config.yml +199 -135
- data/lib/starter_web/_data/blocks/banner.yml +18 -2
- data/lib/starter_web/_data/blocks/defaults/footer.yml +3 -1
- data/lib/starter_web/_data/blocks/defaults/panel.yml +4 -0
- data/lib/starter_web/_data/blocks/footer.yml +12 -1
- data/lib/starter_web/_data/blocks/panel.yml +88 -19
- data/lib/starter_web/_data/j1_config.yml +2 -2
- data/lib/starter_web/_data/layouts/collection.yml +0 -9
- data/lib/starter_web/_data/layouts/home.yml +21 -30
- data/lib/starter_web/_data/layouts/news_panel_posts.yml +0 -9
- data/lib/starter_web/_data/layouts/page.yml +0 -9
- data/lib/starter_web/_data/layouts/post.yml +0 -9
- data/lib/starter_web/_data/modules/blog_navigator.yml +6 -0
- data/lib/starter_web/_data/modules/defaults/blog_navigator.yml +15 -8
- data/lib/starter_web/_data/modules/defaults/cookieconsent.yml +5 -4
- data/lib/starter_web/_data/modules/defaults/navigator.yml +1 -1
- data/lib/starter_web/_data/modules/defaults/waves.yml +32 -0
- data/lib/starter_web/_data/modules/navigator_menu.yml +48 -120
- data/lib/starter_web/_data/modules/waves.yml +32 -0
- data/lib/starter_web/_data/plugins/defaults/feed.yml +82 -0
- data/lib/starter_web/_data/plugins/defaults/seo-tags.yml +65 -0
- data/lib/starter_web/_data/plugins/defaults/sitemap.yml +66 -0
- data/lib/starter_web/_data/plugins/feed.yml +35 -0
- data/lib/starter_web/_data/plugins/seo-tags.yml +30 -0
- data/lib/starter_web/_data/plugins/sitemap.yml +30 -0
- data/lib/starter_web/_data/resources.yml +22 -0
- data/lib/starter_web/_data/templates/feed.xml +191 -0
- data/lib/starter_web/_data/templates/robots.txt +1 -0
- data/lib/starter_web/_data/templates/seo-tags.html +140 -0
- data/lib/starter_web/_data/templates/sitemap.xml +36 -0
- data/lib/starter_web/_includes/attributes.asciidoc +49 -47
- data/lib/starter_web/_includes/custom/static/bs5_accordion.html +84 -0
- data/lib/starter_web/_includes/custom/templates/bs5_accordion.html +103 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/admonition-block-answer.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/admonition-block-question.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/banner.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/callout.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/carousel-block.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/conum.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/fab-icon-inline.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/fas-icon-inline.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/flag-icon-inline.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/gallery-block.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/gist-block.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/iconify-icon-inline.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/lightbox-block.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/lorem_inline.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/masterslider-block.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/mdi-icon-inline.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/panel.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/range-slider-block.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/shout-block.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/textbook-block.rb +0 -0
- data/lib/starter_web/_plugins/{asciidoctor-extensions → asciidoctor}/twitter-emoji-inline.rb +0 -0
- data/lib/starter_web/_plugins/{debug.rb → filter/debug.rb} +0 -0
- data/lib/starter_web/_plugins/{encodeBase64.rb → filter/encodeBase64.rb} +0 -0
- data/lib/starter_web/_plugins/{encryptAES.rb → filter/encryptAES.rb} +0 -0
- data/lib/starter_web/_plugins/{filters.rb → filter/filters.rb} +11 -0
- data/lib/starter_web/_plugins/{minifyJS.rb → filter/minifyJS.rb} +0 -0
- data/lib/starter_web/_plugins/{minifyJSON.rb → filter/minifyJSON.rb} +0 -0
- data/lib/starter_web/_plugins/{prettify.rb → filter/prettify.rb} +0 -0
- data/lib/starter_web/_plugins/filter/xml_prettify.rb +36 -0
- data/lib/starter_web/_plugins/{symlink_watcher.rb → helper/symlink_watcher.rb} +0 -0
- data/lib/starter_web/_plugins/{date-i18n.rb → i18n/date.rb} +1 -1
- data/lib/starter_web/_plugins/{lunr_index.rb → index/lunr.rb} +38 -35
- data/lib/starter_web/_plugins/seo/j1-feed.rb +268 -0
- data/lib/starter_web/_plugins/seo/j1-seo-tags.rb +717 -0
- data/lib/starter_web/_plugins/seo/j1-sitemap.rb +140 -0
- data/lib/starter_web/assets/images/banner/scalable/wave.svg +13 -0
- data/lib/starter_web/assets/images/blocks/waves/scalable/1280x100/wave-1.svg +63 -0
- data/lib/starter_web/assets/images/blocks/waves/scalable/1280x100/wave-2.svg +60 -0
- data/lib/starter_web/assets/images/blocks/waves/scalable/1280x100/wave-3.svg +64 -0
- data/lib/starter_web/assets/images/blocks/waves/scalable/1280x100/wave-4.svg +62 -0
- data/lib/starter_web/assets/images/blocks/waves/scalable/1920x100/wave-1.svg +64 -0
- data/lib/starter_web/assets/images/blocks/waves/scalable/1920x100/wave-2.svg +60 -0
- data/lib/starter_web/assets/images/blocks/waves/scalable/1920x100/wave-3.svg +65 -0
- data/lib/starter_web/assets/images/blocks/waves/scalable/1920x100/wave-4.svg +62 -0
- data/lib/starter_web/assets/images/collections/blog/featured/dynamic-web-access.png +0 -0
- data/lib/starter_web/assets/images/collections/blog/featured/jamstack-generators.png +0 -0
- data/lib/starter_web/assets/images/collections/blog/featured/static-web-access.png +0 -0
- data/lib/starter_web/assets/images/icons/jekyll/logo-2x.png +0 -0
- data/lib/starter_web/assets/images/icons/jekyll/octojekyll.png +0 -0
- data/lib/starter_web/assets/images/modules/attics/1280x800/j1-template.png +0 -0
- data/lib/starter_web/assets/images/modules/attics/1280x800/jekyll-generator.png +0 -0
- data/lib/starter_web/assets/images/modules/attics/1280x800jekyll-generator.jpg +0 -0
- data/lib/starter_web/assets/images/modules/attics/1920x1280/_ben-kolde.jpg +0 -0
- data/lib/starter_web/assets/images/modules/attics/1920x1280/_moritz-kindler.jpg +0 -0
- data/lib/starter_web/assets/images/modules/attics/1920x1280/alina-grubnyak.jpg +0 -0
- data/lib/starter_web/assets/images/modules/attics/1920x1280/andrea-badino.jpg +0 -0
- data/lib/starter_web/assets/images/modules/attics/1920x1280/brad-neathery.jpg +0 -0
- data/lib/starter_web/assets/images/modules/attics/1920x1280/bruno-figueiredo.jpg +0 -0
- data/lib/starter_web/assets/images/modules/attics/1920x1280/fly-d.jpg +0 -0
- data/lib/starter_web/assets/images/modules/attics/1920x1280/guillaume-bolduc.jpg +0 -0
- data/lib/starter_web/assets/images/modules/attics/1920x1280/melanie-deziel.jpg +0 -0
- data/lib/starter_web/assets/images/modules/attics/1920x1280/milad-fakurian.jpg +0 -0
- data/lib/starter_web/assets/images/modules/attics/1920x1280/quino-al-2.jpg +0 -0
- data/lib/starter_web/assets/images/modules/attics/lunr-1280x800.jpg +0 -0
- data/lib/starter_web/assets/images/modules/attics/no-time-1920x1280.jpg +0 -0
- data/lib/starter_web/assets/images/modules/gallery/mega_cities/author.txt +75 -0
- data/lib/starter_web/assets/images/pages/egrid/bg.png +0 -0
- data/lib/starter_web/assets/images/pages/egrid/black_denim.png +0 -0
- data/lib/starter_web/assets/images/pages/egrid/explanation.png +0 -0
- data/lib/starter_web/assets/images/pages/egrid/html_markup.png +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/1.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/10.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/11.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/12.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/13.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/14.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/15.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/16.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/17.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/18.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/19.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/2.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/20.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/3.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/4.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/5.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/6.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/7.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/8.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/large/9.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/loading.gif +0 -0
- data/lib/starter_web/assets/images/pages/egrid/loading_dark.gif +0 -0
- data/lib/starter_web/assets/images/pages/egrid/nav-icon.png +0 -0
- data/lib/starter_web/assets/images/pages/egrid/nav.png +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/1.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/10.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/11.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/12.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/13.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/14.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/15.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/16.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/17.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/18.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/19.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/1a.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/2.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/20.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/3.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/4.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/5.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/6.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/7.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/8.jpg +0 -0
- data/lib/starter_web/assets/images/pages/egrid/small/9.jpg +0 -0
- data/lib/starter_web/assets/images/pages/roundtrip/500_themes/themes-menu-1280x800.jpg +0 -0
- data/lib/starter_web/assets/images/promo/home/screenshot.jpg +0 -0
- data/lib/starter_web/assets/images/promo/jekyll/jekyll-generator.png +0 -0
- data/lib/starter_web/assets/images/promo/jekyll/jekyll-og.png +0 -0
- data/lib/starter_web/collections/asciidoc_skeletons/simple-post/_posts/yyyy-mm-dd-your-post-name.asciidoc +13 -10
- data/lib/starter_web/collections/posts/public/featured/_posts/0000-00-00-welcome-to-j1.adoc.erb +8 -3
- data/lib/starter_web/collections/posts/public/featured/_posts/2021-01-01-about-cookies.adoc +11 -6
- data/lib/starter_web/collections/posts/public/featured/_posts/2021-02-01-site-generators.adoc +13 -10
- data/lib/starter_web/collections/posts/public/featured/_posts/2022-02-01-about-j1.adoc +12 -9
- data/lib/starter_web/collections/posts/public/featured/_posts/_includes/attributes.asciidoc +2 -2
- data/lib/starter_web/collections/posts/public/series/_posts/2020-01-01-post-wiki-series.adoc +13 -5
- data/lib/starter_web/collections/posts/public/series/_posts/2020-01-02-post-wiki-series.adoc +13 -6
- data/lib/starter_web/collections/posts/public/series/_posts/2020-01-03-post-wiki-series.adoc +13 -6
- data/lib/starter_web/index.html +85 -60
- data/lib/starter_web/package.json +1 -1
- data/lib/starter_web/pages/public/about/features.adoc +15 -7
- data/lib/starter_web/pages/public/about/reporting_issues.adoc +13 -5
- data/lib/starter_web/pages/public/about/site.adoc +2 -6
- data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/000_intro.adoc +14 -7
- data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/100_converter.adoc +15 -7
- data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/200_themes.adoc +14 -6
- data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/_includes/documents/100_converter/111_about_the_converter.asciidoc +15 -10
- data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/documentation.adoc +9 -8
- data/lib/starter_web/pages/public/asciidoc_skeletons/multi-document/multi.adoc +9 -8
- data/lib/starter_web/pages/public/asciidoc_skeletons/simple-document/simple.adoc +9 -8
- data/lib/starter_web/pages/public/blog/navigator/{archive.html → archive/allview.html} +53 -26
- data/lib/starter_web/pages/public/blog/navigator/archive/categoryview.html +45 -20
- data/lib/starter_web/pages/public/blog/navigator/archive/dateview.html +49 -19
- data/lib/starter_web/pages/public/blog/navigator/archive/tagview.html +57 -53
- data/lib/starter_web/pages/public/blog/navigator/index.html +212 -35
- data/lib/starter_web/pages/public/features/general.adoc +12 -30
- data/lib/starter_web/pages/public/features/template.adoc +9 -33
- data/lib/starter_web/pages/public/learn/quickstart.adoc +10 -8
- data/lib/starter_web/pages/public/learn/roundtrip/_includes/attributes.asciidoc +0 -7
- data/lib/starter_web/pages/public/learn/roundtrip/_includes/documents/410_table_bs_modal_examples.asciidoc +2 -2
- data/lib/starter_web/pages/public/learn/roundtrip/_includes/documents/themes_bootstrap.asciidoc +51 -0
- data/lib/starter_web/pages/public/learn/roundtrip/_includes/documents/themes_rouge.asciidoc +110 -0
- data/lib/starter_web/pages/public/learn/roundtrip/asciidoc_extensions.adoc +11 -9
- data/lib/starter_web/pages/public/learn/roundtrip/bootstrap_themes.adoc +80 -0
- data/lib/starter_web/pages/public/learn/roundtrip/icon_fonts.adoc +9 -7
- data/lib/starter_web/pages/public/learn/roundtrip/{quicksearch.adoc → lunr_search.adoc} +23 -18
- data/lib/starter_web/pages/public/learn/roundtrip/{bs_modals_extentions.adoc → modal_extentions.adoc} +23 -24
- data/lib/starter_web/pages/public/learn/roundtrip/present_images.adoc +12 -11
- data/lib/starter_web/pages/public/learn/roundtrip/present_videos.adoc +14 -10
- data/lib/starter_web/pages/public/learn/roundtrip/{responsive_tables_extensions.adoc → responsive_tables.adoc} +16 -13
- data/lib/starter_web/pages/public/learn/roundtrip/{typography.adoc → template_typography.adoc} +8 -7
- data/lib/starter_web/pages/public/learn/where_to_go.adoc +12 -29
- data/lib/starter_web/pages/public/legal/de/100_copyright.adoc +1 -1
- data/lib/starter_web/pages/public/legal/de/100_impress.adoc +1 -1
- data/lib/starter_web/pages/public/legal/de/300_privacy.adoc +1 -1
- data/lib/starter_web/pages/public/legal/de/400_comment_policy.adoc +3 -1
- data/lib/starter_web/pages/public/legal/en/100_copyright.adoc +7 -5
- data/lib/starter_web/pages/public/legal/en/200_impress.adoc +7 -5
- data/lib/starter_web/pages/public/legal/en/300_privacy.adoc +7 -5
- data/lib/starter_web/pages/public/legal/en/400_comment_policy.adoc +9 -5
- data/lib/starter_web/pages/public/panels/intro_panel/panel.adoc +11 -10
- data/lib/starter_web/pages/public/plans/plans.adoc +8 -5
- data/lib/starter_web/pages/public/previewer/preview_bootstrap_theme.adoc +15 -38
- data/lib/starter_web/utilsrv/_defaults/package.json +1 -1
- data/lib/starter_web/utilsrv/package.json +1 -1
- metadata +170 -128
- data/_includes/themes/j1/blocks/footer/generator.html +0 -151
- data/_includes/themes/j1/layouts/content_generator_app.html +0 -32
- data/_includes/themes/j1/layouts/content_generator_article_navigator.html +0 -176
- data/_includes/themes/j1/layouts/content_generator_blog_archive.html +0 -251
- data/_layouts/app.html +0 -65
- data/_layouts/article_navigator.html +0 -66
- data/_layouts/blog_archive.html +0 -64
- data/assets/data/article_navigator/index.html +0 -51
- data/lib/starter_web/_data/layouts/app.yml +0 -172
- data/lib/starter_web/_data/layouts/article_navigator.yml +0 -173
- data/lib/starter_web/_data/layouts/blog_archive.yml +0 -191
- data/lib/starter_web/_includes/custom/static/custom_teaser.html +0 -64
- data/lib/starter_web/assets/images/banner/scalable/readme +0 -0
- data/lib/starter_web/assets/images/collections/blog/featured/dynamic-web-access.jpg +0 -0
- data/lib/starter_web/assets/images/collections/blog/featured/jamstack-generators-2.jpg +0 -0
- data/lib/starter_web/assets/images/collections/blog/featured/markus-spiske-2.jpg +0 -0
- data/lib/starter_web/assets/images/collections/blog/featured/static-web-access.jpg +0 -0
- data/lib/starter_web/assets/images/collections/blog/featured/welcome-to-j1-template.jpg +0 -0
- data/lib/starter_web/assets/images/collections/blog/featured/what-is-a-baseurl.jpg +0 -0
- data/lib/starter_web/assets/images/collections/blog/series/j1_using_docker/j1_docker_banner.1280x500.png +0 -0
- data/lib/starter_web/assets/images/collections/blog/series/j1_using_docker/kinematic_alpha.1280x600.png +0 -0
- data/lib/starter_web/assets/images/collections/blog/series/j1_using_docker/kinematic_j1.1280x300.png +0 -0
- data/lib/starter_web/assets/images/collections/blog/series/j1_using_docker/windows_docker_banner.1280x500.png +0 -0
- data/lib/starter_web/assets/images/modules/attics/1920x1280/moritz-kindler.jpg +0 -0
- data/lib/starter_web/assets/videos/gallery/dailymotion/meditation.jpg +0 -0
- data/lib/starter_web/assets/videos/gallery/dailymotion/pilates.jpg +0 -0
- data/lib/starter_web/assets/videos/gallery/html5/video1.mp4 +0 -0
- data/lib/starter_web/assets/videos/gallery/html5/video2.mp4 +0 -0
- data/lib/starter_web/assets/videos/gallery/kick-it-old-school-poster.jpg +0 -0
- data/lib/starter_web/assets/videos/gallery/nye-party-shop-poster.jpg +0 -0
- data/lib/starter_web/assets/videos/gallery/stay-colorful-poster.jpg +0 -0
- data/lib/starter_web/assets/videos/gallery/video1-poster.jpg +0 -0
- data/lib/starter_web/assets/videos/gallery/video1-thumb.jpg +0 -0
- data/lib/starter_web/assets/videos/gallery/video2-poster.jpg +0 -0
- data/lib/starter_web/assets/videos/gallery/video2-thumb.jpg +0 -0
- data/lib/starter_web/assets/videos/gallery/video_adele-poster.jpg +0 -0
- data/lib/starter_web/assets/videos/gallery/video_gaga-poster.jpg +0 -0
- data/lib/starter_web/assets/videos/gallery/video_gwen-poster.jpg +0 -0
- data/lib/starter_web/assets/videos/gallery/video_michelle-poster.jpg +0 -0
- data/lib/starter_web/assets/videos/gallery/vk/hai.jpg +0 -0
- data/lib/starter_web/assets/videos/gallery/vk/otter.jpg +0 -0
- data/lib/starter_web/assets/videos/gallery/voice_kids_de_2021/battle.jpg +0 -0
- data/lib/starter_web/assets/videos/gallery/voice_kids_de_2021/ben.jpg +0 -0
- data/lib/starter_web/assets/videos/gallery/voice_kids_de_2021/constance.jpg +0 -0
- data/lib/starter_web/assets/videos/gallery/voice_kids_de_2021/elisa.jpg +0 -0
- data/lib/starter_web/assets/videos/headers/present_videos/still/underground-broadway.jpg +0 -0
- data/lib/starter_web/assets/videos/headers/present_videos/underground-broadway.mp4 +0 -0
- data/lib/starter_web/assets/videos/tiktok/einhorn.jpg +0 -0
- data/lib/starter_web/assets/videos/tiktok/waluschka.jpg +0 -0
- data/lib/starter_web/pages/public/jupyter/examples/distributed/j1-circular-times-table.adoc +0 -142
- data/lib/starter_web/pages/public/jupyter/examples/distributed/j1-common-used-widgets.adoc +0 -232
- data/lib/starter_web/pages/public/jupyter/examples/distributed/j1-odes-in-python.adoc +0 -115
- data/lib/starter_web/pages/public/jupyter/examples/localized/j1_climate-change-forecast.adoc +0 -109
- data/lib/starter_web/pages/public/jupyter/notebooks/j1/j1_circular_times_table.ipynb +0 -12382
- data/lib/starter_web/pages/public/jupyter/notebooks/j1/j1_climate_change_forecast.ipynb +0 -1058
- data/lib/starter_web/pages/public/jupyter/notebooks/j1/j1_docs_example_dynamic.ipynb +0 -14478
- data/lib/starter_web/pages/public/jupyter/notebooks/j1/j1_interactive_widgets.ipynb +0 -442
- data/lib/starter_web/pages/public/jupyter/notebooks/j1/j1_nbi_widgets.ipynb +0 -523
- data/lib/starter_web/pages/public/jupyter/notebooks/j1/j1_nbi_widgets_bar_chart.ipynb +0 -89
- data/lib/starter_web/pages/public/jupyter/notebooks/j1/j1_nbi_widgets_hist_chart.ipynb +0 -87
- data/lib/starter_web/pages/public/jupyter/notebooks/j1/j1_nbi_widgets_line_chart.ipynb +0 -90
- data/lib/starter_web/pages/public/jupyter/notebooks/j1/j1_nbi_widgets_question_multiple_choice.ipynb +0 -64
- data/lib/starter_web/pages/public/jupyter/notebooks/j1/j1_nbi_widgets_question_short_answer.ipynb +0 -122
- data/lib/starter_web/pages/public/jupyter/notebooks/j1/j1_nbi_widgets_scatter_chart.ipynb +0 -89
- data/lib/starter_web/pages/public/jupyter/notebooks/j1/j1_nbi_widgets_scatter_drag_chart.ipynb +0 -87
- data/lib/starter_web/pages/public/jupyter/notebooks/j1/j1_odes_in_python.ipynb +0 -15227
- data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_circular_times_table.html +0 -747
- data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_climate_change_forecast.html +0 -1250
- data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_docs_example_dynamic.html +0 -186
- data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_interactive_widgets.html +0 -512
- data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_nbi_widgets.html +0 -629
- data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_nbi_widgets_bar_chart.html +0 -95
- data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_nbi_widgets_hist_chart.html +0 -93
- data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_nbi_widgets_line_chart.html +0 -96
- data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_nbi_widgets_question_multiple_choice.html +0 -70
- data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_nbi_widgets_question_short_answer.html +0 -156
- data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_nbi_widgets_scatter_chart.html +0 -95
- data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_nbi_widgets_scatter_drag_chart.html +0 -93
- data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_odes_in_python.html +0 -955
- data/lib/starter_web/pages/public/jupyter/where_to_go.adoc +0 -232
- data/lib/starter_web/pages/public/learn/roundtrip/_includes/google-ad.js +0 -130
- data/lib/starter_web/pages/public/learn/roundtrip/themes.adoc +0 -253
- data/lib/starter_web/pages/public/se/se-fake.adoc +0 -48
@@ -0,0 +1,717 @@
|
|
1
|
+
# ------------------------------------------------------------------------------
|
2
|
+
# ~/_plugins/j1-seo-tags.rb
|
3
|
+
# Generate SEO tags for posts and pages of a site
|
4
|
+
#
|
5
|
+
# Product/Info:
|
6
|
+
# http://jekyll.one
|
7
|
+
#
|
8
|
+
# Copyright (C) 2022 Ben Balter and Contributors
|
9
|
+
# Copyright (C) 2022 Juergen Adams
|
10
|
+
#
|
11
|
+
# J1 Template is licensed under the MIT License.
|
12
|
+
# See: https://github.com/jekyll-one-org/J1 Template/blob/master/LICENSE
|
13
|
+
# ------------------------------------------------------------------------------
|
14
|
+
# frozen_string_literal: true
|
15
|
+
|
16
|
+
require "jekyll"
|
17
|
+
|
18
|
+
module Jekyll
|
19
|
+
class SeoTag < Liquid::Tag
|
20
|
+
attr_accessor :context
|
21
|
+
|
22
|
+
@project_path = File.join(File.dirname(__FILE__)).sub('_plugins/seo', '')
|
23
|
+
@module_data_path = File.join(File.join(@project_path, '_data'))
|
24
|
+
@module_config_path = File.join(File.join(@module_data_path, 'plugins'))
|
25
|
+
@module_template_path = File.join(File.join(@module_data_path, 'templates'))
|
26
|
+
@module_config_default = YAML::load(File.open(File.join(@module_config_path, 'defaults', 'seo-tags.yml')))
|
27
|
+
@module_config_user = YAML::load(File.open(File.join(@module_config_path, 'seo-tags.yml')))
|
28
|
+
|
29
|
+
@module_config_default_settings = @module_config_default['defaults']
|
30
|
+
@module_config_user_settings = @module_config_user['settings']
|
31
|
+
@module_config = @module_config_default_settings.merge!(@module_config_user_settings)
|
32
|
+
|
33
|
+
# Matches all whitespace that follows either
|
34
|
+
# 1. A '}', which closes a Liquid tag
|
35
|
+
# 2. A '{', which opens a JSON block
|
36
|
+
# 3. A '>' followed by a newline, which closes an XML tag or
|
37
|
+
# 4. A ',' followed by a newline, which ends a JSON line
|
38
|
+
# We will strip all of this whitespace to minify the template
|
39
|
+
# We will not strip any whitespace if the next character is a '-'
|
40
|
+
# so that we do not interfere with the HTML comment at the
|
41
|
+
# very beginning
|
42
|
+
MINIFY_REGEX = %r!(?<=[{}]|[>,]\n)\s+(?\!-)!.freeze
|
43
|
+
|
44
|
+
def initialize(_tag_name, text, _tokens)
|
45
|
+
super
|
46
|
+
@text = text
|
47
|
+
end
|
48
|
+
|
49
|
+
def render(context)
|
50
|
+
@context = context
|
51
|
+
SeoTag.template.render!(payload, info)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def options
|
57
|
+
{
|
58
|
+
"title" => title?,
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
def payload
|
63
|
+
# site_payload is an instance of UnifiedPayloadDrop. See https://github.com/jekyll/jekyll/blob/22f2724a1f117a94cc16d18c499a93d5915ede4f/lib/jekyll/site.rb#L261-L276
|
64
|
+
context.registers[:site].site_payload.tap do |site_payload|
|
65
|
+
site_payload["page"] = context.registers[:page]
|
66
|
+
site_payload["paginator"] = context["paginator"]
|
67
|
+
site_payload["seo_tag"] = drop
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def drop
|
72
|
+
if context.registers[:site].liquid_renderer.respond_to?(:cache)
|
73
|
+
Jekyll::SeoTag::Drop.new(@text, @context)
|
74
|
+
else
|
75
|
+
@drop ||= Jekyll::SeoTag::Drop.new(@text, @context)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def info
|
80
|
+
{
|
81
|
+
:registers => context.registers,
|
82
|
+
:filters => [Jekyll::Filters],
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
class << self
|
87
|
+
def template
|
88
|
+
@template ||= Liquid::Template.parse template_contents
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def template_contents
|
94
|
+
@template_contents ||= begin
|
95
|
+
File.read(template_path).gsub(MINIFY_REGEX, "")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def template_path
|
100
|
+
@template_path ||= File.expand_path @module_config['template_name'], @module_template_path
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
Liquid::Template.register_tag("seo", Jekyll::SeoTag)
|
108
|
+
|
109
|
+
module Jekyll
|
110
|
+
class SeoTag
|
111
|
+
# A drop representing the current page's author
|
112
|
+
#
|
113
|
+
# Author name will be pulled from:
|
114
|
+
#
|
115
|
+
# 1. The page's `author` key
|
116
|
+
# 2. The first author in the page's `authors` key
|
117
|
+
# 3. The `author` key in the site config
|
118
|
+
#
|
119
|
+
# If the result from the name search is a string, we'll also check
|
120
|
+
# for additional author metadata in `site.data.authors`
|
121
|
+
class AuthorDrop < Jekyll::Drops::Drop
|
122
|
+
# Initialize a new AuthorDrop
|
123
|
+
#
|
124
|
+
# page - The page hash (e.g., Page#to_liquid)
|
125
|
+
# site - The Jekyll::Drops::SiteDrop
|
126
|
+
def initialize(page: nil, site: nil)
|
127
|
+
raise ArgumentError unless page && site
|
128
|
+
|
129
|
+
@mutations = {}
|
130
|
+
@page = page
|
131
|
+
@site = site
|
132
|
+
end
|
133
|
+
|
134
|
+
# AuthorDrop#to_s should return name, allowing the author drop to safely
|
135
|
+
# replace `page.author`, if necessary, and remain backwards compatible
|
136
|
+
def name
|
137
|
+
author_hash["name"]
|
138
|
+
end
|
139
|
+
alias_method :to_s, :name
|
140
|
+
|
141
|
+
def twitter
|
142
|
+
return @twitter if defined? @twitter
|
143
|
+
|
144
|
+
twitter = author_hash["twitter"] || author_hash["name"]
|
145
|
+
@twitter = twitter.is_a?(String) ? twitter.sub(%r!^@!, "") : nil
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
|
150
|
+
attr_reader :site, :page
|
151
|
+
|
152
|
+
# Finds the page author in the page.author, page.authors, or site.author
|
153
|
+
#
|
154
|
+
# Returns a string or hash representing the author
|
155
|
+
def resolved_author
|
156
|
+
return @resolved_author if defined? @resolved_author
|
157
|
+
|
158
|
+
sources = [page["author"]]
|
159
|
+
sources << page["authors"].first if page["authors"].is_a?(Array)
|
160
|
+
sources << site["author"]
|
161
|
+
@resolved_author = sources.find { |s| !s.to_s.empty? }
|
162
|
+
end
|
163
|
+
|
164
|
+
# If resolved_author is a string, attempts to find corresponding author
|
165
|
+
# metadata in `site.data.authors`
|
166
|
+
#
|
167
|
+
# Returns a hash representing additional metadata or an empty hash
|
168
|
+
def site_data_hash
|
169
|
+
@site_data_hash ||= begin
|
170
|
+
return {} unless resolved_author.is_a?(String)
|
171
|
+
return {} unless site.data["authors"].is_a?(Hash)
|
172
|
+
|
173
|
+
author_hash = site.data["authors"][resolved_author]
|
174
|
+
author_hash.is_a?(Hash) ? author_hash : {}
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
# Returns the normalized author hash representing the page author,
|
179
|
+
# including site-wide metadata if the author is provided as a string,
|
180
|
+
# or an empty hash, if the author cannot be resolved
|
181
|
+
def author_hash
|
182
|
+
@author_hash ||= begin
|
183
|
+
case resolved_author
|
184
|
+
when Hash
|
185
|
+
resolved_author
|
186
|
+
when String
|
187
|
+
{ "name" => resolved_author }.merge!(site_data_hash)
|
188
|
+
else
|
189
|
+
{}
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# Since author_hash is aliased to fallback_data, any values in the hash
|
195
|
+
# will be exposed via the drop, allowing support for arbitrary metadata
|
196
|
+
alias_method :fallback_data, :author_hash
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
|
202
|
+
module Jekyll
|
203
|
+
class SeoTag
|
204
|
+
|
205
|
+
module UrlHelper
|
206
|
+
private
|
207
|
+
|
208
|
+
# Determines if the given string is an absolute URL
|
209
|
+
#
|
210
|
+
# Returns true if an absolute URL
|
211
|
+
# Returns false if it's a relative URL
|
212
|
+
# Returns nil if it is not a string or can't be parsed as a URL
|
213
|
+
def absolute_url?(string)
|
214
|
+
return unless string
|
215
|
+
|
216
|
+
Addressable::URI.parse(string).absolute?
|
217
|
+
rescue Addressable::URI::InvalidURIError
|
218
|
+
nil
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
class Drop < Jekyll::Drops::Drop
|
223
|
+
include Jekyll::SeoTag::UrlHelper
|
224
|
+
|
225
|
+
TITLE_SEPARATOR = " | "
|
226
|
+
FORMAT_STRING_METHODS = [
|
227
|
+
:markdownify, :strip_html, :normalize_whitespace, :escape_once,
|
228
|
+
].freeze
|
229
|
+
HOMEPAGE_OR_ABOUT_REGEX = %r!^/(about/)?(index.html?)?$!.freeze
|
230
|
+
|
231
|
+
EMPTY_READ_ONLY_HASH = {}.freeze
|
232
|
+
private_constant :EMPTY_READ_ONLY_HASH
|
233
|
+
|
234
|
+
def initialize(text, context)
|
235
|
+
@obj = EMPTY_READ_ONLY_HASH
|
236
|
+
@mutations = {}
|
237
|
+
@text = text
|
238
|
+
@context = context
|
239
|
+
end
|
240
|
+
|
241
|
+
def version
|
242
|
+
Jekyll::SeoTag::VERSION
|
243
|
+
end
|
244
|
+
|
245
|
+
# Should the `<title>` tag be generated for this page?
|
246
|
+
def title?
|
247
|
+
return false unless title
|
248
|
+
return @display_title if defined?(@display_title)
|
249
|
+
|
250
|
+
@display_title = (@text !~ %r!title=false!i)
|
251
|
+
end
|
252
|
+
|
253
|
+
def site_title
|
254
|
+
@site_title ||= format_string(site["title"] || site["name"])
|
255
|
+
end
|
256
|
+
|
257
|
+
def site_tagline
|
258
|
+
@site_tagline ||= format_string site["tagline"]
|
259
|
+
end
|
260
|
+
|
261
|
+
def site_description
|
262
|
+
@site_description ||= format_string site["description"]
|
263
|
+
end
|
264
|
+
|
265
|
+
# Page title without site title or description appended
|
266
|
+
def page_title
|
267
|
+
@page_title ||= format_string(page["title"]) || site_title
|
268
|
+
end
|
269
|
+
|
270
|
+
def site_tagline_or_description
|
271
|
+
site_tagline || site_description
|
272
|
+
end
|
273
|
+
|
274
|
+
# Page title with site title or description appended
|
275
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
276
|
+
def title
|
277
|
+
@title ||= begin
|
278
|
+
if site_title && page_title != site_title
|
279
|
+
page_title + TITLE_SEPARATOR + site_title
|
280
|
+
elsif site_description && site_title
|
281
|
+
site_title + TITLE_SEPARATOR + site_tagline_or_description
|
282
|
+
else
|
283
|
+
page_title || site_title
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
return page_number + @title if page_number
|
288
|
+
|
289
|
+
@title
|
290
|
+
end
|
291
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
292
|
+
|
293
|
+
def name
|
294
|
+
return @name if defined?(@name)
|
295
|
+
|
296
|
+
@name = if seo_name
|
297
|
+
seo_name
|
298
|
+
elsif !homepage_or_about?
|
299
|
+
nil
|
300
|
+
elsif site_social["name"]
|
301
|
+
format_string site_social["name"]
|
302
|
+
elsif site_title
|
303
|
+
site_title
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
def description
|
308
|
+
@description ||= begin
|
309
|
+
format_string(page["description"] || page["excerpt"]) || site_description
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
# A drop representing the page author
|
314
|
+
def author
|
315
|
+
@author ||= AuthorDrop.new(:page => page, :site => site)
|
316
|
+
end
|
317
|
+
|
318
|
+
# A drop representing the JSON-LD output
|
319
|
+
def json_ld
|
320
|
+
@json_ld ||= JSONLDDrop.new(self)
|
321
|
+
end
|
322
|
+
|
323
|
+
# Returns a Drop representing the page's image
|
324
|
+
# Returns nil if the image has no path, to preserve backwards compatability
|
325
|
+
def image
|
326
|
+
@image ||= ImageDrop.new(:page => page, :context => @context)
|
327
|
+
@image if @image.path
|
328
|
+
end
|
329
|
+
|
330
|
+
def date_modified
|
331
|
+
@date_modified ||= begin
|
332
|
+
date = page_seo["date_modified"] || page["last_modified_at"].to_liquid || page["date"]
|
333
|
+
filters.date_to_xmlschema(date) if date
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
def date_published
|
338
|
+
@date_published ||= filters.date_to_xmlschema(page["date"]) if page["date"]
|
339
|
+
end
|
340
|
+
|
341
|
+
def type
|
342
|
+
@type ||= begin
|
343
|
+
if page_seo["type"]
|
344
|
+
page_seo["type"]
|
345
|
+
elsif homepage_or_about?
|
346
|
+
"WebSite"
|
347
|
+
elsif page["date"]
|
348
|
+
"BlogPosting"
|
349
|
+
else
|
350
|
+
"WebPage"
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
def links
|
356
|
+
@links ||= begin
|
357
|
+
if page_seo["links"]
|
358
|
+
page_seo["links"]
|
359
|
+
elsif homepage_or_about? && site_social["links"]
|
360
|
+
site_social["links"]
|
361
|
+
end
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
def logo
|
366
|
+
@logo ||= begin
|
367
|
+
return unless site["logo"]
|
368
|
+
|
369
|
+
if absolute_url? site["logo"]
|
370
|
+
filters.uri_escape site["logo"]
|
371
|
+
else
|
372
|
+
filters.uri_escape filters.absolute_url site["logo"]
|
373
|
+
end
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
def page_lang
|
378
|
+
@page_lang ||= page["lang"] || site["lang"] || "en_US"
|
379
|
+
end
|
380
|
+
|
381
|
+
def page_locale
|
382
|
+
@page_locale ||= (page["locale"] || site["locale"] || page_lang).tr("-", "_")
|
383
|
+
end
|
384
|
+
|
385
|
+
def canonical_url
|
386
|
+
@canonical_url ||= begin
|
387
|
+
if page["canonical_url"].to_s.empty?
|
388
|
+
filters.absolute_url(page["url"]).to_s.gsub(%r!/index\.html$!, "/")
|
389
|
+
else
|
390
|
+
page["canonical_url"]
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
private
|
396
|
+
|
397
|
+
def filters
|
398
|
+
@filters ||= Jekyll::SeoTag::Filters.new(@context)
|
399
|
+
end
|
400
|
+
|
401
|
+
def page
|
402
|
+
@page ||= @context.registers[:page].to_liquid
|
403
|
+
end
|
404
|
+
|
405
|
+
def site
|
406
|
+
@site ||= @context.registers[:site].site_payload["site"].to_liquid
|
407
|
+
end
|
408
|
+
|
409
|
+
def homepage_or_about?
|
410
|
+
page["url"] =~ HOMEPAGE_OR_ABOUT_REGEX
|
411
|
+
end
|
412
|
+
|
413
|
+
def page_number
|
414
|
+
return unless @context["paginator"] && @context["paginator"]["page"]
|
415
|
+
|
416
|
+
current = @context["paginator"]["page"]
|
417
|
+
total = @context["paginator"]["total_pages"]
|
418
|
+
paginator_message = site["seo_paginator_message"] || "Page %<current>s of %<total>s for "
|
419
|
+
|
420
|
+
format(paginator_message, :current => current, :total => total) if current > 1
|
421
|
+
end
|
422
|
+
|
423
|
+
attr_reader :context
|
424
|
+
|
425
|
+
def fallback_data
|
426
|
+
@fallback_data ||= {}
|
427
|
+
end
|
428
|
+
|
429
|
+
def format_string(string)
|
430
|
+
string = FORMAT_STRING_METHODS.reduce(string) do |memo, method|
|
431
|
+
filters.public_send(method, memo)
|
432
|
+
end
|
433
|
+
|
434
|
+
string unless string.empty?
|
435
|
+
end
|
436
|
+
|
437
|
+
def seo_name
|
438
|
+
@seo_name ||= format_string(page_seo["name"]) if page_seo["name"]
|
439
|
+
end
|
440
|
+
|
441
|
+
def page_seo
|
442
|
+
@page_seo ||= sub_hash(page, "seo")
|
443
|
+
end
|
444
|
+
|
445
|
+
def site_social
|
446
|
+
@site_social ||= sub_hash(site, "social")
|
447
|
+
end
|
448
|
+
|
449
|
+
# Safely returns a sub hash
|
450
|
+
#
|
451
|
+
# hash - the parent hash
|
452
|
+
# key - the key in the parent hash
|
453
|
+
#
|
454
|
+
# Returns the sub hash or an empty hash, if it does not exist
|
455
|
+
def sub_hash(hash, key)
|
456
|
+
if hash[key].is_a?(Hash)
|
457
|
+
hash[key]
|
458
|
+
else
|
459
|
+
EMPTY_READ_ONLY_HASH
|
460
|
+
end
|
461
|
+
end
|
462
|
+
end
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
466
|
+
|
467
|
+
module Jekyll
|
468
|
+
class SeoTag
|
469
|
+
class Filters
|
470
|
+
include Jekyll::Filters
|
471
|
+
include Liquid::StandardFilters
|
472
|
+
|
473
|
+
def initialize(context)
|
474
|
+
@context = context
|
475
|
+
end
|
476
|
+
end
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
|
481
|
+
module Jekyll
|
482
|
+
class SeoTag
|
483
|
+
# A drop representing the page image
|
484
|
+
# The image path will be pulled from:
|
485
|
+
#
|
486
|
+
# 1. The `image` key if it's a string
|
487
|
+
# 2. The `image.path` key if it's a hash
|
488
|
+
# 3. The `image.facebook` key
|
489
|
+
# 4. The `image.twitter` key
|
490
|
+
class ImageDrop < Jekyll::Drops::Drop
|
491
|
+
include Jekyll::SeoTag::UrlHelper
|
492
|
+
|
493
|
+
# Initialize a new ImageDrop
|
494
|
+
#
|
495
|
+
# page - The page hash (e.g., Page#to_liquid)
|
496
|
+
# context - the Liquid::Context
|
497
|
+
def initialize(page: nil, context: nil)
|
498
|
+
raise ArgumentError unless page && context
|
499
|
+
|
500
|
+
@mutations = {}
|
501
|
+
@page = page
|
502
|
+
@context = context
|
503
|
+
end
|
504
|
+
|
505
|
+
# Called path for backwards compatability, this is really
|
506
|
+
# the escaped, absolute URL representing the page's image
|
507
|
+
# Returns nil if no image path can be determined
|
508
|
+
def path
|
509
|
+
@path ||= filters.uri_escape(absolute_url) if absolute_url
|
510
|
+
end
|
511
|
+
alias_method :to_s, :path
|
512
|
+
|
513
|
+
private
|
514
|
+
|
515
|
+
attr_accessor :page, :context
|
516
|
+
|
517
|
+
# The normalized image hash with a `path` key (which may be nil)
|
518
|
+
def image_hash
|
519
|
+
@image_hash ||= begin
|
520
|
+
image_meta = page["image"]
|
521
|
+
|
522
|
+
case image_meta
|
523
|
+
when Hash
|
524
|
+
{ "path" => nil }.merge!(image_meta)
|
525
|
+
when String
|
526
|
+
{ "path" => image_meta }
|
527
|
+
else
|
528
|
+
{ "path" => nil }
|
529
|
+
end
|
530
|
+
end
|
531
|
+
end
|
532
|
+
alias_method :fallback_data, :image_hash
|
533
|
+
|
534
|
+
def raw_path
|
535
|
+
@raw_path ||= begin
|
536
|
+
image_hash["path"] || image_hash["facebook"] || image_hash["twitter"]
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
def absolute_url
|
541
|
+
return unless raw_path
|
542
|
+
@absolute_url ||= build_absolute_path
|
543
|
+
end
|
544
|
+
|
545
|
+
def build_absolute_path
|
546
|
+
return raw_path unless raw_path.is_a?(String) && absolute_url?(raw_path) == false
|
547
|
+
return filters.absolute_url(raw_path) if raw_path.start_with?("/")
|
548
|
+
|
549
|
+
page_dir = @page["url"]
|
550
|
+
page_dir = File.dirname(page_dir) unless page_dir.end_with?("/")
|
551
|
+
|
552
|
+
filters.absolute_url File.join(page_dir, raw_path)
|
553
|
+
end
|
554
|
+
|
555
|
+
def filters
|
556
|
+
@filters ||= Jekyll::SeoTag::Filters.new(context)
|
557
|
+
end
|
558
|
+
end
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
|
563
|
+
module Jekyll
|
564
|
+
class SeoTag
|
565
|
+
class JSONLDDrop < Jekyll::Drops::Drop
|
566
|
+
extend Forwardable
|
567
|
+
|
568
|
+
def_delegator :page_drop, :name, :name
|
569
|
+
def_delegator :page_drop, :description, :description
|
570
|
+
def_delegator :page_drop, :canonical_url, :url
|
571
|
+
def_delegator :page_drop, :page_title, :headline
|
572
|
+
def_delegator :page_drop, :date_modified, :dateModified
|
573
|
+
def_delegator :page_drop, :date_published, :datePublished
|
574
|
+
def_delegator :page_drop, :links, :sameAs
|
575
|
+
def_delegator :page_drop, :logo, :logo
|
576
|
+
def_delegator :page_drop, :type, :type
|
577
|
+
|
578
|
+
# Expose #type and #logo as private methods and #@type as a public method
|
579
|
+
alias_method :@type, :type
|
580
|
+
private :type, :logo
|
581
|
+
|
582
|
+
VALID_ENTITY_TYPES = %w(BlogPosting CreativeWork).freeze
|
583
|
+
VALID_AUTHOR_TYPES = %w(Organization Person).freeze
|
584
|
+
private_constant :VALID_ENTITY_TYPES, :VALID_AUTHOR_TYPES
|
585
|
+
|
586
|
+
# page_drop should be an instance of Jekyll::SeoTag::Drop
|
587
|
+
def initialize(page_drop)
|
588
|
+
@mutations = {}
|
589
|
+
@page_drop = page_drop
|
590
|
+
end
|
591
|
+
|
592
|
+
def fallback_data
|
593
|
+
@fallback_data ||= {
|
594
|
+
"@context" => "https://schema.org",
|
595
|
+
}
|
596
|
+
end
|
597
|
+
|
598
|
+
def author
|
599
|
+
return unless page_drop.author["name"]
|
600
|
+
|
601
|
+
author_type = page_drop.author["type"]
|
602
|
+
return if author_type && !VALID_AUTHOR_TYPES.include?(author_type)
|
603
|
+
|
604
|
+
hash = {
|
605
|
+
"@type" => author_type || "Person",
|
606
|
+
"name" => page_drop.author["name"],
|
607
|
+
}
|
608
|
+
|
609
|
+
author_url = page_drop.author["url"]
|
610
|
+
hash["url"] = author_url if author_url
|
611
|
+
|
612
|
+
hash
|
613
|
+
end
|
614
|
+
|
615
|
+
def image
|
616
|
+
return unless page_drop.image
|
617
|
+
return page_drop.image.path if page_drop.image.keys.length == 1
|
618
|
+
|
619
|
+
hash = page_drop.image.to_h
|
620
|
+
hash["url"] = hash.delete("path")
|
621
|
+
hash["@type"] = "imageObject"
|
622
|
+
hash
|
623
|
+
end
|
624
|
+
|
625
|
+
def publisher
|
626
|
+
return unless logo
|
627
|
+
|
628
|
+
output = {
|
629
|
+
"@type" => "Organization",
|
630
|
+
"logo" => {
|
631
|
+
"@type" => "ImageObject",
|
632
|
+
"url" => logo,
|
633
|
+
},
|
634
|
+
}
|
635
|
+
output["name"] = page_drop.author.name if page_drop.author.name
|
636
|
+
output
|
637
|
+
end
|
638
|
+
|
639
|
+
def main_entity
|
640
|
+
return unless VALID_ENTITY_TYPES.include?(type)
|
641
|
+
|
642
|
+
{
|
643
|
+
"@type" => "WebPage",
|
644
|
+
"@id" => page_drop.canonical_url,
|
645
|
+
}
|
646
|
+
end
|
647
|
+
alias_method :mainEntityOfPage, :main_entity
|
648
|
+
private :main_entity
|
649
|
+
|
650
|
+
# Returns a JSON-encoded object containing the JSON-LD data.
|
651
|
+
# Keys are sorted.
|
652
|
+
def to_json(state = nil)
|
653
|
+
keys.sort.each_with_object({}) do |(key, _), result|
|
654
|
+
v = self[key]
|
655
|
+
result[key] = v unless v.nil?
|
656
|
+
end.to_json(state)
|
657
|
+
end
|
658
|
+
|
659
|
+
private
|
660
|
+
|
661
|
+
attr_reader :page_drop
|
662
|
+
end
|
663
|
+
end
|
664
|
+
end
|
665
|
+
|
666
|
+
# module Jekyll
|
667
|
+
# class SeoTag
|
668
|
+
# # This module is deprecated, but is included in the Gem to avoid a breaking
|
669
|
+
# # change and should be removed at the next major version bump
|
670
|
+
# module JSONLD
|
671
|
+
# METHODS_KEYS = {
|
672
|
+
# :json_context => "@context",
|
673
|
+
# :type => "@type",
|
674
|
+
# :name => "name",
|
675
|
+
# :page_title => "headline",
|
676
|
+
# :json_author => "author",
|
677
|
+
# :json_image => "image",
|
678
|
+
# :date_published => "datePublished",
|
679
|
+
# :date_modified => "dateModified",
|
680
|
+
# :description => "description",
|
681
|
+
# :publisher => "publisher",
|
682
|
+
# :main_entity => "mainEntityOfPage",
|
683
|
+
# :links => "sameAs",
|
684
|
+
# :canonical_url => "url",
|
685
|
+
# }.freeze
|
686
|
+
#
|
687
|
+
# # Self should be a Jekyll::SeoTag::Drop instance (when extending the module)
|
688
|
+
# def json_ld
|
689
|
+
# Jekyll.logger.warn "Jekyll::SeoTag::JSONLD is deprecated"
|
690
|
+
# @json_ld ||= JSONLDDrop.new(self)
|
691
|
+
# end
|
692
|
+
# end
|
693
|
+
# end
|
694
|
+
# end
|
695
|
+
|
696
|
+
|
697
|
+
# module Jekyll
|
698
|
+
# class SeoTag
|
699
|
+
# # Mixin to share common URL-related methods between class
|
700
|
+
# module UrlHelper
|
701
|
+
# private
|
702
|
+
#
|
703
|
+
# # Determines if the given string is an absolute URL
|
704
|
+
# #
|
705
|
+
# # Returns true if an absolute URL
|
706
|
+
# # Returns false if it's a relative URL
|
707
|
+
# # Returns nil if it is not a string or can't be parsed as a URL
|
708
|
+
# def absolute_url?(string)
|
709
|
+
# return unless string
|
710
|
+
#
|
711
|
+
# Addressable::URI.parse(string).absolute?
|
712
|
+
# rescue Addressable::URI::InvalidURIError
|
713
|
+
# nil
|
714
|
+
# end
|
715
|
+
# end
|
716
|
+
# end
|
717
|
+
# end
|