publish updates from main (#22709)
Automated pull request for publishing docs updates. --------- Co-authored-by: Kristiyan Velkov <40764277+kristiyan-velkov@users.noreply.github.com> Co-authored-by: Arthur <arthur.flageul@docker.com>
|
@ -179,7 +179,6 @@ hugo:
|
|||
- hugo_stats.json
|
||||
- i18n/**
|
||||
- layouts/**
|
||||
- postcss.config.js
|
||||
- static/**
|
||||
- tailwind.config.js
|
||||
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
@layer components {
|
||||
.prose {
|
||||
.highlight,
|
||||
:not(pre) > code {
|
||||
font-size: 0.875em;
|
||||
border: 1px solid;
|
||||
border-radius: theme("spacing.1");
|
||||
background: theme("colors.white");
|
||||
border-color: theme("colors.gray.light.300");
|
||||
.dark & {
|
||||
background: theme("colors.gray.dark.200");
|
||||
border-color: theme("colors.gray.dark.300");
|
||||
}
|
||||
}
|
||||
|
||||
:not(pre) > code {
|
||||
background: theme("colors.gray.light.200");
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
font-weight: 400;
|
||||
overflow-wrap: anywhere;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
table:not(.lntable) code {
|
||||
overflow-wrap: unset;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Indented code blocks */
|
||||
pre:not(.chroma) {
|
||||
@apply my-4 overflow-x-auto p-3;
|
||||
font-size: 0.875em;
|
||||
border: 1px solid;
|
||||
border-radius: theme("spacing.1");
|
||||
background: theme("colors.white");
|
||||
border-color: theme("colors.gray.light.300");
|
||||
.dark & {
|
||||
background: theme("colors.gray.dark.200");
|
||||
border-color: theme("colors.gray.dark.300");
|
||||
}
|
||||
}
|
||||
|
||||
.highlight {
|
||||
@apply my-4 overflow-x-auto p-3;
|
||||
|
||||
/* LineTableTD */
|
||||
.lntd {
|
||||
vertical-align: top;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-weight: 400;
|
||||
padding: 0 4px;
|
||||
&:first-child {
|
||||
width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* LineTableTD */
|
||||
.lntd {
|
||||
vertical-align: top;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
/* LineTable */
|
||||
.lntable {
|
||||
display: table;
|
||||
width: 100%;
|
||||
border-spacing: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
/* LineNumberColumnHighlight */
|
||||
.lntd:first-child .hl {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
@layer components {
|
||||
.card {
|
||||
@apply mt-2 mb-2 flex flex-col gap-2 rounded-sm border border-gray-200 p-3;
|
||||
@apply dark:border-gray-700 dark:bg-gray-900;
|
||||
@apply transition-shadow duration-200;
|
||||
&:hover,
|
||||
&:focus {
|
||||
@apply border-gray-300 dark:border-gray-600;
|
||||
}
|
||||
}
|
||||
.card-link:hover {
|
||||
@apply !no-underline;
|
||||
}
|
||||
.card-header {
|
||||
@apply mb-2 flex items-center gap-2;
|
||||
@apply text-gray-700 dark:text-gray-100;
|
||||
}
|
||||
.card-icon {
|
||||
@apply text-gray-700 dark:text-gray-100;
|
||||
}
|
||||
.card-img,
|
||||
.card-img svg {
|
||||
@apply m-0 flex max-h-5 min-h-5 max-w-5 min-w-5 items-center justify-center fill-current;
|
||||
}
|
||||
.card-title {
|
||||
@apply font-semibold;
|
||||
}
|
||||
.card-link {
|
||||
@apply block text-inherit no-underline hover:underline;
|
||||
}
|
||||
.card-description {
|
||||
@apply text-gray-600;
|
||||
@apply dark:text-gray-300;
|
||||
}
|
||||
|
||||
.admonition {
|
||||
@apply relative mb-4 flex w-full flex-col items-start gap-3 rounded-sm px-6 py-4;
|
||||
@apply bg-gray-50 dark:bg-gray-900;
|
||||
}
|
||||
.admonition-header {
|
||||
@apply flex flex-wrap items-center gap-2;
|
||||
}
|
||||
.admonition-title {
|
||||
@apply font-semibold;
|
||||
}
|
||||
.admonition-content {
|
||||
@apply w-full min-w-0 flex-1 flex-wrap overflow-x-auto break-words;
|
||||
color: var(--tw-prose-body);
|
||||
}
|
||||
.admonition-note {
|
||||
@apply border-blue-400 bg-blue-50 text-blue-900;
|
||||
@apply dark:border-blue-600 dark:bg-blue-950 dark:text-blue-100;
|
||||
}
|
||||
.admonition-tip {
|
||||
@apply border-green-400 bg-green-100 text-green-900;
|
||||
@apply dark:border-green-600 dark:bg-green-950 dark:text-green-100;
|
||||
}
|
||||
.admonition-warning {
|
||||
@apply border-yellow-400 bg-yellow-50 text-yellow-900;
|
||||
@apply dark:border-yellow-600 dark:bg-yellow-950 dark:text-yellow-100;
|
||||
}
|
||||
.admonition-danger {
|
||||
@apply border-red-400 bg-red-50 text-red-900;
|
||||
@apply dark:border-red-600 dark:bg-red-950 dark:text-red-100;
|
||||
}
|
||||
.admonition-important {
|
||||
@apply border-purple-400 bg-purple-50 text-purple-900;
|
||||
@apply dark:border-purple-600 dark:bg-purple-950 dark:text-purple-100;
|
||||
}
|
||||
.admonition-icon {
|
||||
@apply flex-shrink-0;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
min-width: 24px;
|
||||
min-height: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.download-links {
|
||||
@apply block;
|
||||
@apply text-gray-800;
|
||||
@apply dark:text-gray-200;
|
||||
}
|
||||
.download-links a {
|
||||
@apply link;
|
||||
}
|
||||
.download-links-subcontainer {
|
||||
@apply flex flex-wrap gap-2;
|
||||
}
|
||||
|
||||
.card-image {
|
||||
@apply h-12 w-12 overflow-hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.summary-bar {
|
||||
@apply my-1 mt-4 flex flex-col rounded-sm border-1 border-gray-100 bg-gray-50 p-4 dark:border-gray-800 dark:bg-gray-900;
|
||||
}
|
|
@ -1,89 +1,106 @@
|
|||
/* global styles */
|
||||
|
||||
@layer base {
|
||||
[x-cloak=""] {
|
||||
[x-cloak=""] {
|
||||
display: none !important;
|
||||
}
|
||||
/* alpine cloak for small screens only */
|
||||
[x-cloak="sm"] {
|
||||
@media (width <= 768px) {
|
||||
display: none !important;
|
||||
}
|
||||
/* alpine cloak for small screens only */
|
||||
[x-cloak="sm"] {
|
||||
@media (width <= 768px) {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
:root {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
:root {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
scrollbar-color: theme(colors.gray.light.400) theme(colors.black / 0.05);
|
||||
&.dark {
|
||||
scrollbar-color: theme(colors.gray.dark.800) theme(colors.white / 0.10);
|
||||
}
|
||||
}
|
||||
|
||||
mark {
|
||||
@apply bg-transparent font-bold text-blue-light dark:text-blue-dark;
|
||||
}
|
||||
|
||||
/* Hide the clear (X) button for search inputs */
|
||||
/* Chrome, Safari, Edge, and Opera */
|
||||
input[type="search"]::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
/* Firefox */
|
||||
input[type="search"]::-moz-search-cancel-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Internet Explorer and Edge (legacy) */
|
||||
input[type="search"]::-ms-clear {
|
||||
display: none;
|
||||
scrollbar-color: var(--color-gray-400) rgba(0, 0, 0, 0.05);
|
||||
&.dark {
|
||||
scrollbar-color: var(--color-gray-700) rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
/* utility classes */
|
||||
mark {
|
||||
@apply bg-transparent font-bold text-blue-500 dark:text-blue-800;
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.link {
|
||||
@apply text-blue-light underline underline-offset-2 dark:text-blue-dark;
|
||||
/* Hide the clear (X) button for search inputs */
|
||||
/* Chrome, Safari, Edge, and Opera */
|
||||
input[type="search"]::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
/* Firefox */
|
||||
input[type="search"]::-moz-search-cancel-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Internet Explorer and Edge (legacy) */
|
||||
input[type="search"]::-ms-clear {
|
||||
display: none;
|
||||
}
|
||||
.prose {
|
||||
code {
|
||||
@apply !bg-gray-100;
|
||||
}
|
||||
|
||||
.invertible {
|
||||
@apply dark:hue-rotate-180 dark:invert dark:filter;
|
||||
}
|
||||
|
||||
.bg-pattern-blue {
|
||||
background-color: theme(colors.white / 50%);
|
||||
background-image: url('/assets/images/bg-pattern-blue.webp');
|
||||
background-blend-mode: overlay;
|
||||
background-size: cover;
|
||||
background-repeat: none;
|
||||
& .highlight,
|
||||
& :not(pre) > code {
|
||||
.dark & {
|
||||
background-color: theme(colors.black / 70%);
|
||||
}
|
||||
}
|
||||
|
||||
.bg-pattern-purple {
|
||||
background-color: theme(colors.white / 50%);
|
||||
background-image: url('/assets/images/bg-pattern-purple.webp');
|
||||
background-blend-mode: overlay;
|
||||
background-size: cover;
|
||||
background-repeat: none;
|
||||
.dark & {
|
||||
background-color: theme(colors.black / 70%);
|
||||
}
|
||||
}
|
||||
|
||||
.bg-pattern-verde {
|
||||
background-color: theme(colors.white / 50%);
|
||||
background-image: url('/assets/images/bg-pattern-verde.webp');
|
||||
background-blend-mode: overlay;
|
||||
background-size: cover;
|
||||
background-repeat: none;
|
||||
.dark & {
|
||||
background-color: theme(colors.black / 70%);
|
||||
background: var(--color-gray-900) !important;
|
||||
border-color: var(--color-gray-700) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.prose {
|
||||
li {
|
||||
@apply my-2;
|
||||
> :last-child,
|
||||
> :first-child {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
hr {
|
||||
@apply mt-8 mb-4;
|
||||
}
|
||||
:where(h1):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
|
||||
color: var(--tw-prose-headings);
|
||||
font-weight: 500 !important;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.2em !important;
|
||||
line-height: 1.1111111;
|
||||
}
|
||||
> h2 {
|
||||
@apply mt-5! mb-3! text-3xl!;
|
||||
a {
|
||||
@apply hover:no-underline!;
|
||||
}
|
||||
}
|
||||
> h3 {
|
||||
@apply text-2xl!;
|
||||
a {
|
||||
@apply hover:no-underline!;
|
||||
}
|
||||
}
|
||||
> h4 {
|
||||
a {
|
||||
@apply hover:no-underline!;
|
||||
}
|
||||
}
|
||||
> h5 {
|
||||
a {
|
||||
@apply hover:no-underline!;
|
||||
}
|
||||
}
|
||||
ol {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
|
||||
ol ol {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
|
||||
ol ol ol {
|
||||
list-style-type: lower-roman;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
@layer utilities {
|
||||
.icon-svg {
|
||||
svg {
|
||||
font-size: 24px;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
display: inline-block;
|
||||
fill: currentColor;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-xs {
|
||||
svg {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-sm {
|
||||
svg {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-lg {
|
||||
svg {
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
.prose ol {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
|
||||
.prose ol ol {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
|
||||
.prose ol ol ol {
|
||||
list-style-type: lower-roman;
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/* Main CSS entry point */
|
||||
@import "tailwindcss";
|
||||
@plugin "@tailwindcss/typography";
|
||||
@source "hugo_stats.json";
|
||||
|
||||
@font-face {
|
||||
font-family: "Roboto Flex";
|
||||
src: url("/assets/fonts/RobotoFlex.woff2") format("woff2");
|
||||
font-weight: 100 1000; /* Range of weights Roboto Flex supports */
|
||||
font-stretch: 100%; /* Range of width Roboto Flex supports */
|
||||
font-style: oblique 0deg 10deg; /* Range of oblique angle Roboto Flex supports */
|
||||
font-display: fallback;
|
||||
}
|
||||
|
||||
/* Roboto Mono */
|
||||
@font-face {
|
||||
font-family: "Roboto Mono";
|
||||
src: url("/assets/fonts/RobotoMono-Regular.woff2") format("woff2");
|
||||
font-weight: 100 700; /* Define the range of weight the variable font supports */
|
||||
font-style: normal;
|
||||
font-display: fallback;
|
||||
}
|
||||
|
||||
/* Roboto Mono Italic */
|
||||
@font-face {
|
||||
font-family: "Roboto Mono";
|
||||
src: url("/assets/fonts/RobotoMono-Italic.woff2") format("woff2");
|
||||
font-weight: 100 700; /* Define the range of weight the variable font supports */
|
||||
font-style: italic;
|
||||
font-display: fallback;
|
||||
}
|
||||
|
||||
@layer theme {
|
||||
@import "theme.css";
|
||||
}
|
||||
|
||||
@layer base {
|
||||
@import "global.css";
|
||||
}
|
||||
@import "utilities.css";
|
||||
@import "syntax-dark.css";
|
||||
@import "syntax-light.css";
|
||||
@import "components.css";
|
||||
|
||||
@variant dark (&:where(.dark, .dark *));
|
|
@ -1,16 +0,0 @@
|
|||
/* see also: tailwind.config.js */
|
||||
|
||||
@import "tailwindcss/base";
|
||||
@import "/assets/css/global";
|
||||
@import "/assets/css/typography";
|
||||
@import "/assets/css/hack";
|
||||
|
||||
@import "tailwindcss/components";
|
||||
@import "/assets/css/code";
|
||||
@import "/assets/css/toc";
|
||||
|
||||
@import "tailwindcss/utilities";
|
||||
@import "/assets/css/syntax-light";
|
||||
@import "/assets/css/syntax-dark";
|
||||
@import "/assets/css/icons";
|
||||
@import "/assets/css/lists";
|
|
@ -1,343 +1,342 @@
|
|||
@layer utilities {
|
||||
.syntax-dark {
|
||||
/* Other */
|
||||
.x {
|
||||
color: theme("colors.white");
|
||||
}
|
||||
/* Error */
|
||||
.err {
|
||||
color: theme("colors.red.dark.500");
|
||||
}
|
||||
/* CodeLine */
|
||||
.cl {
|
||||
}
|
||||
/* LineHighlight */
|
||||
.hl {
|
||||
min-width: fit-content;
|
||||
background-color: theme("colors.gray.dark.300");
|
||||
}
|
||||
.lntd:first-child .hl,
|
||||
& > .chroma > code > .hl {
|
||||
margin-left: -4px;
|
||||
border-left: 4px solid theme("colors.gray.dark.400");
|
||||
}
|
||||
/* LineNumbersTable */
|
||||
.lnt {
|
||||
white-space: pre;
|
||||
user-select: none;
|
||||
margin-right: 0.4em;
|
||||
padding: 0 0.4em 0 0.4em;
|
||||
color: theme("colors.gray.dark.400");
|
||||
}
|
||||
/* LineNumbers */
|
||||
.ln {
|
||||
white-space: pre;
|
||||
user-select: none;
|
||||
margin-right: 0.4em;
|
||||
padding: 0 0.4em 0 0.4em;
|
||||
color: theme("colors.gray.dark.400");
|
||||
}
|
||||
/* Line */
|
||||
.line {
|
||||
display: flex;
|
||||
}
|
||||
/* Keyword */
|
||||
.k {
|
||||
color: theme("colors.amber.dark.700");
|
||||
}
|
||||
/* KeywordConstant */
|
||||
.kc {
|
||||
color: theme("colors.violet.dark.700");
|
||||
}
|
||||
/* KeywordDeclaration */
|
||||
.kd {
|
||||
color: theme("colors.amber.dark.700");
|
||||
}
|
||||
/* KeywordNamespace */
|
||||
.kn {
|
||||
color: theme("colors.amber.dark.700");
|
||||
}
|
||||
/* KeywordPseudo */
|
||||
.kp {
|
||||
color: theme("colors.amber.dark.700");
|
||||
}
|
||||
/* KeywordReserved */
|
||||
.kr {
|
||||
color: theme("colors.amber.dark.700");
|
||||
}
|
||||
/* KeywordType */
|
||||
.kt {
|
||||
color: theme("colors.amber.dark.700");
|
||||
}
|
||||
/* Name */
|
||||
.n {
|
||||
color: theme("colors.violet.dark.700");
|
||||
}
|
||||
/* NameAttribute */
|
||||
.na {
|
||||
color: theme("colors.amber.dark.700");
|
||||
}
|
||||
/* NameBuiltin */
|
||||
.nb {
|
||||
color: theme("colors.amber.dark.700");
|
||||
}
|
||||
/* NameBuiltinPseudo */
|
||||
.bp {
|
||||
color: theme("colors.violet.dark.700");
|
||||
}
|
||||
/* NameClass */
|
||||
.nc {
|
||||
color: theme("colors.white");
|
||||
}
|
||||
/* NameConstant */
|
||||
.no {
|
||||
color: theme("colors.white");
|
||||
}
|
||||
/* NameDecorator */
|
||||
.nd {
|
||||
color: theme("colors.violet.dark.700");
|
||||
}
|
||||
/* NameEntity */
|
||||
.ni {
|
||||
color: theme("colors.amber.dark.700");
|
||||
}
|
||||
/* NameException */
|
||||
.ne {
|
||||
color: theme("colors.red.dark.700");
|
||||
}
|
||||
/* NameFunction */
|
||||
.nf {
|
||||
color: theme("colors.blue.dark.600");
|
||||
}
|
||||
/* NameFunctionMagic */
|
||||
.fm {
|
||||
color: theme("colors.blue.dark.600");
|
||||
}
|
||||
/* NameLabel */
|
||||
.nl {
|
||||
color: theme("colors.amber.dark.500");
|
||||
}
|
||||
/* NameNamespace */
|
||||
.nn {
|
||||
color: theme("colors.white");
|
||||
}
|
||||
/* NameOther */
|
||||
.nx {
|
||||
color: theme("colors.white");
|
||||
}
|
||||
/* NameProperty */
|
||||
.py {
|
||||
color: theme("colors.white");
|
||||
}
|
||||
/* NameTag */
|
||||
.nt {
|
||||
color: theme("colors.green.dark.600");
|
||||
}
|
||||
/* NameVariable */
|
||||
.nv {
|
||||
color: theme("colors.white");
|
||||
}
|
||||
/* NameVariableClass */
|
||||
.vc {
|
||||
color: theme("colors.violet.dark.600");
|
||||
}
|
||||
/* NameVariableGlobal */
|
||||
.vg {
|
||||
color: theme("colors.violet.dark.600");
|
||||
}
|
||||
/* NameVariableInstance */
|
||||
.vi {
|
||||
color: theme("colors.violet.dark.600");
|
||||
}
|
||||
/* NameVariableMagic */
|
||||
.vm {
|
||||
color: theme("colors.violet.dark.600");
|
||||
}
|
||||
/* Literal */
|
||||
.l {
|
||||
color: theme("colors.white");
|
||||
}
|
||||
/* LiteralDate */
|
||||
.ld {
|
||||
color: theme("colors.green.dark.600");
|
||||
}
|
||||
/* LiteralString */
|
||||
.s {
|
||||
color: theme("colors.white");
|
||||
}
|
||||
/* LiteralStringAffix */
|
||||
.sa {
|
||||
color: theme("colors.green.dark.600");
|
||||
}
|
||||
/* LiteralStringBacktick */
|
||||
.sb {
|
||||
color: theme("colors.green.dark.600");
|
||||
}
|
||||
/* LiteralStringChar */
|
||||
.sc {
|
||||
color: theme("colors.green.dark.600");
|
||||
}
|
||||
/* LiteralStringDelimiter */
|
||||
.dl {
|
||||
color: theme("colors.green.dark.600");
|
||||
}
|
||||
/* LiteralStringDoc */
|
||||
.sd {
|
||||
color: theme("colors.green.dark.600");
|
||||
}
|
||||
/* LiteralStringDouble */
|
||||
.s2 {
|
||||
color: theme("colors.green.dark.600");
|
||||
}
|
||||
/* LiteralStringEscape */
|
||||
.se {
|
||||
color: theme("colors.white");
|
||||
}
|
||||
/* LiteralStringHeredoc */
|
||||
.sh {
|
||||
color: theme("colors.green.dark.600");
|
||||
}
|
||||
/* LiteralStringInterpol */
|
||||
.si {
|
||||
color: theme("colors.green.dark.600");
|
||||
}
|
||||
/* LiteralStringOther */
|
||||
.sx {
|
||||
color: theme("colors.green.dark.600");
|
||||
}
|
||||
/* LiteralStringRegex */
|
||||
.sr {
|
||||
color: theme("colors.blue.dark.500");
|
||||
}
|
||||
/* LiteralStringSingle */
|
||||
.s1 {
|
||||
color: theme("colors.green.dark.600");
|
||||
}
|
||||
/* LiteralStringSymbol */
|
||||
.ss {
|
||||
color: theme("colors.blue.dark.600");
|
||||
}
|
||||
/* LiteralNumber */
|
||||
.m {
|
||||
color: theme("colors.blue.dark.600");
|
||||
}
|
||||
/* LiteralNumberBin */
|
||||
.mb {
|
||||
color: theme("colors.blue.dark.600");
|
||||
}
|
||||
/* LiteralNumberFloat */
|
||||
.mf {
|
||||
color: theme("colors.blue.dark.600");
|
||||
}
|
||||
/* LiteralNumberHex */
|
||||
.mh {
|
||||
color: theme("colors.blue.dark.600");
|
||||
}
|
||||
/* LiteralNumberInteger */
|
||||
.mi {
|
||||
color: theme("colors.blue.dark.600");
|
||||
}
|
||||
/* LiteralNumberIntegerLong */
|
||||
.il {
|
||||
color: theme("colors.blue.dark.600");
|
||||
}
|
||||
/* LiteralNumberOct */
|
||||
.mo {
|
||||
color: theme("colors.blue.dark.600");
|
||||
}
|
||||
/* Operator */
|
||||
.o {
|
||||
color: theme("colors.blue.dark.700");
|
||||
}
|
||||
/* OperatorWord */
|
||||
.ow {
|
||||
color: theme("colors.amber.dark.700");
|
||||
}
|
||||
/* Punctuation */
|
||||
.p {
|
||||
color: theme("colors.gray.dark.500");
|
||||
}
|
||||
/* Comment */
|
||||
.c {
|
||||
color: theme("colors.gray.dark.500");
|
||||
}
|
||||
/* CommentHashbang */
|
||||
.ch {
|
||||
color: theme("colors.gray.dark.500");
|
||||
}
|
||||
/* CommentMultiline */
|
||||
.cm {
|
||||
color: theme("colors.gray.dark.500");
|
||||
}
|
||||
/* CommentSingle */
|
||||
.c1 {
|
||||
color: theme("colors.gray.dark.500");
|
||||
}
|
||||
/* CommentSpecial */
|
||||
.cs {
|
||||
color: theme("colors.gray.dark.500");
|
||||
}
|
||||
/* CommentPreproc */
|
||||
.cp {
|
||||
color: theme("colors.gray.dark.500");
|
||||
}
|
||||
/* CommentPreprocFile */
|
||||
.cpf {
|
||||
color: theme("colors.gray.dark.500");
|
||||
}
|
||||
/* Generic */
|
||||
.g {
|
||||
color: theme("colors.white");
|
||||
}
|
||||
/* GenericDeleted */
|
||||
.gd {
|
||||
color: theme("colors.red.dark.500");
|
||||
}
|
||||
/* GenericEmph */
|
||||
.ge {
|
||||
color: theme("colors.white");
|
||||
}
|
||||
/* GenericError */
|
||||
.gr {
|
||||
color: theme("colors.red.dark.500");
|
||||
}
|
||||
/* GenericHeading */
|
||||
.gh {
|
||||
color: theme("colors.gray.dark.600");
|
||||
}
|
||||
/* GenericInserted */
|
||||
.gi {
|
||||
color: theme("colors.green.dark.500");
|
||||
}
|
||||
/* GenericOutput */
|
||||
.go {
|
||||
color: theme("colors.white");
|
||||
}
|
||||
/* GenericPrompt */
|
||||
.gp {
|
||||
user-select: none;
|
||||
color: theme("colors.green.dark.400");
|
||||
}
|
||||
/* GenericStrong */
|
||||
.gs {
|
||||
color: theme("colors.white");
|
||||
}
|
||||
/* GenericSubheading */
|
||||
.gu {
|
||||
color: theme("colors.gray.dark.600");
|
||||
}
|
||||
/* GenericTraceback */
|
||||
.gt {
|
||||
color: theme("colors.red.dark.500");
|
||||
}
|
||||
/* GenericUnderline */
|
||||
.gl {
|
||||
color: theme("colors.white");
|
||||
text-decoration: underline;
|
||||
}
|
||||
/* TextWhitespace */
|
||||
.w {
|
||||
color: theme("colors.gray.dark.100");
|
||||
}
|
||||
@utility syntax-dark {
|
||||
/* Other */
|
||||
.x {
|
||||
color: var(--color-white-main);
|
||||
}
|
||||
/* Error */
|
||||
.err {
|
||||
color: var(--color-red-500);
|
||||
}
|
||||
/* CodeLine */
|
||||
.cl {
|
||||
color: var(--color-gray-200);
|
||||
}
|
||||
/* LineHighlight */
|
||||
.hl {
|
||||
min-width: fit-content;
|
||||
background-color: var(--color-gray-800);
|
||||
}
|
||||
.lntd:first-child .hl,
|
||||
& > .chroma > code > .hl {
|
||||
margin-left: -4px;
|
||||
border-left: 4px solid var(--color-gray-900);
|
||||
}
|
||||
/* LineNumbersTable */
|
||||
.lnt {
|
||||
white-space: pre;
|
||||
user-select: none;
|
||||
margin-right: 0.4em;
|
||||
padding: 0 0.4em 0 0.4em;
|
||||
color: var(--color-gray-900);
|
||||
}
|
||||
/* LineNumbers */
|
||||
.ln {
|
||||
white-space: pre;
|
||||
user-select: none;
|
||||
margin-right: 0.4em;
|
||||
padding: 0 0.4em 0 0.4em;
|
||||
color: var(--color-gray-900);
|
||||
}
|
||||
/* Line */
|
||||
.line {
|
||||
display: flex;
|
||||
}
|
||||
/* Keyword */
|
||||
.k {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* KeywordConstant */
|
||||
.kc {
|
||||
color: var(--color-violet-300);
|
||||
}
|
||||
/* KeywordDeclaration */
|
||||
.kd {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* KeywordNamespace */
|
||||
.kn {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* KeywordPseudo */
|
||||
.kp {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* KeywordReserved */
|
||||
.kr {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* KeywordType */
|
||||
.kt {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* Name */
|
||||
.n {
|
||||
color: var(--color-violet-300);
|
||||
}
|
||||
/* NameAttribute */
|
||||
.na {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* NameBuiltin */
|
||||
.nb {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* NameBuiltinPseudo */
|
||||
.bp {
|
||||
color: var(--color-violet-300);
|
||||
}
|
||||
/* NameClass */
|
||||
.nc {
|
||||
color: var(--color-white-main);
|
||||
}
|
||||
/* NameConstant */
|
||||
.no {
|
||||
color: var(--color-white-main);
|
||||
}
|
||||
/* NameDecorator */
|
||||
.nd {
|
||||
color: var(--color-violet-300);
|
||||
}
|
||||
/* NameEntity */
|
||||
.ni {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* NameException */
|
||||
.ne {
|
||||
color: var(--color-red-700);
|
||||
}
|
||||
/* NameFunction */
|
||||
.nf {
|
||||
color: var(--color-blue-400);
|
||||
}
|
||||
/* NameFunctionMagic */
|
||||
.fm {
|
||||
color: var(--color-blue-400);
|
||||
}
|
||||
/* NameLabel */
|
||||
.nl {
|
||||
color: var(--color-yellow-500);
|
||||
}
|
||||
/* NameNamespace */
|
||||
.nn {
|
||||
color: var(--color-white-main);
|
||||
}
|
||||
/* NameOther */
|
||||
.nx {
|
||||
color: var(--color-white-main);
|
||||
}
|
||||
/* NameProperty */
|
||||
.py {
|
||||
color: var(--color-violet-300);
|
||||
}
|
||||
/* NameTag */
|
||||
.nt {
|
||||
color: var(--color-green-300);
|
||||
}
|
||||
/* NameVariable */
|
||||
.nv {
|
||||
color: var(--color-green-500);
|
||||
}
|
||||
/* NameVariableClass */
|
||||
.vc {
|
||||
color: var(--color-violet-600);
|
||||
}
|
||||
/* NameVariableGlobal */
|
||||
.vg {
|
||||
color: var(--color-violet-600);
|
||||
}
|
||||
/* NameVariableInstance */
|
||||
.vi {
|
||||
color: var(--color-violet-600);
|
||||
}
|
||||
/* NameVariableMagic */
|
||||
.vm {
|
||||
color: var(--color-violet-600);
|
||||
}
|
||||
/* Literal */
|
||||
.l {
|
||||
color: var(--color-white-main);
|
||||
}
|
||||
/* LiteralDate */
|
||||
.ld {
|
||||
color: var(--color-green-600);
|
||||
}
|
||||
/* LiteralString */
|
||||
.s {
|
||||
color: var(--color-white-main);
|
||||
}
|
||||
/* LiteralStringAffix */
|
||||
.sa {
|
||||
color: var(--color-green-600);
|
||||
}
|
||||
/* LiteralStringBacktick */
|
||||
.sb {
|
||||
color: var(--color-green-600);
|
||||
}
|
||||
/* LiteralStringChar */
|
||||
.sc {
|
||||
color: var(--color-green-600);
|
||||
}
|
||||
/* LiteralStringDelimiter */
|
||||
.dl {
|
||||
color: var(--color-green-600);
|
||||
}
|
||||
/* LiteralStringDoc */
|
||||
.sd {
|
||||
color: var(--color-green-600);
|
||||
}
|
||||
/* LiteralStringDouble */
|
||||
.s2 {
|
||||
color: var(--color-green-600);
|
||||
}
|
||||
/* LiteralStringEscape */
|
||||
.se {
|
||||
color: var(--color-white-main);
|
||||
}
|
||||
/* LiteralStringHeredoc */
|
||||
.sh {
|
||||
color: var(--color-green-600);
|
||||
}
|
||||
/* LiteralStringInterpol */
|
||||
.si {
|
||||
color: var(--color-green-600);
|
||||
}
|
||||
/* LiteralStringOther */
|
||||
.sx {
|
||||
color: var(--color-green-600);
|
||||
}
|
||||
/* LiteralStringRegex */
|
||||
.sr {
|
||||
color: var(--color-blue-400);
|
||||
}
|
||||
/* LiteralStringSingle */
|
||||
.s1 {
|
||||
color: var(--color-green-600);
|
||||
}
|
||||
/* LiteralStringSymbol */
|
||||
.ss {
|
||||
color: var(--color-blue-400);
|
||||
}
|
||||
/* LiteralNumber */
|
||||
.m {
|
||||
color: var(--color-blue-400);
|
||||
}
|
||||
/* LiteralNumberBin */
|
||||
.mb {
|
||||
color: var(--color-blue-400);
|
||||
}
|
||||
/* LiteralNumberFloat */
|
||||
.mf {
|
||||
color: var(--color-blue-400);
|
||||
}
|
||||
/* LiteralNumberHex */
|
||||
.mh {
|
||||
color: var(--color-blue-400);
|
||||
}
|
||||
/* LiteralNumberInteger */
|
||||
.mi {
|
||||
color: var(--color-blue-400);
|
||||
}
|
||||
/* LiteralNumberIntegerLong */
|
||||
.il {
|
||||
color: var(--color-blue-400);
|
||||
}
|
||||
/* LiteralNumberOct */
|
||||
.mo {
|
||||
color: var(--color-blue-400);
|
||||
}
|
||||
/* Operator */
|
||||
.o {
|
||||
color: var(--color-blue-200);
|
||||
}
|
||||
/* OperatorWord */
|
||||
.ow {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* Punctuation */
|
||||
.p {
|
||||
color: var(--color-gray-500);
|
||||
}
|
||||
/* Comment */
|
||||
.c {
|
||||
color: var(--color-gray-500);
|
||||
}
|
||||
/* CommentHashbang */
|
||||
.ch {
|
||||
color: var(--color-gray-500);
|
||||
}
|
||||
/* CommentMultiline */
|
||||
.cm {
|
||||
color: var(--color-gray-500);
|
||||
}
|
||||
/* CommentSingle */
|
||||
.c1 {
|
||||
color: var(--color-gray-500);
|
||||
}
|
||||
/* CommentSpecial */
|
||||
.cs {
|
||||
color: var(--color-gray-500);
|
||||
}
|
||||
/* CommentPreproc */
|
||||
.cp {
|
||||
color: var(--color-gray-500);
|
||||
}
|
||||
/* CommentPreprocFile */
|
||||
.cpf {
|
||||
color: var(--color-gray-500);
|
||||
}
|
||||
/* Generic */
|
||||
.g {
|
||||
color: var(--color-white-main);
|
||||
}
|
||||
/* GenericDeleted */
|
||||
.gd {
|
||||
color: var(--color-red-500);
|
||||
}
|
||||
/* GenericEmph */
|
||||
.ge {
|
||||
color: var(--color-white-main);
|
||||
}
|
||||
/* GenericError */
|
||||
.gr {
|
||||
color: var(--color-red-500);
|
||||
}
|
||||
/* GenericHeading */
|
||||
.gh {
|
||||
color: var(--color-gray-600);
|
||||
}
|
||||
/* GenericInserted */
|
||||
.gi {
|
||||
color: var(--color-green-500);
|
||||
}
|
||||
/* GenericOutput */
|
||||
.go {
|
||||
color: var(--color-white-main);
|
||||
}
|
||||
/* GenericPrompt */
|
||||
.gp {
|
||||
user-select: none;
|
||||
color: var(--color-green-500);
|
||||
}
|
||||
/* GenericStrong */
|
||||
.gs {
|
||||
color: var(--color-white-main);
|
||||
}
|
||||
/* GenericSubheading */
|
||||
.gu {
|
||||
color: var(--color-gray-600);
|
||||
}
|
||||
/* GenericTraceback */
|
||||
.gt {
|
||||
color: var(--color-red-500);
|
||||
}
|
||||
/* GenericUnderline */
|
||||
.gl {
|
||||
color: var(--color-white-main);
|
||||
text-decoration: underline;
|
||||
}
|
||||
/* TextWhitespace */
|
||||
.w {
|
||||
color: var(--color-gray-100);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,343 +1,342 @@
|
|||
@layer utilities {
|
||||
.syntax-light {
|
||||
/* Other */
|
||||
.x {
|
||||
color: theme("colors.black");
|
||||
}
|
||||
/* Error */
|
||||
.err {
|
||||
color: theme("colors.red.light.500");
|
||||
}
|
||||
/* CodeLine */
|
||||
.cl {
|
||||
}
|
||||
/* LineHighlight */
|
||||
.hl {
|
||||
min-width: fit-content;
|
||||
background-color: theme("colors.blue.light.100");
|
||||
}
|
||||
.lntd:first-child .hl,
|
||||
& > .chroma > code > .hl {
|
||||
margin-left: -4px;
|
||||
border-left: 4px solid theme("colors.blue.light.300");
|
||||
}
|
||||
/* LineNumbersTable */
|
||||
.lnt {
|
||||
white-space: pre;
|
||||
user-select: none;
|
||||
margin-right: 0.4em;
|
||||
padding: 0 0.4em 0 0.4em;
|
||||
color: theme("colors.gray.light.400");
|
||||
}
|
||||
/* LineNumbers */
|
||||
.ln {
|
||||
white-space: pre;
|
||||
user-select: none;
|
||||
margin-right: 0.4em;
|
||||
padding: 0 0.4em 0 0.4em;
|
||||
color: theme("colors.gray.light.400");
|
||||
}
|
||||
/* Line */
|
||||
.line {
|
||||
display: flex;
|
||||
}
|
||||
/* Keyword */
|
||||
.k {
|
||||
color: theme("colors.amber.light.500");
|
||||
}
|
||||
/* KeywordConstant */
|
||||
.kc {
|
||||
color: theme("colors.violet.light.400");
|
||||
}
|
||||
/* KeywordDeclaration */
|
||||
.kd {
|
||||
color: theme("colors.amber.light.500");
|
||||
}
|
||||
/* KeywordNamespace */
|
||||
.kn {
|
||||
color: theme("colors.amber.light.500");
|
||||
}
|
||||
/* KeywordPseudo */
|
||||
.kp {
|
||||
color: theme("colors.amber.light.500");
|
||||
}
|
||||
/* KeywordReserved */
|
||||
.kr {
|
||||
color: theme("colors.amber.light.500");
|
||||
}
|
||||
/* KeywordType */
|
||||
.kt {
|
||||
color: theme("colors.amber.light.500");
|
||||
}
|
||||
/* Name */
|
||||
.n {
|
||||
color: theme("colors.violet.light.400");
|
||||
}
|
||||
/* NameAttribute */
|
||||
.na {
|
||||
color: theme("colors.amber.light.500");
|
||||
}
|
||||
/* NameBuiltin */
|
||||
.nb {
|
||||
color: theme("colors.amber.light.500");
|
||||
}
|
||||
/* NameBuiltinPseudo */
|
||||
.bp {
|
||||
color: theme("colors.violet.light.400");
|
||||
}
|
||||
/* NameClass */
|
||||
.nc {
|
||||
color: theme("colors.black");
|
||||
}
|
||||
/* NameConstant */
|
||||
.no {
|
||||
color: theme("colors.black");
|
||||
}
|
||||
/* NameDecorator */
|
||||
.nd {
|
||||
color: theme("colors.violet.light.400");
|
||||
}
|
||||
/* NameEntity */
|
||||
.ni {
|
||||
color: theme("colors.amber.light.500");
|
||||
}
|
||||
/* NameException */
|
||||
.ne {
|
||||
color: theme("colors.red.light.700");
|
||||
}
|
||||
/* NameFunction */
|
||||
.nf {
|
||||
color: theme("colors.blue.light.600");
|
||||
}
|
||||
/* NameFunctionMagic */
|
||||
.fm {
|
||||
color: theme("colors.blue.light.600");
|
||||
}
|
||||
/* NameLabel */
|
||||
.nl {
|
||||
color: theme("colors.amber.light.700");
|
||||
}
|
||||
/* NameNamespace */
|
||||
.nn {
|
||||
color: theme("colors.black");
|
||||
}
|
||||
/* NameOther */
|
||||
.nx {
|
||||
color: theme("colors.black");
|
||||
}
|
||||
/* NameProperty */
|
||||
.py {
|
||||
color: theme("colors.black");
|
||||
}
|
||||
/* NameTag */
|
||||
.nt {
|
||||
color: theme("colors.green.light.600");
|
||||
}
|
||||
/* NameVariable */
|
||||
.nv {
|
||||
color: theme("colors.black");
|
||||
}
|
||||
/* NameVariableClass */
|
||||
.vc {
|
||||
color: theme("colors.violet.light.600");
|
||||
}
|
||||
/* NameVariableGlobal */
|
||||
.vg {
|
||||
color: theme("colors.violet.light.600");
|
||||
}
|
||||
/* NameVariableInstance */
|
||||
.vi {
|
||||
color: theme("colors.violet.light.600");
|
||||
}
|
||||
/* NameVariableMagic */
|
||||
.vm {
|
||||
color: theme("colors.violet.light.600");
|
||||
}
|
||||
/* Literal */
|
||||
.l {
|
||||
color: theme("colors.black");
|
||||
}
|
||||
/* LiteralDate */
|
||||
.ld {
|
||||
color: theme("colors.black");
|
||||
}
|
||||
/* LiteralString */
|
||||
.s {
|
||||
color: theme("colors.black");
|
||||
}
|
||||
/* LiteralStringAffix */
|
||||
.sa {
|
||||
color: theme("colors.green.light.600");
|
||||
}
|
||||
/* LiteralStringBacktick */
|
||||
.sb {
|
||||
color: theme("colors.green.light.600");
|
||||
}
|
||||
/* LiteralStringChar */
|
||||
.sc {
|
||||
color: theme("colors.green.light.600");
|
||||
}
|
||||
/* LiteralStringDelimiter */
|
||||
.dl {
|
||||
color: theme("colors.green.light.600");
|
||||
}
|
||||
/* LiteralStringDoc */
|
||||
.sd {
|
||||
color: #8f5902;
|
||||
}
|
||||
/* LiteralStringDouble */
|
||||
.s2 {
|
||||
color: theme("colors.green.light.600");
|
||||
}
|
||||
/* LiteralStringEscape */
|
||||
.se {
|
||||
color: theme("colors.black");
|
||||
}
|
||||
/* LiteralStringHeredoc */
|
||||
.sh {
|
||||
color: theme("colors.green.light.600");
|
||||
}
|
||||
/* LiteralStringInterpol */
|
||||
.si {
|
||||
color: theme("colors.green.light.600");
|
||||
}
|
||||
/* LiteralStringOther */
|
||||
.sx {
|
||||
color: theme("colors.green.light.600");
|
||||
}
|
||||
/* LiteralStringRegex */
|
||||
.sr {
|
||||
color: theme("colors.blue.light.500");
|
||||
}
|
||||
/* LiteralStringSingle */
|
||||
.s1 {
|
||||
color: theme("colors.green.light.600");
|
||||
}
|
||||
/* LiteralStringSymbol */
|
||||
.ss {
|
||||
color: theme("colors.green.light.600");
|
||||
}
|
||||
/* LiteralNumber */
|
||||
.m {
|
||||
color: theme("colors.blue.light.600");
|
||||
}
|
||||
/* LiteralNumberBin */
|
||||
.mb {
|
||||
color: theme("colors.blue.light.600");
|
||||
}
|
||||
/* LiteralNumberFloat */
|
||||
.mf {
|
||||
color: theme("colors.blue.light.600");
|
||||
}
|
||||
/* LiteralNumberHex */
|
||||
.mh {
|
||||
color: theme("colors.blue.light.600");
|
||||
}
|
||||
/* LiteralNumberInteger */
|
||||
.mi {
|
||||
color: theme("colors.blue.light.600");
|
||||
}
|
||||
/* LiteralNumberIntegerLong */
|
||||
.il {
|
||||
color: theme("colors.blue.light.600");
|
||||
}
|
||||
/* LiteralNumberOct */
|
||||
.mo {
|
||||
color: theme("colors.blue.light.600");
|
||||
}
|
||||
/* Operator */
|
||||
.o {
|
||||
color: theme("colors.blue.light.400");
|
||||
}
|
||||
/* OperatorWord */
|
||||
.ow {
|
||||
color: theme("colors.amber.light.500");
|
||||
}
|
||||
/* Punctuation */
|
||||
.p {
|
||||
color: theme("colors.gray.light.400");
|
||||
}
|
||||
/* Comment */
|
||||
.c {
|
||||
color: theme("colors.gray.light.400");
|
||||
}
|
||||
/* CommentHashbang */
|
||||
.ch {
|
||||
color: theme("colors.gray.light.400");
|
||||
}
|
||||
/* CommentMultiline */
|
||||
.cm {
|
||||
color: theme("colors.gray.light.400");
|
||||
}
|
||||
/* CommentSingle */
|
||||
.c1 {
|
||||
color: theme("colors.gray.light.400");
|
||||
}
|
||||
/* CommentSpecial */
|
||||
.cs {
|
||||
color: theme("colors.gray.light.400");
|
||||
}
|
||||
/* CommentPreproc */
|
||||
.cp {
|
||||
color: theme("colors.gray.light.400");
|
||||
}
|
||||
/* CommentPreprocFile */
|
||||
.cpf {
|
||||
color: theme("colors.gray.light.400");
|
||||
}
|
||||
/* Generic */
|
||||
.g {
|
||||
color: theme("colors.black");
|
||||
}
|
||||
/* GenericDeleted */
|
||||
.gd {
|
||||
color: theme("colors.red.light.500");
|
||||
}
|
||||
/* GenericEmph */
|
||||
.ge {
|
||||
color: theme("colors.black");
|
||||
}
|
||||
/* GenericError */
|
||||
.gr {
|
||||
color: theme("colors.red.light.500");
|
||||
}
|
||||
/* GenericHeading */
|
||||
.gh {
|
||||
color: theme("colors.gray.light.600");
|
||||
}
|
||||
/* GenericInserted */
|
||||
.gi {
|
||||
color: theme("colors.green.light.500");
|
||||
}
|
||||
/* GenericOutput */
|
||||
.go {
|
||||
color: theme("colors.black");
|
||||
}
|
||||
/* GenericPrompt */
|
||||
.gp {
|
||||
user-select: none;
|
||||
color: theme("colors.green.light.400");
|
||||
}
|
||||
/* GenericStrong */
|
||||
.gs {
|
||||
color: theme("colors.black");
|
||||
}
|
||||
/* GenericSubheading */
|
||||
.gu {
|
||||
color: theme("colors.gray.light.600");
|
||||
}
|
||||
/* GenericTraceback */
|
||||
.gt {
|
||||
color: theme("colors.red.light.500");
|
||||
}
|
||||
/* GenericUnderline */
|
||||
.gl {
|
||||
color: theme("colors.black");
|
||||
text-decoration: underline;
|
||||
}
|
||||
/* TextWhitespace */
|
||||
.w {
|
||||
color: theme("colors.gray.light.100");
|
||||
}
|
||||
@utility syntax-light {
|
||||
/* Other */
|
||||
.x {
|
||||
color: var(--color-black-main);
|
||||
}
|
||||
/* Error */
|
||||
.err {
|
||||
color: var(--color-red-500);
|
||||
}
|
||||
/* CodeLine */
|
||||
.cl {
|
||||
color: var(--color-gray-700);
|
||||
}
|
||||
/* LineHighlight */
|
||||
.hl {
|
||||
min-width: fit-content;
|
||||
background-color: var(--color-blue-100);
|
||||
}
|
||||
.lntd:first-child .hl,
|
||||
& > .chroma > code > .hl {
|
||||
margin-left: -4px;
|
||||
border-left: 4px solid var(--color-blue-300);
|
||||
}
|
||||
/* LineNumbersTable */
|
||||
.lnt {
|
||||
white-space: pre;
|
||||
user-select: none;
|
||||
margin-right: 0.4em;
|
||||
padding: 0 0.4em 0 0.4em;
|
||||
color: var(--color-gray-400);
|
||||
}
|
||||
/* LineNumbers */
|
||||
.ln {
|
||||
white-space: pre;
|
||||
user-select: none;
|
||||
margin-right: 0.4em;
|
||||
padding: 0 0.4em 0 0.4em;
|
||||
color: var(--color-gray-400);
|
||||
}
|
||||
/* Line */
|
||||
.line {
|
||||
display: flex;
|
||||
}
|
||||
/* Keyword */
|
||||
.k {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* KeywordConstant */
|
||||
.kc {
|
||||
color: var(--color-violet-400);
|
||||
}
|
||||
/* KeywordDeclaration */
|
||||
.kd {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* KeywordNamespace */
|
||||
.kn {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* KeywordPseudo */
|
||||
.kp {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* KeywordReserved */
|
||||
.kr {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* KeywordType */
|
||||
.kt {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* Name */
|
||||
.n {
|
||||
color: var(--color-violet-400);
|
||||
}
|
||||
/* NameAttribute */
|
||||
.na {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* NameBuiltin */
|
||||
.nb {
|
||||
color: var(--color-yellow-800);
|
||||
}
|
||||
/* NameBuiltinPseudo */
|
||||
.bp {
|
||||
color: var(--color-violet-400);
|
||||
}
|
||||
/* NameClass */
|
||||
.nc {
|
||||
color: var(--color-black-main);
|
||||
}
|
||||
/* NameConstant */
|
||||
.no {
|
||||
color: var(--color-black-main);
|
||||
}
|
||||
/* NameDecorator */
|
||||
.nd {
|
||||
color: var(--color-violet-400);
|
||||
}
|
||||
/* NameEntity */
|
||||
.ni {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* NameException */
|
||||
.ne {
|
||||
color: var(--color-red-700);
|
||||
}
|
||||
/* NameFunction */
|
||||
.nf {
|
||||
color: var(--color-blue-500);
|
||||
}
|
||||
/* NameFunctionMagic */
|
||||
.fm {
|
||||
color: var(--color-blue-500);
|
||||
}
|
||||
/* NameLabel */
|
||||
.nl {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* NameNamespace */
|
||||
.nn {
|
||||
color: var(--color-black-main);
|
||||
}
|
||||
/* NameOther */
|
||||
.nx {
|
||||
color: var(--color-black-main);
|
||||
}
|
||||
/* NameProperty */
|
||||
.py {
|
||||
color: var(--color-black-main);
|
||||
}
|
||||
/* NameTag */
|
||||
.nt {
|
||||
color: var(--color-blue-400);
|
||||
}
|
||||
/* NameVariable */
|
||||
.nv {
|
||||
color: var(--color-black-main);
|
||||
}
|
||||
/* NameVariableClass */
|
||||
.vc {
|
||||
color: var(--color-violet-600);
|
||||
}
|
||||
/* NameVariableGlobal */
|
||||
.vg {
|
||||
color: var(--color-violet-600);
|
||||
}
|
||||
/* NameVariableInstance */
|
||||
.vi {
|
||||
color: var(--color-violet-600);
|
||||
}
|
||||
/* NameVariableMagic */
|
||||
.vm {
|
||||
color: var(--color-violet-600);
|
||||
}
|
||||
/* Literal */
|
||||
.l {
|
||||
color: var(--color-black-main);
|
||||
}
|
||||
/* LiteralDate */
|
||||
.ld {
|
||||
color: var(--color-black-main);
|
||||
}
|
||||
/* LiteralString */
|
||||
.s {
|
||||
color: var(--color-black-main);
|
||||
}
|
||||
/* LiteralStringAffix */
|
||||
.sa {
|
||||
color: var(--color-green-700);
|
||||
}
|
||||
/* LiteralStringBacktick */
|
||||
.sb {
|
||||
color: var(--color-green-700);
|
||||
}
|
||||
/* LiteralStringChar */
|
||||
.sc {
|
||||
color: var(--color-green-700);
|
||||
}
|
||||
/* LiteralStringDelimiter */
|
||||
.dl {
|
||||
color: var(--color-green-700);
|
||||
}
|
||||
/* LiteralStringDoc */
|
||||
.sd {
|
||||
color: #8f5902;
|
||||
}
|
||||
/* LiteralStringDouble */
|
||||
.s2 {
|
||||
color: var(--color-green-700);
|
||||
}
|
||||
/* LiteralStringEscape */
|
||||
.se {
|
||||
color: var(--color-black-main);
|
||||
}
|
||||
/* LiteralStringHeredoc */
|
||||
.sh {
|
||||
color: var(--color-green-700);
|
||||
}
|
||||
/* LiteralStringInterpol */
|
||||
.si {
|
||||
color: var(--color-green-700);
|
||||
}
|
||||
/* LiteralStringOther */
|
||||
.sx {
|
||||
color: var(--color-green-700);
|
||||
}
|
||||
/* LiteralStringRegex */
|
||||
.sr {
|
||||
color: var(--color-blue-500);
|
||||
}
|
||||
/* LiteralStringSingle */
|
||||
.s1 {
|
||||
color: var(--color-green-700);
|
||||
}
|
||||
/* LiteralStringSymbol */
|
||||
.ss {
|
||||
color: var(--color-green-700);
|
||||
}
|
||||
/* LiteralNumber */
|
||||
.m {
|
||||
color: var(--color-blue-500);
|
||||
}
|
||||
/* LiteralNumberBin */
|
||||
.mb {
|
||||
color: var(--color-blue-500);
|
||||
}
|
||||
/* LiteralNumberFloat */
|
||||
.mf {
|
||||
color: var(--color-blue-500);
|
||||
}
|
||||
/* LiteralNumberHex */
|
||||
.mh {
|
||||
color: var(--color-blue-500);
|
||||
}
|
||||
/* LiteralNumberInteger */
|
||||
.mi {
|
||||
color: var(--color-blue-500);
|
||||
}
|
||||
/* LiteralNumberIntegerLong */
|
||||
.il {
|
||||
color: var(--color-blue-500);
|
||||
}
|
||||
/* LiteralNumberOct */
|
||||
.mo {
|
||||
color: var(--color-blue-500);
|
||||
}
|
||||
/* Operator */
|
||||
.o {
|
||||
color: var(--color-blue-400);
|
||||
}
|
||||
/* OperatorWord */
|
||||
.ow {
|
||||
color: var(--color-yellow-700);
|
||||
}
|
||||
/* Punctuation */
|
||||
.p {
|
||||
color: var(--color-gray-400);
|
||||
}
|
||||
/* Comment */
|
||||
.c {
|
||||
color: var(--color-gray-400);
|
||||
}
|
||||
/* CommentHashbang */
|
||||
.ch {
|
||||
color: var(--color-gray-400);
|
||||
}
|
||||
/* CommentMultiline */
|
||||
.cm {
|
||||
color: var(--color-gray-400);
|
||||
}
|
||||
/* CommentSingle */
|
||||
.c1 {
|
||||
color: var(--color-gray-400);
|
||||
}
|
||||
/* CommentSpecial */
|
||||
.cs {
|
||||
color: var(--color-gray-400);
|
||||
}
|
||||
/* CommentPreproc */
|
||||
.cp {
|
||||
color: var(--color-gray-400);
|
||||
}
|
||||
/* CommentPreprocFile */
|
||||
.cpf {
|
||||
color: var(--color-gray-400);
|
||||
}
|
||||
/* Generic */
|
||||
.g {
|
||||
color: var(--color-black-main);
|
||||
}
|
||||
/* GenericDeleted */
|
||||
.gd {
|
||||
color: var(--color-red-500);
|
||||
}
|
||||
/* GenericEmph */
|
||||
.ge {
|
||||
color: var(--color-black-main);
|
||||
}
|
||||
/* GenericError */
|
||||
.gr {
|
||||
color: var(--color-red-500);
|
||||
}
|
||||
/* GenericHeading */
|
||||
.gh {
|
||||
color: var(--color-gray-600);
|
||||
}
|
||||
/* GenericInserted */
|
||||
.gi {
|
||||
color: var(--color-green-500);
|
||||
}
|
||||
/* GenericOutput */
|
||||
.go {
|
||||
color: var(--color-black-main);
|
||||
}
|
||||
/* GenericPrompt */
|
||||
.gp {
|
||||
user-select: none;
|
||||
color: var(--color-green-400);
|
||||
}
|
||||
/* GenericStrong */
|
||||
.gs {
|
||||
color: var(--color-black-main);
|
||||
}
|
||||
/* GenericSubheading */
|
||||
.gu {
|
||||
color: var(--color-gray-600);
|
||||
}
|
||||
/* GenericTraceback */
|
||||
.gt {
|
||||
color: var(--color-red-500);
|
||||
}
|
||||
/* GenericUnderline */
|
||||
.gl {
|
||||
color: var(--color-black-main);
|
||||
text-decoration: underline;
|
||||
}
|
||||
/* TextWhitespace */
|
||||
.w {
|
||||
color: var(--color-gray-100);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,203 @@
|
|||
@theme inline {
|
||||
--font-sans: "roboto flex", sans-serif;
|
||||
--font-mono: "roboto flex mono", ui-monospace, SFMono-Regular, monospace;
|
||||
--default-font-family: var(--font-sans);
|
||||
|
||||
--text-xs: 0.7143rem;
|
||||
--text-xs--letter-spacing: 0.015em;
|
||||
--text-xs--font-weight: 500;
|
||||
--text-sm: 0.851rem;
|
||||
--text-base: 14px;
|
||||
--text-lg: 1.1429rem;
|
||||
--text-lg--line-height: 1.75;
|
||||
--text-xl: 1.2857rem;
|
||||
--text-xl--letter-spacing: -0.015em;
|
||||
--text-xl--font-weight: 500;
|
||||
--text-2xl: 1.5rem;
|
||||
--text-2xl--letter-spacing: -0.015em;
|
||||
--text-2xl--font-weight: 500;
|
||||
--text-3xl: 2rem;
|
||||
--text-3xl--font-weight: 500;
|
||||
--text-4xl: 2.5rem;
|
||||
--text-4xl--letter-spacing: -0.015em;
|
||||
--text-4xl--font-weight: 500;
|
||||
|
||||
--color-background-light: #f9f9fa;
|
||||
--color-background-dark: #10151b;
|
||||
--color-primary-blue: var(--color-blue);
|
||||
|
||||
--color-divider-light: hsla(0, 0%, 0%, 0.1);
|
||||
--color-divider-dark: hsla(0, 0%, 100%, 0.05);
|
||||
|
||||
--card-bg-dark: #1d262d;
|
||||
--card-border-dark: #516980;
|
||||
--card-bg-dark: var(--color-gray-900);
|
||||
--card-border-dark: var(--color-gray-700);
|
||||
|
||||
--color-navbar-bg: var(--color-background-light);
|
||||
--color-navbar-bg-dark: var(--color-background-dark);
|
||||
--color-navbar-text: var(--color-gray-700);
|
||||
--color-navbar-text-dark: var(--tw-prose-body);
|
||||
--color-navbar-border-color-light: var(--tw-prose-inverse-body);
|
||||
--navbar-font-size: 1rem;
|
||||
--navbar-group-font-title-size: 1rem;
|
||||
--color-navbar-text-dark: var(--color-gray-200);
|
||||
--color-navbar-group-text-dark: var(--tw-prose-body);
|
||||
|
||||
--color-blue: var(--color-blue-400);
|
||||
--color-blue-100: rgba(217, 229, 252, 1);
|
||||
--color-blue-200: rgba(170, 196, 248, 1);
|
||||
--color-blue-300: rgba(123, 164, 244, 1);
|
||||
--color-blue-400: rgba(75, 131, 241, 1);
|
||||
--color-blue-50: rgba(246, 248, 254, 1);
|
||||
--color-blue-500: rgba(37, 96, 255, 1);
|
||||
--color-blue-600: rgba(13, 77, 242, 1);
|
||||
--color-blue-700: rgba(0, 61, 181, 1);
|
||||
--color-blue-800: rgba(0, 41, 120, 1);
|
||||
--color-blue-900: rgba(0, 29, 86, 1);
|
||||
--color-blue-950: rgba(0, 21, 60, 1);
|
||||
--color-blue-focus: rgba(37, 96, 255, 0.24);
|
||||
--color-blue-focusvisible: rgba(37, 96, 255, 0.32);
|
||||
--color-blue-hover: rgba(37, 96, 255, 0.12);
|
||||
--color-blue-outlinedborder: rgba(37, 96, 255, 0.56);
|
||||
--color-blue-selected: rgba(37, 96, 255, 0.16);
|
||||
|
||||
--color-gray: var(--color-gray-600);
|
||||
--color-gray-100: rgba(231, 234, 239, 1);
|
||||
--color-gray-200: rgba(200, 207, 218, 1);
|
||||
--color-gray-300: rgba(169, 180, 198, 1);
|
||||
--color-gray-400: rgba(139, 153, 178, 1);
|
||||
--color-gray-50: rgba(249, 250, 251, 1);
|
||||
--color-gray-500: rgba(108, 126, 157, 1);
|
||||
--color-gray-600: rgba(86, 101, 129, 1);
|
||||
--color-gray-700: rgba(67, 76, 95, 1);
|
||||
--color-gray-800: rgba(44, 51, 63, 1);
|
||||
--color-gray-900: rgba(30, 33, 41, 1);
|
||||
--color-gray-950: rgb(18, 21, 31);
|
||||
--color-gray-focus: rgba(108, 126, 157, 0.24);
|
||||
--color-gray-focusvisible: rgba(108, 126, 157, 0.32);
|
||||
--color-gray-hover: rgba(108, 126, 157, 0.12);
|
||||
--color-gray-outlinedborder: rgba(108, 126, 157, 0.56);
|
||||
--color-gray-selected: rgba(108, 126, 157, 0.16);
|
||||
|
||||
--color-green-100: rgba(235, 249, 238, 1);
|
||||
--color-green-200: rgba(208, 241, 215, 1);
|
||||
--color-green-300: rgba(169, 229, 189, 1);
|
||||
--color-green-400: rgba(129, 217, 162, 1);
|
||||
--color-green-50: rgba(245, 252, 247, 1);
|
||||
--color-green-500: rgba(90, 206, 140, 1);
|
||||
--color-green-600: rgba(56, 189, 125, 1);
|
||||
--color-green-700: rgba(45, 149, 104, 1);
|
||||
--color-green-800: rgba(33, 110, 75, 1);
|
||||
--color-green-900: rgba(23, 75, 50, 1);
|
||||
--color-green-950: rgba(17, 55, 26, 1);
|
||||
--color-green-focus: rgba(56, 189, 125, 0.24);
|
||||
--color-green-focusvisible: rgba(56, 189, 125, 0.32);
|
||||
--color-green-hover: rgba(56, 189, 125, 0.12);
|
||||
--color-green-outlinedborder: rgba(56, 189, 125, 0.56);
|
||||
--color-green-selected: rgba(56, 189, 125, 0.16);
|
||||
|
||||
--color-orange-100: rgba(255, 233, 217, 1);
|
||||
--color-orange-200: rgba(255, 216, 187, 1);
|
||||
--color-orange-300: rgba(255, 196, 153, 1);
|
||||
--color-orange-400: rgba(255, 169, 107, 1);
|
||||
--color-orange-50: rgba(255, 249, 245, 1);
|
||||
--color-orange-500: rgba(255, 135, 49, 1);
|
||||
--color-orange-600: rgba(255, 107, 0, 1);
|
||||
--color-orange-700: rgba(218, 92, 0, 1);
|
||||
--color-orange-800: rgba(173, 72, 0, 1);
|
||||
--color-orange-900: rgba(137, 58, 1, 1);
|
||||
--color-orange-950: rgba(94, 40, 0, 1);
|
||||
--color-orange-focus: rgba(255, 107, 0, 0.24);
|
||||
--color-orange-focusvisible: rgba(255, 107, 0, 0.32);
|
||||
--color-orange-hover: rgba(255, 107, 0, 0.12);
|
||||
--color-orange-outlinedborder: rgba(255, 107, 0, 0.56);
|
||||
--color-orange-selected: rgba(255, 107, 0, 0.16);
|
||||
|
||||
--color-pink-100: rgba(255, 230, 251, 1);
|
||||
--color-pink-200: rgba(255, 201, 246, 1);
|
||||
--color-pink-300: rgba(255, 166, 240, 1);
|
||||
--color-pink-400: rgba(252, 113, 220, 1);
|
||||
--color-pink-50: rgba(255, 247, 254, 1);
|
||||
--color-pink-500: rgba(237, 73, 199, 1);
|
||||
--color-pink-600: rgba(201, 24, 171, 1);
|
||||
--color-pink-700: rgba(171, 0, 137, 1);
|
||||
--color-pink-800: rgba(131, 0, 105, 1);
|
||||
--color-pink-900: rgba(109, 0, 81, 1);
|
||||
--color-pink-950: rgba(85, 0, 51, 1);
|
||||
--color-pink-focus: rgba(201, 24, 171, 0.24);
|
||||
--color-pink-focusvisible: rgba(201, 24, 171, 0.32);
|
||||
--color-pink-hover: rgba(201, 24, 171, 0.12);
|
||||
--color-pink-outlinedborder: rgba(201, 24, 171, 0.56);
|
||||
--color-pink-selected: rgba(201, 24, 171, 0.16);
|
||||
|
||||
--color-red-100: rgba(255, 223, 223, 1);
|
||||
--color-red-200: rgba(255, 194, 194, 1);
|
||||
--color-red-300: rgba(255, 168, 168, 1);
|
||||
--color-red-400: rgba(255, 117, 117, 1);
|
||||
--color-red-50: rgba(255, 245, 245, 1);
|
||||
--color-red-500: rgba(255, 87, 87, 1);
|
||||
--color-red-600: rgba(244, 47, 57, 1);
|
||||
--color-red-700: rgba(228, 12, 44, 1);
|
||||
--color-red-800: rgba(179, 9, 9, 1);
|
||||
--color-red-900: rgba(137, 0, 0, 1);
|
||||
--color-red-950: rgba(110, 0, 0, 1);
|
||||
--color-red-focus: rgba(244, 47, 57, 0.24);
|
||||
--color-red-focusvisible: rgba(244, 47, 57, 0.32);
|
||||
--color-red-hover: rgba(244, 47, 57, 0.12);
|
||||
--color-red-outlinedborder: rgba(244, 47, 57, 0.56);
|
||||
--color-red-selected: rgba(244, 47, 57, 0.16);
|
||||
|
||||
--color-teal-100: rgba(223, 246, 246, 1);
|
||||
--color-teal-200: rgba(195, 240, 241, 1);
|
||||
--color-teal-300: rgba(160, 229, 232, 1);
|
||||
--color-teal-400: rgba(106, 220, 222, 1);
|
||||
--color-teal-50: rgba(243, 252, 252, 1);
|
||||
--color-teal-500: rgba(47, 208, 210, 1);
|
||||
--color-teal-600: rgba(27, 189, 191, 1);
|
||||
--color-teal-700: rgba(44, 158, 160, 1);
|
||||
--color-teal-800: rgba(24, 116, 115, 1);
|
||||
--color-teal-900: rgba(18, 85, 85, 1);
|
||||
--color-teal-950: rgba(9, 61, 61, 1);
|
||||
--color-teal-focus: rgba(27, 189, 191, 0.24);
|
||||
--color-teal-focusvisible: rgba(27, 189, 191, 0.32);
|
||||
--color-teal-hover: rgba(27, 189, 191, 0.12);
|
||||
--color-teal-outlinedborder: rgba(27, 189, 191, 0.56);
|
||||
--color-teal-selected: rgba(27, 189, 191, 0.16);
|
||||
|
||||
--color-violet: var(--color-violet-500);
|
||||
--color-violet-100: rgba(239, 224, 255, 1);
|
||||
--color-violet-200: rgba(211, 183, 255, 1);
|
||||
--color-violet-300: rgba(174, 130, 255, 1);
|
||||
--color-violet-400: rgba(152, 96, 255, 1);
|
||||
--color-violet-50: rgba(252, 249, 255, 1);
|
||||
--color-violet-500: rgba(125, 46, 255, 1);
|
||||
--color-violet-600: rgba(109, 0, 235, 1);
|
||||
--color-violet-700: rgba(87, 0, 187, 1);
|
||||
--color-violet-800: rgba(69, 0, 147, 1);
|
||||
--color-violet-900: rgba(55, 0, 118, 1);
|
||||
--color-violet-950: rgba(37, 0, 80, 1);
|
||||
--color-violet-focus: rgba(125, 46, 255, 0.24);
|
||||
--color-violet-focusvisible: rgba(125, 46, 255, 0.32);
|
||||
--color-violet-hover: rgba(125, 46, 255, 0.12);
|
||||
--color-violet-outlinedborder: rgba(125, 46, 255, 0.56);
|
||||
--color-violet-selected: rgba(125, 46, 255, 0.16);
|
||||
|
||||
--color-white-main: rgba(255, 255, 255, 1);
|
||||
--color-yellow-100: rgba(255, 245, 219, 1);
|
||||
--color-yellow-200: rgba(255, 241, 204, 1);
|
||||
--color-yellow-300: rgba(255, 232, 173, 1);
|
||||
--color-yellow-400: rgba(255, 218, 122, 1);
|
||||
--color-yellow-50: rgba(255, 251, 240, 1);
|
||||
--color-yellow-500: rgba(255, 204, 72, 1);
|
||||
--color-yellow-600: rgba(248, 182, 15, 1);
|
||||
--color-yellow-700: rgba(235, 156, 0, 1);
|
||||
--color-yellow-800: rgba(184, 110, 0, 1);
|
||||
--color-yellow-900: rgba(133, 73, 0, 1);
|
||||
--color-yellow-950: rgba(100, 55, 0, 1);
|
||||
--color-yellow-focus: rgba(235, 156, 0, 0.24);
|
||||
--color-yellow-focusvisible: rgba(235, 156, 0, 0.32);
|
||||
--color-yellow-hover: rgba(235, 156, 0, 0.12);
|
||||
--color-yellow-outlinedborder: rgba(235, 156, 0, 0.56);
|
||||
--color-yellow-selected: rgba(235, 156, 0, 0.16);
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
@layer components {
|
||||
#TableOfContents {
|
||||
.toc a {
|
||||
@apply block max-w-full truncate py-1 pl-2 hover:font-medium hover:no-underline;
|
||||
&[aria-current="true"],
|
||||
&:hover {
|
||||
@apply border-l-2 border-l-gray-light bg-gradient-to-r from-gray-light-100 font-medium text-black dark:border-l-gray-dark dark:from-gray-dark-200 dark:text-white;
|
||||
}
|
||||
&:not([aria-current="true"]) {
|
||||
@apply text-gray-light-600 hover:text-black dark:text-gray-dark-700 dark:hover:text-white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
@layer base {
|
||||
|
||||
/*
|
||||
* Font faces for Roboto Flex and Roboto Mono.
|
||||
*
|
||||
* - https://fonts.google.com/specimen/Roboto+Flex
|
||||
* - https://fonts.google.com/specimen/Roboto+Mono
|
||||
*
|
||||
* The TTF fonts have been compressed to woff2,
|
||||
* preserving the latin character subset.
|
||||
*
|
||||
* */
|
||||
|
||||
/* Roboto Flex */
|
||||
@font-face {
|
||||
font-family: 'Roboto Flex';
|
||||
src: url('/assets/fonts/RobotoFlex.woff2') format('woff2');
|
||||
font-weight: 100 1000; /* Range of weights Roboto Flex supports */
|
||||
font-stretch: 100%; /* Range of width Roboto Flex supports */
|
||||
font-style: oblique 0deg 10deg; /* Range of oblique angle Roboto Flex supports */
|
||||
font-display: fallback;
|
||||
}
|
||||
|
||||
/* Roboto Mono */
|
||||
@font-face {
|
||||
font-family: 'Roboto Mono';
|
||||
src: url('/assets/fonts/RobotoMono-Regular.woff2') format('woff2');
|
||||
font-weight: 100 700; /* Define the range of weight the variable font supports */
|
||||
font-style: normal;
|
||||
font-display: fallback;
|
||||
}
|
||||
|
||||
/* Roboto Mono Italic */
|
||||
@font-face {
|
||||
font-family: 'Roboto Mono';
|
||||
src: url('/assets/fonts/RobotoMono-Italic.woff2') format('woff2');
|
||||
font-weight: 100 700; /* Define the range of weight the variable font supports */
|
||||
font-style: italic;
|
||||
font-display: fallback;
|
||||
}
|
||||
|
||||
.prose {
|
||||
li {
|
||||
@apply my-2;
|
||||
> :last-child,
|
||||
> :first-child {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
a {
|
||||
font-weight: 400;
|
||||
}
|
||||
hr {
|
||||
@apply mb-4 mt-8;
|
||||
}
|
||||
h1 {
|
||||
@apply my-4 text-4xl;
|
||||
line-height: 1.167;
|
||||
}
|
||||
h2 {
|
||||
@apply mb-4 mt-8 text-3xl;
|
||||
line-height: 1.2;
|
||||
}
|
||||
h3 {
|
||||
@apply text-2xl;
|
||||
line-height: 1.167;
|
||||
}
|
||||
h4 {
|
||||
@apply text-xl;
|
||||
line-height: 1.235;
|
||||
}
|
||||
h5 {
|
||||
@apply text-lg;
|
||||
line-height: 1.75;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,242 @@
|
|||
@utility icon-svg {
|
||||
svg {
|
||||
font-size: 24px;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
display: inline-block;
|
||||
fill: currentColor;
|
||||
}
|
||||
}
|
||||
|
||||
@utility icon-xs {
|
||||
svg {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@utility icon-sm {
|
||||
svg {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@utility icon-lg {
|
||||
svg {
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
@utility text-primary-blue {
|
||||
color: var(--color-primary-blue);
|
||||
}
|
||||
|
||||
@utility link {
|
||||
@apply text-blue no-underline dark:text-blue-400;
|
||||
font-weight: inherit;
|
||||
&:hover {
|
||||
@apply underline underline-offset-3;
|
||||
}
|
||||
}
|
||||
|
||||
@utility invertible {
|
||||
@apply dark:hue-rotate-180 dark:invert dark:filter;
|
||||
}
|
||||
|
||||
@utility bg-pattern-blue {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
background-image: url("/assets/images/bg-pattern-blue.webp");
|
||||
background-blend-mode: overlay;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
.dark & {
|
||||
background-color: rgba(0, 0, 0, 0.741);
|
||||
}
|
||||
}
|
||||
|
||||
@utility bg-pattern-purple {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
background-image: url("/assets/images/bg-pattern-purple.webp");
|
||||
background-blend-mode: overlay;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
.dark & {
|
||||
background-color: rgba(0, 0, 0, 0.741);
|
||||
}
|
||||
}
|
||||
|
||||
@utility bg-background-toc {
|
||||
background-color: var(--color-navbar-bg);
|
||||
.dark & {
|
||||
background-color: var(--color-navbar-bg-dark);
|
||||
}
|
||||
}
|
||||
|
||||
@utility bg-pattern-verde {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
background-image: url("/assets/images/bg-pattern-verde.webp");
|
||||
background-blend-mode: overlay;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
.dark & {
|
||||
background-color: rgba(0, 0, 0, 0.741);
|
||||
}
|
||||
}
|
||||
|
||||
@utility icon-svg {
|
||||
svg {
|
||||
font-size: 24px;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
display: inline-block;
|
||||
fill: currentColor;
|
||||
}
|
||||
}
|
||||
|
||||
@utility icon-xs {
|
||||
svg {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@utility icon-sm {
|
||||
svg {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@utility icon-lg {
|
||||
svg {
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
@utility navbar-font {
|
||||
font-size: var(--navbar-font-size);
|
||||
color: var(--color-navbar-text);
|
||||
.dark & {
|
||||
color: var(--color-navbar-text-dark);
|
||||
}
|
||||
}
|
||||
|
||||
@utility navbar-group-font-title {
|
||||
font-size: var(--color-navbar-group-font-title-size);
|
||||
@apply font-semibold uppercase;
|
||||
color: var(--color-navbar-text);
|
||||
.dark & {
|
||||
color: var(--color-navbar-text-dark);
|
||||
}
|
||||
}
|
||||
|
||||
@utility prose {
|
||||
.highlight,
|
||||
:not(pre) > code {
|
||||
font-size: 0.875em;
|
||||
border: 1px solid;
|
||||
border-radius: 0.25rem; /* theme("spacing.1") fallback */
|
||||
background: var(--color-white-main);
|
||||
border-color: var(--color-gray-300);
|
||||
.dark & {
|
||||
background: var(--color-gray-200);
|
||||
border-color: var(--color-gray-400);
|
||||
}
|
||||
&::before,
|
||||
&::after {
|
||||
content: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
:not(pre) > code {
|
||||
background: var(--color-gray-200);
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
font-weight: 400;
|
||||
overflow-wrap: anywhere;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
table:not(.lntable) code {
|
||||
overflow-wrap: unset;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Indented code blocks */
|
||||
pre:not(.chroma) {
|
||||
@apply my-4 overflow-x-auto p-3;
|
||||
font-size: 0.875em;
|
||||
border: 1px solid;
|
||||
border-radius: 0.25rem; /* theme("spacing.1") fallback */
|
||||
background: var(--color-white-main);
|
||||
border-color: var(--color-gray-300);
|
||||
.dark & {
|
||||
background: var(--color-gray-200);
|
||||
border-color: var(--color-gray-400);
|
||||
}
|
||||
}
|
||||
|
||||
.highlight {
|
||||
@apply my-4 overflow-x-auto p-3;
|
||||
|
||||
/* LineTableTD */
|
||||
.lntd {
|
||||
vertical-align: top;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-weight: 400;
|
||||
padding: 0 4px;
|
||||
&:first-child {
|
||||
width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* LineTableTD */
|
||||
.lntd {
|
||||
vertical-align: top;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
/* LineTable */
|
||||
.lntable {
|
||||
display: table;
|
||||
width: 100%;
|
||||
border-spacing: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
/* LineNumberColumnHighlight */
|
||||
.lntd:first-child .hl {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@utility section-card {
|
||||
@apply flex h-full flex-col gap-2 rounded-sm border p-4 drop-shadow-xs hover:drop-shadow-lg;
|
||||
@apply text-gray dark:text-gray-200;
|
||||
@apply border-gray-100 bg-gray-50 hover:border-gray-200 dark:border-gray-600 dark:bg-gray-900 hover:dark:border-gray-500;
|
||||
}
|
||||
|
||||
@utility section-card-text {
|
||||
@apply leading-snug text-gray-800 dark:text-gray-200;
|
||||
}
|
||||
@utility section-card-title {
|
||||
@apply text-xl font-semibold text-gray-900 dark:text-gray-100;
|
||||
}
|
||||
|
||||
@utility sub-button {
|
||||
@apply flex w-full items-start gap-2 rounded-sm px-2 py-2 text-left text-gray-700 transition-colors hover:bg-gray-50 dark:text-gray-100 dark:hover:bg-gray-800;
|
||||
}
|
||||
|
||||
@utility toc {
|
||||
a {
|
||||
@apply block max-w-full truncate py-1 pl-2 hover:font-medium hover:no-underline;
|
||||
&[aria-current="true"],
|
||||
&:hover {
|
||||
@apply border-l-2 border-x-gray-200 bg-gradient-to-r from-gray-50 font-medium text-black dark:border-l-gray-300 dark:from-gray-900 dark:text-white;
|
||||
}
|
||||
&:not([aria-current="true"]) {
|
||||
@apply text-gray-600 hover:text-black dark:text-gray-100 dark:hover:text-white;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="blue" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="mask0_26_122" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="24" height="24">
|
||||
<path d="M17.9549 21.7542C16.8041 22.871 15.5344 22.6969 14.3241 22.1703C13.0373 21.6331 11.861 21.5991 10.5021 22.1703C8.80981 22.9007 7.91165 22.6884 6.89246 21.7542C1.13826 15.8301 1.98759 6.80604 8.52741 6.46631C10.1135 6.55125 11.224 7.34324 12.1583 7.40906C13.5469 7.12666 14.8761 6.31768 16.3625 6.42385C18.1482 6.56823 19.4837 7.27317 20.3755 8.54079C16.7022 10.749 17.5728 15.5902 20.9467 16.9491C20.2715 18.7221 19.4052 20.4738 17.9528 21.769L17.9549 21.7542ZM12.0309 6.40261C11.8589 3.76971 13.9928 1.60393 16.4474 1.3916C16.785 4.42794 13.6871 6.69988 12.0309 6.40261Z" fill="currentColor"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_26_122)">
|
||||
<rect width="24" height="24" fill="currentColor" fill-opacity="0.9"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 931 B |
Before Width: | Height: | Size: 613 B After Width: | Height: | Size: 613 B |
After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 732 B After Width: | Height: | Size: 732 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
@ -0,0 +1,8 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="mask0_26_117" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="24" height="24">
|
||||
<path d="M2.8584 11.5731H10.2447V4.31147L2.8584 5.34754V11.5731ZM2.8584 18.6499L10.2447 19.682V12.503H2.8584V18.6499ZM11.0617 4.19737V11.5731H20.89V2.82031L11.0591 4.19737H11.0617ZM11.0617 19.7961L20.89 21.1732V12.5043H11.0591V19.7961H11.0617Z" fill="currentColor"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_26_117)">
|
||||
<rect width="24" height="24" fill="currentColor" fill-opacity="0.9"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 594 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,7 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14.1604 16.8125C14.3454 16.4613 14.8724 16.4613 15.0575 16.8125C15.1827 17.0508 15.2459 17.1704 15.3296 17.2737C15.4038 17.3652 15.49 17.4472 15.5863 17.5178C15.6948 17.5974 15.8201 17.6576 16.0707 17.7768C16.4403 17.9527 16.4403 18.454 16.0707 18.6299C15.8201 18.7491 15.6948 18.8093 15.5863 18.8889C15.49 18.9595 15.4038 19.0415 15.3296 19.133C15.2459 19.2363 15.1827 19.3551 15.0575 19.5933C14.8725 19.9451 14.3453 19.9451 14.1604 19.5933C14.0351 19.3551 13.9719 19.2363 13.8882 19.133C13.814 19.0415 13.7278 18.9595 13.6315 18.8889C13.523 18.8093 13.3977 18.7491 13.1471 18.6299C12.7774 18.454 12.7775 17.9527 13.1471 17.7768C13.3977 17.6576 13.523 17.5974 13.6315 17.5178C13.7278 17.4472 13.814 17.3652 13.8882 17.2737C13.9719 17.1704 14.0351 17.0508 14.1604 16.8125Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.93855 11.9528C6.18684 11.7089 6.58915 11.7089 6.83747 11.9528L9.10245 14.1805C9.34736 14.4214 9.34724 14.8242 9.10245 15.0652L5.7662 18.3473L5.60021 18.496C4.7982 19.1516 3.64836 19.2319 2.82725 18.5792L2.65672 18.4278C1.83844 17.6224 1.78233 16.2321 2.50252 15.3495L2.65672 15.1807L5.93855 11.9528ZM3.85044 16.3094C3.61193 16.544 3.61271 17.0649 3.85044 17.299L3.9221 17.3568C3.99403 17.404 4.06853 17.4204 4.14887 17.4172C4.27136 17.4121 4.4317 17.3561 4.57248 17.2177L7.21028 14.6224L6.38755 13.8139L3.85044 16.3094Z" fill="currentColor"/>
|
||||
<path d="M18.508 14.7449C18.693 14.3936 19.22 14.3936 19.4051 14.7449C19.5304 14.9832 19.5936 15.1028 19.6772 15.206C19.7514 15.2976 19.8377 15.3796 19.9339 15.4502C20.0425 15.5297 20.168 15.5892 20.4183 15.7083C20.7882 15.8842 20.7882 16.3864 20.4183 16.5623C20.1679 16.6814 20.0425 16.7409 19.9339 16.8204C19.8376 16.891 19.7515 16.9738 19.6772 17.0654C19.5936 17.1686 19.5303 17.2875 19.4051 17.5257C19.2202 17.8774 18.6929 17.8774 18.508 17.5257C18.3828 17.2874 18.3195 17.1686 18.2359 17.0654C18.1616 16.9738 18.0755 16.891 17.9792 16.8204C17.8707 16.7409 17.7451 16.6813 17.4948 16.5623C17.1251 16.3863 17.125 15.8841 17.4948 15.7083C17.7453 15.5891 17.8706 15.5297 17.9792 15.4502C18.0754 15.3796 18.1617 15.2976 18.2359 15.206C18.3196 15.1028 18.3827 14.9832 18.508 14.7449Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.53683 4.30615C8.19308 4.17877 8.90012 4.10059 9.56507 4.16702C10.2334 4.23384 10.9066 4.45295 11.4264 4.96415L14.4461 7.93477C14.7509 8.23479 14.5896 8.6711 14.5241 9.03377C14.9209 9.07759 15.5454 9.01593 15.853 9.31815L17.4658 10.9045C17.6126 11.049 17.6788 11.2555 17.6426 11.4567L17.4249 12.6607L17.4005 12.7534C17.3693 12.8432 17.3177 12.9254 17.249 12.9932L15.3269 14.884L15.2534 14.9462C15.1753 15.0024 15.0847 15.0405 14.9885 15.0573L13.7649 15.2708L13.6878 15.2795C13.5343 15.2877 13.3826 15.2414 13.2614 15.1483L13.2034 15.0975L11.5897 13.5103C11.4029 13.3261 11.4006 13.0743 11.3729 12.8322L10.9012 13.2959C10.6528 13.5399 10.2506 13.54 10.0023 13.2959L7.73729 11.0682C7.43105 10.7667 7.54835 10.3692 7.81893 10.103L7.97041 8.8754L6.9055 8.72577C6.80325 8.71138 6.70638 8.67262 6.6234 8.61377L6.54539 8.54902L4.14343 6.18565C3.79161 5.83906 3.97995 5.22677 4.46817 5.1304C5.3554 4.90181 6.24072 4.59734 7.14678 4.38927L7.53683 4.30615ZM9.39272 5.7709C9.07191 5.73885 8.69879 5.75781 8.2888 5.8164L7.8661 5.88727C7.43972 5.97006 7.00368 6.0878 6.52543 6.2259L7.4942 7.1779L8.2117 7.2794L8.37588 7.3109C9.18373 7.50483 9.73066 8.25226 9.63038 9.06615L9.47889 10.2938C9.47241 10.3462 9.46246 10.3983 9.45077 10.4495L10.4839 11.4663C10.9068 11.2103 11.4341 11.1464 11.9189 11.3079C12.5185 11.5079 12.947 12.0182 13.0292 12.623L14.0107 13.5882L14.3635 13.5269L15.8312 12.0832L15.9056 11.6737L14.8869 10.6709C14.8569 10.6693 14.8222 10.6665 14.7817 10.6648C14.7283 10.6625 14.6555 10.6599 14.5858 10.656L14.3336 10.6359C13.8765 10.5853 13.4609 10.3551 13.1852 9.99978C12.9097 9.64421 12.7979 9.19376 12.8768 8.7564L12.8868 8.7039L10.2327 6.0929C10.0903 5.95302 9.87595 5.84351 9.5433 5.79015L9.39272 5.7709Z" fill="currentColor"/>
|
||||
<path d="M18.7184 6.60652C18.9958 6.07886 19.7872 6.07886 20.0646 6.60652C20.2524 6.96391 20.3463 7.14291 20.4718 7.29777C20.5832 7.43517 20.7129 7.55849 20.8573 7.6644C21.0201 7.78372 21.2084 7.87255 21.5839 8.05115C22.1387 8.31498 22.1387 9.06832 21.5839 9.33215C21.2082 9.51082 21.0202 9.6004 20.8573 9.71977C20.7129 9.82568 20.5832 9.94902 20.4718 10.0864C20.3464 10.2412 20.2524 10.4204 20.0646 10.7777C19.7871 11.3049 18.9959 11.3049 18.7184 10.7777C18.5306 10.4204 18.4366 10.2412 18.3112 10.0864C18.1998 9.94903 18.0701 9.82568 17.9257 9.71977C17.7628 9.60041 17.5748 9.51082 17.1991 9.33215C16.6443 9.06832 16.6443 8.31498 17.1991 8.05115C17.5746 7.87254 17.7629 7.78373 17.9257 7.6644C18.0701 7.55848 18.1998 7.43517 18.3112 7.29777C18.4367 7.14291 18.5306 6.96392 18.7184 6.60652Z" fill="currentColor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 4.8 KiB |
|
@ -0,0 +1,8 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="mask0_5432_2123" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="1" y="1" width="22" height="22">
|
||||
<path d="M18 10.0001L14 6.00006M2.5 21.5001L5.88437 21.124C6.29786 21.0781 6.5046 21.0551 6.69785 20.9925C6.86929 20.937 7.03245 20.8586 7.18289 20.7594C7.35245 20.6476 7.49955 20.5005 7.79373 20.2063L21 7.00006C22.1046 5.89549 22.1046 4.10463 21 3.00006C19.8955 1.89549 18.1046 1.89549 17 3.00006L3.79373 16.2063C3.49955 16.5005 3.35246 16.6476 3.24064 16.8172C3.14143 16.9676 3.06301 17.1308 3.00751 17.3022C2.94496 17.4955 2.92198 17.7022 2.87604 18.1157L2.5 21.5001Z" stroke="#6C7E9D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_5432_2123)">
|
||||
<rect width="24" height="24" fill="currentColor" fill-opacity="0.9"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 888 B |
|
@ -0,0 +1,8 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="mask0_5432_1323" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="1" y="2" width="21" height="21">
|
||||
<path d="M12 10.5V7M12 14H12.01M7 18V20.3355C7 20.8684 7 21.1348 7.10923 21.2716C7.20422 21.3906 7.34827 21.4599 7.50054 21.4597C7.67563 21.4595 7.88367 21.2931 8.29976 20.9602L10.6852 19.0518C11.1725 18.662 11.4162 18.4671 11.6875 18.3285C11.9282 18.2055 12.1844 18.1156 12.4492 18.0613C12.7477 18 13.0597 18 13.6837 18H16.2C17.8802 18 18.7202 18 19.362 17.673C19.9265 17.3854 20.3854 16.9265 20.673 16.362C21 15.7202 21 14.8802 21 13.2V7.8C21 6.11984 21 5.27976 20.673 4.63803C20.3854 4.07354 19.9265 3.6146 19.362 3.32698C18.7202 3 17.8802 3 16.2 3H7.8C6.11984 3 5.27976 3 4.63803 3.32698C4.07354 3.6146 3.6146 4.07354 3.32698 4.63803C3 5.27976 3 6.11984 3 7.8V14C3 14.93 3 15.395 3.10222 15.7765C3.37962 16.8117 4.18827 17.6204 5.22354 17.8978C5.60504 18 6.07003 18 7 18Z" stroke="#6C7E9D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_5432_1323)">
|
||||
<rect width="24" height="24" fill="currentColor" fill-opacity="0.9"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
|
@ -31,27 +31,25 @@ section and choose the best installation path for you.
|
|||
> employees OR more than $10 million USD in annual revenue) requires a [paid
|
||||
> subscription](https://www.docker.com/pricing/).
|
||||
|
||||
<div class="not-prose">
|
||||
{{< card
|
||||
title="Docker Desktop for Mac"
|
||||
description="A native application using the macOS sandbox security model that delivers all Docker tools to your Mac."
|
||||
link="/desktop/setup/install/mac-install/"
|
||||
icon="/assets/images/apple_48.svg" >}}
|
||||
|
||||
<br>
|
||||
icon="/icons/AppleMac.svg" >}}
|
||||
|
||||
{{< card
|
||||
title="Docker Desktop for Windows"
|
||||
description="A native Windows application that delivers all Docker tools to your Windows computer."
|
||||
link="/desktop/setup/install/windows-install/"
|
||||
icon="/assets/images/windows_48.svg" >}}
|
||||
|
||||
<br>
|
||||
icon="/icons/Windows.svg" >}}
|
||||
|
||||
{{< card
|
||||
title="Docker Desktop for Linux"
|
||||
description="A native Linux application that delivers all Docker tools to your Linux computer."
|
||||
link="/desktop/setup/install/linux/"
|
||||
icon="/assets/images/linux_48.svg" >}}
|
||||
icon="/icons/Linux.svg" >}}
|
||||
</div>
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
|
|
|
@ -29,21 +29,18 @@ This guide will walk you through the installation process, enabling you to exper
|
|||
{{< card
|
||||
title="Docker Desktop for Mac"
|
||||
description="[Download (Apple Silicon)](https://desktop.docker.com/mac/main/arm64/Docker.dmg?utm_source=docker&utm_medium=webreferral&utm_campaign=docs-driven-download-mac-arm64) | [Download (Intel)](https://desktop.docker.com/mac/main/amd64/Docker.dmg?utm_source=docker&utm_medium=webreferral&utm_campaign=docs-driven-download-mac-amd64) | [Install instructions](/desktop/setup/install/mac-install)"
|
||||
icon="/assets/images/apple_48.svg" >}}
|
||||
|
||||
<br>
|
||||
icon="/icons/AppleMac.svg" >}}
|
||||
|
||||
{{< card
|
||||
title="Docker Desktop for Windows"
|
||||
description="[Download](https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe?utm_source=docker&utm_medium=webreferral&utm_campaign=docs-driven-download-windows) | [Install instructions](/desktop/setup/install/windows-install)"
|
||||
icon="/assets/images/windows_48.svg" >}}
|
||||
|
||||
<br>
|
||||
icon="/icons/Windows.svg" >}}
|
||||
|
||||
{{< card
|
||||
title="Docker Desktop for Linux"
|
||||
description="[Install instructions](/desktop/setup/install/linux/)"
|
||||
icon="/assets/images/linux_48.svg" >}}
|
||||
icon="/icons/Linux.svg" >}}
|
||||
|
||||
|
||||
Once it's installed, complete the setup process and you're all set to run a Docker container.
|
||||
|
||||
|
@ -94,4 +91,3 @@ Docker Desktop simplifies container management for developers by streamlining th
|
|||
Now that you have Docker Desktop installed and ran your first container, it's time to start developing with containers.
|
||||
|
||||
{{< button text="Develop with containers" url="develop-with-containers" >}}
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
---
|
||||
title: Angular language-specific guide
|
||||
linkTitle: Angular
|
||||
description: Containerize and develop Angular apps using Docker
|
||||
keywords: getting started, angular, docker, language, Dockerfile
|
||||
summary: |
|
||||
This guide explains how to containerize Angular applications using Docker.
|
||||
toc_min: 1
|
||||
toc_max: 2
|
||||
languages: [js]
|
||||
params:
|
||||
time: 20 minutes
|
||||
|
||||
---
|
||||
|
||||
The Angular language-specific guide shows you how to containerize an Angular application using Docker, following best practices for creating efficient, production-ready containers.
|
||||
|
||||
[Angular](https://angular.dev/) is a robust and widely adopted framework for building dynamic, enterprise-grade web applications. However, managing dependencies, environments, and deployments can become complex as applications scale. Docker streamlines these challenges by offering a consistent, isolated environment for development and production.
|
||||
|
||||
>
|
||||
> **Acknowledgment**
|
||||
>
|
||||
> Docker extends its sincere gratitude to [Kristiyan Velkov](https://www.linkedin.com/in/kristiyan-velkov-763130b3/) for authoring this guide. As a Docker Captain and experienced Front-end engineer, his expertise in Docker, DevOps, and modern web development has made this resource essential for the community, helping developers navigate and optimize their Docker workflows.
|
||||
|
||||
---
|
||||
|
||||
## What will you learn?
|
||||
|
||||
In this guide, you will learn how to:
|
||||
|
||||
- Containerize and run an Angular application using Docker.
|
||||
- Set up a local development environment for Angular inside a container.
|
||||
- Run tests for your Angular application within a Docker container.
|
||||
- Configure a CI/CD pipeline using GitHub Actions for your containerized app.
|
||||
- Deploy the containerized Angular application to a local Kubernetes cluster for testing and debugging.
|
||||
|
||||
You'll start by containerizing an existing Angular application and work your way up to production-level deployments.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, ensure you have a working knowledge of:
|
||||
|
||||
- Basic understanding of [TypeScript](https://www.typescriptlang.org/) and [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript).
|
||||
- Familiarity with [Node.js](https://nodejs.org/en) and [npm](https://docs.npmjs.com/about-npm) for managing dependencies and running scripts.
|
||||
- Familiarity with [Angular](https://angular.io/) fundamentals.
|
||||
- Understanding of core Docker concepts such as images, containers, and Dockerfiles. If you're new to Docker, start with the [Docker basics](/get-started/docker-concepts/the-basics/what-is-a-container.md) guide.
|
||||
|
||||
Once you've completed the Angular getting started modules, you’ll be fully prepared to containerize your own Angular application using the detailed examples and best practices outlined in this guide.
|
|
@ -0,0 +1,323 @@
|
|||
---
|
||||
title: Automate your builds with GitHub Actions
|
||||
linkTitle: Automate your builds with GitHub Actions
|
||||
weight: 60
|
||||
keywords: CI/CD, GitHub( Actions), Angular
|
||||
description: Learn how to configure CI/CD using GitHub Actions for your Angular application.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Complete all the previous sections of this guide, starting with [Containerize an Angular application](containerize.md).
|
||||
|
||||
You must also have:
|
||||
- A [GitHub](https://github.com/signup) account.
|
||||
- A [Docker Hub](https://hub.docker.com/signup) account.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
In this section, you'll set up a CI/CD pipeline using [GitHub Actions](https://docs.github.com/en/actions) to automatically:
|
||||
|
||||
- Build your Angular application inside a Docker container.
|
||||
- Run tests in a consistent environment.
|
||||
- Push the production-ready image to [Docker Hub](https://hub.docker.com).
|
||||
|
||||
---
|
||||
|
||||
## Connect your GitHub repository to Docker Hub
|
||||
|
||||
To enable GitHub Actions to build and push Docker images, you’ll securely store your Docker Hub credentials in your new GitHub repository.
|
||||
|
||||
### Step 1: Generate Docker Hub Credentials and Set GitHub Secrets"
|
||||
|
||||
1. Create a Personal Access Token (PAT) from [Docker Hub](https://hub.docker.com)
|
||||
1. Go to your **Docker Hub account → Account Settings → Security**.
|
||||
2. Generate a new Access Token with **Read/Write** permissions.
|
||||
3. Name it something like `docker-angular-sample`.
|
||||
4. Copy and save the token — you’ll need it in Step 4.
|
||||
|
||||
2. Create a repository in [Docker Hub](https://hub.docker.com/repositories/)
|
||||
1. Go to your **Docker Hub account → Create a repository**.
|
||||
2. For the Repository Name, use something descriptive — for example: `angular-sample`.
|
||||
3. Once created, copy and save the repository name — you’ll need it in Step 4.
|
||||
|
||||
3. Create a new [GitHub repository](https://github.com/new) for your Angular project
|
||||
|
||||
4. Add Docker Hub credentials as GitHub repository secrets
|
||||
|
||||
In your newly created GitHub repository:
|
||||
|
||||
1. Navigate to:
|
||||
**Settings → Secrets and variables → Actions → New repository secret**.
|
||||
|
||||
2. Add the following secrets:
|
||||
|
||||
| Name | Value |
|
||||
|-------------------|--------------------------------|
|
||||
| `DOCKER_USERNAME` | Your Docker Hub username |
|
||||
| `DOCKERHUB_TOKEN` | Your Docker Hub access token (created in Step 1) |
|
||||
| `DOCKERHUB_PROJECT_NAME` | Your Docker Project Name (created in Step 2) |
|
||||
|
||||
These secrets allow GitHub Actions to authenticate securely with Docker Hub during automated workflows.
|
||||
|
||||
5. Connect Your Local Project to GitHub
|
||||
|
||||
Link your local project `docker-angular-sample` to the GitHub repository you just created by running the following command from your project root:
|
||||
|
||||
```console
|
||||
$ git remote set-url origin https://github.com/{your-username}/{your-repository-name}.git
|
||||
```
|
||||
|
||||
>[!IMPORTANT]
|
||||
>Replace `{your-username}` and `{your-repository}` with your actual GitHub username and repository name.
|
||||
|
||||
To confirm that your local project is correctly connected to the remote GitHub repository, run:
|
||||
|
||||
```console
|
||||
$ git remote -v
|
||||
```
|
||||
|
||||
You should see output similar to:
|
||||
|
||||
```console
|
||||
origin https://github.com/{your-username}/{your-repository-name}.git (fetch)
|
||||
origin https://github.com/{your-username}/{your-repository-name}.git (push)
|
||||
```
|
||||
|
||||
This confirms that your local repository is properly linked and ready to push your source code to GitHub.
|
||||
|
||||
6. Push your source code to GitHub
|
||||
|
||||
Follow these steps to commit and push your local project to your GitHub repository:
|
||||
|
||||
1. Stage all files for commit.
|
||||
|
||||
```console
|
||||
$ git add -A
|
||||
```
|
||||
This command stages all changes — including new, modified, and deleted files — preparing them for commit.
|
||||
|
||||
|
||||
2. Commit the staged changes with a descriptive message.
|
||||
|
||||
```console
|
||||
$ git commit -m "Initial commit"
|
||||
```
|
||||
This command creates a commit that snapshots the staged changes with a descriptive message.
|
||||
|
||||
3. Push the code to the `main` branch.
|
||||
|
||||
```console
|
||||
$ git push -u origin main
|
||||
```
|
||||
This command pushes your local commits to the `main` branch of the remote GitHub repository and sets the upstream branch.
|
||||
|
||||
Once completed, your code will be available on GitHub, and any GitHub Actions workflow you’ve configured will run automatically.
|
||||
|
||||
> [!NOTE]
|
||||
> Learn more about the Git commands used in this step:
|
||||
> - [Git add](https://git-scm.com/docs/git-add) – Stage changes (new, modified, deleted) for commit
|
||||
> - [Git commit](https://git-scm.com/docs/git-commit) – Save a snapshot of your staged changes
|
||||
> - [Git push](https://git-scm.com/docs/git-push) – Upload local commits to your GitHub repository
|
||||
> - [Git remote](https://git-scm.com/docs/git-remote) – View and manage remote repository URLs
|
||||
|
||||
---
|
||||
|
||||
### Step 2: Set up the workflow
|
||||
|
||||
Now you'll create a GitHub Actions workflow that builds your Docker image, runs tests, and pushes the image to Docker Hub.
|
||||
|
||||
1. Go to your repository on GitHub and select the **Actions** tab in the top menu.
|
||||
|
||||
2. Select **Set up a workflow yourself** when prompted.
|
||||
|
||||
This opens an inline editor to create a new workflow file. By default, it will be saved to:
|
||||
`.github/workflows/main.yml`
|
||||
|
||||
|
||||
3. Add the following workflow configuration to the new file:
|
||||
|
||||
```yaml
|
||||
name: CI/CD – Angular Application with Docker
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
build-test-push:
|
||||
name: Build, Test, and Push Docker Image
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
# 1. Checkout source code
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# 2. Set up Docker Buildx
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
# 3. Cache Docker layers
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildx-
|
||||
|
||||
# 4. Cache npm dependencies
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-npm-
|
||||
|
||||
# 5. Extract metadata
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
run: |
|
||||
echo "REPO_NAME=${GITHUB_REPOSITORY##*/}" >> "$GITHUB_OUTPUT"
|
||||
echo "SHORT_SHA=${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# 6. Build dev Docker image
|
||||
- name: Build Docker image for tests
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: Dockerfile.dev
|
||||
tags: ${{ steps.meta.outputs.REPO_NAME }}-dev:latest
|
||||
load: true
|
||||
cache-from: type=local,src=/tmp/.buildx-cache
|
||||
cache-to: type=local,dest=/tmp/.buildx-cache,mode=max
|
||||
|
||||
# 7. Run Angular tests with Jasmine
|
||||
- name: Run Angular Jasmine tests inside container
|
||||
run: |
|
||||
docker run --rm \
|
||||
--workdir /app \
|
||||
--entrypoint "" \
|
||||
${{ steps.meta.outputs.REPO_NAME }}-dev:latest \
|
||||
sh -c "npm ci && npm run test -- --ci --runInBand"
|
||||
env:
|
||||
CI: true
|
||||
NODE_ENV: test
|
||||
timeout-minutes: 10
|
||||
|
||||
# 8. Log in to Docker Hub
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
# 9. Build and push production image
|
||||
- name: Build and push production image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: Dockerfile
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: |
|
||||
${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKERHUB_PROJECT_NAME }}:latest
|
||||
${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKERHUB_PROJECT_NAME }}:${{ steps.meta.outputs.SHORT_SHA }}
|
||||
cache-from: type=local,src=/tmp/.buildx-cache
|
||||
```
|
||||
|
||||
This workflow performs the following tasks for your Angular application:
|
||||
- Triggers on every `push` or `pull request` targeting the `main` branch.
|
||||
- Builds a development Docker image using `Dockerfile.dev`, optimized for testing.
|
||||
- Executes unit tests using Vitest inside a clean, containerized environment to ensure consistency.
|
||||
- Halts the workflow immediately if any test fails — enforcing code quality.
|
||||
- Caches both Docker build layers and npm dependencies for faster CI runs.
|
||||
- Authenticates securely with Docker Hub using GitHub repository secrets.
|
||||
- Builds a production-ready image using the `prod` stage in `Dockerfile`.
|
||||
- Tags and pushes the final image to Docker Hub with both `latest` and short SHA tags for traceability.
|
||||
|
||||
> [!NOTE]
|
||||
> For more information about `docker/build-push-action`, refer to the [GitHub Action README](https://github.com/docker/build-push-action/blob/master/README.md).
|
||||
|
||||
---
|
||||
|
||||
### Step 3: Run the workflow
|
||||
|
||||
After you've added your workflow file, it's time to trigger and observe the CI/CD process in action.
|
||||
|
||||
1. Commit and push your workflow file
|
||||
|
||||
- Select "Commit changes…" in the GitHub editor.
|
||||
|
||||
- This push will automatically trigger the GitHub Actions pipeline.
|
||||
|
||||
2. Monitor the workflow execution
|
||||
|
||||
- Go to the Actions tab in your GitHub repository.
|
||||
- Click into the workflow run to follow each step: **build**, **test**, and (if successful) **push**.
|
||||
|
||||
3. Verify the Docker image on Docker Hub
|
||||
|
||||
- After a successful workflow run, visit your [Docker Hub repositories](https://hub.docker.com/repositories).
|
||||
- You should see a new image under your repository with:
|
||||
- Repository name: `${your-repository-name}`
|
||||
- Tags include:
|
||||
- `latest` – represents the most recent successful build; ideal for quick testing or deployment.
|
||||
- `<short-sha>` – a unique identifier based on the commit hash, useful for version tracking, rollbacks, and traceability.
|
||||
|
||||
> [!TIP] Protect your main branch
|
||||
> To maintain code quality and prevent accidental direct pushes, enable branch protection rules:
|
||||
> - Navigate to your **GitHub repo → Settings → Branches**.
|
||||
> - Under Branch protection rules, click **Add rule**.
|
||||
> - Specify `main` as the branch name.
|
||||
> - Enable options like:
|
||||
> - *Require a pull request before merging*.
|
||||
> - *Require status checks to pass before merging*.
|
||||
>
|
||||
> This ensures that only tested and reviewed code is merged into `main` branch.
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you set up a complete CI/CD pipeline for your containerized Angular application using GitHub Actions.
|
||||
|
||||
Here's what you accomplished:
|
||||
|
||||
- Created a new GitHub repository specifically for your project.
|
||||
- Generated a secure Docker Hub access token and added it to GitHub as a secret.
|
||||
- Defined a GitHub Actions workflow that:
|
||||
- Build your application inside a Docker container.
|
||||
- Run tests in a consistent, containerized environment.
|
||||
- Push a production-ready image to Docker Hub if tests pass.
|
||||
- Triggered and verified the workflow execution through GitHub Actions.
|
||||
- Confirmed that your image was successfully published to Docker Hub.
|
||||
|
||||
With this setup, your Angular application is now ready for automated testing and deployment across environments — increasing confidence, consistency, and team productivity.
|
||||
|
||||
---
|
||||
|
||||
## Related resources
|
||||
|
||||
Deepen your understanding of automation and best practices for containerized apps:
|
||||
|
||||
- [Introduction to GitHub Actions](/guides/gha.md) – Learn how GitHub Actions automate your workflows
|
||||
- [Docker Build GitHub Actions](/manuals/build/ci/github-actions/_index.md) – Set up container builds with GitHub Actions
|
||||
- [Workflow syntax for GitHub Actions](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions) – Full reference for writing GitHub workflows
|
||||
- [Compose file reference](/compose/compose-file/) – Full configuration reference for `compose.yaml`
|
||||
- [Best practices for writing Dockerfiles](/develop/develop-images/dockerfile_best-practices/) – Optimize your image for performance and security
|
||||
|
||||
---
|
||||
|
||||
## Next steps
|
||||
|
||||
Next, learn how you can locally test and debug your Angular workloads on Kubernetes before deploying. This helps you ensure your application behaves as expected in a production-like environment, reducing surprises during deployment.
|
|
@ -0,0 +1,503 @@
|
|||
---
|
||||
title: Containerize an Angular Application
|
||||
linkTitle: Containerize
|
||||
weight: 10
|
||||
keywords: angular, node, image, initialize, build
|
||||
description: Learn how to containerize an Angular application with Docker by creating an optimized, production-ready image using best practices for performance, security, and scalability.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, make sure the following tools are installed and available on your system:
|
||||
|
||||
- You have installed the latest version of [Docker Desktop](/get-started/get-docker.md).
|
||||
- You have a [git client](https://git-scm.com/downloads). The examples in this section use a command-line based git client, but you can use any client.
|
||||
|
||||
> **New to Docker?**
|
||||
> Start with the [Docker basics](/get-started/docker-concepts/the-basics/what-is-a-container.md) guide to get familiar with key concepts like images, containers, and Dockerfiles.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
This guide walks you through the complete process of containerizing an Angular application with Docker. You’ll learn how to create a production-ready Docker image using best practices that improve performance, security, scalability, and deployment efficiency.
|
||||
|
||||
By the end of this guide, you will:
|
||||
|
||||
- Containerize an Angular application using Docker.
|
||||
- Create and optimize a Dockerfile for production builds.
|
||||
- Use multi-stage builds to minimize image size.
|
||||
- Serve the application efficiently with a custom NGINX configuration.
|
||||
- Build secure and maintainable Docker images by following best practices.
|
||||
|
||||
---
|
||||
|
||||
## Get the sample application
|
||||
|
||||
Clone the sample application to use with this guide. Open a terminal, navigate to the directory where you want to work, and run the following command
|
||||
to clone the git repository:
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/kristiyan-velkov/docker-angular-sample
|
||||
```
|
||||
---
|
||||
|
||||
## Generate a Dockerfile
|
||||
|
||||
Docker provides an interactive CLI tool called `docker init` that helps scaffold the necessary configuration files for containerizing your application. This includes generating a `Dockerfile`, `.dockerignore`, `compose.yaml`, and `README.Docker.md`.
|
||||
|
||||
To begin, navigate to the root of your project directory:
|
||||
|
||||
```console
|
||||
$ cd docker-angular-sample
|
||||
```
|
||||
|
||||
Then run the following command:
|
||||
|
||||
```console
|
||||
$ docker init
|
||||
```
|
||||
You’ll see output similar to:
|
||||
|
||||
```text
|
||||
Welcome to the Docker Init CLI!
|
||||
|
||||
This utility will walk you through creating the following files with sensible defaults for your project:
|
||||
- .dockerignore
|
||||
- Dockerfile
|
||||
- compose.yaml
|
||||
- README.Docker.md
|
||||
|
||||
Let's get started!
|
||||
```
|
||||
|
||||
The CLI will prompt you with a few questions about your app setup.
|
||||
For consistency, please use the same responses shown in the example below when prompted:
|
||||
| Question | Answer |
|
||||
|------------------------------------------------------------|-----------------|
|
||||
| What application platform does your project use? | Node |
|
||||
| What version of Node do you want to use? | 23.11.0-alpine |
|
||||
| Which package manager do you want to use? | npm |
|
||||
| Do you want to run "npm run build" before starting server? | yes |
|
||||
| What directory is your build output to? | dist |
|
||||
| What command do you want to use to start the app? | npm run start |
|
||||
| What port does your server listen on? | 8080 |
|
||||
|
||||
After completion, your project directory will contain the following new files:
|
||||
|
||||
```text
|
||||
├── docker-angular-sample/
|
||||
│ ├── Dockerfile
|
||||
│ ├── .dockerignore
|
||||
│ ├── compose.yaml
|
||||
│ └── README.Docker.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Build the Docker image
|
||||
|
||||
The default Dockerfile generated by `docker init` serves as a solid starting point for general Node.js applications. However, Angular is a front-end framework that compiles into static assets, so we need to tailor the Dockerfile to optimize for how Angular applications are built and served in a production environment.
|
||||
|
||||
### Step 1: Improve the generated Dockerfile and configuration
|
||||
|
||||
In this step, you’ll improve the Dockerfile and configuration files by following best practices:
|
||||
|
||||
- Use multi-stage builds to keep the final image clean and small
|
||||
- Serve the app using NGINX, a fast and secure web server
|
||||
- Improve performance and security by only including what’s needed
|
||||
|
||||
These updates help ensure your app is easy to deploy, fast to load, and production-ready.
|
||||
|
||||
> [!NOTE]
|
||||
> A `Dockerfile` is a plain text file that contains step-by-step instructions to build a Docker image. It automates packaging your application along with its dependencies and runtime environment.
|
||||
> For full details, see the [Dockerfile reference](/reference/dockerfile/).
|
||||
|
||||
|
||||
### Step 2: Configure the Dockerfile
|
||||
|
||||
Copy and replace the contents of your existing `Dockerfile` with the configuration below:
|
||||
|
||||
```dockerfile
|
||||
# =========================================
|
||||
# Stage 1: Build the Angular Application
|
||||
# =========================================
|
||||
# =========================================
|
||||
# Stage 1: Build the Angular Application
|
||||
# =========================================
|
||||
ARG NODE_VERSION=22.14.0-alpine
|
||||
ARG NGINX_VERSION=alpine3.21
|
||||
|
||||
# Use a lightweight Node.js image for building (customizable via ARG)
|
||||
FROM node:${NODE_VERSION} AS builder
|
||||
|
||||
# Set the working directory inside the container
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package-related files first to leverage Docker's caching mechanism
|
||||
COPY package.json package-lock.json ./
|
||||
|
||||
# Install project dependencies using npm ci (ensures a clean, reproducible install)
|
||||
RUN --mount=type=cache,target=/root/.npm npm ci
|
||||
|
||||
# Copy the rest of the application source code into the container
|
||||
COPY . .
|
||||
|
||||
# Build the Angular application
|
||||
RUN npm run build
|
||||
|
||||
# =========================================
|
||||
# Stage 2: Prepare Nginx to Serve Static Files
|
||||
# =========================================
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:${NGINX_VERSION} AS runner
|
||||
|
||||
# Use a built-in non-root user for security best practices
|
||||
USER nginx
|
||||
|
||||
# Copy custom Nginx config
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
|
||||
# Copy the static build output from the build stage to Nginx's default HTML serving directory
|
||||
COPY --chown=nginx:nginx --from=builder /app/dist/*/browser /usr/share/nginx/html
|
||||
|
||||
# Expose port 8080 to allow HTTP traffic
|
||||
# Note: The default NGINX container now listens on port 8080 instead of 80
|
||||
EXPOSE 8080
|
||||
|
||||
# Start Nginx directly with custom config
|
||||
ENTRYPOINT ["nginx", "-c", "/etc/nginx/nginx.conf"]
|
||||
CMD ["-g", "daemon off;"]
|
||||
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> We are using nginx-unprivileged instead of the standard NGINX image to follow security best practices.
|
||||
> Running as a non-root user in the final image:
|
||||
>- Reduces the attack surface
|
||||
>- Aligns with Docker’s recommendations for container hardening
|
||||
>- Helps comply with stricter security policies in production environments
|
||||
|
||||
### Step 3: Configure the .dockerignore file
|
||||
|
||||
The `.dockerignore` file tells Docker which files and folders to exclude when building the image.
|
||||
|
||||
> [!NOTE]
|
||||
>This helps:
|
||||
>- Reduce image size
|
||||
>- Speed up the build process
|
||||
>- Prevent sensitive or unnecessary files (like `.env`, `.git`, or `node_modules`) from being added to the final image.
|
||||
>
|
||||
> To learn more, visit the [.dockerignore reference](/reference/dockerfile.md#dockerignore-file).
|
||||
|
||||
Copy and replace the contents of your existing `.dockerignore` with the configuration below:
|
||||
|
||||
```dockerignore
|
||||
# ================================
|
||||
# Node and build output
|
||||
# ================================
|
||||
node_modules
|
||||
dist
|
||||
out-tsc
|
||||
.angular
|
||||
.cache
|
||||
.tmp
|
||||
|
||||
# ================================
|
||||
# Testing & Coverage
|
||||
# ================================
|
||||
coverage
|
||||
jest
|
||||
cypress
|
||||
cypress/screenshots
|
||||
cypress/videos
|
||||
reports
|
||||
playwright-report
|
||||
.vite
|
||||
.vitepress
|
||||
|
||||
# ================================
|
||||
# Environment & log files
|
||||
# ================================
|
||||
*.env*
|
||||
!*.env.production
|
||||
*.log
|
||||
*.tsbuildinfo
|
||||
|
||||
# ================================
|
||||
# IDE & OS-specific files
|
||||
# ================================
|
||||
.vscode
|
||||
.idea
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
*.swp
|
||||
|
||||
# ================================
|
||||
# Version control & CI files
|
||||
# ================================
|
||||
.git
|
||||
.gitignore
|
||||
|
||||
# ================================
|
||||
# Docker & local orchestration
|
||||
# ================================
|
||||
Dockerfile
|
||||
Dockerfile.*
|
||||
.dockerignore
|
||||
docker-compose.yml
|
||||
docker-compose*.yml
|
||||
|
||||
# ================================
|
||||
# Miscellaneous
|
||||
# ================================
|
||||
*.bak
|
||||
*.old
|
||||
*.tmp
|
||||
```
|
||||
|
||||
### Step 4: Create the `nginx.conf` file
|
||||
|
||||
To serve your Angular application efficiently inside the container, you’ll configure NGINX with a custom setup. This configuration is optimized for performance, browser caching, gzip compression, and support for client-side routing.
|
||||
|
||||
Create a file named `nginx.conf` in the root of your project directory, and add the following content:
|
||||
|
||||
> [!NOTE]
|
||||
> To learn more about configuring NGINX, see the [official NGINX documentation](https://nginx.org/en/docs/).
|
||||
|
||||
|
||||
```nginx
|
||||
worker_processes auto;
|
||||
|
||||
pid /tmp/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
# Logging
|
||||
access_log off;
|
||||
error_log /dev/stderr warn;
|
||||
|
||||
# Performance
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
keepalive_requests 1000;
|
||||
|
||||
# Compression
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_proxied any;
|
||||
gzip_min_length 256;
|
||||
gzip_comp_level 6;
|
||||
gzip_types
|
||||
text/plain
|
||||
text/css
|
||||
text/xml
|
||||
text/javascript
|
||||
application/javascript
|
||||
application/x-javascript
|
||||
application/json
|
||||
application/xml
|
||||
application/xml+rss
|
||||
font/ttf
|
||||
font/otf
|
||||
image/svg+xml;
|
||||
|
||||
server {
|
||||
listen 8080;
|
||||
server_name localhost;
|
||||
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
# Angular Routing
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# Static Assets Caching
|
||||
location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|map)$ {
|
||||
expires 1y;
|
||||
access_log off;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
# Optional: Explicit asset route
|
||||
location /assets/ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5: Build the Angular application image
|
||||
|
||||
With your custom configuration in place, you're now ready to build the Docker image for your Angular application.
|
||||
|
||||
The updated setup includes:
|
||||
|
||||
- The updated setup includes a clean, production-ready NGINX configuration tailored specifically for Angular.
|
||||
- Efficient multi-stage Docker build, ensuring a small and secure final image.
|
||||
|
||||
After completing the previous steps, your project directory should now contain the following files:
|
||||
|
||||
```text
|
||||
├── docker-angular-sample/
|
||||
│ ├── Dockerfile
|
||||
│ ├── .dockerignore
|
||||
│ ├── compose.yaml
|
||||
│ ├── nginx.conf
|
||||
│ └── README.Docker.md
|
||||
```
|
||||
|
||||
Now that your Dockerfile is configured, you can build the Docker image for your Angular application.
|
||||
|
||||
> [!NOTE]
|
||||
> The `docker build` command packages your application into an image using the instructions in the Dockerfile. It includes all necessary files from the current directory (called the [build context](/build/concepts/context/#what-is-a-build-context)).
|
||||
|
||||
Run the following command from the root of your project:
|
||||
|
||||
```console
|
||||
$ docker build --tag docker-angular-sample .
|
||||
```
|
||||
|
||||
What this command does:
|
||||
- Uses the Dockerfile in the current directory (.)
|
||||
- Packages the application and its dependencies into a Docker image
|
||||
- Tags the image as docker-angular-sample so you can reference it later
|
||||
|
||||
|
||||
#### Step 6: View local images
|
||||
|
||||
After building your Docker image, you can check which images are available on your local machine using either the Docker CLI or [Docker Desktop](/manuals/desktop/use-desktop/images.md). Since you're already working in the terminal, let's use the Docker CLI.
|
||||
|
||||
To list all locally available Docker images, run the following command:
|
||||
|
||||
```console
|
||||
$ docker images
|
||||
```
|
||||
|
||||
Example Output:
|
||||
|
||||
```shell
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
docker-angular-sample latest 34e66bdb9d40 14 seconds ago 76.4MB
|
||||
```
|
||||
|
||||
This output provides key details about your images:
|
||||
|
||||
- **Repository** – The name assigned to the image.
|
||||
- **Tag** – A version label that helps identify different builds (e.g., latest).
|
||||
- **Image ID** – A unique identifier for the image.
|
||||
- **Created** – The timestamp indicating when the image was built.
|
||||
- **Size** – The total disk space used by the image.
|
||||
|
||||
If the build was successful, you should see `docker-angular-sample` image listed.
|
||||
|
||||
---
|
||||
|
||||
## Run the containerized application
|
||||
|
||||
In the previous step, you created a Dockerfile for your Angular application and built a Docker image using the docker build command. Now it’s time to run that image in a container and verify that your application works as expected.
|
||||
|
||||
|
||||
Inside the `docker-angular-sample` directory, run the following command in a
|
||||
terminal.
|
||||
|
||||
```console
|
||||
$ docker compose up --build
|
||||
```
|
||||
|
||||
Open a browser and view the application at [http://localhost:8080](http://localhost:8080). You should see a simple Angular web application.
|
||||
|
||||
Press `ctrl+c` in the terminal to stop your application.
|
||||
|
||||
### Run the application in the background
|
||||
|
||||
You can run the application detached from the terminal by adding the `-d`
|
||||
option. Inside the `docker-angular-sample` directory, run the following command
|
||||
in a terminal.
|
||||
|
||||
```console
|
||||
$ docker compose up --build -d
|
||||
```
|
||||
|
||||
Open a browser and view the application at [http://localhost:8080](http://localhost:8080). You should see your Angular application running in the browser.
|
||||
|
||||
|
||||
To confirm that the container is running, use `docker ps` command:
|
||||
|
||||
```console
|
||||
$ docker ps
|
||||
```
|
||||
|
||||
This will list all active containers along with their ports, names, and status. Look for a container exposing port 8080.
|
||||
|
||||
Example Output:
|
||||
|
||||
```shell
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
eb13026806d1 docker-angular-sample-server "nginx -c /etc/nginx…" About a minute ago Up About a minute 0.0.0.0:8080->8080/tcp docker-angular-sample-server-1
|
||||
```
|
||||
|
||||
|
||||
To stop the application, run:
|
||||
|
||||
```console
|
||||
$ docker compose down
|
||||
```
|
||||
|
||||
|
||||
> [!NOTE]
|
||||
> For more information about Compose commands, see the [Compose CLI
|
||||
> reference](/reference/cli/docker/compose/_index.md).
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
In this guide, you learned how to containerize, build, and run an Angular application using Docker. By following best practices, you created a secure, optimized, and production-ready setup.
|
||||
|
||||
What you accomplished:
|
||||
- Initialized your project using `docker init` to scaffold essential Docker configuration files.
|
||||
- Replaced the default `Dockerfile` with a multi-stage build that compiles the Angular application and serves the static files using Nginx.
|
||||
- Replaced the default `.dockerignore` file to exclude unnecessary files and keep the image clean and efficient.
|
||||
- Built your Docker image using `docker build`.
|
||||
- Ran the container using `docker compose up`, both in the foreground and in detached mode.
|
||||
- Verified that the app was running by visiting [http://localhost:8080](http://localhost:8080).
|
||||
- Learned how to stop the containerized application using `docker compose down`.
|
||||
|
||||
You now have a fully containerized Angular application, running in a Docker container, and ready for deployment across any environment with confidence and consistency.
|
||||
|
||||
---
|
||||
|
||||
## Related resources
|
||||
|
||||
Explore official references and best practices to sharpen your Docker workflow:
|
||||
|
||||
- [Multi-stage builds](/build/building/multi-stage/) – Learn how to separate build and runtime stages.
|
||||
- [Best practices for writing Dockerfiles](/develop/develop-images/dockerfile_best-practices/) – Write efficient, maintainable, and secure Dockerfiles.
|
||||
- [Build context in Docker](/build/concepts/context/) – Learn how context affects image builds.
|
||||
- [`docker init` CLI reference](/reference/cli/docker/init/) – Scaffold Docker assets automatically.
|
||||
- [`docker build` CLI reference](/reference/cli/docker/build/) – Build Docker images from a Dockerfile.
|
||||
- [`docker images` CLI reference](/reference/cli/docker/images/) – Manage and inspect local Docker images.
|
||||
- [`docker compose up` CLI reference](/reference/cli/docker/compose/up/) – Start and run multi-container applications.
|
||||
- [`docker compose down` CLI reference](/reference/cli/docker/compose/down/) – Stop and remove containers, networks, and volumes.
|
||||
|
||||
---
|
||||
|
||||
## Next steps
|
||||
|
||||
With your Angular application now containerized, you're ready to move on to the next step.
|
||||
|
||||
In the next section, you'll learn how to develop your application using Docker containers, enabling a consistent, isolated, and reproducible development environment across any machine.
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
---
|
||||
title: Test your Angular deployment
|
||||
linkTitle: Test your deployment
|
||||
weight: 60
|
||||
keywords: deploy, kubernetes, angular
|
||||
description: Learn how to deploy locally to test and debug your Kubernetes deployment
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, make sure you’ve completed the following:
|
||||
- Complete all the previous sections of this guide, starting with [Containerize Angular application](containerize.md).
|
||||
- [Enable Kubernetes](/manuals/desktop/features/kubernetes.md#install-and-turn-on-kubernetes) in Docker Desktop.
|
||||
|
||||
> **New to Kubernetes?**
|
||||
> Visit the [Kubernetes basics tutorial](https://kubernetes.io/docs/tutorials/kubernetes-basics/) to get familiar with how clusters, pods, deployments, and services work.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
This section guides you through deploying your containerized Angular application locally using [Docker Desktop’s built-in Kubernetes](/desktop/kubernetes/). Running your app in a local Kubernetes cluster closely simulates a real production environment, enabling you to test, validate, and debug your workloads with confidence before promoting them to staging or production.
|
||||
|
||||
---
|
||||
|
||||
## Create a Kubernetes YAML file
|
||||
|
||||
Follow these steps to define your deployment configuration:
|
||||
|
||||
1. In the root of your project, create a new file named: angular-sample-kubernetes.yaml
|
||||
|
||||
2. Open the file in your IDE or preferred text editor.
|
||||
|
||||
3. Add the following configuration, and be sure to replace `{DOCKER_USERNAME}` and `{DOCKERHUB_PROJECT_NAME}` with your actual Docker Hub username and repository name from the previous [Automate your builds with GitHub Actions](configure-github-actions.md).
|
||||
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: angular-sample
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: angular-sample
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: angular-sample
|
||||
spec:
|
||||
containers:
|
||||
- name: angular-container
|
||||
image: {DOCKER_USERNAME}/{DOCKERHUB_PROJECT_NAME}:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
resources:
|
||||
limits:
|
||||
cpu: "500m"
|
||||
memory: "256Mi"
|
||||
requests:
|
||||
cpu: "250m"
|
||||
memory: "128Mi"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: angular-sample-service
|
||||
namespace: default
|
||||
spec:
|
||||
type: NodePort
|
||||
selector:
|
||||
app: angular-sample
|
||||
ports:
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
nodePort: 30001
|
||||
```
|
||||
|
||||
This manifest defines two key Kubernetes resources, separated by `---`:
|
||||
|
||||
- Deployment
|
||||
Deploys a single replica of your Angular application inside a pod. The pod uses the Docker image built and pushed by your GitHub Actions CI/CD workflow
|
||||
(refer to [Automate your builds with GitHub Actions](configure-github-actions.md)).
|
||||
The container listens on port `8080`, which is typically used by [Nginx](https://nginx.org/en/docs/) to serve your production Angular app.
|
||||
|
||||
- Service (NodePort)
|
||||
Exposes the deployed pod to your local machine.
|
||||
It forwards traffic from port `30001` on your host to port `8080` inside the container.
|
||||
This lets you access the application in your browser at [http://localhost:30001](http://localhost:30001).
|
||||
|
||||
> [!NOTE]
|
||||
> To learn more about Kubernetes objects, see the [Kubernetes documentation](https://kubernetes.io/docs/home/).
|
||||
|
||||
---
|
||||
|
||||
## Deploy and check your application
|
||||
|
||||
Follow these steps to deploy your containerized Angular app into a local Kubernetes cluster and verify that it’s running correctly.
|
||||
|
||||
### Step 1. Apply the Kubernetes configuration
|
||||
|
||||
In your terminal, navigate to the directory where your `angular-sample-kubernetes.yaml` file is located, then deploy the resources using:
|
||||
|
||||
```console
|
||||
$ kubectl apply -f angular-sample-kubernetes.yaml
|
||||
```
|
||||
|
||||
If everything is configured properly, you’ll see confirmation that both the Deployment and the Service were created:
|
||||
|
||||
```shell
|
||||
deployment.apps/angular-sample created
|
||||
service/angular-sample-service created
|
||||
```
|
||||
|
||||
This confirms that both the Deployment and the Service were successfully created and are now running inside your local cluster.
|
||||
|
||||
### Step 2. Check the Deployment status
|
||||
|
||||
Run the following command to check the status of your deployment:
|
||||
|
||||
```console
|
||||
$ kubectl get deployments
|
||||
```
|
||||
|
||||
You should see output similar to the following:
|
||||
|
||||
```shell
|
||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||
angular-sample 1/1 1 1 14s
|
||||
```
|
||||
|
||||
This confirms that your pod is up and running with one replica available.
|
||||
|
||||
### Step 3. Verify the Service exposure
|
||||
|
||||
Check if the NodePort service is exposing your app to your local machine:
|
||||
|
||||
```console
|
||||
$ kubectl get services
|
||||
```
|
||||
|
||||
You should see something like:
|
||||
|
||||
```shell
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
angular-sample-service NodePort 10.100.185.105 <none> 8080:30001/TCP 1m
|
||||
```
|
||||
|
||||
This output confirms that your app is available via NodePort on port 30001.
|
||||
|
||||
### Step 4. Access your app in the browser
|
||||
|
||||
Open your browser and navigate to [http://localhost:30001](http://localhost:30001).
|
||||
|
||||
You should see your production-ready Angular Sample application running — served by your local Kubernetes cluster.
|
||||
|
||||
### Step 5. Clean up Kubernetes resources
|
||||
|
||||
Once you're done testing, you can delete the deployment and service using:
|
||||
|
||||
```console
|
||||
$ kubectl delete -f angular-sample-kubernetes.yaml
|
||||
```
|
||||
|
||||
Expected output:
|
||||
|
||||
```shell
|
||||
deployment.apps "angular-sample" deleted
|
||||
service "angular-sample-service" deleted
|
||||
```
|
||||
|
||||
This ensures your cluster stays clean and ready for the next deployment.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you learned how to deploy your Angular application to a local Kubernetes cluster using Docker Desktop. This setup allows you to test and debug your containerized app in a production-like environment before deploying it to the cloud.
|
||||
|
||||
What you accomplished:
|
||||
|
||||
- Created a Kubernetes Deployment and NodePort Service for your Angular app
|
||||
- Used `kubectl apply` to deploy the application locally
|
||||
- Verified the app was running and accessible at `http://localhost:30001`
|
||||
- Cleaned up your Kubernetes resources after testing
|
||||
|
||||
---
|
||||
|
||||
## Related resources
|
||||
|
||||
Explore official references and best practices to sharpen your Kubernetes deployment workflow:
|
||||
|
||||
- [Kubernetes documentation](https://kubernetes.io/docs/home/) – Learn about core concepts, workloads, services, and more.
|
||||
- [Deploy on Kubernetes with Docker Desktop](/manuals/desktop/features/kubernetes.md) – Use Docker Desktop’s built-in Kubernetes support for local testing and development.
|
||||
- [`kubectl` CLI reference](https://kubernetes.io/docs/reference/kubectl/) – Manage Kubernetes clusters from the command line.
|
||||
- [Kubernetes Deployment resource](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) – Understand how to manage and scale applications using Deployments.
|
||||
- [Kubernetes Service resource](https://kubernetes.io/docs/concepts/services-networking/service/) – Learn how to expose your application to internal and external traffic.
|
|
@ -0,0 +1,179 @@
|
|||
---
|
||||
title: Use containers for Angular development
|
||||
linkTitle: Develop your app
|
||||
weight: 30
|
||||
keywords: angular, development, node
|
||||
description: Learn how to develop your Angular application locally using containers.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Complete [Containerize Angular application](containerize.md).
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
In this section, you'll learn how to set up both production and development environments for your containerized Angular application using Docker Compose. This setup allows you to serve a static production build via Nginx and to develop efficiently inside containers using a live-reloading dev server with Compose Watch.
|
||||
|
||||
You’ll learn how to:
|
||||
- Configure separate containers for production and development
|
||||
- Enable automatic file syncing using Compose Watch in development
|
||||
- Debug and live-preview your changes in real-time without manual rebuilds
|
||||
|
||||
---
|
||||
|
||||
## Automatically update services (Development Mode)
|
||||
|
||||
Use Compose Watch to automatically sync source file changes into your containerized development environment. This provides a seamless, efficient development experience without restarting or rebuilding containers manually.
|
||||
|
||||
## Step 1: Create a development Dockerfile
|
||||
|
||||
Create a file named `Dockerfile.dev` in your project root with the following content:
|
||||
|
||||
```dockerfile
|
||||
# =========================================
|
||||
# Stage 1: Development - Angular Application
|
||||
# =========================================
|
||||
|
||||
# Define the Node.js version to use (Alpine for a small footprint)
|
||||
ARG NODE_VERSION=22.14.0-alpine
|
||||
|
||||
# Set the base image for development
|
||||
FROM node:${NODE_VERSION} AS dev
|
||||
|
||||
# Set environment variable to indicate development mode
|
||||
ENV NODE_ENV=development
|
||||
|
||||
# Set the working directory inside the container
|
||||
WORKDIR /app
|
||||
|
||||
# Copy only the dependency files first to optimize Docker caching
|
||||
COPY package.json package-lock.json ./
|
||||
|
||||
# Install dependencies using npm with caching to speed up subsequent builds
|
||||
RUN --mount=type=cache,target=/root/.npm npm ci
|
||||
|
||||
# Copy all application source files into the container
|
||||
COPY . .
|
||||
|
||||
# Expose the port Angular uses for the dev server (default is 4200)
|
||||
EXPOSE 4200
|
||||
|
||||
# Start the Angular dev server and bind it to all network interfaces
|
||||
CMD ["npm", "start", "--", "--host=0.0.0.0"]
|
||||
|
||||
```
|
||||
|
||||
This file sets up a lightweight development environment for your Angular application using the dev server.
|
||||
|
||||
|
||||
### Step 2: Update your `compose.yaml` file
|
||||
|
||||
Open your `compose.yaml` file and define two services: one for production (`angular-prod`) and one for development (`angular-dev`).
|
||||
|
||||
Here’s an example configuration for an Angular application:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
angular-prod:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: docker-angular-sample
|
||||
ports:
|
||||
- "8080:8080"
|
||||
|
||||
angular-dev:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
ports:
|
||||
- "4200:4200"
|
||||
develop:
|
||||
watch:
|
||||
- action: sync
|
||||
path: .
|
||||
target: /app
|
||||
```
|
||||
- The `angular-prod` service builds and serves your static production app using Nginx.
|
||||
- The `angular-dev` service runs your Angular development server with live reload and hot module replacement.
|
||||
- `watch` triggers file sync with Compose Watch.
|
||||
|
||||
> [!NOTE]
|
||||
> For more details, see the official guide: [Use Compose Watch](/manuals/compose/how-tos/file-watch.md).
|
||||
|
||||
After completing the previous steps, your project directory should now contain the following files:
|
||||
|
||||
```text
|
||||
├── docker-angular-sample/
|
||||
│ ├── Dockerfile
|
||||
│ ├── Dockerfile.dev
|
||||
│ ├── .dockerignore
|
||||
│ ├── compose.yaml
|
||||
│ ├── nginx.conf
|
||||
│ └── README.Docker.md
|
||||
```
|
||||
|
||||
### Step 4: Start Compose Watch
|
||||
|
||||
Run the following command from the project root to start the container in watch mode
|
||||
|
||||
```console
|
||||
$ docker compose watch angular-dev
|
||||
```
|
||||
|
||||
### Step 5: Test Compose Watch with Angular
|
||||
|
||||
To verify that Compose Watch is working correctly:
|
||||
|
||||
1. Open the `src/app/app.component.html` file in your text editor.
|
||||
|
||||
2. Locate the following line:
|
||||
|
||||
```html
|
||||
<h1>Docker Angular Sample Application</h1>
|
||||
```
|
||||
|
||||
3. Change it to:
|
||||
|
||||
```html
|
||||
<h1>Hello from Docker Compose Watch</h1>
|
||||
```
|
||||
|
||||
4. Save the file.
|
||||
|
||||
5. Open your browser at [http://localhost:4200](http://localhost:4200).
|
||||
|
||||
You should see the updated text appear instantly, without needing to rebuild the container manually. This confirms that file watching and automatic synchronization are working as expected.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you set up a complete development and production workflow for your Angular application using Docker and Docker Compose.
|
||||
|
||||
Here’s what you accomplished:
|
||||
- Created a `Dockerfile.dev` to streamline local development with hot reloading
|
||||
- Defined separate `angular-dev` and `angular-prod` services in your `compose.yaml` file
|
||||
- Enabled real-time file syncing using Compose Watch for a smoother development experience
|
||||
- Verified that live updates work seamlessly by modifying and previewing a component
|
||||
|
||||
With this setup, you're now equipped to build, run, and iterate on your Angular app entirely within containers—efficiently and consistently across environments.
|
||||
|
||||
---
|
||||
|
||||
## Related resources
|
||||
|
||||
Deepen your knowledge and improve your containerized development workflow with these guides:
|
||||
|
||||
- [Using Compose Watch](/manuals/compose/how-tos/file-watch.md) – Automatically sync source changes during development
|
||||
- [Multi-stage builds](/manuals/build/building/multi-stage.md) – Create efficient, production-ready Docker images
|
||||
- [Dockerfile best practices](/build/building/best-practices/) – Write clean, secure, and optimized Dockerfiles.
|
||||
- [Compose file reference](/compose/compose-file/) – Learn the full syntax and options available for configuring services in `compose.yaml`.
|
||||
- [Docker volumes](/storage/volumes/) – Persist and manage data between container runs
|
||||
|
||||
## Next steps
|
||||
|
||||
In the next section, you'll learn how to run unit tests for your Angular application inside Docker containers. This ensures consistent testing across all environments and removes dependencies on local machine setup.
|
|
@ -0,0 +1,138 @@
|
|||
---
|
||||
title: Run Angular tests in a container
|
||||
linkTitle: Run your tests
|
||||
weight: 40
|
||||
keywords: angular, test, jasmine
|
||||
description: Learn how to run your Angular tests in a container.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Complete all the previous sections of this guide, starting with [Containerize Angular application](containerize.md).
|
||||
|
||||
## Overview
|
||||
|
||||
Testing is a critical part of the development process. In this section, you'll learn how to:
|
||||
|
||||
- Run Jasmine unit tests using the Angular CLI inside a Docker container.
|
||||
- Use Docker Compose to isolate your test environment.
|
||||
- Ensure consistency between local and container-based testing.
|
||||
|
||||
|
||||
The `docker-angular-sample` project comes pre-configured with Jasmine, so you can get started quickly without extra setup.
|
||||
|
||||
---
|
||||
|
||||
## Run tests during development
|
||||
|
||||
The `docker-angular-sample` application includes a sample test file at the following location:
|
||||
|
||||
```console
|
||||
$ src/app/app.component.spec.ts
|
||||
```
|
||||
|
||||
This test uses Jasmine to validate the AppComponent logic.
|
||||
|
||||
### Step 1: Update compose.yaml
|
||||
|
||||
Add a new service named `angular-test` to your `compose.yaml` file. This service allows you to run your test suite in an isolated, containerized environment.
|
||||
|
||||
```yaml {hl_lines="22-26",linenos=true}
|
||||
services:
|
||||
angular-dev:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
ports:
|
||||
- "5173:5173"
|
||||
develop:
|
||||
watch:
|
||||
- action: sync
|
||||
path: .
|
||||
target: /app
|
||||
|
||||
angular-prod:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: docker-angular-sample
|
||||
ports:
|
||||
- "8080:8080"
|
||||
|
||||
angular-test:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
command: ["npm", "run", "test"]
|
||||
|
||||
```
|
||||
|
||||
The angular-test service reuses the same `Dockerfile.dev` used for [development](develop.md) and overrides the default command to run tests with `npm run test`. This setup ensures a consistent test environment that matches your local development configuration.
|
||||
|
||||
|
||||
After completing the previous steps, your project directory should contain the following files:
|
||||
|
||||
```text
|
||||
├── docker-angular-sample/
|
||||
│ ├── Dockerfile
|
||||
│ ├── Dockerfile.dev
|
||||
│ ├── .dockerignore
|
||||
│ ├── compose.yaml
|
||||
│ ├── nginx.conf
|
||||
│ └── README.Docker.md
|
||||
```
|
||||
|
||||
### Step 2: Run the tests
|
||||
|
||||
To execute your test suite inside the container, run the following command from your project root:
|
||||
|
||||
```console
|
||||
$ docker compose run --rm angular-test
|
||||
```
|
||||
|
||||
This command will:
|
||||
- Start the `angular-test` service defined in your `compose.yaml` file.
|
||||
- Execute the `npm run test` script using the same environment as development.
|
||||
- Automatically removes the container after tests complete, using the [`docker compose run --rm`](/engine/reference/commandline/compose_run) command.
|
||||
|
||||
You should see output similar to the following:
|
||||
|
||||
```shell
|
||||
Test Suites: 1 passed, 1 total
|
||||
Tests: 3 passed, 3 total
|
||||
Snapshots: 0 total
|
||||
Time: 1.529 s
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> For more information about Compose commands, see the [Compose CLI
|
||||
> reference](/reference/cli/docker/compose/_index.md).
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you learned how to run unit tests for your Angular application inside a Docker container using Jasmine and Docker Compose.
|
||||
|
||||
What you accomplished:
|
||||
- Created a `angular-test` service in `compose.yaml` to isolate test execution.
|
||||
- Reused the development `Dockerfile.dev` to ensure consistency between dev and test environments.
|
||||
- Ran tests inside the container using `docker compose run --rm angular-test`.
|
||||
- Ensured reliable, repeatable testing across environments without depending on your local machine setup.
|
||||
|
||||
---
|
||||
|
||||
## Related resources
|
||||
|
||||
Explore official references and best practices to sharpen your Docker testing workflow:
|
||||
|
||||
- [Dockerfile reference](/reference/dockerfile/) – Understand all Dockerfile instructions and syntax.
|
||||
- [Best practices for writing Dockerfiles](/develop/develop-images/dockerfile_best-practices/) – Write efficient, maintainable, and secure Dockerfiles.
|
||||
- [Compose file reference](/compose/compose-file/) – Learn the full syntax and options available for configuring services in `compose.yaml`.
|
||||
- [`docker compose run` CLI reference](/reference/cli/docker/compose/run/) – Run one-off commands in a service container.
|
||||
---
|
||||
|
||||
## Next steps
|
||||
|
||||
Next, you’ll learn how to set up a CI/CD pipeline using GitHub Actions to automatically build and test your Angular application in a containerized environment. This ensures your code is validated on every push or pull request, maintaining consistency and reliability across your development workflow.
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Configure CI/CD for your React.js application
|
||||
linkTitle: Configure CI/CD
|
||||
title: Automate your builds with GitHub Actions
|
||||
linkTitle: Automate your builds with GitHub Actions
|
||||
weight: 60
|
||||
keywords: CI/CD, GitHub( Actions), React.js, Next.js
|
||||
description: Learn how to configure CI/CD using GitHub Actions for your React.js application.
|
|
@ -7,7 +7,6 @@ description: Learn how to containerize a React.js application with Docker by cre
|
|||
|
||||
---
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, make sure the following tools are installed and available on your system:
|
||||
|
@ -135,13 +134,13 @@ FROM node:${NODE_VERSION} AS builder
|
|||
WORKDIR /app
|
||||
|
||||
# Copy package-related files first to leverage Docker's caching mechanism
|
||||
COPY --link package.json package-lock.json ./
|
||||
COPY package.json package-lock.json ./
|
||||
|
||||
# Install project dependencies using npm ci (ensures a clean, reproducible install)
|
||||
RUN --mount=type=cache,target=/root/.npm npm ci
|
||||
|
||||
# Copy the rest of the application source code into the container
|
||||
COPY --link . .
|
||||
COPY . .
|
||||
|
||||
# Build the React.js application (outputs to /app/dist)
|
||||
RUN npm run build
|
||||
|
@ -156,10 +155,10 @@ FROM nginxinc/nginx-unprivileged:${NGINX_VERSION} AS runner
|
|||
USER nginx
|
||||
|
||||
# Copy custom Nginx config
|
||||
COPY --link nginx.conf /etc/nginx/nginx.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
|
||||
# Copy the static build output from the build stage to Nginx's default HTML serving directory
|
||||
COPY --link --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --chown=nginx:nginx --from=builder /app/dist /usr/share/nginx/html
|
||||
|
||||
# Expose port 8080 to allow HTTP traffic
|
||||
# Note: The default NGINX container now listens on port 8080 instead of 80
|
||||
|
|
|
@ -32,7 +32,7 @@ Follow these steps to define your deployment configuration:
|
|||
|
||||
2. Open the file in your IDE or preferred text editor.
|
||||
|
||||
3. Add the following configuration, and be sure to replace `{DOCKER_USERNAME}` and `{DOCKERHUB_PROJECT_NAME}` with your actual Docker Hub username and repository name from the previous [Configure CI/CD for your React.js application](configure-ci-cd.md).
|
||||
3. Add the following configuration, and be sure to replace `{DOCKER_USERNAME}` and `{DOCKERHUB_PROJECT_NAME}` with your actual Docker Hub username and repository name from the previous [Automate your builds with GitHub Actions](configure-github-actions.md).
|
||||
|
||||
|
||||
```yaml
|
||||
|
@ -77,7 +77,7 @@ This manifest defines two key Kubernetes resources, separated by `---`:
|
|||
|
||||
- Deployment
|
||||
Deploys a single replica of your React.js application inside a pod. The pod uses the Docker image built and pushed by your GitHub Actions CI/CD workflow
|
||||
(refer to [Configure CI/CD for your React.js application](configure-ci-cd.md)).
|
||||
(refer to [Automate your builds with GitHub Actions](configure-github-actions.md)).
|
||||
The container listens on port `8080`, which is typically used by [Nginx](https://nginx.org/en/docs/) to serve your production React app.
|
||||
|
||||
- Service (NodePort)
|
||||
|
|
|
@ -45,13 +45,13 @@ FROM node:${NODE_VERSION} AS dev
|
|||
WORKDIR /app
|
||||
|
||||
# Copy package-related files first to leverage Docker's caching mechanism
|
||||
COPY --link package.json package-lock.json ./
|
||||
COPY package.json package-lock.json ./
|
||||
|
||||
# Install project dependencies
|
||||
RUN --mount=type=cache,target=/root/.npm npm install
|
||||
|
||||
# Copy the rest of the application source code into the container
|
||||
COPY --link . .
|
||||
COPY . .
|
||||
|
||||
# Expose the port used by the Vite development server
|
||||
EXPOSE 5173
|
||||
|
|
|
@ -25,11 +25,11 @@ params:
|
|||
link: /engine/
|
||||
- title: Docker Compose
|
||||
description: Define and run multi-container applications.
|
||||
icon: /assets/icons/Compose.svg
|
||||
icon: /icons/Compose.svg
|
||||
link: /compose/
|
||||
- title: Testcontainers
|
||||
description: Run containers programmatically in your preferred programming language.
|
||||
icon: /assets/icons/Testcontainers.svg
|
||||
icon: /icons/Testcontainers.svg
|
||||
link: /testcontainers/
|
||||
ai:
|
||||
- title: Ask Gordon
|
||||
|
@ -47,11 +47,11 @@ params:
|
|||
products:
|
||||
- title: Docker Desktop
|
||||
description: Your command center for container development.
|
||||
icon: /assets/icons/Whale.svg
|
||||
icon: /icons/Whale.svg
|
||||
link: /desktop/
|
||||
- title: Build Cloud
|
||||
description: Build your images faster in the cloud.
|
||||
icon: /assets/images/logo-build-cloud.svg
|
||||
icon: /icons/logo-build-cloud.svg
|
||||
link: /build-cloud/
|
||||
- title: Docker Hub
|
||||
description: Discover, share, and integrate container images.
|
||||
|
@ -59,7 +59,7 @@ params:
|
|||
link: /docker-hub/
|
||||
- title: Docker Scout
|
||||
description: Image analysis and policy evaluation.
|
||||
icon: /assets/icons/Scout.svg
|
||||
icon: /icons/Scout.svg
|
||||
link: /scout/
|
||||
- title: Docker for GitHub Copilot
|
||||
description: Integrate Docker's capabilities with GitHub Copilot.
|
||||
|
|
|
@ -50,4 +50,4 @@ The following example assumes you have already installed and set up Claude Deskt
|
|||
Take a screenshot of docs.docker.com and then invert the colors
|
||||
```
|
||||
|
||||
Once you've given your consent to use the new tools, Claude spins up the Puppeteer MCP server inside a container, navigates to the target URL, captures and modify the page, and returns the screenshot.
|
||||
Once you've given your consent to use the new tools, Claude spins up the Puppeteer MCP server inside a container, navigates to the target URL, captures and modify the page, and returns the screenshot.
|
||||
|
|
|
@ -32,6 +32,8 @@ Models are pulled from Docker Hub the first time they're used and stored locally
|
|||
|
||||
## Enable Docker Model Runner
|
||||
|
||||
### Enable DMR in Docker Desktop
|
||||
|
||||
1. Navigate to the **Features in development** tab in settings.
|
||||
2. Under the **Experimental features** tab, select **Access experimental features**.
|
||||
3. Select **Apply and restart**.
|
||||
|
@ -42,6 +44,15 @@ Models are pulled from Docker Hub the first time they're used and stored locally
|
|||
|
||||
You can now use the `docker model` command in the CLI and view and interact with your local models in the **Models** tab in the Docker Desktop Dashboard.
|
||||
|
||||
### Enable DMR in Docker Engine
|
||||
|
||||
1. Ensure you have installed [Docker Engine](/engine/install/).
|
||||
2. DMR is available as a package. To install it, run:
|
||||
|
||||
```console
|
||||
apt install docker-model-plugin
|
||||
```
|
||||
|
||||
## Available commands
|
||||
|
||||
### Model runner status
|
||||
|
|
|
@ -18,11 +18,11 @@ intro:
|
|||
quickstart:
|
||||
- title: Testcontainers for Go
|
||||
description: A Go package that makes it simple to create and clean up container-based dependencies for automated integration/smoke tests.
|
||||
icon: /assets/icons/go.svg
|
||||
icon: /icons/go.svg
|
||||
link: https://golang.testcontainers.org/quickstart/
|
||||
- title: Testcontainers for Java
|
||||
description: A Java library that supports JUnit tests, providing lightweight, throwaway instances of anything that can run in a Docker container.
|
||||
icon: /assets/icons/java.svg
|
||||
icon: /icons/java.svg
|
||||
link: https://java.testcontainers.org/
|
||||
---
|
||||
|
||||
|
|
|
@ -46,8 +46,8 @@ build:
|
|||
disableTags: true
|
||||
# Ensure that CSS/assets changes trigger a dev server rebuild
|
||||
cachebusters:
|
||||
- source: assets/watching/hugo_stats\.json
|
||||
target: styles\.css
|
||||
- source: assets/notwatching/hugo_stats\.json
|
||||
target: css
|
||||
- source: (postcss|tailwind)\.config\.js
|
||||
target: css
|
||||
- source: assets/.*\.js
|
||||
|
@ -278,8 +278,9 @@ module:
|
|||
- source: assets
|
||||
target: assets
|
||||
# Mount hugo_stats.json to the assets dir to trigger cachebust
|
||||
- source: hugo_stats.json
|
||||
target: assets/watching/hugo_stats.json
|
||||
- disableWatch: true
|
||||
source: hugo_stats.json
|
||||
target: assets/notwatching/hugo_stats.json
|
||||
# Mount the icon files to assets so we can access them with resources.Get
|
||||
- source: node_modules/@material-symbols/svg-400/rounded
|
||||
target: assets/icons
|
||||
|
|
262
hugo_stats.json
|
@ -5,10 +5,8 @@
|
|||
"!mt-0",
|
||||
"--mount",
|
||||
"--tmpfs",
|
||||
"-mb-3",
|
||||
"-mr-8",
|
||||
"-mt-0.5",
|
||||
"-mt-4",
|
||||
"-mt-8",
|
||||
"-top-16",
|
||||
"-v",
|
||||
|
@ -133,126 +131,143 @@
|
|||
"Without-systemd",
|
||||
"[display:none]",
|
||||
"absolute",
|
||||
"admonition",
|
||||
"admonition-content",
|
||||
"admonition-danger",
|
||||
"admonition-header",
|
||||
"admonition-icon",
|
||||
"admonition-note",
|
||||
"admonition-tip",
|
||||
"admonition-title",
|
||||
"admonition-warning",
|
||||
"aspect-video",
|
||||
"bake-action",
|
||||
"bg-amber-light",
|
||||
"bg-amber-500",
|
||||
"bg-background-light",
|
||||
"bg-background-toc",
|
||||
"bg-black/50",
|
||||
"bg-black/70",
|
||||
"bg-blue-light",
|
||||
"bg-blue-light-400",
|
||||
"bg-blue-light-500",
|
||||
"bg-cover",
|
||||
"bg-blue",
|
||||
"bg-blue-400",
|
||||
"bg-blue-500",
|
||||
"bg-gradient-to-br",
|
||||
"bg-gradient-to-r",
|
||||
"bg-gradient-to-t",
|
||||
"bg-gray-light-100",
|
||||
"bg-gray-light-200",
|
||||
"bg-gray-light-400",
|
||||
"bg-gray-light-700",
|
||||
"bg-green-light",
|
||||
"bg-green-light-400",
|
||||
"bg-opacity-75",
|
||||
"bg-gray-00",
|
||||
"bg-gray-100",
|
||||
"bg-gray-200",
|
||||
"bg-gray-400",
|
||||
"bg-gray-50",
|
||||
"bg-gray-700",
|
||||
"bg-green-400",
|
||||
"bg-green-500",
|
||||
"bg-navbar-bg",
|
||||
"bg-pattern-blue",
|
||||
"bg-pattern-purple",
|
||||
"bg-pattern-verde",
|
||||
"bg-red-light",
|
||||
"bg-red-500",
|
||||
"bg-transparent",
|
||||
"bg-violet-light",
|
||||
"bg-violet-500",
|
||||
"bg-white",
|
||||
"bg-white/10",
|
||||
"block",
|
||||
"border",
|
||||
"border-0",
|
||||
"border-amber-light",
|
||||
"border-b",
|
||||
"border-b-4",
|
||||
"border-blue-light",
|
||||
"border-blue-light-500",
|
||||
"border-blue",
|
||||
"border-divider-light",
|
||||
"border-gray-light-100",
|
||||
"border-gray-light-200",
|
||||
"border-gray-light-400",
|
||||
"border-green-light",
|
||||
"border-green-light-400",
|
||||
"border-gray-200",
|
||||
"border-gray-300",
|
||||
"border-gray-400",
|
||||
"border-gray-600",
|
||||
"border-green-400",
|
||||
"border-l-2",
|
||||
"border-l-4",
|
||||
"border-l-magenta-light",
|
||||
"border-red-light",
|
||||
"border-transparent",
|
||||
"border-violet-light",
|
||||
"border-white",
|
||||
"bottom-0",
|
||||
"build-push-action",
|
||||
"card",
|
||||
"card-content",
|
||||
"card-description",
|
||||
"card-header",
|
||||
"card-icon",
|
||||
"card-img",
|
||||
"card-link",
|
||||
"card-title",
|
||||
"chroma",
|
||||
"cls-1",
|
||||
"cls-2",
|
||||
"col-start-2",
|
||||
"containerd-image-store",
|
||||
"cursor-pointer",
|
||||
"dark:bg-amber-dark",
|
||||
"dark:bg-amber-300",
|
||||
"dark:bg-background-dark",
|
||||
"dark:bg-blue-dark",
|
||||
"dark:bg-blue-dark-400",
|
||||
"dark:bg-gray-dark-100",
|
||||
"dark:bg-gray-dark-200",
|
||||
"dark:bg-gray-dark-300",
|
||||
"dark:bg-gray-dark-400",
|
||||
"dark:bg-green-dark",
|
||||
"dark:bg-background-toc",
|
||||
"dark:bg-blue",
|
||||
"dark:bg-blue-300",
|
||||
"dark:bg-blue-400",
|
||||
"dark:bg-blue-500",
|
||||
"dark:bg-blue-800",
|
||||
"dark:bg-gray-300",
|
||||
"dark:bg-gray-400",
|
||||
"dark:bg-gray-500",
|
||||
"dark:bg-gray-800",
|
||||
"dark:bg-gray-900",
|
||||
"dark:bg-gray-950",
|
||||
"dark:bg-green-300",
|
||||
"dark:bg-green-700",
|
||||
"dark:bg-green-dark-400",
|
||||
"dark:bg-opacity-75",
|
||||
"dark:bg-red-dark",
|
||||
"dark:bg-violet-dark",
|
||||
"dark:bg-navbar-bg-dark",
|
||||
"dark:bg-red-300",
|
||||
"dark:bg-violet-300",
|
||||
"dark:bg-violet-400",
|
||||
"dark:block",
|
||||
"dark:border-amber-dark",
|
||||
"dark:border-b-blue-dark-600",
|
||||
"dark:border-blue-dark",
|
||||
"dark:border-b-blue-600",
|
||||
"dark:border-divider-dark",
|
||||
"dark:border-gray-dark-200",
|
||||
"dark:border-gray-dark-400",
|
||||
"dark:border-green-dark",
|
||||
"dark:border-green-dark-400",
|
||||
"dark:border-gray-100",
|
||||
"dark:border-gray-400",
|
||||
"dark:border-gray-50",
|
||||
"dark:border-gray-700",
|
||||
"dark:border-green-400",
|
||||
"dark:border-l-magenta-dark",
|
||||
"dark:border-red-dark",
|
||||
"dark:border-violet-dark",
|
||||
"dark:fill-blue-dark",
|
||||
"dark:focus:ring-blue-dark",
|
||||
"dark:from-background-dark",
|
||||
"dark:from-blue-dark-200",
|
||||
"dark:from-blue-dark-400",
|
||||
"dark:from-gray-dark-100",
|
||||
"dark:fill-blue-300",
|
||||
"dark:focus:ring-3-blue-dark",
|
||||
"dark:from-blue-300",
|
||||
"dark:from-blue-600",
|
||||
"dark:hidden",
|
||||
"dark:hover:bg-blue-dark",
|
||||
"dark:hover:bg-blue-dark-500",
|
||||
"dark:hover:bg-gray-dark-200",
|
||||
"dark:hover:bg-gray-dark-400",
|
||||
"dark:hover:bg-gray-dark-500",
|
||||
"dark:hover:text-blue-dark",
|
||||
"dark:hover:bg-blue-400",
|
||||
"dark:hover:bg-blue-500",
|
||||
"dark:hover:bg-blue-700",
|
||||
"dark:hover:bg-gray-500",
|
||||
"dark:hover:bg-gray-800",
|
||||
"dark:hover:bg-gray-900",
|
||||
"dark:hover:text-blue",
|
||||
"dark:prose-invert",
|
||||
"dark:ring-blue-dark-400",
|
||||
"dark:ring-gray-dark-400",
|
||||
"dark:ring-3-blue-dark-400",
|
||||
"dark:ring-3-gray-dark-400",
|
||||
"dark:syntax-dark",
|
||||
"dark:text-amber-dark",
|
||||
"dark:text-blue-dark",
|
||||
"dark:text-blue",
|
||||
"dark:text-blue-700",
|
||||
"dark:text-divider-dark",
|
||||
"dark:text-gray-dark",
|
||||
"dark:text-gray-dark-300",
|
||||
"dark:text-gray-dark-500",
|
||||
"dark:text-gray-dark-600",
|
||||
"dark:text-gray-dark-700",
|
||||
"dark:text-gray-dark-800",
|
||||
"dark:text-green-dark",
|
||||
"dark:text-gray",
|
||||
"dark:text-gray-100",
|
||||
"dark:text-gray-200",
|
||||
"dark:text-gray-300",
|
||||
"dark:text-gray-400",
|
||||
"dark:text-gray-500",
|
||||
"dark:text-gray-900",
|
||||
"dark:text-magenta-dark",
|
||||
"dark:text-red-dark",
|
||||
"dark:text-violet-dark",
|
||||
"dark:text-white",
|
||||
"dark:to-background-dark",
|
||||
"dark:to-blue-dark-100",
|
||||
"dark:to-magenta-dark-400",
|
||||
"dark:to-blue-400",
|
||||
"dark:to-blue-500",
|
||||
"docker/bake-action",
|
||||
"docker/build-push-action",
|
||||
"download-links",
|
||||
"download-links-subcontainer",
|
||||
"drop-shadow",
|
||||
"drop-shadow-sm",
|
||||
"duration-300",
|
||||
"fill-blue-light",
|
||||
"fill-blue",
|
||||
"fixed",
|
||||
"flex",
|
||||
"flex-1",
|
||||
|
@ -260,21 +275,19 @@
|
|||
"flex-col",
|
||||
"flex-col-reverse",
|
||||
"flex-grow",
|
||||
"flex-grow-0",
|
||||
"flex-none",
|
||||
"flex-shrink",
|
||||
"flex-wrap",
|
||||
"focus:ring-blue-light",
|
||||
"focus:ring-3-blue-light",
|
||||
"font-bold",
|
||||
"font-medium",
|
||||
"font-semibold",
|
||||
"footnote-backref",
|
||||
"footnote-ref",
|
||||
"footnotes",
|
||||
"from-20%",
|
||||
"from-background-light",
|
||||
"from-blue-light-400",
|
||||
"from-blue-light-600",
|
||||
"from-blue-400",
|
||||
"from-blue-600",
|
||||
"gap-0",
|
||||
"gap-1",
|
||||
"gap-10",
|
||||
"gap-12",
|
||||
|
@ -282,7 +295,6 @@
|
|||
"gap-20",
|
||||
"gap-3",
|
||||
"gap-4",
|
||||
"gap-6",
|
||||
"gap-8",
|
||||
"goat",
|
||||
"grid",
|
||||
|
@ -305,20 +317,23 @@
|
|||
"hidden",
|
||||
"hidden'",
|
||||
"highlight",
|
||||
"hover:bg-blue-light-400",
|
||||
"hover:bg-gray-light-100",
|
||||
"hover:bg-gray-light-200",
|
||||
"hover:bg-gray-light-300",
|
||||
"hover:bg-blue",
|
||||
"hover:bg-blue-400",
|
||||
"hover:bg-blue-500",
|
||||
"hover:bg-gray-100",
|
||||
"hover:bg-gray-200",
|
||||
"hover:bg-gray-300",
|
||||
"hover:bg-gray-50",
|
||||
"hover:bg-white/20",
|
||||
"hover:border-gray-light-200",
|
||||
"hover:border-white/20",
|
||||
"hover:dark:bg-gray-dark-200",
|
||||
"hover:dark:bg-gray-dark-300",
|
||||
"hover:dark:border-gray-dark",
|
||||
"hover:dark:text-blue-dark",
|
||||
"hover:drop-shadow-lg",
|
||||
"hover:dark:bg-blue-500",
|
||||
"hover:dark:bg-gray-300",
|
||||
"hover:dark:bg-gray-700",
|
||||
"hover:dark:bg-gray-800",
|
||||
"hover:dark:text-blue-400",
|
||||
"hover:dark:text-blue-700",
|
||||
"hover:opacity-90",
|
||||
"hover:text-blue-light",
|
||||
"hover:text-blue",
|
||||
"hover:text-white",
|
||||
"hover:underline",
|
||||
"icon-lg",
|
||||
|
@ -364,13 +379,14 @@
|
|||
"max-w-56",
|
||||
"max-w-[1920px]",
|
||||
"max-w-[840px]",
|
||||
"max-w-fit",
|
||||
"max-w-full",
|
||||
"max-w-none",
|
||||
"max-w-xl",
|
||||
"mb-1",
|
||||
"mb-2",
|
||||
"mb-3",
|
||||
"mb-4",
|
||||
"mb-6",
|
||||
"mb-8",
|
||||
"md-dropdown",
|
||||
"md:block",
|
||||
|
@ -404,9 +420,10 @@
|
|||
"mt-[2px]",
|
||||
"mx-auto",
|
||||
"my-0",
|
||||
"my-1",
|
||||
"my-4",
|
||||
"my-6",
|
||||
"navbar-font",
|
||||
"navbar-group-font-title",
|
||||
"no-underline",
|
||||
"no-wrap",
|
||||
"not-prose",
|
||||
|
@ -416,7 +433,7 @@
|
|||
"origin-bottom-right",
|
||||
"origin-top-right",
|
||||
"ot-sdk-show-settings",
|
||||
"outline-none",
|
||||
"outline-hidden",
|
||||
"overflow-clip",
|
||||
"overflow-hidden",
|
||||
"overflow-x-auto",
|
||||
|
@ -447,6 +464,7 @@
|
|||
"pt-10",
|
||||
"pt-2",
|
||||
"pt-4",
|
||||
"pt-5",
|
||||
"px-1",
|
||||
"px-2",
|
||||
"px-4",
|
||||
|
@ -460,20 +478,22 @@
|
|||
"right-0",
|
||||
"right-3",
|
||||
"right-8",
|
||||
"ring-2",
|
||||
"ring-[1.5px]",
|
||||
"ring-blue-light-400",
|
||||
"ring-gray-light-200",
|
||||
"ring-3-2",
|
||||
"ring-3-[1.5px]",
|
||||
"ring-3-blue-light-400",
|
||||
"ring-3-gray-light-200",
|
||||
"rotate-45",
|
||||
"rounded",
|
||||
"rounded-[6px]",
|
||||
"rounded-b-lg",
|
||||
"rounded-full",
|
||||
"rounded-sm",
|
||||
"rounded-sm-b-lg",
|
||||
"scale-50",
|
||||
"scale-75",
|
||||
"scroll-mt-2",
|
||||
"scroll-mt-20",
|
||||
"scroll-mt-36",
|
||||
"section-card",
|
||||
"section-card-text",
|
||||
"section-card-title",
|
||||
"select-none",
|
||||
"self-center",
|
||||
"self-start",
|
||||
|
@ -490,38 +510,34 @@
|
|||
"space-y-2",
|
||||
"space-y-4",
|
||||
"sticky",
|
||||
"sub-button",
|
||||
"summary-bar",
|
||||
"svg",
|
||||
"svg-container",
|
||||
"syntax-light",
|
||||
"systemd-networkd",
|
||||
"text-2xl",
|
||||
"text-amber-light",
|
||||
"text-base",
|
||||
"text-black",
|
||||
"text-blue",
|
||||
"text-blue-light",
|
||||
"text-divider-light",
|
||||
"text-gray-light",
|
||||
"text-gray-light-200",
|
||||
"text-gray-light-300",
|
||||
"text-gray-light-500",
|
||||
"text-gray-light-600",
|
||||
"text-gray-light-800",
|
||||
"text-green-light",
|
||||
"text-gray",
|
||||
"text-gray-100",
|
||||
"text-gray-200",
|
||||
"text-gray-400",
|
||||
"text-gray-600",
|
||||
"text-gray-800",
|
||||
"text-left",
|
||||
"text-lg",
|
||||
"text-magenta-light",
|
||||
"text-red-light",
|
||||
"text-sm",
|
||||
"text-violet-light",
|
||||
"text-white",
|
||||
"text-xl",
|
||||
"text-xs",
|
||||
"to-30%",
|
||||
"to-50%",
|
||||
"to-75%",
|
||||
"to-blue-light",
|
||||
"to-magenta-light-400",
|
||||
"to-transparent",
|
||||
"to-white",
|
||||
"to-blue-200",
|
||||
"to-blue-500",
|
||||
"toc",
|
||||
"top-0",
|
||||
"top-16",
|
||||
|
@ -533,12 +549,10 @@
|
|||
"transition-transform",
|
||||
"truncate",
|
||||
"underline-offset-2",
|
||||
"uppercase",
|
||||
"w-2",
|
||||
"w-56",
|
||||
"w-8",
|
||||
"w-[1200px]",
|
||||
"w-[32px]",
|
||||
"w-fit",
|
||||
"w-full",
|
||||
"w-screen",
|
||||
|
|
|
@ -1,41 +1,42 @@
|
|||
{{- $icons := dict
|
||||
"caution" "dangerous"
|
||||
"important" "report"
|
||||
"note" "info"
|
||||
"tip" "lightbulb"
|
||||
"warning" "warning"
|
||||
"caution" "warning.svg"
|
||||
"important" "important.svg"
|
||||
"note" "info.svg"
|
||||
"tip" "lightbulb.svg"
|
||||
"warning" "warning.svg"
|
||||
}}
|
||||
{{- $borders := dict
|
||||
"caution" "border-red-light dark:border-red-dark"
|
||||
"important" "border-violet-light dark:border-violet-dark"
|
||||
"note" "border-blue-light dark:border-blue-dark"
|
||||
"tip" "border-green-light dark:border-green-dark"
|
||||
"warning" "border-amber-light dark:border-amber-dark"
|
||||
}}
|
||||
{{- $textColors := dict
|
||||
"caution" "text-red-light dark:text-red-dark"
|
||||
"important" "text-violet-light dark:text-violet-dark"
|
||||
"note" "text-blue-light dark:text-blue-dark"
|
||||
"tip" "text-green-light dark:text-green-dark"
|
||||
"warning" "text-amber-light dark:text-amber-dark"
|
||||
{{- $admonitionClasses := dict
|
||||
"caution" "admonition admonition-danger"
|
||||
"important" "admonition admonition-note"
|
||||
"note" "admonition admonition-note"
|
||||
"tip" "admonition admonition-tip"
|
||||
"warning" "admonition admonition-warning"
|
||||
}}
|
||||
{{- $type := cond (index $icons .AlertType) .AlertType "note" }}
|
||||
{{- $iconFile := index $icons $type }}
|
||||
{{- $partial := printf "admonitions/icons/%s" $iconFile }}
|
||||
|
||||
|
||||
{{ if eq .Type "alert" }}
|
||||
<blockquote
|
||||
{{ with .Attributes.id }}id="{{ . }}"{{ end }}
|
||||
class="px-4 border-l-4 {{ index $borders .AlertType }}">
|
||||
<p class="flex gap-2 items-center {{ index $textColors .AlertType }}">
|
||||
<span class="icon-svg pb-1">{{ $i := index $icons .AlertType }}
|
||||
{{ partialCached "icon.html" $i $i }}
|
||||
class="{{ index $admonitionClasses .AlertType }} admonition not-prose">
|
||||
<div class="admonition-header">
|
||||
<span class="admonition-icon">
|
||||
{{- partialCached $partial . }}
|
||||
</span>
|
||||
<strong>{{ i18n .AlertType }}</strong>
|
||||
</p>
|
||||
{{ .Text | safeHTML }}
|
||||
<span class="admonition-title">
|
||||
{{ printf "%s%s" (upper (substr $.AlertType 0 1)) (substr $.AlertType 1) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="admonition-content">
|
||||
{{ .Text | safeHTML }}
|
||||
</div>
|
||||
</blockquote>
|
||||
{{ else }}
|
||||
<blockquote
|
||||
{{ with .Attributes.id }}id="{{ . }}"{{ end }}
|
||||
class="px-4 border-l-4 text-gray-light dark:text-gray-dark">
|
||||
{{ .Text | safeHTML }}
|
||||
class="admonition not-prose">
|
||||
{{ .Text | safeHTML }}
|
||||
</blockquote>
|
||||
{{ end }}
|
||||
|
|
|
@ -1,38 +1,65 @@
|
|||
<div data-pagefind-ignore class="scroll-mt-20" x-data x-ref="root">
|
||||
<div data-pagefind-ignore class="scroll-mt-2" x-data x-ref="root">
|
||||
{{ with .Attributes.title }}
|
||||
<div class="text-sm -mb-3 text-gray-light dark:text-gray-dark">{{ . }}</div>
|
||||
<div class="mb-3 text-sm text-gray-100 dark:bg-gray-900 dark:text-gray-900">
|
||||
{{ . }}
|
||||
</div>
|
||||
{{ end }}
|
||||
<div class="group relative">
|
||||
<button x-data="{ code: '{{encoding.Base64Encode .Inner}}', copying: false }"
|
||||
class="absolute right-3 top-3 z-10 text-gray-light-300 dark:text-gray-dark-600" title="copy" @click="window.navigator.clipboard.writeText(atob(code).replaceAll(/^[\$>]\s+/gm, ''));
|
||||
<!-- copy button -->
|
||||
<button
|
||||
x-data="{ code: '{{ encoding.Base64Encode .Inner }}', copying: false }"
|
||||
class="absolute top-3 right-3 z-10 text-gray-200 dark:text-gray-500"
|
||||
title="copy"
|
||||
@click="window.navigator.clipboard.writeText(atob(code).replaceAll(/^[\$>]\s+/gm, ''));
|
||||
copying = true;
|
||||
setTimeout(() => copying = false, 2000);">
|
||||
<span :class="{ 'group-hover:block' : !copying }" class="icon-svg hidden">{{ partialCached "icon" "content_copy" "content_copy" }}</span>
|
||||
<span :class="{ 'group-hover:block' : copying }" class="icon-svg hidden">{{ partialCached "icon" "check_circle" "check_circle" }}</span>
|
||||
setTimeout(() => copying = false, 2000);"
|
||||
>
|
||||
<span :class="{ 'group-hover:block' : !copying }" class="icon-svg hidden"
|
||||
>{{ partialCached "icon" "content_copy" "content_copy" }}</span
|
||||
>
|
||||
<span :class="{ 'group-hover:block' : copying }" class="icon-svg hidden"
|
||||
>{{ partialCached "icon" "check_circle" "check_circle" }}</span
|
||||
>
|
||||
</button>
|
||||
{{ $lang := .Type | default "text" }} {{ $result := transform.Highlight .Inner
|
||||
$lang .Options }}
|
||||
<div class="syntax-light dark:syntax-dark">
|
||||
{{ $lang := .Type | default "text" }}
|
||||
{{ $result := transform.Highlight .Inner
|
||||
$lang .Options
|
||||
}}
|
||||
<div class="syntax-light dark:syntax-dark not-prose">
|
||||
{{ with .Attributes.collapse }}
|
||||
<div x-data="{ collapse: true }" class="relative overflow-clip"
|
||||
x-init="$watch('collapse', value => $refs.root.scrollIntoView({ behavior: 'smooth'}))">
|
||||
<div x-show="collapse"
|
||||
class="to-transparent absolute z-10 flex h-32 w-full flex-col-reverse items-center overflow-clip bg-gradient-to-t from-background-light to-75% bg-cover pb-4 dark:from-background-dark">
|
||||
<button @click="collapse = false"
|
||||
class="flex items-center rounded-full bg-blue-light px-2 text-sm text-white dark:bg-blue-dark-400">
|
||||
<span>Show more</span>
|
||||
<span class="icon-svg">{{ partialCached "icon" "arrow_drop_down" "arrow_drop_down" }}</span>
|
||||
</button>
|
||||
<div
|
||||
x-data="{ collapse: true }"
|
||||
class="relative overflow-clip"
|
||||
x-init="$watch('collapse', value => $refs.root.scrollIntoView({ behavior: 'smooth'}))"
|
||||
>
|
||||
<div
|
||||
x-show="collapse"
|
||||
class="absolute z-10 flex h-32 w-full flex-col-reverse items-center overflow-clip pb-4"
|
||||
>
|
||||
<button
|
||||
@click="collapse = false"
|
||||
class="bg-blue flex items-center rounded-full px-2 text-sm text-white dark:bg-blue-400"
|
||||
>
|
||||
<span>Show more</span>
|
||||
<span class="icon-svg"
|
||||
>{{ partialCached "icon" "arrow_drop_down" "arrow_drop_down" }}</span
|
||||
>
|
||||
</button>
|
||||
</div>
|
||||
<div :class="{ 'h-32': collapse }">
|
||||
{{ $result }}
|
||||
<button
|
||||
@click="collapse = true"
|
||||
x-show="!collapse"
|
||||
class="rounded-sm-b-lg bg-blue mx-auto mt-4 flex items-center px-2 text-sm text-white dark:bg-blue-800"
|
||||
>
|
||||
<span>Hide</span>
|
||||
<span class="icon-svg"
|
||||
>{{ partialCached "icon" "arrow_drop_up" "arrow_drop_up" }}</span
|
||||
>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="{ 'h-32': collapse }">
|
||||
{{ $result }}
|
||||
<button @click="collapse = true" x-show="!collapse"
|
||||
class="mx-auto -mt-4 flex items-center rounded-b-lg bg-blue-light px-2 text-sm text-white dark:bg-blue-dark-400">
|
||||
<span>Hide</span>
|
||||
<span class="icon-svg">{{ partialCached "icon" "arrow_drop_up" "arrow_drop_up" }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{ else }}
|
||||
{{ $result }}
|
||||
{{ end }}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
{{ $height := $params.Get "h" }}
|
||||
{{ $border := $params.Has "border" }}
|
||||
|
||||
|
||||
<figure
|
||||
x-data="{ zoom: false }"
|
||||
@click="zoom = ! zoom"
|
||||
|
@ -23,28 +24,28 @@
|
|||
loading="lazy"
|
||||
src="{{ $src }}"
|
||||
alt="{{ .Text }}"
|
||||
{{ with $width }} width="{{ . }}" {{ end }}
|
||||
{{ with $height }} height="{{ . }}" {{ end }}
|
||||
class="rounded mx-auto{{ with $border }} border border-divider-light dark:border-divider-dark{{end}}"
|
||||
{{ with $width }}width="{{ . }}"{{ end }}
|
||||
{{ with $height }}height="{{ . }}"{{ end }}
|
||||
class="mx-auto{{ with $border }}
|
||||
border border-divider-light dark:border-divider-dark
|
||||
{{ end }} rounded-sm"
|
||||
/>
|
||||
{{ with .Title }}
|
||||
<figcaption class="text-gray-light dark:text-gray-dark">{{ . }}</figcaption>
|
||||
<figcaption class="text-gray-200 dark:text-gray-500">{{ . }}</figcaption>
|
||||
{{ end }}
|
||||
<template x-teleport="body">
|
||||
<div
|
||||
x-show="zoom"
|
||||
@click="zoom = false"
|
||||
x-transition.opacity.duration.250ms
|
||||
class="fixed z-20 inset-0 flex items-center justify-center bg-black/70 p-6"
|
||||
class="fixed inset-0 z-20 flex items-center justify-center bg-black/70 p-6"
|
||||
>
|
||||
<button
|
||||
class="text-white fixed z-30 top-6 right-8 icon-svg"
|
||||
>
|
||||
<button class="icon-svg fixed top-6 right-8 z-30 text-white">
|
||||
{{ partialCached "icon" "close" "close" }}
|
||||
</button>
|
||||
<img
|
||||
loading="lazy"
|
||||
class="rounded max-w-full max-h-full"
|
||||
class="max-h-full max-w-full rounded-sm"
|
||||
src="{{ $src }}"
|
||||
alt="{{ .Text }}"
|
||||
/>
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
{{- if $v }}
|
||||
{{- printf " %s=%q" $k $v | safeHTMLAttr }}
|
||||
{{- end }}
|
||||
{{- end }}>
|
||||
<thead class="bg-gray-light-100 dark:bg-gray-dark-200">
|
||||
{{- end }}
|
||||
>
|
||||
<thead class="bg-gray-100 dark:bg-gray-800">
|
||||
{{- range .THead }}
|
||||
<tr>
|
||||
{{- range . }}
|
||||
<th class="p-2"
|
||||
<th
|
||||
class="p-2"
|
||||
{{- with .Alignment }}
|
||||
{{- printf " style=%q" (printf "text-align: %s" .) | safeHTMLAttr }}
|
||||
{{- end -}}
|
||||
|
@ -24,7 +26,8 @@
|
|||
{{- range .TBody }}
|
||||
<tr>
|
||||
{{- range . }}
|
||||
<td class="p-2"
|
||||
<td
|
||||
class="p-2"
|
||||
{{- with .Alignment }}
|
||||
{{- printf " style=%q" (printf "text-align: %s" .) | safeHTMLAttr }}
|
||||
{{- end -}}
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{ partial "head.html" . }}
|
||||
</head>
|
||||
|
||||
<head>
|
||||
{{ partial "head.html" . }}
|
||||
</head>
|
||||
|
||||
<body
|
||||
class="flex flex-col items-center bg-gradient-to-r from-background-light from-20% to-white to-30% text-base dark:from-gray-dark-100 dark:to-background-dark dark:text-white">
|
||||
{{ partial "header.html" . }}
|
||||
<main class="relative flex w-full max-w-[1920px]">
|
||||
<!-- Sidebar -->
|
||||
<div style="scroll-behavior: smooth;" x-data x-init="$nextTick(() => {
|
||||
<body
|
||||
class="dark:bg-navbar-bg-dark bg-navbar-bg flex flex-col items-center text-base text-black dark:text-white"
|
||||
>
|
||||
{{ partial "header.html" . }}
|
||||
<main class="relative flex w-full max-w-[1920px]">
|
||||
<!-- Sidebar -->
|
||||
<div
|
||||
style="scroll-behavior: smooth;"
|
||||
x-data
|
||||
x-init="$nextTick(() => {
|
||||
const container = $el; // The div with overflow
|
||||
const item = document.getElementById('sidebar-current-page')
|
||||
if (item) {
|
||||
|
@ -26,39 +29,51 @@
|
|||
}
|
||||
}
|
||||
})"
|
||||
class="md:h-[calc(100vh-64px)] fixed md:sticky top-0 md:top-16 z-40 hidden h-screen flex-none overflow-y-auto overflow-x-hidden bg-background-light dark:bg-gray-dark-100 w-full md:z-auto md:block md:w-[300px]"
|
||||
:class="{ 'hidden': ! $store.showSidebar }">
|
||||
<!-- Gray backdrop on small screens -->
|
||||
<div class="fixed bg-black/50 md:hidden z-30" x-show="$store.showSidebar" @click="openSidebar = false"
|
||||
x-transition.opacity></div>
|
||||
<div class="z-50 w-full bg-background-light p-4 dark:bg-gray-dark-100 md:block md:w-[300px]">
|
||||
<!-- Collapse button for small screens -->
|
||||
<button class="my-4 md:hidden" @click="$store.showSidebar = false">
|
||||
<span class="icon-svg">{{ partialCached "icon" "arrow_left_alt" "arrow_left_alt" }}</span>
|
||||
Back
|
||||
</button>
|
||||
<!-- Actual Sidebar Content -->
|
||||
{{ block "left" . }}
|
||||
{{ partial "sidebar/mainnav.html" . }}
|
||||
{{ partial "sidebar/sections.html" . }}
|
||||
class="bg-background-toc dark:bg-background-toc fixed top-0 z-40 hidden h-screen w-full flex-none overflow-x-hidden overflow-y-auto md:sticky md:top-16 md:z-auto md:block md:h-[calc(100vh-64px)] md:w-[300px]"
|
||||
:class="{ 'hidden': ! $store.showSidebar }"
|
||||
>
|
||||
<!-- Gray backdrop on small screens -->
|
||||
<div
|
||||
class="fixed bg-black/50 md:hidden"
|
||||
x-show="$store.showSidebar"
|
||||
@click="openSidebar = false"
|
||||
x-transition.opacity
|
||||
></div>
|
||||
<div
|
||||
class="bg-background-toc dark:bg-background-toc z-50 w-full p-4 md:block md:w-[300px]"
|
||||
>
|
||||
<!-- Collapse button for small screens -->
|
||||
<button class="my-4 md:hidden" @click="$store.showSidebar = false">
|
||||
<span class="icon-svg"
|
||||
>{{ partialCached "icon" "arrow_left_alt" "arrow_left_alt" }}</span
|
||||
>
|
||||
Back
|
||||
</button>
|
||||
<!-- Actual Sidebar Content -->
|
||||
{{ block "left" . }}
|
||||
{{ partial "sidebar/mainnav.html" . }}
|
||||
{{ partial "sidebar/sections.html" . }}
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<div
|
||||
{{ if ne .Params.sitemap false }}data-pagefind-body{{- end }}
|
||||
class="dark:bg-background-dark w-full min-w-0 bg-white p-8"
|
||||
>
|
||||
{{ block "main" . }}
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Main content -->
|
||||
<div {{ if ne .Params.sitemap false }}data-pagefind-body{{- end }}
|
||||
class="w-full min-w-0 bg-white p-8 dark:bg-background-dark">
|
||||
{{ block "main" . }}
|
||||
{{ end }}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="w-full z-10 relative">{{ partialCached "footer.html" . }}</footer>
|
||||
|
||||
{{/* Load the YouTube player if the page embeds a YouTube video */}}
|
||||
{{ with .Store.Get "youtube" }}
|
||||
{{ partial "youtube-script.html" . }}
|
||||
{{ end }}
|
||||
</body>
|
||||
<footer class="relative z-10 w-full">
|
||||
{{ partialCached "footer.html" . }}
|
||||
</footer>
|
||||
|
||||
{{/* Load the YouTube player if the page embeds a YouTube video */}}
|
||||
{{ with .Store.Get "youtube" }}
|
||||
{{ partial "youtube-script.html" . }}
|
||||
{{ end }}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<div class="flex w-full">
|
||||
<article class="prose min-w-0 flex-[2_2_0%] max-w-4xl dark:prose-invert">
|
||||
{{ partial "breadcrumbs.html" . }}
|
||||
<h1 class="scroll-mt-36">{{ .Title }}</h1>
|
||||
<h1>{{ .Title }}</h1>
|
||||
<div class="overflow-x-auto">
|
||||
<table>
|
||||
<tbody>
|
||||
|
@ -100,7 +100,7 @@ can be removed entirely in a future release.
|
|||
{{ $.Store.Add "headings" $heading }}
|
||||
<div class="overflow-x-auto">
|
||||
<table>
|
||||
<thead class="bg-gray-light-100 dark:bg-gray-dark-200">
|
||||
<thead class="bg-gray-100 dark:bg-gray-800">
|
||||
<tr>
|
||||
<th class="p-2">Option</th>
|
||||
<th class="p-2">Default</th>
|
||||
|
|
|
@ -3,25 +3,34 @@
|
|||
{{ end }}
|
||||
|
||||
{{ define "main" }}
|
||||
<article class="prose max-w-none dark:prose-invert">
|
||||
<article class="prose dark:prose-invert max-w-none">
|
||||
<h1 class="py-4">{{ .Title }}</h1>
|
||||
{{ .Content }}
|
||||
<div class="not-prose">
|
||||
<div class="flex flex-col lg:flex-row justify-between gap-8">
|
||||
<input type="search" id="search-page-input"
|
||||
class="min-w-0 ring-[1.5px] ring-gray-light-200 dark:ring-gray-dark-400 w-full max-w-xl rounded px-4 py-2 outline-none bg-white dark:bg-background-dark focus:ring-blue-light dark:focus:ring-blue-dark"
|
||||
placeholder="Search…" tabindex="0" />
|
||||
<div class="flex min-w-fit flex-col flex-grow items-center">
|
||||
<div class="flex flex-col justify-between gap-8 lg:flex-row">
|
||||
<input
|
||||
type="search"
|
||||
id="search-page-input"
|
||||
class="ring-3-gray-light-200 dark:ring-3-gray-dark-400 dark:bg-background-dark focus:ring-3-blue-light dark:focus:ring-3-blue-dark ring-3-[1.5px] w-full max-w-xl min-w-0 rounded-sm bg-white px-4 py-2 outline-hidden"
|
||||
placeholder="Search…"
|
||||
tabindex="0"
|
||||
/>
|
||||
<div class="flex min-w-fit flex-grow flex-col items-center">
|
||||
<p>Not finding what you're looking for?</p>
|
||||
<button
|
||||
class="px-2 py-1 font-semibold rounded open-kapa-widget flex w-fit gap-2 items-center hover:bg-gray-light-200 dark:hover:bg-gray-dark-200">
|
||||
class="open-kapa-widget flex w-fit items-center gap-2 rounded-sm px-2 py-1 font-semibold hover:bg-gray-200 dark:hover:bg-gray-800"
|
||||
>
|
||||
<span>Try Ask AI</span>
|
||||
<img height="24px" width="24px" src="{{ (resources.Get "images/ai-stars.svg").Permalink }}"
|
||||
alt="AI sparkles!" />
|
||||
<img
|
||||
height="24px"
|
||||
width="24px"
|
||||
src="{{ (resources.Get "images/ai-stars.svg").Permalink }}"
|
||||
alt="AI sparkles!"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="border-divider-light dark:border-divider-dark">
|
||||
<hr class="border-divider-light dark:border-divider-dark" />
|
||||
<div id="search-page-results">
|
||||
<!-- results -->
|
||||
</div>
|
||||
|
@ -124,14 +133,14 @@
|
|||
}
|
||||
|
||||
// Generate the search results HTML
|
||||
let resultsHTML = `<div class="text-gray-light dark:text-gray-dark p-2">${resultsLength} results</div>`;
|
||||
let resultsHTML = `<div class="text-gray-200 dark:text-gray-500 p-2">${resultsLength} results</div>`;
|
||||
|
||||
// Map results to HTML
|
||||
resultsHTML += results
|
||||
.map((item) => {
|
||||
return `<div class="p-4">
|
||||
<div class="flex flex-col">
|
||||
<span class="text-gray-light dark:texty-gray-dark text-sm">${item.meta.breadcrumbs}</span>
|
||||
<span class="text-gray-200 dark:texty-gray-dark text-sm">${item.meta.breadcrumbs}</span>
|
||||
<a class="link" href="${item.url}" data-query="${query}" data-index="${item.index}">${item.meta.title}</a>
|
||||
<p class="text-black dark:text-white overflow-hidden">…${item.excerpt}…</p>
|
||||
</div>
|
||||
|
@ -140,7 +149,7 @@
|
|||
.join("");
|
||||
// If the results length is greater than 10, display links to show more results
|
||||
if (resultsLength > 10) {
|
||||
resultsHTML += `<hr class="border-divider-light dark:border-divider-dark">`
|
||||
resultsHTML += `<hr class="border-divider-light dark:border-divider-dark">`;
|
||||
resultsHTML += `<ul class="flex flex-wrap gap-1 pt-4 pb-8 justify-center text-sm">`;
|
||||
for (let i = 1; i <= resultsLength / 10; i++) {
|
||||
if (i == currentPage) {
|
||||
|
@ -148,8 +157,8 @@
|
|||
<a href="/search/?q=${query}&page=${i}" class="block h-6 w-6 rounded-sm bg-blue-light dark:bg-blue-dark">${i}</a>
|
||||
</li>`;
|
||||
} else {
|
||||
resultsHTML += `<li class="text-center text-gray-light dark:text-gray-dark">
|
||||
<a href="/search/?q=${query}&page=${i}" class="block h-6 w-6 rounded-sm bg-gray-light-200 dark:bg-gray-dark-200">${i}</a>
|
||||
resultsHTML += `<li class="text-center text-gray-200 dark:text-gray-500">
|
||||
<a href="/search/?q=${query}&page=${i}" class="block h-6 w-6 rounded-sm bg-gray-200 dark:bg-gray-800">${i}</a>
|
||||
</li>`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{{ define "main" }}
|
||||
<article class="prose min-w-0 flex-[2_2_0%] max-w-4xl dark:prose-invert">
|
||||
<article class="prose dark:prose-invert max-w-4xl min-w-0 flex-[2_2_0%]">
|
||||
{{ partial "breadcrumbs.html" . }}
|
||||
<h1 data-pagefind-weight="10" class="scroll-mt-36">{{ .Title }}</h1>
|
||||
<h1 data-pagefind-weight="10">{{ .Title }}</h1>
|
||||
<div class="block lg:hidden">
|
||||
{{ partialCached "pagemeta.html" . . }}
|
||||
<hr />
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
{{ define "left" }}
|
||||
{{- partial "sidebar/mainnav.html" . }}
|
||||
<div class="p-4 flex flex-col gap-2 text-sm">
|
||||
<p>Filter guides by tag or programming language.<p>
|
||||
<div class="space-y-4" x-data="{
|
||||
{{- partial "sidebar/mainnav.html" . }}
|
||||
<div class="navbar-font flex flex-col gap-2 p-4 text-sm">
|
||||
<p>Filter guides by tag or programming language.</p>
|
||||
<p></p>
|
||||
<div
|
||||
class="space-y-4"
|
||||
x-data="{
|
||||
filters: { tags: [], languages: [] },
|
||||
toggleFilter(grp, tag) {
|
||||
this.filters[grp].includes(tag)
|
||||
|
@ -20,7 +23,7 @@
|
|||
|
||||
this.$dispatch('guide-filter', { filters: this.filters });
|
||||
},
|
||||
|
||||
|
||||
init() {
|
||||
const url = new URL(window.location.href);
|
||||
const tags = url.searchParams.get('tags')
|
||||
|
@ -32,42 +35,59 @@
|
|||
this.filters['languages'] = langs.split('~');
|
||||
}
|
||||
}
|
||||
}" @guide-filter.window="filters = $event.detail.filters;">
|
||||
<div class="pl-2"><strong>Tags</strong></div>
|
||||
<fieldset class="flex flex-col gap-2">
|
||||
{{- range $name, $taxonomy := where site.Taxonomies.tags ".Page.Type" "guides" }}
|
||||
{{- $id := anchorize (fmt.Printf "tag-%s" $name) }}
|
||||
<div class="pl-2 flex gap-2">
|
||||
<input value="{{ $name }}" type="checkbox" id="{{ $id }}" @change="toggleFilter('tags', '{{ $name }}')"
|
||||
:checked="filters['tags'].includes('{{ $name }}')">
|
||||
<label class="select-none" for="{{ $id }}">{{ .Page.LinkTitle }}</label>
|
||||
</div>
|
||||
{{ end }}
|
||||
</fieldset>
|
||||
<div class="pl-2"><strong>Languages</strong></div>
|
||||
<fieldset class="pl-2 flex flex-wrap gap-2">
|
||||
{{- range $name, $taxonomy := where site.Taxonomies.languages ".Page.Type" "guides" }}
|
||||
{{- $id := anchorize (fmt.Printf "lang-%s" $name) }}
|
||||
<button
|
||||
class="px-2 py-1 rounded-full flex gap-1 bg-white dark:bg-gray-dark-300 border border-divider-light dark:border-divider-dark"
|
||||
:class="{ 'ring-2 ring-blue-light-400 dark:ring-blue-dark-400': filters['languages'].includes('{{ $name }}') }"
|
||||
@click="toggleFilter('languages', '{{ $name }}')">
|
||||
<img height="18" width="18" title="{{ .Page.LinkTitle }}" src="{{ .Page.Params.icon }}">
|
||||
<span>{{ .Page.LinkTitle }}</span>
|
||||
</button>
|
||||
{{ end }}
|
||||
</fieldset>
|
||||
}"
|
||||
@guide-filter.window="filters = $event.detail.filters;"
|
||||
>
|
||||
<div class="pl-2"><strong>Tags</strong></div>
|
||||
<fieldset class="flex flex-col gap-2">
|
||||
{{- range $name, $taxonomy := where site.Taxonomies.tags ".Page.Type" "guides" }}
|
||||
{{- $id := anchorize (fmt.Printf "tag-%s" $name) }}
|
||||
<div class="flex gap-2 pl-2">
|
||||
<input
|
||||
value="{{ $name }}"
|
||||
type="checkbox"
|
||||
id="{{ $id }}"
|
||||
@change="toggleFilter('tags', '{{ $name }}')"
|
||||
:checked="filters['tags'].includes('{{ $name }}')"
|
||||
/>
|
||||
<label class="select-none" for="{{ $id }}"
|
||||
>{{ .Page.LinkTitle }}</label
|
||||
>
|
||||
</div>
|
||||
{{ end }}
|
||||
</fieldset>
|
||||
<div class="pl-2"><strong>Languages</strong></div>
|
||||
<fieldset class="flex flex-wrap gap-2 pl-2">
|
||||
{{- range $name, $taxonomy := where site.Taxonomies.languages ".Page.Type" "guides" }}
|
||||
{{- $id := anchorize (fmt.Printf "lang-%s" $name) }}
|
||||
<button
|
||||
class="border-divider-light dark:border-divider-dark flex gap-1 rounded-full border bg-white px-2 py-1 dark:bg-gray-800"
|
||||
:class="{ 'ring-3-2 ring-3-blue-light-400 dark:ring-3-blue-dark-400': filters['languages'].includes('{{ $name }}') }"
|
||||
@click="toggleFilter('languages', '{{ $name }}')"
|
||||
>
|
||||
<img
|
||||
height="18"
|
||||
width="18"
|
||||
title="{{ .Page.LinkTitle }}"
|
||||
src="{{ .Page.Params.icon }}"
|
||||
/>
|
||||
<span>{{ .Page.LinkTitle }}</span>
|
||||
</button>
|
||||
{{ end }}
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ define "main" }}
|
||||
<div class="flex gap-8 w-full">
|
||||
<article class="prose min-w-0 max-w-none dark:prose-invert">
|
||||
{{- partial "breadcrumbs.html" . }}
|
||||
<h1 data-pagefind-weight="10" class="scroll-mt-36">{{ .Title }}</h1>
|
||||
{{ .Content }}
|
||||
<div class="not-prose min-h-screen" x-data="{
|
||||
<div class="flex w-full gap-8">
|
||||
<article class="prose dark:prose-invert max-w-none min-w-0">
|
||||
{{- partial "breadcrumbs.html" . }}
|
||||
<h1 data-pagefind-weight="10" class="scroll-mt-36">{{ .Title }}</h1>
|
||||
{{ .Content }}
|
||||
<div
|
||||
class="not-prose min-h-screen"
|
||||
x-data="{
|
||||
filters: { tags: [], languages: [] },
|
||||
hidden: [],
|
||||
total: {{ len .Pages }},
|
||||
|
@ -123,99 +143,127 @@
|
|||
}
|
||||
this.updateVisible();
|
||||
}
|
||||
}" x-cloak
|
||||
@guide-filter.window="filters = $event.detail.filters; updateVisible(); $nextTick(() => { window.scrollTo({ top: 0 }) })">
|
||||
<div x-show="noFilters()">
|
||||
<h2>Featured guides</h2>
|
||||
<div class="not-prose py-4 grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-8">
|
||||
{{- $featured := where .Pages "Params.featured" true }}
|
||||
{{- with $featured }}
|
||||
{{- range . }}
|
||||
<div class="flex flex-col h-full">
|
||||
<a class="hover:underline" href="{{ .Permalink }}">
|
||||
{{- $img := resources.Get (.Params.image | default "/images/thumbnail.webp") }}
|
||||
{{- $img = $img.Process "resize 600x" }}
|
||||
<img class="h-48 w-full object-cover rounded shadow" src="{{ $img.Permalink }}">
|
||||
<p class="text-xl leading-snug my-4">{{ .Title }}</p>
|
||||
</a>
|
||||
<p class="flex-grow text-sm">{{ .Summary }}</p>
|
||||
<div class="mt-4">
|
||||
{{ template "guide-metadata" . }}
|
||||
}"
|
||||
x-cloak
|
||||
@guide-filter.window="filters = $event.detail.filters; updateVisible(); $nextTick(() => { window.scrollTo({ top: 0 }) })"
|
||||
>
|
||||
<div x-show="noFilters()">
|
||||
<h2>Featured guides</h2>
|
||||
<div
|
||||
class="not-prose grid grid-cols-1 gap-8 py-4 lg:grid-cols-2 xl:grid-cols-3"
|
||||
>
|
||||
{{- $featured := where .Pages "Params.featured" true }}
|
||||
{{- with $featured }}
|
||||
{{- range . }}
|
||||
<div class="flex h-full flex-col">
|
||||
<a class="hover:underline" href="{{ .Permalink }}">
|
||||
{{- $img := resources.Get (.Params.image | default "/images/thumbnail.webp") }}
|
||||
{{- $img = $img.Process "resize 600x" }}
|
||||
<img
|
||||
class="h-48 w-full rounded-sm object-cover shadow"
|
||||
src="{{ $img.Permalink }}"
|
||||
/>
|
||||
<p class="my-4 text-xl leading-snug">{{ .Title }}</p>
|
||||
</a>
|
||||
<p class="flex-grow text-sm">{{ .Summary }}</p>
|
||||
<div class="mt-4">
|
||||
{{ template "guide-metadata" . }}
|
||||
</div>
|
||||
</div>
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
</div>
|
||||
<hr class="text-divider-light dark:text-divider-dark" />
|
||||
</div>
|
||||
<h2 x-show="noFilters()" id="all-guides" class="scroll-mt-36">
|
||||
All guides
|
||||
</h2>
|
||||
<div x-show="!noFilters()" class="flex flex-col gap-2 pb-8">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="icon-svg icon-sm mb-1"
|
||||
>{{ partialCached "icon" "filter_alt" "filter_alt" }}</span
|
||||
>
|
||||
<p>
|
||||
Filtered results: showing
|
||||
<span x-text="total - hidden.length"></span> out of
|
||||
<span x-text="total"></span> guides.
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 pl-4">
|
||||
{{- range $name, $taxonomy := site.Taxonomies.tags }}
|
||||
<div x-show="filters.tags.includes('{{ $name }}')">
|
||||
{{ template "termchip" $taxonomy.Page.LinkTitle }}
|
||||
</div>
|
||||
{{- end }}
|
||||
{{- range $name, $taxonomy := site.Taxonomies.languages }}
|
||||
<div
|
||||
x-show="filters.languages.includes('{{ $name }}')"
|
||||
class="border-divider-light dark:border-divider-dark inline-flex items-center gap-1 rounded-full border bg-gray-100 px-2 text-sm text-gray-200 select-none dark:bg-gray-800 dark:text-gray-300"
|
||||
>
|
||||
<img
|
||||
class="py-1"
|
||||
height="18"
|
||||
width="18"
|
||||
title="{{ .Page.LinkTitle }}"
|
||||
src="{{ .Page.Params.icon }}"
|
||||
/>
|
||||
<span>{{ .Page.LinkTitle }}</span>
|
||||
</div>
|
||||
{{- end }}
|
||||
</div>
|
||||
</div>
|
||||
<div x-ref="guide-container">
|
||||
{{- range .Pages }}
|
||||
<div
|
||||
id="guide-{{ math.Counter }}"
|
||||
data-languages="{{ jsonify (.Params.languages | default slice) }}"
|
||||
data-tags="{{ jsonify (.Params.tags | default slice) }}"
|
||||
x-show="isVisible($el);"
|
||||
class="border-divider-light dark:border-divider-dark flex flex-col justify-between border-b p-4 hover:bg-gray-100 hover:dark:bg-gray-800"
|
||||
>
|
||||
<div class="flex flex-col justify-between xl:flex-row">
|
||||
<a
|
||||
href="{{ .Permalink }}"
|
||||
class="mb-2 truncate text-lg hover:underline xl:mb-0"
|
||||
>{{ .Title }}</a
|
||||
>
|
||||
{{ template "guide-metadata" . }}
|
||||
</div>
|
||||
</div>
|
||||
{{- end }}
|
||||
</div>
|
||||
<hr class="text-divider-light dark:text-divider-dark">
|
||||
</div>
|
||||
<h2 x-show="noFilters()" id="all-guides" class="scroll-mt-36">All guides</h2>
|
||||
<div x-show="!noFilters()" class="pb-8 flex flex-col gap-2">
|
||||
<div class="flex gap-2 items-center">
|
||||
<span class="mb-1 icon-svg icon-sm">{{ partialCached "icon" "filter_alt" "filter_alt" }}</span>
|
||||
<p>Filtered results: showing <span x-text="total - hidden.length"></span> out of <span x-text="total"></span> guides.</p>
|
||||
</div>
|
||||
<div class="pl-4 flex gap-2 items-center">
|
||||
{{- range $name, $taxonomy := site.Taxonomies.tags }}
|
||||
<div x-show="filters.tags.includes('{{$name}}')">{{ template "termchip" $taxonomy.Page.LinkTitle }}</div>
|
||||
{{- end }}
|
||||
{{- range $name, $taxonomy := site.Taxonomies.languages }}
|
||||
<div x-show="filters.languages.includes('{{$name}}')"
|
||||
class="text-sm inline-flex gap-1 items-center rounded-full border
|
||||
border-divider-light dark:border-divider-dark bg-gray-light-100
|
||||
px-2 text-gray-light-800 dark:bg-gray-dark-200
|
||||
dark:text-gray-dark-800 select-none">
|
||||
<img class="py-1" height="18" width="18" title="{{ .Page.LinkTitle }}" src="{{ .Page.Params.icon }}">
|
||||
<span>{{ .Page.LinkTitle }}</span>
|
||||
</div>
|
||||
{{- end }}
|
||||
</div>
|
||||
</div>
|
||||
<div x-ref="guide-container">
|
||||
{{- range .Pages }}
|
||||
<div
|
||||
id="guide-{{ math.Counter }}"
|
||||
data-languages='{{ jsonify (.Params.languages | default slice) }}'
|
||||
data-tags='{{ jsonify (.Params.tags | default slice) }}'
|
||||
x-show="isVisible($el);"
|
||||
class="flex flex-col justify-between p-4 border-b border-divider-light
|
||||
hover:bg-gray-light-100 hover:dark:bg-gray-dark-200
|
||||
dark:border-divider-dark">
|
||||
<div class="flex flex-col xl:flex-row justify-between">
|
||||
<a href="{{ .Permalink }}" class="text-lg hover:underline mb-2 xl:mb-0 truncate">{{ .Title }}</a>
|
||||
{{ template "guide-metadata" . }}
|
||||
</div>
|
||||
</div>
|
||||
{{- end }}
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{- define "guide-metadata" }}
|
||||
<div class="text-sm flex gap-8 items-center justify-between text-gray-light dark:text-gray-dark">
|
||||
<div class="flex flex-wrap md:flex-nowrap gap-2">
|
||||
{{- $langs := .GetTerms "languages" }}
|
||||
{{ partial "languages" $langs }}
|
||||
{{- $tags := .GetTerms "tags" }}
|
||||
{{- range $tags }}
|
||||
{{ template "termchip" .Page.LinkTitle }}
|
||||
<div
|
||||
class="flex items-center justify-between gap-8 text-sm text-gray-200 dark:text-gray-300"
|
||||
>
|
||||
<div class="flex flex-wrap gap-2 md:flex-nowrap">
|
||||
{{- $langs := .GetTerms "languages" }}
|
||||
{{ partial "languages" $langs }}
|
||||
{{- $tags := .GetTerms "tags" }}
|
||||
{{- range $tags }}
|
||||
{{ template "termchip" .Page.LinkTitle }}
|
||||
{{- end }}
|
||||
</div>
|
||||
{{- with .Params.time }}
|
||||
<div class="flex flex-shrink gap-2 whitespace-nowrap">
|
||||
<span class="icon-svg"
|
||||
>{{ partialCached "icon" "schedule" "schedule" }}</span
|
||||
>
|
||||
<span>{{ . }}</span>
|
||||
</div>
|
||||
{{- end }}
|
||||
</div>
|
||||
{{- with .Params.time }}
|
||||
<div class="flex whitespace-nowrap flex-shrink gap-2">
|
||||
<span class="icon-svg">{{ partialCached "icon" "schedule" "schedule" }}</span>
|
||||
<span>{{ . }}</span>
|
||||
</div>
|
||||
{{- end }}
|
||||
</div>
|
||||
{{- end }}
|
||||
|
||||
{{- define "termchip" }}
|
||||
<span class="whitespace-nowrap inline-flex text-sm min-w-0 items-center rounded-full
|
||||
border border-divider-light dark:border-divider-dark
|
||||
bg-gray-light-100 px-2 text-gray-light-800 dark:bg-gray-dark-200
|
||||
dark:text-gray-dark-800 select-none">
|
||||
<span
|
||||
class="border-divider-light dark:border-divider-dark inline-flex min-w-0 items-center rounded-full border bg-gray-100 px-2 text-sm whitespace-nowrap text-gray-200 select-none dark:bg-gray-800 dark:text-gray-300"
|
||||
>
|
||||
<span class="icon-svg icon-sm pb-0.5">
|
||||
{{ partialCached "icon" "tag" "tag" }}
|
||||
</span>
|
||||
|
|
|
@ -6,13 +6,17 @@
|
|||
{{ define "main" }}
|
||||
{{ partial "content-default.html" . }}
|
||||
<div class="prose dark:prose-invert max-w-4xl">
|
||||
<div class="md-dropdown ml-auto hidden lg:block">
|
||||
{{ partial "md-dropdown.html" . }}
|
||||
</div>
|
||||
{{ if (.Store.Get "multipage") }}
|
||||
{{- with .PrevInSection }}
|
||||
<div class="col-start-2 not-prose my-4">
|
||||
<a href="{{ .Permalink }}"
|
||||
class="cursor-pointer py-2 px-4 rounded bg-blue-light-500
|
||||
dark:bg-blue-dark-400 hover:bg-blue-light-400
|
||||
dark:hover:bg-blue-dark-500 text-white">{{ .Title }} »</a>
|
||||
<div class="not-prose col-start-2 my-4">
|
||||
<a
|
||||
href="{{ .Permalink }}"
|
||||
class="cursor-pointer rounded-sm bg-blue-500 px-4 py-2 text-white hover:bg-blue-400 dark:bg-blue-800 dark:hover:bg-blue-700"
|
||||
>{{ .Title }} »</a
|
||||
>
|
||||
</div>
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
|
|
@ -1,262 +1,322 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{ partial "head.html" . }}
|
||||
</head>
|
||||
|
||||
<head>
|
||||
{{ partial "head.html" . }}
|
||||
</head>
|
||||
|
||||
<body class="flex h-max flex-col bg-background-light text-base dark:bg-background-dark dark:text-white">
|
||||
<div class="absolute -z-10 w-full">
|
||||
<svg class="dark:hidden" viewBox="0 0 1616 797" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1066.69 797L0 136.789V0H1616V488.038L1066.69 797Z" fill="#EFEFF2" />
|
||||
</svg>
|
||||
<svg class="hidden dark:block" viewBox="0 0 1616 797" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1066.69 797L0 136.789V0H1616V488.038L1066.69 797Z" fill="#080B0E" fill-opacity="0.3" />
|
||||
</svg>
|
||||
</div>
|
||||
{{ partial "header.html" . }}
|
||||
<main class="flex min-h-screen w-full flex-col items-stretch self-center">
|
||||
<div class="flex xl:w-[1200px] flex-col items-stretch gap-20 self-center py-20 w-full px-4">
|
||||
<div class="bg-pattern-blue relative overflow-hidden rounded drop-shadow">
|
||||
<div class="flex h-full flex-col items-start justify-between gap-4 p-8">
|
||||
<div class="flex items-center gap-6">
|
||||
<span class="icon-svg text-violet-light dark:text-violet-dark">
|
||||
{{ partial "icon" "play_circle" }}</span>
|
||||
<h1 class="text-2xl">Get Docker</h1>
|
||||
</div>
|
||||
<p>
|
||||
Learn how to install Docker for Mac, Windows, or Linux and explore
|
||||
our developer tools.
|
||||
</p>
|
||||
<a href="/get-started/get-docker/"
|
||||
class="mt-20 flex cursor-pointer items-center gap-2 rounded bg-blue-light p-2 px-4 text-white transition duration-300 hover:bg-blue-light-400 dark:bg-blue-dark-400 dark:hover:bg-blue-dark">
|
||||
<span class="icon-svg">{{ partial "icon" "download"}}</span>
|
||||
Get Docker
|
||||
</a>
|
||||
</div>
|
||||
<div class="absolute bottom-0 right-0 origin-bottom-right scale-50 lg:scale-100">
|
||||
<img class="dark:hidden" alt="Low-fi desktop app" src="/assets/images/app-wf-light-1.svg" />
|
||||
<img class="hidden dark:block" alt="Low-fi desktop app" src="/assets/images/app-wf-dark-1.svg" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="grid grid-cols-1 gap-4 lg:grid-cols-4">
|
||||
|
||||
<div>
|
||||
<a class="h-full" href="/get-started/">
|
||||
<div
|
||||
class="flex h-full flex-col gap-2 rounded border border-gray-light-100 bg-white p-4 drop-shadow-sm hover:border-gray-light-200 hover:drop-shadow-lg dark:border-gray-dark-400 dark:bg-gray-dark-200 hover:dark:border-gray-dark">
|
||||
<div class="flex items-center gap-4">
|
||||
<span class="icon-svg text-violet-light dark:text-violet-dark">
|
||||
{{ partial "icon" "rocket" }}
|
||||
</span>
|
||||
<div>
|
||||
<div class="text-xl leading-snug text-gray-light-800 dark:text-white">
|
||||
Get started
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="leading-snug text-gray-light-500 dark:text-gray-dark-700">
|
||||
Learn Docker basics and the benefits of containerization.
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a class="h-full" href="/guides/">
|
||||
<div
|
||||
class="flex h-full flex-col gap-2 rounded border border-gray-light-100 bg-white p-4 drop-shadow-sm hover:border-gray-light-200 hover:drop-shadow-lg dark:border-gray-dark-400 dark:bg-gray-dark-200 hover:dark:border-gray-dark">
|
||||
<div class="flex items-center gap-4">
|
||||
<span class="icon-svg text-violet-light dark:text-violet-dark">
|
||||
{{ partial "icon" "developer_guide" }}
|
||||
</span>
|
||||
<div>
|
||||
<div class="text-xl leading-snug text-gray-light-800 dark:text-white">
|
||||
Guides
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="leading-snug text-gray-light-500 dark:text-gray-dark-700">
|
||||
Learn how Docker can optimize your development workflows.
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a class="h-full" href="/manuals/">
|
||||
<div
|
||||
class="flex h-full flex-col gap-2 rounded border border-gray-light-100 bg-white p-4 drop-shadow-sm hover:border-gray-light-200 hover:drop-shadow-lg dark:border-gray-dark-400 dark:bg-gray-dark-200 hover:dark:border-gray-dark">
|
||||
<div class="flex items-center gap-4">
|
||||
<span class="icon-svg text-violet-light dark:text-violet-dark">
|
||||
{{ partial "icon" "description" }}
|
||||
</span>
|
||||
<div>
|
||||
<div class="text-xl leading-snug text-gray-light-800 dark:text-white">
|
||||
Manuals
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="leading-snug text-gray-light-500 dark:text-gray-dark-700">
|
||||
Learn how to install, set up, configure, and use Docker
|
||||
products.
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a class="h-full" href="/reference/">
|
||||
<div
|
||||
class="flex h-full flex-col gap-2 rounded border border-gray-light-100 bg-white p-4 drop-shadow-sm hover:border-gray-light-200 hover:drop-shadow-lg dark:border-gray-dark-400 dark:bg-gray-dark-200 hover:dark:border-gray-dark">
|
||||
<div class="flex items-center gap-4">
|
||||
<span class="icon-svg text-violet-light dark:text-violet-dark">
|
||||
{{ partial "icon" "terminal" }}
|
||||
</span>
|
||||
<div>
|
||||
<div class="text-xl leading-snug text-gray-light-800 dark:text-white">
|
||||
Reference
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="leading-snug text-gray-light-500 dark:text-gray-dark-700">
|
||||
Browse the CLI and API documentation.
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="z-10 grid grid-cols-1 gap-20 lg:grid-cols-2">
|
||||
<div class="bg-pattern-verde relative rounded p-6 drop-shadow">
|
||||
<div class="flex h-full flex-col items-start justify-between gap-12">
|
||||
<div class="flex flex-col gap-4">
|
||||
<h2 class="font-medium">Gen AI catalog {{ partial
|
||||
"components/badge.html" (dict "color" "blue" "content" "New")
|
||||
}}</h2>
|
||||
<p class="text-xl">
|
||||
Integrate AI solutions into your apps with minimal effort
|
||||
</p>
|
||||
<body
|
||||
class="flex h-max flex-col bg-gray-50 text-base dark:bg-gray-950 dark:text-white"
|
||||
>
|
||||
<div class="absolute -z-10 w-full">
|
||||
<svg
|
||||
class="dark:hidden"
|
||||
viewBox="0 0 1616 797"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M1066.69 797L0 136.789V0H1616V488.038L1066.69 797Z"
|
||||
fill="#EFEFF2"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
class="hidden dark:block"
|
||||
viewBox="0 0 1616 797"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M1066.69 797L0 136.789V0H1616V488.038L1066.69 797Z"
|
||||
fill="#080B0E"
|
||||
fill-opacity="0.3"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
{{ partial "header.html" . }}
|
||||
<main class="flex min-h-screen w-full flex-col items-stretch self-center">
|
||||
<div
|
||||
class="flex w-full flex-col items-stretch gap-20 self-center px-4 py-20 xl:w-[1200px]"
|
||||
>
|
||||
<div
|
||||
class="bg-pattern-blue relative overflow-hidden rounded-sm drop-shadow"
|
||||
>
|
||||
<div
|
||||
class="flex h-full flex-col items-start justify-between gap-4 p-8"
|
||||
>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="icon-svg text-blue dark:text-blue">
|
||||
{{ partial "icon" "play_circle" }}</span
|
||||
>
|
||||
<h1 class="text-2xl">Get Docker</h1>
|
||||
</div>
|
||||
<div class="flex flex-col xl:flex-row gap-4 items-start">
|
||||
<a href="https://hub.docker.com/catalogs/gen-ai"
|
||||
class="flex cursor-pointer items-center gap-2 rounded bg-blue-light p-2 px-4 text-white transition duration-300 hover:bg-blue-light-400 dark:bg-blue-dark-400 dark:hover:bg-blue-dark">
|
||||
Explore on Docker Hub
|
||||
<p>
|
||||
Learn how to install Docker for Mac, Windows, or Linux and explore
|
||||
our developer tools.
|
||||
</p>
|
||||
<a
|
||||
href="/get-started/get-docker/"
|
||||
class="bg-blue mt-20 flex cursor-pointer items-center gap-2 rounded-sm p-2 px-4 text-white transition duration-300 hover:bg-blue-500 dark:bg-blue-500 dark:hover:bg-blue-400"
|
||||
>
|
||||
<span class="icon-svg">{{ partial "icon" "download" }}</span>
|
||||
Get Docker
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
class="absolute right-0 bottom-0 origin-bottom-right scale-50 lg:scale-100"
|
||||
>
|
||||
<img
|
||||
class="dark:hidden"
|
||||
alt="Low-fi desktop app"
|
||||
src="/assets/images/app-wf-light-1.svg"
|
||||
/>
|
||||
<img
|
||||
class="hidden dark:block"
|
||||
alt="Low-fi desktop app"
|
||||
src="/assets/images/app-wf-dark-1.svg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="grid grid-cols-1 gap-4 lg:grid-cols-4">
|
||||
<div>
|
||||
<a class="h-full" href="/get-started/">
|
||||
<div class="section-card">
|
||||
<div class="flex items-center gap-4">
|
||||
<span class="icon-svg text-blue dark:text-blue">
|
||||
{{ partial "icon" "rocket" }}
|
||||
</span>
|
||||
<div>
|
||||
<div class="section-card-title">Get started</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section-card-text">
|
||||
Learn Docker basics and the benefits of containerization.
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a href="/docker-hub/image-library/catalogs/"
|
||||
class="flex-grow-0 flex cursor-pointer items-center gap-2 rounded bg-blue-light p-2 px-4 text-white transition duration-300 hover:bg-blue-light-400 dark:bg-blue-dark-400 dark:hover:bg-blue-dark">
|
||||
Read the docs
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a class="h-full" href="/guides/">
|
||||
<div class="section-card">
|
||||
<div class="flex items-center gap-4">
|
||||
<span class="icon-svg text-blue dark:text-blue">
|
||||
{{ partial "icon" "developer_guide" }}
|
||||
</span>
|
||||
<div>
|
||||
<div class="section-card-title">Guides</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section-card-text">
|
||||
Learn how Docker can optimize your development workflows.
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a class="h-full" href="/manuals/">
|
||||
<div class="section-card">
|
||||
<div class="flex items-center gap-4">
|
||||
<span class="icon-svg text-blue dark:text-blue">
|
||||
{{ partial "icon" "description" }}
|
||||
</span>
|
||||
<div>
|
||||
<div class="section-card-title">Manuals</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section-card-text">
|
||||
Learn how to install, set up, configure, and use Docker
|
||||
products.
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a class="h-full" href="/reference/">
|
||||
<div class="section-card">
|
||||
<div class="flex items-center gap-4">
|
||||
<span class="icon-svg text-blue dark:text-blue">
|
||||
{{ partial "icon" "terminal" }}
|
||||
</span>
|
||||
<div>
|
||||
<div class="section-card-title">Reference</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section-card-text">
|
||||
Browse the CLI and API documentation.
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="absolute bottom-0 right-0 origin-bottom-right scale-75 md:scale-100">
|
||||
<img class="dark:hidden" alt="Low-fi desktop app" src="/assets/images/app-wf-light-2.svg" />
|
||||
<img class="hidden dark:block" alt="Low-fi desktop app" src="/assets/images/app-wf-dark-2.svg" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="rounded-[6px] bg-gradient-to-br from-blue-light-400 to-magenta-light-400 dark:from-blue-dark-400 dark:to-magenta-dark-400 p-[2px] drop-shadow">
|
||||
<div class="bg-pattern-purple rounded p-6">
|
||||
<div class="flex flex-col gap-12">
|
||||
|
||||
<div class="z-10 grid grid-cols-1 gap-20 lg:grid-cols-2">
|
||||
<div class="bg-pattern-verde relative rounded-sm p-6 drop-shadow">
|
||||
<div
|
||||
class="flex h-full flex-col items-start justify-between gap-12"
|
||||
>
|
||||
<div class="flex flex-col gap-4">
|
||||
<h2 class="font-medium">
|
||||
Docker Model Runner
|
||||
{{ partial "components/badge.html" (dict "color" "blue" "content" "Beta") }}
|
||||
Gen AI catalog
|
||||
{{ partial
|
||||
"components/badge.html" (dict "color" "blue" "content" "New")
|
||||
}}
|
||||
</h2>
|
||||
<p class="text-xl">
|
||||
Run, test, and serve AI models locally in seconds — no setup, no hassle.
|
||||
</p>
|
||||
<p>
|
||||
Whether you’re experimenting with the latest LLMs or deploying to production,
|
||||
Docker Model Runner brings the performance and control you need, without the friction.
|
||||
|
||||
Integrate AI solutions into your apps with minimal effort
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-col xl:flex-row gap-4 items-start">
|
||||
<a href="/desktop/features/model-runner/"
|
||||
class="max-w-fit cursor-pointer rounded bg-blue-light px-4 py-2 text-white transition duration-300 hover:bg-blue-light-400 dark:bg-blue-dark-400 dark:hover:bg-blue-dark">Read the docs</a>
|
||||
<div class="flex flex-col items-start gap-4 xl:flex-row">
|
||||
<a
|
||||
href="https://hub.docker.com/catalogs/gen-ai"
|
||||
class="bg-blue dark:bg-blue rounded-sm p-2 px-4 text-white transition duration-300 hover:bg-blue-500 dark:hover:bg-blue-500"
|
||||
>
|
||||
Explore on Docker Hub
|
||||
</a>
|
||||
<a
|
||||
href="/docker-hub/image-library/catalogs/"
|
||||
class="bg-blue dark:bg-blue rounded-sm p-2 px-4 text-white transition duration-300 hover:bg-blue-500 dark:hover:bg-blue-500"
|
||||
>
|
||||
Read the docs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 class="mb-4 text-xl">Browse by section</h2>
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
||||
{{ range .Params.grid }}
|
||||
<div>
|
||||
<div
|
||||
class="flex h-full flex-col gap-2 rounded border border-gray-light-100 bg-white p-4 drop-shadow-sm dark:border-gray-dark-400 dark:bg-gray-dark-200">
|
||||
<div class="flex items-center gap-4">
|
||||
<span class="icon-svg text-gray-light dark:text-gray-dark">{{ partial "icon" .icon }}</span>
|
||||
<div>
|
||||
<div class="text-xl">{{ .title }}</div>
|
||||
class="absolute right-0 bottom-0 origin-bottom-right scale-75 md:scale-100"
|
||||
>
|
||||
<img
|
||||
class="dark:hidden"
|
||||
alt="Low-fi desktop app"
|
||||
src="/assets/images/app-wf-light-2.svg"
|
||||
/>
|
||||
<img
|
||||
class="hidden dark:block"
|
||||
alt="Low-fi desktop app"
|
||||
src="/assets/images/app-wf-dark-2.svg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="rounded-sm bg-gradient-to-br from-blue-400 to-blue-200 p-[2px] drop-shadow dark:from-blue-300 dark:to-blue-400"
|
||||
>
|
||||
<div class="bg-pattern-purple rounded-sm p-6">
|
||||
<div class="flex flex-col gap-12">
|
||||
<div class="flex flex-col gap-4">
|
||||
<h2 class="font-medium">
|
||||
Docker Model Runner
|
||||
{{ partial "components/badge.html" (dict "color" "blue" "content" "Beta") }}
|
||||
</h2>
|
||||
<p class="text-xl">
|
||||
Run, test, and serve AI models locally in seconds — no
|
||||
setup, no hassle.
|
||||
</p>
|
||||
<p>
|
||||
Whether you’re experimenting with the latest LLMs or
|
||||
deploying to production, Docker Model Runner brings the
|
||||
performance and control you need, without the friction.
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-start gap-4 xl:flex-row">
|
||||
<a
|
||||
href="/desktop/features/model-runner/"
|
||||
class="bg-blue dark:bg-blue rounded-sm p-2 px-4 text-white transition duration-300 hover:bg-blue-500 dark:hover:bg-blue-500"
|
||||
>Read the docs</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex h-full flex-col justify-between gap-4">
|
||||
<p>{{ .description | markdownify }}</p>
|
||||
<nav class="flex flex-col gap-2">
|
||||
{{ range .links }}
|
||||
<div>
|
||||
<span class="icon-svg text-gray-light dark:text-gray-dark">{{ partial "icon" "arrow_right" }}</span>
|
||||
<a class="link" href="{{ .url }}">{{ .text }}</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-4">
|
||||
<h2 class="mb-4 text-xl">Browse by tag</h2>
|
||||
<div class="flex flex-wrap gap-4">
|
||||
{{ $tags := slice }}
|
||||
{{- range site.Taxonomies.tags }}
|
||||
{{ $tags = $tags | append .Page }}
|
||||
{{ end }}
|
||||
{{ partial "tags.html" $tags }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="relative flex md:h-[334px] items-center justify-center overflow-hidden bg-gray-light-100 dark:bg-gray-dark-200 h-full py-8">
|
||||
<div class="w-[1200px] px-4">
|
||||
<div class="flex md:max-w-[66%] flex-col gap-8 max-w-full">
|
||||
<h2 class="text-2xl">Community resources</h2>
|
||||
<p>
|
||||
Find fellow Docker enthusiasts, engage in insightful discussions,
|
||||
share knowledge, and collaborate on projects. Our communities
|
||||
offer a rich online experience for developers to create valuable
|
||||
connections that challenge and inspire!
|
||||
</p>
|
||||
<div class="flex gap-4 flex-col md:flex-row">
|
||||
<a href="https://forums.docker.com/"
|
||||
class="cursor-pointer rounded bg-white px-4 py-2 text-blue-light hover:bg-gray-light-100 dark:bg-gray-dark-400 dark:text-white dark:hover:bg-gray-dark-500">
|
||||
Visit Docker Forum
|
||||
</a>
|
||||
<a href="https://dockr.ly/comm-slack"
|
||||
class="cursor-pointer rounded bg-white px-4 py-2 text-blue-light hover:bg-gray-light-100 dark:bg-gray-dark-400 dark:text-white dark:hover:bg-gray-dark-500">
|
||||
Join Docker Slack
|
||||
</a>
|
||||
<a href="https://www.docker.com/community/captains/"
|
||||
class="cursor-pointer rounded bg-white px-4 py-2 text-blue-light hover:bg-gray-light-100 dark:bg-gray-dark-400 dark:text-white dark:hover:bg-gray-dark-500">
|
||||
Find your Docker Captain
|
||||
</a>
|
||||
<div>
|
||||
<h2 class="mb-4 text-xl">Browse by section</h2>
|
||||
<div
|
||||
class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"
|
||||
>
|
||||
{{ range .Params.grid }}
|
||||
<div>
|
||||
<div class="section-card">
|
||||
<div class="flex items-center gap-4">
|
||||
<span class="icon-svg text-gray dark:text-gray"
|
||||
>{{ partial "icon" .icon }}</span
|
||||
>
|
||||
<div>
|
||||
<div class="section-card-title">{{ .title }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex h-full flex-col justify-between gap-4">
|
||||
<p>{{ .description | markdownify }}</p>
|
||||
<nav class="flex flex-col gap-2">
|
||||
{{ range .links }}
|
||||
<div>
|
||||
<span class="icon-svg text-gray dark:text-gray"
|
||||
>{{ partial "icon" "arrow_right" }}</span
|
||||
>
|
||||
<a class="link" href="{{ .url }}">{{ .text }}</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-4">
|
||||
<h2 class="mb-4 text-xl">Browse by tag</h2>
|
||||
<div class="flex flex-wrap gap-4">
|
||||
{{ $tags := slice }}
|
||||
{{- range site.Taxonomies.tags }}
|
||||
{{ $tags = $tags | append .Page }}
|
||||
{{ end }}
|
||||
{{ partial "tags.html" $tags }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="absolute right-0 top-0 hidden md:block">
|
||||
{{- (resources.Get "images/home-abstract-faint.svg").Content | safe.HTML -}}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer>{{ partialCached "footer.html" . }}</footer>
|
||||
</body>
|
||||
|
||||
<div
|
||||
class="relative flex h-full items-center justify-center overflow-hidden bg-gray-100 py-8 md:h-[334px] dark:bg-gray-900"
|
||||
>
|
||||
<div class="w-[1200px] px-4">
|
||||
<div class="flex max-w-full flex-col gap-8 md:max-w-[66%]">
|
||||
<h2 class="text-2xl">Community resources</h2>
|
||||
<p>
|
||||
Find fellow Docker enthusiasts, engage in insightful discussions,
|
||||
share knowledge, and collaborate on projects. Our communities
|
||||
offer a rich online experience for developers to create valuable
|
||||
connections that challenge and inspire!
|
||||
</p>
|
||||
<div class="flex flex-col gap-4 md:flex-row">
|
||||
<a
|
||||
href="https://forums.docker.com/"
|
||||
class="cursor-pointer rounded-sm bg-white px-4 py-2 hover:bg-gray-50 dark:bg-gray-400 dark:text-white dark:hover:bg-gray-500"
|
||||
>
|
||||
Visit Docker Forum
|
||||
</a>
|
||||
<a
|
||||
href="https://dockr.ly/comm-slack"
|
||||
class="cursor-pointer rounded-sm bg-white px-4 py-2 hover:bg-gray-50 dark:bg-gray-400 dark:text-white dark:hover:bg-gray-500"
|
||||
>
|
||||
Join Docker Slack
|
||||
</a>
|
||||
<a
|
||||
href="https://www.docker.com/community/captains/"
|
||||
class="cursor-pointer rounded-sm bg-white px-4 py-2 hover:bg-gray-50 dark:bg-gray-400 dark:text-white dark:hover:bg-gray-500"
|
||||
>
|
||||
Find your Docker Captain
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="absolute top-0 right-0 hidden md:block">
|
||||
{{- (resources.Get "images/home-abstract-faint.svg").Content | safe.HTML -}}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer>{{ partialCached "footer.html" . }}</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="mask0_23_93" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="2" y="1" width="20" height="22">
|
||||
<path d="M12 8.00008V12.0001M12 16.0001H12.01M3 7.94153V16.0586C3 16.4013 3 16.5726 3.05048 16.7254C3.09515 16.8606 3.16816 16.9847 3.26463 17.0893C3.37369 17.2077 3.52345 17.2909 3.82297 17.4573L11.223 21.5684C11.5066 21.726 11.6484 21.8047 11.7985 21.8356C11.9315 21.863 12.0685 21.863 12.2015 21.8356C12.3516 21.8047 12.4934 21.726 12.777 21.5684L20.177 17.4573C20.4766 17.2909 20.6263 17.2077 20.7354 17.0893C20.8318 16.9847 20.9049 16.8606 20.9495 16.7254C21 16.5726 21 16.4013 21 16.0586V7.94153C21 7.59889 21 7.42756 20.9495 7.27477C20.9049 7.13959 20.8318 7.01551 20.7354 6.91082C20.6263 6.79248 20.4766 6.70928 20.177 6.54288L12.777 2.43177C12.4934 2.27421 12.3516 2.19543 12.2015 2.16454C12.0685 2.13721 11.9315 2.13721 11.7985 2.16454C11.6484 2.19543 11.5066 2.27421 11.223 2.43177L3.82297 6.54288C3.52345 6.70928 3.37369 6.79248 3.26463 6.91082C3.16816 7.01551 3.09515 7.13959 3.05048 7.27477C3 7.42756 3 7.59889 3 7.94153Z" stroke="#6C7E9D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_23_93)">
|
||||
<rect width="24" height="24" fill="black" fill-opacity="0.8"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
|
@ -0,0 +1,8 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="mask0_23_89" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="2" y="2" width="20" height="20">
|
||||
<path d="M12 8V12M12 16H12.01M7.8 21H16.2C17.8802 21 18.7202 21 19.362 20.673C19.9265 20.3854 20.3854 19.9265 20.673 19.362C21 18.7202 21 17.8802 21 16.2V7.8C21 6.11984 21 5.27976 20.673 4.63803C20.3854 4.07354 19.9265 3.6146 19.362 3.32698C18.7202 3 17.8802 3 16.2 3H7.8C6.11984 3 5.27976 3 4.63803 3.32698C4.07354 3.6146 3.6146 4.07354 3.32698 4.63803C3 5.27976 3 6.11984 3 7.8V16.2C3 17.8802 3 18.7202 3.32698 19.362C3.6146 19.9265 4.07354 20.3854 4.63803 20.673C5.27976 21 6.11984 21 7.8 21Z" stroke="#6C7E9D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_23_89)">
|
||||
<rect width="24" height="24" fill="currentColor" fill-opacity="0.8"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 905 B |
|
@ -0,0 +1,3 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 16V12M12 8H12.01M22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 335 B |
|
@ -0,0 +1,8 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="mask0_5432_1749" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="4" y="1" width="17" height="22">
|
||||
<path d="M9.93896 22H14.939M10.439 10H14.439M12.439 10L12.439 16M15.439 15.3264C17.8039 14.2029 19.439 11.7924 19.439 9C19.439 5.13401 16.305 2 12.439 2C8.57297 2 5.43896 5.13401 5.43896 9C5.43896 11.7924 7.07402 14.2029 9.43896 15.3264V16C9.43896 16.9319 9.43896 17.3978 9.59121 17.7654C9.79419 18.2554 10.1835 18.6448 10.6736 18.8478C11.0411 19 11.5071 19 12.439 19C13.3708 19 13.8368 19 14.2043 18.8478C14.6944 18.6448 15.0837 18.2554 15.2867 17.7654C15.439 17.3978 15.439 16.9319 15.439 16V15.3264Z" stroke="#6C7E9D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_5432_1749)">
|
||||
<rect width="24" height="24" fill="currentColor" fill-opacity="0.8"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 920 B |
|
@ -0,0 +1,8 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="mask0_5432_2018" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="2" width="24" height="21">
|
||||
<path d="M11.9998 9.99999V14M11.9998 18H12.0098M10.6151 4.89171L2.39019 19.0983C1.93398 19.8863 1.70588 20.2803 1.73959 20.6037C1.769 20.8857 1.91677 21.142 2.14613 21.3088C2.40908 21.5 2.86435 21.5 3.77487 21.5H20.2246C21.1352 21.5 21.5904 21.5 21.8534 21.3088C22.0827 21.142 22.2305 20.8857 22.2599 20.6037C22.2936 20.2803 22.0655 19.8863 21.6093 19.0983L13.3844 4.89171C12.9299 4.10654 12.7026 3.71396 12.4061 3.58211C12.1474 3.4671 11.8521 3.4671 11.5935 3.58211C11.2969 3.71396 11.0696 4.10655 10.6151 4.89171Z" stroke="#6C7E9D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_5432_2018)">
|
||||
<rect width="24" height="24" fill="currentColor" fill-opacity="0.8"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 933 B |
|
@ -1,12 +1,19 @@
|
|||
<nav id="breadcrumbs"
|
||||
<nav
|
||||
id="breadcrumbs"
|
||||
{{- $breadcrumbTitles := slice }}
|
||||
data-pagefind-ignore class="gap-4 flex items-center text-gray-light dark:text-gray-dark min-w-0">
|
||||
data-pagefind-ignore
|
||||
class="mb-4 flex min-w-0 items-center gap-2 text-gray-400 dark:text-gray-300"
|
||||
>
|
||||
{{ range .Ancestors.Reverse }}
|
||||
{{ $breadcrumbTitles = $breadcrumbTitles | append .LinkTitle }}
|
||||
<a href="{{ .Permalink }}" class="link truncate">{{ markdownify .LinkTitle }}</a>
|
||||
<a href="{{ .Permalink }}" class="link truncate"
|
||||
>{{ markdownify .LinkTitle }}</a
|
||||
>
|
||||
<span>/</span>
|
||||
{{- end }}
|
||||
<span
|
||||
data-pagefind-meta="breadcrumbs:{{ collections.Delimit $breadcrumbTitles " / " }}"
|
||||
class="truncate">{{ markdownify .LinkTitle }}</span>
|
||||
class="truncate"
|
||||
>{{ markdownify .LinkTitle }}</span
|
||||
>
|
||||
</nav>
|
||||
|
|
|
@ -1,15 +1,24 @@
|
|||
<div
|
||||
id="{{ urls.Anchorize .title }}"
|
||||
x-data="{ open: {{ .open | default false }} }" class="border border-gray-light-200 dark:border-gray-dark-200 bg-white dark:bg-gray-dark-100 py-2 my-6 rounded">
|
||||
<button class="not-prose w-full py-2 px-4 flex justify-between" x-on:click="open = ! open">
|
||||
<div class="{{ with .large }} text-xl {{ end }} flex items-center gap-2">
|
||||
x-data="{ open: {{ .open | default false }} }"
|
||||
class="my-6 rounded-sm border border-gray-200 bg-white py-2 dark:border-gray-700 dark:bg-gray-900"
|
||||
>
|
||||
<button
|
||||
class="not-prose flex w-full justify-between px-4 py-2"
|
||||
x-on:click="open = ! open"
|
||||
>
|
||||
<div class="{{ with .large }}text-xl{{ end }} flex items-center gap-2">
|
||||
{{- with .icon }}
|
||||
<span class="icon-svg -mt-1">{{ partialCached "icon" . . }}</span>
|
||||
{{- end }}
|
||||
{{ .title }}
|
||||
</div>
|
||||
<span :class="{ 'hidden' : !open }" class="icon-svg">{{ partialCached "icon" "arrow_drop_up" "arrow_drop_up" }}</span>
|
||||
<span :class="{ 'hidden' : open }" class="icon-svg">{{ partialCached "icon" "arrow_drop_down" "arrow_drop_down" }}</span>
|
||||
<span :class="{ 'hidden' : !open }" class="icon-svg"
|
||||
>{{ partialCached "icon" "arrow_drop_up" "arrow_drop_up" }}</span
|
||||
>
|
||||
<span :class="{ 'hidden' : open }" class="icon-svg"
|
||||
>{{ partialCached "icon" "arrow_drop_down" "arrow_drop_down" }}</span
|
||||
>
|
||||
</button>
|
||||
<div x-show="open" x-collapse class="px-4">
|
||||
{{ markdownify .body }}
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
{{- $colors := (dict
|
||||
"amber" "bg-amber-light dark:bg-amber-dark"
|
||||
"blue" "bg-blue-light dark:bg-blue-dark"
|
||||
"green" "bg-green-light dark:bg-green-dark"
|
||||
"red" "bg-red-light dark:bg-red-dark"
|
||||
"violet" "bg-violet-light dark:bg-violet-dark"
|
||||
"amber" "bg-amber-500 dark:bg-amber-400"
|
||||
"blue" "bg-blue-500 dark:bg-blue-400"
|
||||
"green" "bg-green-500 dark:bg-green-700"
|
||||
"red" "bg-red-500 dark:bg-red-400"
|
||||
"violet" "bg-violet-500 dark:bg-violet-400"
|
||||
)
|
||||
-}}
|
||||
|
||||
{{- if not (isset $colors .color) -}}
|
||||
{{- errorf "[badge] wrong color name: '%s' - supported values: amber, blue, green, red, violet" .color -}}h
|
||||
{{- errorf "[badge] wrong color name: '%s' - supported values: amber, blue, green, red, violet" .color -}}h
|
||||
{{- end -}}
|
||||
|
||||
|
||||
<span
|
||||
class="not-prose px-1 rounded-sm {{ index $colors .color }} text-white text-xs"
|
||||
class="not-prose {{ index $colors .color }} rounded-sm px-1 text-xs text-white"
|
||||
>{{ .content }}</span
|
||||
>
|
||||
|
|
|
@ -1,51 +1,31 @@
|
|||
{{ if (and .image .icon) }}
|
||||
{{ errorf "card: don't use both image and icon: %s" . }}
|
||||
{{ end }}
|
||||
<div class="not-prose overflow-x-hidden drop-shadow bg-white rounded
|
||||
border border-gray-light-100 dark:bg-gray-dark-200 dark:border-gray-dark-400
|
||||
{{ if .link }}hover:border-gray-light-200 hover:dark:border-gray-dark{{ end }}">
|
||||
<div class="card">
|
||||
{{ if .link }}
|
||||
<a href="{{ .link }}">
|
||||
<a href="{{ .link }}" class="card-link">
|
||||
{{ end }}
|
||||
{{ if .image }}
|
||||
{{/* use the "tall image" layout */}}
|
||||
<div class="flex gap-2 items-stretch">
|
||||
<div class="basis-1/3">
|
||||
<img class="h-full w-full object-cover" src="{{ .image }}" alt="">
|
||||
</div>
|
||||
<div class="basis-2/3 flex flex-col gap-2 p-4">
|
||||
<div class="text-xl text-gray-light-800 leading-snug dark:text-white flex gap-2">
|
||||
{{ markdownify .title }}
|
||||
</div>
|
||||
<div class="text-gray-light-500 leading-snug dark:text-gray-dark-700">
|
||||
{{ .description | markdownify }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ else }}
|
||||
{{/* use the default layout */}}
|
||||
<div class="flex flex-col gap-2 p-4">
|
||||
<div class="flex gap-4 items-center">
|
||||
{{ with .icon }}
|
||||
{{ if strings.ContainsAny . "/." }}
|
||||
{{/* image file */}}
|
||||
<img class="w-[32px] invertible" src="{{ . }}" alt="">
|
||||
{{ else }}
|
||||
{{/* icon ligature */}}
|
||||
<span class="icon-svg">{{ partial "icon" . }}</span>
|
||||
{{ end }}
|
||||
<div class="card-header">
|
||||
{{ with .image }}
|
||||
<img class="card-image" src="{{ . }}" alt="">
|
||||
{{ end }}
|
||||
{{ with .icon }}
|
||||
<div class="card-icon">
|
||||
{{ if (in . ".svg") }}
|
||||
<span class="card-img svg">
|
||||
{{ partial "utils/svg" . }}
|
||||
</span>
|
||||
{{ else if (in . "/") }}
|
||||
<img class="card-img" src="{{ . }}" alt="">
|
||||
{{ else }}
|
||||
<span class="card-img svg">
|
||||
{{ partial "icon" . }}
|
||||
</span>
|
||||
{{ end }}
|
||||
<div>
|
||||
<div class="text-xl text-gray-light-800 leading-snug dark:text-white flex items-center gap-2">
|
||||
{{ markdownify .title }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-gray-light-600 leading-snug dark:text-gray-dark-700">
|
||||
{{ .description | markdownify }}
|
||||
</div>
|
||||
{{ end }}
|
||||
<h3 class="card-title">{{ markdownify .title }}</h3>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<p class="card-description">{{ .description | markdownify }}</p>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ if .link }}
|
||||
</a>
|
||||
{{ end }}
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
<div class="not-prose">
|
||||
<div class="flex flex-col sm:flex-row gap-4 p-6 m-4 bg-gray-light-200 dark:bg-gray-dark-300">
|
||||
<div class="flex-grow flex flex-col sm:items-center">
|
||||
<div
|
||||
class="m-4 flex flex-col gap-4 bg-gray-200 p-6 sm:flex-row dark:bg-gray-300"
|
||||
>
|
||||
<div class="flex flex-grow flex-col sm:items-center">
|
||||
<span><strong>Skill level</strong></span>
|
||||
<span>{{ .Params.skill }}</span>
|
||||
</div>
|
||||
<div class="flex-grow flex flex-col sm:items-center">
|
||||
<div class="flex flex-grow flex-col sm:items-center">
|
||||
<span><strong>Time to complete</strong></span>
|
||||
<span>{{ .Params.time }}</span>
|
||||
</div>
|
||||
<div class="flex-grow flex flex-col sm:items-center">
|
||||
<div class="flex flex-grow flex-col sm:items-center">
|
||||
<span><strong>Prerequisites</strong></span>
|
||||
<span>{{ .Params.prereq }}</span>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<a
|
||||
href="https://hub.docker.com/support/contact"
|
||||
class="flex items-center rounded bg-blue-light dark:bg-blue-dark text-white
|
||||
py-2 px-4 z-50"
|
||||
aria-label="Contact support">
|
||||
class="hover:bg-blue bg-blue z-50 flex items-center rounded-sm px-4 py-2 text-white dark:bg-blue-400 hover:dark:bg-blue-500"
|
||||
aria-label="Contact support"
|
||||
>
|
||||
<span>Contact support</span>
|
||||
</a>
|
||||
</a>
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
<div class="flex w-full gap-8">
|
||||
<article class="prose min-w-0 max-w-4xl flex-[2_2_0%] dark:prose-invert">
|
||||
<article class="prose dark:prose-invert max-w-4xl min-w-0 flex-[2_2_0%]">
|
||||
{{ partial "breadcrumbs.html" . }}
|
||||
<h1 data-pagefind-weight="10" class="flex scroll-mt-36 items-center">
|
||||
<span>{{ .Title }}</span>
|
||||
</h1>
|
||||
|
||||
<div class="flex items-start justify-between">
|
||||
<h1 data-pagefind-weight="10">{{ .Title }}</h1>
|
||||
<div class="md-dropdown ml-auto hidden lg:block">
|
||||
{{ partial "md-dropdown.html" . }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="block lg:hidden">
|
||||
{{ partialCached "pagemeta.html" . . }}
|
||||
<hr />
|
||||
</div>
|
||||
{{ .Content }}
|
||||
</article>
|
||||
<div class="hidden lg:block ml-auto md-dropdown">
|
||||
{{ partial "md-dropdown.html" . }}
|
||||
</div>
|
||||
<div class="-mr-8 -mt-8 hidden min-w-52 flex-1 lg:block">
|
||||
<div class="-mt-8 -mr-8 hidden min-w-52 flex-1 lg:block">
|
||||
{{ partial "aside.html" . }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,51 +1,72 @@
|
|||
<div class="flex justify-center py-8 px-4 bg-gray-light-100 dark:bg-gray-dark-200 relative z-10">
|
||||
<div
|
||||
class="relative z-10 flex justify-center bg-gray-100 px-4 py-8 dark:bg-gray-900"
|
||||
>
|
||||
{{ partialCached "components/support-button.html" . }}
|
||||
</div>
|
||||
<div class="flex justify-center pt-10 pb-20 px-4 bg-gray-light-100 dark:bg-gray-dark-200">
|
||||
<div class="flex justify-center bg-gray-100 px-4 pt-10 pb-20 dark:bg-gray-900">
|
||||
<div class="flex w-full max-w-[840px] flex-col gap-10">
|
||||
<div class="flex flex-col md:flex-row gap-4 items-center justify-evenly">
|
||||
<a class="underline-offset-2 hover:underline" href="https://www.docker.com/">Product offerings</a>
|
||||
<a class="underline-offset-2 hover:underline" href="https://www.docker.com/pricing/">Pricing</a>
|
||||
<a class="underline-offset-2 hover:underline" href="https://www.docker.com/company/">About us</a>
|
||||
<div class="flex flex-col items-center justify-evenly gap-4 md:flex-row">
|
||||
<a
|
||||
class="underline-offset-2 hover:underline"
|
||||
href="https://www.docker.com/"
|
||||
>Product offerings</a
|
||||
>
|
||||
<a
|
||||
class="underline-offset-2 hover:underline"
|
||||
href="https://www.docker.com/pricing/"
|
||||
>Pricing</a
|
||||
>
|
||||
<a
|
||||
class="underline-offset-2 hover:underline"
|
||||
href="https://www.docker.com/company/"
|
||||
>About us</a
|
||||
>
|
||||
{{- with .GetPage "/contribute" }}
|
||||
<a class="underline-offset-2 hover:underline" href="{{ .Permalink }}">{{ .LinkTitle }}</a>
|
||||
<a class="underline-offset-2 hover:underline" href="{{ .Permalink }}"
|
||||
>{{ .LinkTitle }}</a
|
||||
>
|
||||
{{- end }}
|
||||
<a href="{{ "llms.txt" | relURL }}">Read llms.txt</a>
|
||||
</div>
|
||||
<hr class="text-divider-light dark:text-divider-dark" />
|
||||
<div class="grid lg:grid-cols-3 place-items-center gap-8 grid-cols-1">
|
||||
<div class="grid grid-cols-1 place-items-center gap-8 lg:grid-cols-3">
|
||||
<p class="text-sm">
|
||||
Copyright © 2013-{{ time.Now.Year}} Docker Inc. All rights reserved.
|
||||
Copyright © 2013-{{ time.Now.Year }} Docker Inc. All rights reserved.
|
||||
</p>
|
||||
<div class="flex gap-4">
|
||||
<a
|
||||
class="h-8 w-8 rounded-full fill-blue-light dark:fill-blue-dark"
|
||||
class="fill-blue h-8 w-8 rounded-full dark:fill-blue-300"
|
||||
title="X (Twitter)"
|
||||
href="http://twitter.com/docker/">
|
||||
href="http://twitter.com/docker/"
|
||||
>
|
||||
{{ (resources.Get "images/TwitterCircle.svg").Content | safe.HTML }}
|
||||
</a>
|
||||
<a
|
||||
class="h-8 w-8 rounded-full fill-blue-light dark:fill-blue-dark"
|
||||
class="fill-blue h-8 w-8 rounded-full dark:fill-blue-300"
|
||||
title="LinkedIn"
|
||||
href="https://www.linkedin.com/company/docker">
|
||||
href="https://www.linkedin.com/company/docker"
|
||||
>
|
||||
{{ (resources.Get "images/LinkedinCircle.svg").Content | safe.HTML }}
|
||||
</a>
|
||||
<a
|
||||
class="h-8 w-8 rounded-full fill-blue-light dark:fill-blue-dark"
|
||||
class="fill-blue h-8 w-8 rounded-full dark:fill-blue-300"
|
||||
title="Instagram"
|
||||
href="https://www.instagram.com/dockerinc/">
|
||||
href="https://www.instagram.com/dockerinc/"
|
||||
>
|
||||
{{ (resources.Get "images/InstagramCircle.svg").Content | safe.HTML }}
|
||||
</a>
|
||||
<a
|
||||
class="h-8 w-8 rounded-full fill-blue-light dark:fill-blue-dark"
|
||||
class="fill-blue h-8 w-8 rounded-full dark:fill-blue-300"
|
||||
title="YouTube"
|
||||
href="http://www.youtube.com/user/dockerrun">
|
||||
href="http://www.youtube.com/user/dockerrun"
|
||||
>
|
||||
{{ (resources.Get "images/YoutubeCircle.svg").Content | safe.HTML }}
|
||||
</a>
|
||||
<a
|
||||
class="h-8 w-8 rounded-full fill-blue-light dark:fill-blue-dark"
|
||||
class="fill-blue h-8 w-8 rounded-full dark:fill-blue-300"
|
||||
title="Facebook"
|
||||
href="https://www.facebook.com/docker.run">
|
||||
href="https://www.facebook.com/docker.run"
|
||||
>
|
||||
{{ (resources.Get "images/FacebookCircle.svg").Content | safe.HTML }}
|
||||
</a>
|
||||
</div>
|
||||
|
@ -54,20 +75,23 @@
|
|||
class="underline-offset-2 hover:underline"
|
||||
title="Docker Terms of Service"
|
||||
href="https://www.docker.com/legal/docker-terms-service"
|
||||
>Terms of Service</a>
|
||||
>Terms of Service</a
|
||||
>
|
||||
<a
|
||||
class="underline-offset-2 hover:underline"
|
||||
title="Docker Systems Status Page"
|
||||
href="https://www.dockerstatus.com/"
|
||||
>Status</a>
|
||||
>Status</a
|
||||
>
|
||||
<a
|
||||
class="underline-offset-2 hover:underline"
|
||||
title="Docker Legal Terms"
|
||||
href="https://www.docker.com/legal"
|
||||
>Legal</a>
|
||||
>Legal</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="flex items-center justify-between">
|
||||
<button type="button" id="ot-sdk-btn" class="ot-sdk-show-settings">
|
||||
Cookies Settings
|
||||
</button>
|
||||
|
@ -76,9 +100,7 @@
|
|||
<button
|
||||
aria-label="Theme switch"
|
||||
id="theme-switch"
|
||||
class="rounded bg-blue-light px-4 py-1 text-white transition
|
||||
hover:bg-blue-light-400 dark:bg-blue-dark-400
|
||||
dark:hover:bg-blue-dark"
|
||||
class="bg-blue rounded-sm px-4 py-1 text-white transition hover:bg-blue-400 dark:bg-blue-400 dark:hover:bg-blue-500"
|
||||
x-data="{ theme: localStorage.getItem('theme-preference') }"
|
||||
x-init="$watch('theme', value => {
|
||||
localStorage.setItem('theme-preference', value);
|
||||
|
|
|
@ -4,20 +4,24 @@
|
|||
- "Request changes": Links to a pre-filled issue form.
|
||||
*/ -}}
|
||||
{{ if hugo.IsProduction }}
|
||||
{{ with .File }}
|
||||
{{ if not (in .Filename "/_vendor/") }}
|
||||
<p class="flex items-center gap-2">
|
||||
<span class="icon-svg">{{ partialCached "icon" "edit" "edit" }}</span>
|
||||
{{ with .File }}
|
||||
{{ if not (in .Filename "/_vendor/") }}
|
||||
<p class="flex items-center gap-1">
|
||||
<span class="icon-svg icon-sm">
|
||||
{{ partial "utils/svg.html" "theme/icons/edit.svg" }}
|
||||
</span>
|
||||
<a class="link" rel="noopener"
|
||||
href="{{ site.Params.repo }}/edit/main/content/{{ .Path }}">{{- T "editPage" -}}
|
||||
<span class="icon-svg icon-sm">
|
||||
{{ partialCached "icon" "open_in_new" "open_in_new" }}
|
||||
</span></a>
|
||||
</p>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
<p class="flex items-center gap-2">
|
||||
<span class="icon-svg">{{ partialCached "icon" "check" "check" }}</span>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
<p class="flex items-center gap-1">
|
||||
<span class="icon-svg icon-sm">
|
||||
{{ partial "utils/svg.html" "theme/icons/issue.svg" }}
|
||||
</span>
|
||||
<a class="link" rel="noopener"
|
||||
href="{{ site.Params.repo }}/issues/new?template=doc_issue.yml&location={{ .Permalink }}&labels=status%2Ftriage">{{- T "requestChanges" -}}
|
||||
<span class="icon-svg icon-sm">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{{/*- Multi-page guide: render a progress bar -*/}}
|
||||
<div class="flex flex-col my-4 items-start text-sm">
|
||||
{{/* - Multi-page guide: render a progress bar - */}}
|
||||
<div class="my-4 flex flex-col items-start text-sm">
|
||||
{{ $totalPages := len .CurrentSection.Pages }}
|
||||
{{/*- initialize the page store
|
||||
{{/* - initialize the page store
|
||||
|
||||
$stepper_seen controls the color of the item in the stepper
|
||||
|
||||
|
@ -13,42 +13,42 @@
|
|||
default to true if kind = section
|
||||
(make all entries gray)
|
||||
|
||||
-*/}}
|
||||
-
|
||||
*/}}
|
||||
{{ page.Store.Set "stepper_seen" .IsSection }}
|
||||
{{/*- Loop over the pages in this guide -*/}}
|
||||
{{/* - Loop over the pages in this guide - */}}
|
||||
{{ range $i, $e := .CurrentSection.Pages }}
|
||||
{{ $isLast := eq (add $i 1) $totalPages }}
|
||||
<div class="flex">
|
||||
<div class="flex flex-col items-center">
|
||||
{{/*- Render the page's index digit (1,2,3,4 etc) -*/}}
|
||||
{{/* - Render the page's index digit (1,2,3,4 etc) - */}}
|
||||
<a
|
||||
href="{{ .Permalink }}"
|
||||
class="{{ if (page.Store.Get "stepper_seen") }}
|
||||
bg-gray-light-400 dark:bg-gray-dark-400
|
||||
bg-gray-400 dark:bg-gray-500
|
||||
{{ else if (eq . page) }}
|
||||
{{ .Store.Set "stepper_seen" true }} bg-blue-light-400
|
||||
dark:bg-blue-dark-400
|
||||
{{ .Store.Set "stepper_seen" true }} bg-blue-400 dark:bg-blue-800
|
||||
{{ else }}
|
||||
bg-green-light-400 dark:bg-green-dark-400
|
||||
bg-green-400 dark:bg-green-dark-400
|
||||
{{ end }} flex h-8 w-8 items-center justify-center rounded-full text-white no-underline"
|
||||
>
|
||||
{{ add $i 1 }}
|
||||
</a>
|
||||
{{/*- Render the vertical border -*/}}
|
||||
{{/* - Render the vertical border - */}}
|
||||
{{ if not $isLast }}
|
||||
<div
|
||||
class="{{ if (page.Store.Get "stepper_seen") }}
|
||||
border-gray-light-400 dark:border-gray-dark-400
|
||||
border-gray-400 dark:border-gray-400
|
||||
{{ else if (eq . page) }}
|
||||
border-blue-light-400 dark:border-blue-dark-400
|
||||
border-blue-400 dark:border-blue-400
|
||||
{{ else }}
|
||||
border-green-light-400 dark:border-green-dark-400
|
||||
border-green-400 dark:border-green-400
|
||||
{{ end }} h-6 border-l-2"
|
||||
></div>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{/*- Render the page's title -*/}}
|
||||
<div class="ml-2 flex self-start h-8 items-center">
|
||||
{{/* - Render the page's title - */}}
|
||||
<div class="ml-2 flex h-8 items-center self-start">
|
||||
<a href="{{ .Permalink }}">
|
||||
{{ .LinkTitle }}
|
||||
</a>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
{{ partial "meta.html" . }}
|
||||
{{ partial "utils/css.html" "-" }}
|
||||
{{- if hugo.IsProduction -}}
|
||||
<script
|
||||
src="https://cdn.cookielaw.org/scripttemplates/otSDKStub.js"
|
||||
|
@ -8,13 +9,14 @@
|
|||
charset="UTF-8"
|
||||
data-domain-script="{{ site.Params.analytics.onetrust }}"
|
||||
></script>
|
||||
<script type="text/javascript">function OptanonWrapper() {}</script>
|
||||
<script type="text/javascript">
|
||||
function OptanonWrapper() {}
|
||||
</script>
|
||||
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
||||
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
||||
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
||||
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
||||
})(window,document,'script','dataLayer','{{ site.Params.analytics.google }}');</script>
|
||||
<script>
|
||||
})(window,document,'script','dataLayer','{{ site.Params.analytics.google }}');</script> <script>
|
||||
(function(h,o,t,j,a,r){
|
||||
h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
|
||||
h._hjSettings={hjid:{{ site.Params.analytics.hotjar.prod | safeJS }},hjsv:6};
|
||||
|
@ -50,30 +52,37 @@
|
|||
</script>
|
||||
{{ end }}
|
||||
{{/* kapa.ai widget */}}
|
||||
<script async src="https://widget.kapa.ai/kapa-widget.bundle.js"
|
||||
data-button-hide="true"
|
||||
data-font-family="Roboto Flex,sans-serif"
|
||||
data-modal-disclaimer-bg-color="#e5f2fc"
|
||||
data-modal-disclaimer-text-color="#086dd7"
|
||||
data-modal-disclaimer="This is a custom LLM for answering questions about Docker. Answers are based on the contents of the documentation. Rate the answers to let us know what you think!"
|
||||
data-kapa-branding-text="powered by [kapa.ai](https://www.kapa.ai) and Docker"
|
||||
data-modal-header-bg-color="#1d63ed"
|
||||
data-modal-image-height="25px"
|
||||
data-modal-image-width="181px"
|
||||
data-modal-title=""
|
||||
data-modal-override-open-class="open-kapa-widget"
|
||||
data-modal-ask-ai-input-placeholder="Ask me a question about Docker…"
|
||||
data-modal-title-color="#fff"
|
||||
data-project-color="#1d63ed"
|
||||
data-project-logo="/assets/images/logo-icon-white.svg"
|
||||
data-project-name="Docker"
|
||||
data-user-analytics-fingerprint-enabled="true"
|
||||
data-bot-protection-mechanism="hcaptcha"
|
||||
data-website-id="{{ site.Params.kapa.id }}"
|
||||
<script
|
||||
async
|
||||
src="https://widget.kapa.ai/kapa-widget.bundle.js"
|
||||
data-button-hide="true"
|
||||
data-font-family="Roboto Flex,sans-serif"
|
||||
data-modal-disclaimer-bg-color="#e5f2fc"
|
||||
data-modal-disclaimer-text-color="#086dd7"
|
||||
data-modal-disclaimer="This is a custom LLM for answering questions about Docker. Answers are based on the contents of the documentation. Rate the answers to let us know what you think!"
|
||||
data-kapa-branding-text="powered by [kapa.ai](https://www.kapa.ai) and Docker"
|
||||
data-modal-header-bg-color="#1d63ed"
|
||||
data-modal-image-height="25px"
|
||||
data-modal-image-width="181px"
|
||||
data-modal-title=""
|
||||
data-modal-override-open-class="open-kapa-widget"
|
||||
data-modal-ask-ai-input-placeholder="Ask me a question about Docker…"
|
||||
data-modal-title-color="#fff"
|
||||
data-project-color="#1d63ed"
|
||||
data-project-logo="/assets/images/logo-icon-white.svg"
|
||||
data-project-name="Docker"
|
||||
data-user-analytics-fingerprint-enabled="true"
|
||||
data-bot-protection-mechanism="hcaptcha"
|
||||
data-website-id="{{ site.Params.kapa.id }}"
|
||||
></script>
|
||||
{{/* preload Roboto Flex as it's a critical font: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel/preload */}}
|
||||
<link href="/assets/fonts/RobotoFlex.woff2" rel="preload" as="font" type="font/woff2" crossorigin />
|
||||
{{ partialCached "utils/css.html" "-" }}
|
||||
<link
|
||||
href="/assets/fonts/RobotoFlex.woff2"
|
||||
rel="preload"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin
|
||||
/>
|
||||
{{ $theme := resources.Get "js/theme.js" | js.Build (dict "minify" true) }}
|
||||
<script>{{ $theme.Content | safeJS }}</script>
|
||||
{{ $js := resources.Match "js/src/**.js"
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
<header class="w-full sticky top-0 z-20 h-16 px-6 text-white bg-gradient-to-r from-blue-light-600 to-blue-light dark:from-blue-dark-200 to-50% dark:to-blue-dark-100">
|
||||
<div class="max-w-[1920px] mx-auto flex lg:gap-8 gap-2 h-full items-center justify-between">
|
||||
<div class="flex h-full items-center lg:gap-8 gap-2">
|
||||
<header
|
||||
class="sticky top-0 z-20 h-16 w-full bg-gradient-to-r from-blue-600 to-blue-500 to-50% px-6 text-white dark:from-blue-600 dark:to-blue-500"
|
||||
>
|
||||
<div
|
||||
class="mx-auto flex h-full max-w-[1920px] items-center justify-between gap-2 lg:gap-8"
|
||||
>
|
||||
<div class="flex h-full items-center gap-2 lg:gap-8">
|
||||
{{- if not .IsHome }}
|
||||
<button x-data @click="$store.showSidebar = true"
|
||||
class="icon-svg block px-4 md:hidden h-full" aria-label="Menu">
|
||||
{{ partialCached "icon" "menu" "menu" }}
|
||||
</button>
|
||||
<button
|
||||
x-data
|
||||
@click="$store.showSidebar = true"
|
||||
class="icon-svg block h-full px-4 md:hidden"
|
||||
aria-label="Menu"
|
||||
>
|
||||
{{ partialCached "icon" "menu" "menu" }}
|
||||
</button>
|
||||
{{- end }}
|
||||
<div>
|
||||
{{/* main logo */}}
|
||||
|
@ -21,24 +29,32 @@
|
|||
<nav class="mt-1 hidden md:block">
|
||||
<ul class="flex text-sm md:text-base lg:gap-4">
|
||||
{{ range site.Menus.main }}
|
||||
<li
|
||||
{{- if or (eq page.Permalink .Page.Permalink) (page.IsDescendant .Page) }}
|
||||
class="border-b-4"
|
||||
{{- else }}
|
||||
class="border-b-4 border-transparent hover:border-white/20"
|
||||
{{- end }}>
|
||||
<a class="block px-2 py-1 whitespace-nowrap" href="{{ .URL }}">{{ .Name }}</a>
|
||||
</li>
|
||||
<li
|
||||
{{- if or (eq page.Permalink .Page.Permalink) (page.IsDescendant .Page) }}
|
||||
class="border-b-4"
|
||||
{{- else }}
|
||||
class="border-b-4 border-transparent hover:border-white/20"
|
||||
{{- end }}
|
||||
>
|
||||
<a class="block px-2 py-1 whitespace-nowrap" href="{{ .URL }}"
|
||||
>{{ .Name }}</a
|
||||
>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="flex min-w-0 items-center gap-4 flex-grow justify-end">
|
||||
<div class="flex min-w-0 flex-grow items-center justify-end gap-4">
|
||||
{{ partialCached "search-bar.html" "-" }}
|
||||
<button @click="open = false"
|
||||
class="dark:text-white py-1 px-2 rounded open-kapa-widget flex gap-1 items-center hover:bg-white/20 transition">
|
||||
<button
|
||||
@click="open = false"
|
||||
class="open-kapa-widget flex items-center gap-1 rounded-sm px-2 py-1 transition hover:bg-white/20 dark:text-white"
|
||||
>
|
||||
<span>Ask AI</span>
|
||||
<img src="{{ (resources.Get "images/ai-stars.svg").Permalink }}" alt="AI Stars" />
|
||||
<img
|
||||
src="{{ (resources.Get "images/ai-stars.svg").Permalink }}"
|
||||
alt="AI Stars"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -10,12 +10,16 @@
|
|||
{{- if not .Page.Params.icon }}
|
||||
{{- errorf "[languages] language is missing an icon: '%s' in %s" (urlize (strings.ToLower .Title)) page.File.Filename }}
|
||||
{{- end }}
|
||||
<span class="text-sm inline-flex gap-1 items-center rounded-full border
|
||||
border-divider-light dark:border-divider-dark bg-gray-light-100
|
||||
px-2 text-gray-light-800 dark:bg-gray-dark-200
|
||||
dark:text-gray-dark-800 select-none">
|
||||
<img class="py-1" height="18" width="18" title="{{ .Page.LinkTitle }}" src="{{ .Page.Params.icon }}">
|
||||
<span
|
||||
class="border-divider-light dark:border-divider-dark inline-flex items-center gap-1 rounded-full border bg-gray-100 px-2 text-sm text-gray-200 select-none dark:bg-gray-800 dark:text-gray-400"
|
||||
>
|
||||
<img
|
||||
class="py-1"
|
||||
height="18"
|
||||
width="18"
|
||||
title="{{ .Page.LinkTitle }}"
|
||||
src="{{ .Page.Params.icon }}"
|
||||
/>
|
||||
<span>{{ .Page.LinkTitle }}</span>
|
||||
</span>
|
||||
{{- end -}}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<details id="markdownDropdown" class="group relative z-10 inline-block" data-heap-id="markdown-dropdown">
|
||||
<summary
|
||||
class="inline-flex cursor-pointer items-center gap-2 rounded border border-gray-light-200 bg-gray-light-200 px-4 py-2 text-base font-semibold text-black transition-colors hover:bg-gray-light-300 dark:border-gray-dark-200 dark:bg-gray-dark-300 dark:text-white dark:hover:bg-gray-dark-400"
|
||||
class="inline-flex cursor-pointer items-center gap-0 rounded-sm border border-gray-600 bg-white px-2 py-2
|
||||
text-base font-semibold text-gray-600 transition-colors hover:bg-gray-50 dark:border-gray-50 dark:bg-gray-950 dark:text-gray-100 dark:hover:bg-gray-900"
|
||||
data-heap-id="markdown-dropdown-toggle"
|
||||
>
|
||||
<span>Page options</span>
|
||||
|
@ -13,13 +14,13 @@
|
|||
|
||||
<!-- Dropdown menu -->
|
||||
<div
|
||||
class="absolute right-0 z-50 mt-2 w-56 origin-top-right rounded border border-gray-light-200 bg-gray-light-200 p-2 text-sm text-black shadow-md [display:none] group-open:[display:block] dark:border-gray-dark-200 dark:bg-gray-dark-300 dark:text-white"
|
||||
class="absolute right-0 z-50 mt-2 w-56 origin-top-right rounded-sm border border-gray-300 bg-white p-2 text-sm text-black shadow-md [display:none] group-open:[display:block] dark:border-gray-100 dark:text-gray-100 dark:bg-gray-950"
|
||||
data-heap-id="markdown-dropdown-menu"
|
||||
>
|
||||
<button
|
||||
onclick="copyMarkdown()"
|
||||
data-heap-id="copy-markdown-button"
|
||||
class="flex w-full items-start gap-2 rounded px-2 py-2 text-left transition-colors hover:bg-gray-light-300 dark:hover:bg-gray-dark-400"
|
||||
class="sub-button"
|
||||
>
|
||||
<span class="icon-svg mt-[2px] text-base leading-none">
|
||||
{{ partial "icon" "content_copy" }}
|
||||
|
@ -35,7 +36,7 @@
|
|||
<button
|
||||
onclick="viewPlainText()"
|
||||
data-heap-id="view-markdown-button"
|
||||
class="flex w-full items-start gap-2 rounded px-2 py-2 text-left transition-colors hover:bg-gray-light-300 dark:hover:bg-gray-dark-400"
|
||||
class="sub-button"
|
||||
>
|
||||
<span class="icon-svg mt-[2px] text-base leading-none">
|
||||
{{ partial "icon" "description" }}
|
||||
|
@ -48,7 +49,7 @@
|
|||
<button
|
||||
onclick="openInDocsAI()"
|
||||
data-heap-id="search-docs-ai-button"
|
||||
class="flex w-full items-start gap-2 rounded px-2 py-2 text-left transition-colors hover:bg-gray-light-300 dark:hover:bg-gray-dark-400"
|
||||
class="sub-button"
|
||||
>
|
||||
<span class="icon-svg mt-[2px] text-base leading-none">
|
||||
{{ partial "icon" "search" }}
|
||||
|
@ -116,4 +117,4 @@
|
|||
dropdown.removeAttribute("open");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -4,18 +4,21 @@
|
|||
- Limits heading levels to a min and max range (`$min` and `$max`).
|
||||
- Wraps the ToC in a `data-pagefind-ignore` container to exclude it from search indexing.
|
||||
- Includes a recursive template (`walkHeadingFragments`) to handle nested headings.
|
||||
*/ -}}
|
||||
*/
|
||||
-}}
|
||||
{{- $toc := false }}
|
||||
{{- with .Fragments }}
|
||||
{{- $toc = and (ne page.Params.notoc true) .Headings }}
|
||||
{{- end }}
|
||||
{{- with $toc }}
|
||||
<div data-pagefind-ignore class="not-prose">
|
||||
<div class="text-lg pb-0 lg:pb-2">{{ T "tableOfContents" }}</div>
|
||||
<nav class="toc">
|
||||
{{ $root := (index page.Fragments.Headings 0).Headings }}
|
||||
{{- template "walkHeadingFragments" $root }}
|
||||
</nav>
|
||||
<div class="pb-0 text-lg lg:pb-2">
|
||||
{{ T "tableOfContents" }}
|
||||
</div>
|
||||
<nav class="toc">
|
||||
{{ $root := (index page.Fragments.Headings 0).Headings }}
|
||||
{{- template "walkHeadingFragments" $root }}
|
||||
</nav>
|
||||
</div>
|
||||
{{- end }}
|
||||
|
||||
|
@ -26,7 +29,9 @@
|
|||
{{- range . }}
|
||||
{{- if and (ge .Level $min) (le .Level $max) }}
|
||||
<li>
|
||||
<a class="link lg:no-underline" href="#{{ .ID }}">{{ markdownify .Title }}</a>
|
||||
<a class="link lg:no-underline" href="#{{ .ID }}"
|
||||
>{{ markdownify .Title }}</a
|
||||
>
|
||||
</li>
|
||||
{{- end }}
|
||||
{{- with .Headings }}
|
||||
|
|
|
@ -1,70 +1,79 @@
|
|||
{{- if gt .Paginator.TotalPages 1 }}
|
||||
{{ $selectable := "cursor-pointer" }}
|
||||
{{ $active := "hover:text-black dark:hover:text-white underline underline-offset-8" }}
|
||||
{{ $disabled := "cursor-not-allowed text-gray-light dark:text-gray-dark" }}
|
||||
<ul class="flex gap-6 items-center">
|
||||
{{- with .Paginator }}
|
||||
{{- $currentPageNumber := .PageNumber }}
|
||||
{{ $disabled := "cursor-not-allowed text-gray-200 dark:text-gray-500" }}
|
||||
<ul class="flex items-center gap-6">
|
||||
{{- with .Paginator }}
|
||||
{{- $currentPageNumber := .PageNumber }}
|
||||
|
||||
{{- with .First }}
|
||||
{{- if ne $currentPageNumber .PageNumber }}
|
||||
<li>
|
||||
<a class="{{ $selectable }}" href="{{ .URL }}" aria-label="First">
|
||||
<span class="icon-svg">
|
||||
{{- partialCached "icon" "chevron_backward" "chevron_backward" -}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{{- else }}
|
||||
<li>
|
||||
<a class="{{ $disabled }}" aria-disabled="true" aria-label="First">
|
||||
<span class="icon-svg">
|
||||
{{- partialCached "icon" "chevron_backward" "chevron_backward" -}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{{- with .First }}
|
||||
{{- if ne $currentPageNumber .PageNumber }}
|
||||
<li>
|
||||
<a class="{{ $selectable }}" href="{{ .URL }}" aria-label="First">
|
||||
<span class="icon-svg">
|
||||
{{- partialCached "icon" "chevron_backward" "chevron_backward" -}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{{- else }}
|
||||
<li>
|
||||
<a class="{{ $disabled }}" aria-disabled="true" aria-label="First">
|
||||
<span class="icon-svg">
|
||||
{{- partialCached "icon" "chevron_backward" "chevron_backward" -}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- $slots := 5 }}
|
||||
{{- $start := math.Max 1 (sub .PageNumber (math.Floor (div $slots 2))) }}
|
||||
{{- $end := math.Min .TotalPages (sub (add $start $slots) 1) }}
|
||||
{{- if lt (add (sub $end $start) 1) $slots }}
|
||||
{{- $start = math.Max 1 (add (sub $end $slots) 1) }}
|
||||
{{- end }}
|
||||
|
||||
{{- range $k := seq $start $end }}
|
||||
{{- if eq $.Paginator.PageNumber $k }}
|
||||
<li>
|
||||
<a
|
||||
class="{{ $active }}"
|
||||
aria-current="page"
|
||||
aria-label="Page {{ $k }}"
|
||||
>{{ $k }}</a
|
||||
>
|
||||
</li>
|
||||
{{- else }}
|
||||
<li>
|
||||
<a
|
||||
class="{{ $selectable }}"
|
||||
href="{{ (index $.Paginator.Pagers (sub $k 1)).URL }}"
|
||||
aria-label="Page {{ $k }}"
|
||||
>{{ $k }}</a
|
||||
>
|
||||
</li>
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- with .Last }}
|
||||
{{- if ne $currentPageNumber .PageNumber }}
|
||||
<li>
|
||||
<a class="{{ $selectable }}" href="{{ .URL }}" aria-label="Last">
|
||||
<span class="icon-svg">
|
||||
{{- partialCached "icon" "chevron_forward" "chevron_forward" -}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{{- else }}
|
||||
<li>
|
||||
<a class="{{ $disabled }}" aria-disabled="true" aria-label="Last">
|
||||
<span class="icon-svg">
|
||||
{{- partialCached "icon" "chevron_forward" "chevron_forward" -}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- $slots := 5 }}
|
||||
{{- $start := math.Max 1 (sub .PageNumber (math.Floor (div $slots 2))) }}
|
||||
{{- $end := math.Min .TotalPages (sub (add $start $slots) 1) }}
|
||||
{{- if lt (add (sub $end $start) 1) $slots }}
|
||||
{{- $start = math.Max 1 (add (sub $end $slots) 1) }}
|
||||
{{- end }}
|
||||
|
||||
{{- range $k := seq $start $end }}
|
||||
{{- if eq $.Paginator.PageNumber $k }}
|
||||
<li>
|
||||
<a class="{{ $active }}" aria-current="page" aria-label="Page {{ $k }}">{{ $k }}</a>
|
||||
</li>
|
||||
{{- else }}
|
||||
<li>
|
||||
<a class="{{ $selectable }}" href="{{ (index $.Paginator.Pagers (sub $k 1)).URL }}" aria-label="Page {{ $k }}">{{ $k }}</a>
|
||||
</li>
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- with .Last }}
|
||||
{{- if ne $currentPageNumber .PageNumber }}
|
||||
<li>
|
||||
<a class="{{ $selectable }}" href="{{ .URL }}" aria-label="Last">
|
||||
<span class="icon-svg">
|
||||
{{- partialCached "icon" "chevron_forward" "chevron_forward" -}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{{- else }}
|
||||
<li>
|
||||
<a class="{{ $disabled }}" aria-disabled="true" aria-label="Last">
|
||||
<span class="icon-svg">
|
||||
{{- partialCached "icon" "chevron_forward" "chevron_forward" -}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
</ul>
|
||||
{{- end }}
|
||||
|
||||
|
|
|
@ -3,13 +3,23 @@
|
|||
<span class="icon-svg">{{ partialCached "icon" "search" "search" }}</span>
|
||||
</a>
|
||||
<!-- search button -->
|
||||
<div x-ref="searchBarRef" x-data="{ open: false }" @click.outside="open = false;"
|
||||
@keyup.escape.window="open = false" id="search-bar"
|
||||
class="hidden min-w-0 sm:flex relative bg-white/10 rounded items-center p-2 sm:w-full xl:w-[400px]">
|
||||
<div
|
||||
x-ref="searchBarRef"
|
||||
x-data="{ open: false }"
|
||||
@click.outside="open = false;"
|
||||
@keyup.escape.window="open = false"
|
||||
id="search-bar"
|
||||
class="relative hidden min-w-0 items-center rounded-sm bg-white/10 p-2 sm:flex sm:w-full xl:w-[400px]"
|
||||
>
|
||||
{{ (resources.Get "images/search-ai.svg").Content | safeHTML }}
|
||||
<input x-ref="searchBarInput" type="search" id="search-bar-input" @focus="open = true;"
|
||||
<input
|
||||
x-ref="searchBarInput"
|
||||
type="search"
|
||||
id="search-bar-input"
|
||||
@focus="open = true;"
|
||||
@keyup.enter.prevent="window.location.href = '/search/?q=' + $event.target.value;"
|
||||
@keyup.escape.prevent="open = false;" @keydown.window="(e) => {
|
||||
@keyup.escape.prevent="open = false;"
|
||||
@keydown.window="(e) => {
|
||||
switch(e.key) {
|
||||
case 'k':
|
||||
if (e.metaKey || e.ctrlKey) {
|
||||
|
@ -18,24 +28,41 @@
|
|||
}
|
||||
break;
|
||||
}
|
||||
}" class="flex-grow px-2 bg-transparent min-w-0 text-white placeholder:text-white outline-none" placeholder="Search"
|
||||
tabindex="0" />
|
||||
<div x-cloak :class="open && 'hidden'" class="hidden lg:flex border px-1 text-sm border-white rounded items-center">
|
||||
}"
|
||||
class="min-w-0 flex-grow bg-transparent px-2 text-white outline-hidden placeholder:text-white"
|
||||
placeholder="Search"
|
||||
tabindex="0"
|
||||
/>
|
||||
<div
|
||||
x-cloak
|
||||
:class="open && 'hidden'"
|
||||
class="hidden items-center rounded-sm border border-white px-1 text-sm lg:flex"
|
||||
>
|
||||
<div class="-mt-0.5">
|
||||
<span x-show="navigator.platform == 'MacIntel'" class="icon-svg icon-sm">{{ partialCached "icon" "keyboard_command_key" "keyboard_command_key" }}</span>
|
||||
<span x-show="navigator.platform != 'MacIntel'" class="icon-svg icon-sm">{{ partialCached "icon" "keyboard_control_key" "keyboard_control_key" }}</span>
|
||||
<span x-show="navigator.platform == 'MacIntel'" class="icon-svg icon-sm"
|
||||
>{{ partialCached "icon" "keyboard_command_key" "keyboard_command_key" }}</span
|
||||
>
|
||||
<span x-show="navigator.platform != 'MacIntel'" class="icon-svg icon-sm"
|
||||
>{{ partialCached "icon" "keyboard_control_key" "keyboard_control_key" }}</span
|
||||
>
|
||||
</div>
|
||||
<span>K</span>
|
||||
</div>
|
||||
<div x-cloak :class="open || 'hidden'">
|
||||
<button @click="$refs.searchBarInput.value = ''; open = false" class="text-white hover:text-white">
|
||||
<button
|
||||
@click="$refs.searchBarInput.value = ''; open = false"
|
||||
class="text-white hover:text-white"
|
||||
>
|
||||
<span class="icon-svg">{{ partialCached "icon" "close" "close" }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div x-show="open" x-cloak
|
||||
class="absolute px-6 py-4 right-0 w-screen max-w-xl top-full bg-background-light dark:bg-background-dark rounded shadow-lg z-50">
|
||||
<div
|
||||
x-show="open"
|
||||
x-cloak
|
||||
class="bg-background-light dark:bg-background-dark absolute top-full right-0 z-50 w-screen max-w-xl rounded-sm px-6 py-4 shadow-lg"
|
||||
>
|
||||
<div id="search-bar-results">
|
||||
{{- $emptyState := `<div class="p-2 text-gray-light dark:text-gray-dark">Start typing to search… or try <button @click="open=false" class="open-kapa-widget link">Ask AI</button></div>` }}
|
||||
{{- $emptyState := `<div class="p-2 text-gray-200 dark:text-gray-500">Start typing to search… or try <button @click="open=false" class="open-kapa-widget link">Ask AI</button></div>` }}
|
||||
{{- $emptyState | safe.HTML }}
|
||||
<!-- results -->
|
||||
</div>
|
||||
|
@ -77,7 +104,7 @@
|
|||
searchBarResults.classList.add("hidden");
|
||||
}
|
||||
|
||||
let resultsHTML = `<div class="p-2 text-gray-light dark:text-gray-dark">${resultsLength} results</div>`;
|
||||
let resultsHTML = `<div class="p-2 text-gray-200 dark:text-gray-500">${resultsLength} results</div>`;
|
||||
resultsHTML += results
|
||||
.map((item) => {
|
||||
return `<div class="p-2">
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
- Includes a stepper navigation (`guides-stepper.html`) for multipage guides.
|
||||
- Optionally lists resource links from `Params.resource_links`.
|
||||
- Provides a link back to the main `/guides/` index.
|
||||
*/ -}}
|
||||
*/
|
||||
-}}
|
||||
<div class="flex flex-col gap-4 px-4 pt-2">
|
||||
{{- $root := . }}
|
||||
{{- .Store.Set "multipage" false }}
|
||||
|
@ -18,35 +19,35 @@
|
|||
</div>
|
||||
<div>{{ $root.Summary }}</div>
|
||||
<div class="space-y-4">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
{{- with ($root.GetTerms "languages") }}
|
||||
<div class="flex flex-wrap gap-2">
|
||||
{{- with ($root.GetTerms "languages") }}
|
||||
{{ partial "languages.html" . }}
|
||||
{{- end }}
|
||||
{{- with ($root.GetTerms "tags") }}
|
||||
{{- end }}
|
||||
{{- with ($root.GetTerms "tags") }}
|
||||
{{ partial "tags.html" . }}
|
||||
{{- end }}
|
||||
</div>
|
||||
{{- with ($root.Params.time) }}
|
||||
<div class="flex gap-2 text-gray-light dark:text-gray-dark">
|
||||
<span class="icon-svg"
|
||||
>{{ partialCached "icon" "schedule" "schedule" }}</span
|
||||
>
|
||||
<span>{{ . }}</span>
|
||||
{{- end }}
|
||||
</div>
|
||||
{{- end -}}
|
||||
{{- with ($root.Params.time) }}
|
||||
<div class="flex gap-2 text-gray-200 dark:text-gray-500">
|
||||
<span class="icon-svg"
|
||||
>{{ partialCached "icon" "schedule" "schedule" }}</span
|
||||
>
|
||||
<span>{{ . }}</span>
|
||||
</div>
|
||||
{{- end -}}
|
||||
</div>
|
||||
{{- if (.Store.Get "multipage") }}
|
||||
{{- partial "guides-stepper.html" . }}
|
||||
{{- end }}
|
||||
{{- with $root.Params.resource_links }}
|
||||
<div class="space-y-2">
|
||||
<p>Resources:</p>
|
||||
<ul class="ml-4 space-y-2">
|
||||
{{- range . }}
|
||||
<li><a href="{{ .url }}" class="link">{{ .title }}</a></li>
|
||||
{{- end }}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<p>Resources:</p>
|
||||
<ul class="ml-4 space-y-2">
|
||||
{{- range . }}
|
||||
<li><a href="{{ .url }}" class="link">{{ .title }}</a></li>
|
||||
{{- end }}
|
||||
</ul>
|
||||
</div>
|
||||
{{- end }}
|
||||
<a href="/guides/" class="mt-2 link">« Back to all guides</a>
|
||||
<a href="/guides/" class="link mt-2">« Back to all guides</a>
|
||||
</div>
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
- Renders the main navigation for site sections, linking to the current or ancestor section/page.
|
||||
- Uses the `site.Menus.main` configuration to determine primary navigation structure.
|
||||
- Toggles visibility of nested menu items for the main sections.
|
||||
*/ -}}
|
||||
*/
|
||||
-}}
|
||||
<!-- Main navigation for the sidebar -->
|
||||
<div class="py-2 px-4" x-data="{ expanded: false }">
|
||||
<div class="px-4 py-2" x-data="{ expanded: false }">
|
||||
<div class="flex w-full items-center justify-between">
|
||||
<!-- Current section: use menu, fall back to current section or page -->
|
||||
{{- $curr := .FirstSection }}
|
||||
|
@ -17,15 +18,21 @@
|
|||
{{- $curr = .Page }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
<a class="hover:text-blue-light dark:hover:text-blue-dark" href="{{ $curr.Permalink }}">
|
||||
<a
|
||||
class="hover:text-blue dark:hover:text-blue"
|
||||
href="{{ $curr.Permalink }}"
|
||||
>
|
||||
{{- with $curr.Params.icon }}
|
||||
<span class="pr-2 icon-sm icon-svg">
|
||||
<span class="icon-sm icon-svg pr-2">
|
||||
{{- partialCached "icon.html" . . -}}
|
||||
</span>
|
||||
{{- end }}
|
||||
{{- $curr.LinkTitle -}}
|
||||
</a>
|
||||
<button @click="expanded = !expanded" class="rounded hover:bg-gray-light-300 hover:dark:bg-gray-dark-300">
|
||||
<button
|
||||
@click="expanded = !expanded"
|
||||
class="rounded-sm hover:bg-gray-300 hover:dark:bg-gray-300"
|
||||
>
|
||||
<span x-show="! expanded" class="icon-svg">
|
||||
{{ partialCached "icon" "arrow_drop_down" "arrow_drop_down" }}
|
||||
</span>
|
||||
|
@ -34,21 +41,21 @@
|
|||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<ul x-cloak x-show="expanded" class="pt-4 space-y-4">
|
||||
<ul x-cloak x-show="expanded" class="space-y-4 pt-4">
|
||||
{{ range site.Menus.main }}
|
||||
{{ if ne page.FirstSection .Page }}
|
||||
<li>
|
||||
<a class="hover:text-blue-light dark:hover:text-blue-dark" href="{{ .URL }}">
|
||||
{{- with .Page.Params.icon }}
|
||||
<span class="pr-2 icon-sm icon-svg">
|
||||
{{- partialCached "icon.html" . . -}}
|
||||
</span>
|
||||
{{- end }}
|
||||
{{- .Name }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="hover:text-blue dark:hover:text-blue" href="{{ .URL }}">
|
||||
{{- with .Page.Params.icon }}
|
||||
<span class="icon-sm icon-svg pr-2">
|
||||
{{- partialCached "icon.html" . . -}}
|
||||
</span>
|
||||
{{- end }}
|
||||
{{- .Name }}
|
||||
</a>
|
||||
</li>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
<hr class="m-2 text-gray-light-200 dark:text-gray-dark-300" />
|
||||
<hr class="m-2 text-gray-200 dark:text-gray-500" />
|
||||
|
|
|
@ -5,11 +5,13 @@
|
|||
- Dynamically applies current page highlighting and expanded states.
|
||||
- Handles external links via `Params.sidebar.goto` in `renderSingle`.
|
||||
- Requires `Params.sitemap` and `Params.sidebar` for filtering and behavior.
|
||||
*/ -}}
|
||||
*/
|
||||
-}}
|
||||
<!-- section tree -->
|
||||
<nav class="md:text-sm flex flex-col">
|
||||
<div
|
||||
class="block py-4 md:hidden text-gray-light dark:text-gray-dark">This section</div>
|
||||
<nav class="navbar-font flex flex-col">
|
||||
<div class="block py-4 text-gray-200 md:hidden dark:text-gray-200">
|
||||
This section
|
||||
</div>
|
||||
<ul>
|
||||
{{ template "renderChildren" .FirstSection }}
|
||||
</ul>
|
||||
|
@ -29,8 +31,10 @@
|
|||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range .Params.sidebar.groups }}
|
||||
<li class="px-2 py-2 pb-2 text-gray-light dark:text-gray-dark uppercase
|
||||
text-xs font-semibold">{{ . }}</li>
|
||||
<!-- Main titles -->
|
||||
<li class="navbar-group-font-title mt-2 px-2 py-2 pt-5 pb-2">
|
||||
{{ . }}
|
||||
</li>
|
||||
{{- range where $pages "Params.sidebar.group" . }}
|
||||
{{- if .IsSection }}
|
||||
{{- template "renderList" . }}
|
||||
|
@ -45,34 +49,56 @@
|
|||
{{ define "renderList" }}
|
||||
{{ $isCurrent := eq page . }}
|
||||
{{ $expanded := or $isCurrent (page.IsDescendant .) }}
|
||||
<li x-data="{ expanded: {{$expanded}} }">
|
||||
<div class="rounded px-4 w-full flex items-center justify-between{{ if $isCurrent }} bg-gray-light-200 dark:bg-gray-dark-200{{ end }}">
|
||||
<div class="w-full py-2 truncate">
|
||||
<li x-data="{ expanded: {{ $expanded }} }">
|
||||
<div
|
||||
class="justify-between{{ if $isCurrent }}
|
||||
bg-gray-100 dark:bg-gray-900
|
||||
{{ end }} flex w-full items-center rounded-sm px-4"
|
||||
>
|
||||
<div class="w-full truncate py-1">
|
||||
{{- if .Permalink }}
|
||||
{{/* If the link is not empty, use it */}}
|
||||
<a {{ if $isCurrent }}aria-current="page" id="sidebar-current-page" {{ end }}
|
||||
class="block select-none hover:text-blue-light hover:dark:text-blue-dark"
|
||||
href="{{ .Permalink }}">
|
||||
<a
|
||||
{{ if $isCurrent }}
|
||||
aria-current="page" id="sidebar-current-page"
|
||||
{{ end }}
|
||||
class="hover:text-blue block select-none hover:dark:text-blue-400"
|
||||
href="{{ .Permalink }}"
|
||||
>
|
||||
{{ template "renderTitle" . }}
|
||||
</a>
|
||||
{{- else }}
|
||||
{{/* Otherwise, just expand the section */}}
|
||||
<button @click="expanded = !expanded"
|
||||
class="w-full text-left select-none hover:text-blue-light hover:dark:text-blue-dark">
|
||||
<button
|
||||
@click="expanded = !expanded"
|
||||
class="hover:text-blue w-full text-left select-none hover:dark:text-blue-400"
|
||||
>
|
||||
{{ template "renderTitle" . }}
|
||||
</button>
|
||||
{{- end }}
|
||||
</div>
|
||||
<button @click="expanded = !expanded" class="hover:bg-gray-light-300 hover:dark:bg-gray-dark-300 rounded">
|
||||
<span :class="{ 'hidden' : expanded }" class="icon-svg {{ if $expanded }}hidden{{ end }}">
|
||||
<button
|
||||
@click="expanded = !expanded"
|
||||
class="rounded-sm hover:bg-gray-300 hover:dark:bg-gray-300"
|
||||
>
|
||||
<span
|
||||
:class="{ 'hidden' : expanded }"
|
||||
class="icon-svg {{ if $expanded }}hidden{{ end }}"
|
||||
>
|
||||
{{ partialCached "icon" "arrow_drop_down" "arrow_drop_down" }}
|
||||
</span>
|
||||
<span :class="{ 'hidden' : !expanded }" class="icon-svg {{ if not $expanded }}hidden{{ end }}">
|
||||
<span
|
||||
:class="{ 'hidden' : !expanded }"
|
||||
class="icon-svg {{ if not $expanded }}hidden{{ end }}"
|
||||
>
|
||||
{{ partialCached "icon" "arrow_drop_up" "arrow_drop_up" }}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<ul :class="{ 'hidden' : !expanded }" class="{{if not $expanded}}hidden {{end}}ml-3">
|
||||
<ul
|
||||
:class="{ 'hidden' : !expanded }"
|
||||
class="{{ if not $expanded }}hidden{{ end }} ml-3"
|
||||
>
|
||||
{{ template "renderChildren" . }}
|
||||
</ul>
|
||||
</li>
|
||||
|
@ -80,19 +106,30 @@
|
|||
|
||||
{{ define "renderSingle" }}
|
||||
{{- if .Params.sidebar.goto }}
|
||||
<li class="px-4 hover:text-blue-light hover:dark:text-blue-dark">
|
||||
<a class="py-2 w-full truncate block"
|
||||
href="{{ .Params.sidebar.goto }}"
|
||||
title="{{ .LinkTitle }}">
|
||||
<li class="hover:text-blue px-4 hover:dark:text-blue-400">
|
||||
<a
|
||||
class="block w-full truncate py-2"
|
||||
href="{{ .Params.sidebar.goto }}"
|
||||
title="{{ .LinkTitle }}"
|
||||
>
|
||||
{{ template "renderTitle" . }}
|
||||
</a>
|
||||
</li>
|
||||
{{- else }}
|
||||
{{ $isCurrent := eq page . }}
|
||||
<li class="rounded px-4 hover:text-blue-light hover:dark:text-blue-dark
|
||||
{{ if $isCurrent }} bg-gray-light-200 dark:bg-gray-dark-200{{ end }}">
|
||||
<a {{ if $isCurrent }}aria-current="page" id="sidebar-current-page" {{ end }} class="py-2 w-full truncate block"
|
||||
href="{{ .Permalink }}" title="{{ .LinkTitle }}">
|
||||
<li
|
||||
class="hover:text-blue {{ if $isCurrent }}
|
||||
bg-gray-100 dark:bg-gray-900
|
||||
{{ end }} rounded-sm px-4 hover:dark:text-blue-400"
|
||||
>
|
||||
<a
|
||||
{{ if $isCurrent }}
|
||||
aria-current="page" id="sidebar-current-page"
|
||||
{{ end }}
|
||||
class="block w-full truncate py-2"
|
||||
href="{{ .Permalink }}"
|
||||
title="{{ .LinkTitle }}"
|
||||
>
|
||||
{{ template "renderTitle" . }}
|
||||
</a>
|
||||
</li>
|
||||
|
@ -102,6 +139,8 @@
|
|||
{{ define "renderTitle" }}
|
||||
{{ .LinkTitle }}
|
||||
{{- with .Params.sidebar.badge }}
|
||||
<span>{{- partial "components/badge.html" (dict "color" .color "content" .text) }}</span>
|
||||
<span
|
||||
>{{- partial "components/badge.html" (dict "color" .color "content" .text) }}</span
|
||||
>
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
|
|
@ -2,14 +2,20 @@
|
|||
Renders a flat list of tags for the "tags" taxonomy.
|
||||
- Unlike `sections.html`, this template is based on taxonomy terms, not section pages.
|
||||
- Highlights the current tag page and links to all tag pages.
|
||||
*/ -}}
|
||||
*/
|
||||
-}}
|
||||
<ul class="md:text-sm">
|
||||
{{- range site.Taxonomies.tags }}
|
||||
<li class="pl-4 hover:text-blue-light hover:dark:text-blue-dark
|
||||
{{ if eq .Page page }} bg-gray-light-200 dark:bg-gray-dark-200{{ end }}">
|
||||
<a class="py-2 w-full truncate block"
|
||||
href="{{ .Page.Permalink }}"
|
||||
title="{{ .Page.LinkTitle }}">
|
||||
<li
|
||||
class="hover:text-blue {{ if eq .Page page }}
|
||||
bg-gray-400 dark:bg-gray-800
|
||||
{{ end }} pl-4 hover:dark:text-blue-700"
|
||||
>
|
||||
<a
|
||||
class="block w-full truncate py-2"
|
||||
href="{{ .Page.Permalink }}"
|
||||
title="{{ .Page.LinkTitle }}"
|
||||
>
|
||||
{{ .Page.LinkTitle }}
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -7,14 +7,13 @@
|
|||
{{- if eq .File nil }}
|
||||
{{- errorf "[tags] Undefined tag: '%s' in %s" (urlize (strings.ToLower .Title)) page.File.Filename }}
|
||||
{{- end }}
|
||||
<a class="text-sm inline-flex items-center rounded-full border
|
||||
border-divider-light dark:border-divider-dark bg-gray-light-100 px-2
|
||||
text-gray-light-800 dark:bg-gray-dark-200 dark:text-gray-dark-800
|
||||
select-none"
|
||||
href="{{ .Permalink }}">
|
||||
<a
|
||||
class="border-divider-light dark:border-divider-dark bg-gray-00 inline-flex items-center rounded-full border px-2 text-sm text-gray-800 select-none hover:bg-gray-100 dark:bg-gray-800 dark:text-gray-200 hover:dark:bg-gray-700"
|
||||
href="{{ .Permalink }}"
|
||||
>
|
||||
<span class="icon-svg icon-sm pb-0.5">
|
||||
{{ partialCached "icon" "tag" "tag" }}
|
||||
</span>
|
||||
<span>{{ .LinkTitle }}</span>
|
||||
</a>
|
||||
</a>
|
||||
{{- end -}}
|
||||
|
|
|
@ -1,15 +1,24 @@
|
|||
{{- /*
|
||||
Renders a tooltip component using Floating UI for positioning.
|
||||
See script at `assets/js/src/tooltip.js` for functionality.
|
||||
*/ -}}
|
||||
*/
|
||||
-}}
|
||||
<div data-tooltip-wrapper>
|
||||
<div data-tooltip-button class="icon-svg flex items-center text-blue-light dark:text-blue-dark">
|
||||
<div
|
||||
data-tooltip-button
|
||||
class="icon-svg text-blue-light flex items-center dark:text-blue-700"
|
||||
>
|
||||
{{ partialCached "icon" "help" "help" }}
|
||||
</div>
|
||||
<div data-tooltip-body
|
||||
class="absolute left-0 top-0 hidden max-w-56 rounded bg-gray-light-700 p-2 text-white dark:bg-gray-dark-300"
|
||||
role="tooltip">
|
||||
<div
|
||||
data-tooltip-body
|
||||
class="absolute top-0 left-0 hidden max-w-56 rounded-sm bg-gray-700 p-2 text-white dark:bg-gray-300"
|
||||
role="tooltip"
|
||||
>
|
||||
{{ . }}
|
||||
<div data-tooltip-arrow class="absolute h-2 w-2 rotate-45 bg-gray-light-700 dark:bg-gray-dark-300"></div>
|
||||
<div
|
||||
data-tooltip-arrow
|
||||
class="absolute h-2 w-2 rotate-45 bg-gray-700 dark:bg-gray-300"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
{{- /*
|
||||
Processes and links the main CSS file (`assets/css/styles.css`).
|
||||
- Applies PostCSS, minification, fingerprinting, and post-processing in production.
|
||||
- Adds inline CSS to hide injected images in production builds.
|
||||
*/ -}}
|
||||
{{ $styles := resources.Get "css/styles.css" }}
|
||||
{{ $styles = $styles | css.PostCSS }}
|
||||
{{ if hugo.IsProduction }}
|
||||
{{ $styles = $styles | minify | fingerprint | resources.PostProcess }}
|
||||
<style>
|
||||
/* hide img injected by prod scripts */
|
||||
body > img { display: none }
|
||||
</style>
|
||||
{{ with (templates.Defer (dict "key" "global")) }}
|
||||
{{ with resources.Get "css/style.css" }}
|
||||
{{ $opts := dict
|
||||
"minify" hugo.IsProduction
|
||||
"inlineImports" true
|
||||
}}
|
||||
{{ with . | css.TailwindCSS $opts }}
|
||||
{{ if hugo.IsProduction }}
|
||||
{{ with . | fingerprint }}
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="{{ .RelPermalink }}"
|
||||
integrity="{{ .Data.Integrity }}"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
<link rel="stylesheet" href="{{ .RelPermalink }}" />
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
<link href="{{ $styles.Permalink }}" rel="stylesheet" />
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
{{- $path := printf "%s" . }}
|
||||
{{- with resources.Get $path }}
|
||||
{{ .Content | safeHTML }}
|
||||
{{- else }}
|
||||
{{- if in $path "toolbox.svg" }}
|
||||
{{/* Temporary empty branch */}}
|
||||
{{- else }}
|
||||
{{- errorf "The 'svg' partial was unable to find %s" $path }}
|
||||
{{- end }}
|
||||
{{- end }}
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
{{ define "main" }}
|
||||
{{ partial "breadcrumbs.html" . }}
|
||||
<article class="prose max-w-none dark:prose-invert">
|
||||
<article class="prose dark:prose-invert max-w-none">
|
||||
{{ with .Title }}
|
||||
<h1 class="scroll-mt-36">{{ . }}</h1>
|
||||
<h1>{{ . }}</h1>
|
||||
{{ end }}
|
||||
<table>
|
||||
<thead>
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
{{ $url = ref .Page $url }}
|
||||
{{- end -}}
|
||||
<div class="not-prose my-4">
|
||||
<a href="{{ $url }}"
|
||||
class="cursor-pointer py-2 px-4 rounded bg-blue-light-500 dark:bg-blue-dark-400 hover:bg-blue-light-400 dark:hover:bg-blue-dark-500 text-white">{{
|
||||
$text }}</a>
|
||||
<a
|
||||
href="{{ $url }}"
|
||||
class="cursor-pointer rounded-sm bg-blue-500 px-4 py-2 text-white hover:bg-blue-400 dark:bg-blue-800 dark:hover:bg-blue-700"
|
||||
>{{ $text }}</a
|
||||
>
|
||||
</div>
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
{{ partial "components/card.html"
|
||||
(dict
|
||||
"description" (.Get "description")
|
||||
"link" (.Get "link")
|
||||
"title" (.Get "title")
|
||||
"icon" (.Get "icon")
|
||||
"image" (.Get "image")
|
||||
"description" (.Get "description")
|
||||
"link" (.Get "link")
|
||||
"title" (.Get "title")
|
||||
"icon" (.Get "icon")
|
||||
)
|
||||
}}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
<div class="p-4 bg-amber-light-200 dark:bg-amber-dark-200" role="alert">
|
||||
<div class="bg-amber-light-200 dark:bg-amber-dark-200 p-4" role="alert">
|
||||
<div class="text-lg">{{ .Get "header" }}</div>
|
||||
{{ .Get "body" | .Page.RenderString (dict "display" "block") }}
|
||||
<div class="not-prose">
|
||||
<a href="{{ .Get "url" }}"
|
||||
class="cursor-pointer py-2 px-4 rounded bg-blue-light-500 dark:bg-blue-dark-400 hover:bg-blue-light-400 dark:hover:bg-blue-dark-500 text-white"
|
||||
>{{ .Get "cta" }}</a>
|
||||
<a
|
||||
href="{{ .Get "url" }}"
|
||||
class="cursor-pointer rounded-sm bg-blue-500 px-4 py-2 text-white hover:bg-blue-400 dark:bg-blue-800 dark:hover:bg-blue-700"
|
||||
>{{ .Get "cta" }}</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -4,43 +4,50 @@
|
|||
{{- $mac := .Get "mac" -}}
|
||||
{{- $linux := .Get "linux" -}}
|
||||
{{- $build_path := .Get "build_path" -}}
|
||||
<blockquote {{ if eq $build_path "/" }} class="tip" {{ end }}>
|
||||
<p>Download Docker Desktop</p>
|
||||
<p>
|
||||
<blockquote {{ if eq $build_path "/" }} class="tip" {{ end }} class="not-prose download-links">
|
||||
<p>Download Docker Desktop:</p>
|
||||
<div class="download-links-subcontainer">
|
||||
{{- if or $all $win }}
|
||||
<a rel="noopener"
|
||||
href="https://desktop.docker.com/win/main/amd64{{ $build_path }}Docker%20Desktop%20Installer.exe">Windows</a>
|
||||
(<a rel="noopener"
|
||||
href="https://desktop.docker.com/win/main/amd64{{ $build_path }}checksums.txt">checksum</a>) |
|
||||
<div>
|
||||
<a rel="noopener"
|
||||
href="https://desktop.docker.com/win/main/amd64{{ $build_path }}Docker%20Desktop%20Installer.exe">Windows</a>
|
||||
(<a rel="noopener"
|
||||
href="https://desktop.docker.com/win/main/amd64{{ $build_path }}checksums.txt">checksum</a>)
|
||||
</div>
|
||||
{{ end }}
|
||||
{{- if or $beta_win_arm }}
|
||||
<a rel="noopener"
|
||||
href="https://desktop.docker.com/win/main/arm64{{ $build_path }}Docker%20Desktop%20Installer.exe">Windows ARM Beta</a>
|
||||
(<a rel="noopener"
|
||||
href="https://desktop.docker.com/win/main/arm64{{ $build_path }}checksums.txt">checksum</a>) |
|
||||
<div>
|
||||
<a rel="noopener"
|
||||
href="https://desktop.docker.com/win/main/arm64{{ $build_path }}Docker%20Desktop%20Installer.exe">Windows ARM Beta</a>
|
||||
(<a rel="noopener"
|
||||
href="https://desktop.docker.com/win/main/arm64{{ $build_path }}checksums.txt">checksum</a>)
|
||||
</div>
|
||||
{{ end }}
|
||||
{{- if or $all $mac }}
|
||||
<a rel="noopener" href="https://desktop.docker.com/mac/main/arm64{{ $build_path }}Docker.dmg">Mac
|
||||
with Apple chip</a>
|
||||
(<a rel="noopener"
|
||||
href="https://desktop.docker.com/mac/main/arm64{{ $build_path }}checksums.txt">checksum</a>) |
|
||||
<a rel="noopener" href="https://desktop.docker.com/mac/main/amd64{{ $build_path }}Docker.dmg">Mac
|
||||
with Intel chip</a>
|
||||
(<a rel="noopener"
|
||||
href="https://desktop.docker.com/mac/main/amd64{{ $build_path }}checksums.txt">checksum</a>)
|
||||
<div>
|
||||
<a rel="noopener" href="https://desktop.docker.com/mac/main/arm64{{ $build_path }}Docker.dmg">Mac with Apple chip</a>
|
||||
(<a rel="noopener"
|
||||
href="https://desktop.docker.com/mac/main/arm64{{ $build_path }}checksums.txt">checksum</a>)
|
||||
</div>
|
||||
<div>
|
||||
<a rel="noopener" href="https://desktop.docker.com/mac/main/amd64{{ $build_path }}Docker.dmg">Mac with Intel chip</a>
|
||||
(<a rel="noopener"
|
||||
href="https://desktop.docker.com/mac/main/amd64{{ $build_path }}checksums.txt">checksum</a>)
|
||||
</div>
|
||||
{{ end -}}
|
||||
{{- if or $all $linux }}
|
||||
|
|
||||
<a rel="noopener"
|
||||
href="https://desktop.docker.com/linux/main/amd64{{ $build_path }}docker-desktop-amd64.deb">Debian</a>
|
||||
-
|
||||
<a rel="noopener"
|
||||
href="https://desktop.docker.com/linux/main/amd64{{ $build_path }}docker-desktop-x86_64.rpm">RPM</a>
|
||||
-
|
||||
<a rel="noopener"
|
||||
href="https://desktop.docker.com/linux/main/amd64{{ $build_path }}docker-desktop-x86_64.pkg.tar.zst">Arch</a>
|
||||
(<a rel="noopener"
|
||||
href="https://desktop.docker.com/linux/main/amd64{{ $build_path }}checksums.txt">checksum</a>)
|
||||
<div>
|
||||
<a rel="noopener"
|
||||
href="https://desktop.docker.com/linux/main/amd64{{ $build_path }}docker-desktop-amd64.deb">Debian</a>
|
||||
-
|
||||
<a rel="noopener"
|
||||
href="https://desktop.docker.com/linux/main/amd64{{ $build_path }}docker-desktop-x86_64.rpm">RPM</a>
|
||||
-
|
||||
<a rel="noopener"
|
||||
href="https://desktop.docker.com/linux/main/amd64{{ $build_path }}docker-desktop-x86_64.pkg.tar.zst">Arch</a>
|
||||
(<a rel="noopener"
|
||||
href="https://desktop.docker.com/linux/main/amd64{{ $build_path }}checksums.txt">checksum</a>)
|
||||
</div>
|
||||
{{- end -}}
|
||||
</p>
|
||||
</div>
|
||||
</blockquote>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
{{ $cols := .Get "cols" | default 3 }}
|
||||
<div class="not-prose grid grid-cols-1 md:grid-cols-{{ math.Max 2 (sub $cols 1) }} lg:grid-cols-{{ $cols }} gap-4">
|
||||
<div
|
||||
class="not-prose md:grid-cols-{{ math.Max 2 (sub $cols 1) }} lg:grid-cols-{{ $cols }} grid grid-cols-1 gap-4 mb-6"
|
||||
>
|
||||
{{ $items := index .Page.Params (.Get "items" | default "grid") }}
|
||||
{{ range $items }}
|
||||
{{ $opts := dict "title" .title "link" .link "description" .description "icon" .icon "image" .image }}
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
<em class="italic text-gray-light-500 dark:text-gray-dark-500"
|
||||
>{{ .Get "date" }}</em
|
||||
>
|
||||
<em class="text-gray-200 italic dark:text-gray-500">{{ .Get "date" }}</em>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
|
||||
<div
|
||||
class="not-prose my-1 flex flex-col border-l-4 border-gray-light-200 bg-gray-light-200 bg-opacity-75 px-4 py-1 dark:bg-gray-dark-300 dark:bg-opacity-75"
|
||||
class="not-prose summary-bar"
|
||||
>
|
||||
{{ with $feature.subscription }}
|
||||
<div class="flex flex-wrap gap-1">
|
||||
|
@ -79,4 +79,4 @@
|
|||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
|
|
@ -4,26 +4,27 @@
|
|||
{{ $groupID := fmt.Printf "tabgroup-%s" (urlize $group) }}
|
||||
{{ $persist := .Get "persist" }}
|
||||
|
||||
|
||||
<div
|
||||
{{ with $group }}
|
||||
{{ if $persist }}
|
||||
x-data="{ selected: $persist('{{$first}}').as('{{$groupID}}') }"
|
||||
x-data="{ selected: $persist('{{ $first }}').as('{{ $groupID }}') }"
|
||||
{{ else }}
|
||||
x-data="{ selected: '{{$first}}' }"
|
||||
x-data="{ selected: '{{ $first }}' }"
|
||||
{{ end }}
|
||||
@tab-select.window="$event.detail.group === '{{ . }}'
|
||||
? selected = $event.detail.name
|
||||
: null"
|
||||
@tab-select.window="$event.detail.group === '{{ . }}' ? selected =
|
||||
$event.detail.name : null"
|
||||
{{ else }}
|
||||
x-data="{ selected: '{{ $first }}' }"
|
||||
{{ end }}
|
||||
aria-role="tabpanel">
|
||||
aria-role="tabpanel"
|
||||
>
|
||||
<div aria-role="tablist" class="space-x-2">
|
||||
{{ range (.Store.Get "tabs") }}
|
||||
<button
|
||||
class="p-1"
|
||||
:class="selected === '{{ .name | urlize }}' &&
|
||||
'border-blue-light-500 border-b-4 dark:border-b-blue-dark-600'"
|
||||
'border-blue border-b-4 dark:border-b-blue-600'"
|
||||
{{ if $group }}
|
||||
@click="$dispatch('tab-select', { group: '{{ $group }}', name:
|
||||
'{{ .name | urlize }}'})"
|
||||
|
|
|
@ -4,20 +4,22 @@
|
|||
{{ end }}
|
||||
|
||||
{{ define "main" }}
|
||||
<article class="prose max-w-none dark:prose-invert">
|
||||
<article class="prose dark:prose-invert max-w-none">
|
||||
{{ partial "breadcrumbs.html" . }}
|
||||
<h1 class="scroll-mt-36 flex items-center">
|
||||
<span class="icon-svg icon-lg pb-2">{{ partialCached "icon" "tag" "tag" }}</span>
|
||||
<h1 class="flex items-center">
|
||||
<span class="icon-svg icon-lg pb-2"
|
||||
>{{ partialCached "icon" "tag" "tag" }}</span
|
||||
>
|
||||
<span>{{ .Title }}</span>
|
||||
</h1>
|
||||
{{ .Content }}
|
||||
<ul>
|
||||
{{ range site.Taxonomies.tags }}
|
||||
<li>
|
||||
<a href="{{ .Page.Permalink }}">{{ .Page.Title }}</a>
|
||||
({{ (len .Pages) }} {{ cond (gt (len .Pages) 1) "pages" "page" }})
|
||||
</li>
|
||||
{{ end }}
|
||||
{{ range site.Taxonomies.tags }}
|
||||
<li>
|
||||
<a href="{{ .Page.Permalink }}">{{ .Page.Title }}</a>
|
||||
({{ (len .Pages) }} {{ cond (gt (len .Pages) 1) "pages" "page" }})
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</article>
|
||||
{{ end }}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
{{ define "main" }}
|
||||
<article class="prose max-w-none dark:prose-invert">
|
||||
{{ partial "breadcrumbs.html" . }}
|
||||
<h1 class="scroll-mt-36 flex items-center">
|
||||
<h1 class="flex items-center">
|
||||
<span class="icon-svg icon-lg pb-2">{{ partialCached "icon" "tag" "tag" }}</span>
|
||||
</span>{{ .Title }}</span>
|
||||
</h1>
|
||||
|
|
|
@ -19,19 +19,16 @@
|
|||
"@alpinejs/persist": "^3.14.3",
|
||||
"@floating-ui/dom": "^1.6.12",
|
||||
"@material-symbols/svg-400": "^0.23.0",
|
||||
"@tailwindcss/cli": "^4.1.6",
|
||||
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
|
||||
"@tailwindcss/typography": "^0.5.15",
|
||||
"alpinejs": "^3.14.3",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"postcss": "^8.4.49",
|
||||
"postcss-cli": "^11.0.0",
|
||||
"postcss-import": "^16.1.0",
|
||||
"tailwindcss": "^3.4.15"
|
||||
"tailwindcss": "^4.1.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"markdownlint": "^0.35.0",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-go-template": "^0.0.15",
|
||||
"prettier-plugin-tailwindcss": "^0.6.8"
|
||||
"prettier-plugin-tailwindcss": "^0.6.11"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
module.exports = {
|
||||
plugins: {
|
||||
"postcss-import": {},
|
||||
"tailwindcss/nesting": {},
|
||||
tailwindcss: {},
|
||||
...(process.env.NODE_ENV === "production" ? { autoprefixer: {} } : {}),
|
||||
},
|
||||
};
|