mirror of
https://github.com/tommilligan/mdbook-admonish.git
synced 2025-12-27 15:51:33 -05:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
02640dab1f | ||
|
|
771e9c9fd8 | ||
|
|
cce9343c47 | ||
|
|
20b158966b | ||
|
|
491f9cf341 | ||
|
|
6deaf1ea2b | ||
|
|
041e5a566f | ||
|
|
99b5a235cf | ||
|
|
39edc4d92a | ||
|
|
7773213093 | ||
|
|
e888fcd021 | ||
|
|
95dc7582ad | ||
|
|
b658eb6049 | ||
|
|
623291625a | ||
|
|
4dad5a86c8 |
30
.github/workflows/deploy.yml
vendored
30
.github/workflows/deploy.yml
vendored
@@ -16,14 +16,16 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target:
|
||||
- x86_64-unknown-linux-gnu
|
||||
- x86_64-unknown-linux-musl
|
||||
- x86_64-apple-darwin
|
||||
- x86_64-pc-windows-msvc
|
||||
include:
|
||||
- target: x86_64-unknown-linux-gnu
|
||||
- target: aarch64-unknown-linux-musl
|
||||
os: ubuntu-latest
|
||||
name: aarch64-unknown-linux-musl.tar.gz
|
||||
- target: x86_64-unknown-linux-gnu
|
||||
# Deliberately pinned to the same version `mdbook` uses to build
|
||||
# binaries, so we use the same glibc version
|
||||
#
|
||||
# ref: https://github.com/rust-lang/mdBook/pull/1955
|
||||
os: ubuntu-20.04
|
||||
name: x86_64-unknown-linux-gnu.tar.gz
|
||||
- target: x86_64-unknown-linux-musl
|
||||
os: ubuntu-latest
|
||||
@@ -56,17 +58,19 @@ jobs:
|
||||
profile: minimal
|
||||
target: ${{ matrix.target }}
|
||||
|
||||
- name: Setup | musl tools
|
||||
if: matrix.target == 'x86_64-unknown-linux-musl'
|
||||
run: sudo apt install -y musl-tools
|
||||
- name: Setup | cross
|
||||
if: endsWith(matrix.target, '-unknown-linux-musl')
|
||||
uses: taiki-e/install-action@v2
|
||||
with:
|
||||
tool: cross
|
||||
|
||||
- name: Build | Build
|
||||
if: matrix.target != 'x86_64-unknown-linux-musl'
|
||||
if: ${{ !endsWith(matrix.target, '-unknown-linux-musl') }}
|
||||
run: cargo build --release --target ${{ matrix.target }}
|
||||
|
||||
- name: Build | Build (musl)
|
||||
if: matrix.target == 'x86_64-unknown-linux-musl'
|
||||
run: cargo build --release --target ${{ matrix.target }}
|
||||
if: endsWith(matrix.target, '-unknown-linux-musl')
|
||||
run: cross build --release --target ${{ matrix.target }}
|
||||
|
||||
- name: Post Setup | Extract tag name
|
||||
shell: bash
|
||||
@@ -78,7 +82,6 @@ jobs:
|
||||
run: |
|
||||
mkdir target/stage
|
||||
cd target/${{ matrix.target }}/release
|
||||
strip ${{ env.CRATE_NAME }}.exe
|
||||
7z a ../../stage/${{ env.CRATE_NAME }}-${{ steps.extract_tag.outputs.tag }}-${{ matrix.name }} ${{ env.CRATE_NAME }}.exe
|
||||
cd -
|
||||
- name: Post Setup | Prepare artifacts [-nix]
|
||||
@@ -86,7 +89,6 @@ jobs:
|
||||
run: |
|
||||
mkdir target/stage
|
||||
cd target/${{ matrix.target }}/release
|
||||
strip ${{ env.CRATE_NAME }}
|
||||
tar czvf ../../stage/${{ env.CRATE_NAME }}-${{ steps.extract_tag.outputs.tag }}-${{ matrix.name }} ${{ env.CRATE_NAME }}
|
||||
cd -
|
||||
- name: Post Setup | Upload artifacts
|
||||
|
||||
26
CHANGELOG.md
26
CHANGELOG.md
@@ -2,6 +2,26 @@
|
||||
|
||||
## Unreleased
|
||||
|
||||
## 1.11.1
|
||||
|
||||
### Fixed
|
||||
|
||||
- Reverted internal dependency upgrades that unintentionally increased MSRV from 1.66.0 in 1.11.0
|
||||
|
||||
## 1.11.0 (yanked)
|
||||
|
||||
**Note:** This release has been yanked.
|
||||
|
||||
It unintentionally increased the MSRV from 1.66.0
|
||||
|
||||
### Changed
|
||||
|
||||
- `gnu` prebuilt binaries are now built on `ubuntu-20.04` to match `mdbook` binaries. Thanks to [@eitsupi](https://github.com/eitsupi) for the fix! ([#118](https://github.com/tommilligan/mdbook-admonish/pull/118))
|
||||
|
||||
### Added
|
||||
|
||||
- `aarch64-unknown-linux-musl` prebuilt binary now available ([#119](https://github.com/tommilligan/mdbook-admonish/pull/119))
|
||||
|
||||
## 1.10.2
|
||||
|
||||
### Fixed
|
||||
@@ -136,7 +156,11 @@ This behaviour is [documented in the readme here](https://github.com/tommilligan
|
||||
- Flattened indentation of generated HTML, otherwise it's styled as a markdown code block
|
||||
- Fixed edge cases where the info string changes length when parsed, causing title/body to be incorrectly split
|
||||
|
||||
## 1.3.0
|
||||
## 1.3.0 (yanked)
|
||||
|
||||
**Note:** This release has been yanked.
|
||||
|
||||
It unintentionally introduced a serious parsing bug.
|
||||
|
||||
### Added
|
||||
|
||||
|
||||
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -1014,7 +1014,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mdbook-admonish"
|
||||
version = "1.10.2"
|
||||
version = "1.11.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mdbook-admonish"
|
||||
version = "1.10.2"
|
||||
version = "1.11.1"
|
||||
edition = "2021"
|
||||
|
||||
authors = ["Tom Milligan <code@tommilligan.net>"]
|
||||
@@ -17,6 +17,9 @@ name = "mdbook-admonish"
|
||||
path = "src/bin/mdbook-admonish.rs"
|
||||
required-features = ["cli"]
|
||||
|
||||
[profile.release]
|
||||
strip = true
|
||||
|
||||
[lib]
|
||||
name = "mdbook_admonish"
|
||||
path = "src/lib.rs"
|
||||
|
||||
@@ -5,5 +5,5 @@ set -exuo pipefail
|
||||
cd "$(dirname "$0")"/../..
|
||||
|
||||
if ! mdbook-toc --version; then
|
||||
cargo install mdbook-toc --version 0.13.0 --force
|
||||
cargo install mdbook-toc --version 0.14.1 --force
|
||||
fi
|
||||
|
||||
@@ -90,4 +90,29 @@ let x = 20;
|
||||
<span class="boring">}</span></code></pre></pre>
|
||||
</div>
|
||||
</div>
|
||||
<p>In a list:</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Thing one</p>
|
||||
<pre><code class="language-sh">Thing one
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Thing two</p>
|
||||
<div id="admonition-note-4" class="admonition note">
|
||||
<div class="admonition-title">
|
||||
<p>Note</p>
|
||||
<p><a class="admonition-anchor-link" href="#admonition-note-4"></a></p>
|
||||
</div>
|
||||
<div>
|
||||
<p>Thing two</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>Thing three</p>
|
||||
<pre><code class="language-sh">Thing three
|
||||
</code></pre>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
|
||||
@@ -41,3 +41,23 @@ let x = 10;
|
||||
let x = 20;
|
||||
```
|
||||
````
|
||||
|
||||
In a list:
|
||||
|
||||
1. Thing one
|
||||
|
||||
```sh
|
||||
Thing one
|
||||
```
|
||||
|
||||
1. Thing two
|
||||
|
||||
```admonish
|
||||
Thing two
|
||||
```
|
||||
|
||||
1. Thing three
|
||||
|
||||
```sh
|
||||
Thing three
|
||||
```
|
||||
|
||||
@@ -29,11 +29,24 @@ pub(crate) fn preprocess(
|
||||
if let Event::Start(Tag::CodeBlock(Fenced(info_string))) = event.clone() {
|
||||
let span_content = &content[span.start..span.end];
|
||||
|
||||
// Scan for a line start before this span.
|
||||
// For safety, only scan up to a fixed limit of the text
|
||||
const INDENT_SCAN_MAX: usize = 1024;
|
||||
// If there's less text than that, just scan from the start
|
||||
let line_scan_start = span.start.checked_sub(INDENT_SCAN_MAX).unwrap_or_default();
|
||||
// If we can't find a newline, assume no indent
|
||||
let indent = content[line_scan_start..span.start]
|
||||
.chars()
|
||||
.rev()
|
||||
.position(|c| c == '\n')
|
||||
.unwrap_or_default();
|
||||
|
||||
let admonition = match parse_admonition(
|
||||
info_string.as_ref(),
|
||||
admonition_defaults,
|
||||
span_content,
|
||||
on_failure,
|
||||
indent,
|
||||
) {
|
||||
Some(admonition) => admonition,
|
||||
None => continue,
|
||||
@@ -418,7 +431,7 @@ Will have bonus classnames
|
||||
```
|
||||
"#;
|
||||
|
||||
let expected = r##"
|
||||
let expected = r#"
|
||||
|
||||
<div id="admonition-default" class="admonition note">
|
||||
<div>
|
||||
@@ -427,7 +440,7 @@ Will have bonus classnames
|
||||
|
||||
</div>
|
||||
</div>
|
||||
"##;
|
||||
"#;
|
||||
|
||||
assert_eq!(expected, prep(content));
|
||||
}
|
||||
@@ -684,7 +697,7 @@ A simple admonition.
|
||||
Text
|
||||
"#;
|
||||
|
||||
let expected = r##"# Chapter
|
||||
let expected = r#"# Chapter
|
||||
|
||||
<div id="admonition-default" class="admonition note">
|
||||
<div>
|
||||
@@ -694,7 +707,7 @@ A simple admonition.
|
||||
</div>
|
||||
</div>
|
||||
Text
|
||||
"##;
|
||||
"#;
|
||||
|
||||
let preprocess_result = preprocess(
|
||||
content,
|
||||
@@ -718,7 +731,7 @@ A simple admonition.
|
||||
Text
|
||||
"#;
|
||||
|
||||
let expected = r##"# Chapter
|
||||
let expected = r#"# Chapter
|
||||
|
||||
<div id="admonition-default" class="admonition note">
|
||||
<div>
|
||||
@@ -728,6 +741,64 @@ A simple admonition.
|
||||
</div>
|
||||
</div>
|
||||
Text
|
||||
"#;
|
||||
|
||||
assert_eq!(expected, prep(content));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_embed() {
|
||||
let content = r#"# Chapter
|
||||
|
||||
1. Thing one
|
||||
|
||||
```sh
|
||||
Thing one
|
||||
```
|
||||
|
||||
1. Thing two
|
||||
|
||||
```admonish
|
||||
Thing two
|
||||
```
|
||||
|
||||
1. Thing three
|
||||
|
||||
```sh
|
||||
Thing three
|
||||
```
|
||||
"#;
|
||||
|
||||
let expected = r##"# Chapter
|
||||
|
||||
1. Thing one
|
||||
|
||||
```sh
|
||||
Thing one
|
||||
```
|
||||
|
||||
1. Thing two
|
||||
|
||||
|
||||
<div id="admonition-note" class="admonition note">
|
||||
<div class="admonition-title">
|
||||
|
||||
Note
|
||||
|
||||
<a class="admonition-anchor-link" href="#admonition-note"></a>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
Thing two
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
1. Thing three
|
||||
|
||||
```sh
|
||||
Thing three
|
||||
```
|
||||
"##;
|
||||
|
||||
assert_eq!(expected, prep(content));
|
||||
|
||||
23
src/parse.rs
23
src/parse.rs
@@ -23,6 +23,7 @@ pub(crate) fn parse_admonition<'a>(
|
||||
admonition_defaults: &'a AdmonitionDefaults,
|
||||
content: &'a str,
|
||||
on_failure: OnFailure,
|
||||
indent: usize,
|
||||
) -> Option<Result<Admonition<'a>>> {
|
||||
// We need to know fence details anyway for error messages
|
||||
let extracted = extract_admonish_body(content);
|
||||
@@ -30,8 +31,6 @@ pub(crate) fn parse_admonition<'a>(
|
||||
let info = AdmonitionMeta::from_info_string(info_string, admonition_defaults)?;
|
||||
let info = match info {
|
||||
Ok(info) => info,
|
||||
// FIXME return error messages to break build if configured
|
||||
// Err(message) => return Some(Err(content)),
|
||||
Err(message) => {
|
||||
// Construct a fence capable of enclosing whatever we wrote for the
|
||||
// actual input block
|
||||
@@ -63,6 +62,7 @@ Original markdown input:
|
||||
{enclosing_fence}
|
||||
"#
|
||||
)),
|
||||
indent,
|
||||
})
|
||||
}
|
||||
OnFailure::Bail => Err(anyhow!("Error processing admonition, bailing:\n{content}")),
|
||||
@@ -70,7 +70,24 @@ Original markdown input:
|
||||
}
|
||||
};
|
||||
|
||||
Some(Ok(Admonition::new(info, extracted.body)))
|
||||
Some(Ok(Admonition::new(
|
||||
info,
|
||||
extracted.body,
|
||||
// Note that this is a bit hacky - the fence information comes from the start
|
||||
// of the block, and includes the whole line.
|
||||
//
|
||||
// This is more likely to be what we want, as ending indentation is unrelated
|
||||
// according to the commonmark spec (ref https://spec.commonmark.org/0.12/#example-85)
|
||||
//
|
||||
// The main case we're worried about here is indenting enough to be inside list items,
|
||||
// and in this case the starting code fence must be indented enough to be considered
|
||||
// part of the list item.
|
||||
//
|
||||
// The hacky thing is that we're considering line indent in the document as a whole,
|
||||
// not relative to the context of some containing item. But I think that's what we
|
||||
// want for now, anyway.
|
||||
indent,
|
||||
)))
|
||||
}
|
||||
|
||||
/// We can't trust the info string length to find the start of the body
|
||||
|
||||
@@ -31,10 +31,11 @@ pub(crate) struct Admonition<'a> {
|
||||
pub(crate) content: Cow<'a, str>,
|
||||
pub(crate) additional_classnames: Vec<String>,
|
||||
pub(crate) collapsible: bool,
|
||||
pub(crate) indent: usize,
|
||||
}
|
||||
|
||||
impl<'a> Admonition<'a> {
|
||||
pub(crate) fn new(info: AdmonitionMeta, content: &'a str) -> Self {
|
||||
pub(crate) fn new(info: AdmonitionMeta, content: &'a str, indent: usize) -> Self {
|
||||
let AdmonitionMeta {
|
||||
directive,
|
||||
title,
|
||||
@@ -47,6 +48,7 @@ impl<'a> Admonition<'a> {
|
||||
content: Cow::Borrowed(content),
|
||||
additional_classnames,
|
||||
collapsible,
|
||||
indent,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,17 +68,18 @@ impl<'a> Admonition<'a> {
|
||||
let mut additional_class = Cow::Borrowed(self.directive.classname());
|
||||
let title = &self.title;
|
||||
let content = &self.content;
|
||||
let indent = " ".repeat(self.indent);
|
||||
|
||||
let title_block = if self.collapsible { "summary" } else { "div" };
|
||||
|
||||
let title_html = if !title.is_empty() {
|
||||
Cow::Owned(format!(
|
||||
r##"<{title_block} class="admonition-title">
|
||||
|
||||
{title}
|
||||
|
||||
<a class="admonition-anchor-link" href="#{ANCHOR_ID_PREFIX}-{anchor_id}"></a>
|
||||
</{title_block}>
|
||||
r##"{indent}<{title_block} class="admonition-title">
|
||||
{indent}
|
||||
{indent}{title}
|
||||
{indent}
|
||||
{indent}<a class="admonition-anchor-link" href="#{ANCHOR_ID_PREFIX}-{anchor_id}"></a>
|
||||
{indent}</{title_block}>
|
||||
"##
|
||||
))
|
||||
} else {
|
||||
@@ -100,13 +103,13 @@ impl<'a> Admonition<'a> {
|
||||
// rendered as markdown paragraphs.
|
||||
format!(
|
||||
r#"
|
||||
<{admonition_block} id="{ANCHOR_ID_PREFIX}-{anchor_id}" class="admonition {additional_class}">
|
||||
{title_html}<div>
|
||||
|
||||
{content}
|
||||
|
||||
</div>
|
||||
</{admonition_block}>"#,
|
||||
{indent}<{admonition_block} id="{ANCHOR_ID_PREFIX}-{anchor_id}" class="admonition {additional_class}">
|
||||
{title_html}{indent}<div>
|
||||
{indent}
|
||||
{indent}{content}
|
||||
{indent}
|
||||
{indent}</div>
|
||||
{indent}</{admonition_block}>"#,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user