init
This commit is contained in:
18
priv/ui/pug-demo/README.md
Normal file
18
priv/ui/pug-demo/README.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Pug Features Demo
|
||||
|
||||
This folder is a small Pug demo showing:
|
||||
|
||||
- interpolation with `#{name}`
|
||||
- conditionals with `if` and `case`
|
||||
- loops with `each`
|
||||
- includes with `_summary.pug` and `_mixins.pug`
|
||||
- layout inheritance with `extends ./layout.pug`
|
||||
- reusable mixins with `+featureCard(feature)` and `+badge(...)`
|
||||
|
||||
Compile it with:
|
||||
|
||||
```bash
|
||||
npx pug-cli priv/ui/pug-demo/index.pug --pretty --out priv/ui/pug-demo
|
||||
```
|
||||
|
||||
That writes `priv/ui/pug-demo/index.html`.
|
||||
8
priv/ui/pug-demo/_mixins.pug
Normal file
8
priv/ui/pug-demo/_mixins.pug
Normal file
@@ -0,0 +1,8 @@
|
||||
mixin badge(label, tone)
|
||||
span.badge(class=`badge--${tone}`)= label
|
||||
|
||||
mixin featureCard(feature)
|
||||
li.feature-card
|
||||
h3 #{feature.name}
|
||||
p.muted= feature.description
|
||||
+badge(feature.statusLabel, feature.status)
|
||||
12
priv/ui/pug-demo/_summary.pug
Normal file
12
priv/ui/pug-demo/_summary.pug
Normal file
@@ -0,0 +1,12 @@
|
||||
section.panel
|
||||
h2 Included Summary
|
||||
p
|
||||
| This section comes from
|
||||
code _summary.pug
|
||||
| . It can still read variables declared in
|
||||
code index.pug
|
||||
| , including
|
||||
strong #{name}
|
||||
| and the feature count:
|
||||
strong #{features.length}
|
||||
| .
|
||||
149
priv/ui/pug-demo/index.html
Normal file
149
priv/ui/pug-demo/index.html
Normal file
@@ -0,0 +1,149 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Pug Features Demo</title>
|
||||
<style>
|
||||
:root {
|
||||
color-scheme: light;
|
||||
--ink: #202124;
|
||||
--muted: #5f6368;
|
||||
--line: #dadce0;
|
||||
--paper: #ffffff;
|
||||
--soft: #f7f8fa;
|
||||
--accent: #0b57d0;
|
||||
--accent-soft: #e8f0fe;
|
||||
--good: #137333;
|
||||
--warn: #b06000;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background: var(--soft);
|
||||
color: var(--ink);
|
||||
font: 15px/1.5 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
}
|
||||
|
||||
main {
|
||||
width: min(960px, calc(100% - 32px));
|
||||
margin: 32px auto;
|
||||
}
|
||||
|
||||
header {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
h1, h2, h3, p { margin-top: 0; }
|
||||
h1 { font-size: 32px; line-height: 1.1; }
|
||||
h2 { font-size: 20px; margin-bottom: 12px; }
|
||||
h3 { font-size: 16px; margin-bottom: 6px; }
|
||||
|
||||
.muted { color: var(--muted); }
|
||||
|
||||
.panel, .feature-card {
|
||||
background: var(--paper);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.panel {
|
||||
padding: 18px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.feature-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
gap: 12px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.feature-card p { margin-bottom: 10px; }
|
||||
|
||||
.badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 24px;
|
||||
padding: 2px 8px;
|
||||
border-radius: 999px;
|
||||
background: var(--accent-soft);
|
||||
color: var(--accent);
|
||||
font-size: 12px;
|
||||
font-weight: 650;
|
||||
}
|
||||
|
||||
.badge--ready {
|
||||
background: #e6f4ea;
|
||||
color: var(--good);
|
||||
}
|
||||
|
||||
.badge--practice {
|
||||
background: #fef7e0;
|
||||
color: var(--warn);
|
||||
}
|
||||
|
||||
code {
|
||||
background: #eef0f3;
|
||||
border-radius: 4px;
|
||||
padding: 1px 5px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<header>
|
||||
<h1>Pug features for Ada Lovelace</h1>
|
||||
<p class="muted">This page is rendered from <code>index.pug</code> and extends <code>layout.pug</code>.</p>
|
||||
</header>
|
||||
<section class="panel">
|
||||
<h2>Interpolation</h2>
|
||||
<p>Hello, Ada Lovelace. Your current plan is PRO.</p>
|
||||
<p>The literal syntax is <code>#{name}</code>, which inserts escaped text into a line.</p>
|
||||
</section>
|
||||
<section class="panel">
|
||||
<h2>Conditionals</h2>
|
||||
<p>Welcome back, Ada Lovelace.</p>
|
||||
<p>You are using the pro plan, so all examples are visible.</p>
|
||||
</section>
|
||||
<section class="panel">
|
||||
<h2>Loops and Mixins</h2>
|
||||
<ul class="feature-grid">
|
||||
<li class="feature-card">
|
||||
<h3>Interpolation</h3>
|
||||
<p class="muted">Drop values into text with #{name} and escaped output.</p><span class="badge badge--ready">ready</span>
|
||||
</li>
|
||||
<li class="feature-card">
|
||||
<h3>Conditionals</h3>
|
||||
<p class="muted">Render different branches with if, else if, else, and case.</p><span class="badge badge--ready">ready</span>
|
||||
</li>
|
||||
<li class="feature-card">
|
||||
<h3>Loops</h3>
|
||||
<p class="muted">Repeat markup with each item in collection syntax.</p><span class="badge badge--ready">ready</span>
|
||||
</li>
|
||||
<li class="feature-card">
|
||||
<h3>Includes and extends</h3>
|
||||
<p class="muted">Compose pages from layouts and smaller partial files.</p><span class="badge badge--practice">practice</span>
|
||||
</li>
|
||||
<li class="feature-card">
|
||||
<h3>Mixins</h3>
|
||||
<p class="muted">Create reusable snippets that accept arguments.</p><span class="badge badge--ready">ready</span>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section class="panel">
|
||||
<h2>Included Summary</h2>
|
||||
<p>This section comes from <code>_summary.pug</code>. It can still read variables declared in <code>index.pug</code>, including <strong>Ada Lovelace</strong> and the feature count: <strong>5</strong>.</p>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
80
priv/ui/pug-demo/index.pug
Normal file
80
priv/ui/pug-demo/index.pug
Normal file
@@ -0,0 +1,80 @@
|
||||
extends ./layout.pug
|
||||
include ./_mixins.pug
|
||||
|
||||
block content
|
||||
-
|
||||
const name = "Ada Lovelace";
|
||||
const signedIn = true;
|
||||
const plan = "pro";
|
||||
const features = [
|
||||
{
|
||||
name: "Interpolation",
|
||||
description: "Drop values into text with #{name} and escaped output.",
|
||||
status: "ready",
|
||||
statusLabel: "ready"
|
||||
},
|
||||
{
|
||||
name: "Conditionals",
|
||||
description: "Render different branches with if, else if, else, and case.",
|
||||
status: "ready",
|
||||
statusLabel: "ready"
|
||||
},
|
||||
{
|
||||
name: "Loops",
|
||||
description: "Repeat markup with each item in collection syntax.",
|
||||
status: "ready",
|
||||
statusLabel: "ready"
|
||||
},
|
||||
{
|
||||
name: "Includes and extends",
|
||||
description: "Compose pages from layouts and smaller partial files.",
|
||||
status: "practice",
|
||||
statusLabel: "practice"
|
||||
},
|
||||
{
|
||||
name: "Mixins",
|
||||
description: "Create reusable snippets that accept arguments.",
|
||||
status: "ready",
|
||||
statusLabel: "ready"
|
||||
}
|
||||
];
|
||||
|
||||
header
|
||||
h1 Pug features for #{name}
|
||||
p.muted
|
||||
| This page is rendered from
|
||||
code index.pug
|
||||
| and extends
|
||||
code layout.pug
|
||||
| .
|
||||
|
||||
section.panel
|
||||
h2 Interpolation
|
||||
p Hello, #{name}. Your current plan is #{plan.toUpperCase()}.
|
||||
p
|
||||
| The literal syntax is
|
||||
code #{'#{name}'}
|
||||
| , which inserts escaped text into a line.
|
||||
|
||||
section.panel
|
||||
h2 Conditionals
|
||||
if signedIn
|
||||
p Welcome back, #{name}.
|
||||
else
|
||||
p Please sign in to see the demo.
|
||||
|
||||
case plan
|
||||
when "free"
|
||||
p You are using the free plan.
|
||||
when "pro"
|
||||
p You are using the pro plan, so all examples are visible.
|
||||
default
|
||||
p Your plan is #{plan}.
|
||||
|
||||
section.panel
|
||||
h2 Loops and Mixins
|
||||
ul.feature-grid
|
||||
each feature in features
|
||||
+featureCard(feature)
|
||||
|
||||
include ./_summary.pug
|
||||
102
priv/ui/pug-demo/layout.pug
Normal file
102
priv/ui/pug-demo/layout.pug
Normal file
@@ -0,0 +1,102 @@
|
||||
doctype html
|
||||
html(lang="en")
|
||||
head
|
||||
meta(charset="utf-8")
|
||||
meta(name="viewport", content="width=device-width, initial-scale=1")
|
||||
title Pug Features Demo
|
||||
style.
|
||||
:root {
|
||||
color-scheme: light;
|
||||
--ink: #202124;
|
||||
--muted: #5f6368;
|
||||
--line: #dadce0;
|
||||
--paper: #ffffff;
|
||||
--soft: #f7f8fa;
|
||||
--accent: #0b57d0;
|
||||
--accent-soft: #e8f0fe;
|
||||
--good: #137333;
|
||||
--warn: #b06000;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background: var(--soft);
|
||||
color: var(--ink);
|
||||
font: 15px/1.5 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
}
|
||||
|
||||
main {
|
||||
width: min(960px, calc(100% - 32px));
|
||||
margin: 32px auto;
|
||||
}
|
||||
|
||||
header {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
h1, h2, h3, p { margin-top: 0; }
|
||||
h1 { font-size: 32px; line-height: 1.1; }
|
||||
h2 { font-size: 20px; margin-bottom: 12px; }
|
||||
h3 { font-size: 16px; margin-bottom: 6px; }
|
||||
|
||||
.muted { color: var(--muted); }
|
||||
|
||||
.panel, .feature-card {
|
||||
background: var(--paper);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.panel {
|
||||
padding: 18px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.feature-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
gap: 12px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.feature-card p { margin-bottom: 10px; }
|
||||
|
||||
.badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 24px;
|
||||
padding: 2px 8px;
|
||||
border-radius: 999px;
|
||||
background: var(--accent-soft);
|
||||
color: var(--accent);
|
||||
font-size: 12px;
|
||||
font-weight: 650;
|
||||
}
|
||||
|
||||
.badge--ready {
|
||||
background: #e6f4ea;
|
||||
color: var(--good);
|
||||
}
|
||||
|
||||
.badge--practice {
|
||||
background: #fef7e0;
|
||||
color: var(--warn);
|
||||
}
|
||||
|
||||
code {
|
||||
background: #eef0f3;
|
||||
border-radius: 4px;
|
||||
padding: 1px 5px;
|
||||
}
|
||||
|
||||
body
|
||||
main
|
||||
block content
|
||||
Reference in New Issue
Block a user