summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock97
-rw-r--r--docs/Cargo.toml1
-rw-r--r--docs/src/contribs.rs97
-rw-r--r--docs/src/general/changelog.md6
-rw-r--r--docs/src/html.rs28
-rw-r--r--docs/src/lib.rs2
6 files changed, 225 insertions, 6 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 1eceaa61..c31425a1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1501,6 +1501,21 @@ dependencies = [
]
[[package]]
+name = "ring"
+version = "0.16.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
+dependencies = [
+ "cc",
+ "libc",
+ "once_cell",
+ "spin",
+ "untrusted",
+ "web-sys",
+ "winapi",
+]
+
+[[package]]
name = "roff"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1545,6 +1560,18 @@ dependencies = [
]
[[package]]
+name = "rustls"
+version = "0.20.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f"
+dependencies = [
+ "log",
+ "ring",
+ "sct",
+ "webpki",
+]
+
+[[package]]
name = "rustversion"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1603,6 +1630,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1"
[[package]]
+name = "sct"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
+[[package]]
name = "semver"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1679,6 +1716,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
+name = "spin"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+
+[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1989,6 +2032,7 @@ dependencies = [
"typst-library",
"unicode_names2",
"unscanny",
+ "ureq",
"yaml-front-matter",
]
@@ -2165,6 +2209,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9df2af067a7953e9c3831320f35c1cc0600c30d44d9f7a12b01db1cd88d6b47"
[[package]]
+name = "untrusted"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
+
+[[package]]
+name = "ureq"
+version = "2.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "338b31dd1314f68f3aabf3ed57ab922df95ffcd902476ca7ba3c4ce7b908c46d"
+dependencies = [
+ "base64",
+ "flate2",
+ "log",
+ "once_cell",
+ "rustls",
+ "serde",
+ "serde_json",
+ "url",
+ "webpki",
+ "webpki-roots",
+]
+
+[[package]]
name = "url"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2284,6 +2352,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
[[package]]
+name = "web-sys"
+version = "0.3.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "webpki"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
+[[package]]
+name = "webpki-roots"
+version = "0.22.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
+dependencies = [
+ "webpki",
+]
+
+[[package]]
name = "weezl"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/docs/Cargo.toml b/docs/Cargo.toml
index a2e64f99..a5885a8a 100644
--- a/docs/Cargo.toml
+++ b/docs/Cargo.toml
@@ -22,3 +22,4 @@ heck = "0.4"
yaml-front-matter = "0.1"
unicode_names2 = "0.6.0"
once_cell = "1"
+ureq = { version = "2.6", features = ["json"] }
diff --git a/docs/src/contribs.rs b/docs/src/contribs.rs
new file mode 100644
index 00000000..df1d4944
--- /dev/null
+++ b/docs/src/contribs.rs
@@ -0,0 +1,97 @@
+use std::cmp::Reverse;
+use std::collections::HashMap;
+use std::fmt::Write;
+
+use serde::Deserialize;
+
+use super::Html;
+
+/// Build HTML detailing the contributors between two tags.
+pub fn contributors(from: &str, to: &str) -> Option<Html> {
+ let staff = ["laurmaedje", "reknih"];
+
+ let url = format!("https://api.github.com/repos/typst/typst/compare/{from}...{to}");
+ let response: Response = ureq::get(&url)
+ .set("X-GitHub-Api-Version", "2022-11-28")
+ .call()
+ .ok()?
+ .into_json()
+ .ok()?;
+
+ // Determine number of contributions per person.
+ let mut contributors = HashMap::<String, Contributor>::new();
+ for commit in response.commits {
+ contributors
+ .entry(commit.author.login.clone())
+ .or_insert_with(|| Contributor {
+ login: commit.author.login,
+ avatar: commit.author.avatar_url,
+ contributions: 0,
+ })
+ .contributions += 1;
+ }
+
+ // Keep only non-staff people.
+ let mut contributors: Vec<_> = contributors
+ .into_values()
+ .filter(|c| !staff.contains(&c.login.as_str()))
+ .collect();
+
+ // Sort by highest number of commits.
+ contributors.sort_by_key(|c| Reverse(c.contributions));
+ if contributors.is_empty() {
+ return None;
+ }
+
+ let mut html = "Thanks to everyone who contributed to this release!".to_string();
+ html += "<ul class=\"contribs\">";
+
+ for Contributor { login, avatar, contributions } in contributors {
+ let login = login.replace('\"', "&quot;").replace('&', "&amp;");
+ let avatar = avatar.replace("?v=", "?s=64&v=");
+ let s = if contributions > 1 { "s" } else { "" };
+ write!(
+ html,
+ r#"<li>
+ <a href="https://github.com/{login}" target="_blank">
+ <img
+ width="64"
+ height="64"
+ src="{avatar}"
+ alt="GitHub avatar of {login}"
+ title="@{login} made {contributions} contribution{s}"
+ crossorigin="anonymous"
+ >
+ </a>
+ </li>"#
+ )
+ .unwrap();
+ }
+
+ html += "</ul>";
+
+ Some(Html::new(html))
+}
+
+#[derive(Debug)]
+struct Contributor {
+ login: String,
+ avatar: String,
+ contributions: usize,
+}
+
+#[derive(Debug, Deserialize)]
+struct Response {
+ commits: Vec<Commit>,
+}
+
+#[derive(Debug, Deserialize)]
+struct Commit {
+ author: Author,
+}
+
+#[derive(Debug, Deserialize)]
+struct Author {
+ login: String,
+ avatar_url: String,
+}
diff --git a/docs/src/general/changelog.md b/docs/src/general/changelog.md
index 22f4147b..1b28bc09 100644
--- a/docs/src/general/changelog.md
+++ b/docs/src/general/changelog.md
@@ -45,6 +45,8 @@ description: |
- [Ratios]($type/ratio) can now be multiplied with more types and be converted
to [floats]($type/float) with the [`float`]($func/float) function
+<contributors from="v0.1.0" to="v0.2.0" />
+
## April 04, 2023 (v0.1.0)
- **Breaking changes:**
- When using the CLI, you now have to use subcommands:
@@ -113,7 +115,7 @@ description: |
- Fixed line number in error message for CSV parsing
- Fixed invalid autocompletion after certain markup elements
-Thanks to everybody who contributed to this release!
+<contributors from="v23-03-28" to="v0.1.0" />
## March 28, 2023
- **Breaking changes:**
@@ -153,7 +155,7 @@ Thanks to everybody who contributed to this release!
- Links in bibliographies are now affected by link styling
- Fixed hovering over comments in web app
-Thanks to everybody who contributed to this release!
+<contributors from="v23-03-21" to="v23-03-28" />
## March 21, 2023
- Reference and bibliography management
diff --git a/docs/src/html.rs b/docs/src/html.rs
index b189a09c..d3566b07 100644
--- a/docs/src/html.rs
+++ b/docs/src/html.rs
@@ -1,3 +1,5 @@
+use std::ops::Range;
+
use comemo::Prehashed;
use md::escape::escape_html;
use pulldown_cmark as md;
@@ -108,16 +110,21 @@ impl<'a> Handler<'a> {
// Rewrite HTML images.
md::Event::Html(html) if html.starts_with("<img") => {
- let needle = "src=\"";
- let offset = html.find(needle).unwrap() + needle.len();
- let len = html[offset..].find('"').unwrap();
- let range = offset..offset + len;
+ let range = html_attr_range(html, "src").unwrap();
let path = &html[range.clone()];
let mut buf = html.to_string();
buf.replace_range(range, &self.handle_image(path));
*html = buf.into();
}
+ // Rewrite contributor sectinos.
+ md::Event::Html(html) if html.starts_with("<contributors") => {
+ let from = html_attr(html, "from").unwrap();
+ let to = html_attr(html, "to").unwrap();
+ let Some(output) = contributors(from, to) else { return false };
+ *html = output.raw.into();
+ }
+
// Rewrite links.
md::Event::Start(md::Tag::Link(ty, dest, _)) => {
assert!(
@@ -327,6 +334,19 @@ fn code_block(resolver: &dyn Resolver, lang: &str, text: &str) -> Html {
resolver.example(highlighted, &frames)
}
+/// Extract an attribute value from an HTML element.
+fn html_attr<'a>(html: &'a str, attr: &str) -> Option<&'a str> {
+ html.get(html_attr_range(html, attr)?)
+}
+
+/// Extract the range of the attribute value of an HTML element.
+fn html_attr_range(html: &str, attr: &str) -> Option<Range<usize>> {
+ let needle = format!("{attr}=\"");
+ let offset = html.find(&needle)? + needle.len();
+ let len = html[offset..].find('"')?;
+ Some(offset..offset + len)
+}
+
/// World for example compilations.
struct DocWorld(Source);
diff --git a/docs/src/lib.rs b/docs/src/lib.rs
index 4a20a008..7333090d 100644
--- a/docs/src/lib.rs
+++ b/docs/src/lib.rs
@@ -1,7 +1,9 @@
//! Documentation provider for Typst.
+mod contribs;
mod html;
+pub use contribs::contributors;
pub use html::Html;
use std::fmt::{self, Debug, Formatter};