Skip to content
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

feat: API History #594

Merged
merged 66 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
14afa19
feat(api-history): basic webpack and remark plugin
piotrpdev Jun 1, 2024
9a5d259
feat(api-history): basic table
piotrpdev Jun 3, 2024
f1e9b09
feat(api-history): minor table styling
piotrpdev Jun 4, 2024
253d9c9
refactor(api-history): move regexp to variable
piotrpdev Jun 8, 2024
ae1e413
feat(api-history): better regexp
piotrpdev Jun 9, 2024
f687070
feat(api-history): move plugin to own file
piotrpdev Jun 18, 2024
2ab0e80
feat(api-history): remove `removed` property
piotrpdev Jun 18, 2024
1309387
feat(api-history): fetch version using pr
piotrpdev Jun 20, 2024
efdd84c
feat(api-history): types for data fetch code
piotrpdev Jun 20, 2024
92cc468
refactor(api-history): more readable row sorting
piotrpdev Jun 20, 2024
41c13b2
feat(api-history): changes markdown support
piotrpdev Jun 20, 2024
225a50c
feat(api-history): strip comment tags in pre-build instead of plugin
piotrpdev Jun 28, 2024
0382bc2
feat(api-history): `pr-release-versions-plugin`
piotrpdev Jun 28, 2024
2f74afe
feat(api-history): use react component instead of handmade AST
piotrpdev Jun 28, 2024
edb5a84
fix(api-history): revert accidental dependency
piotrpdev Jun 28, 2024
8397e97
refactor(api-history): get pr releases in transformer, remove plugin
piotrpdev Jun 28, 2024
0674b0e
docs(api-history): todo in transformer
piotrpdev Jul 2, 2024
e5345d6
docs(api-history): add temp example api history and schema for pr review
piotrpdev Jul 2, 2024
96d8046
fix(api-history): update `yarn.lock` for now
piotrpdev Jul 2, 2024
d0be11b
Merge remote-tracking branch 'origin/main' into feat/api-history
piotrpdev Jul 4, 2024
fd76258
feat(api-history): use example pr versions by default for now
piotrpdev Jul 4, 2024
d9e15cb
refactor(api-history): move `ApiHistoryTable` styles to module
piotrpdev Jul 5, 2024
c927a72
style(api-history): better var name, fix style lint
piotrpdev Jul 5, 2024
a5d30f1
feat(api-history): map pre-releases to released stable versions
piotrpdev Jul 5, 2024
6d2032c
feat(api-history): better styles, remove pr number
piotrpdev Jul 9, 2024
503b6e7
feat(api-history): link table change to breaking-changes
piotrpdev Jul 11, 2024
c65c39d
fix(api-history): provide key for table elements
piotrpdev Jul 11, 2024
6a72bea
feat(api-history): table semver ranges
piotrpdev Jul 11, 2024
394cc14
feat(api-history): better error handling
piotrpdev Jul 11, 2024
d563d0a
feat(api-history): type predicates in transformer
piotrpdev Jul 12, 2024
6454c48
feat(api-history): update to accepted schema
piotrpdev Jul 12, 2024
2503006
Merge remote-tracking branch 'origin/main' into feat/api-history
piotrpdev Jul 12, 2024
e2c16c5
docs(api-history): remove old comments
piotrpdev Jul 12, 2024
247b7d9
feat(api-history): only pre-process `/docs/api/*.md` containing `<!--`
piotrpdev Jul 15, 2024
dbe887c
Update scripts/tasks/preprocess-api-history.ts
piotrpdev Jul 15, 2024
acc8d21
fix(api-history): match api history block consistently
piotrpdev Jul 15, 2024
cb6ca04
feat(api-history): pre-process more error checking
piotrpdev Jul 15, 2024
0b1b6a7
Update docs/latest/api-history.schema.json
piotrpdev Jul 15, 2024
99b36d1
fix(api-history): duplicate dependencies
piotrpdev Jul 15, 2024
5a552aa
docs(api-history): remove unnecessary comment
piotrpdev Jul 15, 2024
51ab304
refactor(api-history): move pre-process deps to dev deps
piotrpdev Jul 15, 2024
9481b1c
feat(api-history): `isHtml(node)` type guard
piotrpdev Jul 15, 2024
a111aea
fix(api-history): missing `toLowerCase()`
piotrpdev Jul 16, 2024
228653f
Update scripts/tasks/preprocess-api-history.ts
piotrpdev Jul 16, 2024
6849610
Update scripts/tasks/preprocess-api-history.ts
piotrpdev Jul 16, 2024
8a08d34
Update src/components/ApiHistoryTable.tsx
piotrpdev Jul 16, 2024
6e74b23
revert(api-history): `isHtml(node)` type guard
piotrpdev Jul 16, 2024
04029d1
feat(api-history): tell user to run `lint-roller`
piotrpdev Jul 16, 2024
92ae687
fix(api-history): stricter change type param
piotrpdev Jul 16, 2024
f5295f5
Apply suggestions from code review
piotrpdev Jul 26, 2024
0db471e
style(api-history): fix lint
piotrpdev Jul 26, 2024
b7ef54e
Merge branch 'main' into feat/api-history
piotrpdev Jul 26, 2024
644106a
fix(api-history): remove unnecessary null check
piotrpdev Jul 26, 2024
f72365b
style(api-history): fix lint
piotrpdev Jul 26, 2024
0186844
docs(api-history): stricter schema
piotrpdev Jul 29, 2024
ca2f9de
docs(api-history): `ipc-renderer`
piotrpdev Jul 29, 2024
b310ecf
docs(api-history): `browser-view`
piotrpdev Jul 29, 2024
6c709fd
Merge branch 'main' into feat/api-history
piotrpdev Aug 4, 2024
cdd1eb3
ci: use GH token with correct permissions
dsanders11 Aug 5, 2024
a047f6a
fix(api-history): change semver sign if backport is `x.0.0`
piotrpdev Aug 5, 2024
e5b2578
fix(api-history): preprocess warn on missing schema
piotrpdev Aug 6, 2024
60f5457
Update src/components/ApiHistoryTable.tsx
piotrpdev Aug 11, 2024
e61e7d6
refactor(api-history): better semver logic
piotrpdev Aug 11, 2024
b1325ae
Merge branch 'main' into feat/api-history
piotrpdev Aug 11, 2024
3176216
refactor(api-history): remove test `docs/`
piotrpdev Aug 12, 2024
a9d5975
refactor(api-history): remove test PR data
piotrpdev Aug 12, 2024
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
Prev Previous commit
Next Next commit
feat(api-history): minor table styling
  • Loading branch information
piotrpdev committed Jul 2, 2024
commit f1e9b096593e384915e94153e86907f741de59c8
24 changes: 24 additions & 0 deletions src/css/custom.scss
Original file line number Diff line number Diff line change
Expand Up @@ -256,3 +256,27 @@
.navbar__logo {
width: 2rem;
}

// TODO: Test these on mobile
details.api-history {
transform: translateY(
calc(
var(--ifm-heading-vertical-rhythm-bottom) * var(--ifm-leading) * -0.5
)
);

summary {
width: fit-content;
font-weight: normal;
font-style: italic;

&:hover {
cursor: pointer;
}
}

table {
margin-top: 0.5rem;
margin-bottom: 0;
}
}
167 changes: 122 additions & 45 deletions src/transformers/api-history.ts
Original file line number Diff line number Diff line change
@@ -1,109 +1,186 @@
import { InlineCode, Link, Parent, Table, TableRow } from 'mdast';
import { MdxJsxFlowElement } from 'mdast-util-mdx-jsx';
import { parse as parseYaml } from 'yaml'
import {
BlockContent,
DefinitionContent,
InlineCode,
Link,
Node,
RootContentMap,
TableRow,
} from 'mdast';
import {
MdxJsxAttribute,
MdxJsxExpressionAttribute,
MdxJsxFlowElementData,
} from 'mdast-util-mdx-jsx';
import { parse as parseYaml } from 'yaml';

enum Change {
ADDED = "API ADDED",
CHANGED = "API CHANGED",
DEPRECATED = "API DEPRECATED",
REMOVED = "API REMOVED",
ADDED = 'API ADDED',
CHANGED = 'API CHANGED',
DEPRECATED = 'API DEPRECATED',
REMOVED = 'API REMOVED',
}

type ApiHistory = {
added?: { 'pr-url': string }[];
deprecated?: { 'pr-url': string, 'breaking-changes-header': string }[];
removed?: { 'pr-url': string, 'breaking-changes-header': string }[];
changes?: { 'pr-url': string, description: string }[];
}
deprecated?: { 'pr-url': string; 'breaking-changes-header': string }[];
removed?: { 'pr-url': string; 'breaking-changes-header': string }[];
changes?: { 'pr-url': string; description: string }[];
};

export default function attacher() {
return transformer;
}

// TODO: Add styling based on type
const generateTableRow = (type: Change, prUrl: string, changes?: string) => ({
type: "tableRow",
const generateTableRow = (type: Change, prUrl: string, changes?: string) =>
({
type: 'tableRow',
children: [
{
type: "tableCell",
type: 'tableCell',
children: [
{
type: "link",
type: 'link',
title: null,
url: prUrl,
children: [ { type: "inlineCode", value: '#' + prUrl.split("/").at(-1) } ],
children: [
{ type: 'inlineCode', value: '#' + prUrl.split('/').at(-1) },
],
},
],
},
{
type: "tableCell",
type: 'tableCell',
children: [
// TODO: Handle formatting for inline code in changes. Maybe support full markdown?
{ type: "text", value: changes || type },
...(changes
? [{ type: 'text', value: changes }]
: [{ type: 'inlineCode', value: type }]),
],
},
],
} as TableRow
)
} as TableRow);

function transformer(tree: Parent) {
// ! Typescript witchcraft to avoid adding `remark-mdx` as a dependency <https://mdxjs.com/packages/remark-mdx/#types>
interface MdxJsxFlowElementWithSummary extends ParentWithMdxJsxFlowElement {
type: 'mdxJsxFlowElement';
name: string | null;
attributes: Array<MdxJsxAttribute | MdxJsxExpressionAttribute>;
children: Array<
| BlockContent
| DefinitionContent
| MdxJsxFlowElementWithSummary
| { type: 'text'; value: string }
>;
data?: MdxJsxFlowElementData | undefined;
}
interface RootContentMapWithMdxJsxFlowElement extends RootContentMap {
mdxJsxFlowElement: MdxJsxFlowElementWithSummary;
}
type RootContentWithMdxJsxFlowElement =
RootContentMapWithMdxJsxFlowElement[keyof RootContentMapWithMdxJsxFlowElement];
interface ParentWithMdxJsxFlowElement extends Node {
children: Array<RootContentWithMdxJsxFlowElement>;
}

function transformer(tree: ParentWithMdxJsxFlowElement) {
for (let nodeIdx = 0; nodeIdx < tree.children.length; nodeIdx++) {
const node = tree.children[nodeIdx];

const isYamlHistoryCodeBlock = node.type === 'code' && node.lang === 'YAML' && node.meta === 'history';
const isYamlHistoryCodeBlock =
node.type === 'code' && node.lang === 'YAML' && node.meta === 'history';
if (!isYamlHistoryCodeBlock) continue;

// TODO: Handle validation
const apiHistory = parseYaml(node.value) as ApiHistory;

// ? Maybe this is too much abstraction?
let apiHistoryChangeRows: TableRow[] = [
...(apiHistory.added?.map(added => generateTableRow(Change.ADDED, added['pr-url'])) ?? []),
...(apiHistory.changes?.map(change => generateTableRow(Change.CHANGED, change['pr-url'], change['description'])) ?? []),
...(apiHistory.deprecated?.map(deprecated => generateTableRow(Change.DEPRECATED, deprecated['pr-url'])) ?? []),
...(apiHistory.removed?.map(removed => generateTableRow(Change.REMOVED, removed['pr-url'])) ?? []),
const apiHistoryChangeRows: TableRow[] = [
...(apiHistory.added?.map((added) =>
generateTableRow(Change.ADDED, added['pr-url'])
) ?? []),
...(apiHistory.changes?.map((change) =>
generateTableRow(
Change.CHANGED,
change['pr-url'],
change['description']
)
) ?? []),
...(apiHistory.deprecated?.map((deprecated) =>
generateTableRow(Change.DEPRECATED, deprecated['pr-url'])
) ?? []),
...(apiHistory.removed?.map((removed) =>
generateTableRow(Change.REMOVED, removed['pr-url'])
) ?? []),
];

// Sort by PR number, lower number on bottom of table
apiHistoryChangeRows.sort((a, b) => {
const aPrNumber = parseInt(((a.children[0].children[0] as Link).children[0] as InlineCode).value.slice(1));
const bPrNumber = parseInt(((b.children[0].children[0] as Link).children[0] as InlineCode).value.slice(1));
const aPrNumber = parseInt(
(
(a.children[0].children[0] as Link).children[0] as InlineCode
).value.slice(1)
);
const bPrNumber = parseInt(
(
(b.children[0].children[0] as Link).children[0] as InlineCode
).value.slice(1)
);
return bPrNumber - aPrNumber;
})
});

const apiHistoryDetails = {
type: "mdxJsxFlowElement",
// TODO: Maybe use a custom element? Change "Details" at least.
name: "Details",
attributes: [],
type: 'mdxJsxFlowElement',
name: 'details',
attributes: [
{
type: 'mdxJsxAttribute',
name: 'class',
value: 'api-history',
},
],
children: [
{
type: "table",
align: [ "center", "center" ],
type: 'mdxJsxFlowElement',
name: 'summary',
attributes: [],
children: [
{
type: 'text',
value: 'History',
},
],
data: {
_mdxExplicitJsx: true,
},
},
{
type: 'table',
align: ['center', 'center'],
children: [
{
type: "tableRow",
type: 'tableRow',
children: [
{
type: "tableCell",
children: [ { type: "text", value: "Version" } ],
type: 'tableCell',
children: [{ type: 'text', value: 'PR' }],
},
{
type: "tableCell",
children: [ { type: "text", value: "Changes" } ],
type: 'tableCell',
children: [{ type: 'text', value: 'Changes' }],
},
],
},
...apiHistoryChangeRows,
],
} satisfies Table,
},
],
data: {
_mdxExplicitJsx: true,
},
} satisfies MdxJsxFlowElement
} satisfies MdxJsxFlowElementWithSummary;

// TODO: Find better type than 'any'
tree.children[nodeIdx] = apiHistoryDetails as any;
tree.children[nodeIdx] = apiHistoryDetails;
}
}