mirror of
https://git.pumpin.online/funkpower/catena.git
synced 2026-10-22 18:57:14 +00:00
bindings: the footnote signal, which book-pipeline still had its own copy of
`looks_like_footnote_citations` is the function chunkmd's `looks_like_citations` was ported from, and book-pipeline was still running the Python original at four call sites. Bound on all four surfaces so it can stop. Checked against the Python over 34,458 chunks of the live corpus: no disagreement.
This commit is contained in:
@@ -79,6 +79,7 @@ except ValueError as why:
|
||||
| `series_of` | [`seriesof`](../seriesof/README.md) |
|
||||
| `parse_identifier` | [`idnorm`](../idnorm/README.md) |
|
||||
| `find_citations` | [`citefind`](../citefind/README.md) |
|
||||
| `looks_like_footnote_citations` | whether a body chunk carries notes worth reading |
|
||||
| `citation_prompt` | the question `citefind --prompt` writes |
|
||||
| `merge_citation_reply` | what `citefind --merge` does with the answer |
|
||||
|
||||
|
||||
@@ -98,6 +98,10 @@ char *catena_series_of(const char *title, const char *author);
|
||||
* one — an answer, not an error. */
|
||||
char *catena_parse_identifier(const char *text);
|
||||
|
||||
/* Whether a chunk of body text carries footnote or endnote citations.
|
||||
* Returns 1 for yes, 0 for no, -1 on error. */
|
||||
int catena_looks_like_footnote_citations(const char *text);
|
||||
|
||||
/* Read the references out of a bibliography or a page of notes. Returns a
|
||||
* JSON array, one object per reference. */
|
||||
char *catena_find_citations(const char *text);
|
||||
|
||||
@@ -19,6 +19,7 @@ from ._catena import (
|
||||
find_citations,
|
||||
fuse_hits,
|
||||
identify,
|
||||
looks_like_footnote_citations,
|
||||
merge_citation_reply,
|
||||
pack_cues,
|
||||
parse_identifier,
|
||||
@@ -38,6 +39,7 @@ __all__ = [
|
||||
"find_citations",
|
||||
"fuse_hits",
|
||||
"identify",
|
||||
"looks_like_footnote_citations",
|
||||
"merge_citation_reply",
|
||||
"pack_cues",
|
||||
"parse_identifier",
|
||||
|
||||
@@ -38,6 +38,7 @@ def fuse_hits(
|
||||
) -> list[dict[str, Any]]: ...
|
||||
def identify(name: str, data: bytes) -> dict[str, Any]: ...
|
||||
def find_citations(text: str) -> list[dict[str, Any]]: ...
|
||||
def looks_like_footnote_citations(text: str) -> bool: ...
|
||||
def citation_prompt(references: Iterable[Mapping[str, Any]]) -> str | None: ...
|
||||
def merge_citation_reply(
|
||||
references: Iterable[Mapping[str, Any]], reply: str
|
||||
|
||||
@@ -417,6 +417,21 @@ pub unsafe extern "C" fn catena_identify(
|
||||
give_json(&crate::identify(name, bytes))
|
||||
}
|
||||
|
||||
/// Whether a chunk of body text carries footnote or endnote citations.
|
||||
/// Returns 1 for yes, 0 for no, -1 on error.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `text` must be NUL-terminated UTF-8.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn catena_looks_like_footnote_citations(text: *const c_char) -> i32 {
|
||||
clear_error();
|
||||
let Some(text) = (unsafe { borrow(text, "text") }) else {
|
||||
return -1;
|
||||
};
|
||||
i32::from(crate::looks_like_footnote_citations(text))
|
||||
}
|
||||
|
||||
/// Read the references out of a bibliography or a page of notes. Returns a
|
||||
/// JSON array, one object per reference.
|
||||
///
|
||||
|
||||
@@ -215,6 +215,14 @@ pub fn parse_identifier(text: &str) -> Option<idnorm::Identifier> {
|
||||
idnorm::parse(text)
|
||||
}
|
||||
|
||||
/// Whether a chunk of body text carries footnote or endnote citations.
|
||||
///
|
||||
/// The structural signal a converter leaves on EPUB3 note definitions first;
|
||||
/// otherwise the numbered-note markers and what sits after them.
|
||||
pub fn looks_like_footnote_citations(text: &str) -> bool {
|
||||
chunkmd::footnote::looks_like_citations(text)
|
||||
}
|
||||
|
||||
/// Read the references out of a bibliography or a page of notes.
|
||||
///
|
||||
/// Each carries `unsettled`: the fields that could not be read off the entry,
|
||||
@@ -261,6 +269,18 @@ mod tests {
|
||||
assert_eq!(count_tokens("a passage"), textkit::count("a passage"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_footnote_signal_agrees_with_the_library_underneath() {
|
||||
const NOTES: &str = "1. John Smith, *A Title* (Oxford: Clarendon Press, 1998), 183.\n\
|
||||
2. Jane Doe, *Another* (Cambridge: University Press, 2001), p. 12.";
|
||||
assert!(looks_like_footnote_citations(NOTES));
|
||||
assert_eq!(
|
||||
looks_like_footnote_citations(NOTES),
|
||||
chunkmd::footnote::looks_like_citations(NOTES)
|
||||
);
|
||||
assert!(!looks_like_footnote_citations("Just a paragraph of prose."));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_citation_surface_agrees_with_the_library_underneath() {
|
||||
const REFS: &str = "Smith, John. *A Title*. Oxford: Clarendon Press, 1998.\n\nMarron, Kevin Ritual Abuse, Seal Books, 1988";
|
||||
|
||||
@@ -220,6 +220,12 @@ fn identify<'py>(py: Python<'py>, name: &str, data: &[u8]) -> PyResult<Bound<'py
|
||||
to_py(py, &crate::identify(name, data))
|
||||
}
|
||||
|
||||
/// Whether a chunk of body text carries footnote or endnote citations.
|
||||
#[pyfunction]
|
||||
fn looks_like_footnote_citations(text: &str) -> bool {
|
||||
crate::looks_like_footnote_citations(text)
|
||||
}
|
||||
|
||||
/// Read the references out of a bibliography or a page of notes.
|
||||
#[pyfunction]
|
||||
fn find_citations<'py>(py: Python<'py>, text: &str) -> PyResult<Bound<'py, PyList>> {
|
||||
@@ -290,6 +296,7 @@ fn _catena(module: &Bound<'_, PyModule>) -> PyResult<()> {
|
||||
module.add_function(wrap_pyfunction!(fuse_hits, module)?)?;
|
||||
module.add_function(wrap_pyfunction!(identify, module)?)?;
|
||||
module.add_function(wrap_pyfunction!(find_citations, module)?)?;
|
||||
module.add_function(wrap_pyfunction!(looks_like_footnote_citations, module)?)?;
|
||||
module.add_function(wrap_pyfunction!(citation_prompt, module)?)?;
|
||||
module.add_function(wrap_pyfunction!(merge_citation_reply, module)?)?;
|
||||
module.add_function(wrap_pyfunction!(series_of, module)?)?;
|
||||
|
||||
@@ -305,6 +305,12 @@ pub fn identify(name: &str, data: &[u8]) -> Result<JsValue, JsValue> {
|
||||
to_js(&crate::identify(name, data))
|
||||
}
|
||||
|
||||
/// Whether a chunk of body text carries footnote or endnote citations.
|
||||
#[wasm_bindgen(js_name = looksLikeFootnoteCitations)]
|
||||
pub fn looks_like_footnote_citations(text: &str) -> bool {
|
||||
crate::looks_like_footnote_citations(text)
|
||||
}
|
||||
|
||||
/// Read the references out of a bibliography or a page of notes.
|
||||
#[wasm_bindgen(js_name = findCitations, skip_typescript)]
|
||||
pub fn find_citations(text: &str) -> Result<JsValue, JsValue> {
|
||||
|
||||
Reference in New Issue
Block a user