Commit
This commit is contained in:
1 parent
9e6804c1ab
commit
a59be0fc9c
10 files changed
+47
-41
No files matched your search
@@ -22,6 +22,14 @@ bun run preview # serve dist/
|
|||||||
| Theme tokens | top of `src/styles/global.css` |
|
| Theme tokens | top of `src/styles/global.css` |
|
||||||
| Pages | `src/pages/` |
|
| Pages | `src/pages/` |
|
||||||
|
|
||||||
|
### Direct downloads
|
||||||
|
|
||||||
|
Every download button links straight to the file (`platforms.linux.url` in `src/config.ts`), with no
|
||||||
|
intermediate page. Only visitors on Windows, macOS or a phone are sent to `/download/`, because the
|
||||||
|
Linux AppImage is no use to them yet. Point `url` at any direct file URL. By default it is the GitHub
|
||||||
|
Releases asset, which is a plain download link. Don't host the 157 MB file with the site itself on
|
||||||
|
GitHub Pages (100 MB per-file limit) or Cloudflare Pages (25 MB); use Releases, R2/S3 or a CDN.
|
||||||
|
|
||||||
### Releasing a new version
|
### Releasing a new version
|
||||||
|
|
||||||
1. Build the app (`bun run dist` in the Ink repo) and upload the AppImage to your release page.
|
1. Build the app (`bun run dist` in the Ink repo) and upload the AppImage to your release page.
|
||||||
|
|||||||
@@ -1,17 +1,21 @@
|
|||||||
---
|
---
|
||||||
|
// A direct download: the href is the file itself, in the HTML, so it works without JS and never
|
||||||
|
// bounces through another page. Only visitors on Windows, macOS or a phone (detected in
|
||||||
|
// scripts/site.ts) are sent to /download/ instead, because the Linux AppImage is no use to them yet.
|
||||||
import { config, formatSize } from '../config';
|
import { config, formatSize } from '../config';
|
||||||
import { href } from '../lib/url';
|
import { href } from '../lib/url';
|
||||||
|
|
||||||
interface Props { variant?: 'primary' | 'default'; note?: boolean; center?: boolean }
|
interface Props { variant?: 'primary' | 'default'; note?: boolean; center?: boolean }
|
||||||
const { variant = 'primary', note = true, center = false } = Astro.props;
|
const { variant = 'primary', note = true, center = false } = Astro.props;
|
||||||
const linux = config.platforms.linux;
|
const linux = config.platforms.linux;
|
||||||
|
const meta = `v${config.version} · ${linux.format} · ${formatSize(linux.bytes)}`;
|
||||||
---
|
---
|
||||||
<div class:list={['dl', { center }]} data-download data-linux-url={linux.url} data-linux-meta={`v${config.version} · ${linux.format} · ${formatSize(linux.bytes)}`}>
|
<div class:list={['dl', { center }]} data-download data-meta={meta}>
|
||||||
<a class:list={['btn', variant]} href={href('/download/')} data-download-btn>
|
<a class:list={['btn', variant]} href={linux.url} download={linux.file} data-dl-link data-info={href('/download/')}>
|
||||||
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 4v11m0 0l-4.5-4.5M12 15l4.5-4.5M5 19h14" /></svg>
|
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 4v11m0 0l-4.5-4.5M12 15l4.5-4.5M5 19h14" /></svg>
|
||||||
<span data-download-label>Download Ink</span>
|
<span data-download-label>Download for Linux</span>
|
||||||
</a>
|
</a>
|
||||||
{note && <p class="muted" data-download-note>Linux AppImage available · Windows & macOS coming soon</p>}
|
{note && <p class="muted" data-download-note>{meta} · Windows & macOS coming soon</p>}
|
||||||
</div>
|
</div>
|
||||||
<style>
|
<style>
|
||||||
.dl { display: grid; gap: 0.7rem; justify-items: start; }
|
.dl { display: grid; gap: 0.7rem; justify-items: start; }
|
||||||
@@ -19,29 +23,3 @@ const linux = config.platforms.linux;
|
|||||||
p { font-size: 0.88rem; }
|
p { font-size: 0.88rem; }
|
||||||
.dl.center { justify-items: center; text-align: center; }
|
.dl.center { justify-items: center; text-align: center; }
|
||||||
</style>
|
</style>
|
||||||
<script>
|
|
||||||
// Progressive enhancement: without JS the button goes to /download/ and lists every platform.
|
|
||||||
import { detectOS } from '../lib/os';
|
|
||||||
const os = detectOS();
|
|
||||||
|
|
||||||
document.querySelectorAll<HTMLElement>('[data-download]').forEach((box) => {
|
|
||||||
const btn = box.querySelector<HTMLAnchorElement>('[data-download-btn]');
|
|
||||||
const label = box.querySelector<HTMLElement>('[data-download-label]');
|
|
||||||
const note = box.querySelector<HTMLElement>('[data-download-note]');
|
|
||||||
if (!btn || !label) return;
|
|
||||||
if (os === 'linux') {
|
|
||||||
label.textContent = 'Download for Linux';
|
|
||||||
btn.href = box.dataset.linuxUrl || btn.href;
|
|
||||||
if (note) note.textContent = box.dataset.linuxMeta ?? '';
|
|
||||||
} else if (os === 'windows') {
|
|
||||||
label.textContent = 'Download options';
|
|
||||||
if (note) note.textContent = 'The Windows version is not ready yet. The Linux AppImage is available now.';
|
|
||||||
} else if (os === 'macos') {
|
|
||||||
label.textContent = 'Download options';
|
|
||||||
if (note) note.textContent = 'The macOS version is not ready yet. The Linux AppImage is available now.';
|
|
||||||
} else if (os === 'mobile') {
|
|
||||||
label.textContent = 'Download options';
|
|
||||||
if (note) note.textContent = 'Ink is a desktop app. Open this page on your computer to download it.';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@@ -15,7 +15,7 @@ import { href } from '../lib/url';
|
|||||||
<a href={href('/download/')}>Download</a>
|
<a href={href('/download/')}>Download</a>
|
||||||
<a href={href('/changelog/')}>Changelog</a>
|
<a href={href('/changelog/')}>Changelog</a>
|
||||||
<a href={href('/docs/')}>Docs & FAQ</a>
|
<a href={href('/docs/')}>Docs & FAQ</a>
|
||||||
<a href={config.repo} rel="noopener">Source & issues</a>
|
<a href={config.releases} rel="noopener">Releases</a>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
---
|
---
|
||||||
import Wordmark from './Wordmark.astro';
|
import Wordmark from './Wordmark.astro';
|
||||||
import { href } from '../lib/url';
|
import { href } from '../lib/url';
|
||||||
|
import { config, formatSize } from '../config';
|
||||||
|
|
||||||
const { current = '' } = Astro.props as { current?: string };
|
const { current = '' } = Astro.props as { current?: string };
|
||||||
const links = [
|
const links = [
|
||||||
@@ -24,7 +25,7 @@ const links = [
|
|||||||
<span class="s-label">Search</span>
|
<span class="s-label">Search</span>
|
||||||
<span class="s-keys" aria-hidden="true"><kbd data-mod>Ctrl</kbd><kbd>K</kbd></span>
|
<span class="s-keys" aria-hidden="true"><kbd data-mod>Ctrl</kbd><kbd>K</kbd></span>
|
||||||
</button>
|
</button>
|
||||||
<a class="get" href={href('/download/')}>Get Ink</a>
|
<a class="get" href={config.platforms.linux.url} download={config.platforms.linux.file} data-dl-link data-info={href('/download/')} title={`Ink ${config.version} for Linux · ${config.platforms.linux.format} · ${formatSize(config.platforms.linux.bytes)}`}>Get Ink</a>
|
||||||
<button type="button" class="menu" aria-expanded="false" aria-controls="site-nav" data-menu>
|
<button type="button" class="menu" aria-expanded="false" aria-controls="site-nav" data-menu>
|
||||||
<span class="sr-only">Menu</span>
|
<span class="sr-only">Menu</span>
|
||||||
<svg viewBox="0 0 24 24" aria-hidden="true"><path class="l1" d="M5 9h14" /><path class="l2" d="M5 15h14" /></svg>
|
<svg viewBox="0 0 24 24" aria-hidden="true"><path class="l1" d="M5 9h14" /><path class="l2" d="M5 15h14" /></svg>
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ const items: Item[] = [
|
|||||||
{ group: 'Page', label: 'Docs & FAQ', url: href('/docs/'), keys: 'help questions' },
|
{ group: 'Page', label: 'Docs & FAQ', url: href('/docs/'), keys: 'help questions' },
|
||||||
{ group: 'Action', label: `Download Ink ${config.version} for Linux`, url: config.platforms.linux.url, keys: 'appimage linux get' },
|
{ group: 'Action', label: `Download Ink ${config.version} for Linux`, url: config.platforms.linux.url, keys: 'appimage linux get' },
|
||||||
{ group: 'Action', label: 'Verify the download (SHA-256)', url: href('/download/#verify'), keys: 'checksum sha256 hash' },
|
{ group: 'Action', label: 'Verify the download (SHA-256)', url: href('/download/#verify'), keys: 'checksum sha256 hash' },
|
||||||
{ group: 'Action', label: 'Report a bug or request a feature', url: config.issues, keys: 'issue github' },
|
|
||||||
{ group: 'Features', label: 'Writing: block editor', url: href('/features/#writing'), keys: 'slash menu markdown code math katex mermaid callout table' },
|
{ group: 'Features', label: 'Writing: block editor', url: href('/features/#writing'), keys: 'slash menu markdown code math katex mermaid callout table' },
|
||||||
{ group: 'Features', label: 'Linking: wiki links, embeds, backlinks', url: href('/features/#linking'), keys: '[[ ]] link rename' },
|
{ group: 'Features', label: 'Linking: wiki links, embeds, backlinks', url: href('/features/#linking'), keys: '[[ ]] link rename' },
|
||||||
{ group: 'Features', label: 'Canvas', url: href('/features/#canvas'), keys: 'json canvas arrows groups export png svg pdf' },
|
{ group: 'Features', label: 'Canvas', url: href('/features/#canvas'), keys: 'json canvas arrows groups export png svg pdf' },
|
||||||
|
|||||||
+4
-2
@@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
const version = '0.1.0';
|
const version = '0.1.0';
|
||||||
|
|
||||||
/** TODO: set to the real repository once it is public. Release links derive from it. */
|
/**
|
||||||
|
* TODO: set to the real repository once it is public. The download links below derive from it and are
|
||||||
|
* used as direct links by every download button. Replace `url` with any direct file URL if you host it elsewhere.
|
||||||
|
*/
|
||||||
const repo = 'https://github.com/OWNER/ink';
|
const repo = 'https://github.com/OWNER/ink';
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
@@ -14,7 +17,6 @@ export const config = {
|
|||||||
version,
|
version,
|
||||||
releaseDate: '2026-10-11',
|
releaseDate: '2026-10-11',
|
||||||
repo,
|
repo,
|
||||||
issues: `${repo}/issues`,
|
|
||||||
releases: `${repo}/releases`,
|
releases: `${repo}/releases`,
|
||||||
license: 'TODO',
|
license: 'TODO',
|
||||||
platforms: {
|
platforms: {
|
||||||
|
|||||||
+3
-1
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
import Base from '../layouts/Base.astro';
|
import Base from '../layouts/Base.astro';
|
||||||
|
import DownloadButton from '../components/DownloadButton.astro';
|
||||||
import { href } from '../lib/url';
|
import { href } from '../lib/url';
|
||||||
---
|
---
|
||||||
<Base title="Page not found" noindex description="This page does not exist.">
|
<Base title="Page not found" noindex description="This page does not exist.">
|
||||||
@@ -7,7 +8,8 @@ import { href } from '../lib/url';
|
|||||||
<p class="eyebrow">404</p>
|
<p class="eyebrow">404</p>
|
||||||
<h1>This page is blank.</h1>
|
<h1>This page is blank.</h1>
|
||||||
<p class="lede">The page you were after is not here. It may have moved, or the link may be mistyped.</p>
|
<p class="lede">The page you were after is not here. It may have moved, or the link may be mistyped.</p>
|
||||||
<p class="links"><a class="btn primary" href={href('/')}>Back to home</a><a class="btn" href={href('/download/')}>Download</a></p>
|
<p class="links"><a class="btn primary" href={href('/')}>Back to home</a></p>
|
||||||
|
<DownloadButton variant="default" note={false} />
|
||||||
</section>
|
</section>
|
||||||
</Base>
|
</Base>
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
import Base from '../layouts/Base.astro';
|
import Base from '../layouts/Base.astro';
|
||||||
import { config } from '../config';
|
|
||||||
import { href } from '../lib/url';
|
import { href } from '../lib/url';
|
||||||
|
|
||||||
const shortcuts: [string, string][] = [
|
const shortcuts: [string, string][] = [
|
||||||
@@ -91,8 +90,6 @@ const shortcuts: [string, string][] = [
|
|||||||
<p>Code-signing certificates cost money and effort that a small project has not spent yet. Use the checksum on the download page to verify your file.</p>
|
<p>Code-signing certificates cost money and effort that a small project has not spent yet. Use the checksum on the download page to verify your file.</p>
|
||||||
<h3>Can I export my notes?</h3>
|
<h3>Can I export my notes?</h3>
|
||||||
<p>They are already Markdown files. You can also export a page to Markdown, HTML or PDF, and a canvas to PNG, SVG or PDF.</p>
|
<p>They are already Markdown files. You can also export a page to Markdown, HTML or PDF, and a canvas to PNG, SVG or PDF.</p>
|
||||||
<h3>How do I report a bug or ask for something?</h3>
|
|
||||||
<p>Open an issue on the <a href={config.issues} rel="noopener">issue tracker</a>.</p>
|
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</Base>
|
</Base>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ const soon: PlatformId[] = ['windows', 'macos'];
|
|||||||
<h2>Linux</h2>
|
<h2>Linux</h2>
|
||||||
<p class="meta">{linux.format} · {linux.arch} · {formatSize(linux.bytes)} · v{config.version}</p>
|
<p class="meta">{linux.format} · {linux.arch} · {formatSize(linux.bytes)} · v{config.version}</p>
|
||||||
<p>A single file. No install step, no root needed.</p>
|
<p>A single file. No install step, no root needed.</p>
|
||||||
<a class="btn primary" href={linux.url}>
|
<a class="btn primary" href={linux.url} download={linux.file}>
|
||||||
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 4v11m0 0l-4.5-4.5M12 15l4.5-4.5M5 19h14" /></svg>
|
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 4v11m0 0l-4.5-4.5M12 15l4.5-4.5M5 19h14" /></svg>
|
||||||
Download AppImage
|
Download AppImage
|
||||||
</a>
|
</a>
|
||||||
@@ -49,7 +49,7 @@ const soon: PlatformId[] = ['windows', 'macos'];
|
|||||||
<h2 id={`${id}-h`}>{p[id].label}</h2>
|
<h2 id={`${id}-h`}>{p[id].label}</h2>
|
||||||
<p class="meta">{p[id].format}</p>
|
<p class="meta">{p[id].format}</p>
|
||||||
<p>Not built or tested yet. There is no download to offer, so there is no link here.</p>
|
<p>Not built or tested yet. There is no download to offer, so there is no link here.</p>
|
||||||
<p><a href={config.issues} rel="noopener">Watch the issue tracker</a> for news. No sign-up, nothing collected.</p>
|
<p>News will show up in the <a href={href('/changelog/')}>changelog</a>. No sign-up, nothing collected.</p>
|
||||||
</article>
|
</article>
|
||||||
))}
|
))}
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// Small, site-wide enhancements. Every page reads fine without them.
|
// Small, site-wide enhancements. Every page reads fine without them.
|
||||||
|
|
||||||
|
import { detectOS } from '../lib/os';
|
||||||
|
|
||||||
const reduce = matchMedia('(prefers-reduced-motion: reduce)');
|
const reduce = matchMedia('(prefers-reduced-motion: reduce)');
|
||||||
const finePointer = matchMedia('(hover: hover) and (pointer: fine)');
|
const finePointer = matchMedia('(hover: hover) and (pointer: fine)');
|
||||||
|
|
||||||
@@ -80,3 +82,20 @@ document.querySelectorAll<HTMLPreElement>('pre[data-copy], .prose pre').forEach(
|
|||||||
if (/mac|iphone|ipad/i.test(navigator.platform || navigator.userAgent)) {
|
if (/mac|iphone|ipad/i.test(navigator.platform || navigator.userAgent)) {
|
||||||
document.querySelectorAll('[data-mod]').forEach((k) => (k.textContent = '⌘'));
|
document.querySelectorAll('[data-mod]').forEach((k) => (k.textContent = '⌘'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Download links are direct file links in the HTML. Visitors on Windows, macOS or a phone can't use the
|
||||||
|
Linux AppImage yet, so for them (and only them) the same buttons point at the page that explains why. */
|
||||||
|
const os = detectOS();
|
||||||
|
if (os === 'windows' || os === 'macos' || os === 'mobile') {
|
||||||
|
document.querySelectorAll<HTMLAnchorElement>('[data-dl-link]').forEach((a) => {
|
||||||
|
if (a.dataset.info) a.href = a.dataset.info;
|
||||||
|
a.removeAttribute('download');
|
||||||
|
});
|
||||||
|
const what = { windows: 'The Windows version is not ready yet.', macos: 'The macOS version is not ready yet.', mobile: 'Ink is a desktop app. Open this page on your computer to download it.' }[os];
|
||||||
|
document.querySelectorAll<HTMLElement>('[data-download]').forEach((box) => {
|
||||||
|
const label = box.querySelector<HTMLElement>('[data-download-label]');
|
||||||
|
const note = box.querySelector<HTMLElement>('[data-download-note]');
|
||||||
|
if (label) label.textContent = 'Download options';
|
||||||
|
if (note) note.textContent = `${what} The Linux AppImage is available now.`;
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in new issue
Block a user