diff --git a/crates/wasm/README.md b/crates/wasm/README.md
index 3c291eea..0735b4eb 100644
--- a/crates/wasm/README.md
+++ b/crates/wasm/README.md
@@ -471,14 +471,15 @@ Sometimes, a user wants to see how a cluster will look while they are editing
it, before confirming the change.
```javascript
-let cites = [ { id: "citekey", locator: "45" }, { ... } ];
+let cluster = { cites: [ { id: "citekey", locator: "45" }, { ... } ] };
let positions = [ ... before, { note: 34 }, ... after ];
-let preview = driver.previewCitationCluster(cites, positions, "html").unwrap();
+let preview = driver.previewCluster(cluster, positions).unwrap();
+let plainPreview = driver.previewCluster(cluster, positions, "plain").unwrap();
```
-The format argument is like the format passed to `Driver.new`: one of `"html"`,
-`"rtf"` or `"plain"`. The driver will use that instead of its normal output
-format.
+The cluster argument is just a cluster, without an `id` field, since it's
+ephemeral. The lack of `id` field is reflected in the `positions` argument as
+well.
The positions array is exactly like a call to `setClusterOrder`, except exactly
one of the positions omits the id field. This could either:
@@ -492,6 +493,10 @@ mean you would never see "ibid" in a preview.** So for maximum utility,
assemble the positions array as you would a call to `setClusterOrder` with
exactly the operation you're previewing applied.
+The format argument is optional, and works like the format passed to
+`Driver.new`: one of `"html"`, `"rtf"` or `"plain"`. The driver will use that
+instead of its normal output format.
+
### `AuthorOnly`, `SuppressAuthor` & `Composite`
@@ -652,9 +657,9 @@ Both of these methods will require throwing out almost all cached computation,
so use sparingly.
If you need to render a preview in a different format, there is an argument on
-`previewCitationCluster` for doing just that. It does not throw out all the
+`previewCluster` for doing just that. It does not throw out all the
computation. `citeproc-rs`' disambiguation procedures do take formatting into
account, so `Title` can be distinct from `Title` in HTML and RTF,
but not if the whole driver's output format is `"plain"`, since they both look
-identical in plain text. `previewCitationCluster` will simply translate the
-formatting into another format, without re-computing all the disambiguation.
+identical in plain text. `previewCluster` will simply translate the formatting
+into another format, without re-computing all the disambiguation.
diff --git a/crates/wasm/js-tests/node/index.test.ts b/crates/wasm/js-tests/node/index.test.ts
index 51b443be..9789bc53 100644
--- a/crates/wasm/js-tests/node/index.test.ts
+++ b/crates/wasm/js-tests/node/index.test.ts
@@ -13,6 +13,16 @@ let boldStyle = mkNoteStyle(
`,
);
+let authorTitleStyle = mkInTextStyle(
+ `
+
+
+
+
+ `,
+ ``
+);
+
describe("Driver", () => {
@@ -182,7 +192,7 @@ describe("batchedUpdates", () => {
});
-describe("previewCitationCluster", () => {
+describe("previewCluster", () => {
let ibidStyle = mkNoteStyle(
`
@@ -198,7 +208,7 @@ describe("previewCitationCluster", () => {
``,
);
- function pccSetup(callback) {
+ function pccSetup(callback: (driver: Driver, ids: [string, string]) => void) {
withDriver({ style: ibidStyle }, driver => {
let one = "cluster-one";
let two = "cluster-two";
@@ -213,8 +223,8 @@ describe("previewCitationCluster", () => {
test("between two other clusters", () => {
pccSetup((driver, [one, two]) => {
// between the other two
- let pcc = driver.previewCitationCluster(
- [{ id: "r1" }],
+ let pcc = driver.previewCluster(
+ { cites: [{ id: "r1" }] },
[{ id: one }, {}, { id: two }],
"plain"
).unwrap();
@@ -225,15 +235,15 @@ describe("previewCitationCluster", () => {
test("replacing a cluster", () => {
pccSetup((driver, [one, two]) => {
// replacing #1
- var pcc = driver.previewCitationCluster(
- [{ id: "r1" }],
+ var pcc = driver.previewCluster(
+ { cites: [{ id: "r1" }] },
[{}, { id: two }],
"plain"
).unwrap();
expect(pcc).toEqual("ONE");
// replacing #1, with note numbers isntead
- pcc = driver.previewCitationCluster(
- [{ id: "r1" }],
+ pcc = driver.previewCluster(
+ { cites: [{ id: "r1" }] },
[{ note: 1, }, { id: two, note: 5 }],
"plain"
).unwrap();
@@ -242,27 +252,51 @@ describe("previewCitationCluster", () => {
})
test("should error when supplying unsupported output format", () => {
- pccSetup((driver, [one, two]) => {
- let res = driver.previewCitationCluster([{ id: "r1" }], [{}], "plaintext");
+ pccSetup((driver) => {
+ let res = driver.previewCluster({ cites: [{ id: "r1" }] }, [{}], "plaintext");
expect(() => res.unwrap()).toThrow("Unknown output format \"plaintext\"");
})
- })
+ });
+
+ test("should allow omitting the format argument", () => {
+ pccSetup((driver, [_, two]) => {
+ let res = driver.previewCluster(
+ { cites: [{ id: "r1" }] },
+ [{ note: 1 }, { id: two, note: 5 }]
+ ).unwrap();
+ expect(res).toEqual("ONE");
+ })
+ });
+
+ test("should handle cluster modes", () => {
+ pccSetup((driver, [_, two]) => {
+ driver.setStyle(authorTitleStyle).unwrap();
+ driver.insertReference(
+ { title: "ONE", id: "r1", type: "book", author: [{ family: "Smith" }] }
+ ).unwrap();
+ let res = driver.previewCluster(
+ { cites: [{ id: "r1" }], mode: "Composite", infix: ", whose book" },
+ [{ note: 1 }, { id: two, note: 5 }]
+ ).unwrap();
+ expect(res).toEqual("Smith, whose book ONE");
+ })
+ });
+
+ test("should also work via deprecated previewCitationCluster(cites: Cite[], ...)", () => {
+ pccSetup((driver, [_, two]) => {
+ let res = driver.previewCitationCluster(
+ [{ id: "r1" }],
+ [{ note: 1 }, { id: two, note: 5 }]
+ ).unwrap();
+ expect(res).toEqual("ONE");
+ })
+ });
});
describe("AuthorOnly and friends", () => {
- let style = mkInTextStyle(
- `
-
-
-
-
- `,
- ``
- );
-
- function withSupp(callback) {
- withDriver({ style }, driver => {
+ function withSupp(callback: (driver: Driver, ids: [string, string]) => void) {
+ withDriver({ style: authorTitleStyle }, driver => {
let one = "cluster-one";
let two = "cluster-two";
oneOneOne(driver, { title: "ONE", id: "r1", author: [{ family: "Smith" }] }, "cluster-one");
diff --git a/crates/wasm/src/lib.rs b/crates/wasm/src/lib.rs
index fdf23c81..7e84ecbd 100644
--- a/crates/wasm/src/lib.rs
+++ b/crates/wasm/src/lib.rs
@@ -20,7 +20,6 @@ extern crate log;
use js_sys::Promise;
use std::cell::RefCell;
use std::rc::Rc;
-use std::str::FromStr;
use std::sync::Arc;
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::{future_to_promise, JsFuture};
@@ -296,37 +295,64 @@ impl Driver {
})
}
+ /// @deprecated Use `previewCluster` instead
+ #[wasm_bindgen(js_name = "previewCitationCluster")]
+ pub fn preview_citation_cluster(
+ &self,
+ cites: Box<[JsValue]>,
+ positions: Box<[JsValue]>,
+ format: Option,
+ ) -> StringResult {
+ typescript_serde_result(|| {
+ let cites = utils::read_js_array_2(cites)?;
+ self.preview_cluster_inner(PreviewCluster::new(cites, None), positions, format)
+ })
+ }
+
/// Previews a formatted citation cluster, in a particular position.
///
- /// - `cites`: The cites to go in the cluster
+ /// - `cluster`: A cluster, without an `id` field. You'll want this to contain some cites.
/// - `positions`: An array of `ClusterPosition`s as in set_cluster_order, but with a single
/// cluster's id set to zero. The cluster with id=0 is the position to preview the cite. It
/// can replace another cluster, or be inserted before/after/between existing clusters, in
/// any location you can think of.
+ /// - `format`: an optional argument, an output format as a string, that is used only for this
+ /// preview.
///
- #[wasm_bindgen(js_name = "previewCitationCluster")]
- pub fn preview_citation_cluster(
+ #[wasm_bindgen(js_name = "previewCluster")]
+ pub fn preview_cluster(
&self,
- cites: Box<[JsValue]>,
+ preview_cluster: TPreviewCluster,
positions: Box<[JsValue]>,
- format: &str,
+ format: Option,
) -> StringResult {
typescript_serde_result(|| {
- let cites: Vec> = utils::read_js_array_2(cites)?;
- let positions: Vec = utils::read_js_array_2(positions)?;
- let mut eng = self.engine.borrow_mut();
- let preview = eng.preview_citation_cluster(
- PreviewCluster::new(cites, None),
- PreviewPosition::MarkWithZeroStr(&positions),
- Some(
- SupportedFormat::from_str(format)
- .map_err(|()| DriverError::UnknownOutputFormat(format.to_owned()))?,
- ),
- );
- Ok(preview?)
+ let preview_cluster: PreviewCluster = preview_cluster.into_serde()?;
+ self.preview_cluster_inner(preview_cluster, positions, format)
})
}
+ fn preview_cluster_inner(
+ &self,
+ preview_cluster: PreviewCluster,
+ positions: Box<[JsValue]>,
+ format: Option,
+ ) -> Result, DriverError> {
+ let positions: Vec = utils::read_js_array_2(positions)?;
+ let mut eng = self.engine.borrow_mut();
+ let preview = eng.preview_citation_cluster(
+ preview_cluster,
+ PreviewPosition::MarkWithZeroStr(&positions),
+ format
+ .map(|frmt| {
+ frmt.parse::()
+ .map_err(|()| DriverError::UnknownOutputFormat(frmt))
+ })
+ .transpose()?,
+ );
+ Ok(preview?)
+ }
+
#[wasm_bindgen(js_name = "makeBibliography")]
pub fn make_bibliography(&self) -> BibEntriesResult {
typescript_serde_result(|| {
@@ -508,7 +534,7 @@ interface InitOptions {
localeOverride?: string,
/** Disables sorting in the bibliography; items appear in cited order. */
- bibliographyNoSort?: bool,
+ bibliographyNoSort?: boolean,
}
/** This interface lets citeproc retrieve locales or modules asynchronously,
@@ -559,7 +585,7 @@ export type Cluster = {
cites: Cite[];
} & ClusterMode;
-export type PreviewCluster {
+export type PreviewCluster = {
cites: Cite[];
} & ClusterMode;
@@ -706,11 +732,11 @@ interface WasmResult {
is_ok(): boolean;
is_err(): boolean;
/** If this is an error, returns the default value. */
- unwrap_or(default: T): T;
+ unwrap_or(defaultValue: T): T;
/** If this is Ok, returns f(ok_val), else returns Err unmodified. */
map(f: (t: T) => R): WasmResult;
/** If this is Ok, returns f(ok_val), else returns the default value. */
- map_or(default: R, f: (t: T) => R): R;
+ map_or(defaultValue: R, f: (t: T) => R): R;
}
"#;
@@ -753,11 +779,11 @@ interface IndependentMeta {
/** A list of languages for which a locale override was specified.
* Does not include the language-less final override. */
localeOverrides: string[],
- hasBibliography: bool,
+ hasBibliography: boolean,
}
interface StyleMeta {
info: StyleInfo,
- features: { [feature: string]: bool },
+ features: { [feature: string]: boolean },
defaultLocale: string,
/** May be absent on a dependent style */
class?: "in-text" | "note",