Skip to content

Increasing popularity / download counts #56

Description

@karlhorky

Hi @dnut, thanks again for taking over this initiative to reboot @stkb's original (and unmaintained) Rewrap VS Code extension, looks like with 52k total downloads (estimated 3.4k/mo in Jul 2026), Rewrap Revived is gaining a bit on the original Rewrap with 891k total downloads (estimated 18.2k/mo in Jul 2026).

Image

Source: Internet Archive Wayback Machine snapshots

vscode-marketplace-install-history.ts

const extensions = process.argv.slice(2);

if (extensions.length === 0) {
  console.error(
    'Usage: node vscode-marketplace-install-history.mts <extension...>',
  );
  process.exit(1);
}

console.log('extension,captured_at,installs');

for (const extension of extensions) {
  const marketplaceUrl =
    `https://marketplace.visualstudio.com/items?itemName=${extension}`;

  console.error(`Finding Wayback captures for ${extension}...`);

  const cdxUrl = new URL('https://web.archive.org/cdx/search/cdx');
  cdxUrl.searchParams.set('url', marketplaceUrl);
  cdxUrl.searchParams.set('from', '202412');
  cdxUrl.searchParams.set('output', 'json');
  cdxUrl.searchParams.set('filter', 'statuscode:200');
  cdxUrl.searchParams.set('fl', 'timestamp');

  const cdxResponse = await fetch(cdxUrl);
  const captures = (await cdxResponse.json()) as string[][];

  for (const [timestamp] of captures.slice(1)) {
    console.error(`${extension} ${timestamp}`);

    const snapshotUrl =
      `https://web.archive.org/web/${timestamp}id_/${marketplaceUrl}`;

    let html = '';

    for (let attempt = 1; attempt <= 5; attempt++) {
      try {
        const response = await fetch(snapshotUrl);

        if (!response.ok) {
          throw new Error(`${response.status} ${response.statusText}`);
        }

        html = await response.text();
        break;
      } catch (error) {
        console.error(`  attempt ${attempt} failed: ${error}`);

        if (attempt < 5) {
          await new Promise((resolve) => setTimeout(resolve, 5000));
        }
      }
    }

    const text = html
      .replaceAll('&nbsp;', ' ')
      .replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, ' ')
      .replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, ' ')
      .replace(/<[^>]+>/g, ' ')
      .replace(/\s+/g, ' ');

    const match = text.match(
      /\|\s*([0-9][0-9,]*)\s+installs?\s*\|/i,
    );

    const installs = match?.[1].replaceAll(',', '') ?? '';

    const capturedAt =
      `${timestamp.slice(0, 4)}-${timestamp.slice(4, 6)}-${timestamp.slice(6, 8)}` +
      `T${timestamp.slice(8, 10)}:${timestamp.slice(10, 12)}:${timestamp.slice(12, 14)}Z`;

    console.log(`${extension},${capturedAt},${installs}`);

    // Avoid hammering the Internet Archive.
    await new Promise((resolve) => setTimeout(resolve, 2000));
  }

  console.error(`Fetching current count for ${extension}...`);

  const response = await fetch(marketplaceUrl);
  const html = await response.text();

  const text = html
    .replaceAll('&nbsp;', ' ')
    .replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, ' ')
    .replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, ' ')
    .replace(/<[^>]+>/g, ' ')
    .replace(/\s+/g, ' ');

  const match = text.match(
    /\|\s*([0-9][0-9,]*)\s+installs?\s*\|/i,
  );

  const installs = match?.[1].replaceAll(',', '') ?? '';

  console.log(`${extension},${new Date().toISOString()},${installs}`);
}

Usage:

node vscode-marketplace-install-history.ts stkb.rewrap dnut.rewrap-revived > installs.csv

Output (installs.csv):

extension,captured_at,installs
stkb.rewrap,2024-12-04T03:29:38Z,550569
stkb.rewrap,2024-12-21T20:52:36Z,557849
stkb.rewrap,2025-01-14T15:34:07Z,563637
stkb.rewrap,2025-02-01T04:35:13Z,570107
stkb.rewrap,2025-02-07T21:15:06Z,572487
stkb.rewrap,2025-02-13T12:43:51Z,574506
stkb.rewrap,2025-03-08T09:59:23Z,582969
stkb.rewrap,2025-03-20T03:08:44Z,587038
stkb.rewrap,2025-04-01T00:34:06Z,591332
stkb.rewrap,2025-04-05T23:14:49Z,593231
stkb.rewrap,2025-04-22T21:28:13Z,599288
stkb.rewrap,2025-04-24T18:07:21Z,600176
stkb.rewrap,2025-04-29T04:24:54Z,601559
stkb.rewrap,2025-05-10T00:01:45Z,606221
stkb.rewrap,2025-05-15T17:05:29Z,609056
stkb.rewrap,2025-06-02T19:59:26Z,617653
stkb.rewrap,2025-08-06T14:12:15Z,643575
stkb.rewrap,2025-08-19T17:28:03Z,650190
stkb.rewrap,2025-10-10T18:25:22Z,681365
stkb.rewrap,2025-12-12T05:38:48Z,730487
stkb.rewrap,2025-12-15T13:47:46Z,732314
stkb.rewrap,2025-12-30T17:49:26Z,739665
stkb.rewrap,2026-01-18T19:49:34Z,750913
stkb.rewrap,2026-02-23T04:22:30Z,775946
stkb.rewrap,2026-03-10T09:02:38Z,787939
stkb.rewrap,2026-05-09T14:13:34Z,828109
stkb.rewrap,2026-05-21T13:58:13Z,835851
stkb.rewrap,2026-08-18T19:42:04Z,888368
stkb.rewrap,2026-08-25T10:28:41.245Z,891338
dnut.rewrap-revived,2025-01-14T17:12:35Z,741
dnut.rewrap-revived,2025-05-10T00:01:39Z,7939
dnut.rewrap-revived,2025-07-14T12:43:42Z,12353
dnut.rewrap-revived,2025-09-11T18:05:52Z,16728
dnut.rewrap-revived,2025-11-18T23:00:49Z,22785
dnut.rewrap-revived,2026-04-14T12:47:21Z,37438
dnut.rewrap-revived,2026-08-25T10:29:29.407Z,52049

Some things that would help:

  1. marketing of Rewrap Revived
    1. maybe also renaming / rebranding of this repo to be clear that it's a separate, new project
  2. if the original was unpublished or marked as unmaintained / deprecated
  3. further features only available in Rewrap Revived such as a CLI or a Prettier plugin

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions