<commit_before>/*
 * bibliography-provider_zotero.ts
 *
 * Copyright (C) 2020 by RStudio, PBC
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */
import { Node as ProsemirrorNode } from 'prosemirror-model';

import { ZoteroCollection, ZoteroServer, kZoteroBibLaTeXTranslator, kZoteroMyLibrary } from "../zotero";

import { ParsedYaml } from "../yaml";
import { suggestCiteId } from "../cite";

import { BibliographyDataProvider, BibliographySource, BibliographyFile } from "./bibliography";
import { EditorUI } from '../ui';
import { CSL } from '../csl';
import { toBibLaTeX } from './bibDB';

export const kZoteroItemProvider = 'Zotero';

export class BibliographyDataProviderZotero implements BibliographyDataProvider {

  private collections: ZoteroCollection[] = [];
  private server: ZoteroServer;

  public constructor(server: ZoteroServer) {
    this.server = server;
  }

  public name: string = "Zotero";

  public async load(docPath: string, _resourcePath: string, yamlBlocks: ParsedYaml[]): Promise<boolean> {

    let hasUpdates = false;
    if (zoteroEnabled(docPath, yamlBlocks)) {

      try {

        // Don't send the items back through to the server
        const collectionSpecs = this.collections.map(({ items, ...rest }) => rest);

        const useCache = true;

        // TODO: remove collection names from server call
        const result = await this.server.getCollections(docPath, null, collectionSpecs || [], useCache);
        if (result.status === "ok") {

          if (result.message) {

            const newCollections = (result.message as ZoteroCollection[]).map(collection => {
              const existingCollection = this.collections.find(col => col.name === collection.name);
              if (useCache && existingCollection && existingCollection.version === collection.version) {
                collection.items = existingCollection.items;
              } else {
                hasUpdates = true;
              }
              return collection;

            });
            hasUpdates = hasUpdates || newCollections.length !== this.collections.length;
            this.collections = newCollections;
          }
        } else {
          // console.log(result.status);
        }
      }
      catch (err) {
        // console.log(err);
      }
    } else {
      // Zotero is disabled, clear any already loaded bibliography
      if (this.collections.length > 0) {
        hasUpdates = true;
      }
      this.collections = [];
    }
    return hasUpdates;
  }

  public containers(doc: ProsemirrorNode, ui: EditorUI): string[] {
    return this.collections.map(collection => collection.name);
  }

  public items(): BibliographySource[] {
    const entryArrays = this.collections?.map(collection => this.bibliographySources(collection)) || [];
    const zoteroEntries = ([] as BibliographySource[]).concat(...entryArrays);
    return zoteroEntries;
  }

  public bibliographyPaths(doc: ProsemirrorNode, ui: EditorUI): BibliographyFile[] {
    return [];
  }

  public async generateBibLaTeX(ui: EditorUI, id: string, csl: CSL): Promise<string | undefined> {
    if (csl.key && ui.prefs.zoteroUseBetterBibtex) {
      const bibLaTeX = await this.server.betterBibtexExport([csl.key], kZoteroBibLaTeXTranslator, kZoteroMyLibrary);
      if (bibLaTeX) {
        return Promise.resolve(bibLaTeX.message);
      }
    }
    return Promise.resolve(toBibLaTeX(id, csl));
  }


  private bibliographySources(collection: ZoteroCollection): BibliographySource[] {

    const items = collection.items?.map(item => {
      return {
        ...item,
        id: item.id || suggestCiteId([], item),
        provider: kZoteroItemProvider,
      };
    });
    return items || [];
  }
}
<commit_msg>Use the BBT preference properly<commit_after>/*
 * bibliography-provider_zotero.ts
 *
 * Copyright (C) 2020 by RStudio, PBC
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */
import { Node as ProsemirrorNode } from 'prosemirror-model';

import { ZoteroCollection, ZoteroServer, kZoteroBibLaTeXTranslator, kZoteroMyLibrary } from "../zotero";

import { ParsedYaml } from "../yaml";
import { suggestCiteId } from "../cite";

import { BibliographyDataProvider, BibliographySource, BibliographyFile } from "./bibliography";
import { EditorUI } from '../ui';
import { CSL } from '../csl';
import { toBibLaTeX } from './bibDB';

export const kZoteroItemProvider = 'Zotero';

export class BibliographyDataProviderZotero implements BibliographyDataProvider {

  private collections: ZoteroCollection[] = [];
  private server: ZoteroServer;

  public constructor(server: ZoteroServer) {
    this.server = server;
  }

  public name: string = "Zotero";

  public async load(docPath: string, _resourcePath: string, yamlBlocks: ParsedYaml[]): Promise<boolean> {

    let hasUpdates = false;
    if (zoteroEnabled(docPath, yamlBlocks)) {

      try {

        // Don't send the items back through to the server
        const collectionSpecs = this.collections.map(({ items, ...rest }) => rest);

        const useCache = true;

        // TODO: remove collection names from server call
        const result = await this.server.getCollections(docPath, null, collectionSpecs || [], useCache);
        if (result.status === "ok") {

          if (result.message) {

            const newCollections = (result.message as ZoteroCollection[]).map(collection => {
              const existingCollection = this.collections.find(col => col.name === collection.name);
              if (useCache && existingCollection && existingCollection.version === collection.version) {
                collection.items = existingCollection.items;
              } else {
                hasUpdates = true;
              }
              return collection;

            });
            hasUpdates = hasUpdates || newCollections.length !== this.collections.length;
            this.collections = newCollections;
          }
        } else {
          // console.log(result.status);
        }
      }
      catch (err) {
        // console.log(err);
      }
    } else {
      // Zotero is disabled, clear any already loaded bibliography
      if (this.collections.length > 0) {
        hasUpdates = true;
      }
      this.collections = [];
    }
    return hasUpdates;
  }

  public containers(doc: ProsemirrorNode, ui: EditorUI): string[] {
    return this.collections.map(collection => collection.name);
  }

  public items(): BibliographySource[] {
    const entryArrays = this.collections?.map(collection => this.bibliographySources(collection)) || [];
    const zoteroEntries = ([] as BibliographySource[]).concat(...entryArrays);
    return zoteroEntries;
  }

  public bibliographyPaths(doc: ProsemirrorNode, ui: EditorUI): BibliographyFile[] {
    return [];
  }

  public async generateBibLaTeX(ui: EditorUI, id: string, csl: CSL): Promise<string | undefined> {
    if (csl.key && ui.prefs.zoteroUseBetterBibtex()) {
      const bibLaTeX = await this.server.betterBibtexExport([csl.key], kZoteroBibLaTeXTranslator, kZoteroMyLibrary);
      if (bibLaTeX) {
        return Promise.resolve(bibLaTeX.message);
      }
    }
    return Promise.resolve(toBibLaTeX(id, csl));
  }


  private bibliographySources(collection: ZoteroCollection): BibliographySource[] {

    const items = collection.items?.map(item => {
      return {
        ...item,
        id: item.id || suggestCiteId([], item),
        provider: kZoteroItemProvider,
      };
    });
    return items || [];
  }
}

{'fraction_non_alphanumeric': 0.11333333333333333, 'fraction_numerical': 0.0019047619047619048, 'mean_word_length': 2.9721040189125296, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '537223', 'n_tokens_mistral': 2456, 'n_tokens_neox': 2333, 'n_words': 636}