Skip to content

Commit

Permalink
fix: update README
Browse files Browse the repository at this point in the history
  • Loading branch information
DenisGorbachev committed Feb 15, 2025
1 parent a635c2a commit 25d1ec2
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 47 deletions.
121 changes: 80 additions & 41 deletions README.ts
Original file line number Diff line number Diff line change
@@ -1,81 +1,120 @@
#!/usr/bin/env -S deno run --allow-read --allow-run=bash,git,cargo --allow-env --allow-sys
#!/usr/bin/env -S deno run --allow-read --allow-run=bash,git,cargo --allow-net=docs.rs:443 --allow-env --allow-sys

import * as zx from "npm:zx"
import { z, ZodSchema } from "https://deno.land/x/[email protected]/mod.ts"
import { assertEquals } from "https://jsr.io/@std/assert/1.0.0/equals.ts"
import { assert } from "https://jsr.io/@std/assert/1.0.0/assert.ts"

const CargoToml = z.object({
package: z.object({
name: z.string().min(1),
description: z.string().min(1),
repository: z.string().url().min(1),
metadata: z.object({
details: z.object({
title: z.string().min(1),
tagline: z.string(),
summary: z.string(),
}),
import { z, ZodSchema, ZodTypeDef } from "https://deno.land/x/[email protected]/mod.ts"
import { assert, assertEquals } from "jsr:@std/[email protected]"

const CargoTomlSchema = z.object({
package: z.object({
name: z.string().min(1),
description: z.string().min(1),
repository: z.string().url().min(1),
metadata: z.object({
details: z.object({
title: z.string().min(1).optional(),
tagline: z.string().optional(),
summary: z.string().optional(),
peers: z.array(z.string()).default([]).describe("Packages that should be installed alongside this package"),
}).default({}),
}).default({}),
}),
}),
})

type CargoToml = z.infer<typeof CargoToml>
type CargoToml = z.infer<typeof CargoTomlSchema>

const CargoMetadataSchema = z.object({
packages: z.array(z.object({
name: z.string(),
targets: z.array(z.object({
name: z.string(),
packages: z.array(z.object({
name: z.string(),
targets: z.array(z.object({
name: z.string(),
})),
})),
})),
})

type CargoMetadata = z.infer<typeof CargoMetadataSchema>

const Repo = z.object({
url: z.string().url(),
const RepoSchema = z.object({
url: z.string().url(),
})

type Repo = z.infer<typeof Repo>
type Repo = z.infer<typeof RepoSchema>

const $ = zx.$({
cwd: import.meta.dirname,
const BadgeSchema = z.object({
name: z.string().min(1),
image: z.string().url(),
url: z.string().url(),
})

const parse = <T>(schema: ZodSchema<T>, input: zx.ProcessOutput) => schema.parse(JSON.parse(input.stdout))
const renderMarkdownList = (items: string[]) => items.map((bin) => `* ${bin}`).join("\n")
type Badge = z.infer<typeof BadgeSchema>

const badge = (name: string, image: string, url: string): Badge => BadgeSchema.parse({ name, url, image })

const theCargoToml: CargoToml = parse(CargoToml, await $`yj -t < Cargo.toml`)
const { package: { name, metadata: { details: { title } } } } = theCargoToml
const bin = name
const help = await $`cargo run --quiet --bin ${bin} -- --help`
const dirname = import.meta.dirname
if (!dirname) throw new Error("Cannot determine the current script dirname")

const $ = zx.$({ cwd: dirname })

// deno-lint-ignore no-explicit-any
const parse = <Output = any, Def extends ZodTypeDef = ZodTypeDef, Input = Output>(schema: ZodSchema<Output, Def, Input>, input: zx.ProcessOutput) => schema.parse(JSON.parse(input.stdout))

const theCargoToml: CargoToml = parse(CargoTomlSchema, await $`yj -t < Cargo.toml`)
const { package: { name, description, metadata: { details } } } = theCargoToml
const title = details.title || description
const peers = details.peers
const theCargoMetadata: CargoMetadata = parse(CargoMetadataSchema, await $`cargo metadata --format-version 1`)
const thePackageMetadata = theCargoMetadata.packages.find((p) => p.name == name)
assert(thePackageMetadata, "Could not find package metadata")
const target = thePackageMetadata.targets[0]
assert(target, "Could not find package first target")
const doc = await $`cargo doc2readme --template README.jl --target-name ${target.name} --out -`
const repo: Repo = parse(Repo, await $`gh repo view --json url`)
const extraBins = (await $`find src/bin/*.rs -type f -exec basename {} .rs \\;`).valueOf().split("\n")
const docsUrl = `https://docs.rs/${name}`

// launch multiple promises in parallel
const doc2ReadmePromise = $`cargo doc2readme --template README.jl --target-name ${target.name} --out -`
const ghRepoPromise = $`gh repo view --json url`
const docsUrlPromise = fetch(docsUrl, { method: "HEAD" })
const helpPromise = $`cargo run --quiet --bin ${name} -- --help`
const extraBinsPromise = $`find src/bin/*.rs -type f -exec basename {} .rs \\;`

const doc = await doc2ReadmePromise
const docStr = doc.stdout.trim()

const repo: Repo = parse(RepoSchema, await ghRepoPromise)
assertEquals(repo.url, theCargoToml.package.repository)

const docsUrlHead = await docsUrlPromise
const docsUrlIs200 = docsUrlHead.status === 200

const badges: Badge[] = [
badge("Build", `${repo.url}/actions/workflows/ci.yml/badge.svg`, repo.url),
]
if (docsUrlIs200) {
badges.push(badge("Documentation", `https://docs.rs/${name}/badge.svg`, docsUrl))
}
const badgesStr = badges.map(({ name, image, url }) => `[![${name}](${image})](${url})`).join("\n")

const titleSection = [
badgesStr,
docStr,
].filter((s) => s.length)

const cargoAddPackages = [name, ...peers]

const autogenerated = `
<!-- DO NOT EDIT -->
<!-- This file is automatically generated by README.ts. -->
<!-- Edit README.ts if you want to make changes. -->
`.trim()

const help = await helpPromise
const extraBins = (await extraBinsPromise).valueOf().split("\n")
const renderMarkdownList = (items: string[]) => items.map((bin) => `* ${bin}`).join("\n")

console.info(`
${autogenerated}
# ${title}
[![Build](${repo.url}/actions/workflows/ci.yml/badge.svg)](${repo.url})
[![Documentation](https://docs.rs/${name}/badge.svg)](https://docs.rs/${name})
${doc.stdout.trim()}
${titleSection.join("\n\n")}
## Installation
Expand Down
11 changes: 5 additions & 6 deletions commitlint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
const severity = {
disable: 0,
warn: 1,
error: 2,
}
const disable = 0
const warn = 1
const error = 2

export default {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
severity.error,
error,
'always',
[
'build',
Expand All @@ -26,5 +24,6 @@ export default {
'test',
],
],
'subject-case': [disable]
},
}
1 change: 1 addition & 0 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 25d1ec2

Please sign in to comment.