Merge of Insiders features tied to 'Caribbean Red' funding goal

This commit is contained in:
squidfunk 2021-09-23 08:53:51 +02:00
parent 62742b4f0d
commit 377b4d648f
32 changed files with 228 additions and 198 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -39,7 +39,7 @@
{% endif %}
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="{{ 'assets/stylesheets/main.92558b1b.min.css' | url }}">
<link rel="stylesheet" href="{{ 'assets/stylesheets/main.8b42a75e.min.css' | url }}">
{% if config.theme.palette %}
{% set palette = config.theme.palette %}
<link rel="stylesheet" href="{{ 'assets/stylesheets/palette.3f5d1f46.min.css' | url }}">
@ -119,8 +119,10 @@
<div class="md-container" data-md-component="container">
{% block hero %}{% endblock %}
{% block tabs %}
{% if "navigation.tabs" in features %}
{% include "partials/tabs.html" %}
{% if not "navigation.tabs.sticky" in features %}
{% if "navigation.tabs" in features %}
{% include "partials/tabs.html" %}
{% endif %}
{% endif %}
{% endblock %}
<main class="md-main" data-md-component="main">
@ -196,7 +198,7 @@
"base": base_url,
"features": features,
"translations": {},
"search": "assets/javascripts/workers/search.94ec81fe.min.js" | url,
"search": "assets/javascripts/workers/search.f8263e09.min.js" | url,
"version": config.extra.version or None
} -%}
{%- set translations = app.translations -%}
@ -223,7 +225,7 @@
</script>
{% endblock %}
{% block scripts %}
<script src="{{ 'assets/javascripts/bundle.48dfec6c.min.js' | url }}"></script>
<script src="{{ 'assets/javascripts/bundle.4fc53ad4.min.js' | url }}"></script>
{% for path in config["extra_javascript"] %}
<script src="{{ path | url }}"></script>
{% endfor %}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -16,5 +16,5 @@
{% endblock %}
{% block scripts %}
{{ super() }}
<script src="{{ 'overrides/assets/javascripts/bundle.f9a9c765.min.js' | url }}"></script>
<script src="{{ 'overrides/assets/javascripts/bundle.5c8bd0f7.min.js' | url }}"></script>
{% endblock %}

View File

@ -47,10 +47,12 @@
{{ config.copyright }}
</div>
{% endif %}
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
{% if not config.extra.generator == false %}
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
{% endif %}
{{ extracopyright }}
</div>
{% include "partials/social.html" %}

View File

@ -1,7 +1,11 @@
{#-
This file was automatically generated - do not edit
-#}
<header class="md-header" data-md-component="header">
{% set class = "md-header" %}
{% if "navigation.tabs.sticky" in features %}
{% set class = class ~ " md-header--lifted" %}
{% endif %}
<header class="{{ class }}" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="{{ lang.t('header.title') }}">
<a href="{{ config.extra.homepage | d(nav.homepage.url, true) | url }}" title="{{ config.site_name | e }}" class="md-header__button md-logo" aria-label="{{ config.site_name }}" data-md-component="logo">
{% include "partials/logo.html" %}
@ -74,4 +78,9 @@
</div>
{% endif %}
</nav>
{% if "navigation.tabs.sticky" in features %}
{% if "navigation.tabs" in features %}
{% include "partials/tabs.html" %}
{% endif %}
{% endif %}
</header>

View File

@ -19,10 +19,29 @@
{% else %}
<input class="md-nav__toggle md-toggle" data-md-toggle="{{ path }}" type="checkbox" id="{{ path }}" {{ checked }}>
{% endif %}
<label class="md-nav__link" for="{{ path }}">
{{ nav_item.title }}
<span class="md-nav__icon md-icon"></span>
</label>
{% set indexes = [] %}
{% if "navigation.indexes" in features %}
{% for item in nav_item.children %}
{% if item.is_index and not index is defined %}
{% set _ = indexes.append(item) %}
{% endif %}
{% endfor %}
{% endif %}
{% if not indexes %}
<label class="md-nav__link" for="{{ path }}">
{{ nav_item.title }}
<span class="md-nav__icon md-icon"></span>
</label>
{% else %}
{% set index = indexes | first %}
{% set class = "md-nav__link--active" if index == page %}
<div class="md-nav__link md-nav__link--container {{ class }}">
<a href="{{ index.url | url }}">{{ nav_item.title }}</a>
<label for="{{ path }}">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
{% endif %}
<nav class="md-nav" aria-label="{{ nav_item.title }}" data-md-level="{{ level }}">
<label class="md-nav__title" for="{{ path }}">
<span class="md-nav__icon md-icon"></span>
@ -30,7 +49,10 @@
</label>
<ul class="md-nav__list" data-md-scrollfix>
{% for nav_item in nav_item.children %}
{{ render(nav_item, path ~ "_" ~ loop.index, level + 1) }}
{% if "navigation.indexes" in features and nav_item.is_index %}
{% else %}
{{ render(nav_item, path ~ "_" ~ loop.index, level + 1) }}
{% endif %}
{% endfor %}
</ul>
</nav>

View File

@ -212,7 +212,7 @@ nav:
- Meta tags: reference/meta-tags.md
- Variables: reference/variables.md
- Insiders:
- Sponsorship: insiders/index.md
- insiders/index.md
- Getting started:
- Installation: insiders/getting-started.md
- Changelog: insiders/changelog.md

View File

@ -33,8 +33,10 @@ export type Flag =
| "header.autohide" /* Hide header */
| "navigation.expand" /* Automatic expansion */
| "navigation.instant" /* Instant loading */
| "navigation.sections" /* Sections navigation */
| "navigation.indexes" /* Section pages */
| "navigation.sections" /* Section navigation */
| "navigation.tabs" /* Tabs navigation */
| "navigation.tabs.sticky" /* Tabs navigation (sticky) */
| "navigation.top" /* Back-to-top button */
| "search.highlight" /* Search highlighting */
| "search.share" /* Search sharing */

View File

@ -36,7 +36,7 @@
*/
export function getElement<T extends keyof HTMLElementTagNameMap>(
selector: T, node?: ParentNode
): HTMLElementTagNameMap[T]
): HTMLElementTagNameMap[T] | undefined
export function getElement<T extends HTMLElement>(
selector: string, node?: ParentNode
@ -74,6 +74,8 @@ export function getElementOrThrow<T extends HTMLElement>(
throw new ReferenceError(
`Missing element: expected "${selector}" to be present`
)
/* Return element */
return el
}
@ -114,21 +116,6 @@ export function getElements<T extends HTMLElement>(
/* ------------------------------------------------------------------------- */
/**
* Create an element
*
* @template T - Tag name type
*
* @param tagName - Tag name
*
* @returns Element
*/
export function createElement<T extends keyof HTMLElementTagNameMap>(
tagName: T
): HTMLElementTagNameMap[T] {
return document.createElement(tagName)
}
/**
* Replace an element with the given list of nodes
*

View File

@ -28,7 +28,8 @@ import {
startWith
} from "rxjs/operators"
import { createElement, getElement } from "~/browser"
import { getElement } from "~/browser"
import { h } from "~/utilities"
/* ----------------------------------------------------------------------------
* Functions
@ -54,8 +55,7 @@ export function getLocationHash(): string {
* @param hash - Location hash
*/
export function setLocationHash(hash: string): void {
const el = createElement("a")
el.href = hash
const el = h("a", { href: hash })
el.addEventListener("click", ev => ev.stopPropagation())
el.click()
}

View File

@ -27,7 +27,7 @@ import { getElementOrThrow, getElements } from "~/browser"
* ------------------------------------------------------------------------- */
/**
* Component
* Component type
*/
export type ComponentType =
| "announce" /* Announcement bar */
@ -52,7 +52,7 @@ export type ComponentType =
| "top" /* Back-to-top button */
/**
* A component
* Component
*
* @template T - Component type
* @template U - Reference type

View File

@ -22,8 +22,9 @@
import { Observable, of } from "rxjs"
import { createElement, replaceElement } from "~/browser"
import { replaceElement } from "~/browser"
import { renderTable } from "~/templates"
import { h } from "~/utilities"
import { Component } from "../../_"
@ -43,7 +44,7 @@ export interface DataTable {}
/**
* Sentinel for replacement
*/
const sentinel = createElement("table")
const sentinel = h("table")
/* ----------------------------------------------------------------------------
* Functions

View File

@ -213,7 +213,7 @@ export function mountSearch(
/* Search sharing */
...getComponentElements("search-share", el)
.map(child => mountSearchShare(child, { query$ })),
.map(child => mountSearchShare(child, { query$ })),
/* Search suggestions */
...getComponentElements("search-suggest", el)

View File

@ -20,7 +20,12 @@
* IN THE SOFTWARE.
*/
import { Observable, Subject, animationFrameScheduler } from "rxjs"
import {
Observable,
Subject,
animationFrameScheduler,
of
} from "rxjs"
import {
distinctUntilKeyChanged,
finalize,
@ -30,6 +35,7 @@ import {
tap
} from "rxjs/operators"
import { feature } from "~/_"
import { resetTabsState, setTabsState } from "~/actions"
import {
Viewport,
@ -134,7 +140,11 @@ export function mountTabs(
})
/* Create and return component */
return watchTabs(el, options)
return (
feature("navigation.tabs.sticky")
? of({ hidden: false })
: watchTabs(el, options)
)
.pipe(
tap(state => internal$.next(state)),
finalize(() => internal$.complete()),

View File

@ -45,11 +45,10 @@ import {
switchMap
} from "rxjs/operators"
import { configuration } from "~/_"
import { configuration, feature } from "~/_"
import {
Viewport,
ViewportOffset,
createElement,
getElement,
getElements,
replaceElement,
@ -60,6 +59,7 @@ import {
setViewportOffset
} from "~/browser"
import { getComponentElement } from "~/components"
import { h } from "~/utilities"
/* ----------------------------------------------------------------------------
* Types
@ -283,7 +283,10 @@ export function setupInstantLoading(
"[data-md-component=container]",
"[data-md-component=header-topic]",
"[data-md-component=logo], .md-logo", // compat
"[data-md-component=skip]"
"[data-md-component=skip]",
...feature("navigation.tabs.sticky")
? ["[data-md-component=tabs]"]
: []
]) {
const source = getElement(selector)
const target = getElement(selector, replacement)
@ -303,7 +306,7 @@ export function setupInstantLoading(
map(() => getComponentElement("container")),
switchMap(el => of(...getElements("script", el))),
concatMap(el => {
const script = createElement("script")
const script = h("script")
if (el.src) {
for (const name of el.getAttributeNames())
script.setAttribute(name, el.getAttribute(name)!)

View File

@ -39,7 +39,7 @@ export const enum SearchMessageType {
/* ------------------------------------------------------------------------- */
/**
* A message containing the data necessary to setup the search index
* Message containing the data necessary to setup the search index
*/
export interface SearchSetupMessage {
type: SearchMessageType.SETUP /* Message type */
@ -47,14 +47,14 @@ export interface SearchSetupMessage {
}
/**
* A message indicating the search index is ready
* Message indicating the search index is ready
*/
export interface SearchReadyMessage {
type: SearchMessageType.READY /* Message type */
}
/**
* A message containing a search query
* Message containing a search query
*/
export interface SearchQueryMessage {
type: SearchMessageType.QUERY /* Message type */
@ -62,7 +62,7 @@ export interface SearchQueryMessage {
}
/**
* A message containing results for a search query
* Message containing results for a search query
*/
export interface SearchResultMessage {
type: SearchMessageType.RESULT /* Message type */
@ -72,7 +72,7 @@ export interface SearchResultMessage {
/* ------------------------------------------------------------------------- */
/**
* A message exchanged with the search worker
* Message exchanged with the search worker
*/
export type SearchMessage =
| SearchSetupMessage

View File

@ -1,6 +1,7 @@
{
"rules": {
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-namespace": "off"
"@typescript-eslint/no-namespace": "off",
"jsdoc/require-jsdoc": "off"
}
}

View File

@ -77,15 +77,25 @@ function appendChild(el: HTMLElement, child: Child | Child[]): void {
/**
* JSX factory
*
* @template T - Element type
*
* @param tag - HTML tag
* @param attributes - HTML attributes
* @param children - Child elements
*
* @returns Element
*/
export function h(
tag: string, attributes: Attributes | null, ...children: Child[]
): HTMLElement {
export function h<T extends keyof HTMLElementTagNameMap>(
tag: T, attributes?: Attributes | null, ...children: Child[]
): HTMLElementTagNameMap[T]
export function h<T extends h.JSX.Element>(
tag: string, attributes?: Attributes | null, ...children: Child[]
): T
export function h<T extends h.JSX.Element>(
tag: string, attributes?: Attributes | null, ...children: Child[]
): T {
const el = document.createElement(tag)
/* Set attributes, if any */
@ -101,7 +111,7 @@ export function h(
appendChild(el, child)
/* Return element */
return el
return el as T
}
/* ----------------------------------------------------------------------------

View File

@ -72,6 +72,15 @@
// it properly, so we settle with a cross-browser anchor correction solution.
:target {
scroll-margin-top: px2rem(48px + 24px);
// [screen +]: Sticky navigation tabs
@include break-from-device(screen) {
// Adjust scroll offset for sticky navigation tabs
.md-header--lifted ~ .md-container & {
scroll-margin-top: px2rem(96px + 24px);
}
}
}
// Adjust scroll offset for headlines of level 1-3
@ -87,6 +96,21 @@
padding-top: px2rem(48px + 24px - 4px);
content: "";
}
// [screen +]: Sticky navigation tabs
@include break-from-device(screen) {
// Adjust scroll offset for sticky navigation tabs
.md-header--lifted ~ .md-container & {
scroll-margin-top: initial;
// Anchor correction hack
&::before {
margin-top: -1 * px2rem(96px + 24px - 4px);
padding-top: px2rem(96px + 24px - 4px);
}
}
}
}
// Adjust scroll offset for headlines of level 4
@ -100,6 +124,21 @@
padding-top: px2rem(48px + 24px - 3px);
content: "";
}
// [screen +]: Sticky navigation tabs
@include break-from-device(screen) {
// Adjust scroll offset for sticky navigation tabs
.md-header--lifted ~ .md-container & {
scroll-margin-top: initial;
// Anchor correction hack
&::before {
margin-top: -1 * px2rem(96px + 24px - 3px);
padding-top: px2rem(96px + 24px - 3px);
}
}
}
}
// Adjust scroll offset for headlines of level 5-6
@ -114,5 +153,20 @@
padding-top: px2rem(48px + 24px);
content: "";
}
// [screen +]: Sticky navigation tabs
@include break-from-device(screen) {
// Adjust scroll offset for sticky navigation tabs
.md-header--lifted ~ .md-container & {
scroll-margin-top: initial;
// Anchor correction hack
&::before {
margin-top: -1 * px2rem(96px + 24px);
padding-top: px2rem(96px + 24px);
}
}
}
}
}

View File

@ -26,7 +26,7 @@
<html lang="{{ lang.t('language') }}" class="no-js">
<head>
<!-- Metatags -->
<!-- Meta tags -->
{% block site_meta %}
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
@ -233,10 +233,12 @@
<!-- Hero teaser -->
{% block hero %}{% endblock %}
<!-- Navigation tabs -->
<!-- Navigation tabs (collapsing) -->
{% block tabs %}
{% if "navigation.tabs" in features %}
{% include "partials/tabs.html" %}
{% if not "navigation.tabs.sticky" in features %}
{% if "navigation.tabs" in features %}
{% include "partials/tabs.html" %}
{% endif %}
{% endif %}
{% endblock %}

View File

@ -27,7 +27,7 @@ import { getElementOrThrow, getElements } from "~/browser"
* ------------------------------------------------------------------------- */
/**
* Component
* Component type
*/
export type ComponentType =
| "iconsearch" /* Icon search */
@ -38,7 +38,7 @@ export type ComponentType =
| "sponsorship-total" /* Sponsorship total */
/**
* A component
* Component
*
* @template T - Component type
* @template U - Reference type

View File

@ -91,13 +91,15 @@
{{ config.copyright }}
</div>
{% endif %}
Made with
<a
href="https://squidfunk.github.io/mkdocs-material/"
target="_blank" rel="noopener"
>
Material for MkDocs
</a>
{% if not config.extra.generator == false %}
Made with
<a
href="https://squidfunk.github.io/mkdocs-material/"
target="_blank" rel="noopener"
>
Material for MkDocs
</a>
{% endif %}
{{ extracopyright }}
</div>

View File

@ -20,8 +20,14 @@
IN THE SOFTWARE.
-->
<!-- Determine class according to configuration -->
{% set class = "md-header" %}
{% if "navigation.tabs.sticky" in features %}
{% set class = class ~ " md-header--lifted" %}
{% endif %}
<!-- Header -->
<header class="md-header" data-md-component="header">
<header class="{{ class }}" data-md-component="header">
<nav
class="md-header__inner md-grid"
aria-label="{{ lang.t('header.title') }}"
@ -145,4 +151,11 @@
</div>
{% endif %}
</nav>
<!-- Navigation tabs (sticky) -->
{% if "navigation.tabs.sticky" in features %}
{% if "navigation.tabs" in features %}
{% include "partials/tabs.html" %}
{% endif %}
{% endif %}
</header>

View File

@ -63,11 +63,36 @@
/>
{% endif %}
<!-- Expand active pages -->
<label class="md-nav__link" for="{{ path }}">
{{ nav_item.title }}
<span class="md-nav__icon md-icon"></span>
</label>
<!-- Determine all nested items that are index pages -->
{% set indexes = [] %}
{% if "navigation.indexes" in features %}
{% for item in nav_item.children %}
{% if item.is_index and not index is defined %}
{% set _ = indexes.append(item) %}
{% endif %}
{% endfor %}
{% endif %}
<!-- Render toggle to expand nested items -->
{% if not indexes %}
<label class="md-nav__link" for="{{ path }}">
{{ nav_item.title }}
<span class="md-nav__icon md-icon"></span>
</label>
<!-- Render link to index page + toggle -->
{% else %}
{% set index = indexes | first %}
{% set class = "md-nav__link--active" if index == page %}
<div class="md-nav__link md-nav__link--container {{ class }}">
<a href="{{ index.url | url }}">{{ nav_item.title }}</a>
<label for="{{ path }}">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
{% endif %}
<!-- Render nested navigation -->
<nav
class="md-nav"
aria-label="{{ nav_item.title }}"
@ -81,7 +106,11 @@
<!-- Render nested item list -->
{% for nav_item in nav_item.children %}
{{ render(nav_item, path ~ "_" ~ loop.index, level + 1) }}
{% if "navigation.indexes" in features and nav_item.is_index %}
<!-- Render nothing -->
{% else %}
{{ render(nav_item, path ~ "_" ~ loop.index, level + 1) }}
{% endif %}
{% endfor %}
</ul>
</nav>

View File

@ -54,7 +54,7 @@ declare global {
/**
* Global function to prefix storage items
*/
function __prefix(key: string): string
function __prefix(key: string): string
/**
* Google Analytics