RelaxedJS / ReLaXed

Create PDF documents using web technologies
ISC License
11.8k stars 428 forks source link

Loading bibtex files for citations #74

Open will-hart opened 6 years ago

will-hart commented 6 years ago

Thanks for #27 / #64 💯

However, I'd love to be able to load bibtex files in so it fits with my standard workflow. I've discovered that I can read a bibtex file into a javascript variable like so:

mixin loadBibliography(path)
  - var tex = fs.readFileSync(path)
  script.
    var bib = '!{tex}'
    // or window.bibtex = ...

+loadBibliography("./bibliography.txt")

However I don't believe there is currently a way to pass it through to the bibliography generator. (Are there plans to add support for this? via plugins?)

A slightly dodgy way I suppose would be to save the bibtex to window.bibtex in our pug, and then I think we should be able to check for that variable in the generator. I'm not very familiar with puppeteer but I believe the generator could do something like

const bibtex = await page.evaluate(() => bibtex);
const data = new Cite(bibtex);

Thoughts?

will-hart commented 6 years ago

I've got a "demo" working here https://github.com/will-hart/ReLaXed/commit/ce4588d3415d3b0d401ad536eff8789ffbf7ca17. It does the job but I think it has slowed down compilation times a couple of seconds while the bibtex is parsed.

I've also added a "multiCite" command here https://github.com/will-hart/ReLaXed/commit/6d09c3b3a96e464ab6c480372733b5639de59c32

e.g.

  +multiCite('Q21972835', 'Zhang2009')

produces

image

Drew-S commented 6 years ago

The plan is to add a way to load a local bibliography library, currently I have not added one, as I have not tested how citation-js loads one, I developed it under the (probably false) assumption that citation-js would provide the entire bibtex file as the bibliography, regardless whether or not something was cited. As for loading the bibliography through the pug and then by finding it in page it would be better to have a normal file extension to look for, then bibliography will automatically load that.

var bibtex
if(fs.existsSync(path.join(masterPath, 'bibliography.txt')) {
    bibtex = fs.readFileSync(path.join(masterPath, 'bibliography.txt'))
}
if(bibFile) {
    const data = new Cite(bibtex)
} else {
    const data = new Cite()
}

The multicite is a nice touch, I had not thought of that before.

As I am working on the plugin system, loading a library would be done when activating the bibliography.

{
  "plugins": {
    "bibliography: {
      "enabled": true,
      "library": "path/to/file.txt"
      ...
     }
  }
}

Or via comments

//- use-plugin: bibliography library='path/to/file.txt'
will-hart commented 6 years ago

Oh yeah, oops I was trying so hard to include the bibtex into the Pug template I didn't even think of just reading in a file :) I'll give that a go.

Would you except a PR for one or both changes? Separate PRs?

EDIT: Also, yes citation.js does appear to put everything in the loaded file into the bibliography, even if there is no reference within the text.

Drew-S commented 6 years ago

That is how I understood citation-js working, I do not think there is much demand for such a feature, though it could be easily implemented to include an entire library, but for me, and most people I believe, we want to reference a global library containing all the material we referenced.

Since I use Zotero to automate grabbing of data and holding it a global library, I want to reference that library every time, but only include the data I actually selected. So a custom solution to filter out material not cited is needed. I would probably accept the multicite one as is, after I checked the tests. As for the bibtex, that should not be loaded in using pug, but instead through the bibliography module directly. It is up to you if you want to do separate PRs, you may want @Zulko to look over it as well.

Zulko commented 6 years ago

Lots to read, I'll try to follow :) Some questions and remarks:

@will-hart you can propose a PR, but it will have to be checked by both @Drew-S and me as I'm not 100% up to date with that part (I haven't tried it myself yet)

will-hart commented 6 years ago

It takes about 3 seconds extra to build a bibliography with only a couple of test references in the file. I'll try it later with my 900 reference monster list later to see if that makes it a lot worse :) Also, the increase in build seems to only occur if you include the +bibliography mixin, otherwise build times are unchanged.

Citation.js definitely includes everything in the bibfile in the exported bibliography, even if it wasn't cited. Another approach would be to use a separate Cite object to convert the file, then just copy references from it as we encounter them in the text to the main Cite object. I might have a quick look at how hard this might be to do.

I'll put in a PR for the multiCite tag, but hold off on the bibtex file stuff for now.

will-hart commented 6 years ago

I've noticed that even with the current implementation, multiple +cite calls to the same reference result in multiple bibliography entries. I think we'll need to check if a citation key has already been added to prevent this.

My tasks

Drew-S commented 6 years ago

Huh, in all my work I never did try citing the same code multiple times, I only tested two unique ones. You talk about having two Cite() objects one for duplicates, one for unique's. I am not fond of this method, as when you do add a new unique +cite, each object would make separate calls to get the info from online, so that should not happen for net calls. But for local libraries there needs to be a separate Cite() to read the data properly. Just something to take note of.