Skip to content

Commit f181977

Browse files
authored
Merge pull request #141 from zotero/previewCluster
previewCitationCluster => previewCluster
2 parents 7f67551 + 6750e71 commit f181977

File tree

3 files changed

+120
-55
lines changed

3 files changed

+120
-55
lines changed

crates/wasm/README.md

+13-8
Original file line numberDiff line numberDiff line change
@@ -471,14 +471,15 @@ Sometimes, a user wants to see how a cluster will look while they are editing
471471
it, before confirming the change.
472472

473473
```javascript
474-
let cites = [ { id: "citekey", locator: "45" }, { ... } ];
474+
let cluster = { cites: [ { id: "citekey", locator: "45" }, { ... } ] };
475475
let positions = [ ... before, { note: 34 }, ... after ];
476-
let preview = driver.previewCitationCluster(cites, positions, "html").unwrap();
476+
let preview = driver.previewCluster(cluster, positions).unwrap();
477+
let plainPreview = driver.previewCluster(cluster, positions, "plain").unwrap();
477478
```
478479

479-
The format argument is like the format passed to `Driver.new`: one of `"html"`,
480-
`"rtf"` or `"plain"`. The driver will use that instead of its normal output
481-
format.
480+
The cluster argument is just a cluster, without an `id` field, since it's
481+
ephemeral. The lack of `id` field is reflected in the `positions` argument as
482+
well.
482483

483484
The positions array is exactly like a call to `setClusterOrder`, except exactly
484485
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,
492493
assemble the positions array as you would a call to `setClusterOrder` with
493494
exactly the operation you're previewing applied.
494495

496+
The format argument is optional, and works like the format passed to
497+
`Driver.new`: one of `"html"`, `"rtf"` or `"plain"`. The driver will use that
498+
instead of its normal output format.
499+
495500

496501
### `AuthorOnly`, `SuppressAuthor` & `Composite`
497502

@@ -652,9 +657,9 @@ Both of these methods will require throwing out almost all cached computation,
652657
so use sparingly.
653658

654659
If you need to render a preview in a different format, there is an argument on
655-
`previewCitationCluster` for doing just that. It does not throw out all the
660+
`previewCluster` for doing just that. It does not throw out all the
656661
computation. `citeproc-rs`' disambiguation procedures do take formatting into
657662
account, so `<i>Title</i>` can be distinct from `<b>Title</b>` in HTML and RTF,
658663
but not if the whole driver's output format is `"plain"`, since they both look
659-
identical in plain text. `previewCitationCluster` will simply translate the
660-
formatting into another format, without re-computing all the disambiguation.
664+
identical in plain text. `previewCluster` will simply translate the formatting
665+
into another format, without re-computing all the disambiguation.

crates/wasm/js-tests/node/index.test.ts

+57-23
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@ let boldStyle = mkNoteStyle(
1313
<text variable="URL" prefix=" " />
1414
`,
1515
);
16+
let authorTitleStyle = mkInTextStyle(
17+
`
18+
<group delimiter=", ">
19+
<names variable="author" />
20+
<text variable="title" />
21+
</group>
22+
`,
23+
``
24+
);
25+
1626

1727
describe("Driver", () => {
1828

@@ -182,7 +192,7 @@ describe("batchedUpdates", () => {
182192

183193
});
184194

185-
describe("previewCitationCluster", () => {
195+
describe("previewCluster", () => {
186196

187197
let ibidStyle = mkNoteStyle(
188198
`
@@ -198,7 +208,7 @@ describe("previewCitationCluster", () => {
198208
``,
199209
);
200210

201-
function pccSetup(callback) {
211+
function pccSetup(callback: (driver: Driver, ids: [string, string]) => void) {
202212
withDriver({ style: ibidStyle }, driver => {
203213
let one = "cluster-one";
204214
let two = "cluster-two";
@@ -213,8 +223,8 @@ describe("previewCitationCluster", () => {
213223
test("between two other clusters", () => {
214224
pccSetup((driver, [one, two]) => {
215225
// between the other two
216-
let pcc = driver.previewCitationCluster(
217-
[{ id: "r1" }],
226+
let pcc = driver.previewCluster(
227+
{ cites: [{ id: "r1" }] },
218228
[{ id: one }, {}, { id: two }],
219229
"plain"
220230
).unwrap();
@@ -225,15 +235,15 @@ describe("previewCitationCluster", () => {
225235
test("replacing a cluster", () => {
226236
pccSetup((driver, [one, two]) => {
227237
// replacing #1
228-
var pcc = driver.previewCitationCluster(
229-
[{ id: "r1" }],
238+
var pcc = driver.previewCluster(
239+
{ cites: [{ id: "r1" }] },
230240
[{}, { id: two }],
231241
"plain"
232242
).unwrap();
233243
expect(pcc).toEqual("ONE");
234244
// replacing #1, with note numbers isntead
235-
pcc = driver.previewCitationCluster(
236-
[{ id: "r1" }],
245+
pcc = driver.previewCluster(
246+
{ cites: [{ id: "r1" }] },
237247
[{ note: 1, }, { id: two, note: 5 }],
238248
"plain"
239249
).unwrap();
@@ -242,27 +252,51 @@ describe("previewCitationCluster", () => {
242252
})
243253

244254
test("should error when supplying unsupported output format", () => {
245-
pccSetup((driver, [one, two]) => {
246-
let res = driver.previewCitationCluster([{ id: "r1" }], [{}], "plaintext");
255+
pccSetup((driver) => {
256+
let res = driver.previewCluster({ cites: [{ id: "r1" }] }, [{}], "plaintext");
247257
expect(() => res.unwrap()).toThrow("Unknown output format \"plaintext\"");
248258
})
249-
})
259+
});
260+
261+
test("should allow omitting the format argument", () => {
262+
pccSetup((driver, [_, two]) => {
263+
let res = driver.previewCluster(
264+
{ cites: [{ id: "r1" }] },
265+
[{ note: 1 }, { id: two, note: 5 }]
266+
).unwrap();
267+
expect(res).toEqual("ONE");
268+
})
269+
});
270+
271+
test("should handle cluster modes", () => {
272+
pccSetup((driver, [_, two]) => {
273+
driver.setStyle(authorTitleStyle).unwrap();
274+
driver.insertReference(
275+
{ title: "ONE", id: "r1", type: "book", author: [{ family: "Smith" }] }
276+
).unwrap();
277+
let res = driver.previewCluster(
278+
{ cites: [{ id: "r1" }], mode: "Composite", infix: ", whose book" },
279+
[{ note: 1 }, { id: two, note: 5 }]
280+
).unwrap();
281+
expect(res).toEqual("Smith, whose book ONE");
282+
})
283+
});
284+
285+
test("should also work via deprecated previewCitationCluster(cites: Cite[], ...)", () => {
286+
pccSetup((driver, [_, two]) => {
287+
let res = driver.previewCitationCluster(
288+
[{ id: "r1" }],
289+
[{ note: 1 }, { id: two, note: 5 }]
290+
).unwrap();
291+
expect(res).toEqual("ONE");
292+
})
293+
});
250294

251295
});
252296

253297
describe("AuthorOnly and friends", () => {
254-
let style = mkInTextStyle(
255-
`
256-
<group delimiter=", ">
257-
<names variable="author" />
258-
<text variable="title" />
259-
</group>
260-
`,
261-
``
262-
);
263-
264-
function withSupp(callback) {
265-
withDriver({ style }, driver => {
298+
function withSupp(callback: (driver: Driver, ids: [string, string]) => void) {
299+
withDriver({ style: authorTitleStyle }, driver => {
266300
let one = "cluster-one";
267301
let two = "cluster-two";
268302
oneOneOne(driver, { title: "ONE", id: "r1", author: [{ family: "Smith" }] }, "cluster-one");

crates/wasm/src/lib.rs

+50-24
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ extern crate log;
2020
use js_sys::Promise;
2121
use std::cell::RefCell;
2222
use std::rc::Rc;
23-
use std::str::FromStr;
2423
use std::sync::Arc;
2524
use wasm_bindgen::prelude::*;
2625
use wasm_bindgen_futures::{future_to_promise, JsFuture};
@@ -296,37 +295,64 @@ impl Driver {
296295
})
297296
}
298297

298+
/// @deprecated Use `previewCluster` instead
299+
#[wasm_bindgen(js_name = "previewCitationCluster")]
300+
pub fn preview_citation_cluster(
301+
&self,
302+
cites: Box<[JsValue]>,
303+
positions: Box<[JsValue]>,
304+
format: Option<String>,
305+
) -> StringResult {
306+
typescript_serde_result(|| {
307+
let cites = utils::read_js_array_2(cites)?;
308+
self.preview_cluster_inner(PreviewCluster::new(cites, None), positions, format)
309+
})
310+
}
311+
299312
/// Previews a formatted citation cluster, in a particular position.
300313
///
301-
/// - `cites`: The cites to go in the cluster
314+
/// - `cluster`: A cluster, without an `id` field. You'll want this to contain some cites.
302315
/// - `positions`: An array of `ClusterPosition`s as in set_cluster_order, but with a single
303316
/// cluster's id set to zero. The cluster with id=0 is the position to preview the cite. It
304317
/// can replace another cluster, or be inserted before/after/between existing clusters, in
305318
/// any location you can think of.
319+
/// - `format`: an optional argument, an output format as a string, that is used only for this
320+
/// preview.
306321
///
307-
#[wasm_bindgen(js_name = "previewCitationCluster")]
308-
pub fn preview_citation_cluster(
322+
#[wasm_bindgen(js_name = "previewCluster")]
323+
pub fn preview_cluster(
309324
&self,
310-
cites: Box<[JsValue]>,
325+
preview_cluster: TPreviewCluster,
311326
positions: Box<[JsValue]>,
312-
format: &str,
327+
format: Option<String>,
313328
) -> StringResult {
314329
typescript_serde_result(|| {
315-
let cites: Vec<Cite<Markup>> = utils::read_js_array_2(cites)?;
316-
let positions: Vec<string_id::ClusterPosition> = utils::read_js_array_2(positions)?;
317-
let mut eng = self.engine.borrow_mut();
318-
let preview = eng.preview_citation_cluster(
319-
PreviewCluster::new(cites, None),
320-
PreviewPosition::MarkWithZeroStr(&positions),
321-
Some(
322-
SupportedFormat::from_str(format)
323-
.map_err(|()| DriverError::UnknownOutputFormat(format.to_owned()))?,
324-
),
325-
);
326-
Ok(preview?)
330+
let preview_cluster: PreviewCluster = preview_cluster.into_serde()?;
331+
self.preview_cluster_inner(preview_cluster, positions, format)
327332
})
328333
}
329334

335+
fn preview_cluster_inner(
336+
&self,
337+
preview_cluster: PreviewCluster,
338+
positions: Box<[JsValue]>,
339+
format: Option<String>,
340+
) -> Result<Arc<SmartString>, DriverError> {
341+
let positions: Vec<string_id::ClusterPosition> = utils::read_js_array_2(positions)?;
342+
let mut eng = self.engine.borrow_mut();
343+
let preview = eng.preview_citation_cluster(
344+
preview_cluster,
345+
PreviewPosition::MarkWithZeroStr(&positions),
346+
format
347+
.map(|frmt| {
348+
frmt.parse::<SupportedFormat>()
349+
.map_err(|()| DriverError::UnknownOutputFormat(frmt))
350+
})
351+
.transpose()?,
352+
);
353+
Ok(preview?)
354+
}
355+
330356
#[wasm_bindgen(js_name = "makeBibliography")]
331357
pub fn make_bibliography(&self) -> BibEntriesResult {
332358
typescript_serde_result(|| {
@@ -508,7 +534,7 @@ interface InitOptions {
508534
localeOverride?: string,
509535
510536
/** Disables sorting in the bibliography; items appear in cited order. */
511-
bibliographyNoSort?: bool,
537+
bibliographyNoSort?: boolean,
512538
}
513539
514540
/** This interface lets citeproc retrieve locales or modules asynchronously,
@@ -559,7 +585,7 @@ export type Cluster = {
559585
cites: Cite[];
560586
} & ClusterMode;
561587
562-
export type PreviewCluster {
588+
export type PreviewCluster = {
563589
cites: Cite[];
564590
} & ClusterMode;
565591
@@ -706,11 +732,11 @@ interface WasmResult<T> {
706732
is_ok(): boolean;
707733
is_err(): boolean;
708734
/** If this is an error, returns the default value. */
709-
unwrap_or(default: T): T;
735+
unwrap_or(defaultValue: T): T;
710736
/** If this is Ok, returns f(ok_val), else returns Err unmodified. */
711737
map<R>(f: (t: T) => R): WasmResult<T>;
712738
/** If this is Ok, returns f(ok_val), else returns the default value. */
713-
map_or<R>(default: R, f: (t: T) => R): R;
739+
map_or<R>(defaultValue: R, f: (t: T) => R): R;
714740
}
715741
"#;
716742

@@ -753,11 +779,11 @@ interface IndependentMeta {
753779
/** A list of languages for which a locale override was specified.
754780
* Does not include the language-less final override. */
755781
localeOverrides: string[],
756-
hasBibliography: bool,
782+
hasBibliography: boolean,
757783
}
758784
interface StyleMeta {
759785
info: StyleInfo,
760-
features: { [feature: string]: bool },
786+
features: { [feature: string]: boolean },
761787
defaultLocale: string,
762788
/** May be absent on a dependent style */
763789
class?: "in-text" | "note",

0 commit comments

Comments
 (0)