commit 02b3edf6668b5f03362bf61e1379e0faf6a01034 Author: Hamza Ali Date: Wed Jul 6 20:45:22 2022 +0500 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7e34696 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ + +resources/_gen +public diff --git a/archetypes/default.md b/archetypes/default.md new file mode 100644 index 0000000..00e77bd --- /dev/null +++ b/archetypes/default.md @@ -0,0 +1,6 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +date: {{ .Date }} +draft: true +--- + diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..9634070 --- /dev/null +++ b/config.toml @@ -0,0 +1,188 @@ +baseURL = "https://blog.teamortix.com" +title = "Team Ortix | Blog" +languageCode = "en-us" +theme = "hello-friend-ng" + +PygmentsCodeFences = false + +paginate = 10 +rssLimit = 10 # Maximum number of items in the RSS feed. +copyright = "This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License." # This message is only used by the RSS template. + +archetypeDir = "archetypes" +contentDir = "content" +dataDir = "data" +layoutDir = "layouts" +publishDir = "public" + +buildDrafts = false +buildFuture = false +buildExpired = false +canonifyURLs = false + +enableRobotsTXT = true +enableGitInfo = false +enableEmoji = true +enableMissingTranslationPlaceholders = false +disableRSS = false +disableSitemap = false +disable404 = false +disableHugoGeneratorInject = false + +[permalinks] + posts = "/posts/:year/:month/:title/" + +[author] + name = 'Hamza Ali and Chan Wen Xu' + +[markup] +defaultMarkdownHandler = 'goldmark' + [markup.goldmark] + [markup.goldmark.extensions] + linkify = false + [markup.goldmark.parser] + autoHeadingID = true + autoHeadingIDType = "github" + [markup.goldmark.parser.attribute] + block = true + title = true + +[markup.tableOfContents] +endLevel = 4 +ordered = false +startLevel = 2 + +[taxonomies] + tag = "tags" + category = "categories" + series = "series" + +[params] + dateform = "Jan 2, 2006" + dateformShort = "Jan 2" + dateformNum = "2006-01-02" + dateformNumTime = "2006-01-02 15:04" + themeColor = "#f2203a" + + # Metadata mostly used in document's head + # + description = "The blog for hhhapz - Hamza Ali" + keywords = "" + images = [""] + + # Home subtitle of the index page. + # + subtitle = "idk" + + + # Set a background for the homepage + # backgroundImage = "assets/images/background.jpg" + + # Prefix of link to the git commit detail page. GitInfo must be enabled. + # + # gitUrl = "" + + # Set disableReadOtherPosts to true in order to hide the links to other posts. + # + disableReadOtherPosts = false + + # Enable theme toggle + # + # This options enables the theme toggle for the theme. + # Per default, this option is off. + # The theme is respecting the prefers-color-scheme of the operating systeme. + # With this option on, the page user is able to set the scheme he wants. + enableThemeToggle = true + + # Sharing buttons + # + # There are a lot of buttons preconfigured. If you want to change them, + # generate the buttons here: https://sharingbuttons.io + # and add them into your own `layouts/partials/sharing-buttons.html` + # + enableSharingButtons = false + + # Integrate Javascript files or stylesheets by adding the url to the external assets or by + # linking local files with their path relative to the static folder, e.g. "css/styles.css" + # + customCSS = [ "/one-dark.css" ] + customJS = [] + + # Toggle this option need to rebuild SCSS, requires extended version of Hugo + # + justifyContent = false # Set "text-align: justify" to .post-content. + + # Custom footer + # If you want, you can easily override the default footer with your own content. + # + [params.footer] + trademark = true + rss = true + copyright = true + author = true + + topText = [] + bottomText = [ + "Powered by Hugo" + ] + + # Colors for favicons + # + [params.favicon.color] + mask = "#f2203a" + msapplication = "#f2203a" + theme = "#f2203a" + + [params.logo] + path = "/logo-192.png" + logoMark = "$" + logoText = "/hhhapz" + logoHomeLink = "/" + # Set true to remove the logo cursor entirely. + # logoCursorDisabled = false + # Set to a valid CSS color to change the cursor in the logo. + logoCursorColor = "#f2203a" + # Set to a valid CSS time value to change the animation duration, "0s" to disable. + # logoCursorAnimate = "2s" + + # Commento is more than just a comments widget you can embed — + # it’s a return to the roots of the internet. + # An internet without the tracking and invasions of privacy. + # An internet that is simple and lightweight. + # An internet that is focused on interesting discussions, not ads. + # A better internet. + # Uncomment this to enable Commento. + # + # [params.commento] + # url = "" + + # Uncomment this if you want a portrait on your start page + # + # [params.portrait] + # path = "/img/image.jpg" + # alt = "Portrait" + # maxWidth = "50px" + + [[params.social]] + name = "email" + url = "mailto:hamza@teamortix.com" + + [[params.social]] + name = "github" + url = "https://github.com/teamortix" + +[languages] + [languages.en] + subtitle = "" + weight = 1 + copyright = 'CC BY-NC 4.0' + +[menu] + [[menu.main]] + identifier = "about" + name = "About" + url = "about/" + [[menu.main]] + identifier = "posts" + name = "Posts" + url = "posts/" diff --git a/content/about.md b/content/about.md new file mode 100644 index 0000000..491bd6d --- /dev/null +++ b/content/about.md @@ -0,0 +1,35 @@ +--- +title: "About" +date: "2021-08-16" +date: 2021-08-17T01:30:19+07:00 +Description: "About blog.teamortix.com" +--- + +Hey \o + +--- + +This is just a simple blog. + +A place for members of Team Ortix to share thoughts. + +Members: + +- **hhhapz**: + + - Hamza Ali + - [GitHub](https://github.com/hhhapz) + - [Email](mailto:hamza@teamortix.com) + +- **chanbakjsd**: + + - Chan Wen Xu + - [GitHub](https://github.com/chanbakjsd) + - [Email](mailto:chan@teamortix.com) + +> Team Ortix is just a team of developers. + +--- + +Have a vulnerability or issue to report? Please report it +[here](https://teamortix.com/.well-known/security.txt). diff --git a/content/posts/go-databases.md b/content/posts/go-databases.md new file mode 100644 index 0000000..d8a79e9 --- /dev/null +++ b/content/posts/go-databases.md @@ -0,0 +1,224 @@ +--- +title: "Go Databases" +tinyname: "go_databases" +date: 2021-08-13T20:56:12+07:00 +toc: true +description: |- + There are a plethora of libraries available in Go. + Here is a list of libraries that may be of interest. +tags: + - go + - databases + - sql +author: + name: Hamza Ali + url: https://github.com/hhhapz +--- + +> This is currently under construction and incomplete. + +## Prelude + +When working on a Go project, there comes a time where you application needs +a database. As a developer, you have a plethora of options to pick from, some +good, others not so much. As a new developer, making a decision can be +difficult, especially when treading blind. + +My goal with this post is to share some perspective and evaluate the different +tools that are available in the Go ecosystem. Perhaps you will be able to find +a new tool that helps reduce your code complexity, or gain more perspective +about why some other libraries might not be as appealing as they seem. + +--- + +## What are my options? {#options} + +I plan to compare a half dozen different libraries here that accomplish +different goals. There may be other similar tools that accomplish similar +goals, which I have omitted. + +If you would like to suggest another tool, feel free to send me an [email](mailto:hamza@teamortix.com). + +Apart from these tools, I strongly believe that looking for libraries that are +compatible with the Go standard library (`database/sqlite`) is really +important. All the tools I mentioned will work seamlessly with it. + +- Utility libraries + + - **[github.com/jmoiron/sqlx](https://github.com/jmoiron/sqlx)** + + Quoting the README of the repository, sqlx is a library which provides + extensions on Go's standard `database/sql` library with marshalling from + sql rows to Go types. + + - **[github.com/keengancsmith/sqlf](https://github.com/keegancsmith/sqlf)** + + Create SQL queries that are safe from injections with printf, making + composing queries and working with dynamic number of arguments (more on + this later). + + - **[github.com/Masterminds/squirrel](https://github.com/Masterminds/squirrel)** + + A highly composable SQL generator for Go. Using a builder pattern, this + library can really help writing SQL queries in a type safe manner. + +- Code generation libraries + + - **[github.com/xo/xo](https://github.com/xo/xo)** + + A code generation libraries that creates a model and CRUD operations from + your database, and generate type-safe functions from queries. (Limited + Documentation) + + - **[github.com/kyleconrow/sqlc](https//github.com/kyleconrow/sqlc)** + + Similar to xo, a different style code generation library that should be + mentioned seperately. Generates code by parsing your SQL. + +- Object Relational Mappers - Map Go types in SQL and ORM likes. + + - **[github.com/ent/ent](https://github.com/ent/ent)** + + A composable entity framework that emphasizes on user control. + +--- + +## What about GORM or XORM? {#gorm} + +To much of my disappointment, many developers who work with Go fall in the trap +of using an ORM. This is really, really tempting to do, however there are +a number of flaws that most, if not all of these libraries exhibit, which can +severely cripple your project. + +### What you Gain {#gain} + +Firstly, it is difficult to deny that these libraries do appeal thousands of +developers. While not being the most accurate metric by any means, it is still +a strong indicator. GORM has almost 25,000 stars (at the time of writing this +post) on GitHub and Xorm has over 6,000 on its archived Github. + +I will try to explain why many features ORMs are often celebrated and praised +are in fact a source of never ending gotchas. + +#### 1. No need for SQL {#no-sql} + +Many beginners fall into the trap of using an ORM because it means they don't +need to learn SQL, which can often come across as being challenging or +daunting. A complete new query language, which has its own quirks, learning +about selects, updates, *joins*, *indexes*? + +From their point of shoes, all of this programmer jargon can be easily avoided +and ORMs are the way to go. + +> *ORMs rules, SQL drools*. + +In the contrary, I believe that if you are writing a backend application, +knowing SQL is a prerequisite. As an analogy, imagine trying to use a styling +framework, such as Bootstrap or TailwindCSS, without knowing CSS. Most people +would agree that attempting to use it without knowing CSS is a recipe for +botched styling that is terrible to maintain, and generally a recipe for +disaster. + +Similarly, writing SQL with clean queries that tell both, yourself and your +database exactly what to do ensure a healthy architecture that is both easy to +debug, extend, and refactor. + +#### 2. Magically Simple {#magical} + +ORMs are magic. You can call `db.Find(&users)`, and boom! All your rows are +returned. A simple filter can be done trivially. `db.First(&user, 10)` will +query the user whose primary key matches 10. However, there is a pain point +that always surfaces when a project uses an ORM more and more. + +As a user, writing calling functions like `Find`, `Take`, `First`, `Last` lead +to a loss of control. You no longer have the ability to tune or modify your +queries. + +This works fine for simple use cases, however, when pushing these to their +limits, (which is not very far). + +For example, updating rows to the zero value of the Go type will simply be +ignored. This usually makes sense, however, very quickly turns into messy +design and hacks, such as resorting to pointer field types, or just returning +back to good old plain SQL. + +Complex functionality (SQL) abstracted with another "simpler" layer (your ORM) +always poses the lingering risk of *increasing* complexity through complex +wrappers and hacks. + +#### 3. Easy Migrations {#migrations} + +ORMs always promote having the ability to automagically handle migrating your +schema as your Go data structures change. While valid, again, these migrations +are generally done under the hood, and leave you, the user with very little +control. + +Furthermore, many tools exist already that already handle database migrations +significantly more effectively, and give you more fine-tuning power, so that +you always are able to stay in control. + +When migrations become messy or non-trivial, GORM has the potential to break, +or simply make things worse. Using tools like +[migrate](https://github.com//golang-migrate/migrate) are much better +suites, support more databases, has cleaner documentation, and is a more robust +alternative use. + +--- + +### Pain Points {#pain} + +#### 1. Finding Help {#help} + +Continuing from the points one and two, when working with an ORM, finding help +becomes monumentally more difficult. + +Finding answers for generic SQL is significantly easier to do in your favorite +search engine. You will be able to find a plethora of information about +defining foreign keys, creating indexes, composite foreign keys, and any other +SQL feature on Stack Overflow, or a database forum. When transitioning from one +database to another, for example from MS SQL Server to PostgreSQL, or from +Oracle DB to SQLite3, a large portion of your knowledge will be transferable. + +On the other side of the coin, migrating from Hibernate to Gorm leads leads to +very little directly transferable knowledge. Even if you are knowledgeable in +a SQL itself, many times you will be at the mercy of the documentation for the +ORM you are using to clearly define how to implement your use-case. + +Attempting to find information about questions or concerns you have mean having +to find not only a community specific to the language you are using, but +a subset of that community that also has experience with the very specific +library you use, which might mean the time between finding your answer being +a few searches away to a few days, or being undocumented enough that it just +may never be solved. + +#### 2. (Ab)using language features {#lang-features} + +When working in Gorm in particular, defining primary keys, indexes, and check +constraints can be described lightly as a mess. Go struct tags are overloaded +and stuffed to the brim to gain simple functionality. Here are a few examples +from the Gorm documentation: + +```go +type SomeTable struct { + // Constraints + Name string `gorm:"check:name_checker,name <> 'jinzhu'"` + + // Composite Primary Keys + CategoryID uint64 `gorm:"primaryKey;autoIncrement:false"` + TypeID uint64 `gorm:"primaryKey;autoIncrement:false"` + + // Foreign Key + CreditCard CreditCard `gorm:"foreignKey:UserName"` + + // Indexes + Name4 string `gorm:"uniqueIndex"` +} +``` + +Now, imagine if your project required a combination of these. Having a foreign +key alongside of an index, or attempting to define a many-to-many index. +Abusing struct tags make it easy to make a mistake, force you to give up all +compiler guarantees and with compile-time errors, and terrible to work with. As +a user, you are at the complete whim of the Gorm documentation, and their +support for these features, instead of having the full breadth of options and +customizability one would expect. diff --git a/layouts/_default/_markup/render-heading.html b/layouts/_default/_markup/render-heading.html new file mode 100644 index 0000000..bf15674 --- /dev/null +++ b/layouts/_default/_markup/render-heading.html @@ -0,0 +1,2 @@ +{{ .Text | safeHTML }} + diff --git a/static/android-chrome-192x192.png b/static/android-chrome-192x192.png new file mode 100644 index 0000000..b6f6d71 Binary files /dev/null and b/static/android-chrome-192x192.png differ diff --git a/static/android-chrome-512x512.png b/static/android-chrome-512x512.png new file mode 100644 index 0000000..abfb674 Binary files /dev/null and b/static/android-chrome-512x512.png differ diff --git a/static/apple-touch-icon.png b/static/apple-touch-icon.png new file mode 100644 index 0000000..950a860 Binary files /dev/null and b/static/apple-touch-icon.png differ diff --git a/static/bg-header.svg b/static/bg-header.svg new file mode 100644 index 0000000..ea2c79d --- /dev/null +++ b/static/bg-header.svg @@ -0,0 +1,373 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/browserconfig.xml b/static/browserconfig.xml new file mode 100644 index 0000000..b3930d0 --- /dev/null +++ b/static/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #da532c + + + diff --git a/static/favicon-16x16.png b/static/favicon-16x16.png new file mode 100644 index 0000000..dbf8ad4 Binary files /dev/null and b/static/favicon-16x16.png differ diff --git a/static/favicon-32x32.png b/static/favicon-32x32.png new file mode 100644 index 0000000..0984fb0 Binary files /dev/null and b/static/favicon-32x32.png differ diff --git a/static/favicon.ico b/static/favicon.ico new file mode 100644 index 0000000..0339cbc Binary files /dev/null and b/static/favicon.ico differ diff --git a/static/logo-192.png b/static/logo-192.png new file mode 100644 index 0000000..74b36fb Binary files /dev/null and b/static/logo-192.png differ diff --git a/static/logo-512.png b/static/logo-512.png new file mode 100644 index 0000000..dd99aaa Binary files /dev/null and b/static/logo-512.png differ diff --git a/static/mstile-150x150.png b/static/mstile-150x150.png new file mode 100644 index 0000000..b4f93cf Binary files /dev/null and b/static/mstile-150x150.png differ diff --git a/static/one-dark.css b/static/one-dark.css new file mode 100644 index 0000000..9296216 --- /dev/null +++ b/static/one-dark.css @@ -0,0 +1 @@ +pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#abb2bf;background:#282c34}.hljs-keyword,.hljs-operator,.hljs-pattern-match{color:#f92672}.hljs-function,.hljs-pattern-match .hljs-constructor{color:#61aeee}.hljs-function .hljs-params{color:#a6e22e}.hljs-function .hljs-params .hljs-typing{color:#fd971f}.hljs-module-access .hljs-module{color:#7e57c2}.hljs-constructor{color:#e2b93d}.hljs-constructor .hljs-string{color:#9ccc65}.hljs-comment,.hljs-quote{color:#b18eb1;font-style:italic}.hljs-doctag,.hljs-formula{color:#c678dd}.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#e06c75}.hljs-literal{color:#56b6c2}.hljs-addition,.hljs-attribute,.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#98c379}.hljs-built_in,.hljs-class .hljs-title,.hljs-title.class_{color:#e6c07b}.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#d19a66}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#61aeee}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-link{text-decoration:underline} \ No newline at end of file diff --git a/static/safari-pinned-tab.svg b/static/safari-pinned-tab.svg new file mode 100644 index 0000000..72c4f43 --- /dev/null +++ b/static/safari-pinned-tab.svg @@ -0,0 +1,22 @@ + + + + +Created by potrace 1.14, written by Peter Selinger 2001-2017 + + + + + + diff --git a/static/site.webmanifest b/static/site.webmanifest new file mode 100644 index 0000000..b20abb7 --- /dev/null +++ b/static/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "", + "short_name": "", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/themes/hello-friend-ng/.eslintrc.yml b/themes/hello-friend-ng/.eslintrc.yml new file mode 100644 index 0000000..d6c937d --- /dev/null +++ b/themes/hello-friend-ng/.eslintrc.yml @@ -0,0 +1,60 @@ +--- + +env: + es6: true + +extends: + # https://github.com/airbnb/javascript + - airbnb + - eslint:recommended + - prettier + +parser: babel-eslint + +rules: + # best practices + arrow-parens: + - 2 + - as-needed + semi: + - 2 + - never + class-methods-use-this: 0 + comma-dangle: + - 2 + - always-multiline + no-console: + - 2 + no-unused-expressions: 0 + no-param-reassign: + - 2 + - props: false + no-useless-escape: 0 + func-names: 0 + quotes: + - 2 + - single + - allowTemplateLiterals: true + no-underscore-dangle: 0 + object-curly-newline: 0 + function-paren-newline: 0 + operator-linebreak: + - 2 + - after + no-unused-vars: + - 2 + - argsIgnorePattern: "^_" + # jsx a11y + jsx-a11y/no-static-element-interactions: 0 + jsx-a11y/anchor-is-valid: + - 2 + - specialLink: + - to + +globals: + document: true + requestAnimationFrame: true + window: true + self: true + fetch: true + Headers: true diff --git a/themes/hello-friend-ng/.gitignore b/themes/hello-friend-ng/.gitignore new file mode 100644 index 0000000..46d9d8d --- /dev/null +++ b/themes/hello-friend-ng/.gitignore @@ -0,0 +1,35 @@ + +# Created by https://www.gitignore.io/api/macos +# Edit at https://www.gitignore.io/?templates=macos + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# End of https://www.gitignore.io/api/macos + +.vscode \ No newline at end of file diff --git a/themes/hello-friend-ng/CHANGELOG.md b/themes/hello-friend-ng/CHANGELOG.md new file mode 100644 index 0000000..a014020 --- /dev/null +++ b/themes/hello-friend-ng/CHANGELOG.md @@ -0,0 +1,14 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## 2020-05-13 + +### Added +- Changelog + +### Changed +- In order to make the image handling more consistent, the `cover` tag does not force the image to live in `/img/` anymore. [!131](https://github.com/rhazdon/hugo-theme-hello-friend-ng/pull/131). \ No newline at end of file diff --git a/themes/hello-friend-ng/CONTRIBUTING.md b/themes/hello-friend-ng/CONTRIBUTING.md new file mode 100644 index 0000000..6f48aa9 --- /dev/null +++ b/themes/hello-friend-ng/CONTRIBUTING.md @@ -0,0 +1,4 @@ + +# How to contribute + +If you spot any bugs, please use [Issue Tracker](https://github.com/rhazdon/hugo-theme-hello-friend-ng/issues) or if you want to add a new feature directly please create a new [Pull Request](https://github.com/rhazdon/hugo-theme-hello-friend-ng/pulls). diff --git a/themes/hello-friend-ng/LICENSE.md b/themes/hello-friend-ng/LICENSE.md new file mode 100644 index 0000000..9dac281 --- /dev/null +++ b/themes/hello-friend-ng/LICENSE.md @@ -0,0 +1,11 @@ +The MIT License (MIT) + +Original work Copyright (c) 2018 Track3
+Original work Copyright (c) 2019 panr
+Modified work Copyright (c) 2019 Djordje Atlialp
+ +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/themes/hello-friend-ng/README.md b/themes/hello-friend-ng/README.md new file mode 100644 index 0000000..62e3115 --- /dev/null +++ b/themes/hello-friend-ng/README.md @@ -0,0 +1,205 @@ +# Hello Friend NG + +![Hello Friend NG](https://dsh.re/d914c) + +## General informations + +This theme was highly inspired by the [hello-friend](https://github.com/panr/hugo-theme-hello-friend) and [hermit](https://github.com/Track3/hermit). A lot of kudos for their great work. + +--- + +## Table of Contents + +- [Features](#features) +- [How to start](#how-to-start) +- [How to configure](#how-to-configure) +- [More](#more-things) + - [Built in shortcodes](#built-in-shortcodes) + - [image](#image) + - [Code highlighting](#code-highlighting) + - [Favicon](#favicon) + - [Audio Support](#audio-support) +- [Social Icons](#social-icons) +- [Known issues](#known-issues) +- [How to edit the theme](#how-to-edit-the-theme) +- [Changelog](CHANGELOG.md) +- [Sponsoring](#sponsoring) +- [Licence](#licence) + +--- + +## Features + +- Theming: **dark/light mode**, depending on your system preferences or the users choice +- Great reading experience thanks to [**Inter UI font**](https://rsms.me/inter/), made by [Rasmus Andersson](https://rsms.me/about/) +- Nice code highlighting thanks to [**PrismJS**](https://prismjs.com) +- An easy way to modify the theme with Hugo tooling +- Fully responsive +- Audio support for posts (thanks to [@talbotp](https://github.com/talbotp)) +- Support for social icons +- Support for sharing buttons +- Support for [Commento](https://commento.io) + +## How to start + +You can download the theme manually by going to [https://github.com/rhazdon/hugo-theme-hello-friend-ng.git](https://github.com/rhazdon/hugo-theme-hello-friend-ng.git) and pasting it to `themes/hello-friend-ng` in your root directory. + +You can also clone it directly to your Hugo folder: + +``` bash +$ git clone https://github.com/rhazdon/hugo-theme-hello-friend-ng.git themes/hello-friend-ng +``` + +If you don't want to make any radical changes, it's the best option, because you can get new updates when they are available. To do so, include it as a git submodule: + +``` bash +$ git submodule add https://github.com/rhazdon/hugo-theme-hello-friend-ng.git themes/hello-friend-ng +``` + +## How to configure + +The theme doesn't require any advanced configuration. Just copy the following config file. +To see all possible configurations, [check the docs](docs/config.md). +Note: There are more options to configure. Take a look into the `config.toml` in `exampleSite`. + +``` toml +baseurl = "localhost" +title = "My Blog" +languageCode = "en-us" +theme = "hello-friend-ng" +paginate = 10 + +[params] + dateform = "Jan 2, 2006" + dateformShort = "Jan 2" + dateformNum = "2006-01-02" + dateformNumTime = "2006-01-02 15:04" + + # Subtitle for home + homeSubtitle = "A simple and beautiful blog" + + # Set disableReadOtherPosts to true in order to hide the links to other posts. + disableReadOtherPosts = false + + # Enable sharing buttons, if you like + enableSharingButtons = true + + # Metadata mostly used in document's head + description = "My new homepage or blog" + keywords = "homepage, blog" + images = [""] + +[taxonomies] + category = "blog" + tag = "tags" + series = "series" + +[languages] + [languages.en] + title = "Hello Friend NG" + subtitle = "A simple theme for Hugo" + keywords = "" + copyright = 'CC BY-NC 4.0' + readOtherPosts = "Read other posts" + + [languages.en.params.logo] + logoText = "hello friend ng" + logoHomeLink = "/" + # or + # + # path = "/img/your-example-logo.svg" + # alt = "Your example logo alt text" + + # And you can even create generic menu + [[menu.main]] + identifier = "blog" + name = "Blog" + url = "/posts" +``` + +## More things + +### Built-in shortcodes + +Of course you are able to use all default shortcodes from hugo (https://gohugo.io/content-management/shortcodes/). + +#### image + +Properties: + + - `src` (required) + - `alt` (optional) + - `position` (optional, default: `left`, options: [`left`, `center`, `right`]) + - `style` + +Example: + +``` golang +{{< image src="/img/hello.png" alt="Hello Friend" position="center" style="border-radius: 8px;" >}} +``` + +### Code highlighting + +By default the theme is using PrismJS to color your code syntax. All you need to do is to wrap you code like this: + +
+``` html
+  // your code here
+```
+
+ +### Favicon + +Check the [docs](docs/favicons.md). + +### Audio Support + +You wrote an article and recorded it? Or do you have a special music that you would like to put on a certain article? Then you can do this now without further ado. + +In your article add to your front matters part: + +```yaml +audio: path/to/file.mp3 +``` + +## Social Icons: + +A large variety of social icons are available and can be configured like this: + +```toml +[[params.social]] + name = "" + url = "" +``` + +Take a look into this [list](docs/svgs.md) of available icon options. + +If you need another one, just open an issue or create a pull request with your wished icon. :) + +## Known issues + +There is a bug in Hugo that sometimes causes the main page not to render correctly. The reason is an empty taxonomy part. +Related issue tickets: [!14](https://github.com/rhazdon/hugo-theme-hello-friend-ng/issues/14) [!59](https://github.com/rhazdon/hugo-theme-hello-friend-ng/issues/59). + +Either you comment it out completely or you write the following in + +``` toml +[taxonomies] + tag = "tags" + category = "categories" +``` + +## How to edit the theme + +Just edit it. You don't need any node stuff. ;) + +## Sponsoring + +If you like my work and if you think this project is worth to support it, just
+Buy Me A Coffee + +## Licence + +Copyright © 2019-2021 Djordje Atlialp + +The theme is released under the MIT License. Check the [original theme license](https://github.com/rhazdon/hugo-theme-hello-friend-ng/blob/master/LICENSE.md) for additional licensing information. diff --git a/themes/hello-friend-ng/archetypes/default.md b/themes/hello-friend-ng/archetypes/default.md new file mode 100644 index 0000000..63c1c63 --- /dev/null +++ b/themes/hello-friend-ng/archetypes/default.md @@ -0,0 +1,8 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +date: {{ .Date }} +draft: true +comments: false +images: +--- + diff --git a/themes/hello-friend-ng/archetypes/posts.md b/themes/hello-friend-ng/archetypes/posts.md new file mode 100644 index 0000000..82889f3 --- /dev/null +++ b/themes/hello-friend-ng/archetypes/posts.md @@ -0,0 +1,10 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +date: {{ .Date }} +draft: true +toc: false +images: +tags: + - untagged +--- + diff --git a/themes/hello-friend-ng/assets/js/highlight.min.js b/themes/hello-friend-ng/assets/js/highlight.min.js new file mode 100644 index 0000000..074f370 --- /dev/null +++ b/themes/hello-friend-ng/assets/js/highlight.min.js @@ -0,0 +1,916 @@ +/*! + Highlight.js v11.0.1 (git: 1cf31f015d) + (c) 2006-2021 Ivan Sagalaev and other contributors + License: BSD-3-Clause + */ +var hljs=function(){"use strict";var e={exports:{}};function t(e){ +return e instanceof Map?e.clear=e.delete=e.set=()=>{ +throw Error("map is read-only")}:e instanceof Set&&(e.add=e.clear=e.delete=()=>{ +throw Error("set is read-only") +}),Object.freeze(e),Object.getOwnPropertyNames(e).forEach((n=>{var i=e[n] +;"object"!=typeof i||Object.isFrozen(i)||t(i)})),e} +e.exports=t,e.exports.default=t;var n=e.exports;class i{constructor(e){ +void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1} +ignoreMatch(){this.isMatchIgnored=!0}}function r(e){ +return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'") +}function s(e,...t){const n=Object.create(null);for(const t in e)n[t]=e[t] +;return t.forEach((e=>{for(const t in e)n[t]=e[t]})),n}const o=e=>!!e.kind +;class a{constructor(e,t){ +this.buffer="",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){ +this.buffer+=r(e)}openNode(e){if(!o(e))return;let t=e.kind +;t=e.sublanguage?"language-"+t:((e,{prefix:t})=>{if(e.includes(".")){ +const n=e.split(".") +;return[`${t}${n.shift()}`,...n.map(((e,t)=>`${e}${"_".repeat(t+1)}`))].join(" ") +}return`${t}${e}`})(t,{prefix:this.classPrefix}),this.span(t)}closeNode(e){ +o(e)&&(this.buffer+="")}value(){return this.buffer}span(e){ +this.buffer+=``}}class l{constructor(){this.rootNode={ +children:[]},this.stack=[this.rootNode]}get top(){ +return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){ +this.top.children.push(e)}openNode(e){const t={kind:e,children:[]} +;this.add(t),this.stack.push(t)}closeNode(){ +if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){ +for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)} +walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){ +return"string"==typeof t?e.addText(t):t.children&&(e.openNode(t), +t.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){ +"string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{ +l._collapse(e)})))}}class c extends l{constructor(e){super(),this.options=e} +addKeyword(e,t){""!==e&&(this.openNode(t),this.addText(e),this.closeNode())} +addText(e){""!==e&&this.add(e)}addSublanguage(e,t){const n=e.root +;n.kind=t,n.sublanguage=!0,this.add(n)}toHTML(){ +return new a(this,this.options).value()}finalize(){return!0}}function g(e){ +return e?"string"==typeof e?e:e.source:null}function d(...e){ +return e.map((e=>g(e))).join("")}function u(...e){return"("+((e=>{ +const t=e[e.length-1] +;return"object"==typeof t&&t.constructor===Object?(e.splice(e.length-1,1),t):{} +})(e).capture?"":"?:")+e.map((e=>g(e))).join("|")+")"}function h(e){ +return RegExp(e.toString()+"|").exec("").length-1} +const f=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./ +;function p(e,{joinWith:t}){let n=0;return e.map((e=>{n+=1;const t=n +;let i=g(e),r="";for(;i.length>0;){const e=f.exec(i);if(!e){r+=i;break} +r+=i.substring(0,e.index), +i=i.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?r+="\\"+(Number(e[1])+t):(r+=e[0], +"("===e[0]&&n++)}return r})).map((e=>`(${e})`)).join(t)} +const b="[a-zA-Z]\\w*",m="[a-zA-Z_]\\w*",E="\\b\\d+(\\.\\d+)?",x="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",y="\\b(0b[01]+)",w={ +begin:"\\\\[\\s\\S]",relevance:0},_={scope:"string",begin:"'",end:"'", +illegal:"\\n",contains:[w]},v={scope:"string",begin:'"',end:'"',illegal:"\\n", +contains:[w]},O=(e,t,n={})=>{const i=s({scope:"comment",begin:e,end:t, +contains:[]},n);i.contains.push({scope:"doctag", +begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)", +end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0}) +;const r=u("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/) +;return i.contains.push({begin:d(/[ ]+/,"(",r,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),i +},k=O("//","$"),N=O("/\\*","\\*/"),S=O("#","$");var M=Object.freeze({ +__proto__:null,MATCH_NOTHING_RE:/\b\B/,IDENT_RE:b,UNDERSCORE_IDENT_RE:m, +NUMBER_RE:E,C_NUMBER_RE:x,BINARY_NUMBER_RE:y, +RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~", +SHEBANG:(e={})=>{const t=/^#![ ]*\// +;return e.binary&&(e.begin=d(t,/.*\b/,e.binary,/\b.*/)),s({scope:"meta",begin:t, +end:/$/,relevance:0,"on:begin":(e,t)=>{0!==e.index&&t.ignoreMatch()}},e)}, +BACKSLASH_ESCAPE:w,APOS_STRING_MODE:_,QUOTE_STRING_MODE:v,PHRASAL_WORDS_MODE:{ +begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ +},COMMENT:O,C_LINE_COMMENT_MODE:k,C_BLOCK_COMMENT_MODE:N,HASH_COMMENT_MODE:S, +NUMBER_MODE:{scope:"number",begin:E,relevance:0},C_NUMBER_MODE:{scope:"number", +begin:x,relevance:0},BINARY_NUMBER_MODE:{scope:"number",begin:y,relevance:0}, +REGEXP_MODE:{begin:/(?=\/[^/\n]*\/)/,contains:[{scope:"regexp",begin:/\//, +end:/\/[gimuy]*/,illegal:/\n/,contains:[w,{begin:/\[/,end:/\]/,relevance:0, +contains:[w]}]}]},TITLE_MODE:{scope:"title",begin:b,relevance:0}, +UNDERSCORE_TITLE_MODE:{scope:"title",begin:m,relevance:0},METHOD_GUARD:{ +begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0},END_SAME_AS_BEGIN:e=>Object.assign(e,{ +"on:begin":(e,t)=>{t.data._beginMatch=e[1]},"on:end":(e,t)=>{ +t.data._beginMatch!==e[1]&&t.ignoreMatch()}})});function R(e,t){ +"."===e.input[e.index-1]&&t.ignoreMatch()}function j(e,t){ +void 0!==e.className&&(e.scope=e.className,delete e.className)}function A(e,t){ +t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)", +e.__beforeBegin=R,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords, +void 0===e.relevance&&(e.relevance=0))}function I(e,t){ +Array.isArray(e.illegal)&&(e.illegal=u(...e.illegal))}function B(e,t){ +if(e.match){ +if(e.begin||e.end)throw Error("begin & end are not supported with match") +;e.begin=e.match,delete e.match}}function T(e,t){ +void 0===e.relevance&&(e.relevance=1)}const L=(e,t)=>{if(!e.beforeMatch)return +;if(e.starts)throw Error("beforeMatch cannot be used with starts") +;const n=Object.assign({},e);Object.keys(e).forEach((t=>{delete e[t] +})),e.keywords=n.keywords, +e.begin=d(n.beforeMatch,d("(?=",n.begin,")")),e.starts={relevance:0, +contains:[Object.assign(n,{endsParent:!0})]},e.relevance=0,delete n.beforeMatch +},D=["of","and","for","in","not","or","if","then","parent","list","value"] +;function P(e,t,n="keyword"){const i=Object.create(null) +;return"string"==typeof e?r(n,e.split(" ")):Array.isArray(e)?r(n,e):Object.keys(e).forEach((n=>{ +Object.assign(i,P(e[n],t,n))})),i;function r(e,n){ +t&&(n=n.map((e=>e.toLowerCase()))),n.forEach((t=>{const n=t.split("|") +;i[n[0]]=[e,C(n[0],n[1])]}))}}function C(e,t){ +return t?Number(t):(e=>D.includes(e.toLowerCase()))(e)?0:1}const H={},$=e=>{ +console.error(e)},U=(e,...t)=>{console.log("WARN: "+e,...t)},z=(e,t)=>{ +H[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),H[`${e}/${t}`]=!0) +},K=Error();function W(e,t,{key:n}){let i=0;const r=e[n],s={},o={} +;for(let e=1;e<=t.length;e++)o[e+i]=r[e],s[e+i]=!0,i+=h(t[e-1]) +;e[n]=o,e[n]._emit=s,e[n]._multi=!0}function X(e){(e=>{ +e.scope&&"object"==typeof e.scope&&null!==e.scope&&(e.beginScope=e.scope, +delete e.scope)})(e),"string"==typeof e.beginScope&&(e.beginScope={ +_wrap:e.beginScope}),"string"==typeof e.endScope&&(e.endScope={_wrap:e.endScope +}),(e=>{if(Array.isArray(e.begin)){ +if(e.skip||e.excludeBegin||e.returnBegin)throw $("skip, excludeBegin, returnBegin not compatible with beginScope: {}"), +K +;if("object"!=typeof e.beginScope||null===e.beginScope)throw $("beginScope must be object"), +K;W(e,e.begin,{key:"beginScope"}),e.begin=p(e.begin,{joinWith:""})}})(e),(e=>{ +if(Array.isArray(e.end)){ +if(e.skip||e.excludeEnd||e.returnEnd)throw $("skip, excludeEnd, returnEnd not compatible with endScope: {}"), +K +;if("object"!=typeof e.endScope||null===e.endScope)throw $("endScope must be object"), +K;W(e,e.end,{key:"endScope"}),e.end=p(e.end,{joinWith:""})}})(e)}function G(e){ +function t(t,n){return RegExp(g(t),"m"+(e.case_insensitive?"i":"")+(n?"g":""))} +class n{constructor(){ +this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0} +addRule(e,t){ +t.position=this.position++,this.matchIndexes[this.matchAt]=t,this.regexes.push([t,e]), +this.matchAt+=h(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null) +;const e=this.regexes.map((e=>e[1]));this.matcherRe=t(p(e,{joinWith:"|" +}),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex +;const t=this.matcherRe.exec(e);if(!t)return null +;const n=t.findIndex(((e,t)=>t>0&&void 0!==e)),i=this.matchIndexes[n] +;return t.splice(0,n),Object.assign(t,i)}}class i{constructor(){ +this.rules=[],this.multiRegexes=[], +this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){ +if(this.multiRegexes[e])return this.multiRegexes[e];const t=new n +;return this.rules.slice(e).forEach((([e,n])=>t.addRule(e,n))), +t.compile(),this.multiRegexes[e]=t,t}resumingScanAtSamePosition(){ +return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,t){ +this.rules.push([e,t]),"begin"===t.type&&this.count++}exec(e){ +const t=this.getMatcher(this.regexIndex);t.lastIndex=this.lastIndex +;let n=t.exec(e) +;if(this.resumingScanAtSamePosition())if(n&&n.index===this.lastIndex);else{ +const t=this.getMatcher(0);t.lastIndex=this.lastIndex+1,n=t.exec(e)} +return n&&(this.regexIndex+=n.position+1, +this.regexIndex===this.count&&this.considerAll()),n}} +if(e.compilerExtensions||(e.compilerExtensions=[]), +e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.") +;return e.classNameAliases=s(e.classNameAliases||{}),function n(r,o){const a=r +;if(r.isCompiled)return a +;[j,B,X,L].forEach((e=>e(r,o))),e.compilerExtensions.forEach((e=>e(r,o))), +r.__beforeBegin=null,[A,I,T].forEach((e=>e(r,o))),r.isCompiled=!0;let l=null +;return"object"==typeof r.keywords&&r.keywords.$pattern&&(r.keywords=Object.assign({},r.keywords), +l=r.keywords.$pattern, +delete r.keywords.$pattern),l=l||/\w+/,r.keywords&&(r.keywords=P(r.keywords,e.case_insensitive)), +a.keywordPatternRe=t(l,!0), +o&&(r.begin||(r.begin=/\B|\b/),a.beginRe=t(r.begin),r.end||r.endsWithParent||(r.end=/\B|\b/), +r.end&&(a.endRe=t(r.end)), +a.terminatorEnd=g(r.end)||"",r.endsWithParent&&o.terminatorEnd&&(a.terminatorEnd+=(r.end?"|":"")+o.terminatorEnd)), +r.illegal&&(a.illegalRe=t(r.illegal)), +r.contains||(r.contains=[]),r.contains=[].concat(...r.contains.map((e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((t=>s(e,{ +variants:null},t)))),e.cachedVariants?e.cachedVariants:Z(e)?s(e,{ +starts:e.starts?s(e.starts):null +}):Object.isFrozen(e)?s(e):e))("self"===e?r:e)))),r.contains.forEach((e=>{n(e,a) +})),r.starts&&n(r.starts,o),a.matcher=(e=>{const t=new i +;return e.contains.forEach((e=>t.addRule(e.begin,{rule:e,type:"begin" +}))),e.terminatorEnd&&t.addRule(e.terminatorEnd,{type:"end" +}),e.illegal&&t.addRule(e.illegal,{type:"illegal"}),t})(a),a}(e)}function Z(e){ +return!!e&&(e.endsWithParent||Z(e.starts))}const F=r,V=s,q=Symbol("nomatch") +;var J=(e=>{const t=Object.create(null),r=Object.create(null),s=[];let o=!0 +;const a="Could not find the language '{}', did you forget to load/include a language module?",l={ +disableAutodetect:!0,name:"Plain text",contains:[]};let g={ +ignoreUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i, +languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-", +cssSelector:"pre code",languages:null,__emitter:c};function d(e){ +return g.noHighlightRe.test(e)}function u(e,t,n,i){let r="",s="" +;"object"==typeof t?(r=e, +n=t.ignoreIllegals,s=t.language,i=void 0):(z("10.7.0","highlight(lang, code, ...args) has been deprecated."), +z("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"), +s=e,r=t),void 0===n&&(n=!0);const o={code:r,language:s};w("before:highlight",o) +;const a=o.result?o.result:h(o.language,o.code,n,i) +;return a.code=o.code,w("after:highlight",a),a}function h(e,n,r,s){ +const l=Object.create(null);function c(){if(!k.keywords)return void S.addText(M) +;let e=0;k.keywordPatternRe.lastIndex=0;let t=k.keywordPatternRe.exec(M),n="" +;for(;t;){n+=M.substring(e,t.index) +;const r=_.case_insensitive?t[0].toLowerCase():t[0],s=(i=r,k.keywords[i]);if(s){ +const[e,i]=s +;if(S.addText(n),n="",l[r]=(l[r]||0)+1,l[r]<=7&&(R+=i),e.startsWith("_"))n+=t[0];else{ +const n=_.classNameAliases[e]||e;S.addKeyword(t[0],n)}}else n+=t[0] +;e=k.keywordPatternRe.lastIndex,t=k.keywordPatternRe.exec(M)}var i +;n+=M.substr(e),S.addText(n)}function d(){null!=k.subLanguage?(()=>{ +if(""===M)return;let e=null;if("string"==typeof k.subLanguage){ +if(!t[k.subLanguage])return void S.addText(M) +;e=h(k.subLanguage,M,!0,N[k.subLanguage]),N[k.subLanguage]=e._top +}else e=f(M,k.subLanguage.length?k.subLanguage:null) +;k.relevance>0&&(R+=e.relevance),S.addSublanguage(e._emitter,e.language) +})():c(),M=""}function u(e,t){let n=1;for(;void 0!==t[n];){if(!e._emit[n]){n++ +;continue}const i=_.classNameAliases[e[n]]||e[n],r=t[n] +;i?S.addKeyword(r,i):(M=r,c(),M=""),n++}}function p(e,t){ +return e.scope&&"string"==typeof e.scope&&S.openNode(_.classNameAliases[e.scope]||e.scope), +e.beginScope&&(e.beginScope._wrap?(S.addKeyword(M,_.classNameAliases[e.beginScope._wrap]||e.beginScope._wrap), +M=""):e.beginScope._multi&&(u(e.beginScope,t),M="")),k=Object.create(e,{parent:{ +value:k}}),k}function b(e,t,n){let r=((e,t)=>{const n=e&&e.exec(t) +;return n&&0===n.index})(e.endRe,n);if(r){if(e["on:end"]){const n=new i(e) +;e["on:end"](t,n),n.isMatchIgnored&&(r=!1)}if(r){ +for(;e.endsParent&&e.parent;)e=e.parent;return e}} +if(e.endsWithParent)return b(e.parent,t,n)}function m(e){ +return 0===k.matcher.regexIndex?(M+=e[0],1):(I=!0,0)}function x(e){ +const t=e[0],i=n.substr(e.index),r=b(k,e,i);if(!r)return q;const s=k +;k.endScope&&k.endScope._wrap?(d(), +S.addKeyword(t,k.endScope._wrap)):k.endScope&&k.endScope._multi?(d(), +u(k.endScope,e)):s.skip?M+=t:(s.returnEnd||s.excludeEnd||(M+=t), +d(),s.excludeEnd&&(M=t));do{ +k.scope&&!k.isMultiClass&&S.closeNode(),k.skip||k.subLanguage||(R+=k.relevance), +k=k.parent}while(k!==r.parent) +;return r.starts&&p(r.starts,e),s.returnEnd?0:t.length}let y={};function w(t,s){ +const a=s&&s[0];if(M+=t,null==a)return d(),0 +;if("begin"===y.type&&"end"===s.type&&y.index===s.index&&""===a){ +if(M+=n.slice(s.index,s.index+1),!o){const t=Error(`0 width match regex (${e})`) +;throw t.languageName=e,t.badRule=y.rule,t}return 1} +if(y=s,"begin"===s.type)return(e=>{ +const t=e[0],n=e.rule,r=new i(n),s=[n.__beforeBegin,n["on:begin"]] +;for(const n of s)if(n&&(n(e,r),r.isMatchIgnored))return m(t) +;return n.skip?M+=t:(n.excludeBegin&&(M+=t), +d(),n.returnBegin||n.excludeBegin||(M=t)),p(n,e),n.returnBegin?0:t.length})(s) +;if("illegal"===s.type&&!r){ +const e=Error('Illegal lexeme "'+a+'" for mode "'+(k.scope||"")+'"') +;throw e.mode=k,e}if("end"===s.type){const e=x(s);if(e!==q)return e} +if("illegal"===s.type&&""===a)return 1 +;if(A>1e5&&A>3*s.index)throw Error("potential infinite loop, way more iterations than matches") +;return M+=a,a.length}const _=E(e) +;if(!_)throw $(a.replace("{}",e)),Error('Unknown language: "'+e+'"') +;const v=G(_);let O="",k=s||v;const N={},S=new g.__emitter(g);(()=>{const e=[] +;for(let t=k;t!==_;t=t.parent)t.scope&&e.unshift(t.scope) +;e.forEach((e=>S.openNode(e)))})();let M="",R=0,j=0,A=0,I=!1;try{ +for(k.matcher.considerAll();;){ +A++,I?I=!1:k.matcher.considerAll(),k.matcher.lastIndex=j +;const e=k.matcher.exec(n);if(!e)break;const t=w(n.substring(j,e.index),e) +;j=e.index+t}return w(n.substr(j)),S.closeAllNodes(),S.finalize(),O=S.toHTML(),{ +language:e,value:O,relevance:R,illegal:!1,_emitter:S,_top:k}}catch(t){ +if(t.message&&t.message.includes("Illegal"))return{language:e,value:F(n), +illegal:!0,relevance:0,_illegalBy:{message:t.message,index:j, +context:n.slice(j-100,j+100),mode:t.mode,resultSoFar:O},_emitter:S};if(o)return{ +language:e,value:F(n),illegal:!1,relevance:0,errorRaised:t,_emitter:S,_top:k} +;throw t}}function f(e,n){n=n||g.languages||Object.keys(t);const i=(e=>{ +const t={value:F(e),illegal:!1,relevance:0,_top:l,_emitter:new g.__emitter(g)} +;return t._emitter.addText(e),t})(e),r=n.filter(E).filter(y).map((t=>h(t,e,!1))) +;r.unshift(i);const s=r.sort(((e,t)=>{ +if(e.relevance!==t.relevance)return t.relevance-e.relevance +;if(e.language&&t.language){if(E(e.language).supersetOf===t.language)return 1 +;if(E(t.language).supersetOf===e.language)return-1}return 0})),[o,a]=s,c=o +;return c.secondBest=a,c}function p(e){let t=null;const n=(e=>{ +let t=e.className+" ";t+=e.parentNode?e.parentNode.className:"" +;const n=g.languageDetectRe.exec(t);if(n){const t=E(n[1]) +;return t||(U(a.replace("{}",n[1])), +U("Falling back to no-highlight mode for this block.",e)),t?n[1]:"no-highlight"} +return t.split(/\s+/).find((e=>d(e)||E(e)))})(e);if(d(n))return +;w("before:highlightElement",{el:e,language:n +}),!g.ignoreUnescapedHTML&&e.children.length>0&&(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."), +console.warn("https://github.com/highlightjs/highlight.js/issues/2886"), +console.warn(e)),t=e;const i=t.textContent,s=n?u(i,{language:n,ignoreIllegals:!0 +}):f(i);e.innerHTML=s.value,((e,t,n)=>{const i=t&&r[t]||n +;e.classList.add("hljs"),e.classList.add("language-"+i) +})(e,n,s.language),e.result={language:s.language,re:s.relevance, +relevance:s.relevance},s.secondBest&&(e.secondBest={ +language:s.secondBest.language,relevance:s.secondBest.relevance +}),w("after:highlightElement",{el:e,result:s,text:i})}let b=!1;function m(){ +"loading"!==document.readyState?document.querySelectorAll(g.cssSelector).forEach(p):b=!0 +}function E(e){return e=(e||"").toLowerCase(),t[e]||t[r[e]]} +function x(e,{languageName:t}){"string"==typeof e&&(e=[e]),e.forEach((e=>{ +r[e.toLowerCase()]=t}))}function y(e){const t=E(e) +;return t&&!t.disableAutodetect}function w(e,t){const n=e;s.forEach((e=>{ +e[n]&&e[n](t)}))} +"undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",(()=>{ +b&&m()}),!1),Object.assign(e,{highlight:u,highlightAuto:f,highlightAll:m, +highlightElement:p, +highlightBlock:e=>(z("10.7.0","highlightBlock will be removed entirely in v12.0"), +z("10.7.0","Please use highlightElement now."),p(e)),configure:e=>{g=V(g,e)}, +initHighlighting:()=>{ +m(),z("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")}, +initHighlightingOnLoad:()=>{ +m(),z("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.") +},registerLanguage:(n,i)=>{let r=null;try{r=i(e)}catch(e){ +if($("Language definition for '{}' could not be registered.".replace("{}",n)), +!o)throw e;$(e),r=l} +r.name||(r.name=n),t[n]=r,r.rawDefinition=i.bind(null,e),r.aliases&&x(r.aliases,{ +languageName:n})},unregisterLanguage:e=>{delete t[e] +;for(const t of Object.keys(r))r[t]===e&&delete r[t]}, +listLanguages:()=>Object.keys(t),getLanguage:E,registerAliases:x, +autoDetection:y,inherit:V,addPlugin:e=>{(e=>{ +e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=t=>{ +e["before:highlightBlock"](Object.assign({block:t.el},t)) +}),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=t=>{ +e["after:highlightBlock"](Object.assign({block:t.el},t))})})(e),s.push(e)} +}),e.debugMode=()=>{o=!1},e.safeMode=()=>{o=!0},e.versionString="11.0.1" +;for(const e in M)"object"==typeof M[e]&&n(M[e]);return Object.assign(e,M),e +})({}),Y=Object.freeze({__proto__:null});const Q=J +;for(const e of Object.keys(Y)){const t=e.replace("grmr_","") +;Q.registerLanguage(t,Y[e])}return Q}() +;"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);hljs.registerLanguage("ini",(()=>{"use strict";function e(e){ +return e?"string"==typeof e?e:e.source:null}function n(...n){ +return n.map((n=>e(n))).join("")}return s=>{const a={className:"number", +relevance:0,variants:[{begin:/([+-]+)?[\d]+_[\d_]+/},{begin:s.NUMBER_RE}] +},t=s.COMMENT();t.variants=[{begin:/;/,end:/$/},{begin:/#/,end:/$/}];const i={ +className:"variable",variants:[{begin:/\$[\w\d"][\w\d_]*/},{begin:/\$\{(.*?)\}/ +}]},r={className:"literal",begin:/\bon|off|true|false|yes|no\b/},c={ +className:"string",contains:[s.BACKSLASH_ESCAPE],variants:[{begin:"'''", +end:"'''",relevance:10},{begin:'"""',end:'"""',relevance:10},{begin:'"',end:'"' +},{begin:"'",end:"'"}]},l={begin:/\[/,end:/\]/,contains:[t,r,i,c,a,"self"], +relevance:0},o=function(...n){return"("+((e=>{const n=e[e.length-1] +;return"object"==typeof n&&n.constructor===Object?(e.splice(e.length-1,1),n):{} +})(n).capture?"":"?:")+n.map((n=>e(n))).join("|")+")" +}(/[A-Za-z0-9_-]+/,/"(\\"|[^"])*"/,/'[^']*'/);return{name:"TOML, also INI", +aliases:["toml"],case_insensitive:!0,illegal:/\S/,contains:[t,{ +className:"section",begin:/\[+/,end:/\]+/},{ +begin:n(o,"(\\s*\\.\\s*",o,")*",n("(?=",/\s*=\s*[^#\s]/,")")),className:"attr", +starts:{end:/$/,contains:[t,l,r,i,c,a]}}]}}})());hljs.registerLanguage("java",(()=>{"use strict" +;var e="\\.([0-9](_*[0-9])*)",a="[0-9a-fA-F](_*[0-9a-fA-F])*",n={ +className:"number",variants:[{ +begin:`(\\b([0-9](_*[0-9])*)((${e})|\\.)?|(${e}))[eE][+-]?([0-9](_*[0-9])*)[fFdD]?\\b` +},{begin:`\\b([0-9](_*[0-9])*)((${e})[fFdD]?\\b|\\.([fFdD]\\b)?)`},{ +begin:`(${e})[fFdD]?\\b`},{begin:"\\b([0-9](_*[0-9])*)[fFdD]\\b"},{ +begin:`\\b0[xX]((${a})\\.?|(${a})?\\.(${a}))[pP][+-]?([0-9](_*[0-9])*)[fFdD]?\\b` +},{begin:"\\b(0|[1-9](_*[0-9])*)[lL]?\\b"},{begin:`\\b0[xX](${a})[lL]?\\b`},{ +begin:"\\b0(_*[0-7])*[lL]?\\b"},{begin:"\\b0[bB][01](_*[01])*[lL]?\\b"}], +relevance:0};function s(e,a,n){return-1===n?"":e.replace(a,(t=>s(e,a,n-1)))} +return e=>{ +const a="[\xc0-\u02b8a-zA-Z_$][\xc0-\u02b8a-zA-Z_$0-9]*",t=a+s("(?:<"+a+"~~~(?:\\s*,\\s*"+a+"~~~)*>)?",/~~~/g,2),i={ +keyword:["synchronized","abstract","private","var","static","if","const ","for","while","strictfp","finally","protected","import","native","final","void","enum","else","break","transient","catch","instanceof","volatile","case","assert","package","default","public","try","switch","continue","throws","protected","public","private","module","requires","exports","do"], +literal:["false","true","null"], +type:["char","boolean","long","float","int","byte","short","double"], +built_in:["super","this"]},r={className:"meta",begin:"@"+a,contains:[{ +begin:/\(/,end:/\)/,contains:["self"]}]},l={className:"params",begin:/\(/, +end:/\)/,keywords:i,relevance:0,contains:[e.C_BLOCK_COMMENT_MODE],endsParent:!0} +;return{name:"Java",aliases:["jsp"],keywords:i,illegal:/<\/|#/, +contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/, +relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]}),{ +begin:/import java\.[a-z]+\./,keywords:"import",relevance:2 +},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{ +match:[/\b(?:class|interface|enum|extends|implements|new)/,/\s+/,a],className:{ +1:"keyword",3:"title.class"}},{begin:[a,/\s+/,a,/\s+/,/=/],className:{1:"type", +3:"variable",5:"operator"}},{begin:[/record/,/\s+/,a],className:{1:"keyword", +3:"title.class"},contains:[l,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{ +beginKeywords:"new throw return else",relevance:0},{ +begin:["(?:"+t+"\\s+)",e.UNDERSCORE_IDENT_RE,/\s*(?=\()/],className:{ +2:"title.function"},keywords:i,contains:[{className:"params",begin:/\(/, +end:/\)/,keywords:i,relevance:0, +contains:[r,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,n,e.C_BLOCK_COMMENT_MODE] +},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},n,r]}}})());hljs.registerLanguage("ruby",(()=>{"use strict";function e(e){ +return n("(?=",e,")")}function n(...e){return e.map((e=>{ +return(n=e)?"string"==typeof n?n:n.source:null;var n})).join("")}return a=>{ +const i="([a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?)",s={ +keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor __FILE__", +built_in:"proc lambda",literal:"true false nil"},r={className:"doctag", +begin:"@[A-Za-z]+"},b={begin:"#<",end:">"},c=[a.COMMENT("#","$",{contains:[r] +}),a.COMMENT("^=begin","^=end",{contains:[r],relevance:10 +}),a.COMMENT("^__END__","\\n$")],t={className:"subst",begin:/#\{/,end:/\}/, +keywords:s},g={className:"string",contains:[a.BACKSLASH_ESCAPE,t],variants:[{ +begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:/%[qQwWx]?\(/, +end:/\)/},{begin:/%[qQwWx]?\[/,end:/\]/},{begin:/%[qQwWx]?\{/,end:/\}/},{ +begin:/%[qQwWx]?/},{begin:/%[qQwWx]?\//,end:/\//},{begin:/%[qQwWx]?%/, +end:/%/},{begin:/%[qQwWx]?-/,end:/-/},{begin:/%[qQwWx]?\|/,end:/\|/},{ +begin:/\B\?(\\\d{1,3})/},{begin:/\B\?(\\x[A-Fa-f0-9]{1,2})/},{ +begin:/\B\?(\\u\{?[A-Fa-f0-9]{1,6}\}?)/},{ +begin:/\B\?(\\M-\\C-|\\M-\\c|\\c\\M-|\\M-|\\C-\\M-)[\x20-\x7e]/},{ +begin:/\B\?\\(c|C-)[\x20-\x7e]/},{begin:/\B\?\\?\S/},{ +begin:n(/<<[-~]?'?/,e(/(\w+)(?=\W)[^\n]*\n(?:[^\n]*\n)*?\s*\1\b/)), +contains:[a.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/, +contains:[a.BACKSLASH_ESCAPE,t]})]}]},d="[0-9](_?[0-9])*",l={className:"number", +relevance:0,variants:[{ +begin:`\\b([1-9](_?[0-9])*|0)(\\.(${d}))?([eE][+-]?(${d})|r)?i?\\b`},{ +begin:"\\b0[dD][0-9](_?[0-9])*r?i?\\b"},{begin:"\\b0[bB][0-1](_?[0-1])*r?i?\\b" +},{begin:"\\b0[oO][0-7](_?[0-7])*r?i?\\b"},{ +begin:"\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*r?i?\\b"},{ +begin:"\\b0(_?[0-7])+r?i?\\b"}]},o={className:"params",begin:"\\(",end:"\\)", +endsParent:!0,keywords:s},_=[g,{className:"class",beginKeywords:"class module", +end:"$|;",illegal:/=/,contains:[a.inherit(a.TITLE_MODE,{ +begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|!)?"}),{begin:"<\\s*",contains:[{ +begin:"("+a.IDENT_RE+"::)?"+a.IDENT_RE,relevance:0}]}].concat(c)},{ +className:"function",begin:n(/def\s+/,e(i+"\\s*(\\(|;|$)")),relevance:0, +keywords:"def",end:"$|;",contains:[a.inherit(a.TITLE_MODE,{begin:i +}),o].concat(c)},{begin:a.IDENT_RE+"::"},{className:"symbol", +begin:a.UNDERSCORE_IDENT_RE+"(!|\\?)?:",relevance:0},{className:"symbol", +begin:":(?!\\s)",contains:[g,{begin:i}],relevance:0},l,{className:"variable", +begin:"(\\$\\W)|((\\$|@@?)(\\w+))(?=[^@$?])(?![A-Za-z])(?![@$?'])"},{ +className:"params",begin:/\|/,end:/\|/,relevance:0,keywords:s},{ +begin:"("+a.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[{ +className:"regexp",contains:[a.BACKSLASH_ESCAPE,t],illegal:/\n/,variants:[{ +begin:"/",end:"/[a-z]*"},{begin:/%r\{/,end:/\}[a-z]*/},{begin:"%r\\(", +end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}] +}].concat(b,c),relevance:0}].concat(b,c);t.contains=_,o.contains=_;const E=[{ +begin:/^\s*=>/,starts:{end:"$",contains:_}},{className:"meta", +begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+>|(\\w+-)?\\d+\\.\\d+\\.\\d+(p\\d+)?[^\\d][^>]+>)(?=[ ])", +starts:{end:"$",contains:_}}];return c.unshift(b),{name:"Ruby", +aliases:["rb","gemspec","podspec","thor","irb"],keywords:s,illegal:/\/\*/, +contains:[a.SHEBANG({binary:"ruby"})].concat(E).concat(c).concat(_)}}})());hljs.registerLanguage("yaml",(()=>{"use strict";return e=>{ +const n="true false yes no null",a="[\\w#;/?:@&=+$,.~*'()[\\]]+",s={ +className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/ +},{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,{className:"template-variable", +variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]}]},i=e.inherit(s,{ +variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),l={ +end:",",endsWithParent:!0,excludeEnd:!0,keywords:n,relevance:0},t={begin:/\{/, +end:/\}/,contains:[l],illegal:"\\n",relevance:0},g={begin:"\\[",end:"\\]", +contains:[l],illegal:"\\n",relevance:0},b=[{className:"attr",variants:[{ +begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{ +begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)"}]},{className:"meta",begin:"^---\\s*$", +relevance:10},{className:"string", +begin:"[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"},{ +begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0, +relevance:0},{className:"type",begin:"!\\w+!"+a},{className:"type", +begin:"!<"+a+">"},{className:"type",begin:"!"+a},{className:"type",begin:"!!"+a +},{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta", +begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"-(?=[ ]|$)", +relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:n,keywords:{literal:n}},{ +className:"number", +begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b" +},{className:"number",begin:e.C_NUMBER_RE+"\\b",relevance:0},t,g,s],c=[...b] +;return c.pop(),c.push(i),l.contains=c,{name:"YAML",case_insensitive:!0, +aliases:["yml"],contains:b}}})());hljs.registerLanguage("sql",(()=>{"use strict";function e(e){ +return e?"string"==typeof e?e:e.source:null}function r(...r){ +return r.map((r=>e(r))).join("")}function t(...r){return"("+((e=>{ +const r=e[e.length-1] +;return"object"==typeof r&&r.constructor===Object?(e.splice(e.length-1,1),r):{} +})(r).capture?"":"?:")+r.map((r=>e(r))).join("|")+")"}return e=>{ +const n=e.COMMENT("--","$"),a=["true","false","unknown"],i=["bigint","binary","blob","boolean","char","character","clob","date","dec","decfloat","decimal","float","int","integer","interval","nchar","nclob","national","numeric","real","row","smallint","time","timestamp","varchar","varying","varbinary"],s=["abs","acos","array_agg","asin","atan","avg","cast","ceil","ceiling","coalesce","corr","cos","cosh","count","covar_pop","covar_samp","cume_dist","dense_rank","deref","element","exp","extract","first_value","floor","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","last_value","lead","listagg","ln","log","log10","lower","max","min","mod","nth_value","ntile","nullif","percent_rank","percentile_cont","percentile_disc","position","position_regex","power","rank","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","row_number","sin","sinh","sqrt","stddev_pop","stddev_samp","substring","substring_regex","sum","tan","tanh","translate","translate_regex","treat","trim","trim_array","unnest","upper","value_of","var_pop","var_samp","width_bucket"],o=["create table","insert into","primary key","foreign key","not null","alter table","add constraint","grouping sets","on overflow","character set","respect nulls","ignore nulls","nulls first","nulls last","depth first","breadth first"],c=s,l=["abs","acos","all","allocate","alter","and","any","are","array","array_agg","array_max_cardinality","as","asensitive","asin","asymmetric","at","atan","atomic","authorization","avg","begin","begin_frame","begin_partition","between","bigint","binary","blob","boolean","both","by","call","called","cardinality","cascaded","case","cast","ceil","ceiling","char","char_length","character","character_length","check","classifier","clob","close","coalesce","collate","collect","column","commit","condition","connect","constraint","contains","convert","copy","corr","corresponding","cos","cosh","count","covar_pop","covar_samp","create","cross","cube","cume_dist","current","current_catalog","current_date","current_default_transform_group","current_path","current_role","current_row","current_schema","current_time","current_timestamp","current_path","current_role","current_transform_group_for_type","current_user","cursor","cycle","date","day","deallocate","dec","decimal","decfloat","declare","default","define","delete","dense_rank","deref","describe","deterministic","disconnect","distinct","double","drop","dynamic","each","element","else","empty","end","end_frame","end_partition","end-exec","equals","escape","every","except","exec","execute","exists","exp","external","extract","false","fetch","filter","first_value","float","floor","for","foreign","frame_row","free","from","full","function","fusion","get","global","grant","group","grouping","groups","having","hold","hour","identity","in","indicator","initial","inner","inout","insensitive","insert","int","integer","intersect","intersection","interval","into","is","join","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","language","large","last_value","lateral","lead","leading","left","like","like_regex","listagg","ln","local","localtime","localtimestamp","log","log10","lower","match","match_number","match_recognize","matches","max","member","merge","method","min","minute","mod","modifies","module","month","multiset","national","natural","nchar","nclob","new","no","none","normalize","not","nth_value","ntile","null","nullif","numeric","octet_length","occurrences_regex","of","offset","old","omit","on","one","only","open","or","order","out","outer","over","overlaps","overlay","parameter","partition","pattern","per","percent","percent_rank","percentile_cont","percentile_disc","period","portion","position","position_regex","power","precedes","precision","prepare","primary","procedure","ptf","range","rank","reads","real","recursive","ref","references","referencing","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","release","result","return","returns","revoke","right","rollback","rollup","row","row_number","rows","running","savepoint","scope","scroll","search","second","seek","select","sensitive","session_user","set","show","similar","sin","sinh","skip","smallint","some","specific","specifictype","sql","sqlexception","sqlstate","sqlwarning","sqrt","start","static","stddev_pop","stddev_samp","submultiset","subset","substring","substring_regex","succeeds","sum","symmetric","system","system_time","system_user","table","tablesample","tan","tanh","then","time","timestamp","timezone_hour","timezone_minute","to","trailing","translate","translate_regex","translation","treat","trigger","trim","trim_array","true","truncate","uescape","union","unique","unknown","unnest","update","upper","user","using","value","values","value_of","var_pop","var_samp","varbinary","varchar","varying","versioning","when","whenever","where","width_bucket","window","with","within","without","year","add","asc","collation","desc","final","first","last","view"].filter((e=>!s.includes(e))),u={ +begin:r(/\b/,t(...c),/\s*\(/),relevance:0,keywords:{built_in:c}};return{ +name:"SQL",case_insensitive:!0,illegal:/[{}]|<\//,keywords:{ +$pattern:/\b[\w\.]+/,keyword:((e,{exceptions:r,when:t}={})=>{const n=t +;return r=r||[],e.map((e=>e.match(/\|\d+$/)||r.includes(e)?e:n(e)?e+"|0":e)) +})(l,{when:e=>e.length<3}),literal:a,type:i, +built_in:["current_catalog","current_date","current_default_transform_group","current_path","current_role","current_schema","current_transform_group_for_type","current_user","session_user","system_time","system_user","current_time","localtime","current_timestamp","localtimestamp"] +},contains:[{begin:t(...o),relevance:0,keywords:{$pattern:/[\w\.]+/, +keyword:l.concat(o),literal:a,type:i}},{className:"type", +begin:t("double precision","large object","with timezone","without timezone") +},u,{className:"variable",begin:/@[a-z0-9]+/},{className:"string",variants:[{ +begin:/'/,end:/'/,contains:[{begin:/''/}]}]},{begin:/"/,end:/"/,contains:[{ +begin:/""/}]},e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE,n,{className:"operator", +begin:/[-+*/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?/,relevance:0}]}}})());hljs.registerLanguage("diff",(()=>{"use strict";function e(...e){ +return"("+((e=>{const n=e[e.length-1] +;return"object"==typeof n&&n.constructor===Object?(e.splice(e.length-1,1),n):{} +})(e).capture?"":"?:")+e.map((e=>{return(n=e)?"string"==typeof n?n:n.source:null +;var n})).join("|")+")"}return n=>({name:"Diff",aliases:["patch"],contains:[{ +className:"meta",relevance:10, +match:e(/^@@ +-\d+,\d+ +\+\d+,\d+ +@@/,/^\*\*\* +\d+,\d+ +\*\*\*\*$/,/^--- +\d+,\d+ +----$/) +},{className:"comment",variants:[{ +begin:e(/Index: /,/^index/,/={3,}/,/^-{3}/,/^\*{3} /,/^\+{3}/,/^diff --git/), +end:/$/},{match:/^\*{15}$/}]},{className:"addition",begin:/^\+/,end:/$/},{ +className:"deletion",begin:/^-/,end:/$/},{className:"addition",begin:/^!/, +end:/$/}]})})());hljs.registerLanguage("plaintext",(()=>{"use strict";return t=>({ +name:"Plain text",aliases:["text","txt"],disableAutodetect:!0})})());hljs.registerLanguage("typescript",(()=>{"use strict" +;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],t=["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer","BigInt64Array","BigUint64Array","BigInt"],s=["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],r=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],c=["arguments","this","super","console","window","document","localStorage","module","global"],i=[].concat(r,t,s) +;function o(e){return l("(?=",e,")")}function l(...e){return e.map((e=>{ +return(n=e)?"string"==typeof n?n:n.source:null;var n})).join("")}return b=>{ +const d={$pattern:e, +keyword:n.concat(["type","namespace","typedef","interface","public","private","protected","implements","declare","abstract","readonly"]), +literal:a, +built_in:i.concat(["any","void","number","boolean","string","object","never","enum"]), +"variable.language":c},g={className:"meta",begin:"@[A-Za-z$_][0-9A-Za-z$_]*" +},u=(e,n,a)=>{const t=e.contains.findIndex((e=>e.label===n)) +;if(-1===t)throw Error("can not find mode to replace");e.contains.splice(t,1,a) +},m=function(b){const d=e,g={begin:/<[A-Za-z0-9\\._:-]+/, +end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{ +const a=e[0].length+e.index,t=e.input[a];"<"!==t?">"===t&&(((e,{after:n})=>{ +const a="",B={ +match:[/const|var|let/,/\s+/,d,/\s*/,/=\s*/,o(C)],className:{1:"keyword", +3:"title.function"},contains:[S]};return{name:"Javascript", +aliases:["js","jsx","mjs","cjs"],keywords:u,exports:{PARAMS_CONTAINS:w}, +illegal:/#(?![$_A-z])/,contains:[b.SHEBANG({label:"shebang",binary:"node", +relevance:5}),{label:"use_strict",className:"meta",relevance:10, +begin:/^\s*['"]use (strict|asm)['"]/ +},b.APOS_STRING_MODE,b.QUOTE_STRING_MODE,p,_,N,A,y,R,{className:"attr", +begin:d+o(":"),relevance:0},B,{ +begin:"("+b.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*", +keywords:"return throw case",relevance:0,contains:[A,b.REGEXP_MODE,{ +className:"function",begin:C,returnBegin:!0,end:"\\s*=>",contains:[{ +className:"params",variants:[{begin:b.UNDERSCORE_IDENT_RE,relevance:0},{ +className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0, +excludeEnd:!0,keywords:u,contains:w}]}]},{begin:/,/,relevance:0},{match:/\s+/, +relevance:0},{variants:[{begin:"<>",end:""},{begin:g.begin, +"on:begin":g.isTrulyOpeningTag,end:g.end}],subLanguage:"xml",contains:[{ +begin:g.begin,end:g.end,skip:!0,contains:["self"]}]}]},I,{ +beginKeywords:"while if switch catch for"},{ +begin:"\\b(?!function)"+b.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", +returnBegin:!0,label:"func.def",contains:[S,b.inherit(b.TITLE_MODE,{begin:d, +className:"title.function"})]},{match:/\.\.\./,relevance:0},k,{match:"\\$"+d, +relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"}, +contains:[S]},x,{relevance:0,match:/\b[A-Z][A-Z_]+\b/, +className:"variable.constant"},O,M,{match:/\$[(.]/}]}}(b) +;return Object.assign(m.keywords,d), +m.exports.PARAMS_CONTAINS.push(g),m.contains=m.contains.concat([g,{ +beginKeywords:"namespace",end:/\{/,excludeEnd:!0},{beginKeywords:"interface", +end:/\{/,excludeEnd:!0,keywords:"interface extends" +}]),u(m,"shebang",b.SHEBANG()),u(m,"use_strict",{className:"meta",relevance:10, +begin:/^\s*['"]use strict['"]/ +}),m.contains.find((e=>"func.def"===e.label)).relevance=0,Object.assign(m,{ +name:"TypeScript",aliases:["ts","tsx"]}),m}})());hljs.registerLanguage("css",(()=>{"use strict" +;const e=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","main","mark","menu","nav","object","ol","p","q","quote","samp","section","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video"],t=["any-hover","any-pointer","aspect-ratio","color","color-gamut","color-index","device-aspect-ratio","device-height","device-width","display-mode","forced-colors","grid","height","hover","inverted-colors","monochrome","orientation","overflow-block","overflow-inline","pointer","prefers-color-scheme","prefers-contrast","prefers-reduced-motion","prefers-reduced-transparency","resolution","scan","scripting","update","width","min-width","max-width","min-height","max-height"],i=["active","any-link","blank","checked","current","default","defined","dir","disabled","drop","empty","enabled","first","first-child","first-of-type","fullscreen","future","focus","focus-visible","focus-within","has","host","host-context","hover","indeterminate","in-range","invalid","is","lang","last-child","last-of-type","left","link","local-link","not","nth-child","nth-col","nth-last-child","nth-last-col","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","past","placeholder-shown","read-only","read-write","required","right","root","scope","target","target-within","user-invalid","valid","visited","where"],o=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"],r=["align-content","align-items","align-self","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","auto","backface-visibility","background","background-attachment","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","clear","clip","clip-path","color","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","content","counter-increment","counter-reset","cursor","direction","display","empty-cells","filter","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","font","font-display","font-family","font-feature-settings","font-kerning","font-language-override","font-size","font-size-adjust","font-smoothing","font-stretch","font-style","font-variant","font-variant-ligatures","font-variation-settings","font-weight","height","hyphens","icon","image-orientation","image-rendering","image-resolution","ime-mode","inherit","initial","justify-content","left","letter-spacing","line-height","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marks","mask","max-height","max-width","min-height","min-width","nav-down","nav-index","nav-left","nav-right","nav-up","none","normal","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page-break-after","page-break-before","page-break-inside","perspective","perspective-origin","pointer-events","position","quotes","resize","right","src","tab-size","table-layout","text-align","text-align-last","text-decoration","text-decoration-color","text-decoration-line","text-decoration-style","text-indent","text-overflow","text-rendering","text-shadow","text-transform","text-underline-position","top","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vertical-align","visibility","white-space","widows","width","word-break","word-spacing","word-wrap","z-index"].reverse() +;return n=>{const a=(e=>({IMPORTANT:{scope:"meta",begin:"!important"},HEXCOLOR:{ +scope:"number",begin:"#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})"}, +ATTRIBUTE_SELECTOR_MODE:{scope:"selector-attr",begin:/\[/,end:/\]/,illegal:"$", +contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{ +scope:"number", +begin:e.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?", +relevance:0}}))(n),l=[n.APOS_STRING_MODE,n.QUOTE_STRING_MODE];return{name:"CSS", +case_insensitive:!0,illegal:/[=|'\$]/,keywords:{keyframePosition:"from to"}, +classNameAliases:{keyframePosition:"selector-tag"}, +contains:[n.C_BLOCK_COMMENT_MODE,{begin:/-(webkit|moz|ms|o)-(?=[a-z])/ +},a.CSS_NUMBER_MODE,{className:"selector-id",begin:/#[A-Za-z0-9_-]+/,relevance:0 +},{className:"selector-class",begin:"\\.[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0 +},a.ATTRIBUTE_SELECTOR_MODE,{className:"selector-pseudo",variants:[{ +begin:":("+i.join("|")+")"},{begin:"::("+o.join("|")+")"}]},{ +className:"attribute",begin:"\\b("+r.join("|")+")\\b"},{begin:":",end:"[;}]", +contains:[a.HEXCOLOR,a.IMPORTANT,a.CSS_NUMBER_MODE,...l,{ +begin:/(url|data-uri)\(/,end:/\)/,relevance:0,keywords:{built_in:"url data-uri" +},contains:[{className:"string",begin:/[^)]/,endsWithParent:!0,excludeEnd:!0}] +},{className:"built_in",begin:/[\w-]+(?=\()/}]},{ +begin:(s=/@/,((...e)=>e.map((e=>(e=>e?"string"==typeof e?e:e.source:null)(e))).join(""))("(?=",s,")")), +end:"[{;]",relevance:0,illegal:/:/,contains:[{className:"keyword", +begin:/@-?\w[\w]*(-\w+)*/},{begin:/\s/,endsWithParent:!0,excludeEnd:!0, +relevance:0,keywords:{$pattern:/[a-z-]+/,keyword:"and or not only", +attribute:t.join(" ")},contains:[{begin:/[a-z-]+(?=:)/,className:"attribute" +},...l,a.CSS_NUMBER_MODE]}]},{className:"selector-tag", +begin:"\\b("+e.join("|")+")\\b"}]};var s}})());hljs.registerLanguage("go",(()=>{"use strict";return e=>{const n={ +keyword:["break","default","func","interface","select","case","map","struct","chan","else","goto","package","switch","const","fallthrough","if","range","type","continue","for","import","return","var","go","defer","bool","byte","complex64","complex128","float32","float64","int8","int16","int32","int64","string","uint8","uint16","uint32","uint64","int","uint","uintptr","rune"], +literal:["true","false","iota","nil"], +built_in:["append","cap","close","complex","copy","imag","len","make","new","panic","print","println","real","recover","delete"] +};return{name:"Go",aliases:["golang"],keywords:n,illegal:"{"use strict" +;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],t=["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer","BigInt64Array","BigUint64Array","BigInt"],s=["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],r=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],i=["arguments","this","super","console","window","document","localStorage","module","global"],c=[].concat(r,t,s) +;function o(e){return l("(?=",e,")")}function l(...e){return e.map((e=>{ +return(n=e)?"string"==typeof n?n:n.source:null;var n})).join("")}return b=>{ +const g=e,d={begin:/<[A-Za-z0-9\\._:-]+/,end:/\/[A-Za-z0-9\\._:-]+>|\/>/, +isTrulyOpeningTag:(e,n)=>{const a=e[0].length+e.index,t=e.input[a] +;"<"!==t?">"===t&&(((e,{after:n})=>{const a="",B={ +match:[/const|var|let/,/\s+/,g,/\s*/,/=\s*/,o(C)],className:{1:"keyword", +3:"title.function"},contains:[w]};return{name:"Javascript", +aliases:["js","jsx","mjs","cjs"],keywords:u,exports:{PARAMS_CONTAINS:S}, +illegal:/#(?![$_A-z])/,contains:[b.SHEBANG({label:"shebang",binary:"node", +relevance:5}),{label:"use_strict",className:"meta",relevance:10, +begin:/^\s*['"]use (strict|asm)['"]/ +},b.APOS_STRING_MODE,b.QUOTE_STRING_MODE,N,f,A,v,y,O,{className:"attr", +begin:g+o(":"),relevance:0},B,{ +begin:"("+b.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*", +keywords:"return throw case",relevance:0,contains:[v,b.REGEXP_MODE,{ +className:"function",begin:C,returnBegin:!0,end:"\\s*=>",contains:[{ +className:"params",variants:[{begin:b.UNDERSCORE_IDENT_RE,relevance:0},{ +className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0, +excludeEnd:!0,keywords:u,contains:S}]}]},{begin:/,/,relevance:0},{match:/\s+/, +relevance:0},{variants:[{begin:"<>",end:""},{begin:d.begin, +"on:begin":d.isTrulyOpeningTag,end:d.end}],subLanguage:"xml",contains:[{ +begin:d.begin,end:d.end,skip:!0,contains:["self"]}]}]},I,{ +beginKeywords:"while if switch catch for"},{ +begin:"\\b(?!function)"+b.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", +returnBegin:!0,label:"func.def",contains:[w,b.inherit(b.TITLE_MODE,{begin:g, +className:"title.function"})]},{match:/\.\.\./,relevance:0},M,{match:"\\$"+g, +relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"}, +contains:[w]},T,{relevance:0,match:/\b[A-Z][A-Z_]+\b/, +className:"variable.constant"},R,k,{match:/\$[(.]/}]}}})());hljs.registerLanguage("xml",(()=>{"use strict";function e(e){ +return e?"string"==typeof e?e:e.source:null}function n(e){return a("(?=",e,")")} +function a(...n){return n.map((n=>e(n))).join("")}function s(...n){ +return"("+((e=>{const n=e[e.length-1] +;return"object"==typeof n&&n.constructor===Object?(e.splice(e.length-1,1),n):{} +})(n).capture?"":"?:")+n.map((n=>e(n))).join("|")+")"}return e=>{ +const t=a(/[A-Z_]/,a("(?:",/[A-Z0-9_.-]*:/,")?"),/[A-Z0-9_.-]*/),i={ +className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},c={begin:/\s/, +contains:[{className:"keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}] +},r=e.inherit(c,{begin:/\(/,end:/\)/}),l=e.inherit(e.APOS_STRING_MODE,{ +className:"string"}),g=e.inherit(e.QUOTE_STRING_MODE,{className:"string"}),m={ +endsWithParent:!0,illegal:/`]+/}]}]}]};return{ +name:"HTML, XML", +aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"], +case_insensitive:!0,contains:[{className:"meta",begin://, +relevance:10,contains:[c,g,l,r,{begin:/\[/,end:/\]/,contains:[{className:"meta", +begin://,contains:[c,r,g,l]}]}]},e.COMMENT(//,{ +relevance:10}),{begin://,relevance:10},i,{ +className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag", +begin:/)/,end:/>/,keywords:{name:"style"},contains:[m],starts:{ +end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag", +begin:/)/,end:/>/,keywords:{name:"script"},contains:[m],starts:{ +end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{ +className:"tag",begin:/<>|<\/>/},{className:"tag", +begin:a(//,/>/,/\s/)))),end:/\/?>/,contains:[{className:"name", +begin:t,relevance:0,starts:m}]},{className:"tag",begin:a(/<\//,n(a(t,/>/))), +contains:[{className:"name",begin:t,relevance:0},{begin:/>/,relevance:0, +endsParent:!0}]}]}}})());hljs.registerLanguage("elixir",(()=>{"use strict";return e=>{ +const n="[a-zA-Z_][a-zA-Z0-9_.]*(!|\\?)?",i={$pattern:n, +keyword:"and false then defined module in return redo retry end for true self when next until do begin unless nil break not case cond alias while ensure or include use alias fn quote require import with|0" +},a={className:"subst",begin:/#\{/,end:/\}/,keywords:i},s={className:"number", +begin:"(\\b0o[0-7_]+)|(\\b0b[01_]+)|(\\b0x[0-9a-fA-F_]+)|(-?\\b[1-9][0-9_]*(\\.[0-9_]+([eE][-+]?[0-9]+)?)?)", +relevance:0},b={className:"string",begin:"~[a-z](?=[/|([{<\"'])",contains:[{ +endsParent:!0,contains:[{contains:[e.BACKSLASH_ESCAPE,a],variants:[{begin:/"/, +end:/"/},{begin:/'/,end:/'/},{begin:/\//,end:/\//},{begin:/\|/,end:/\|/},{ +begin:/\(/,end:/\)/},{begin:/\[/,end:/\]/},{begin:/\{/,end:/\}/},{begin://}]}]}]},d={className:"string",contains:[e.BACKSLASH_ESCAPE,a],variants:[{ +begin:/"""/,end:/"""/},{begin:/'''/,end:/'''/},{begin:/~S"""/,end:/"""/, +contains:[]},{begin:/~S"/,end:/"/,contains:[]},{begin:/~S'''/,end:/'''/, +contains:[]},{begin:/~S'/,end:/'/,contains:[]},{begin:/'/,end:/'/},{begin:/"/, +end:/"/}]},r={className:"function",beginKeywords:"def defp defmacro",end:/\B\b/, +contains:[e.inherit(e.TITLE_MODE,{begin:n,endsParent:!0})]},g=e.inherit(r,{ +className:"class",beginKeywords:"defimpl defmodule defprotocol defrecord", +end:/\bdo\b|$|;/}),t=[d,{className:"string",begin:"~[A-Z](?=[/|([{<\"'])", +contains:[{begin:/"/,end:/"/},{begin:/'/,end:/'/},{begin:/\//,end:/\//},{ +begin:/\|/,end:/\|/},{begin:/\(/,end:/\)/},{begin:/\[/,end:/\]/},{begin:/\{/, +end:/\}/},{begin://}]},b,e.HASH_COMMENT_MODE,g,r,{begin:"::"},{ +className:"symbol",begin:":(?![\\s:])",contains:[d,{ +begin:"[a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?" +}],relevance:0},{className:"symbol",begin:n+":(?!:)",relevance:0},s,{ +className:"variable",begin:"(\\$\\W)|((\\$|@@?)(\\w+))"},{begin:"->"},{ +begin:"("+e.RE_STARTERS_RE+")\\s*",contains:[e.HASH_COMMENT_MODE,{ +begin:/\/: (?=\d+\s*[,\]])/,relevance:0,contains:[s]},{className:"regexp", +illegal:"\\n",contains:[e.BACKSLASH_ESCAPE,a],variants:[{begin:"/",end:"/[a-z]*" +},{begin:"%r\\[",end:"\\][a-z]*"}]}],relevance:0}];return a.contains=t,{ +name:"Elixir",keywords:i,contains:t}}})());hljs.registerLanguage("markdown",(()=>{"use strict";function n(...n){ +return n.map((n=>{return(e=n)?"string"==typeof e?e:e.source:null;var e +})).join("")}return e=>{const a={begin:/<\/?[A-Za-z_]/,end:">", +subLanguage:"xml",relevance:0},i={variants:[{begin:/\[.+?\]\[.*?\]/,relevance:0 +},{begin:/\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/, +relevance:2},{begin:n(/\[.+?\]\(/,/[A-Za-z][A-Za-z0-9+.-]*/,/:\/\/.*?\)/), +relevance:2},{begin:/\[.+?\]\([./?&#].*?\)/,relevance:1},{ +begin:/\[.+?\]\(.*?\)/,relevance:0}],returnBegin:!0,contains:[{ +className:"string",relevance:0,begin:"\\[",end:"\\]",excludeBegin:!0, +returnEnd:!0},{className:"link",relevance:0,begin:"\\]\\(",end:"\\)", +excludeBegin:!0,excludeEnd:!0},{className:"symbol",relevance:0,begin:"\\]\\[", +end:"\\]",excludeBegin:!0,excludeEnd:!0}]},s={className:"strong",contains:[], +variants:[{begin:/_{2}/,end:/_{2}/},{begin:/\*{2}/,end:/\*{2}/}]},c={ +className:"emphasis",contains:[],variants:[{begin:/\*(?!\*)/,end:/\*/},{ +begin:/_(?!_)/,end:/_/,relevance:0}]};s.contains.push(c),c.contains.push(s) +;let t=[a,i] +;return s.contains=s.contains.concat(t),c.contains=c.contains.concat(t), +t=t.concat(s,c),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{ +className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:t},{ +begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n", +contains:t}]}]},a,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)", +end:"\\s+",excludeEnd:!0},s,c,{className:"quote",begin:"^>\\s+",contains:t, +end:"$"},{className:"code",variants:[{begin:"(`{3,})[^`](.|\\n)*?\\1`*[ ]*"},{ +begin:"(~{3,})[^~](.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{ +begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))", +contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{ +begin:"^[-\\*]{3,}",end:"$"},i,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{ +className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{ +className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}}})());hljs.registerLanguage("scss",(()=>{"use strict" +;const e=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","main","mark","menu","nav","object","ol","p","q","quote","samp","section","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video"],t=["any-hover","any-pointer","aspect-ratio","color","color-gamut","color-index","device-aspect-ratio","device-height","device-width","display-mode","forced-colors","grid","height","hover","inverted-colors","monochrome","orientation","overflow-block","overflow-inline","pointer","prefers-color-scheme","prefers-contrast","prefers-reduced-motion","prefers-reduced-transparency","resolution","scan","scripting","update","width","min-width","max-width","min-height","max-height"],i=["active","any-link","blank","checked","current","default","defined","dir","disabled","drop","empty","enabled","first","first-child","first-of-type","fullscreen","future","focus","focus-visible","focus-within","has","host","host-context","hover","indeterminate","in-range","invalid","is","lang","last-child","last-of-type","left","link","local-link","not","nth-child","nth-col","nth-last-child","nth-last-col","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","past","placeholder-shown","read-only","read-write","required","right","root","scope","target","target-within","user-invalid","valid","visited","where"],r=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"],o=["align-content","align-items","align-self","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","auto","backface-visibility","background","background-attachment","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","clear","clip","clip-path","color","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","content","counter-increment","counter-reset","cursor","direction","display","empty-cells","filter","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","font","font-display","font-family","font-feature-settings","font-kerning","font-language-override","font-size","font-size-adjust","font-smoothing","font-stretch","font-style","font-variant","font-variant-ligatures","font-variation-settings","font-weight","height","hyphens","icon","image-orientation","image-rendering","image-resolution","ime-mode","inherit","initial","justify-content","left","letter-spacing","line-height","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marks","mask","max-height","max-width","min-height","min-width","nav-down","nav-index","nav-left","nav-right","nav-up","none","normal","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page-break-after","page-break-before","page-break-inside","perspective","perspective-origin","pointer-events","position","quotes","resize","right","src","tab-size","table-layout","text-align","text-align-last","text-decoration","text-decoration-color","text-decoration-line","text-decoration-style","text-indent","text-overflow","text-rendering","text-shadow","text-transform","text-underline-position","top","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vertical-align","visibility","white-space","widows","width","word-break","word-spacing","word-wrap","z-index"].reverse() +;return a=>{const n=(e=>({IMPORTANT:{scope:"meta",begin:"!important"},HEXCOLOR:{ +scope:"number",begin:"#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})"}, +ATTRIBUTE_SELECTOR_MODE:{scope:"selector-attr",begin:/\[/,end:/\]/,illegal:"$", +contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{ +scope:"number", +begin:e.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?", +relevance:0}}))(a),l=r,s=i,d="@[a-z-]+",c={className:"variable", +begin:"(\\$[a-zA-Z-][a-zA-Z0-9_-]*)\\b"};return{name:"SCSS",case_insensitive:!0, +illegal:"[=/|']",contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,{ +className:"selector-id",begin:"#[A-Za-z0-9_-]+",relevance:0},{ +className:"selector-class",begin:"\\.[A-Za-z0-9_-]+",relevance:0 +},n.ATTRIBUTE_SELECTOR_MODE,{className:"selector-tag", +begin:"\\b("+e.join("|")+")\\b",relevance:0},{className:"selector-pseudo", +begin:":("+s.join("|")+")"},{className:"selector-pseudo", +begin:"::("+l.join("|")+")"},c,{begin:/\(/,end:/\)/,contains:[n.CSS_NUMBER_MODE] +},{className:"attribute",begin:"\\b("+o.join("|")+")\\b"},{ +begin:"\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\b" +},{begin:":",end:";", +contains:[c,n.HEXCOLOR,n.CSS_NUMBER_MODE,a.QUOTE_STRING_MODE,a.APOS_STRING_MODE,n.IMPORTANT] +},{begin:"@(page|font-face)",keywords:{$pattern:d,keyword:"@page @font-face"}},{ +begin:"@",end:"[{;]",returnBegin:!0,keywords:{$pattern:/[a-z-]+/, +keyword:"and or not only",attribute:t.join(" ")},contains:[{begin:d, +className:"keyword"},{begin:/[a-z-]+(?=:)/,className:"attribute" +},c,a.QUOTE_STRING_MODE,a.APOS_STRING_MODE,n.HEXCOLOR,n.CSS_NUMBER_MODE]}]}} +})());hljs.registerLanguage("bash",(()=>{"use strict";function e(...e){ +return e.map((e=>{return(s=e)?"string"==typeof s?s:s.source:null;var s +})).join("")}return s=>{const n={},t={begin:/\$\{/,end:/\}/,contains:["self",{ +begin:/:-/,contains:[n]}]};Object.assign(n,{className:"variable",variants:[{ +begin:e(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},t]});const a={ +className:"subst",begin:/\$\(/,end:/\)/,contains:[s.BACKSLASH_ESCAPE]},i={ +begin:/<<-?\s*(?=\w+)/,starts:{contains:[s.END_SAME_AS_BEGIN({begin:/(\w+)/, +end:/(\w+)/,className:"string"})]}},c={className:"string",begin:/"/,end:/"/, +contains:[s.BACKSLASH_ESCAPE,n,a]};a.contains.push(c);const o={begin:/\$\(\(/, +end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},s.NUMBER_MODE,n] +},r=s.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10 +}),l={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0, +contains:[s.inherit(s.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{ +name:"Bash",aliases:["sh"],keywords:{$pattern:/\b[a-z._-]+\b/, +keyword:["if","then","else","elif","fi","for","while","in","do","done","case","esac","function"], +literal:["true","false"], +built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp" +},contains:[r,s.SHEBANG(),l,o,s.HASH_COMMENT_MODE,i,c,{className:"",begin:/\\"/ +},{className:"string",begin:/'/,end:/'/},n]}}})());hljs.registerLanguage("shell",(()=>{"use strict";return s=>({ +name:"Shell Session",aliases:["console","shellsession"],contains:[{ +className:"meta",begin:/^\s{0,3}[/~\w\d[\]()@-]*[>%$#][ ]?/,starts:{ +end:/[^\\](?=\s*$)/,subLanguage:"bash"}}]})})());hljs.registerLanguage("dockerfile",(()=>{"use strict";return e=>({ +name:"Dockerfile",aliases:["docker"],case_insensitive:!0, +keywords:["from","maintainer","expose","env","arg","user","onbuild","stopsignal"], +contains:[e.HASH_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.NUMBER_MODE,{ +beginKeywords:"run cmd entrypoint volume add copy workdir label healthcheck shell", +starts:{end:/[^\\]$/,subLanguage:"bash"}}],illegal:"{"use strict";function e(e){ +return((...e)=>e.map((e=>(e=>e?"string"==typeof e?e:e.source:null)(e))).join(""))("(?:",e,")?") +}return n=>{const t=n.COMMENT("//","$",{contains:[{begin:/\\\n/}] +}),s="[a-zA-Z_]\\w*::",r="(decltype\\(auto\\)|"+e(s)+"[a-zA-Z_]\\w*"+e("<[^<>]+>")+")",a={ +className:"type",variants:[{begin:"\\b[a-z\\d_]*_t\\b"},{ +match:/\batomic_[a-z]{3,6}\b/}]},i={className:"string",variants:[{ +begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[n.BACKSLASH_ESCAPE]},{ +begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)", +end:"'",illegal:"."},n.END_SAME_AS_BEGIN({ +begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},l={ +className:"number",variants:[{begin:"\\b(0b[01']+)"},{ +begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)" +},{ +begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" +}],relevance:0},c={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{ +keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include" +},contains:[{begin:/\\\n/,relevance:0},n.inherit(i,{className:"string"}),{ +className:"string",begin:/<.*?>/},t,n.C_BLOCK_COMMENT_MODE]},o={ +className:"title",begin:e(s)+n.IDENT_RE,relevance:0 +},d=e(s)+n.IDENT_RE+"\\s*\\(",u={ +keyword:["asm","auto","break","case","const","continue","default","do","else","enum","extern","for","fortran","goto","if","inline","register","restrict","return","sizeof","static","struct","switch","typedef","union","volatile","while","_Alignas","_Alignof","_Atomic","_Generic","_Noreturn","_Static_assert","_Thread_local","alignas","alignof","noreturn","static_assert","thread_local","_Pragma"], +type:["float","double","signed","unsigned","int","short","long","char","void","_Bool","_Complex","_Imaginary","_Decimal32","_Decimal64","_Decimal128","complex","bool","imaginary"], +literal:"true false NULL", +built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr" +},g=[c,a,t,n.C_BLOCK_COMMENT_MODE,l,i],m={variants:[{begin:/=/,end:/;/},{ +begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}], +keywords:u,contains:g.concat([{begin:/\(/,end:/\)/,keywords:u, +contains:g.concat(["self"]),relevance:0}]),relevance:0},_={ +begin:"("+r+"[\\*&\\s]+)+"+d,returnBegin:!0,end:/[{;=]/,excludeEnd:!0, +keywords:u,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:"decltype\\(auto\\)", +keywords:u,relevance:0},{begin:d,returnBegin:!0,contains:[n.inherit(o,{ +className:"title.function"})],relevance:0},{relevance:0,match:/,/},{ +className:"params",begin:/\(/,end:/\)/,keywords:u,relevance:0, +contains:[t,n.C_BLOCK_COMMENT_MODE,i,l,a,{begin:/\(/,end:/\)/,keywords:u, +relevance:0,contains:["self",t,n.C_BLOCK_COMMENT_MODE,i,l,a]}] +},a,t,n.C_BLOCK_COMMENT_MODE,c]};return{name:"C",aliases:["h"],keywords:u, +disableAutodetect:!0,illegal:"=]/,contains:[{ +beginKeywords:"final class struct"},n.TITLE_MODE]}]),exports:{preprocessor:c, +strings:i,keywords:u}}}})());hljs.registerLanguage("cpp",(()=>{"use strict";function e(e){ +return t("(?:",e,")?")}function t(...e){return e.map((e=>{ +return(t=e)?"string"==typeof t?t:t.source:null;var t})).join("")}return n=>{ +const a=n.COMMENT("//","$",{contains:[{begin:/\\\n/}] +}),r="[a-zA-Z_]\\w*::",i="(?!struct)(decltype\\(auto\\)|"+e(r)+"[a-zA-Z_]\\w*"+e("<[^<>]+>")+")",s={ +className:"type",begin:"\\b[a-z\\d_]*_t\\b"},c={className:"string",variants:[{ +begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[n.BACKSLASH_ESCAPE]},{ +begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)", +end:"'",illegal:"."},n.END_SAME_AS_BEGIN({ +begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},o={ +className:"number",variants:[{begin:"\\b(0b[01']+)"},{ +begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)" +},{ +begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" +}],relevance:0},l={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{ +keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include" +},contains:[{begin:/\\\n/,relevance:0},n.inherit(c,{className:"string"}),{ +className:"string",begin:/<.*?>/},a,n.C_BLOCK_COMMENT_MODE]},u={ +className:"title",begin:e(r)+n.IDENT_RE,relevance:0 +},d=e(r)+n.IDENT_RE+"\\s*\\(",p={ +type:["bool","char","char16_t","char32_t","char8_t","double","float","int","long","short","void","wchar_t"], +keyword:["alignas","alignof","and","and_eq","asm","atomic_cancel","atomic_commit","atomic_noexcept","auto","bitand","bitor","break","case","catch","class","co_await","co_return","co_yield","compl","concept","const","const_cast|10","consteval","constexpr","constinit","continue","decltype","default","delete","do","dynamic_cast|10","else","enum","explicit","export","extern","false","final","for","friend","goto","if","import","inline","module","mutable","namespace","new","noexcept","not","not_eq","nullptr","operator","or","or_eq","override","private","protected","public","reflexpr","register","reinterpret_cast|10","requires","return","signed","sizeof","static","static_assert","static_cast|10","struct","switch","synchronized","template","this","thread_local","throw","transaction_safe","transaction_safe_dynamic","true","try","typedef","typeid","typename","union","unsigned","using","virtual","volatile","while","xor","xor_eq,"], +literal:["NULL","false","nullopt","nullptr","true"],built_in:["_Pragma"], +_type_hints:["any","auto_ptr","barrier","binary_semaphore","bitset","complex","condition_variable","condition_variable_any","counting_semaphore","deque","false_type","future","imaginary","initializer_list","istringstream","jthread","latch","lock_guard","multimap","multiset","mutex","optional","ostringstream","packaged_task","pair","promise","priority_queue","queue","recursive_mutex","recursive_timed_mutex","scoped_lock","set","shared_future","shared_lock","shared_mutex","shared_timed_mutex","shared_ptr","stack","string_view","stringstream","timed_mutex","thread","true_type","tuple","unique_lock","unique_ptr","unordered_map","unordered_multimap","unordered_multiset","unordered_set","variant","vector","weak_ptr","wstring","wstring_view"] +},_={className:"function.dispatch",relevance:0,keywords:{ +_hint:["abort","abs","acos","apply","as_const","asin","atan","atan2","calloc","ceil","cerr","cin","clog","cos","cosh","cout","declval","endl","exchange","exit","exp","fabs","floor","fmod","forward","fprintf","fputs","free","frexp","fscanf","future","invoke","isalnum","isalpha","iscntrl","isdigit","isgraph","islower","isprint","ispunct","isspace","isupper","isxdigit","labs","launder","ldexp","log","log10","make_pair","make_shared","make_shared_for_overwrite","make_tuple","make_unique","malloc","memchr","memcmp","memcpy","memset","modf","move","pow","printf","putchar","puts","realloc","scanf","sin","sinh","snprintf","sprintf","sqrt","sscanf","std","stderr","stdin","stdout","strcat","strchr","strcmp","strcpy","strcspn","strlen","strncat","strncmp","strncpy","strpbrk","strrchr","strspn","strstr","swap","tan","tanh","terminate","to_underlying","tolower","toupper","vfprintf","visit","vprintf","vsprintf"] +}, +begin:t(/\b/,/(?!decltype)/,/(?!if)/,/(?!for)/,/(?!while)/,n.IDENT_RE,(m=/(<[^<>]+>|)\s*\(/, +t("(?=",m,")")))};var m;const g=[_,l,s,a,n.C_BLOCK_COMMENT_MODE,o,c],f={ +variants:[{begin:/=/,end:/;/},{begin:/\(/,end:/\)/},{ +beginKeywords:"new throw return else",end:/;/}],keywords:p,contains:g.concat([{ +begin:/\(/,end:/\)/,keywords:p,contains:g.concat(["self"]),relevance:0}]), +relevance:0},b={className:"function",begin:"("+i+"[\\*&\\s]+)+"+d, +returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:p,illegal:/[^\w\s\*&:<>.]/, +contains:[{begin:"decltype\\(auto\\)",keywords:p,relevance:0},{begin:d, +returnBegin:!0,contains:[u],relevance:0},{begin:/::/,relevance:0},{begin:/:/, +endsWithParent:!0,contains:[c,o]},{relevance:0,match:/,/},{className:"params", +begin:/\(/,end:/\)/,keywords:p,relevance:0, +contains:[a,n.C_BLOCK_COMMENT_MODE,c,o,s,{begin:/\(/,end:/\)/,keywords:p, +relevance:0,contains:["self",a,n.C_BLOCK_COMMENT_MODE,c,o,s]}] +},s,a,n.C_BLOCK_COMMENT_MODE,l]};return{name:"C++", +aliases:["cc","c++","h++","hpp","hh","hxx","cxx"],keywords:p,illegal:"",keywords:p,contains:["self",s]},{begin:n.IDENT_RE+"::",keywords:p},{ +match:[/\b(?:enum(?:\s+(?:class|struct))?|class|struct|union)/,/\s+/,/\w+/], +className:{1:"keyword",3:"title.class"}}])}}})());hljs.registerLanguage("kotlin",(()=>{"use strict" +;var e="\\.([0-9](_*[0-9])*)",n="[0-9a-fA-F](_*[0-9a-fA-F])*",a={ +className:"number",variants:[{ +begin:`(\\b([0-9](_*[0-9])*)((${e})|\\.)?|(${e}))[eE][+-]?([0-9](_*[0-9])*)[fFdD]?\\b` +},{begin:`\\b([0-9](_*[0-9])*)((${e})[fFdD]?\\b|\\.([fFdD]\\b)?)`},{ +begin:`(${e})[fFdD]?\\b`},{begin:"\\b([0-9](_*[0-9])*)[fFdD]\\b"},{ +begin:`\\b0[xX]((${n})\\.?|(${n})?\\.(${n}))[pP][+-]?([0-9](_*[0-9])*)[fFdD]?\\b` +},{begin:"\\b(0|[1-9](_*[0-9])*)[lL]?\\b"},{begin:`\\b0[xX](${n})[lL]?\\b`},{ +begin:"\\b0(_*[0-7])*[lL]?\\b"},{begin:"\\b0[bB][01](_*[01])*[lL]?\\b"}], +relevance:0};return e=>{const n={ +keyword:"abstract as val var vararg get set class object open private protected public noinline crossinline dynamic final enum if else do while for when throw try catch finally import package is in fun override companion reified inline lateinit init interface annotation data sealed internal infix operator out by constructor super tailrec where const inner suspend typealias external expect actual", +built_in:"Byte Short Char Int Long Boolean Float Double Void Unit Nothing", +literal:"true false null"},i={className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"@" +},s={className:"subst",begin:/\$\{/,end:/\}/,contains:[e.C_NUMBER_MODE]},t={ +className:"variable",begin:"\\$"+e.UNDERSCORE_IDENT_RE},r={className:"string", +variants:[{begin:'"""',end:'"""(?=[^"])',contains:[t,s]},{begin:"'",end:"'", +illegal:/\n/,contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"',illegal:/\n/, +contains:[e.BACKSLASH_ESCAPE,t,s]}]};s.contains.push(r);const l={ +className:"meta", +begin:"@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\s*:(?:\\s*"+e.UNDERSCORE_IDENT_RE+")?" +},c={className:"meta",begin:"@"+e.UNDERSCORE_IDENT_RE,contains:[{begin:/\(/, +end:/\)/,contains:[e.inherit(r,{className:"string"})]}] +},o=a,b=e.COMMENT("/\\*","\\*/",{contains:[e.C_BLOCK_COMMENT_MODE]}),E={ +variants:[{className:"type",begin:e.UNDERSCORE_IDENT_RE},{begin:/\(/,end:/\)/, +contains:[]}]},d=E;return d.variants[1].contains=[E],E.variants[1].contains=[d], +{name:"Kotlin",aliases:["kt","kts"],keywords:n, +contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{className:"doctag", +begin:"@[A-Za-z]+"}]}),e.C_LINE_COMMENT_MODE,b,{className:"keyword", +begin:/\b(break|continue|return|this)\b/,starts:{contains:[{className:"symbol", +begin:/@\w+/}]}},i,l,c,{className:"function",beginKeywords:"fun",end:"[(]|$", +returnBegin:!0,excludeEnd:!0,keywords:n,relevance:5,contains:[{ +begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0, +contains:[e.UNDERSCORE_TITLE_MODE]},{className:"type",begin://, +keywords:"reified",relevance:0},{className:"params",begin:/\(/,end:/\)/, +endsParent:!0,keywords:n,relevance:0,contains:[{begin:/:/,end:/[=,\/]/, +endsWithParent:!0,contains:[E,e.C_LINE_COMMENT_MODE,b],relevance:0 +},e.C_LINE_COMMENT_MODE,b,l,c,r,e.C_NUMBER_MODE]},b]},{className:"class", +beginKeywords:"class interface trait",end:/[:\{(]|$/,excludeEnd:!0, +illegal:"extends implements",contains:[{ +beginKeywords:"public protected internal private constructor" +},e.UNDERSCORE_TITLE_MODE,{className:"type",begin://,excludeBegin:!0, +excludeEnd:!0,relevance:0},{className:"type",begin:/[,:]\s*/,end:/[<\(,]|$/, +excludeBegin:!0,returnEnd:!0},l,c]},r,{className:"meta",begin:"^#!/usr/bin/env", +end:"$",illegal:"\n"},o]}}})());hljs.registerLanguage("json",(()=>{"use strict";return e=>({name:"JSON", +contains:[{className:"attr",begin:/"(\\.|[^\\"\r\n])*"(?=\s*:)/,relevance:1.01 +},{match:/[{}[\],:]/,className:"punctuation",relevance:0},e.QUOTE_STRING_MODE,{ +beginKeywords:"true false null" +},e.C_NUMBER_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],illegal:"\\S"}) +})()); \ No newline at end of file diff --git a/themes/hello-friend-ng/assets/js/main.js b/themes/hello-friend-ng/assets/js/main.js new file mode 100644 index 0000000..3744003 --- /dev/null +++ b/themes/hello-friend-ng/assets/js/main.js @@ -0,0 +1,27 @@ +const themeToggle = document.querySelector(".theme-toggle"); + +function getTheme() { + const theme = window.localStorage && window.localStorage.getItem("theme"); + return [theme === "dark", theme === "light"]; +} + +function detectOSColorTheme() { + const [dark, light] = getTheme(); + let attribute; + + if (dark) attribute = "dark" + else if (light) attribute = "light" + else if (window.matchMedia("(prefers-color-scheme: dark)").matches) attribute = "dark" + else attribute = "light" + + document.documentElement.setAttribute("data-theme", attribute); +} + +function switchTheme(e) { + const [dark] = getTheme(); + localStorage.setItem("theme", dark ? "light": "dark") + detectOSColorTheme(); +} + +themeToggle.addEventListener("click", switchTheme, false); +detectOSColorTheme(); diff --git a/themes/hello-friend-ng/assets/js/menu.js b/themes/hello-friend-ng/assets/js/menu.js new file mode 100644 index 0000000..11c722c --- /dev/null +++ b/themes/hello-friend-ng/assets/js/menu.js @@ -0,0 +1,22 @@ +// Mobile menu + +const menuTrigger = document.querySelector(".menu-trigger"); +const menu = document.querySelector(".menu"); +const mobileQuery = getComputedStyle(document.body).getPropertyValue( + "--phoneWidth" +); +const isMobile = () => window.matchMedia(mobileQuery).matches; +const isMobileMenu = () => { + menuTrigger && menuTrigger.classList.toggle("hidden", !isMobile()); + menu && menu.classList.toggle("hidden", isMobile()); +}; + +isMobileMenu(); + +menuTrigger && + menuTrigger.addEventListener( + "click", + () => menu && menu.classList.toggle("hidden") + ); + +window.addEventListener("resize", isMobileMenu); diff --git a/themes/hello-friend-ng/assets/scss/_404.scss b/themes/hello-friend-ng/assets/scss/_404.scss new file mode 100644 index 0000000..c6030de --- /dev/null +++ b/themes/hello-friend-ng/assets/scss/_404.scss @@ -0,0 +1,9 @@ +.btn-404 svg { + vertical-align: middle; + display: inline-block; + margin-right: 5px; +} + +.btn-404 a { + margin: 0 10px; +} diff --git a/themes/hello-friend-ng/assets/scss/_buttons.scss b/themes/hello-friend-ng/assets/scss/_buttons.scss new file mode 100644 index 0000000..624e7ee --- /dev/null +++ b/themes/hello-friend-ng/assets/scss/_buttons.scss @@ -0,0 +1,139 @@ +.button-container { + display: table; + margin-left: auto; + margin-right: auto; +} + +button, +.button, +a.button { + position: relative; + display: flex; + align-items: center; + justify-content: center; + padding: 8px 18px; + margin-bottom: 5px; + text-decoration: none; + text-align: center; + font-weight: 500; + border-radius: 8px; + border: 1px solid transparent; + appearance: none; + cursor: pointer; + outline: none; + // Default + background: $light-background-header; + + @media (prefers-color-scheme: dark) { + background: $dark-background-header; + color: inherit; + } + + @media (prefers-color-scheme: light) { + background: $light-background-header; + } + + [data-theme=dark] & { + background: $dark-background-header; + color: inherit; + } + + [data-theme=light] & { + background: $light-background-header; + } + + &.outline { + background: transparent; + box-shadow: none; + padding: 8px 18px; + // Default + border-color: $light-background-secondary; + + @media (prefers-color-scheme: dark) { + border-color: $dark-background-secondary; + color: inherit; + } + + @media (prefers-color-scheme: light) { + border-color: $light-background-secondary; + } + + [data-theme=dark] & { + border-color: $dark-background-secondary; + color: inherit; + } + + [data-theme=light] & { + border-color: $light-background-secondary; + } + + :hover { + transform: none; + box-shadow: none; + } + } + + &.primary { + box-shadow: 0 4px 6px rgba(50, 50, 93, .11), 0 1px 3px rgba(0, 0, 0, .08); + + &:hover { + box-shadow: 0 2px 6px rgba(50, 50, 93, .21), 0 1px 3px rgba(0, 0, 0, .08); + } + } + + &.link { + background: none; + font-size: 1rem; + } + + &.small { + font-size: .8rem; + } + + &.wide { + min-width: 200px; + padding: 14px 24px; + } +} + +.code-toolbar { + margin-bottom: 20px; + + .toolbar-item a { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 3px 8px; + margin-bottom: 5px; + text-decoration: none; + text-align: center; + font-size: 13px; + font-weight: 500; + border-radius: 8px; + border: 1px solid transparent; + appearance: none; + cursor: pointer; + outline: none; + // Default + background: $light-background-secondary; + + @media (prefers-color-scheme: dark) { + background: $dark-background-secondary; + color: inherit; + } + + @media (prefers-color-scheme: light) { + background: $light-background-secondary; + } + + [data-theme=dark] & { + background: $dark-background-secondary; + color: inherit; + } + + [data-theme=light] & { + background: $light-background-secondary; + } + } +} diff --git a/themes/hello-friend-ng/assets/scss/_fonts.scss b/themes/hello-friend-ng/assets/scss/_fonts.scss new file mode 100644 index 0000000..83fb588 --- /dev/null +++ b/themes/hello-friend-ng/assets/scss/_fonts.scss @@ -0,0 +1,50 @@ +@font-face { + font-family: 'Inter UI'; + font-style: normal; + font-display: auto; + font-weight: 400; + src: url("../fonts/Inter-UI-Regular.woff2") format("woff2"), + url("../fonts/Inter-UI-Regular.woff") format("woff"); +} +@font-face { + font-family: 'Inter UI'; + font-style: italic; + font-display: auto; + font-weight: 400; + src: url("../fonts/Inter-UI-Italic.woff2") format("woff2"), + url("../fonts/Inter-UI-Italic.woff") format("woff"); +} + +@font-face { + font-family: 'Inter UI'; + font-style: normal; + font-display: auto; + font-weight: 600; + src: url("../fonts/Inter-UI-Medium.woff2") format("woff2"), + url("../fonts/Inter-UI-Medium.woff") format("woff"); +} +@font-face { + font-family: 'Inter UI'; + font-style: italic; + font-display: auto; + font-weight: 600; + src: url("../fonts/Inter-UI-MediumItalic.woff2") format("woff2"), + url("../fonts/Inter-UI-MediumItalic.woff") format("woff"); +} + +@font-face { + font-family: 'Inter UI'; + font-style: normal; + font-display: auto; + font-weight: 800; + src: url("../fonts/Inter-UI-Bold.woff2") format("woff2"), + url("../fonts/Inter-UI-Bold.woff") format("woff"); +} +@font-face { + font-family: 'Inter UI'; + font-style: italic; + font-display: auto; + font-weight: 800; + src: url("../fonts/Inter-UI-BoldItalic.woff2") format("woff2"), + url("../fonts/Inter-UI-BoldItalic.woff") format("woff"); +} diff --git a/themes/hello-friend-ng/assets/scss/_footer.scss b/themes/hello-friend-ng/assets/scss/_footer.scss new file mode 100644 index 0000000..cc64c9d --- /dev/null +++ b/themes/hello-friend-ng/assets/scss/_footer.scss @@ -0,0 +1,49 @@ +.footer { + padding: 40px 20px; + flex-grow: 0; + color: $light-color-secondary; + + &__inner { + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto; + width: 760px; + max-width: 100%; + + @media #{$media-size-tablet} { + flex-direction: column; + } + } + + &__content { + display: flex; + flex-direction: row; + align-items: center; + font-size: 1rem; + color: $light-color-secondary; + + @media #{$media-size-tablet} { + flex-direction: column; + margin-top: 10px; + } + + & > *:not(:last-child)::after { + content: "•"; + padding: 0 5px; + + @media #{$media-size-tablet} { + content: ""; + padding: 0; + } + } + + & > *:last-child { + padding: 0 0px; + + @media #{$media-size-tablet} { + padding: 0; + } + } + } +} diff --git a/themes/hello-friend-ng/assets/scss/_header.scss b/themes/hello-friend-ng/assets/scss/_header.scss new file mode 100644 index 0000000..d16e12b --- /dev/null +++ b/themes/hello-friend-ng/assets/scss/_header.scss @@ -0,0 +1,63 @@ +.header { + display: flex; + align-items: center; + justify-content: center; + position: relative; + padding: 20px; + // Default + background: $light-background-header; + + @media (prefers-color-scheme: dark) { + background: $dark-background-header; + } + + @media (prefers-color-scheme: light) { + background: $light-background-header; + } + + [data-theme=dark] & { + background: $dark-background-header; + } + + [data-theme=light] & { + background: $light-background-header; + } + + &__right { + display: flex; + flex-direction: row; + align-items: center; + + @media #{$media-size-phone} { + flex-direction: row-reverse; + } + } + + &__inner { + display: flex; + align-items: center; + justify-content: space-between; + margin: 0 auto; + width: 760px; + max-width: 100%; + } +} + +.theme-toggle { + display: flex; + align-items: center; + justify-content: center; + line-height: 1; + cursor: pointer; +} + +.theme-toggler { + fill: currentColor; +} + +.not-selectable { + user-select: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; +} \ No newline at end of file diff --git a/themes/hello-friend-ng/assets/scss/_list.scss b/themes/hello-friend-ng/assets/scss/_list.scss new file mode 100644 index 0000000..e431b37 --- /dev/null +++ b/themes/hello-friend-ng/assets/scss/_list.scss @@ -0,0 +1,85 @@ +.posts { + width: 100%; + max-width: 800px; + text-align: left; + padding: 20px; + margin: 20px auto; + + @media #{$media-size-tablet} { + max-width: 660px; + } + + &:not(:last-of-type) { + // Default + border-bottom: 1px solid $light-border-color; + + @media (prefers-color-scheme: dark) { + border-bottom: 1px solid $dark-border-color; + } + + @media (prefers-color-scheme: light) { + border-bottom: 1px solid $light-border-color; + } + + [data-theme=dark] & { + border-bottom: 1px solid $dark-border-color; + } + + [data-theme=light] & { + border-bottom: 1px solid $light-border-color; + } + } + + &-group { + display: flex; + margin-bottom: 1.9em; + line-height: normal; + + @media #{$media-size-tablet} { + display: block; + } + } + + &-list { + flex-grow: 1; + margin: 0; + padding: 0; + list-style: none; + } + + .post { + &-title { + font-size: 1rem; + margin: 5px 0 5px 0; + } + + &-year { + padding-top: 6px; + margin-right: 1.8em; + font-size: 1.6em; + @include dimmed; + + @media #{$media-size-tablet} { + margin: -6px 0 4px; + } + } + + &-item { + border-bottom: 1px grey dashed; + + a { + display: flex; + justify-content: space-between; + align-items: baseline; + padding: 12px 0; + text-decoration: none; + } + } + + &-day { + flex-shrink: 0; + margin-left: 1em; + @include dimmed; + } + } +} diff --git a/themes/hello-friend-ng/assets/scss/_logo.scss b/themes/hello-friend-ng/assets/scss/_logo.scss new file mode 100644 index 0000000..3fa39c8 --- /dev/null +++ b/themes/hello-friend-ng/assets/scss/_logo.scss @@ -0,0 +1,45 @@ +.logo { + display: flex; + align-items: center; + text-decoration: none; + font-weight: bold; + font-display: auto; + font-family: monospace, monospace; + + img { + height: 32px; + border-radius: 32px; + margin-right: 12px; + } + + &__mark { + margin-right: 3px; + } + + &__text { + font-size: 1rem; + } + + &__cursor { + display: inline-block; + width: 10px; + height: 1rem; + background: #fe5186; + margin-left: 5px; + border-radius: 1px; + animation: cursor 1s infinite; + } + + @media (prefers-reduced-motion: reduce) { + &__cursor { + animation: none; + } + } + +} + +@keyframes cursor { + 0% { opacity: 0; } + 50% { opacity: 1; } + 100% { opacity: 0; } +} diff --git a/themes/hello-friend-ng/assets/scss/_main.scss b/themes/hello-friend-ng/assets/scss/_main.scss new file mode 100644 index 0000000..1c0941d --- /dev/null +++ b/themes/hello-friend-ng/assets/scss/_main.scss @@ -0,0 +1,522 @@ +html { + box-sizing: border-box; + line-height: 1.6; + letter-spacing: 0.06em; + scroll-behavior: smooth; +} + +*, +*:before, +*:after { + box-sizing: inherit; +} + +body { + margin: 0; + padding: 0; + font-family: "Inter UI", -apple-system, BlinkMacSystemFont, "Roboto", + "Segoe UI", Helvetica, Arial, sans-serif; + font-display: auto; + font-size: 1.4rem; + line-height: 1.54; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + font-feature-settings: "liga", "tnum", "case", "calt", "zero", "ss01", "locl"; + -webkit-overflow-scrolling: touch; + -webkit-text-size-adjust: 100%; + + display: flex; + min-height: 100vh; + flex-direction: column; + + // Default + background-color: $light-background; + color: $light-color; + + @media #{$media-size-phone} { + font-size: 1rem; + } + + @media (prefers-color-scheme: dark) { + background-color: $dark-background; + color: $dark-color; + } + + @media (prefers-color-scheme: light) { + background-color: $light-background; + color: $light-color; + } + + [data-theme=dark] & { + background-color: $dark-background; + color: $dark-color; + } + + [data-theme=light] & { + background-color: $light-background; + color: $light-color; + } +} + +h2, +h3, +h4, +h5, +h6 { + display: flex; + align-items: center; + line-height: 1.1; + + &.center { + justify-content: center; + } + +} + +.post-content { + h1, h2, h3, h4, h5, h6 { + & a { + visibility: hidden; + color: #f2203a; + text-decoration: none; + margin-left: 4px; + } + + &:hover a { + visibility: visible; + } + } +} + +h1 { + font-size: 2.625rem; +} + +h2 { + font-size: 1.675rem; +} + +h3 { + font-size: 1.475rem; +} + +h4 { + font-size: 1.325rem; +} + +@media #{$media-size-phone} { + h1 { + font-size: 2rem; + } + + h2 { + font-size: 1.4rem; + } + + h3 { + font-size: 1.15rem; + } + + h4 { + font-size: 1.125rem; + } +} + +a { + color: inherit; + + &:hover { + color: #f2203a; + } +} + +p a, .post-content li a, #toc a { + text-decoration: none; + color: $light-color; + font-weight: normal; + box-shadow: inset 0 -0.06em 0 #f2203a; + -webkit-transition: box-shadow .2s ease-in-out, color .2s ease-in-out; + transition: box-shadow .2s ease-in-out, color .2s ease-in-out; + + @media (prefers-color-scheme: dark) { + color: $dark-color; + } + + @media (prefers-color-scheme: light) { + color: $light-color; + } + + [data-theme=dark] & { + color: $dark-color; + } + + [data-theme=light] & { + color: $light-color; + } + + &:hover { + box-shadow: inset 0 -1.5em 0 #f2203a; + color: white; + } +} + +#toc { + li { + margin-bottom: 5px; + } +} + +img { + display: block; + max-width: 100%; + + &.left { + margin-right: auto; + } + + &.center { + margin-left: auto; + margin-right: auto; + } + + &.right { + margin-left: auto; + } + &.circle { + border-radius: 50%; + max-width: 25%; + margin: auto; + } +} + +figure { + display: table; + max-width: 100%; + margin: 25px 0; + + &.left { + margin-right: auto; + } + + &.left-floated { + margin-right: auto; + float: left; + img { + margin: 20px 20px 20px 0; + } + } + + &.center { + margin-left: auto; + margin-right: auto; + } + + &.right { + margin-left: auto; + } + + &.right-floated { + margin-left: auto; + float: right; + img { + margin: 20px 0 20px 20px; + } + } + + &.rounded { + img { + border-radius: 50%; + } + } + + figcaption { + font-size: 14px; + margin-top: 5px; + opacity: 0.8; + + &.left { + text-align: left; + } + + &.center { + text-align: center; + } + + &.right { + text-align: right; + } + } +} + +em, i, strong { + // Default + color: black; + + @media (prefers-color-scheme: dark) { + color: white; + } + + @media (prefers-color-scheme: light) { + color: black; + } + + [data-theme=dark] & { + color: white; + } + + [data-theme=light] & { + color: black; + } +} + +code { + font-family: Consolas, Monaco, Andale Mono, Ubuntu Mono, monospace; + font-display: auto; + font-feature-settings: normal; + padding: 1px 6px; + margin: 0 2px; + border-radius: 5px; + font-size: 0.95rem; + // Default + background: $light-background-secondary; + + @media (prefers-color-scheme: dark) { + background: $dark-background-secondary; + } + + @media (prefers-color-scheme: light) { + background: $light-background-secondary; + } + + [data-theme=dark] & { + background: $dark-background-secondary; + } + + [data-theme=light] & { + background: $light-background-secondary; + } +} + +pre { + background: #212020; + padding: 10px 10px 10px 20px; + border-radius: 8px; + font-size: 0.95rem; + overflow: auto; + + @media #{$media-size-phone} { + white-space: pre-wrap; + word-wrap: break-word; + } + + code { + background: none !important; + margin: 0; + padding: 0; + font-size: inherit; + // Default + color: #ccc; + + @media (prefers-color-scheme: dark) { + color: inherit; + } + + @media (prefers-color-scheme: light) { + color: #ccc; + } + + [data-theme=dark] & { + color: inherit; + } + + [data-theme=light] & { + color: #ccc; + } + } +} + +blockquote { + border-left: 3px solid #f2203a; + margin: 40px 20px; + padding: 5px 15px; + + @media #{$media-size-phone} { + margin: 10px; + padding: 10px; + } + + &:before { + content: "”"; + font-family: Georgia, serif; + font-display: auto; + font-size: 3.875rem; + position: absolute; + left: -40px; + top: -20px; + } + + p:first-of-type { + margin-top: 0; + } + + p:last-of-type { + margin-bottom: 0; + } +} + +ul, +ol { + margin-left: 40px; + padding: 0; + + @media #{$media-size-phone} { + margin-left: 20px; + } +} + +ol ol { + list-style-type: lower-alpha; +} + +.container { + flex: 1 auto; + display: flex; + flex-direction: column; + justify-content: center; + text-align: center; +} + +.content { + display: flex; + flex-direction: column; + flex: 1 auto; + align-items: center; + justify-content: center; + margin: 0; + + @media #{$media-size-phone} { + margin-top: 0; + } +} + +.hero { + display: flex; + align-items: center; + justify-content: space-between; + margin: 0 auto; + width: 60%; + max-width: 1000px; + + div { + min-width: 240px; + } + + @media #{$media-size-laptop} { + width: 80% + } + + @media #{$media-size-tablet} { + width: 90% + } + + img { + width: 100%; + max-width: 440px; + } + + @media #{$media-size-phone} { + justify-content: center; + width: auto; + img { + display: none; + } + } +} + + +hr { + width: 100%; + border: none; + height: 1px; + // Default + background: $light-border-color; + + @media (prefers-color-scheme: dark) { + background: $dark-border-color; + } + + @media (prefers-color-scheme: light) { + background: $light-border-color; + } + + [data-theme=dark] & { + background: $dark-border-color; + } + + [data-theme=light] & { + background: $light-border-color; + } +} + +.hidden { + display: none; +} + +.hide-on-phone { + @media #{$media-size-phone} { + display: none; + } +} + +.hide-on-tablet { + @media #{$media-size-tablet} { + display: none; + } +} + +// Accessibility +.screen-reader-text { + border: 0; + clip: rect(1px, 1px, 1px, 1px); + clip-path: inset(50%); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute !important; + width: 1px; + word-wrap: normal !important; +} + +.screen-reader-text:focus { + background-color: #f1f1f1; + border-radius: 3px; + box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.6); + clip: auto !important; + clip-path: none; + color: #21759b; + display: block; + font-size: 14px; + font-size: 0.875rem; + font-weight: bold; + height: auto; + width: auto; + top: 5px; + left: 5px; + line-height: normal; + padding: 15px 23px 14px; + text-decoration: none; + z-index: 100000; +} + +.background-image { + background-repeat: no-repeat; + background-attachment: fixed; + background-size: cover; + background-position: center center; +} + +// Prism JS Additionals +.highlight { + margin: 30px auto; +} diff --git a/themes/hello-friend-ng/assets/scss/_menu.scss b/themes/hello-friend-ng/assets/scss/_menu.scss new file mode 100644 index 0000000..f427496 --- /dev/null +++ b/themes/hello-friend-ng/assets/scss/_menu.scss @@ -0,0 +1,83 @@ +.menu { + z-index: 9999; + // Default + background: $light-background-header; + + @media (prefers-color-scheme: dark) { + background: $dark-background-header; + } + + @media (prefers-color-scheme: light) { + background: $light-background-header; + } + + [data-theme=dark] & { + background: $dark-background-header; + } + + [data-theme=light] & { + background: $light-background-header; + } + + @media #{$media-size-phone} { + position: absolute; + top: 50px; + right: 0; + border: none; + margin: 0; + padding: 10px; + } + + &__inner { + display: flex; + align-items: center; + justify-content: flex-start; + max-width: 100%; + margin: 0 auto; + padding: 0 15px; + font-size: 1rem; + list-style: none; + + li { + margin: 0 12px; + } + + @media #{$media-size-phone} { + flex-direction: column; + align-items: flex-start; + padding: 0; + + li { + margin: 0; + padding: 5px; + } + } + } + + &-trigger { + width: 24px; + height: 24px; + fill: currentColor; + margin-left: 10px; + cursor: pointer; + display: none; + + @media #{$media-size-phone} { + display: block; + } + } + + a { + display: inline-block; + margin-right: 15px; + text-decoration: none; + + &:hover { + text-decoration: underline; + } + + &:last-of-type { + margin-right: 0; + } + } +} diff --git a/themes/hello-friend-ng/assets/scss/_mixins.scss b/themes/hello-friend-ng/assets/scss/_mixins.scss new file mode 100644 index 0000000..7293fce --- /dev/null +++ b/themes/hello-friend-ng/assets/scss/_mixins.scss @@ -0,0 +1,3 @@ +@mixin dimmed { + opacity: .6; +} diff --git a/themes/hello-friend-ng/assets/scss/_normalize.scss b/themes/hello-friend-ng/assets/scss/_normalize.scss new file mode 100644 index 0000000..ffa240e --- /dev/null +++ b/themes/hello-friend-ng/assets/scss/_normalize.scss @@ -0,0 +1,367 @@ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ + +/* Webkit Scrollbar Customize */ +::-webkit-scrollbar { + width: 8px; + height: 8px; + background: #212020; +} + +::-webkit-scrollbar-thumb { + background: #888; + + &:hover { + background: #dcdcdc; + } +} + +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers. + */ + +body { + margin: 0; +} + +/** + * Render the `main` element consistently in IE. + */ + +main { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-display: auto; + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Remove the gray background on active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-display: auto; + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove the border on images inside links in IE 10. + */ + +img { + border-style: none; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-display: auto; + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ + +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ + +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ + +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Misc + ========================================================================== */ + +/** + * Add the correct display in IE 10+. + */ + +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ + +[hidden] { + display: none; +} diff --git a/themes/hello-friend-ng/assets/scss/_sharing-buttons.scss b/themes/hello-friend-ng/assets/scss/_sharing-buttons.scss new file mode 100644 index 0000000..c6bee53 --- /dev/null +++ b/themes/hello-friend-ng/assets/scss/_sharing-buttons.scss @@ -0,0 +1,34 @@ +.sharing-buttons { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + + .resp-sharing-button__icon, + .resp-sharing-button__link { + display: inline-block; + } + + .resp-sharing-button__link { + text-decoration: none; + margin: 0.5em; + } + + .resp-sharing-button { + border-radius: 5px; + transition: 25ms ease-out; + padding: 0.5em 0.75em; + font-family: Helvetica Neue,Helvetica,Arial,sans-serif; + } + + .resp-sharing-button__icon svg { + width: 1em; + height: 1em; + margin-right: 0.4em; + vertical-align: top; + } + + .resp-sharing-button--small svg { + margin: 0; + vertical-align: middle; + } +} \ No newline at end of file diff --git a/themes/hello-friend-ng/assets/scss/_single.scss b/themes/hello-friend-ng/assets/scss/_single.scss new file mode 100644 index 0000000..d3b2a23 --- /dev/null +++ b/themes/hello-friend-ng/assets/scss/_single.scss @@ -0,0 +1,230 @@ +.post { + width: 100%; + max-width: 800px; + text-align: left; + padding: 20px; + margin: 20px auto; + @media #{$media-size-tablet} { + max-width: 600px; + } + + &-date { + &:after { + content: '—'; + } + } + + &-title { + font-size: 2.625rem; + margin: 0 0 20px; + @media #{$media-size-phone} { + font-size: 2rem; + } + + a { + text-decoration: none; + } + } + + &-tags { + display: block; + margin-bottom: 20px; + font-size: 1rem; + opacity: 0.5; + + a { + text-decoration: none; + } + } + + &-content { + margin-top: 30px; + } + + &-cover { + border-radius: 8px; + margin: 40px -50px; + width: $max-width; + max-width: $max-width; + @media #{$media-size-tablet} { + margin: 20px 0; + width: 100%; + } + } + + &-excerpt { + font-style: italic; + } + + &-info { + margin-top: 30px; + font-size: 0.9rem; + line-height: normal; + + p { + margin: 0.8em 0; + } + + svg { + margin-right: 0.8em; + } + + .tag { + margin-right: 0.5em; + + &::before { + content: "#"; + } + } + + .feather { + display: inline-block; + vertical-align: -.125em; + width: 1em; + height: 1em; + } + } + + &-audio { + display: flex; + justify-content: center; + align-items: center; + padding-top: 20px; + + audio { + width: 90%; + } + } + + .flag { + border-radius: 50%; + margin: 0 5px; + } +} + +.pagination { + margin-top: 20px; + + &__title { + display: flex; + text-align: center; + position: relative; + margin: 20px 0; + + &-h { + text-align: center; + margin: 0 auto; + padding: 5px 10px; + font-size: 0.8rem; + text-transform: uppercase; + text-decoration: none; + letter-spacing: 0.1em; + z-index: 1; + // Default + background: $light-background; + color: $light-color-secondary; + + @media (prefers-color-scheme: dark) { + background: $dark-background; + color: $dark-color-secondary; + } + + @media (prefers-color-scheme: light) { + background: $light-background; + color: $light-color-secondary; + } + + [data-theme=dark] & { + background: $dark-background; + color: $dark-color-secondary; + } + + [data-theme=light] & { + background: $light-background; + color: $light-color-secondary; + } + } + + hr { + position: absolute; + left: 0; + right: 0; + width: 100%; + margin-top: 15px; + z-index: 0; + } + } + + &__buttons { + display: flex; + align-items: center; + justify-content: center; + + a { + font-weight: bold; + } + } +} + +.button { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 1rem; + font-weight: 600; + border-radius: 8px; + max-width: 40%; + padding: 0; + cursor: pointer; + appearance: none; + // Default + background: $light-background-secondary; + + @media (prefers-color-scheme: dark) { + background: $dark-background-header; + } + + @media (prefers-color-scheme: light) { + background: $light-background-secondary; + } + + [data-theme=dark] & { + background: $dark-background-header; + } + + [data-theme=light] & { + background: $light-background-secondary; + } + + &:hover { + color: #f2203a; + } + + + .button { + margin-left: 10px; + } + + a { + display: flex; + padding: 8px 16px; + text-decoration: none; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + } + + &__text { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + } + + &.next .button__icon { + margin-left: 8px; + } + + &.previous .button__icon { + margin-right: 8px; + } +} diff --git a/themes/hello-friend-ng/assets/scss/_tables.scss b/themes/hello-friend-ng/assets/scss/_tables.scss new file mode 100644 index 0000000..68dbe05 --- /dev/null +++ b/themes/hello-friend-ng/assets/scss/_tables.scss @@ -0,0 +1,84 @@ +.post-content { + table { + border-collapse: collapse; + margin: 25px auto; + font-size: 0.9em; + min-width: 400px; + max-width: 100%; + + th, + td { + padding: 12px 15px; + // Default + border: 1px solid $light-table-color; + + @media (prefers-color-scheme: dark) { + border: 1px solid $dark-table-color; + } + + @media (prefers-color-scheme: light) { + border: 1px solid $light-table-color; + } + + [data-theme=dark] & { + border: 1px solid $dark-table-color; + } + + [data-theme=light] & { + border: 1px solid $light-table-color; + } + } + + thead { + tr { + text-align: left; + // Default + background-color: $light-table-color; + color: $light-color; + + @media (prefers-color-scheme: dark) { + background-color: $dark-table-color; + color: $dark-color; + } + + @media (prefers-color-scheme: light) { + background-color: $light-table-color; + color: $light-color; + } + + [data-theme=dark] & { + background-color: $dark-table-color; + color: $dark-color; + } + + [data-theme=light] & { + background-color: $light-table-color; + color: $light-color; + } + } + } + + tbody { + tr { + // Default + border: 1px solid $light-table-color; + + @media (prefers-color-scheme: dark) { + border: 1px solid $dark-table-color; + } + + @media (prefers-color-scheme: light) { + border: 1px solid $light-table-color; + } + + [data-theme=dark] & { + border: 1px solid $dark-table-color; + } + + [data-theme=light] & { + border: 1px solid $light-table-color; + } + } + } + } +} diff --git a/themes/hello-friend-ng/assets/scss/_toc.scss b/themes/hello-friend-ng/assets/scss/_toc.scss new file mode 100644 index 0000000..2f37b0b --- /dev/null +++ b/themes/hello-friend-ng/assets/scss/_toc.scss @@ -0,0 +1,7 @@ +.toc-title { + font-weight: bold; +} + +#toc li { + font-size: 1.2rem; +} diff --git a/themes/hello-friend-ng/assets/scss/_variables.scss b/themes/hello-friend-ng/assets/scss/_variables.scss new file mode 100644 index 0000000..5d3b82c --- /dev/null +++ b/themes/hello-friend-ng/assets/scss/_variables.scss @@ -0,0 +1,32 @@ +@charset "UTF-8"; + +/* Light theme color */ +$light-background: #fff; +$light-background-secondary: #eaeaea; +$light-background-header: #fafafa; +$light-color: #222; +$light-color-secondary: #999; +$light-border-color: #dcdcdc; +$light-table-color: #dcdcdc; + +/* Dark theme colors */ +$dark-background: #090B0F; +$dark-background-secondary: #0C1016; +$dark-background-header: #151A20; +$dark-color: #a9a9b3; +$dark-color-secondary: #b3b3bd; +$dark-border-color: #4e4e57; +$dark-table-color: #4e4e57; + +$media-size-phone: "(max-width: 684px)"; +$media-size-tablet: "(max-width: 900px)"; +$media-size-laptop: "(max-width: 1200px)"; + +/* Variables for js, must be the same as these in @custom-media queries */ +:root { + --phoneWidth: (max-width: 684px); + --tabletWidth: (max-width: 900px); +} + +/* Content */ +$max-width: 860px; diff --git a/themes/hello-friend-ng/assets/scss/main.scss b/themes/hello-friend-ng/assets/scss/main.scss new file mode 100644 index 0000000..346aab6 --- /dev/null +++ b/themes/hello-friend-ng/assets/scss/main.scss @@ -0,0 +1,20 @@ +/* Must be loaded before everything else */ +@import "normalize"; +// @import "prism"; +/* Main stuff */ +@import "variables"; +@import "mixins"; +@import "fonts"; +@import "buttons"; +/* Modules */ +@import "header"; +@import "logo"; +@import "menu"; +@import "main"; +@import "toc"; +@import "list"; +@import "single"; +@import "footer"; +@import "sharing-buttons"; +@import "tables"; +@import "404"; diff --git a/themes/hello-friend-ng/data/langFlags.yaml b/themes/hello-friend-ng/data/langFlags.yaml new file mode 100644 index 0000000..4132ed4 --- /dev/null +++ b/themes/hello-friend-ng/data/langFlags.yaml @@ -0,0 +1,18 @@ +de: de +en: gb +es: es +fr: fr +gl: es-ga +hi: in +it: it +ja: jp +ml: in +nl: nl +pt-br: br +ru: ru +tr: tr +uk: uk +zh-cn: cn +zh-hk: hk +zh-tw: tw +ro: ro diff --git a/themes/hello-friend-ng/docs/config.md b/themes/hello-friend-ng/docs/config.md new file mode 100644 index 0000000..b632286 --- /dev/null +++ b/themes/hello-friend-ng/docs/config.md @@ -0,0 +1,15 @@ +# Configuration + +There are some settings you can set in your `config.toml`. + +## Default area + +The settings in the default area are usually provided by Hugo itself. Check [Configure Hugo](https://gohugo.io/getting-started/configuration/#all-configuration-settings) for more information. But I want to list some important things here which are relevant to this theme. + +### paginate + +``` +paginate = 10 +``` + +This setting will paginate your list views. Set to `0` to disable it. For more information check (https://gohugo.io/templates/pagination/). diff --git a/themes/hello-friend-ng/docs/favicons.md b/themes/hello-friend-ng/docs/favicons.md new file mode 100644 index 0000000..a4794aa --- /dev/null +++ b/themes/hello-friend-ng/docs/favicons.md @@ -0,0 +1,13 @@ +# Favicons + +Use [RealFaviconGenerator](https://realfavicongenerator.net/) to generate these files, put them into your site's static folder: + +- android-chrome-192x192.png +- android-chrome-512x512.png +- apple-touch-icon.png +- favicon-16x16.png +- favicon-32x32.png +- favicon.ico +- mstile-150x150.png +- safari-pinned-tab.svg +- site.webmanifest \ No newline at end of file diff --git a/themes/hello-friend-ng/docs/svgs.md b/themes/hello-friend-ng/docs/svgs.md new file mode 100644 index 0000000..a8d9296 --- /dev/null +++ b/themes/hello-friend-ng/docs/svgs.md @@ -0,0 +1,74 @@ +# Available Social Icons: + +- [amazon](https://simpleicons.org/?q=amazon) +- [anilist](https://simpleicons.org/?q=anilist) +- [box](https://simpleicons.org/?q=box) +- [behance](https://simpleicons.org/?q=behance) +- [bitbucket](https://simpleicons.org/?q=bitbucket) +- case - generic briefcase icon for work based links +- [codesandbox](https://simpleicons.org/?q=codesandbox) +- [codechef](https://simpleicons.org/?q=codechef) +- [codepen](https://simpleicons.org/?q=codepen) +- dev +- [deviantart](https://simpleicons.org/?q=deviantart) +- [discogs](https://simpleicons.org/?q=discogs) +- [discord](https://simpleicons.org/?q=discord) +- [docker](https://simpleicons.org/?q=docker) +- [dribbble](https://simpleicons.org/?q=dribbble) +- [email](https://feathericons.com/?query=mail) +- [facebook](https://simpleicons.org/?q=facebook) +- [fitbit](https://simpleicons.org/?q=fitbit) +- git +- [gitbook](https://simpleicons.org/?q=gitbook) +- [gitea](https://simpleicons.org/?q=gitea) +- [github](https://feathericons.com/?query=github) +- [gitlab](https://feathericons.com/?query=gitlab) +- [gitter](https://simpleicons.org/icons/gitter.svg) +- [goodreads](https://simpleicons.org/?q=goodreads) +- [googleplay](https://simpleicons.org/?q=googleplay) +- [googlescholar](https://simpleicons.org/?q=googlescholar) +- [hackerone](https://simpleicons.org/?q=hackerone) +- [hackerrank](https://simpleicons.org/?q=hackerrank) +- [hackthebox](https://simpleicons.org/?q=hackthebox) +- [instagram](https://feathericons.com/?query=instagram) +- [kaggle](https://simpleicons.org/?q=kaggle) +- [keybase](https://simpleicons.org/?q=keybase) +- [lastfm](https://simpleicons.org/?q=lastfm) +- [leetcode](https://simpleicons.org/?q=leetcode) +- [letterboxd](https://simpleicons.org/?q=letterboxd) +- [librepay](https://simpleicons.org/?q=liberapay) +- [lichess](https://simpleicons.org/?q=lichess) +- [linkedin](https://feathericons.com/?query=linked) +- [mastodon](https://simpleicons.org/?q=mastodon) +- [matrix](https://simpleicons.org/?q=matrix) +- [medium](https://simpleicons.org/?q=medium) +- [mixcloud](https://simpleicons.org/?q=mixcloud) +- [npm](https://simpleicons.org/?q=npm) +- [orcid](https://simpleicons.org/?q=orcid) +- [peertube](https://simpleicons.org/?q=peertube) +- [pinterest](https://simpleicons.org/?q=pinterest) +- [pixelfed](https://github.com/pixelfed/pixelfed/blob/dev/public/img/pixelfed-icon-black.svg) +- [podcasts-apple](https://simpleicons.org/?q=podcast) +- [podcasts-google](https://simpleicons.org/?q=podcast) +- [polywork](https://simpleicons.org/?q=polywork) +- [reddit](https://simpleicons.org/?q=reddit) +- [researchgate](https://simpleicons.org/?q=researchgate) +- [signal](https://simpleicons.org/?q=signal) +- [slack](https://simpleicons.org/?q=slack) +- [soundcloud](https://simpleicons.org/?q=soundcloud) +- [spotify](https://simpleicons.org/?q=spotify) +- [stackoverflow](https://simpleicons.org/?q=stackoverflow) +- [steam](https://simpleicons.org/?q=Steam) +- [telegram](https://simpleicons.org/?q=telegram) +- [threema](https://simpleicons.org/?q=threema) +- [tryhackme](https://simpleicons.org/?q=tryhackme) +- [tumblr](https://simpleicons.org/?q=tumblr) +- [twitch](https://simpleicons.org/?q=twitch) +- [twitter](https://simpleicons.org/?q=twitter) +- [unsplash](https://simpleicons.org/?q=unsplash) +- [whatsapp](https://simpleicons.org/?q=whatsapp) +- [xampp](https://simpleicons.org/?q=xampp) +- [xing](https://simpleicons.org/?q=xing) +- [xmpp](https://simpleicons.org/?q=xmpp) +- [ycombinator](https://simpleicons.org/?q=ycombinator) +- [youtube](https://simpleicons.org/?q=youtube) diff --git a/themes/hello-friend-ng/i18n/de.toml b/themes/hello-friend-ng/i18n/de.toml new file mode 100644 index 0000000..7ef99a2 --- /dev/null +++ b/themes/hello-friend-ng/i18n/de.toml @@ -0,0 +1,39 @@ +# Translations for German +# https://gohugo.io/content-management/multilingual/#translation-of-strings + +# Generic +# +[translations] +other = "Übersetzungen" + +[postAvailable] +other = "Auch verfügbar auf" + + +# 404.html +# +[archives] +other = "Archiv" + +[home] +other = "Home" + +[notFound] +other = "Oops, Seite nicht gefunden ..." + + +# posts/single.html +# +[readingTime] +one = "Eine Minute" +other = "{{ .Count }} Minuten" + +[tableOfContents] +other = "Inhaltsverzeichnis" + +[wordCount] +one = "Ein Wort" +other = "{{ .Count }} Wörter" + +[lastModified] +other = "Letzte Aktualisierung" diff --git a/themes/hello-friend-ng/i18n/en.toml b/themes/hello-friend-ng/i18n/en.toml new file mode 100644 index 0000000..03c0444 --- /dev/null +++ b/themes/hello-friend-ng/i18n/en.toml @@ -0,0 +1,39 @@ +# Translations for English +# https://gohugo.io/content-management/multilingual/#translation-of-strings + +# Generic +# +[translations] +other = "Translations" + +[postAvailable] +other = "Also available in" + + +# 404.html +# +[archives] +other = "Archives" + +[home] +other = "Home" + +[notFound] +other = "Oops, page not found…" + + +# posts/single.html +# +[readingTime] +one = "One minute" +other = "{{ .Count }} minutes" + +[tableOfContents] +other = "Table of Contents" + +[wordCount] +one = "One Word" +other = "{{ .Count }} Words" + +[lastModified] +other = "Last updated" diff --git a/themes/hello-friend-ng/i18n/es.toml b/themes/hello-friend-ng/i18n/es.toml new file mode 100644 index 0000000..1dce9bb --- /dev/null +++ b/themes/hello-friend-ng/i18n/es.toml @@ -0,0 +1,39 @@ +# Translations for Spanish +# https://gohugo.io/content-management/multilingual/#translation-of-strings + +# Generic +# +[translations] +other = "Traducciones" + +[postAvailable] +other = "También disponible en" + + +# 404.html +# +[archives] +other = "Archivo" + +[home] +other = "Home" + +[notFound] +other = "Oops, página no encontrada…" + + +# posts/single.html +# +[readingTime] +one = "Un minuto" +other = "{{ .Count }} minutos" + +[tableOfContents] +other = "Tabla de Contenido" + +[wordCount] +one = "Una Palabra" +other = "{{ .Count }} Palabras" + +[lastModified] +other = "Ultima actualización" diff --git a/themes/hello-friend-ng/i18n/fr.toml b/themes/hello-friend-ng/i18n/fr.toml new file mode 100644 index 0000000..1ba6fe9 --- /dev/null +++ b/themes/hello-friend-ng/i18n/fr.toml @@ -0,0 +1,39 @@ +# Translations for French +# https://gohugo.io/content-management/multilingual/#translation-of-strings + +# Generic +# +[translations] +other = "Traductions" + +[postAvailable] +other = "Aussi disponible en" + + +# 404.html +# +[archives] +other = "Les archives" + +[home] +other = "Accueil" + +[notFound] +other = "Oups, page non trouvée …" + + +# posts/single.html +# +[readingTime] +one = "Une minute" +other = "{{ .Count }} minutes" + +[tableOfContents] +other = "Table des matières" + +[wordCount] +one = "Un Mot" +other = "{{ .Count }} Mots" + +[lastModified] +other = "Mise à jour" diff --git a/themes/hello-friend-ng/i18n/gl.toml b/themes/hello-friend-ng/i18n/gl.toml new file mode 100644 index 0000000..21e0e89 --- /dev/null +++ b/themes/hello-friend-ng/i18n/gl.toml @@ -0,0 +1,36 @@ +# Translations for Galician +# https://gohugo.io/content-management/multilingual/#translation-of-strings + +# Generic +# +[translations] +other = "Traducións" + +[postAvailable] +other = "Tamén dispoñible en" + + +# 404.html +# +[archives] +other = "Arquivos" + +[home] +other = "Inicio" + +[notFound] +other = "Vaia, non se atopou a páxina..." + + +# posts/single.html +# +[readingTime] +one = "Un minuto" +other = "{{ .Count }} minutos" + +[tableOfContents] +other = "Táboa de contidos" + +[wordCount] +one = "Unha Palabra" +other = "{{ .Count }} Palabras" diff --git a/themes/hello-friend-ng/i18n/hi.toml b/themes/hello-friend-ng/i18n/hi.toml new file mode 100644 index 0000000..6486c73 --- /dev/null +++ b/themes/hello-friend-ng/i18n/hi.toml @@ -0,0 +1,39 @@ +# Translations for Hindi +# https://gohugo.io/content-management/multilingual/#translation-of-strings + +# Generic +# +[translations] +other = "अनुवाद" + +[postAvailable] +other = "पढ़ें इस भाषा में" + + +# 404.html +# +[archives] +other = "पुरालेख" + +[home] +other = "घर" + +[notFound] +other = "क्षमा करें ! पेज़ नहीं मिला…" + + +# posts/single.html +# +[readingTime] +one = "एक मिनट" +other = "{{ .Count }} मिनट" + +[tableOfContents] +other = "अनुक्रमणिका" + +[wordCount] +one = "एक शब्द" +other = "{{ .Count }} शब्द" + +[lastModified] +other = "आखरी अपडेट" diff --git a/themes/hello-friend-ng/i18n/it.toml b/themes/hello-friend-ng/i18n/it.toml new file mode 100644 index 0000000..f78a5a0 --- /dev/null +++ b/themes/hello-friend-ng/i18n/it.toml @@ -0,0 +1,39 @@ +# Translations for English +# https://gohugo.io/content-management/multilingual/#translation-of-strings + +# Generic +# +[translations] +other = "Traduzioni" + +[postAvailable] +other = "Disponibile anche in" + + +# 404.html +# +[archives] +other = "Archivi" + +[home] +other = "Home" + +[notFound] +other = "Oops, pagina non trovata…" + + +# posts/single.html +# +[readingTime] +one = "Un minuto" +other = "{{ .Count }} minuti" + +[tableOfContents] +other = "Contenuti" + +[wordCount] +one = "Una parola" +other = "{{ .Count }} parole" + +[lastModified] +other = "Ultimo aggiornamento" diff --git a/themes/hello-friend-ng/i18n/ja.toml b/themes/hello-friend-ng/i18n/ja.toml new file mode 100644 index 0000000..7350c23 --- /dev/null +++ b/themes/hello-friend-ng/i18n/ja.toml @@ -0,0 +1,39 @@ +# Translations for Japanese +# https://gohugo.io/content-management/multilingual/#translation-of-strings + +# Generic +# +[translations] +other = "翻訳" + +[postAvailable] +other = "他の言語" + + +# 404.html +# +[archives] +other = "アーカイブ" + +[home] +other = "ホームページ" + +[notFound] +other = "あっ、ページが見つかりません……" + +# Please add hasCJKLanguage = true under [languages.ja] for the below to behave correctly +# posts/single.html +# +[readingTime] +one = "一分" +other = "{{ .Count }}分" + +[tableOfContents] +other = "目次" + +[wordCount] +one = "一文字" +other = "{{ .Count }}文字" + +[lastModified] +other = "最終更新" diff --git a/themes/hello-friend-ng/i18n/lmo.toml b/themes/hello-friend-ng/i18n/lmo.toml new file mode 100644 index 0000000..7616dda --- /dev/null +++ b/themes/hello-friend-ng/i18n/lmo.toml @@ -0,0 +1,39 @@ +# Translations for English +# https://gohugo.io/content-management/multilingual/#translation-of-strings + +# Generic +# +[translations] +other = "Traduzion" + +[postAvailable] +other = "Disponibel anca in" + + +# 404.html +# +[archives] +other = "Archivi" + +[home] +other = "Home" + +[notFound] +other = "Oops, pagina minga trovada…" + + +# posts/single.html +# +[readingTime] +one = "On megnuu" +other = "{{ .Count }} megnuu" + +[tableOfContents] +other = "Contegnuu" + +[wordCount] +one = "Ona parolla" +other = "{{ .Count }} paroll" + +[lastModified] +other = "Last update" diff --git a/themes/hello-friend-ng/i18n/ml.toml b/themes/hello-friend-ng/i18n/ml.toml new file mode 100644 index 0000000..a6aa087 --- /dev/null +++ b/themes/hello-friend-ng/i18n/ml.toml @@ -0,0 +1,39 @@ +# Translations for മലയാളം [Malayalam] +# https://gohugo.io/content-management/multilingual/#translation-of-strings + +# Generic +# +[translations] +other = "വിവർത്തനങ്ങൾ" + +[postAvailable] +other = "ഈ പോസ്റ്റ് ലഭ്യമായ മറ്റ് ഭാഷകൾ:" + + +# 404.html +# +[archives] +other = "ശേഖരം" + +[home] +other = "പ്രധാന താൾ" + +[notFound] +other = "ക്ഷമിക്കണം. താൾ ലഭ്യമല്ല. ദേയവയി വിലാസം പരിശോധിക്കുക അല്ലെങ്കിൽ അൽപ സമയത്തിനു ശേഷം വീണ്ടും പരിശ്രമിക്കുക." + + +# posts/single.html +# +[readingTime] +one = "ഒരു മിനിറ്റ്" +other = "{{ .Count }} മിനിറ്റുകൾ" + +[tableOfContents] +other = "ഉള്ളടക്ക പട്ടിക" + +[wordCount] +one = "ഒരു വാക്ക്" +other = "{{ .Count }} വാക്കുകൾ" + +[lastModified] +other = "അവസാനമായി പുതുക്കിയത്" diff --git a/themes/hello-friend-ng/i18n/pt-br.toml b/themes/hello-friend-ng/i18n/pt-br.toml new file mode 100644 index 0000000..b53cbcc --- /dev/null +++ b/themes/hello-friend-ng/i18n/pt-br.toml @@ -0,0 +1,39 @@ +# Translations for Portuguese +# https://gohugo.io/content-management/multilingual/#translation-of-strings + +# Generic +# +[translations] +other = "Traduções" + +[postAvailable] +other = "Também disponível em" + + +# 404.html +# +[archives] +other = "Arquivo" + +[home] +other = "Início" + +[notFound] +other = "Oops, página não encontrada…" + + +# posts/single.html +# +[readingTime] +one = "Um minuto" +other = "{{ .Count }} minutos" + +[tableOfContents] +other = "Índice" + +[wordCount] +one = "Uma Palavra" +other = "{{ .Count }} Palavras" + +[lastModified] +other = "Última actualização" diff --git a/themes/hello-friend-ng/i18n/ro.toml b/themes/hello-friend-ng/i18n/ro.toml new file mode 100644 index 0000000..af97a55 --- /dev/null +++ b/themes/hello-friend-ng/i18n/ro.toml @@ -0,0 +1,39 @@ +# Translations for Romanian +# https://gohugo.io/content-management/multilingual/#translation-of-strings + +# Generic +# +[translations] +other = "Traduceri" + +[postAvailable] +other = "Disponibil și în" + + +# 404.html +# +[archives] +other = "Arhive" + +[home] +other = "Acasă" + +[notFound] +other = "Ups, pagina nu a fost găsită…" + + +# posts/single.html +# +[readingTime] +one = "Un minut" +other = "{{ .Count }} de minute" + +[tableOfContents] +other = "Cuprins" + +[wordCount] +one = "Un cuvânt" +other = "{{ .Count }} de cuvinte" + +[lastModified] +other = "Ultima modificare" diff --git a/themes/hello-friend-ng/i18n/ru.toml b/themes/hello-friend-ng/i18n/ru.toml new file mode 100644 index 0000000..2f16ec4 --- /dev/null +++ b/themes/hello-friend-ng/i18n/ru.toml @@ -0,0 +1,43 @@ +# Translations for Russian +# https://gohugo.io/content-management/multilingual/#translation-of-strings + +# Generic +# +[translations] +other = "Переводы" + +[postAvailable] +other = "Доступно на " + + +# 404.html +# +[archives] +other = "Архивы" + +[home] +other = "Главная" + +[notFound] +other = "Упс, страница не найдена…" + + +# posts/single.html +# +[readingTime] +one = "{{ .Count }} минута" +few = "{{ .Count }} минуты" +many = "{{ .Count }} минут" +other = "{{ .Count }} минут" + +[tableOfContents] +other = "Содержимое" + +[wordCount] +one = "{{ .Count }} слово" +few = "{{ .Count }} слова" +many = "{{ .Count }} слов" +other = "{{ .Count }} слов" + +[lastModified] +other = "Последнее обновление" diff --git a/themes/hello-friend-ng/i18n/tr.toml b/themes/hello-friend-ng/i18n/tr.toml new file mode 100644 index 0000000..df7af32 --- /dev/null +++ b/themes/hello-friend-ng/i18n/tr.toml @@ -0,0 +1,39 @@ +# Translations for English +# https://gohugo.io/content-management/multilingual/#translation-of-strings + +# Generic +# +[translations] +other = "Çeviriler" + +[postAvailable] +other = "Ayrıca" + + +# 404.html +# +[archives] +other = "Arşiv" + +[home] +other = "Ana Sayfa" + +[notFound] +other = "Sayfa bulunamadı…" + + +# posts/single.html +# +[readingTime] +one = "Bir dakika" +other = "{{ .Count }} dakika" + +[tableOfContents] +other = "İçindekiler" + +[wordCount] +one = "One Kelime" +other = "{{ .Count }} Kelime" + +[lastModified] +other = "Son güncelleme" diff --git a/themes/hello-friend-ng/i18n/uk.toml b/themes/hello-friend-ng/i18n/uk.toml new file mode 100644 index 0000000..890a618 --- /dev/null +++ b/themes/hello-friend-ng/i18n/uk.toml @@ -0,0 +1,43 @@ +# Translations for Ukrainian +# https://gohugo.io/content-management/multilingual/#translation-of-strings + +# Generic +# +[translations] +other = "Переклади" + +[postAvailable] +other = "Доступне на " + + +# 404.html +# +[archives] +other = "Архіви" + +[home] +other = "Головна" + +[notFound] +other = "Упс, сторінка не знайдена…" + + +# posts/single.html +# +[readingTime] +one = "{{ .Count }} хвилина" +few = "{{ .Count }} хвилини" +many = "{{ .Count }} хвилин" +other = "{{ .Count }} хвилин" + +[tableOfContents] +other = "Вміст" + +[wordCount] +one = "{{ .Count }} слово" +few = "{{ .Count }} слова" +many = "{{ .Count }} слів" +other = "{{ .Count }} слів" + +[lastModified] +other = "Останнє оновлення" diff --git a/themes/hello-friend-ng/i18n/zh-cn.toml b/themes/hello-friend-ng/i18n/zh-cn.toml new file mode 100644 index 0000000..7ed72a0 --- /dev/null +++ b/themes/hello-friend-ng/i18n/zh-cn.toml @@ -0,0 +1,39 @@ +# Translations for Chinese (China) +# https://gohugo.io/content-management/multilingual/#translation-of-strings + +# Generic +# +[translations] +other = "译文" + +[postAvailable] +other = "其他语言" + + +# 404.html +# +[archives] +other = "档案" + +[home] +other = "主页" + +[notFound] +other = "噢,找不到页面……" + +# Please add hasCJKLanguage = true under [languages.zh-cn] for the below to behave correctly +# posts/single.html +# +[readingTime] +one = "一分钟" +other = "{{ .Count }}分钟" + +[tableOfContents] +other = "目录" + +[wordCount] +one = "一字" +other = "{{ .Count }}字" + +[lastModified] +other = "最后修改" diff --git a/themes/hello-friend-ng/i18n/zh-hk.toml b/themes/hello-friend-ng/i18n/zh-hk.toml new file mode 100644 index 0000000..4f52ffc --- /dev/null +++ b/themes/hello-friend-ng/i18n/zh-hk.toml @@ -0,0 +1,39 @@ +# Translations for Chinese (Hong Kong) [Cantonese] +# https://gohugo.io/content-management/multilingual/#translation-of-strings + +# Generic +# +[translations] +other = "譯文" + +[postAvailable] +other = "其他語言" + + +# 404.html +# +[archives] +other = "貼文" + +[home] +other = "主頁" + +[notFound] +other = "哎呀,揾唔到添……" + +# Please add hasCJKLanguage = true under [languages.zh-hk] for the below to behave correctly +# posts/single.html +# +[readingTime] +one = "一分鐘" +other = "{{ .Count }}分鐘" + +[tableOfContents] +other = "目錄" + +[wordCount] +one = "一粒字" +other = "{{ .Count }}字" + +[lastModified] +other = "最後修改" diff --git a/themes/hello-friend-ng/i18n/zh-tw.toml b/themes/hello-friend-ng/i18n/zh-tw.toml new file mode 100644 index 0000000..4a83bac --- /dev/null +++ b/themes/hello-friend-ng/i18n/zh-tw.toml @@ -0,0 +1,39 @@ +# Translations for Chinese (Taiwan) +# https://gohugo.io/content-management/multilingual/#translation-of-strings + +# Generic +# +[translations] +other = "譯文" + +[postAvailable] +other = "其他語言" + + +# 404.html +# +[archives] +other = "檔案" + +[home] +other = "主頁" + +[notFound] +other = "噢,找不到頁面……" + +# Please add hasCJKLanguage = true under [languages.zh-tw] for the below to behave correctly +# posts/single.html +# +[readingTime] +one = "一分鐘" +other = "{{ .Count }}分鐘" + +[tableOfContents] +other = "目錄" + +[wordCount] +one = "一字" +other = "{{ .Count }}字" + +[lastModified] +other = "最後修改" diff --git a/themes/hello-friend-ng/images/screenshot.png b/themes/hello-friend-ng/images/screenshot.png new file mode 100644 index 0000000..ba5e586 Binary files /dev/null and b/themes/hello-friend-ng/images/screenshot.png differ diff --git a/themes/hello-friend-ng/images/tn.png b/themes/hello-friend-ng/images/tn.png new file mode 100644 index 0000000..287749c Binary files /dev/null and b/themes/hello-friend-ng/images/tn.png differ diff --git a/themes/hello-friend-ng/layouts/404.html b/themes/hello-friend-ng/layouts/404.html new file mode 100644 index 0000000..7c89f3a --- /dev/null +++ b/themes/hello-friend-ng/layouts/404.html @@ -0,0 +1,21 @@ +{{ define "main" }} +
+

+ +

+ +
+{{ end }} diff --git a/themes/hello-friend-ng/layouts/_default/baseof.html b/themes/hello-friend-ng/layouts/_default/baseof.html new file mode 100644 index 0000000..2c80de9 --- /dev/null +++ b/themes/hello-friend-ng/layouts/_default/baseof.html @@ -0,0 +1,25 @@ + + + + {{ partial "head.html" . }} + + + {{ block "body" . }} + + {{ end }} + +
+ {{ partial "header.html" . }} + +
+ {{ block "main" . }}{{ end }} +
+ + {{ block "footer" . }} + {{ partial "footer.html" . }} + {{ end }} +
+ + {{ partial "javascript.html" . }} + + diff --git a/themes/hello-friend-ng/layouts/_default/list.html b/themes/hello-friend-ng/layouts/_default/list.html new file mode 100644 index 0000000..b440287 --- /dev/null +++ b/themes/hello-friend-ng/layouts/_default/list.html @@ -0,0 +1,35 @@ +{{ define "main" }} + {{ $paginator := .Paginate .Data.Pages }} + +
+

{{ .Title }}

+ + {{ if .Content }} +
{{ .Content }}
+ {{ end }} + + {{ range $paginator.Pages.GroupByDate "2006" }} + + {{ end }} + {{ partial "pagination-list.html" . }} +
+{{ end }} diff --git a/themes/hello-friend-ng/layouts/_default/single.html b/themes/hello-friend-ng/layouts/_default/single.html new file mode 100644 index 0000000..0a79c50 --- /dev/null +++ b/themes/hello-friend-ng/layouts/_default/single.html @@ -0,0 +1,52 @@ +{{ define "main" }} +
+ + + +
+

{{ .Title | markdownify }}

+ + {{ if .Params.Cover }} +
+ {{ .Title }} + + {{ if .Params.CoverCaption }} +
{{ .Params.CoverCaption | markdownify }}
+ {{ end }} +
+ {{ end }} + + {{ if .Params.toc }} +
+ +
+ {{ end }} + +
+ {{ .Content }} +
+
+ +
+ + +
+{{ end }} diff --git a/themes/hello-friend-ng/layouts/index.html b/themes/hello-friend-ng/layouts/index.html new file mode 100644 index 0000000..0c2714c --- /dev/null +++ b/themes/hello-friend-ng/layouts/index.html @@ -0,0 +1,31 @@ +{{ define "body" }} + +{{ end }} + +{{ define "main" }} +
+
+ {{ if .Site.Params.Portrait.Path }} + {{ .Site.Params.Portrait.Alt }} + {{ end }} + +
+
+

Team Ortix

+

Blog

+ + {{- with .Site.Params.social }} +
+ {{ partial "social-icons.html" . }} +
+ {{- end }} +
+ + +
+
+
+{{ end }} diff --git a/themes/hello-friend-ng/layouts/partials/breadcrumb.html b/themes/hello-friend-ng/layouts/partials/breadcrumb.html new file mode 100644 index 0000000..15950a3 --- /dev/null +++ b/themes/hello-friend-ng/layouts/partials/breadcrumb.html @@ -0,0 +1,19 @@ +{{ template "breadcrumbnav" (dict "p1" . "p2" .) }} + +{{ define "breadcrumbnav" -}} +{{ if .p1.Parent -}} +{{ template "breadcrumbnav" (dict "p1" .p1.Parent "p2" .p2 ) }} +{{- else if not .p1.IsHome -}} +{{ template "breadcrumbnav" (dict "p1" .p1.Site.Home "p2" .p2 ) }} +{{- end -}} + +{{- if .p1.Params.tinyname -}} +/{{ .p1.Params.tinyname }} +{{- else if .p1.IsHome -}} +/home +{{- else -}} +/{{- lower (delimit (split .p1.Title " ") "_") -}} +{{- end }} + +{{- end }} + diff --git a/themes/hello-friend-ng/layouts/partials/categories.html b/themes/hello-friend-ng/layouts/partials/categories.html new file mode 100644 index 0000000..e3b5b16 --- /dev/null +++ b/themes/hello-friend-ng/layouts/partials/categories.html @@ -0,0 +1,9 @@ +{{ with .Params.categories }} +

+ + + {{ range . -}} + {{.}} + {{ end }} +

+{{ end }} \ No newline at end of file diff --git a/themes/hello-friend-ng/layouts/partials/favicons.html b/themes/hello-friend-ng/layouts/partials/favicons.html new file mode 100644 index 0000000..36e2eac --- /dev/null +++ b/themes/hello-friend-ng/layouts/partials/favicons.html @@ -0,0 +1,10 @@ +{{- with .Site.Params.favicon.color }} + + + + + + + + +{{ end }} diff --git a/themes/hello-friend-ng/layouts/partials/footer.html b/themes/hello-friend-ng/layouts/partials/footer.html new file mode 100644 index 0000000..af30aa5 --- /dev/null +++ b/themes/hello-friend-ng/layouts/partials/footer.html @@ -0,0 +1,20 @@ +
+ {{if or (.Site.Params.footer.trademark) (.Site.Params.footer.author) (.Site.Params.footer.copyright) (.Site.Params.footer.rss) (.Site.Params.footer.topText) }} + + {{ end }} + {{with .Site.Params.footer.bottomText}} + + {{ end }} +
diff --git a/themes/hello-friend-ng/layouts/partials/head.html b/themes/hello-friend-ng/layouts/partials/head.html new file mode 100644 index 0000000..8f59f4f --- /dev/null +++ b/themes/hello-friend-ng/layouts/partials/head.html @@ -0,0 +1,73 @@ + + + + + + + + + + +{{ block "title" . }} + + {{- if .IsHome }} + {{ $.Site.Title }} {{ with $.Site.Params.Subtitle }} — {{ . }} {{ end }} + {{- else -}} + {{ .Title }} | Team Ortix + {{- end -}} + +{{ end }} + + + + +{{ $options := (dict "targetPath" "main.css" "outputStyle" "compressed" "enableSourceMap" true) }} +{{ $style := resources.Get "scss/main.scss" | resources.ToCSS $options | resources.Fingerprint }} + + +{{ range $val := $.Site.Params.customCSS }} + {{ if gt (len $val) 0 }} + + {{ end }} +{{ end }} + + +{{- partial "favicons.html" . }} + +{{ template "_internal/schema.html" . }} +{{ template "_internal/twitter_cards.html" . }} +{{ template "_internal/google_news.html" . }} + +{{ if isset .Site.Taxonomies "series" }} + {{ template "_internal/opengraph.html" . }} +{{ end }} + +{{ range .Params.categories }} + +{{ end }} + +{{ if isset .Params "date" }} + +{{ end }} + + +{{ with .OutputFormats.Get "rss" -}} + {{ printf `` .Rel .MediaType.Type .Permalink $.Site.Title | safeHTML }} +{{ end -}} + + +{{ if .OutputFormats.Get "json" }} + +{{ end }} + + +{{- if templates.Exists "partials/extra-head.html" -}} + {{ partial "extra-head.html" . }} +{{- end }} + + +{{- if .Site.GoogleAnalytics }} + {{ template "_internal/google_analytics.html" . }} +{{- end}} diff --git a/themes/hello-friend-ng/layouts/partials/header.html b/themes/hello-friend-ng/layouts/partials/header.html new file mode 100644 index 0000000..46651d4 --- /dev/null +++ b/themes/hello-friend-ng/layouts/partials/header.html @@ -0,0 +1,21 @@ +
+ + {{ partial "logo.html" . }} + + + {{ if len .Site.Menus }} + {{ partial "menu.html" . }} + + + + + + + {{ end }} + + {{- if .Site.Params.EnableThemeToggle }} + {{ partial "theme-toggle-icon.html" . }} + {{- end}} + + +
diff --git a/themes/hello-friend-ng/layouts/partials/javascript.html b/themes/hello-friend-ng/layouts/partials/javascript.html new file mode 100644 index 0000000..7c92d47 --- /dev/null +++ b/themes/hello-friend-ng/layouts/partials/javascript.html @@ -0,0 +1,12 @@ +{{ $main := resources.Get "js/main.js" }} +{{ $menu := resources.Get "js/menu.js" }} +{{ $hljs := resources.Get "js/highlight.min.js" }} +{{ $secureJS := slice $main $menu $hljs | resources.Concat "bundle.js" | resources.Minify | resources.Fingerprint "sha512" }} + + + +{{ range $val := $.Site.Params.customJS }} + {{ if gt (len $val) 0 }} + + {{ end }} +{{ end }} diff --git a/themes/hello-friend-ng/layouts/partials/logo.html b/themes/hello-friend-ng/layouts/partials/logo.html new file mode 100644 index 0000000..9e99f36 --- /dev/null +++ b/themes/hello-friend-ng/layouts/partials/logo.html @@ -0,0 +1,14 @@ + + + diff --git a/themes/hello-friend-ng/layouts/partials/menu.html b/themes/hello-friend-ng/layouts/partials/menu.html new file mode 100644 index 0000000..e958fab --- /dev/null +++ b/themes/hello-friend-ng/layouts/partials/menu.html @@ -0,0 +1,8 @@ + diff --git a/themes/hello-friend-ng/layouts/partials/pagination-list.html b/themes/hello-friend-ng/layouts/partials/pagination-list.html new file mode 100644 index 0000000..bc4885e --- /dev/null +++ b/themes/hello-friend-ng/layouts/partials/pagination-list.html @@ -0,0 +1,20 @@ + diff --git a/themes/hello-friend-ng/layouts/partials/pagination-single.html b/themes/hello-friend-ng/layouts/partials/pagination-single.html new file mode 100644 index 0000000..6c06e88 --- /dev/null +++ b/themes/hello-friend-ng/layouts/partials/pagination-single.html @@ -0,0 +1,28 @@ +{{ if and (not $.Site.Params.DisableReadOtherPosts) (or .NextInSection .PrevInSection) }} + +{{ end }} \ No newline at end of file diff --git a/themes/hello-friend-ng/layouts/partials/sharing-buttons.html b/themes/hello-friend-ng/layouts/partials/sharing-buttons.html new file mode 100644 index 0000000..86dc1c6 --- /dev/null +++ b/themes/hello-friend-ng/layouts/partials/sharing-buttons.html @@ -0,0 +1,89 @@ + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+
diff --git a/themes/hello-friend-ng/layouts/partials/social-icons.html b/themes/hello-friend-ng/layouts/partials/social-icons.html new file mode 100644 index 0000000..09ca681 --- /dev/null +++ b/themes/hello-friend-ng/layouts/partials/social-icons.html @@ -0,0 +1,3 @@ +{{ range . -}} +   {{ partial "svg.html" . }}   +{{- end -}} diff --git a/themes/hello-friend-ng/layouts/partials/svg.html b/themes/hello-friend-ng/layouts/partials/svg.html new file mode 100644 index 0000000..cf7f796 --- /dev/null +++ b/themes/hello-friend-ng/layouts/partials/svg.html @@ -0,0 +1,150 @@ +{{- if (eq .name "amazon") -}} + +{{- else if (eq .name "anilist") -}} + +{{- else if (eq .name "box") -}} + +{{- else if (eq .name "behence") -}} + +{{- else if (eq .name "bitbucket") -}} + +{{- else if (eq .name "case") -}} + +{{- else if (eq .name "codesandbox") -}} + +{{- else if (eq .name "codechef") -}} + +{{- else if (eq .name "codepen") -}} + +{{- else if (eq .name "dev") -}} + +{{- else if (eq .name "deviantart") -}} + +{{- else if (eq .name "discogs") -}} + +{{- else if (eq .name "discord") -}} + +{{- else if (eq .name "dribbble") -}} + +{{- else if (eq .name "docker") -}} + +{{- else if (eq .name "email") -}} + +{{- else if (eq .name "facebook") -}} + +{{- else if (eq .name "fitbit") -}} + +{{- else if (eq .name "git") -}} + +{{- else if (eq .name "gitea") -}} + +{{- else if (eq .name "gitbook") -}} + +{{- else if (eq .name "github") -}} + +{{- else if (eq .name "gitlab") -}} + +{{- else if (eq .name "gitter") -}} + +{{- else if (eq .name "goodreads") -}} + +{{- else if (eq .name "googleplay") -}} + +{{- else if (eq .name "googlescholar") -}} + +{{- else if (eq .name "gpg") -}} + +{{- else if (eq .name "hackerone") -}} + +{{- else if (eq .name "hackerrank") -}} + +{{- else if (eq .name "hackthebox") -}} + +{{- else if (eq .name "instagram") -}} + +{{- else if (eq .name "kaggle") -}} + +{{- else if (eq .name "keybase") -}} + +{{- else if (eq .name "lastfm") -}} + +{{- else if (eq .name "leetcode") -}} + +{{- else if (eq .name "letterboxd") -}} + +{{- else if (eq .name "librepay") -}} + +{{- else if (eq .name "lichess") -}} + +{{- else if (eq .name "linkedin") -}} + +{{- else if (eq .name "mastodon") -}} + +{{- else if (eq .name "matrix") -}} + +{{- else if (eq .name "medium") -}} + +{{- else if (eq .name "mixcloud") -}} + +{{- else if (eq .name "npm") -}} + +{{- else if (eq .name "orcid") -}} + +{{- else if (eq .name "peertube") }} + +{{- else if (eq .name "pinterest") }} + +{{- else if (eq .name "pixelfed") }} + +{{- else if (eq .name "podcasts-apple") -}} + +{{- else if (eq .name "podcasts-google") -}} + +{{- else if (eq .name "polywork") -}} + +{{- else if (eq .name "reddit") -}} + +{{- else if (eq .name "researchgate") -}} + +{{- else if (eq .name "signal") -}} + +{{- else if (eq .name "slack") -}} + +{{- else if (eq .name "soundcloud") -}} + +{{- else if (eq .name "spotify") -}} + +{{- else if (eq .name "stackoverflow") -}} + +{{- else if (eq .name "steam") -}} + +{{- else if (eq .name "strava") -}} + +{{- else if (eq .name "telegram") -}} + +{{- else if (eq .name "threema") -}} + +{{- else if (eq .name "tryhackme") -}} + +{{- else if (eq .name "tumblr") }} + +{{- else if (eq .name "twitch") -}} + +{{- else if (eq .name "twitter") -}} + +{{- else if (eq .name "unsplash") -}} + +{{- else if (eq .name "whatsapp") }} + +{{- else if (eq .name "xampp") -}} + +{{- else if (eq .name "xing") -}} + +{{- else if (eq .name "xmpp") -}} + +{{- else if (eq .name "ycombinator") -}} + +{{- else if (eq .name "youtube") -}} + +{{- end -}} + diff --git a/themes/hello-friend-ng/layouts/partials/tags.html b/themes/hello-friend-ng/layouts/partials/tags.html new file mode 100644 index 0000000..d9556db --- /dev/null +++ b/themes/hello-friend-ng/layouts/partials/tags.html @@ -0,0 +1,9 @@ +{{ with . }} +

+ + + {{ range . -}} + {{.}} + {{ end }} +

+{{ end }} \ No newline at end of file diff --git a/themes/hello-friend-ng/layouts/partials/theme-toggle-icon.html b/themes/hello-friend-ng/layouts/partials/theme-toggle-icon.html new file mode 100644 index 0000000..c61755b --- /dev/null +++ b/themes/hello-friend-ng/layouts/partials/theme-toggle-icon.html @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/themes/hello-friend-ng/layouts/posts/rss.xml b/themes/hello-friend-ng/layouts/posts/rss.xml new file mode 100644 index 0000000..6bc2684 --- /dev/null +++ b/themes/hello-friend-ng/layouts/posts/rss.xml @@ -0,0 +1,27 @@ + + + {{ if eq .Title .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}{{ end }} + {{ .Permalink }} + Recent content {{ if ne .Title .Site.Title }}{{ with .Title }}in {{.}} {{ end }}{{ end }}on {{ .Site.Title }} + Hugo -- gohugo.io{{ with .Site.LanguageCode }} + {{.}}{{end}}{{ with .Site.Author.email }} + {{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}{{end}}{{ with .Site.Author.email }} + {{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}{{end}}{{ with .Site.Copyright }} + {{.}}{{end}}{{ if not .Date.IsZero }} + {{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}{{ end }} + {{ with .OutputFormats.Get "RSS" -}} + {{ printf "" .Permalink .MediaType | safeHTML }} + {{ end -}} + {{ range .Pages }} + + {{ .Title }} + {{ .Permalink }} + {{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }} + {{ with .Site.Author.email }}{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}{{end}} + {{ .Permalink }} + {{ .Summary | html }} + {{ printf `` .Content | safeHTML }} + + {{ end }} + + diff --git a/themes/hello-friend-ng/layouts/posts/single.html b/themes/hello-friend-ng/layouts/posts/single.html new file mode 100644 index 0000000..0def3b0 --- /dev/null +++ b/themes/hello-friend-ng/layouts/posts/single.html @@ -0,0 +1,114 @@ +{{ define "main" }} +
+ + + +
+

+ {{ .Title | markdownify }} +

+ + {{ with .Params.Description }} +
{{ . }}
+ {{ end }} + + + {{ if .Params.Cover }} +
+ {{ .Title }} + + {{ if .Params.CoverCaption }} +
{{ .Params.CoverCaption | markdownify }}
+ {{ end }} +
+ {{ end }} + + {{- if and .Params.toc (gt .WordCount 400) }} +
+ +
+ {{- end }} + + {{ if .Params.Audio }} +
+ +
+ {{ end }} + +
+ {{ .Content }} +
+
+ +
+ +
+{{ end }} diff --git a/themes/hello-friend-ng/layouts/shortcodes/image.html b/themes/hello-friend-ng/layouts/shortcodes/image.html new file mode 100644 index 0000000..a282467 --- /dev/null +++ b/themes/hello-friend-ng/layouts/shortcodes/image.html @@ -0,0 +1,3 @@ +{{ if .Get "src" }} + {{ . | plainify }} +{{ end }} diff --git a/themes/hello-friend-ng/static/fonts/Inter-UI-Bold.woff b/themes/hello-friend-ng/static/fonts/Inter-UI-Bold.woff new file mode 100644 index 0000000..8fefb2d Binary files /dev/null and b/themes/hello-friend-ng/static/fonts/Inter-UI-Bold.woff differ diff --git a/themes/hello-friend-ng/static/fonts/Inter-UI-Bold.woff2 b/themes/hello-friend-ng/static/fonts/Inter-UI-Bold.woff2 new file mode 100644 index 0000000..522adb9 Binary files /dev/null and b/themes/hello-friend-ng/static/fonts/Inter-UI-Bold.woff2 differ diff --git a/themes/hello-friend-ng/static/fonts/Inter-UI-BoldItalic.woff b/themes/hello-friend-ng/static/fonts/Inter-UI-BoldItalic.woff new file mode 100644 index 0000000..8e0e289 Binary files /dev/null and b/themes/hello-friend-ng/static/fonts/Inter-UI-BoldItalic.woff differ diff --git a/themes/hello-friend-ng/static/fonts/Inter-UI-BoldItalic.woff2 b/themes/hello-friend-ng/static/fonts/Inter-UI-BoldItalic.woff2 new file mode 100644 index 0000000..66d8511 Binary files /dev/null and b/themes/hello-friend-ng/static/fonts/Inter-UI-BoldItalic.woff2 differ diff --git a/themes/hello-friend-ng/static/fonts/Inter-UI-Italic.woff b/themes/hello-friend-ng/static/fonts/Inter-UI-Italic.woff new file mode 100644 index 0000000..70c132b Binary files /dev/null and b/themes/hello-friend-ng/static/fonts/Inter-UI-Italic.woff differ diff --git a/themes/hello-friend-ng/static/fonts/Inter-UI-Italic.woff2 b/themes/hello-friend-ng/static/fonts/Inter-UI-Italic.woff2 new file mode 100644 index 0000000..6af8a7f Binary files /dev/null and b/themes/hello-friend-ng/static/fonts/Inter-UI-Italic.woff2 differ diff --git a/themes/hello-friend-ng/static/fonts/Inter-UI-Medium.woff b/themes/hello-friend-ng/static/fonts/Inter-UI-Medium.woff new file mode 100644 index 0000000..8aef504 Binary files /dev/null and b/themes/hello-friend-ng/static/fonts/Inter-UI-Medium.woff differ diff --git a/themes/hello-friend-ng/static/fonts/Inter-UI-Medium.woff2 b/themes/hello-friend-ng/static/fonts/Inter-UI-Medium.woff2 new file mode 100644 index 0000000..7bdc267 Binary files /dev/null and b/themes/hello-friend-ng/static/fonts/Inter-UI-Medium.woff2 differ diff --git a/themes/hello-friend-ng/static/fonts/Inter-UI-MediumItalic.woff b/themes/hello-friend-ng/static/fonts/Inter-UI-MediumItalic.woff new file mode 100644 index 0000000..58119ef Binary files /dev/null and b/themes/hello-friend-ng/static/fonts/Inter-UI-MediumItalic.woff differ diff --git a/themes/hello-friend-ng/static/fonts/Inter-UI-MediumItalic.woff2 b/themes/hello-friend-ng/static/fonts/Inter-UI-MediumItalic.woff2 new file mode 100644 index 0000000..4d4034b Binary files /dev/null and b/themes/hello-friend-ng/static/fonts/Inter-UI-MediumItalic.woff2 differ diff --git a/themes/hello-friend-ng/static/fonts/Inter-UI-Regular.woff b/themes/hello-friend-ng/static/fonts/Inter-UI-Regular.woff new file mode 100644 index 0000000..2ada3d0 Binary files /dev/null and b/themes/hello-friend-ng/static/fonts/Inter-UI-Regular.woff differ diff --git a/themes/hello-friend-ng/static/fonts/Inter-UI-Regular.woff2 b/themes/hello-friend-ng/static/fonts/Inter-UI-Regular.woff2 new file mode 100644 index 0000000..e29e9c9 Binary files /dev/null and b/themes/hello-friend-ng/static/fonts/Inter-UI-Regular.woff2 differ diff --git a/themes/hello-friend-ng/theme.toml b/themes/hello-friend-ng/theme.toml new file mode 100644 index 0000000..9d0a131 --- /dev/null +++ b/themes/hello-friend-ng/theme.toml @@ -0,0 +1,17 @@ +name = "hello-friend-ng" +license = "MIT" +licenselink = "https://github.com/rhazdon/hugo-theme-hello-friend-ng/blob/master/LICENSE.md" +description = "A simple theme for Hugo. That's it." +tags = ["blog", "clean", "customizable", "dark", "highlighting", "light", "minimal", "monochromatic", "multilingual", "personal", "responsive", "simple", "technical"] +features = ["blog", "shortcode", "syntax highlighting"] +min_version = 0.30 + +[author] + name = "Djordje Atlialp" + homepage = "https://atlialp.com" + twitter = "https://twitter.com/rhazdon" + +[original] + name = "hello-friend" + homepage = "https://github.com/panr/hugo-theme-hello-friend" + repo = "https://github.com/panr/hugo-theme-hello-friend"