From b8d8ff624855c94b79e1f58291318bae3bda8135 Mon Sep 17 00:00:00 2001 From: Igor Kamyshev Date: Wed, 17 Apr 2024 15:13:48 +0700 Subject: [PATCH] Fix changelogs --- apps/website/changelog/cli.mjs | 143 +--------- apps/website/changelog/lib.mjs | 40 --- apps/website/changelog/lib.test.js | 246 ------------------ .../docs/.vitepress/sidebar_creator.mjs | 2 +- package.json | 2 - pnpm-lock.yaml | 74 ------ 6 files changed, 8 insertions(+), 499 deletions(-) delete mode 100644 apps/website/changelog/lib.mjs delete mode 100644 apps/website/changelog/lib.test.js diff --git a/apps/website/changelog/cli.mjs b/apps/website/changelog/cli.mjs index 1c28e9ee..79391ca8 100644 --- a/apps/website/changelog/cli.mjs +++ b/apps/website/changelog/cli.mjs @@ -2,13 +2,8 @@ import glob from 'glob'; import { readFile, writeFile } from 'node:fs/promises'; import { promisify } from 'node:util'; import { markdown } from 'markdown'; -import { format } from 'prettier'; -import { NodeHtmlMarkdown } from 'node-html-markdown'; -import { parseSemVer, compareSemVer } from 'semver-parser'; import { resolve } from 'node:path'; -import { excludeTrashUpdates, groupByVersions } from './lib.mjs'; - const files = await promisify(glob)( '../../{packages,deleted_packages}/*/CHANGELOG.md', { @@ -24,142 +19,18 @@ const changelogs = await Promise.all( ) ); -for (const [release, changelog] of mergeChangelogs(changelogs).entries()) { - const md = await renderChangelog(changelog); - - const releaseFile = release.replaceAll('.', '-'); - const filePath = resolve('docs/releases', `${releaseFile}.changelog.md`); +for (const { name, content } of changelogs) { + const filePath = resolve('docs', name, 'CHANGELOG.md'); - await writeFile(filePath, md); + await writeFile(filePath, content); } // --- // --- -async function renderChangelog(tree) { - return makeLinksOnCommits( - await format( - NodeHtmlMarkdown.translate( - markdown.renderJsonML(markdown.toHTMLTree(tree)) - ), - { - parser: 'markdown', - } - ) - ); -} - -function mergeChangelogs(packages) { - const releases = new Set( - Object.values(packages) - .flatMap(({ changes }) => Object.keys(changes)) - .map(getRelease) - ); - - const log = new Map(); - - for (const release of releases) { - const currentLog = [[]]; - - const relatedChanges = packages - .map(({ name, changes }) => ({ - name, - changes: Object.fromEntries( - Object.entries(changes).filter( - ([version]) => getRelease(version) === release - ) - ), - })) - .filter(({ changes }) => Object.keys(changes).length > 0); - - currentLog.push(['header', { level: 2 }, 'Full changelog']); - for (const { version, packages } of groupByVersions(relatedChanges).sort( - ({ version: v1 }, { version: v2 }) => -compareSemVer(v1, v2) - )) { - const logForVersion = []; - for (const { name: packageName, changes: packageChanges } of packages) { - const pacakgeChangesEntries = Object.entries(packageChanges) - .map(([type, items]) => [type, excludeTrashUpdates(items)]) - .filter(([, items]) => items.length > 0); - - let hasChanges = pacakgeChangesEntries.length > 0; - - if (!hasChanges) { - continue; - } - - logForVersion.push(['para', `::: details ${packageName}`]); - - for (const [type, items] of pacakgeChangesEntries) { - logForVersion.push(['para', ['strong', type]], ...items); - } - - logForVersion.push(['para', ':::']); - } - - if (logForVersion.length > 0) { - currentLog.push(['header', { level: 3 }, version]); - currentLog.push(...logForVersion); - } - } - - log.set(release, currentLog); - } - - return log; -} - -async function parseChangelog(md) { - const [_1, header, ...rest] = markdown.parse(md); +async function parseChangelog(content) { + const [_1, header] = markdown.parse(content); - const name = header.at(2); - - const versions = groupByLevel(2, rest); - - const changes = {}; - for (const [version, content] of Object.entries(versions)) { - changes[version] = groupByLevel(3, content); - } - - return { name, changes }; -} - -function groupByLevel(targetLevel, data) { - const groups = {}; - - let currentGroup; - for (const item of data) { - const { level } = item.at(1); - - if (level === targetLevel) { - const group = item.at(2); - currentGroup = group; - } else { - if (!groups[currentGroup]) { - continue; - } - groups[currentGroup].push(item); - } - } - - return groups; -} - -function getRelease(version) { - const { major, minor } = parseSemVer(version); - - return `${major}.${minor}`; -} - -function makeLinksOnCommits(content) { - function linkToCommit(commitHash) { - return `[${commitHash}](https://github.com/igorkamyshev/farfetched/commit/${commitHash})`; - } - - function replacer(all, commitHash) { - return all.replace(commitHash, linkToCommit(commitHash)); - } + const name = header.at(2).replace('@withease/', ''); - return content - .replaceAll(/- ([0-9a-f]{7}):/gi, replacer) - .replaceAll(/\\\[([0-9a-f]{7})\\\]/gi, replacer); + return { name, content }; } diff --git a/apps/website/changelog/lib.mjs b/apps/website/changelog/lib.mjs deleted file mode 100644 index f7b64123..00000000 --- a/apps/website/changelog/lib.mjs +++ /dev/null @@ -1,40 +0,0 @@ -export function groupByVersions(packages) { - const groupedByVersions = []; - - for (const { name, changes } of packages) { - for (const [version, versionChanges] of Object.entries(changes)) { - const versionGroup = groupedByVersions.find( - (group) => group.version === version - ); - - if (versionGroup) { - versionGroup.packages.push({ name, changes: versionChanges }); - } else { - groupedByVersions.push({ - version, - packages: [{ name, changes: versionChanges }], - }); - } - } - } - - return groupedByVersions; -} - -export function excludeTrashUpdates(items) { - return items - .map((tags) => { - const [header, ...body] = tags; - - const filteredBody = body.filter( - (item) => !item.at(1).toLowerCase().includes('updated dependencies') - ); - - if (filteredBody.length === 0) { - return null; - } - - return [header, ...filteredBody]; - }) - .filter(Boolean); -} diff --git a/apps/website/changelog/lib.test.js b/apps/website/changelog/lib.test.js deleted file mode 100644 index 577fe4fc..00000000 --- a/apps/website/changelog/lib.test.js +++ /dev/null @@ -1,246 +0,0 @@ -import { describe, test, expect } from 'vitest'; - -import { groupByVersions, excludeTrashUpdates } from './lib.mjs'; - -describe('groupByVersion', () => { - test('correct grouping', () => { - const changes = [ - { - name: '@farfetched/core', - changes: { - '0.6.4': { - 'Patch Changes': [ - [ - 'bulletlist', - [ - 'listitem', - '5da04bf: Fix type inference in ', - ['inlinecode', 'createQuery'], - ' in ', - ['inlinecode', 'effect'], - ' and ', - ['inlinecode', 'mapData'], - ' overload', - ], - ], - ], - }, - '0.6.3': {}, - '0.6.2': { - 'Patch Changes': [ - [ - 'bulletlist', - [ - 'listitem', - '05b4860: Fix ', - ['inlinecode', 'cache'], - ' invalidation after ', - ['inlinecode', 'update'], - ], - ], - ], - }, - '0.6.1': { - 'Patch Changes': [ - [ - 'bulletlist', - [ - 'listitem', - 'c2b67a6: Fix ', - ['inlinecode', 'cache'], - ' overlapping in ', - ['inlinecode', 'createJsonQuery'], - ], - ], - ], - }, - }, - }, - { - name: '@farfetched/solid', - changes: { - '0.6.4': {}, - '0.6.3': { - 'Patch Changes': [ - [ - 'bulletlist', - [ - 'listitem', - '0a45391: Re-trigger resource after ', - ['inlinecode', 'update'], - ' a ', - ['em', 'Query'], - ], - ], - ], - }, - '0.6.2': {}, - '0.6.1': {}, - }, - }, - ]; - - const result = groupByVersions(changes); - - expect(result).toEqual([ - { - version: '0.6.4', - packages: [ - { - name: '@farfetched/core', - changes: { - 'Patch Changes': [ - [ - 'bulletlist', - [ - 'listitem', - '5da04bf: Fix type inference in ', - ['inlinecode', 'createQuery'], - ' in ', - ['inlinecode', 'effect'], - ' and ', - ['inlinecode', 'mapData'], - ' overload', - ], - ], - ], - }, - }, - { - name: '@farfetched/solid', - changes: {}, - }, - ], - }, - { - version: '0.6.3', - packages: [ - { - name: '@farfetched/core', - changes: {}, - }, - { - name: '@farfetched/solid', - changes: { - 'Patch Changes': [ - [ - 'bulletlist', - [ - 'listitem', - '0a45391: Re-trigger resource after ', - ['inlinecode', 'update'], - ' a ', - ['em', 'Query'], - ], - ], - ], - }, - }, - ], - }, - { - version: '0.6.2', - packages: [ - { - name: '@farfetched/core', - changes: { - 'Patch Changes': [ - [ - 'bulletlist', - [ - 'listitem', - '05b4860: Fix ', - ['inlinecode', 'cache'], - ' invalidation after ', - ['inlinecode', 'update'], - ], - ], - ], - }, - }, - { - name: '@farfetched/solid', - changes: {}, - }, - ], - }, - { - version: '0.6.1', - packages: [ - { - name: '@farfetched/core', - changes: { - 'Patch Changes': [ - [ - 'bulletlist', - [ - 'listitem', - 'c2b67a6: Fix ', - ['inlinecode', 'cache'], - ' overlapping in ', - ['inlinecode', 'createJsonQuery'], - ], - ], - ], - }, - }, - { - name: '@farfetched/solid', - changes: {}, - }, - ], - }, - ]); - }); -}); - -describe('excludeTrashUpdates', () => { - test('delete trash updates from the list', () => { - const trashUpdates = [ - [ - 'bulletlist', - ['listitem', '896e27d: Update build tool-chain'], - ['listitem', 'Updated dependencies ', [Array]], - ['listitem', 'Updated dependencies ', [Array]], - ['listitem', 'Updated dependencies ', [Array]], - ['listitem', 'Updated dependencies ', [Array]], - ['listitem', 'Updated dependencies ', [Array]], - ['listitem', 'Updated dependencies ', [Array]], - ['listitem', 'Updated dependencies ', [Array]], - ['listitem', 'Updated dependencies ', [Array]], - ['listitem', 'Updated dependencies ', [Array], [Array]], - ], - ]; - - expect(excludeTrashUpdates(trashUpdates)).toMatchInlineSnapshot(` - [ - [ - "bulletlist", - [ - "listitem", - "896e27d: Update build tool-chain", - ], - ], - ] - `); - }); - - test('delete the whole list in case of only updated deps', () => { - const trashUpdates = [ - [ - 'bulletlist', - ['listitem', 'Updated dependencies ', [Array]], - ['listitem', 'Updated dependencies ', [Array]], - ['listitem', 'Updated dependencies ', [Array]], - ['listitem', 'Updated dependencies ', [Array]], - ['listitem', 'Updated dependencies ', [Array]], - ['listitem', 'Updated dependencies ', [Array]], - ['listitem', 'Updated dependencies ', [Array]], - ['listitem', 'Updated dependencies ', [Array]], - ['listitem', 'Updated dependencies ', [Array], [Array]], - ], - ]; - - expect(excludeTrashUpdates(trashUpdates)).toMatchInlineSnapshot(`[]`); - }); -}); diff --git a/apps/website/docs/.vitepress/sidebar_creator.mjs b/apps/website/docs/.vitepress/sidebar_creator.mjs index 17758181..9580b5a6 100644 --- a/apps/website/docs/.vitepress/sidebar_creator.mjs +++ b/apps/website/docs/.vitepress/sidebar_creator.mjs @@ -5,7 +5,7 @@ export function createSidebar(packageName, sidebar) { text: packageName, items: [ ...sidebar, - { text: 'Changelog', link: `/${packageName}/CHANGELOG.md` }, + { text: 'Changelog', link: `/${packageName}/CHANGELOG` }, ], }, ], diff --git a/package.json b/package.json index 16fe222b..f16943a6 100644 --- a/package.json +++ b/package.json @@ -21,14 +21,12 @@ "glob": "^8.0.3", "i18next": "23.0.0", "markdown": "^0.5.0", - "node-html-markdown": "^1.2.0", "playwright": "^1.32.2", "prettier": "^2.6.2", "publint": "^0.2.7", "redux": "^5.0.0", "redux-saga": "^1.2.3", "runtypes": "^6.7.0", - "semver-parser": "^4.0.1", "size-limit": "^7.0.8", "typescript": "5.1.6", "vite": "4.4.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0445d662..04b25111 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,7 +19,6 @@ importers: glob: ^8.0.3 i18next: 23.0.0 markdown: ^0.5.0 - node-html-markdown: ^1.2.0 playwright: ^1.32.2 prettier: ^2.6.2 publint: ^0.2.7 @@ -27,7 +26,6 @@ importers: redux-saga: ^1.2.3 runtypes: ^6.7.0 sandpack-vue3: ^3.1.7 - semver-parser: ^4.0.1 size-limit: ^7.0.8 typescript: 5.1.6 vite: 4.4.9 @@ -54,14 +52,12 @@ importers: glob: 8.1.0 i18next: 23.0.0 markdown: 0.5.0 - node-html-markdown: 1.3.0 playwright: 1.32.2 prettier: 2.7.1 publint: 0.2.7 redux: 5.0.0 redux-saga: 1.2.3 runtypes: 6.7.0 - semver-parser: 4.0.1 size-limit: 7.0.8 typescript: 5.1.6 vite: 4.4.9_@types+node@20.12.7 @@ -2035,10 +2031,6 @@ packages: engines: {node: '>=8'} dev: true - /boolbase/1.0.0: - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - dev: true - /brace-expansion/1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: @@ -2302,21 +2294,6 @@ packages: which: 2.0.2 dev: true - /css-select/5.1.0: - resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} - dependencies: - boolbase: 1.0.0 - css-what: 6.1.0 - domhandler: 5.0.3 - domutils: 3.1.0 - nth-check: 2.1.1 - dev: true - - /css-what/6.1.0: - resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} - engines: {node: '>= 6'} - dev: true - /csstype/3.1.2: resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} @@ -2423,33 +2400,6 @@ packages: path-type: 4.0.0 dev: true - /dom-serializer/2.0.0: - resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - entities: 4.5.0 - dev: true - - /domelementtype/2.3.0: - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - dev: true - - /domhandler/5.0.3: - resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} - engines: {node: '>= 4'} - dependencies: - domelementtype: 2.3.0 - dev: true - - /domutils/3.1.0: - resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} - dependencies: - dom-serializer: 2.0.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - dev: true - /dotenv/16.3.1: resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} engines: {node: '>=12'} @@ -3599,20 +3549,6 @@ packages: skin-tone: 2.0.0 dev: true - /node-html-markdown/1.3.0: - resolution: {integrity: sha512-OeFi3QwC/cPjvVKZ114tzzu+YoR+v9UXW5RwSXGUqGb0qCl0DvP406tzdL7SFn8pZrMyzXoisfG2zcuF9+zw4g==} - engines: {node: '>=10.0.0'} - dependencies: - node-html-parser: 6.1.13 - dev: true - - /node-html-parser/6.1.13: - resolution: {integrity: sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==} - dependencies: - css-select: 5.1.0 - he: 1.2.0 - dev: true - /nopt/2.1.2: resolution: {integrity: sha512-x8vXm7BZ2jE1Txrxh/hO74HTuYZQEbo8edoRcANgdZ4+PCV+pbjd/xdummkmjjC7LU5EjPzlu8zEq/oxWylnKA==} hasBin: true @@ -3664,12 +3600,6 @@ packages: path-key: 4.0.0 dev: true - /nth-check/2.1.1: - resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - dependencies: - boolbase: 1.0.0 - dev: true - /object-inspect/1.12.2: resolution: {integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==} dev: true @@ -4160,10 +4090,6 @@ packages: resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==} dev: true - /semver-parser/4.0.1: - resolution: {integrity: sha512-ZdnhLJSeLkc9fXEwqdvVXqrVJ8jq/vhGlFfsMhOE4oIiSZlvUC6Ar4NAbdj+H5DEkhFjyhucce7BO8VL/rpY9g==} - dev: true - /semver/5.7.1: resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} hasBin: true