Skip to content

feat: allow serving documentation site on a subpath #173

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Oct 31, 2023
Merged

Conversation

fvsch
Copy link
Contributor

@fvsch fvsch commented Oct 30, 2023

This PR fixes issues with our documentation theme and config so that we can build the docs site and serve it as a subfolder of another website (for example on a /docs/ subpath).

VitePress has a built-in feature for this: the base option. That option handles a few things for us:

  • The base URL is prepended to menu and sidebar links, so a sidebar link's URLs can be defined as /guides/integration/open-from-github and will get completed to /docs/guides/integration/open-from-github (when base: '/docs/').
  • URLs in Markdown are also handled automatically, so a link like [some page](/guides/integration/open-from-github) will get a correct link.
  • Frontend assets handled by Vite will work out of the box.

We're still running into a few issues because we have some hardcoded URLs in our styles and Vue components.

Fixing URLs in components

We can use the withBase utility function provided by VitePress:

<a :href="withBase(url)">…</a>

This works well when the url value is either:

  1. an absolute path starting with /, such as '/guides/integration/open-from-github';
  2. an absolute URL with its own protocol and origin, such as 'https://stackblitz.com/enterprise' (in that case the URL is not modified by withBase).

Fixing links to assets (icons, images, fonts)

We were using hardcoded URLs to assets, oftentimes in CSS:

@font-face {
  /* … */
  src: url('/fonts/gilroy-medium.woff2') format('woff2');
}

This was linking absolutely to files placed in docs/public, which is a folder whose content gets copied as-is to the output folder (see related Vite docs).

If we want to serve the docs pages from a subpath, we would have to change those hardcoded paths to something else, for instance url('/docs/fonts/gilroy-medium.woff2').

Here the simpler solution is to have those assets be included in Vite's assets graph, by using relative imports to the asset, or the @theme/… import alias:

@font-face {
  /* … */
  /* fonts were moved to .vitepress/theme/fonts */
  src: url('@theme/fonts/gilroy-medium.woff2') format('woff2');
}

For images, including a few PNG backgrounds and a few SVG icons, I did something similar, and moved those files to:

.vitepress/
  theme/
    icons/
    img/

And referenced them in CSS as:

.card {
  background-image: url('@theme/img/link-bg-squares-dark.png');
}

or imported them in TypeScript or Vue components:

import bgDarkUrl from '@theme/img/link-bg-squares-dark.png';

The <SvgIcon /> component

One special case for assets loading was some icons served from /img/icons/some-icon.svg, and used in CSS as CSS Masks:

.icon {
  display: inline-block;
  width: 1em;
  height: 1em;
  background-color: currentColor;
  mask: url('/img/icons/some-icon.svg');
}

This pattern was used in a handful of places, often reusing the same handful of icons.

I created a new SvgIcon component to replace this duplicated usage, and made it accept a string that matches the file name (without extension) of a file in .vitepress/theme/fonts/*.svg.

We first import all icons (which is reasonable because we have a manually curated icon set):

const importedIconsUrls = import.meta.glob('./*.svg', {
  as: 'url',
  eager: true,
});

Which gives us an object that looks like a manifest of icon URLs:

{
  './fa-books-light.svg': '/assets/fa-books-light.1221b65c.svg',
  './fa-brackets-curly.svg': '/assets/fa-brackets-curly.3f29fd46.svg',
  // …
}

Thanks to that, we can call <SvgIcon icon="fa-brackets-curly" /> and the SvgIcon component will look up the image URL in that object.

If we don't love this implementation, we can change it to have the consumer of SvgIcon pass a full URL:

<script setup>
import SvgIcon from '@theme/components/Icons/SvgIcon.vue';
import thumbsUpIcon from '@theme/icons/fa-thumbs-up.svg';
</script>

<template>
  <SvgIcon :url={thumbsUpIcon} />
</template>

We'll just have to refactor the docs/links.ts file because it defines a few icons for some cards on the home page, and we can't use assets imports in that file currently because it's imported from .vitepress/config.ts, which is executed in a Node context, not in a Vite (bundler) context.

Either approach is fine with me. :)

@bolt-new-by-stackblitz
Copy link

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@stackblitz-staging
Copy link

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@netlify
Copy link

netlify bot commented Oct 30, 2023

Deploy Preview for stackblitz-docs ready!

Name Link
🔨 Latest commit 65a8617
🔍 Latest deploy log https://app.netlify.com/sites/stackblitz-docs/deploys/653ffff0f59a7f00081ffaad
😎 Deploy Preview https://deploy-preview-173--stackblitz-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@@ -23,14 +22,14 @@ defineProps<{ links: any[] }>();
gap: 24px;
list-style: none;

@media (min-width: $bp-medium) {
@media (min-width: 680px) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not directly required by this PR: I removed the .vitepress/theme/styles/vars.scss file which was defining a few breakpoint values because:

  • it defined 3 values and we are using more than that;
  • the same 3 values defined in Sass variables were also often hardcoded in other .scss files.

Using breakpoints defined in Sass variables was the exception and not the rule, so using hardcoded breakpoint values everywhere makes these styles more consistent and removes a layer of indirection.

Comment on lines +87 to +92
<div class="feedbackContainer">
<form name="webcontainer-api-doc-feedback" data-netlify="true" hidden>
<textarea name="feedback"></textarea>
<input name="wasHelpful" />
<input name="page" />
</form>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whitespace formatting by Prettier is confusing GitHub's diff view quite a bit here.

The only changes in this component are about SVG icons:

-      <span class="icon thumbsUp"></span>
+      <SvgIcon class="thumbsUp" icon="fa-thumbs-up" size="12px" />

And some removed CSS in the <style> tag below.

Comment on lines +16 to +23
export interface CardLink {
bgImg?: 'bolt' | 'squares' | 'steps';
description: string;
icon?: string;
large?: boolean;
title: string;
url: string;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This object is used to type some content in docs/links.ts, and is identical to the props for the CardLink.vue component, but in that component we cannot define the props like this:

import type { CardLink as CardLinkProps } from '@theme/data/types';

defineProps<CardLinkProps>();

Because it breaks the Vue SFC compiler. It's a known issue in Vue. You have to pass at least the prop keys literally:

defineProps<{
  bgImg?: 'bolt' | 'squares' | 'steps';
  description: string;
  icon?: string;
  large?: boolean;
  title: string;
  url: string;
}>();

And you can only used imported types for prop values.

So in our case, we end up with duplication.

Comment on lines -120 to +121
| <img alt="Edit in Web Publisher" src="/img/edit_in_web_publisher.svg" /> | <a href="/img/edit_in_web_publisher.svg" target="_blank">edit_in_web_publisher.svg</a> |
| <img alt="Edit in Web Publisher" src="/img/edit_in_web_publisher_small.svg" /> | <a href="/img/edit_in_web_publisher_small.svg" target="_blank">edit_in_web_publisher_small.svg</a> |
| <img alt="Edit in Web Publisher" src="https://developer.stackblitz.com/img/edit_in_web_publisher.svg" /> | <a href="https://developer.stackblitz.com/img/edit_in_web_publisher.svg" target="_blank">edit_in_web_publisher.svg</a> |
| <img alt="Edit in Web Publisher" src="https://developer.stackblitz.com/img/edit_in_web_publisher_small.svg" /> | <a href="https://developer.stackblitz.com/img/edit_in_web_publisher_small.svg" target="_blank">edit_in_web_publisher_small.svg</a> |
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed links to our “Edit in …” button images to be absolute URLs, because we don't want those URLs to change if we set a base config value other than '/' in .vitepress/config.ts.

2. Retrieve the existing StackBlitz application certificate and key via `​kubectl get secret -o jsonpath={.data} stackblitz-tls-secret`
3. Create a new yaml file on the host VM called new-kotsadm-tls.yaml based on the template below:
```apiVersion: v1
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed a formatting issue: here the apiVersion part was understood as a language specifier, and not as the first line of the preformatted content.

Comment on lines -213 to +200
bgImgLight: '/img/theme/link-bg-bolt-light.jpg',
bgImgDark: '/img/theme/link-bg-bolt-dark.jpg',
bgImg: 'bolt',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Responsibility for finding the exact image URLs for the 'bolt' background is moved to the CardLink component.

@fvsch fvsch requested review from sulco, ykmsd and donmckenna October 30, 2023 19:22
Copy link
Contributor

@ykmsd ykmsd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, I like the proposed solution for SVG icon component, but I'm fine with both ways if somebody prefers the other way.

Also not related to this PR, but while I was testing it out, I realised the feedback component is broken and we haven't sent feedback for a while 😭 I will open a PR to fix it.

@fvsch fvsch merged commit 810a868 into main Oct 31, 2023
@fvsch fvsch deleted the fvsch/base-url branch October 31, 2023 10:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants