diff --git a/.gitmodules b/.gitmodules index 6c09dfa..f2bf547 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "themes/zola-clean-blog"] path = themes/zola-clean-blog url = gitea@git.hoyer.xyz:harald/zola-clean-blog.git +[submodule "themes/abridge"] + path = themes/abridge + url = https://github.com/jieiku/abridge.git diff --git a/config.toml b/config.toml index b269229..44c293e 100644 --- a/config.toml +++ b/config.toml @@ -10,7 +10,7 @@ compile_sass = true # Whether to build a search index to be used later on by a JavaScript library build_search_index = true -theme = "zola-clean-blog" +theme = "abridge" taxonomies = [ {name = "tags", feed = true, paginate_by=10}, @@ -19,18 +19,27 @@ taxonomies = [ generate_feed = true feed_filename = "rss.xml" +[search] # Options specific to elasticlunr search. +# index format can be: elasticlunr_json or elasticlunr_javascript +index_format = "elasticlunr_json" +include_title = true # include title of page/section in index +include_description = true # include description of page/section in index +include_content = true # include rendered content of page/section in index +# truncate_content_length = 100 # Truncate at nth character. May be useful if index is getting too large. + [markdown] - -# Whether to do syntax highlighting -# Theme can be customised by setting the `highlight_theme` variable to a theme supported by Zola highlight_code = true - -render_emoji = true +#highlight_theme = "css" +render_emoji = false +external_links_target_blank = true # rel="noopener" +external_links_no_follow = false # rel="nofollow" +external_links_no_referrer = false # rel="noreferrer" +smart_punctuation = false # `...` to `…`, `"quote"` to `“curly”` etc -#highlight_theme = "dracula" +highlight_theme = "dracula" #highlight_theme = "inspired-github" -highlight_theme = "ir-white" +#highlight_theme = "ir-white" #highlight_theme = "material-light" #highlight_theme = "base16-ocean-dark" @@ -59,3 +68,295 @@ clean_blog_social = [ {url = "https://keybase.io/haraldhoyer/", icon="fab fa-keybase"}, {url = "/rss", icon="fas fa-rss"} ] + +menu = [ + {url = "/", name = "Home", slash = true, blank = false, size="s110"}, + {url = "archive", name = "Posts", slash = true, blank = false, size="s110"}, + # {url = "categories", name = "Categories", slash = true, blank = false, size="s110"}, + {url = "tags", name = "Tags", slash = true, blank = false, size="s110"}, + {url = "https://photo-harald.hoyer.xyz/", name = "Photos", blank = true}, +] +menu_footer = [ + {url = "impressum", name = "Impressum", slash = true, blank = false, size="s110"}, + {url = "privacy", name = "Privacy", slash = true, blank = false}, + {url = "sitemap.xml", name = "Sitemap", slash = false, blank = true}, + {url = "rss", name = "Feeds", slash = true, blank = false, size="s110"}, +] + +toc = true +recent = true # TOC / index +recent_items = 15 +series = true +series_items = 9 # Max number of items to display in series list, use 0 to disable +#Series_parts = "$NUMBER_OF_PARTS part Series" + +meta_index = { position="bottom", size="s90", author=false, readtime=false, readstring="min", date=true, updated=false, categories_tags=true, divider="" } +meta_post = { position="top", size="s95", author=true, readtime=false, readstring="min read", date=true, updated=true, categories_tags=true, divider="" } + +hide_section_dates = false # hides the date for sections that use posts.html as their template. +hide_page_nextprev_titles = false # hides the next/previous titles for pages that use page.html as their template. +title_size_index = "s85" +footer_size = "s90" +footer_credit = true +#footer_credit_override = '

Powered by Zola & Abridge

' +#archive_reverse = true # Set to True to sort posts chronologically per year instead of newest first on the archive page: example.com/archive/ + +### Uncomment one of the below lines, or neither, depending on which type of logo you want to use: +#logo = { file="logo.svg", width="32", height="32", alt="Abridge", text="bridge" } +#textlogo = 'Abridge' +#textlogo = 'bridge' + +sitedesc = false # enables or disables the display of the site description below the logo. +headhr = false # show or hide horizontal rule below header +foothr = true # show or hide horizontal rule above footer + +### $CURRENT_YEAR and $SITE_TITLE can be used anywhere within the copyright, you can change their position or you can also delete them and type whatever you want instead. +#copyright = false # set to false to disable the copyright. +#copyright_override = '© 2019-$CURRENT_YEAR $SITE_TITLE' +#copyright_override = '© $CURRENT_YEAR $SITE_TITLE • Website content is licensed CC BY 4.0.' + + +############################################################################### +### meta/seo/analytic tags +### To disable title_addition but keep built in page additions eg, Posts page: "Posts | Abridge" set title_addition to an empty string +### To always set the page title exactly eg "Abridge" then comment out title_addition or set to false (not recommend, bad for SEO) +############################################################################### + +#title_separator = "|" # Separator between title and title_addition, set as |, -, _, etc +title_addition = "" # a default value for title addition +#author = "Jake G" # Put Your Name here +#keywords = "Abridge, Abridge.css, Zola, Theme, Zola Theme, getzola, Semantic Html, Fast, lightweight" # used for the primary site index +#banner = "banner.png" # Used as default image for OpenGraph/Twitter if page specific image is undefined. +#twitter_meta = "your-user-name" # for SEO: twitter:site and twitter:creator +#google = "Your Google Site verification code." +#bing = "Your Bing Site verification code." +seo = false # enable or disable seo-related meta tags: opengraph, facebook, twitter +#dev = false # development mode, if true then robots.txt should prevent search indexing. + + +############################################################################### +### Footer social links; these are used in macros/social.html +### https://github.com/Jieiku/abridge/blob/master/templates/macros/social.html +############################################################################### + +feed = true # this adds the RSS feed icon in the footer. +#mail = "harald@hoyer.xyz" +mastodon = "https://floss.social/@backslash" +#element = "matrix.example.com" +#buymeacoffee = "your-user-name" +#kofi = "your-user-name" +#discord = "your-discord" # Everything after https://discord.com/ eg: invite/my-server *or* servers/my-server-id +#twitter = "your-user-name" +#facebook = "your-user-name" +#linkedin = "your-user-name" +gitlab = "haraldh" +github = "haraldh" +#codeberg = "your-user-name" # Everything after https://codeberg.org/ eg: username *or* username/repository +#github_sponsor = "your-user-name" +#bitbucket = "your-user-name" +#python = "your-user-name" +#docker = "your-user-name" +#stack = "your-user-name" +#instagram = "your-user-name" +#pixelfed = "@your-user-name" # Heaviest icon, off by default +#pinterest = "your-user-name" +#twitch = "your-user-name" +#youtube = "channel/your-channel-id" +#researchgate = "your-profile-id" + + +############################################################################### +### Commenting System for visitors to leave comments on pages. +### hyvor talk +############################################################################### + +#comments.hyvor = "9366" # hyvor website id, comment out to disable. +#comments.hyvorcolor = "os" # set the color property for hyvor + + +############################################################################### +### Resource Files +### You can load extra css files if you need to, just separate by comma: +### stylesheets = [ "abridge.css", "extra.css" ] +### search_library, library to use. valid values: +### false, "elasticlunr", "tinysearch", "stork" +### offline: implies uglyurls=true and integrity=false, when true NPM/node will +### automatically set the path for the base_url, it will build the site, +### then set the base_url back to what it was. This is a way to build a completely +### offline site, a feature not possible with Zola alone. +### The PWA feature is another way to build an offline site, so there are now two +### different ways to build an offline site with Abridge. +### +### For most people the value of online_url will be the same as base_url. +### online_url is used to restore the base_url after generating an Offline site. +### When you set offline = true and run the npm script, the base_url is set to the absolute path on disk. +### Once you set offline = false, the base_url will be set back to the value of online_url when you run the npm script again. +############################################################################### + +# do NOT include a trailing slash on the online URL +online_url = "https://harald.hoyer.xyz" +online_indexformat = "elasticlunr_json"# used to restore your preferred index format when offline = false +offline = false # implies uglyurls=true and integrity=false, when true NPM/node will automatically set the path for the base_url, it will build the site, then set the base_url back to what it was. + +uglyurls = false # if set to true then links are generated with the full path. eg https://abridge.netlify.app/index.html +integrity = true # increases site security, should normally be true. (setting to false is useful during js development) +js_bundle = true # multiple javascript files combined into a single file (setting to false is useful during js development) + +js_copycode = true # The copy button on code blocks that allows you to copy them to the clipboard. +js_email_encode = true # obfuscates email address in footer +js_prestyle = true # used to preload: FontAwesome, Katex, external Google Fonts +js_switcher = true # The button that allows manually changing between light/dark mode. +js_switcher_default = "dark" # default nojs switcher mode: dark, light (make sure to also set $switcherDefault in abridge.scss) + +search_library = 'elasticlunr' +stylesheets = ["abridge.css"] + +webmanifest = "manifest.min.json" # Required for PWAs + +############################################################################### +### PWA (Progressive Web Application) +### By default Abridge has pwa_NORM_TTL and pwa_LONG_TTL set to 0, this essential turns the PWA cache strategy into network first. +### Abridge uses cachebust hashing on js and css files, so anytime a page cache is updated, these resources would also get updated if changed. +### Media files rarely change, especially font files, so it is a good idea cache indefinitely. +### For pwa_TTL_EXEMPT indefinitely cached resources, you can force a new cache by incrementing the pwa_VER (cache version number). +### If you would like to try a cache first strategy then set a value higher than 0 for pwa_NORM_TTL and pwa_LONG_TTL. +### The options below other than pwa=true, only come into play when the npm/node script is ran. +############################################################################### + +pwa = true # true to load the service worker +pwa_VER = '3.11.0' # Service Worker cache version. (increment if you need to force a new cache) + +### 3600=1hour, 28800=8hours, 86400=1day, 604800=1week, 1209600=2weeks +pwa_NORM_TTL = 0 # 86400 is reasonable. html, json, xml, anything else undefined +pwa_LONG_TTL = 0 # 604800 is reasonable. + +### list of files that overrides TTL_LONG/TTL_EXEMPT to be a NORM TTL. +pwa_TTL_NORM = '"sw.min.js", "sw_load.min.js"' + +### TTL_LONG file extensions will be cached for the LONG_TTL duration. +pwa_TTL_LONG = '"jpg", "jpeg", "png", "gif", "webp", "avif", "ico", "svg", "xsl", "txt"' + +### TTL_EXEMPT file extensions will be cached indefinitely unless sw_load version is incremented, which would invalidate any existing cache. (and a new cache would be started) +pwa_TTL_EXEMPT = '"js", "css", "otf", "eot", "ttf", "woff", "woff2", "mp4", "webm", "mp3", "ogg"' + +### If set to true then the entire site is cached. (useful for making an entire site usable while offline) +pwa_cache_all = true + +### List of Files for the PWA to initially Cache, used if pwa_cache_all = false +pwa_BASE_CACHE_FILES = "'/js/theme.min.js','/js/theme_light.min.js','/abridge.css','/js/abridge.min.js','/','/404.html','/offline/','/manifest.min.json'" + +############################################################################### +### Favicons, comment out a line to disable loading some or all of these if needed. +############################################################################### + +favicon_theme_color = "#333333" +favicon_ms_color = "#333333" +favicon_mask = "safari-pinned-tab.svg" # safari-pinned-tab.svg +favicon_mask_color = "#ff9900" +#favicon_svg = "favicon.svg" # favicon.svg +#favicon180 = "apple-touch-icon.png" # apple-touch-icon.png +#favicon32 = "favicon-32x32.png" # favicon-32x32.png +#favicon16 = "favicon-16x16.png" # favicon-16x16.png + + +############################################################################### +### Icons +### Loading the entire fontawesome icon collection will negatively impact your sites performance. +### For a lightweight solution consider adding only the icons that you need to the following file: +### https://github.com/Jieiku/abridge/blob/master/sass/include/_icons.scss +############################################################################### + +### To disable any of these icons set them to "false" (will default to unicode icons instead) +#icon_search = "svgs search" # Search button in search box. +#icon_adjust = "svgs adjust" # Theme Switcher button in top menu. (add class svgh to change colors on hover) +#icon_first = "svgs svgh angll" # Pagination First Page. +#icon_prev = "svgs svgh angl" # Pagination Previous Page. +#icon_next = "svgs svgh angr" # Pagination Next Page. +#icon_last = "svgs svgh angrr" # Pagination Last Page. +#icon_top = "svgs svgh angu" # Back to Top Button. + +#icon_read = "svgs fa-solid fa-glasses" # displayed in metadata on index and below title on page. +#icon_date = "svgs fa-solid fa-calendar" # displayed in metadata on index and below title on page. +#icon_info = "svgs fa-solid fa-circle-info" # displayed in metadata on index and below title on page for categories/tags +#icon_author = "svgs fa-solid fa-pen-fancy" # displayed in metadata on index and below title on page. + +### Uncomment below line to load fontawesome, eg: +#fontawesome = "https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.1.1/css/all.min.css" +#icon_read = "svgs fa-solid fa-glasses" # displayed in metadata on index and below title on page. +#icon_date = "svgs fa-solid fa-calendar" # displayed in metadata on index and below title on page. +#icon_info = "svgs fa-solid fa-circle-info" # displayed in metadata on index and below title on page for categories/tags +#icon_author = "svgs fa-solid fa-pen-fancy" # displayed in metadata on index and below title on page. + + +############################################################################### +### Security Settings +### Security Headers should preferably be set by your webserver (Nginx, Apache) +### https://observatory.mozilla.org https://csp-evaluator.withgoogle.com/ +### If you are unable to load your security headers with your webserver, this will load a couple of them as meta tags. +### There are many other security related headers most of which can only be set by the webserver method. +### If you happen to use Netlify, you can define all the headers in your netlify.toml file: +### https://github.com/Jieiku/abridge/blob/master/netlify.toml +### UnComment any of these lines to enable their meta tags. +############################################################################### + +#security_header_referrer = "strict-origin-when-cross-origin" + +#security_header_csp = "default-src 'none'; object-src 'none'; base-uri 'self'; manifest-src 'self'; connect-src 'self'; form-action 'self'; script-src 'self'; img-src 'self' data: cdn.cloudflare.com; frame-src 'self' www.youtube-nocookie.com player.vimeo.com; media-src 'self' data: cdn.cloudflare.com www.youtube-nocookie.com player.vimeo.com; font-src 'self' cdn.cloudflare.com cdn.jsdelivr.net fonts.gstatic.com; style-src 'self' cdn.cloudflare.com cdn.jsdelivr.net fonts.googleapis.com;" + + +############################################################################### +### FONTS - Abridge by default uses the System Font Stack +### https://css-tricks.com/snippets/css/system-font-stack/ +### However if you need you can load a specific font below, +### make sure to have the relevant woff2 fonts in your static/fonts folder +### I measured the least Cumulative Layout Shift with: Roboto, Lato, Arimo +############################################################################### + +### For externally loaded Fonts, make sure to include the FULL url including the https prefix: + +#fonts = [ {url = "https://fonts.googleapis.com/css?family=Roboto:400,700,italic|Roboto+Mono:400,italic"} ] + +### Local fonts are defined in the css, https://github.com/Jieiku/abridge/tree/master/COPY-TO-ROOT-SASS/fonts/_Arimo.scss +### To load a local font resource, look at the bottom of this file: https://github.com/Jieiku/abridge/blob/master/COPY-TO-ROOT-SASS/abridge.scss + +### After loading them in the CSS, You can also define them below and it will add the preload tag to the head. +### preloading fonts will eliminate Content Layout Shift, but will hurt with page load time. (not recommended) + +#fonts = [ +# {url = "fonts/Roboto-Mono.woff2"}, +# {url = "fonts/Roboto-Mono-Italic.woff2"}, +# {url = "fonts/Roboto.woff2"}, +# {url = "fonts/Roboto-Italic.woff2"}, +# {url = "fonts/Roboto-Bold.woff2"}, +#] + + +############################################################################### +### Katex - math js library, used to to render mathematical notations +### It's best to enable katex on a per page bases as I did here: +### https://abridge.netlify.app/overview-math/ +### https://github.com/Jieiku/abridge/blob/master/content/overview-math.md?plain=1#L11-L13 +### Otherwise you will load the katex related javascript on every page! +############################################################################### + +#katex_options = "js/katexoptions.js" +#katex_bundle = "js/katexbundle.min.js" + +### Load Katex Local Resources +#katex_css = "katex.min.css" # Fonts - load the css/fonts locally +#katex_js = "js/katex.min.js" # use local js, so that we dont have to whitelist cdn.jsdelivr.net for script src in CSP +#mathtex_js = "js/mathtex-script-type.min.js" # use local js, so that we dont have to whitelist cdn.jsdelivr.net for script src in CSP +#katex_autorender_js = "js/katex-auto-render.min.js" + +### Load Katex External Resources +#katex_css = "https://cdn.jsdelivr.net/npm/katex@0.15.6/dist/katex.min.css" # Fonts - use remote fonts +#katex_css_integrity = "sha384-ZPe7yZ91iWxYumsBEOn7ieg8q/o+qh/hQpSaPow8T6BwALcXSCS6C6fSRPIAnTQs" +#katex_js = "https://cdn.jsdelivr.net/npm/katex@0.15.6/dist/katex.min.js" +#katex_js_integrity = "sha384-ljao5I1l+8KYFXG7LNEA7DyaFvuvSCmedUf6Y6JI7LJqiu8q5dEivP2nDdFH31V4" +#katex_autorender_js = "https://cdn.jsdelivr.net/npm/katex@0.15.6/dist/contrib/auto-render.min.js" +#katex_autorender_js_integrity = "sha384-+XBljXPPiv+OzfbB3cVmLHf4hdUFHlWNZN5spNQ7rmHTXpd7WvJum6fIACpNNfIR" +#mathtex_js = "https://cdn.jsdelivr.net/npm/katex@0.15.6/dist/contrib/mathtex-script-type.min.js" +#mathtex_js_integrity = "sha384-jiBVvJ8NGGj5n7kJaiWwWp9AjC+Yh8rhZY3GtAX8yU28azcLgoRo4oukO87g7zDT" + +#math = false # Recommended setting false, and enable on per page bases instead. +#math_auto_render = false # Recommended setting false, and enable on per page bases instead. diff --git a/content/2017/12/18/varlink.md b/content/2017/12/18/varlink.md index e62c0e6..87c63ef 100644 --- a/content/2017/12/18/varlink.md +++ b/content/2017/12/18/varlink.md @@ -148,7 +148,7 @@ and ``` will output: -``` +```text root 0 /bin/bash ``` diff --git a/content/_index.md b/content/_index.md index fc33cfa..e438d6a 100644 --- a/content/_index.md +++ b/content/_index.md @@ -1,4 +1,7 @@ +++ -paginate_by = 10 +paginate_by = 5 sort_by = "date" +template = "index.html" +[extra] +logo = { file="img/home-bg.jpg", width="32", height="32", alt="Abridge", text="bridge" } +++ diff --git a/content/archive/_index.es.md b/content/archive/_index.es.md new file mode 100644 index 0000000..85198a5 --- /dev/null +++ b/content/archive/_index.es.md @@ -0,0 +1,6 @@ ++++ +template = "archive.html" + +[extra] +sec = "" ++++ diff --git a/content/archive/_index.fr.md b/content/archive/_index.fr.md new file mode 100644 index 0000000..85198a5 --- /dev/null +++ b/content/archive/_index.fr.md @@ -0,0 +1,6 @@ ++++ +template = "archive.html" + +[extra] +sec = "" ++++ diff --git a/content/archive/_index.md b/content/archive/_index.md new file mode 100644 index 0000000..85198a5 --- /dev/null +++ b/content/archive/_index.md @@ -0,0 +1,6 @@ ++++ +template = "archive.html" + +[extra] +sec = "" ++++ diff --git a/content/pages/impressum.md b/content/pages/impressum.md index 9e67307..67b23b5 100644 --- a/content/pages/impressum.md +++ b/content/pages/impressum.md @@ -2,7 +2,7 @@ title = "Impressum" path = "impressum" date = 2000-01-01 -template = "impressum.html" +template = "pages.html" +++ # Impressum diff --git a/content/pages/privacy.md b/content/pages/privacy.md new file mode 100644 index 0000000..1b7eec5 --- /dev/null +++ b/content/pages/privacy.md @@ -0,0 +1,15 @@ ++++ +title = "Privacy Policy" +description = "This page outlines the Privacy Policy for this site, and the date at which this policy was put into affect." +path = "privacy" +template = "pages.html" +draft = false ++++ + +## Privacy + +- This site does not set or use cookies. +- This site does not store data in the browser to be shared, sent, or sold to third-parties. +- No personal information is shared, sent, or sold to third-parties. + +**Effective Date:** _1st Jan 2022_ diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 0000000..c38966d --- /dev/null +++ b/netlify.toml @@ -0,0 +1,95 @@ +[build] +publish = "public" +command = "zola build && npm run abridge && zola build" + +[build.environment] +ZOLA_VERSION = "0.17.2" + +[context.deploy-preview] +command = "zola build --base-url $DEPLOY_PRIME_URL && npm run abridge && zola build --base-url $DEPLOY_PRIME_URL" + +[[headers]] + for = "/*" + [headers.values] + X-Frame-Options = "DENY" + X-Content-Type-Options = "nosniff" + X-XSS-Protection = "1; mode=block" + Referrer-Policy = "strict-origin-when-cross-origin" + Strict-Transport-Security = "max-age=63072000; includeSubdomains" + Content-Security-Policy = "default-src 'none'; frame-ancestors 'none'; object-src 'none'; base-uri 'self'; manifest-src 'self'; worker-src 'self'; form-action 'self'; connect-src 'self' *.hyvor.com ws://*.hyvor.com; script-src 'self' talk.hyvor.com; img-src 'self' data: talk.hyvor.com cdn.cloudflare.com; frame-src 'self' www.youtube-nocookie.com player.vimeo.com streamable.com www.streamable.com; media-src 'self' data: cdn.cloudflare.com www.youtube-nocookie.com player.vimeo.com; font-src 'self' cdn.cloudflare.com cdn.jsdelivr.net fonts.gstatic.com; style-src 'self' talk.hyvor.com cdn.cloudflare.com cdn.jsdelivr.net fonts.googleapis.com;" +[[headers]] + for = "*.js"#javascript + [headers.values] + Cache-Control = "public, max-age=604800, must-revalidate" +[[headers]] + for = "*.css"#stylesheet + [headers.values] + Cache-Control = "public, max-age=604800, must-revalidate" +[[headers]] + for = "*.svg"#image/favicon + [headers.values] + Cache-Control = "public, max-age=604800" +[[headers]] + for = "*.png"#image/favicon + [headers.values] + Cache-Control = "public, max-age=604800" +[[headers]] + for = "*.ico"#image/favicon + [headers.values] + Cache-Control = "public, max-age=604800" +[[headers]] + for = "*.jpg"#image + [headers.values] + Cache-Control = "public, max-age=604800" +[[headers]] + for = "*.jpeg"#image + [headers.values] + Cache-Control = "public, max-age=604800" +[[headers]] + for = "*.gif"#image + [headers.values] + Cache-Control = "public, max-age=604800" +[[headers]] + for = "*.webp"#image + [headers.values] + Cache-Control = "public, max-age=604800" +[[headers]] + for = "*.avif"#image + [headers.values] + Cache-Control = "public, max-age=604800" +[[headers]] + for = "*.mp4"#video + [headers.values] + Cache-Control = "public, max-age=604800" +[[headers]] + for = "*.webm"#video + [headers.values] + Cache-Control = "public, max-age=604800" +[[headers]] + for = "*.mp3"#audio + [headers.values] + Cache-Control = "public, max-age=604800" +[[headers]] + for = "*.ogg"#audio + [headers.values] + Cache-Control = "public, max-age=604800" +[[headers]] + for = "*.otf"#font + [headers.values] + Cache-Control = "public, max-age=604800" +[[headers]] + for = "*.eot"#font + [headers.values] + Cache-Control = "public, max-age=604800" +[[headers]] + for = "*.ttf"#font + [headers.values] + Cache-Control = "public, max-age=604800" +[[headers]] + for = "*.woff"#font + [headers.values] + Cache-Control = "public, max-age=604800" +[[headers]] + for = "*.woff2"#font + [headers.values] + Cache-Control = "public, max-age=604800" diff --git a/package.json b/package.json new file mode 100644 index 0000000..bfbf0eb --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "abridge-bundle", + "version": "2.0.0", + "description": "Abridge - set PWA cache files list, bundle and minify js", + "author": "Jake G <106644+Jieiku@users.noreply.github.com>", + "license": "MIT", + "homepage": "https://github.com/Jieiku/abridge", + "scripts": { + "abridge": "node -e \"if ( require('fs').existsSync('./themes/abridge/package_abridge.js')) {require('fs').copyFileSync('./themes/abridge/package_abridge.js', './package_abridge.js')}\" && node package_abridge.js" + }, + "dependencies": { + "fast-toml": "^0.5.4", + "uglify-js": "^3.17.4", + "jsonminify": "^0.4.2", + "replace-in-file": "^7.0.1" + } +} diff --git a/package_abridge.js b/package_abridge.js new file mode 100644 index 0000000..52c704e --- /dev/null +++ b/package_abridge.js @@ -0,0 +1,276 @@ +const fs = require('fs'); +const path = require("path"); +const TOML = require('fast-toml'); +const UglifyJS = require('uglify-js'); +const jsonminify = require("jsonminify"); +const replace = require('replace-in-file'); +const util = require("util"); +const { exec } = require("child_process"); +const execPromise = util.promisify(exec); + +const tomlString = String(fs.readFileSync('config.toml')); +const data = TOML.parse(tomlString); +const js_prestyle = data.extra.js_prestyle; +const js_switcher = data.extra.js_switcher; +const js_email_encode = data.extra.js_email_encode; +const js_copycode = data.extra.js_copycode; +const search_library = data.extra.search_library; +const index_format = data.search.index_format; +const uglyurls = data.extra.uglyurls; +const js_bundle = data.extra.js_bundle; +const offline = data.extra.offline; +const online_url = data.extra.online_url; +const online_indexformat = data.extra.online_indexformat; +const pwa = data.extra.pwa; +const pwa_VER = data.extra.pwa_VER; +const pwa_NORM_TTL = data.extra.pwa_NORM_TTL; +const pwa_LONG_TTL = data.extra.pwa_LONG_TTL; +const pwa_TTL_NORM = data.extra.pwa_TTL_NORM; +const pwa_TTL_LONG = data.extra.pwa_TTL_LONG; +const pwa_TTL_EXEMPT = data.extra.pwa_TTL_EXEMPT; +const pwa_cache_all = data.extra.pwa_cache_all; +const pwa_BASE_CACHE_FILES = data.extra.pwa_BASE_CACHE_FILES; + +async function execWrapper(cmd) { + const { stdout, stderr } = await execPromise(cmd); + if (stdout) { + console.log(stdout); + } + if (stderr) { + console.log('Error: '+stderr); + } +} + +async function abridge() { + if (offline === false) { + replace.sync({files: 'config.toml', from: /base_url.*=.*/g, to: "base_url = \""+online_url+"\""}); + replace.sync({files: 'config.toml', from: /index_format.*=.*/g, to: "index_format = \""+online_indexformat+"\""}); + } else if (offline === true) { + replace.sync({files: 'config.toml', from: /base_url.*=.*/g, to: "base_url = \""+__dirname+"\/public\""}); + replace.sync({files: 'config.toml', from: /index_format.*=.*/g, to: "index_format = \"elasticlunr_javascript\""}); + } + + console.log('Zola Build to generate files for minification:'); + await execWrapper('zola build'); + + //check that static/js exists, do this after zola build, it will handle creating static if missing. + var jsdir = 'static/js'; + try { + fs.mkdirSync(jsdir); + } catch(e) { + if (e.code != 'EEXIST') throw e; + } + + // check if abridge is used directly or as a theme. + bpath = ''; + if (fs.existsSync('./themes')) { + bpath = 'themes/abridge/'; + } + + base_url = data.base_url; + if (base_url.slice(-1) == "/") { + base_url = base_url.slice(0, -1); + } + + if (search_library === 'elasticlunr') { + if (fs.existsSync('content/static/stork_toml.md')) { + replace.sync({files: 'content/static/stork_toml.md', from: /draft.*=.*/g, to: "draft = true"}); + } + if (fs.existsSync('content/static/tinysearch_json.md')) { + replace.sync({files: 'content/static/tinysearch_json.md', from: /draft.*=.*/g, to: "draft = true"}); + } + } else if (search_library === 'tinysearch') { + if (!fs.existsSync('content/static/tinysearch_json.md')) {// 'content/static/tinysearch_json.md' file is missing, copy from abridge theme. + fs.copyFileSync(bpath+'content/static/tinysearch_json.md', 'content/static/tinysearch_json.md',fs.constants.COPYFILE_EXCL); + } + if (fs.existsSync('content/static/stork_toml.md')) { + replace.sync({files: 'content/static/stork_toml.md', from: /draft.*=.*/g, to: "draft = true"}); + } + if (fs.existsSync('content/static/tinysearch_json.md')) { + replace.sync({files: 'content/static/tinysearch_json.md', from: /draft.*=.*/g, to: "draft = false"}); + } + // zola build && mkdir -p tmp && tinysearch --optimize --path tmp public/data_tinysearch/index.html && rsync -avz tmp/*.wasm static/ && rm -rf tmp + } else if (search_library === 'stork') { + + if (!fs.existsSync('content/static/stork_toml.md')) {// 'content/static/stork_toml.md' file is missing, copy from abridge theme. + fs.copyFileSync(bpath+'content/static/stork_toml.md', 'content/static/stork_toml.md',fs.constants.COPYFILE_EXCL); + } + if (fs.existsSync('content/static/stork_toml.md')) { + replace.sync({files: 'content/static/stork_toml.md', from: /draft.*=.*/g, to: "draft = false"}); + } + if (fs.existsSync('content/static/tinysearch_json.md')) { + replace.sync({files: 'content/static/tinysearch_json.md', from: /draft.*=.*/g, to: "draft = true"}); + } + // zola build && stork build --input public/data_stork/index.html --output static/stork.st + } + + if (pwa) {// Update pwa settings, file list, and hashes. + // update from abridge theme. + fs.copyFileSync(bpath+'static/sw.js', 'static/sw.js'); + fs.copyFileSync(bpath+'static/js/sw_load.js', 'static/js/sw_load.js'); + // Update settings in PWA javascript file, using options parsed from config.toml. sw.min.js?v=3.10.0", "++" + if (fs.existsSync('static/js/sw_load.js')) { + sw_load_min = '.js?v='; + if (js_bundle) { + sw_load_min = '.min.js?v='; + } + replace.sync({files: 'static/js/sw_load.js', from: /sw.*v=.*/g, to: "sw"+sw_load_min+pwa_VER+"\","}); + } + if (fs.existsSync('static/sw.js')) { + replace.sync({files: 'static/sw.js', from: /NORM_TTL.*=.*/g, to: "NORM_TTL = "+pwa_NORM_TTL+";"}); + replace.sync({files: 'static/sw.js', from: /LONG_TTL.*=.*/g, to: "LONG_TTL = "+pwa_LONG_TTL+";"}); + replace.sync({files: 'static/sw.js', from: /TTL_NORM.*=.*/g, to: "TTL_NORM = ["+pwa_TTL_NORM+"];"}); + replace.sync({files: 'static/sw.js', from: /TTL_LONG.*=.*/g, to: "TTL_LONG = ["+pwa_TTL_LONG+"];"}); + replace.sync({files: 'static/sw.js', from: /TTL_EXEMPT.*=.*/g, to: "TTL_EXEMPT = ["+pwa_TTL_EXEMPT+"];"}); + } + + if (pwa_cache_all) { + // Generate array from the list of files, for the entire site. + + var dir = 'public'; + try { + fs.mkdirSync(dir); + } catch(e) { + if (e.code != 'EEXIST') throw e; + } + const path = './public/'; + cache = 'this.BASE_CACHE_FILES = ['; + files = fs.readdirSync(path, { recursive: true, withFileTypes: false }) + .forEach( + (file) => { + // check if is directory, if not then add the path/file + if (!fs.lstatSync(path+file).isDirectory()) { + // format output + item = "/"+file.replace(/index\.html$/i,'');// strip index.html from path + item = item.replace(/^\/sw(\.min)?\.js/i,'');// dont cache service worker + + // if formatted output is not empty line then append it to cache var + if (item != '') {// skip empty lines + cache = cache+"'"+item+"',"; + } + } + } + ); + cache = cache.slice(0, -1)+'];'// remove the last comma and close the array + } else if (pwa_BASE_CACHE_FILES) { + cache = 'this.BASE_CACHE_FILES = ['+pwa_BASE_CACHE_FILES+'];'; + } + + // update the BASE_CACHE_FILES variable in the sw.js service worker file + results = replace.sync({ + files: 'static/sw.js', + from: /this\.BASE_CACHE_FILES =.*/g, + to: cache, + countMatches: true, + }); + } + + if (bpath === '') {// abridge used directly + // These are truely static js files, so they should only need to be updated by abridge maintainer or contributors. + minify(['static/js/theme.js']); + minify(['static/js/theme_light.js']); + minify(['static/js/katex.min.js','static/js/mathtex-script-type.min.js','static/js/katex-auto-render.min.js','static/js/katexoptions.js'],'static/js/katexbundle.min.js'); + minify(['static/js/elasticlunr.min.js','static/js/search.js'],'static/js/search_elasticlunr.min.js'); + minify(['static/js/stork.js','static/js/stork_config.js'],'static/js/search_stork.min.js'); + minify(['static/js/tinysearch.js'],'static/js/search_tinysearch.min.js'); + minify(['static/js/prestyle.js','static/js/theme_button.js','static/js/email.js','static/js/codecopy.js','static/js/sw_load.js'],'static/js/abridge_nosearch.min.js'); + minify(['static/js/prestyle.js','static/js/theme_button.js','static/js/email.js','static/js/codecopy.js'],'static/js/abridge_nosearch_nopwa.min.js'); + minify(['static/js/sw_load.js']); + minify(['static/sw.js']); + } else if (pwa) { + minify(['static/js/sw_load.js']); + minify(['static/sw.js']); + } + + // if manifest.json is present, then minify it. + if (fs.existsSync('static/manifest.json')) { + let out; + try { + out = JSON.minify(fs.readFileSync('static/manifest.json', {encoding:"utf-8"})); + } catch(err) { + console.log(err); + } + fs.writeFileSync('static/manifest.min.json', out); + } + + abridge_bundle = bundle(bpath,js_prestyle,js_switcher,js_email_encode,js_copycode,search_library,index_format,uglyurls,false); + minify(abridge_bundle,'static/js/abridge_nopwa.min.js'); + + abridge_bundle = bundle(bpath,js_prestyle,js_switcher,js_email_encode,js_copycode,search_library,index_format,uglyurls,pwa); + minify(abridge_bundle,'static/js/abridge.min.js'); + + console.log('Zola Build to generate new integrity hashes for the previously minified files:'); + await execWrapper('zola build'); +} + +function bundle(bpath,js_prestyle,js_switcher,js_email_encode,js_copycode,search_library,index_format,uglyurls,pwa) { + minify_files = []; + + if (js_prestyle) { + minify_files.push(bpath+'static/js/prestyle.js'); + } + if (js_switcher) { + minify_files.push(bpath+'static/js/theme_button.js'); + } + if (js_email_encode) { + minify_files.push(bpath+'static/js/email.js'); + } + if (js_copycode) { + minify_files.push(bpath+'static/js/codecopy.js'); + } + if (search_library) { + if ((search_library === 'elasticlunr' && offline === true) || (search_library === 'elasticlunr' && index_format === 'elasticlunr_javascript' && uglyurls === true)) { + minify_files.push('public/search_index.en.js'); + minify_files.push(bpath+'static/js/elasticlunr.min.js'); + minify_files.push(bpath+'static/js/searchjavaugly.js'); + } else if (search_library === 'elasticlunr' && index_format === 'elasticlunr_javascript') { + minify_files.push('public/search_index.en.js'); + minify_files.push(bpath+'static/js/elasticlunr.min.js'); + minify_files.push(bpath+'static/js/searchjava.js'); + } else if (search_library === 'elasticlunr') {//abridge default + minify_files.push(bpath+'static/js/elasticlunr.min.js'); + minify_files.push(bpath+'static/js/search.js'); + } else if (search_library === 'stork') { + minify_files.push(bpath+'static/js/stork.js'); + minify_files.push(bpath+'static/js/stork_config.js'); + } else if (search_library === 'tinysearch') { + minify_files.push(bpath+'static/js/tinysearch.js'); + } + } + if (pwa) { + minify_files.push('static/js/sw_load.js'); + } + return minify_files; +} + +function minify(fileA,outfile) { + const options = { + mangle: true, + compress: { + //expression: true,//Parse a single expression, rather than a program (for parsing JSON). + //global_defs: false,// a way to pass parameters + //module: true,//Process input as ES module (implies --toplevel) + //toplevel: true,//Compress and/or mangle variables in top level scope. + hoist_funs: true,//hoist function declarations + unsafe: true, + unsafe_comps: true, + unsafe_Function: true, + unsafe_math: true, + unsafe_proto: true, + unsafe_regexp: true, + unsafe_undefined: true, + drop_console: true + } + } + if (!outfile) {// outfile parameter omitted, infer based on input + outfile = fileA[0].slice(0,-2)+'min.js'; + } + var filesContents = fileA.map(function (file) {// array input to support multiple files + return fs.readFileSync(file, 'utf8'); + }); + + result = UglifyJS.minify(filesContents, options); + fs.writeFileSync(outfile, result.code); +} + +abridge(); diff --git a/sass/_extra.scss b/sass/_extra.scss new file mode 100644 index 0000000..42d9392 --- /dev/null +++ b/sass/_extra.scss @@ -0,0 +1,3 @@ +/****************************************************************************** + * Extra - Put your extra SASS/CSS here, it will get bundled with abridge.css + *****************************************************************************/ diff --git a/sass/abridge.scss b/sass/abridge.scss new file mode 100644 index 0000000..a429461 --- /dev/null +++ b/sass/abridge.scss @@ -0,0 +1,205 @@ +@use '../themes/abridge/sass/abridge' with ( + /// LINES HERE END WITH COMMA AFTER THE VALUE! + /// The things your less likely to need to override have been commented out. + + /// Enable a centered viewport for
,
,