#import "@preview/i-figured:0.2.3" #let count-words(it) = { let fn = repr(it.func()) if fn == "sequence" { it.children.map(count-words).sum() } else if fn == "heading" { count-words(it.body) } else if fn == "figure" { count-words(it.caption.body) } else if fn == "text" { it.text.split().len() } else if fn in ("styled") { count-words(it.child) } else if fn in ("highlight", "item", "strong", "link") { count-words(it.body) } else if fn == "equation" { 1 } else { 0 } } #let lapreprint( // The paper's title. title: "Paper Title", subtitle: none, // An array of authors. For each author you can specify a name, orcid, and affiliations. // affiliations should be content, e.g. "1", which is shown in superscript and should match the affiliations list. // Everything but but the name is optional. authors: (), // This is the affiliations list. Include an id and `name` in each affiliation. These are shown below the authors. affiliations: (), // The paper's abstract. Can be omitted if you don't have one. abstract: none, // The short-title is shown in the running header short-title: none, // The short-citation is shown in the running header, if set to auto it will show the author(s) and the year in APA format. short-citation: auto, // The venue is show in the footer venue: none, // An image path that is shown in the top right of the page. Can also be content. logo: none, // A DOI link, shown in the header on the first page. Should be just the DOI, e.g. `10.10123/123456` ,not a URL doi: none, heading-numbering: "1.a.i", // Show an Open Access badge on the first page, and support open science, default is true, because that is what the default should be. open-access: true, // A list of keywords to display after the abstract keywords: (), // The "kind" of the content, e.g. "Original Research", this is shown as the title of the margin content on the first page. kind: none, // Content to put on the margin of the first page // Should be a list of dicts with `title` and `content` margin: (), paper-size: "us-letter", // A color for the theme of the document theme: blue.darken(30%), // Date published, for example, when you publish your preprint to an archive server. // To hide the date, set this to `none`. You can also supply a list of dicts with `title` and `date`. date: datetime.today(), // Feel free to change this, the font applies to the whole document font-face: "Noto Sans", // The path to a bibliography file if you want to cite some external works. bibliography-file: none, bibliography-style: "apa", // The outline outline-show: true, outline-depth: 2, // Language of the document lang: "en", // The paper's content. body ) = { /* Logos */ let orcidSvg = ``` ```.text let spacer = text(fill: gray)[#h(8pt) | #h(8pt)] let dates; if (type(date) == "datetime") { dates = ((title: "Published", date: date),) }else if (type(date) == "dictionary") { dates = (date,) } else { dates = date } date = dates.at(0).date // Create a short-citation, e.g. Cockett et al., 2023 let year = if (date != none) { ", " + date.display("[year]") } if (short-citation == auto and authors.len() == 1) { short-citation = authors.at(0).name.split(" ").last() + year } else if (short-citation == auto and authors.len() == 2) { short-citation = authors.at(0).name.split(" ").last() + " & " + authors.at(1).name.split(" ").last() + year } else if (short-citation == auto and authors.len() > 2) { short-citation = authors.at(0).name.split(" ").last() + " " + emph("et al.") + year } // Set document metadata. set document(title: title, author: authors.map(author => author.name)) if short-title == none { short-title = title } set page( paper-size, margin: (left: 20%, bottom: 1.5cm), header: locate(loc => { if(loc.page() == 1) { let headers = ( if (open-access) {smallcaps[Open Access]}, if (doi != none) { link("https://doi.org/" + doi, "https://doi.org/" + doi)} ) return align(left, text(size: 8pt, fill: gray, headers.filter(header => header != none).join(spacer))) } else { return align(right, text(size: 8pt, fill: gray.darken(50%), (short-title, short-citation).join(spacer) )) } }), footer: block( width: 100%, stroke: (top: 1pt + gray), inset: (top: 8pt, right: 2pt), [ #grid(columns: (75%, 25%), align(left, text(size: 9pt, fill: gray.darken(50%), ( if(venue != none) {emph(venue)}, if(date != none) { if (lang == "en") { date.display("[month repr:short] [day], [year]") } else { [#date.year() 年 #date.month() 月 #date.day() 日] } } ).filter(t => t != none).join(spacer) )), align(right)[ #text( size: 9pt, fill: gray.darken(50%) )[ #counter(page).display() of #locate((loc) => {counter(page).final(loc).first()}) ] ] ) ] ) ) // Set the body font. set text(font: font-face, size: 10pt) // Configure lists. set enum(indent: 10pt, body-indent: 9pt) set list(indent: 10pt, body-indent: 9pt) // Configure i-figured show figure: i-figured.show-figure show figure.where( kind: table ): set figure.caption(position: top) show math.equation: i-figured.show-equation // Configure Reference Link show link: it => [#text(fill: theme)[#it]] show ref: it => [#text(fill: theme)[#it]] show ref: it => { let el = it.element if (el != none) { let fn = repr(el.func()) if (fn == "equation") {link( it.target, if (lang == "en") {"Eq."} else {"式 "} + numbering( el.numbering, ..counter(math.equation).at(el.location()) ) )} else if (fn == "heading") {link( it.target, if (lang == "en") {"Section "} else {"第 "} + numbering( el.numbering, ..counter(heading).at(el.location()) ) + if (lang == "zh") {" 节"} )} else { it } } else {it} } // Configure headings. set heading(numbering: heading-numbering) show heading: it => locate(loc => { // Find out the final number of the heading counter. let levels = counter(heading).at(loc) set text(10pt, weight: 400) if it.level == 1 [ // First-level headings are centered smallcaps. // We don't want to number of the acknowledgment section. #let is-ack = it.body in ([Acknowledgment], [Acknowledgement]) // #set align(center) #set text(if is-ack { 10pt } else { 12pt }) #show: smallcaps #v(20pt, weak: true) #if it.numbering != none and not is-ack { numbering(heading-numbering, ..levels) h(7pt, weak: true) } #it.body #v(13.75pt, weak: true) #for kind in (image, table, raw) { counter(figure.where(kind: "i-figured-" + repr(kind))).update(0) } #counter(math.equation).update(0) ] else if it.level == 2 [ // Second-level headings are run-ins. #set par(first-line-indent: 0pt) #v(10pt, weak: true) #if it.numbering != none { numbering(heading-numbering, ..levels) h(7pt, weak: true) } #it.body #v(10pt, weak: true) ] else if it.level == 3 [ #set par(first-line-indent: 0pt) #v(10pt, weak: true) #if it.numbering != none { numbering(heading-numbering, ..levels) } #it.body #v(10pt, weak: true) ] else [ // Fourth level headings are run-ins too, but different. #set par(first-line-indent: 0pt) #if it.level >= 4 { numbering(heading-numbering, ..levels) } #it.body ] }) if (logo != none) { place( top, dx: -33%, float: false, box( width: 27%, { if (type(logo) == "content") { logo } else { image(logo, width: 100%) } }, ), ) } // Title and subtitle box(inset: (bottom: 2pt), text(17pt, weight: "bold", fill: theme, title)) if subtitle != none { parbreak() box(text(14pt, fill: gray.darken(30%), subtitle)) } // Authors and affiliations linebreak() if authors.len() > 0 { box(inset: (y: 10pt), { authors.map(author => { text(11pt, weight: "semibold", author.name) h(1pt) if "affiliations" in author { super(author.affiliations) } if "orcid" in author { link("https://orcid.org/" + author.orcid)[#box(height: 1.1em, baseline: 13.5%)[#image.decode(orcidSvg)]] } }).join(", ", last: ", and ") }) } if affiliations.len() > 0 { linebreak() box(inset: (bottom: 10pt), { affiliations.map(affiliation => { super(affiliation.id) h(1pt) affiliation.name }).join(", ") }) } place( left + bottom, dx: -25%, dy: -10pt, box(width: 22%, { if (kind != none) { show par: set block(spacing: 0em) text(11pt, fill: theme, weight: "semibold", smallcaps(kind)) parbreak() } if (dates != none) { let formatted-dates grid(columns: (40%, 60%), gutter: 7pt, ..dates.zip(range(dates.len())).map((formatted-dates) => { let d = formatted-dates.at(0); let i = formatted-dates.at(1); return ( if (i == 0){ strong[#text(size: 7pt, fill: theme, d.title)] } else { text(size: 7pt, fill: theme, d.title) }, if (lang == "en") { text(size: 7pt, d.date.display("[month repr:short] [day], [year]")) } else {[ #set text(7pt) #d.date.year()-#d.date.month()-#d.date.day() ]} ) }).flatten() ) } v(2em) grid(columns: 1, gutter: 2em, ..margin.map(side => { text(size: 7pt, { if ("title" in side) { text(fill: theme, weight: "bold", side.title) [\ ] } set enum(indent: 0.1em, body-indent: 0.25em) set list(indent: 0.1em, body-indent: 0.25em) side.content }) })) }), ) let abstracts if (type(abstract) == "content") { abstracts = (title: "Abstract", content: abstract) } else { abstracts = abstract } if abstracts != none { box(inset: (top: 16pt, bottom: 16pt), stroke: (top: 1pt + gray, bottom: 1pt + gray), { abstracts.map(abs => { set par(justify: true) text(fill: theme, weight: "semibold", size: 9pt, abs.title) parbreak() abs.content }).join(parbreak()) }) if (keywords.len() > 0) { text(size: 9pt, { if (lang == "en") { text(fill: theme, weight: "semibold", "Keywords") } else { text(fill: theme, weight: "semibold", "关键词") } h(8pt) keywords.join(", ") }) } v(10pt) } if (outline-show) {outline( title: if (lang == "en") {"Content"} else {"目录"}, indent: 2em, depth: outline-depth, )} pagebreak() // Display the paper's contents. show par: set block(spacing: 1.5em) set page( margin: (left: auto, bottom: 1.5cm), ) // show: rest => { // let n = count-words(rest) // if (lang == "en") { // rest + align(right, [(#n words)]) // } else { // rest + align(right, [(#n 字)]) // } // } body if (bibliography-file != none) { show bibliography: set text(8pt) bibliography(bibliography-file, title: text(10pt, "References"), style: bibliography-style) } }