@citeproc-rs/wasm
这是一个前端
citeproc-rs,引用
处理器用 Rust 写成并编译到 Web Assembly .
它包含适合于下列目的的建筑物:
- 节点.js
- 浏览器,使用 Webpack.js 等捆绑器
- 浏览器直接从网络服务器导入 ES 模块
安装/ 释放通道
有两个发布频道:
稳定 每个版本的发布。 ()在编写本报告时,没有 版本发布.安装方式:
yarn add @citeproc-rs/wasm
加那利语Name 跟踪主分支 打开
GitHub 图像。其版本编号随同
格式 0.0.0-canary-GIT_COMMIT_SHA因此,版本范围在您的
package.json 没有意义。 但是,你可以安装最新的一个有:
yarn add @citeproc-rs/wasm@canary
# alternatively, a specific commit
yarn add @citeproc-rs/[email protected]_SHA
如果使用国家预防机制,则替换 yarn add 与 npm install。 。 。 .
包括你的项目
对于Node.js,只需将软件包导入为普通. 字体定义为 ,尽管API中不能自动生成类型的部分 定义在文档注释中被提及,并附带您可以使用的类型 导入.
// Node.js
const { Driver } = require("@citeproc-rs/wasm");
微软边缘
注意微软 Edge 的文本编码器/文本解码器支持中的提醒 原子弹 教程。 。 。 .
使用 Web 软件包
在网络上加载时,由于技术原因和编译原因 Web Assembly 是大型的, 你必须同步装入软件包 。 网包来了 具有这样同步导入包的能力:
// Webpack
import("@citeproc-rs/wasm")
.then(go)
.catch(console.error);
function go(wasm) {
const { Driver } = wasm;
// use Driver
}
当你这样做时,你的代码会触发下载(和流出剖析)
当二进制完成时,您 go 函数将调用。 这个
如果您的网络服务器设置正确, 下载当然可以缓存
整个过程很快.
您可以在任何地方使用正则导入驱动程序作为类型Script类型, 只是不要
用它调用 new Driver()。 。 。 .
反应
如果你正在写 React app,你可能希望使用 React.lazy 像这样:
// App.tsx
import React, { Suspense } from "react";
const AsyncCiteprocEnabledComponent = React.lazy(async () => {
await import("@citeproc-rs/wasm");
return await import("./CiteprocEnabledComponent");
});
const App = () => (
<Suspense
fallback={<div>Loading citation formatting engine...</div>}>
<AsyncCiteprocEnabledComponent />
</Suspense>
);
// CiteprocEnabledComponent
import { Driver } from "@citeproc-rs/wasm";
// ...
以脚本标记导入( I)web 目标)
用 ES 在(现代)网页浏览器中不带捆绑器直接导入 模块支持,程序不同。 你必须:
- 做一个
_web已出版的国家预防机制成套材料的子目录,载于 在您的网络服务器上的内容目录, 或者像 CDN 那样使用 CDN (单位:公斤)。 。 。 . - 包含 a
<script type="module">在您的页面中标记<body>,像这样:
<script type="module">
import init, { Driver } from './path/to/_web/citeproc_rs_wasm.js';
async function run() {
await init();
// use Driver
}
run()
</script>
小心点:此方法不能保证包只装入一次. 若为 您再次调用它, 它会取消您以前创建的驱动程序 .
以脚本标记导入( I)no-modules 目标)
这是 基于 页:1 边框引导
条目, (中文(简体) ),
注意这些警告。 你会,类似地 web 目标,需要使
一、导 言 _no_modules 已出版的国家预防机制成套材料的子目录
可通过网络服务器或通过CDN获取。 但它已经 一个附加符号 改为
通过脚本标记导入.
小心点:此方法不能保证包只装入一次. 若为 您再次调用它, 它会取消您以前创建的驱动程序 .
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
</head>
<body>
<!-- Include these TWO JS files -->
<script src='path/to/@citeproc-rs/wasm/_no_modules/citeproc_rs_wasm_include.js'></script>
<script src='path/to/@citeproc-rs/wasm/_no_modules/citeproc_rs_wasm.js'></script>
<script>
// Like with the `--target web` output the exports are immediately
// available but they won't work until we initialize the module. Unlike
// `--target web`, however, the globals are all stored on a
// `wasm_bindgen` global. The global itself is the initialization
// function and then the properties of the global are all the exported
// functions.
//
// Note that the name `wasm_bindgen` will at some point be configurable with the
// `--no-modules-global` CLI flag (https://github.com/rustwasm/wasm-pack/issues/729)
const { Driver } = wasm_bindgen;
async function run() {
// Note the _bg.wasm ending
await wasm_bindgen('path/to/@citeproc-rs/wasm/_no_modules/citeproc_rs_wasm_bg.wasm');
// Use Driver
}
run();
</script>
</body>
</html>
在Zotero的使用
Zotero有一个特别的建筑 和遗留的Firefox ESR扩展API,
它需要一个通用JS模块格式,但没有节点.js fs API,以及
no-modules' 装载装置,但不使用 window 作为全球
它不存在。 档案在 _zotero 国家防范机制一揽子计划目录.
用法与无模块基本相同;您需要所有三个文件:
@citeproc-rs/wasm/_zotero/citeproc_rs_wasm_include.js@citeproc-rs/wasm/_zotero/citeproc_rs_wasm.js@citeproc-rs/wasm/_zotero/citeproc_rs_wasm_bg.wasm
除了"共同JS shims"之外,主要区别在于API将会是
装入 Zotero.CiteprocRs 对象,以便将其全部链接
一起来.
小心点:此方法不能保证包只装入一次. 若为
你打电话 initWasmModule 再说一次,这会使你之前的司机无效
创建.
require("citeproc_rs_wasm_include");
const initWasmModule = require("citeproc_rs_wasm");
const wasmBinaryPromise = Zotero.HTTP
.request('GET',
'resource://zotero/citeproc_rs_wasm_bg.wasm',
{ responseType: "arraybuffer" })
.then(xhr => xhr.response);
await initWasmModule(wasmBinaryPromise);
let driver;
try {
driver = new Zotero.CiteprocRs.Driver({...});
} catch (e) {
if (e instanceof Zotero.CiteprocRs.CslStyleError) {
// ...
}
}
使用量
概览
交互式使用的基本模式是:
- 用您的风格创建驱动程序实例
- 任意编辑引用或引用组
- 打电话
driver.batchedUpdates() - 对文档应用更新(例如图形界面)
- 用户更改时跳入步骤 2
第三步是重要的一步。 每次编辑一个组或一个引用, 通常只有一两个可见的修改才能产生结果。 因此, 驱动程序只给您那些有 更改,或由其他地方的编辑导致更改。 您可以提交任何 每个调用之间的编辑次数.
API也允许非交互使用. 见下文.
处理错误
许多驱动方法可以抛出错误.
如果您想专门处理这个库的错误,你可以,并且 这主要用于显示样式解析或验证错误。 错误 类型有附着的结构数据.
try {
let driver = new Driver({ ... });
// do stuff with driver
} catch (error) {
if (error instanceof CslStyleError) {
console.error("Could not parse CSL, error:", error);
} else if (error instanceof CiteprocRsDriverError) {
console.error("Error in usage of Driver", error);
} else if (error instanceof CiteprocRsError) {
// CslStyleError and CiteprocRsDriverError are both subclasses of
// CiteprocRsError, so this branch would catch them too had they not
// been checked already.
//
// There may be errors that are not a subclass, but directly an
// instance of CitprocRsError, so for completeness one should test for
// this too.
console.error("Catch-all error", error);
} else {
throw error;
}
} finally {
// Driver is only undefined if `new Driver` threw an error.
if (driver) {
driver.free()
}
}
不幸的是,错误类型必须是全球出口,在窗口/全球/本身.
1. 创建驱动实例
首先,创建驱动程序. 请注意,现在,你还必须打电话 .free() 编辑
当你用完它的时候, 驱动器可以处理它的内存, 但是 有一个TC39
建议
在执行阶段,将没有必要这样做.
驱动程序至少需要 XML 样式字符串、 获取器( 下方) 和输出
格式(其中一种为 "html", (中文(简体) ), "rtf" 或者说 "plain") (中文(简体) ).
let fetcher = ...; // see below
let driver = new Driver({
style: "<style version=\"1.0\" class=\"note\" ... > ... </style>",
format: "html", // optional, html is the default
formatOptions: { // optional
linkAnchors: true, // optional, default true
},
localeOverride: "de-DE", // optional, like setting default-locale on the style
// bibliographyNoSort: true // disables sorting on the bibliography
fetcher,
});
// Fetch the chain of locale files required to use the specified locale
await driver.fetchLocales();
// ... use the driver ...
driver.free()
库解析并验证了 CSL 样式输入. 任何验证错误都是 报告,用字节相抵以发现CSL碎片的责任 和有用的信息(英语),有时甚至提示如何修复. 见 处理错误 如何访问这个.
获取器
有上百个地方 你需要的地方取决于风格 默认, 定义了任何覆盖和任何倒置的地块, 因此 获取一个是同步的, 允许从 HTTP 上获取一个 。 没有 远不止于此:
class Fetcher {
async fetchLocale(lang) {
return await fetch("https://some-cdn-with-locales.com/locales-${lang}.xml")
.then(res => res.text());
// or just
// return "<locale> ... </locale>";
// return LOCALES_PRELOADED[lang];
// or if you don't support locales other than the bundled en-US!
// return null;
}
}
let fetcher = new Fetcher();
let driver = new Driver({ ..., fetcher });
// Make sure you actually fetch them!
await driver.fetchLocales();
除非你没有 async 语法,在这种情况下,返回 a Promise
直接,例如:. return Promise.resolve("<locale> ... </locale>")。 。 。 .
拒绝在 new Driver 或者忘记打电话
await driver.fetchLocales() 使用捆绑结果 en-US 语言。 你个
也不应该试图在获取本地地址时使用驱动程序实例.
2. 编辑参考文献或引文集
参考资料
您可以插入这样的引用 。 这是一个 CSL - 简森 对象.
driver.insertReference({ id: "citekey", type: "book", title: "Title" });
driver.insertReferences([ ... many references ... ]);
driver.resetReferences([ ... deletes any others ... ]);
driver.removeReference("citekey");
引用组及其锡类
文件由一系列集群组成,每个集群都有一系列引用. 每个
组有 id,这是任何旧的字符串.
// initClusters is like booting up an existing document and getting up to speed
driver.initClusters([
{ id: "one", cites: [ {id: "citekey"} ] },
{ id: "two", cites: [ {id: "citekey", locator: "56", label: "page" } ] },
]);
// Update or insert any one of them like so
driver.insertCluster({ id: "one", cites: [ { id: "updated_citekey" } ] });
// (You can use `driver.randomClusterId()` to generate a new one at random.)
let three = driver.randomClusterId();
driver.insertCluster({ id: three, cites: [ { id: "new_cluster_here" } ] });
这些集群不包含位置信息,所以重排是单独的 程序. 不拨打SetCluster命令,驱动程序会考虑文档 以入为空.
这么说吧, setClusterOrder 表示在
文档。 文件内的每一份都应列入本清单。 你可以跳过
注释号,表示两者之间没有引用脚注。 选择
note 意思是它是内文参考. 注意号必须是单调的 但你
可以在同一个脚注中有一个以上的组.
driver.setClusterOrder([ { id: "one", note: 1 }, { id: "two", note: 4 } ]);
您将注意到,如果一个交互式用户剪切并粘贴一段
,可以表示整个重排序操作
在两次呼叫中,一次在剪接后(略去一些分组),一次在
粘贴(在别处放置相同的组)。 没有打电话
insertCluster 需要这样做.
未引用项目
有时用户希望在书目中列入参考文献,尽管 这些文件的任何引用中都没有提及.
driver.includeUncited("None"); // Default
driver.includeUncited("All");
driver.includeUncited({ Specific: ["citekeyA", "citekeyB"] });
"All"是参考车手知道的 如果你有的话
此集为"All",只是调用 driver.insertReference() 带有新的
参考ID将导致在书目中添加一个条目。 条目
在特定模式中,当它们在这里提供时,不必存在;它们可以是,
例如,参考图书馆收集参考文献的引用
之后将全部提供给司机
列入书目,但不包括图书馆其他地方的项目.
3. 电话 driver.batchedUpdates() 并应用 diff
这样您就可以申请到您的文档 UI 。 它包括两个组 和文献目录条目.
// Get the diff since last time batchedUpdates, fullRender or drain was called.
let diff = driver.batchedUpdates();
// apply cluster changes to the UI.
// ("myDocument" is an imaginary API.)
for (let changedCluster of diff.clusters) {
let [id, html] = changedCluster;
myDocument.updateCluster(id, html);
}
// Null? No change to the bibliography.
if (diff.bibliography != null) {
let bib = diff.bibliography;
// Save the entries that have actually changed
for (let key of Object.keys(bib.updatedEntries)) {
let rendered = bib.updatedEntries[key];
myDocument.updateBibEntry(key, rendered);
}
// entryIds is the full list of entries in the bibliography.
// If a citekey isn't in there, it should be removed.
// It is non-null when it has changed.
if (bib.entryIds != null) {
myDocument.setBibliographyOrder(bib.entryIds);
}
}
注意,一些直觉,如果你打电话 batchedUpdates() 再次立即
diff会是空的.
文献目录
除了交互式批量更新方法之外,还有两种功能用于 以静态编制参考书目.
// returns BibliographyMeta, with information about how a library consumer should
// lay out the bibliography. There is a similar API in citeproc-js.
let meta = driver.bibliographyMeta();
// This is an array of BibEntry
let bibliography = driver.makeBibliography();
for (let entry of bibliography) {
console.log(entry.id, entry.value);
}
预览引用群集
有时,一个用户想要在编辑时看到集群的外观 在确认变化之前.
let cluster = { cites: [ { id: "citekey", locator: "45" }, { ... } ] };
let positions = [ ... before, { note: 34 }, ... after ];
let preview = driver.previewCluster(cluster, positions);
let plainPreview = driver.previewCluster(cluster, positions, "plain");
集群论点只是一个集群,没有 id 田间,因为它是
麻黄. 缺乏 id 字段在 positions 参数为
不错.
位置阵列就像呼叫 setClusterOrder,除了准确的
其中一个位置省略了 id 字段。 这可以:
- 替换现有集群的位置并预览集群替换;或
- 假设插入一个集群的位置.
如果你只通过一个位置, 它会像预览一个操作像
"删除整个文档,取而代之的是这个集群". 那会
意味着你永远不会在预览中看到"同上". 因此,为了最大效用,
组装位置阵列,如您要调用 setClusterOrder 与
正是您正在预览的操作.
格式参数是可选的,其作用方式类似传递到的格式
new Driver: 一个 "html", (中文(简体) ), "rtf" 或者说 "plain"。驱动程序将使用
而不是它的正常输出格式.
AuthorOnly, (中文(简体) ), SuppressAuthor 打开 Composite
@citeproc-rs/wasm 支持集群上的这些旗帜(所有3个)并引用(但
Composite),以类似方式 citeproc-js见 citeproc-js
关于特别引用的文件
表单
供参考.
// only two modes for cites
let citeAO = { id: "jones2006", mode: "AuthorOnly" };
let citeSA = { id: "jones2006", mode: "SuppressAuthor" };
// additional options for clusters
let clusterAO = { id: "one", cites: [...], mode: "AuthorOnly" };
let clusterSA = { id: "one", cites: [...], mode: "SuppressAuthor" };
let clusterSA_First = { id: "one", cites: [...], mode: "SuppressAuthor", suppressFirst: 3 };
let clusterC = { id: "one", cites: [...], mode: "Composite" };
let clusterC_Infix = { id: "one", cites: [...], mode: "Composite", infix: ", whose book" };
let clusterC_Full = { id: "one", cites: [...], mode: "Composite", infix: ", whose books", suppressFirst: 0 };
它确实支持一个额外的选项 : SuppressAuthor 财务报告和审定财务报表 Composite 打开
集群 : suppressFirst,将效果限制在第一个 N 名称组
(或者如果引用分组被禁用,第一个N名). 设定为0
无限.
<intext> 元素为 AuthorOnly 包括:.
citeproc-rs 支持 <intext> 中描述的元素 citeproc-js
上面链接的文档, 但默认无法启用 。 它还支持 <intext and="symbol"> 或者说 and="text",将交换最后的文本布局
分隔符( e)<layout delimiter="; ">) 用于水肿或 and
术语.
如果你想用这个 <intext> 在 CML 中,您可以选择:
选项 1: 在样式中添加要使用的特征标志
<style class="in-text">
<features>
<feature name="custom-intext" />
</features>
...
</style>
AFAIK 还没有其他处理器支持此语法 .
备选案文2:启用 custom-intext 所有样式的特性通过 new Driver
let driver = new Driver({ ..., cslFeatures: ["custom-intext"] });
// ... driver.free();
非交互使用, 或重水化先前创建的文档
如果您是在非互动工作, 或重新给先前创建的系统水分 文档供交互使用,您可能想要对所有分组进行一个通过 在文档中,使每组和书目条目反映 正确值.
// Get the clusters from your document (example)
let allNotes = myDocument.footnotes.map(fn => {
return { cluster: getCluster(fn), number: fn.number }
});
// Re-hydrate the entire document based on the reference library and your
// document's clusters
driver.resetReferences(myDocument.allReferences);
driver.initClusters(allNotes.map(fn => fn.cluster));
driver.setClusterOrder(allNotes.map(fn => { id: fn.cluster.id, note: fn.number }));
// Render every cluster and bibliography item.
// It then drains the update queue, leaving the diff empty for the next edit.
// see the FullRender typescript type
let render = driver.fullRender();
// Write out the rendered clusters into the doc
for (let fn of allNotes) {
fn.renderedHtml = render.allClusters[fn.cluster.id];
}
// Write out the bibliography entries as well
let allBibKeys = render.bibEntries.map(entry => entry.id);
for (let bibEntry of render.bibEntries) {
myDocument.bibliographyMap[entry.id] = entry.value;
}
// Update your (example) UI
updateUserInterface(allNotes, myDocument, whatever);
parseStyleMetadata
有时你想要关于 CSL 风格的信息而不实际启动 a
整个司机。 一种重要的用法是依赖式,不能使用
与 new Driver() 因为它没有能力 引用在
它本身,基本上只是三件信息的容器:
- 一个日记名称
- 独立父样式
- 可能的默认本地覆盖
@citeproc-rs/wasm 提供API,用于查找CSL样式文件中的内容.
let styleMeta = parseStyleMetadata("<style ...> ... </style>");
此函数仍然可以丢出 CslStyleError,但这比
使用新的驱动程序( ), 因为它不会真正试图解析和验证所有
样式的部分。 如果 XML 变形或 <info>
块太无效,无法保存.
这是如何使用 parseStyleMetadata 来分析并使用依赖的样式.
let dependentStyle = "<style ...> ... </style>";
let meta = parseStyleMetadata(dependentStyle);
let isDependent = meta.info.parent != null;
let parentStyleId = isDependent && meta.info.parent.href;
let localeOverride = meta.defaultLocale;
// ...
let parentStyle = await downloadStyleWithId(parentStyleId);
let driver = new Driver({
style: parentStyle,
localeOverride,
...
});
await driver.fetchLocales();
// Here you might also want to know if the style can render a bibliography or not
let parentMeta = parseStyleMetadata(parentStyle);
if (parentMeta.independentMeta.hasBibliography) {
let bib = driver.makeBibliography();
// ...
}
// ...
driver.free();
setOutputFormat 财务报告和审定财务报表 setStyle
如果您想要更改整个驱动程序的输出格式, 您可以使用
setOutputFormat(format, formatOptions)。格式为字符串,其中之一 "html" | "rtf" | "plain" 就像一个 new Driver 方法。 选项是可选的
参数,其数值与 formatOptions 内 new Driver。 。 。 .
setStyle(xmlString) 将更改驱动程序使用的 SSL 样式.
这两种方法都要求放弃几乎所有缓存计算, 所以请少用.
如果您需要以不同格式进行预览,则在
previewCluster 做这些。 它不会扔掉所有的
计算. citeproc-rs'混淆程序确实将格式化为:
账户,所以 <i>Title</i> 可区别于 <b>Title</b> 在HTML和RTF中,
但如果整个驱动程序输出格式是 "plain"因为他们都看
纯文本相同. previewCluster 将简单地翻译格式
以另一种格式,而不重新计算所有混淆.