Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
3 changes: 2 additions & 1 deletion packages/web/src/lib/marketing/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export type Integration = {
categoryLabel: string;
tag?: string;
platform?: string;
version?: string;
cta: 'install' | 'docs';
color?: string;
fg?: string;
Expand Down Expand Up @@ -106,7 +107,7 @@ export const integrationCategories: IntegrationCategory[] = [
items: [
{
id: 'vscode',
name: 'Visual Studio Code',
name: 'VS Code',
desc: 'Marketplace extension.',
href: marketingLinks.vscode,
platform: 'VS Code, Cursor',
Expand Down
69 changes: 69 additions & 0 deletions packages/web/src/lib/marketing/versions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { writable } from 'svelte/store';

export const liveVersions = writable<Record<string, string>>({
firefox: '',
js: '',
rust: '',
vscode: '',
});

export async function loadLiveVersions() {
// 1. Firefox Addon
try {
Comment thread
elijah-potter marked this conversation as resolved.
Outdated
const ver = (
await (
await fetch(
'https://addons.mozilla.org/api/v5/addons/addon/private-grammar-checker-harper/',
)
).json()
).current_version.version;
liveVersions.update((v) => ({ ...v, firefox: ver }));
} catch {}

// 2. JS Package
try {
const ver = (await (await fetch('https://registry.npmjs.org/harper.js')).json())['dist-tags']
.latest;
liveVersions.update((v) => ({ ...v, js: ver }));
} catch {}

// 3. Rust Crate
try {
const lines = (await (await fetch('https://index.crates.io/ha/rp/harper-core')).text()).split(
'\n',
);
liveVersions.update((v) => ({ ...v, rust: JSON.parse(lines[lines.length - 2]).vers }));
} catch {}

// 4. VS Code Extension
try {
const res = await fetch(
'https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json;api-version=3.0-preview.1',
},
body: JSON.stringify({
filters: [
{
criteria: [
{ filterType: 8, value: 'Microsoft.VisualStudio.Code' },
{ filterType: 7, value: 'elijah-potter.harper' },
],
pageNumber: 1,
pageSize: 1,
sortBy: 0,
sortOrder: 0,
},
],
assetTypes: [],
flags: 194,
}),
},
);
const ver = (await res.json()).results[0].extensions[0].versions[0].version;
liveVersions.update((v) => ({ ...v, vscode: ver }));
} catch {}
}
21 changes: 19 additions & 2 deletions packages/web/src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import PrivacySpeedCards from '$lib/marketing/PrivacySpeedCards.svelte';
import { featuredIntegrationIds, integrations, marketingLinks } from '$lib/marketing/data';
import { LazyEditor } from 'harper-editor';
import type { Linter } from 'harper.js';
import { loadLiveVersions, liveVersions } from '$lib/marketing/versions';
import { onMount } from 'svelte';
import demoText from '../../../../demo.md?raw';

Expand Down Expand Up @@ -141,10 +142,17 @@ const faqs = [
},
];

let liveFxVer = '';
let liveJsVer = '';
let liveRustVer = '';
let liveVscodeVer = '';

onMount(() => {
void (async () => {
linter = await createEditorLinter();
})();

void loadLiveVersions();
});

</script>
Expand Down Expand Up @@ -246,8 +254,17 @@ onMount(() => {
>
<IntegrationTile {integration} size={32} />
<span class="flex min-w-0 flex-col">
<strong class="overflow-hidden text-ellipsis whitespace-nowrap text-[0.84rem]">{integration.name}</strong>
<small class="overflow-hidden text-ellipsis whitespace-nowrap text-[0.72rem] text-[#807a6e] dark:text-white/55">{integration.desc}</small>
<div class="flex items-center gap-1.5 overflow-hidden">
<strong class="overflow-hidden text-ellipsis whitespace-nowrap text-[0.84rem]">{integration.name}</strong>
{#if $liveVersions[integration.id]}
<span class="inline-flex items-center rounded-full bg-[#f4f1ea] dark:bg-white/10 px-1.5 py-0.5 text-[0.65rem] font-mono font-medium text-[#6b6455] dark:text-white/80 border border-[#e4dfd3] dark:border-white/10 select-none">
v{$liveVersions[integration.id]}
</span>
{/if}
Comment on lines +263 to +273
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It would be nice to have a small bit of hover text (which you can simply do with the title attribute) that explains why we are showing a version number there.

Something like, "This version is slightly behind the core engine due to a delay".

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Ah I was wondering about something like that, sounds like a way to handle it.
Do you think I should also add the current version? We don't already display it anywhere. I'm not sure where it would look the best either.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Sure!

</div>
<small class="overflow-hidden text-ellipsis whitespace-nowrap text-[0.72rem] text-[#807a6e] dark:text-white/55">
{integration.desc}
</small>
</span>
</a>
{/if}
Expand Down
46 changes: 39 additions & 7 deletions packages/web/src/routes/get/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script lang="ts">
import { onMount } from 'svelte';
import {
type Integration,
integrationCategories,
Expand All @@ -8,10 +9,15 @@ import {
import IntegrationTile from '$lib/marketing/IntegrationTile.svelte';
import MarketingFooter from '$lib/marketing/MarketingFooter.svelte';
import MarketingHeader from '$lib/marketing/MarketingHeader.svelte';
import { liveVersions, loadLiveVersions } from '$lib/marketing/versions';

let activeCategory = 'all';
let query = '';

onMount(() => {
void loadLiveVersions();
});

$: filtered = integrations.filter((integration) => {
if (activeCategory === 'community' && !integration.community) {
return false;
Expand Down Expand Up @@ -77,8 +83,21 @@ function clearFilters() {
>
<IntegrationTile {integration} size={40} />
<span class="flex min-w-0 flex-col">
<strong class="text-[0.94rem] leading-[1.25]">{integration.name}</strong>
<small class="overflow-hidden text-ellipsis whitespace-nowrap text-[0.8rem] leading-[1.4] text-[#807a6e] dark:text-white/55">{integration.desc}</small>
<div class="flex items-center gap-1.5">
<strong class="text-[0.94rem] leading-[1.25]">{integration.name}</strong>
{#if $liveVersions[integration.id]}
<span class="inline-flex items-center rounded-full bg-[#f4f1ea] dark:bg-white/10 px-1.5 py-0.5 text-[0.68rem] font-mono font-medium text-[#6b6455] dark:text-white/80 border border-[#e4dfd3] dark:border-white/10 select-none">
{$liveVersions[integration.id]}
</span>
{:else if $liveVersions[integration.name]}
<span class="inline-flex items-center rounded-full bg-[#f4f1ea] dark:bg-white/10 px-1.5 py-0.5 text-[0.68rem] font-mono font-medium text-[#6b6455] dark:text-white/80 border border-[#e4dfd3] dark:border-white/10 select-none">
{$liveVersions[integration.name]}
</span>
{/if}
</div>
<small class="overflow-hidden text-ellipsis whitespace-nowrap text-[0.8rem] leading-[1.4] text-[#807a6e] dark:text-white/55">
{integration.desc}
</small>
</span>
<em class="whitespace-nowrap text-[0.78rem] font-extrabold text-[#b06a1b] not-italic dark:text-primary-300">{ctaLabel(integration)} →</em>
</a>
Expand Down Expand Up @@ -168,12 +187,25 @@ function clearFilters() {
class="grid grid-cols-[2.5rem_1fr_auto] items-center gap-[0.9rem] rounded-xl border-[0.5px] border-[rgba(28,26,22,0.1)] bg-white px-[1.1rem] py-[0.9rem] !text-[#1c1a16] no-underline transition-[transform,box-shadow,border-color] duration-150 hover:-translate-y-px hover:border-[#b06a1b] hover:shadow-[0_10px_24px_-16px_rgba(28,26,22,0.16)] hover:no-underline dark:border-white/10 dark:bg-white/5 dark:!text-white dark:hover:border-primary-300 max-[640px]:grid-cols-[2.5rem_1fr] [&_em]:max-[640px]:col-start-2"
href={integration.href}
>
<IntegrationTile {integration} size={40} />
<span class="flex min-w-0 flex-col">
<IntegrationTile {integration} size={40} />
<span class="flex min-w-0 flex-col">
<div class="flex items-center gap-1.5">
<strong class="text-[0.94rem] leading-[1.25]">{integration.name}</strong>
<small class="overflow-hidden text-ellipsis whitespace-nowrap text-[0.8rem] leading-[1.4] text-[#807a6e] dark:text-white/55">{integration.platform}</small>
</span>
<em class="whitespace-nowrap text-[0.78rem] font-extrabold text-[#b06a1b] not-italic dark:text-primary-300">{ctaLabel(integration)} →</em>
{#if $liveVersions[integration.id]}
<span class="inline-flex items-center rounded-full bg-[#f4f1ea] dark:bg-white/10 px-1.5 py-0.5 text-[0.68rem] font-mono font-medium text-[#6b6455] dark:text-white/80 border border-[#e4dfd3] dark:border-white/10 select-none">
{$liveVersions[integration.id]}
</span>
{:else if $liveVersions[integration.name]}
<span class="inline-flex items-center rounded-full bg-[#f4f1ea] dark:bg-white/10 px-1.5 py-0.5 text-[0.68rem] font-mono font-medium text-[#6b6455] dark:text-white/80 border border-[#e4dfd3] dark:border-white/10 select-none">
{$liveVersions[integration.name]}
</span>
{/if}
</div>
<small class="overflow-hidden text-ellipsis whitespace-nowrap text-[0.8rem] leading-[1.4] text-[#807a6e] dark:text-white/55">
{integration.platform}
</small>
</span>
<em class="whitespace-nowrap text-[0.78rem] font-extrabold text-[#b06a1b] not-italic dark:text-primary-300">{ctaLabel(integration)} →</em>
</a>
{/each}
{/if}
Expand Down
Loading