hans / obsidian-citation-plugin

Obsidian plugin which integrates your academic reference manager with the Obsidian editor. Search your references from within Obsidian and automatically create and reference literature notes for papers and books.
MIT License
1.08k stars 81 forks source link

A template to insert (Pandoc-style) rendered citation #53

Open psyguy opened 3 years ago

psyguy commented 3 years ago

This pertains to #41 and #42, and I thought it's better to have an issue on its own (btw, I'd like to give #44 a push 😄 too):

I am using @{{citekey}} as note names, but I'd like to use aliases implemented from v0.9.16 unward. For instance, for the following bibtex entry:

@book{macdonald_1997_HiddenMarkovOther,
  title={Hidden Markov and other models for discrete-valued time series},
  author={MacDonald, Iain L and Zucchini, Walter},
  volume={110},
  year={1997},
  publisher={CRC Press}
}

have aliases as follows:

aliases:
  - Hidden Markov and other models for discrete-valued time series
  - (MacDonald & Zucchini, 1997)
  - MacDonald and Zucchini (1997)

{{title}} makes the first line, but cannot think of other templates for the other aliases; something like [@{{citekey}}] and @{{citekey}}.

Thanks in advance!

phlind commented 3 years ago

I'm interested in what you mean, but I can't really get what you want to achieve. Could you maybe explain what you mean with "but cannot think of other templates for the other aliases"? Thanks! :)

psyguy commented 3 years ago

Hey @phlind,

I mean, I am looking for a {{...}} handlebar/variable that can render citation strings (like Author1 and Author2, (1990); (Author1, Author2, 1990); or (Author1 et al., 2010); etc.).

I can then make something like this in the header template:

---
aliases:
  - {{title}}
  - {{citeRenderPromary}}
  - {citeRenderSecondary}}
---

to render this YAML:

---
aliases:
  - Hidden Markov and other models for discrete-valued time series
  - (MacDonald & Zucchini, 1997)
  - MacDonald and Zucchini (1997)
---
cbr9 commented 3 years ago

You can do something like this with Templater :)

This my template:

---
title: "{{title}}"
authors: "{{authorString}}"
year: {{year}}
zotero: "{{zoteroSelectURI}}"
publication: "{{containerTitle}}"
aliases:
- "<% `${tp.user.authorShort("{{authorString}}")}, ${"{{year}}"}` %>"
- "<% `${tp.user.authorShort("{{authorString}}")} (${"{{year}}"})` %>"
- "<% `${tp.user.authorLong("{{authorString}}")} (${"{{year}}"}). ${"{{title}}"}. ${"{{containerTitle}}"}.`%>"
---

tp.user.authorShort and tp.user.authorLong are the following two Templater scripts (each should go into its own file, and you need to tell Templater where to look for scripts; you also have to enable Trigger Templater on new file creation):

function authorShort(authorString) {
  const authors = authorString.split(", ");
  let abbrAuthorString = ""
  if (authors.length == 1) {
      const parts = authors[0].split(" ")
      abbrAuthorString = parts[parts.length-1];
  }
  else if (authors.length == 2) {
      let surnames = [];
      authors.forEach(author => {
        const parts = author.split(" ");
        surnames.push(parts[parts.length-1]);
      })
      abbrAuthorString = `${surnames[0]} and ${surnames[1]}`;
  } else {
      const first = authors[0].split(" ")
      const surname = first[first.length - 1];
      abbrAuthorString = `${surname} et al.`;
  }
  return abbrAuthorString
}

module.exports = authorShort;
function authorLong(authorString) {
  const authors = authorString.split(", ");
  let fullAuthorList = [];
  authors.forEach(author => {
      const parts = author.split(" ");
      let str = [];
      str.push(parts[parts.length-1]);
      const name_parts = parts.slice(0, parts.length-1);
      name_parts.forEach(name => {
        str.push(", ");
        str.push(`${name[0]}.`);
      });
      fullAuthorList.push(str.join(""))
  });
  return fullAuthorList.join(", ")
}

module.exports = authorLong;

I know this probably isn't perfect, but it's close enough to what you and I want :)

rxian commented 2 years ago

I added the following (among other minor edits) into main.js for auto-populating the alias in new lit notes with author-year citation:

Object.defineProperty(Entry.prototype, "authorYear", {
    get: function () {
        if (this.data.creators.author.length == 1)
            return this.data.creators.author[0].lastName + ', ' + this.data.fields.year
        else if (this.data.creators.author.length == 2)
            return this.data.creators.author[0].lastName + ' and ' + this.data.creators.author[1].lastName +  ', ' + this.data.fields.year
        else
            return this.data.creators.author[0].lastName + ' et al., ' + this.data.fields.year
    },
    enumerable: false,
    configurable: true
});

Although now I think cbr9's solution is neater.

iandalekelly commented 1 year ago

I might be a fool here, but this isn't working correctly for me: using the {{authorShort}} or {{authorLong}} variables as Markdown citations just seems to come up empty. All I have to do is create those two files tp.user.authorShort and tp.user.authorLong in the Template folder location and Trigger Templater on new file creation?