Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/main.less
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@
@import 'less/api.less';
@import 'less/variables.less';
@import 'less/todo.less';
@import 'less/search.less';

@import 'less/octicons/octicons.less';
40 changes: 40 additions & 0 deletions eleventy.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const path = require('path');

const pulsarApi = require("./pulsar-api/src/index.js");
const hovercardResolution = require("./hovercard_resolution/index.js");
const syntaxHighlight = require("@11ty/eleventy-plugin-syntaxhighlight");
Expand All @@ -7,13 +9,51 @@ const PRISM_LANGUAGE_SCM = require('./plugins/prism-language-scm');

module.exports = (eleventyConfig) => {

// `pagefind` is ESM, so has to be `import`ed rather than `require`d. Can't
// use `await` at the top level or in this function (not until we upgrade to
// 11ty v3) so we'll do it later.
const pagefindImport = import('pagefind');

eleventyConfig.setServerOptions({
// Prevent the server from trying to do a clever hot-reload when only
// Markdown is changed. We have JavaScript code that needs to react to
// changed content, so it’s better to reload the page instead.
domDiff: false
});

// Regenerate the search index after changes.
eleventyConfig.on("eleventy.after", async ({ dir }) => {
// Now we can `await` the import we couldn't above.
let pagefind = await pagefindImport;

const { index } = await pagefind.createIndex({
excludeSelectors: [
".sidebar",
".page_header",
".page_footer",
".adjacent",
".platform-win",
".platform-mac"
],
verbose: process.env.DEBUG
});

await index.addDirectory({
path: dir.output,
// This dumb glob allows us to exclude all of `api` except for the one set
// of API docs we care about (the latest). This works fine as long as `api`
// is the only section that starts with A.
//
// (Pagefind uses Wax, a Rust glob library whose negation syntax is not
// very robust.)
glob: "{*.html,[b-z]*/**/*.html,api/pulsar/latest/**/*.html}"
});

await index.writeFiles({
outputPath: path.join(dir.output, 'pagefind')
});
});

eleventyConfig.addPlugin(syntaxHighlight, {
init({ Prism }) {
Prism.languages.scm = PRISM_LANGUAGE_SCM;
Expand Down
9 changes: 6 additions & 3 deletions layouts/api/page.ejs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<!-- Pulsar API Documentation Page -->
<%- include("header", { title: content.customData?.name ?? title }) %>

<%
let pageTitle = (content.customData?.name ?? title);
let fullPageTitle = `${pageTitle} — Pulsar API documentation v${locals.version}`;
let searchTitle = `${pageTitle} (API documentation)`;
%>
<%- include("header", { title: fullPageTitle, searchTitle }) %>
<body>
<%- include("page_header", { platform_switcher: false }) %>
<div class="content">
Expand All @@ -18,7 +22,6 @@
-%>
<main class="container">
<section class="header">
<% let pageTitle = (content.customData?.name ?? title) %>
<h1 class="title" id="title"><%= pageTitle %></h1>
</section>

Expand Down
2 changes: 1 addition & 1 deletion layouts/api/summary.ejs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!-- Pulsar API Documentation Summary Page -->
<%- include("header") %>
<%- include("header", { title: `Pulsar documentation v${title}` }) %>

<body>
<%- include("page_header", { platform_switcher: false }) %>
Expand Down
22 changes: 22 additions & 0 deletions layouts/header.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" id="meta-scheme" content="">
<meta property="og:title" content="<%= locals.title %>">
<% if (locals.searchTitle) { %>
<meta name="search-title" data-pagefind-meta="title[content]" content="<%= locals.searchTitle %>">
<% } %>
<link rel="shortcut icon" type="image/svg+xml" href="/static/favicon.svg">
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
<link rel="apple-touch-icon" type="image/svg+xml" href="/static/favicon.svg">
Expand All @@ -30,6 +33,25 @@
document.documentElement.dataset.theme = theme;
}
</script>
<link href="/pagefind/pagefind-component-ui.css" rel="stylesheet">
<script src="/pagefind/pagefind-component-ui.js" type="module"></script>

<script type="module">
await import('/pagefind/pagefind-highlight.js');
new PagefindHighlight({
markContext: "main",
highlightParam: "highlight",
addStyles: false
});

{
let match = document.querySelector('mark.pagefind-highlight');
if (match) {
match.scrollIntoView();
match.classList.add('pagefind-highlight-animate');
}
}
</script>

<link rel="stylesheet" href="/main.css" />

Expand Down
82 changes: 81 additions & 1 deletion layouts/page_header.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,91 @@
<a class="page-header__link" href="/api/pulsar">
<span>Pulsar API</span>
</a>
<a class="page-header__link" href="https://api.pulsar-edit.dev/swagger-ui/">
<a class="page-header__link page-header__link--registry" href="https://api.pulsar-edit.dev/swagger-ui/">
<span>Package Registry API</span>
</a>
<a class="page-header__link" href="https://pulsar-edit.dev">
<span>Homepage</span>
</a>
</nav>

<style>
pagefind-modal-body:has(.pf-result) .pf-skeleton-text {
display: none !important;
}
p.pf-skeleton-text {
font-size: 25px !important;
text-align: center !important;
color: var(--pf-text-muted) !important;
font-family: var(--pf-font) !important;
font-weight: 600 !important;
}
</style>

<nav class="page-header__search">
<pagefind-config
highlight-param="highlight"
excerpt-length="60"
></pagefind-config>

<pagefind-modal-trigger class="page-header__search-trigger--full"></pagefind-modal-trigger>
<pagefind-modal-trigger class="page-header__search-trigger--compact" compact hide-shortcut></pagefind-modal-trigger>

<pagefind-modal>
<pagefind-modal-header>
<pagefind-input></pagefind-input>
</pagefind-modal-header>
<pagefind-modal-body>
<pagefind-summary></pagefind-summary>
<pagefind-results hide-sub-results>
<script type="text/pagefind-template">
<li class="pf-result">
<div class="pf-result-card">
{{#if and(options.show_images, meta.image)}}
<img class="pf-result-image" src="{{ meta.image | resolveUrl(meta.url | default(url)) }}" alt="{{ meta.image_alt | default(meta.title) }}">
{{/if}}
<div class="pf-result-content">
<p class="pf-result-title">
<a class="pf-result-link" href="{{ meta.url | default(url) | safeUrl }}"{{#if options.link_target}} target="{{ options.link_target }}"{{/if}}{{#if eq(options.link_target, "_blank")}} rel="noopener"{{/if}}>{{ meta.title }}</a>
</p>
{{#if excerpt}}
<p class="pf-result-excerpt">{{+ excerpt +}}</p>
{{/if}}
</div>
</div>
{{#if sub_results}}
<ul class="pf-heading-chips">
{{#each sub_results as sub}}
<li class="pf-heading-chip">
<a class="pf-heading-link" href="{{ sub.url | safeUrl }}"{{#if options.link_target}} target="{{ options.link_target }}"{{/if}}{{#if eq(options.link_target, "_blank")}} rel="noopener"{{/if}}>{{ sub.title }}</a>
<p class="pf-heading-excerpt">{{+ sub.excerpt +}}</p>
</li>
{{/each}}
</ul>
{{/if}}
</li>
</script>

<script type="text/pagefind-template" data-template="placeholder">
<li class="pf-result" aria-hidden="true">
<div class="pf-result-card">
<div class="pf-skeleton pf-skeleton-image"></div>
<div class="pf-result-content">
<p class="pf-result-title pf-skeleton pf-skeleton-title">Type a search term</p>
<p class="pf-result-excerpt pf-skeleton pf-skeleton-excerpt"></p>
</div>
</div>
</li>
</script>

</pagefind-results>
</pagefind-modal-body>
<pagefind-modal-footer>
<pagefind-keyboard-hints></pagefind-keyboard-hints>
</pagefind-modal-footer>
</pagefind-modal>
</nav>

<nav class="page-header__actions">
<div class="theme-switcher-menu">
<button type="button" id="theme-switcher">
Expand All @@ -30,8 +107,11 @@
</svg>
</button>
</div>

</nav>
</div>


</header>

<% if (platform_switcher) { -%>
Expand Down
32 changes: 31 additions & 1 deletion less/page-header.less
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ html {
width: 100%;
}

.page-header__search {
position: relative;
top: 4px;
}

.page-header__link {
.border-hover-effect();
flex-direction: row;
Expand Down Expand Up @@ -155,4 +160,29 @@ html {
display: block !important;
}
}
}
}

@media (max-width: (@bp-larger-than-phablet - 1px)) {
.page-header .page-header__link--registry {
display: none;
}
}

// Show the compact search widget…
.page-header__search-trigger--full {
display: none;
}
.page-header__search-trigger--compact {
display: inline-block;
}


// …but swap in the bigger one when we have the room.
@media(min-width: @bp-larger-than-tablet) {
.page-header__search-trigger--full {
display: inline-block;
}
.page-header__search-trigger--compact {
display: none;
}
}
111 changes: 111 additions & 0 deletions less/search.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
:root {
/* Colors */
--pf-text: var(--font-color);
--pf-text-secondary: var(--font-color-subtle);
--pf-text-muted: var(--link-color-subtle);
--pf-background: var(--body-color);
--pf-border: var(--btn-border);
--pf-border-focus: var(--kbd-border);
--pf-skeleton: var(--body-color);
--pf-skeleton-shine: var(--table-border);
--pf-hover: var(--btn-bg-hover);
--pf-mark: var(--btn-color-focus);
--pf-scroll-shadow: rgba(0, 0, 0, 0.08);

/* Shadows */
--pf-shadow-sm: 0 2px 8px var(--_pf-shadow-color-sm);
--pf-shadow-md: 0 4px 12px var(--_pf-shadow-color-med);
--pf-shadow-lg: 0 16px 48px var(--_pf-shadow-color-lg);

/* Error states */
--pf-error-bg: var(--alert-bg-danger);
--pf-error-border: var(--alert-border-danger);
--pf-error-text: var(--alert-color-title-danger);
--pf-error-text-secondary: var(--alert-color-danger);

/* Focus ring */
--pf-outline-focus: var(--input-field-border-focus);
--pf-outline-width: 2px;
--pf-outline-offset: 2px;

/* Typography */
--pf-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

/* Sizing */
--pf-input-height: 36px;
--pf-input-font-size: 16px; /* Keep at 16px+ to prevent iOS auto-zoom on focus */
--pf-summary-font-size: 12px;
--pf-result-title-font-size: 14px;
--pf-result-excerpt-font-size: 13px;

/* Results layout */
--pf-results-display: flex;
--pf-results-flex-direction: column;
--pf-results-flex-wrap: nowrap;
--pf-results-columns: none; /* grid-template-columns value, used when display is grid */
--pf-results-gap: 8px;

--pf-border-radius: 6px;
--pf-image-width: 64px;
--pf-image-height: 48px;

/* Icons (SVG data URIs) */
// --pf-icon-search: url("data:image/svg+xml,...");
// --pf-icon-arrow: url("data:image/svg+xml,...");

/* Modal */
--pf-modal-backdrop: rgba(0, 0, 0, 0.5);
--pf-modal-max-width: 720px;
--pf-modal-max-height: min(80dvh, 800px);
--pf-modal-top: 10dvh;

/* Searchbox dimensions */
--pf-searchbox-max-width: 480px;
--pf-searchbox-dropdown-max-height: 320px;

/* Dropdown settings */
--pf-dropdown-max-height: 280px;
--pf-dropdown-z-index: 9999;
}

mark.pagefind-highlight {
display: inline-block;
background-color: var(--alert-bg-warning);
color: var(--alert-color-warning);
outline: 1px solid color-mix(in srgb, var(--alert-border-warning) 50%, transparent);
border-radius: 2px;
}

.pf-result-link {
color: var(--link-color) !important;
}

// Style the trigger keys (which should be `kbd` elements!) like our `kbd`
// elements.
.pf-trigger-key {
padding: 0.125rem 0.5rem;
border: 1.5px solid var(--kbd-border, var(--btn-border)) !important;
border-radius: 3px !important;
box-shadow: 0px 1.5px 0px var(--kbd-border, var(--btn-border)) !important;
}

.pagefind-highlight-animate {
animation: pagefind-highlight-animation;
animation-iteration-count: 1;
animation-duration: 0.6s;
animation-timing-function: ease-in-out;
}

@keyframes pagefind-highlight-animation {
0% {
transform: scale(1);
}

50% {
transform: scale(1.2);
}

100% {
transform: scale(1);
}
}
Loading