├── frontend ├── .nvmrc ├── .stylelintrc ├── babel.config.cjs ├── .eslintrc ├── rollup.config.js ├── src │ ├── utils.js │ ├── AppState.js │ ├── zsr.js │ └── AppComponent.js ├── package.json └── scss │ └── style.scss ├── htdocs ├── styles-files │ ├── css │ ├── js │ └── previews │ │ ├── index.html │ │ ├── bib │ │ └── .gitignore │ │ ├── citation │ │ └── .gitignore │ │ └── combined │ │ └── .gitignore ├── .htaccess └── styles.php ├── scripts ├── schema │ └── .gitignore ├── fetch-schema ├── bbgen ├── generate-json ├── generate-index └── generate-previews ├── styles ├── data │ └── .gitignore ├── local │ └── .gitignore └── .gitignore ├── .gitignore ├── include ├── config.inc.php-sample ├── Styles.inc.php ├── static.inc.php ├── data │ └── previews.json ├── Styles_Preview.inc.php ├── Styles_Repo.inc.php ├── bluebook-19th.csl └── renamed-styles.json ├── README.md └── views └── index.phtml /frontend/.nvmrc: -------------------------------------------------------------------------------- 1 | lts/gallium -------------------------------------------------------------------------------- /htdocs/styles-files/css: -------------------------------------------------------------------------------- 1 | ../../frontend/build/css -------------------------------------------------------------------------------- /htdocs/styles-files/js: -------------------------------------------------------------------------------- 1 | ../../frontend/build/js -------------------------------------------------------------------------------- /htdocs/styles-files/previews/index.html: -------------------------------------------------------------------------------- 1 | Error generating preview 2 | -------------------------------------------------------------------------------- /frontend/.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "stylelint-config-standard-scss" 3 | } -------------------------------------------------------------------------------- /scripts/schema/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /styles/data/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /styles/local/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /htdocs/styles-files/previews/bib/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /htdocs/styles-files/previews/citation/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /htdocs/styles-files/previews/combined/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /styles/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | # And these subdirectories 6 | !original 7 | !local 8 | !data 9 | -------------------------------------------------------------------------------- /frontend/babel.config.cjs: -------------------------------------------------------------------------------- 1 | const presets = [ 2 | ["@babel/preset-env", { 3 | "debug": !!process.env.DEBUG || false, 4 | "corejs": { version: 3 }, 5 | "useBuiltIns": "usage" 6 | }] 7 | ]; 8 | 9 | module.exports = { presets }; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | include/config.inc.php 2 | scripts/schema/* 3 | scripts/trang.jar 4 | htdocs/styles-files/previews/*.html 5 | !htdocs/styles-files/previews/index.html 6 | htdocs/styles-files/styles.json 7 | frontend/build 8 | frontend/node_modules 9 | .DS_Store -------------------------------------------------------------------------------- /frontend/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "globals": {}, 4 | "parser": "@babel/eslint-parser", 5 | "env": { 6 | "browser": true, 7 | "node": true, 8 | "es6": true 9 | }, 10 | "parserOptions": { 11 | "ecmaVersion": 8, 12 | "sourceType": "module" 13 | }, 14 | "extends": [ 15 | "eslint:recommended" 16 | ] 17 | } -------------------------------------------------------------------------------- /scripts/fetch-schema: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | DIR="`dirname $0`/schema" 3 | SCHEMA_URL="https://github.com/citation-style-language/schema/raw/v1.0.1/" 4 | 5 | cd $DIR 6 | for i in csl-categories csl-data csl-terms csl-types csl-variables csl; 7 | do 8 | wget -q --no-check-certificate "${SCHEMA_URL}${i}.rnc" 9 | done 10 | 11 | /usr/bin/java -jar ../trang.jar csl.rnc csl.rng 12 | 13 | rm csl*.rnc 14 | -------------------------------------------------------------------------------- /include/config.inc.php-sample: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /htdocs/.htaccess: -------------------------------------------------------------------------------- 1 | Options +MultiViews 2 | 3 | php_flag zlib.output_compression On 4 | php_value zlib.output_compression_level 5 5 | 6 | php_value date.timezone "UTC" 7 | 8 | # Versioned static files 9 | RewriteEngine On 10 | RewriteRule (styles-files/.+)\.(\d{10})\.(\w{2,4})$ $1.$3 [L] 11 | 12 | # Performance tweaks: gzip, far-future expires, no etags 13 | AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/x-javascript text/javascript application/javascript 14 | 15 | ExpiresActive on 16 | ExpiresDefault "access plus 1 day" 17 | 18 | 19 | 20 | Header set Access-Control-Allow-Origin "*" 21 | Header set Access-Control-Allow-Headers "If-Modified-Since" 22 | ExpiresActive on 23 | ExpiresDefault "access plus 1 minute" 24 | 25 | 26 | 27 | ExpiresActive on 28 | ExpiresDefault "access plus 1 hour" 29 | 30 | 31 | FileETag none 32 | -------------------------------------------------------------------------------- /include/Styles.inc.php: -------------------------------------------------------------------------------- 1 | . 23 | 24 | ***** END LICENSE BLOCK ***** 25 | */ 26 | 27 | class Styles { 28 | public static $debug = true; 29 | 30 | public static function log($str) { 31 | if (self::$debug) { 32 | error_log($str); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /include/static.inc.php: -------------------------------------------------------------------------------- 1 | . 23 | 24 | ***** END LICENSE BLOCK ***** 25 | */ 26 | 27 | function staticFile($relPath) { 28 | $basePath = ROOT_PATH . 'htdocs'; 29 | $file = $basePath . $relPath; 30 | if (!file_exists($file)) { 31 | return $relPath; 32 | } 33 | return str_replace($basePath, "", preg_replace('/(.+)(\.[\w]{2,4})$/', '$1.' . filemtime($file) . '$2', $file)); 34 | } 35 | ?> 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Installation 2 | ------------ 3 | 4 | cp include/config.inc.php-sample include/config.inc.php 5 | 6 | cd scripts 7 | 8 | Extract Trang binary to current directory: 9 | 10 | wget http://jing-trang.googlecode.com/files/trang-20081028.zip 11 | unzip -ej trang-20081028.zip trang-20081028/trang.jar 12 | rm trang-20081028.zip 13 | 14 | Install other prerequisites: 15 | 16 | * apache2 17 | * php5, php5-curl 18 | * java 19 | * xmllint (part of libxml2-utils package) 20 | * [citeproc-node](https://github.com/zotero/citeproc-node) 21 | 22 | Configure apache2 23 | 24 | * In addition to the default setup, the following modules must be enabled: 25 | * mod_rewrite 26 | * mod_expires 27 | * Apache must be configured to allow overrides of the following options in .htaccess 28 | * MultiViews 29 | 30 | Run setup scripts: 31 | 32 | ./fetch-schema 33 | ./generate-index 34 | ./generate-previews 35 | ./generate-json 36 | 37 | Set generate-index, generate-previews and generate-json to run periodically via cron. 38 | 39 | The main page for the style repository is "/htdocs/styles.php". Configure paths and citeproc URL in "/include/config.inc.php" 40 | 41 | 42 | Frontend 43 | -------- 44 | 45 | To work on the frontend of the application run `npm install` followed by `npm start` inside the **frontend** directory. This will generate development version of the frontend library with additional metrics and debug infromation. These files should not be checked in into the repository, instead use `npm run build` to produce distribution ready files. -------------------------------------------------------------------------------- /frontend/rollup.config.js: -------------------------------------------------------------------------------- 1 | import babel from '@rollup/plugin-babel'; 2 | import commonjs from '@rollup/plugin-commonjs'; 3 | import filesize from 'rollup-plugin-filesize'; 4 | import replace from '@rollup/plugin-replace'; 5 | import resolve from '@rollup/plugin-node-resolve'; 6 | import sizes from 'rollup-plugin-sizes'; 7 | import { terser } from 'rollup-plugin-terser'; 8 | 9 | const isProduction = process.env.NODE_ENV?.startsWith('prod'); 10 | 11 | const config = { 12 | input: './src/zsr.js', 13 | output: { 14 | name: 'ZSR', 15 | dir: './build/js', 16 | format: 'umd', 17 | sourcemap: !isProduction, 18 | compact: isProduction 19 | }, 20 | treeshake: { 21 | moduleSideEffects: 'no-external', 22 | }, 23 | plugins: [ 24 | resolve({ 25 | preferBuiltins: false, 26 | mainFields: ['browser', 'module', 'main'], 27 | extensions: ['.js', '.jsx', '.wasm'], 28 | }), 29 | commonjs(), 30 | replace({ 31 | preventAssignment: true, 32 | 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV ?? 'development'), 33 | }), 34 | babel({ 35 | exclude: "node_modules/**", 36 | extensions: ['.js', '.jsx'], 37 | babelHelpers: 'bundled' 38 | }), 39 | filesize({ showMinifiedSize: false, showGzippedSize: !!process.env.DEBUG }), 40 | ] 41 | }; 42 | 43 | if (process.env.DEBUG) { 44 | config.plugins.splice(-1, 0, sizes()); 45 | } 46 | 47 | if (isProduction) { 48 | config.plugins.push(terser({ safari10: true })); 49 | } 50 | 51 | export default config; 52 | -------------------------------------------------------------------------------- /frontend/src/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Finds the first element that pasess function test by testing the element itself 3 | * and traversing up 4 | * @param {HTMLElement} el - A DOM element from which tracersing begins 5 | * @param {Function} fn - Function that tests if element is suitable 6 | * @return {HTMLElement} - First element that passes the test 7 | */ 8 | export function closest(el, fn) { 9 | return el && (fn(el) ? el : closest(el.parentNode, fn)); 10 | } 11 | 12 | /** 13 | * Port of PHP's number_format() 14 | * 15 | * MIT Licensed 16 | * 17 | * From http://kevin.vanzonneveld.net 18 | * + original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com) 19 | * + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) 20 | * + bugfix by: Michael White (http://getsprink.com) 21 | * + bugfix by: Benjamin Lupton 22 | * + bugfix by: Allan Jensen (http://www.winternet.no) 23 | * + revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com) 24 | * + bugfix by: Howard Yeend 25 | * * example 1: number_format(1234.5678, 2, '.', ''); 26 | * * returns 1: 1234.57 27 | */ 28 | export function numberFormat(number, decimals = 0, dec_point, thousands_sep) { 29 | var n = number, c = isNaN(decimals = Math.abs(decimals)) ? 2 : decimals; 30 | var d = dec_point == undefined ? "." : dec_point; 31 | var t = thousands_sep == undefined ? "," : thousands_sep, s = n < 0 ? "-" : ""; 32 | var i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", j = (j = i.length) > 3 ? j % 3 : 0; 33 | 34 | return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : ""); 35 | } 36 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zotero-styles-repo", 3 | "license": "AGPL", 4 | "version": "0.2.0", 5 | "description": "", 6 | "private": true, 7 | "repository": "", 8 | "browserslist": "firefox >= 68, chrome >=67, edge >= 15, safari >= 10, last 2 versions, not dead, ie 11", 9 | "type": "module", 10 | "scripts": { 11 | "build": "NODE_ENV=production run-p 'build:js -s' 'build:scss -s' && npm run build:postprocess", 12 | "build:js": "mkdir -p build/static && NODE_ENV=production rollup -c", 13 | "build:scss": "for f in scss/*.scss; do sass --no-source-map $f build/css/`basename $f .scss`.css; done;", 14 | "clean": "rimraf build lang", 15 | "devel:js": "rollup -c -w", 16 | "devel:scss": "for f in scss/*.scss; do sass --embed-source-map --watch $f build/css/`basename $f .scss`.css; done;", 17 | "build:postprocess": "postcss build/css/style.css --use autoprefixer --use cssnano --no-map -r", 18 | "start": "mkdir -p build && run-p 'devel:js -s' 'devel:scss -s'" 19 | }, 20 | "dependencies": { 21 | "@rollup/plugin-babel": "^5.3.1", 22 | "@rollup/plugin-commonjs": "^22.0.1", 23 | "@rollup/plugin-node-resolve": "^13.3.0", 24 | "@rollup/plugin-replace": "^4.0.0", 25 | "core-js": "^3.23.5", 26 | "lodash": "^4.17.21", 27 | "rollup-plugin-filesize": "^9.1.2", 28 | "rollup-plugin-sizes": "^1.0.4", 29 | "rollup-plugin-terser": "^7.0.2", 30 | "tether-drop": "^1.4.2", 31 | "vidom": "=0.1.7", 32 | "whatwg-fetch": "^3.6.2" 33 | }, 34 | "devDependencies": { 35 | "@babel/core": "^7.18.9", 36 | "@babel/eslint-parser": "^7.18.9", 37 | "@babel/plugin-transform-runtime": "^7.18.9", 38 | "@babel/preset-env": "^7.18.9", 39 | "autoprefixer": "^10.4.7", 40 | "cssnano": "^5.1.12", 41 | "eslint": "^8.20.0", 42 | "npm-run-all": "^4.1.5", 43 | "postcss": "^8.4.14", 44 | "postcss-cli": "^10.0.0", 45 | "rimraf": "^3.0.2", 46 | "rollup": "^2.77.0", 47 | "sass": "^1.53.0", 48 | "stylelint": "^14.9.1", 49 | "stylelint-config-recommended-scss": "^7.0.0", 50 | "stylelint-config-standard": "^26.0.0", 51 | "stylelint-scss": "^4.3.0" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /scripts/generate-json: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php 2 | . 24 | 25 | ***** END LICENSE BLOCK ***** 26 | */ 27 | 28 | error_reporting(E_ALL); 29 | ini_set("display_errors", true); 30 | 31 | ini_set('include_path', '.:' . dirname(dirname(__FILE__)) . '/include'); 32 | require('config.inc.php'); 33 | require('Styles.inc.php'); 34 | require("Styles_Repo.inc.php"); 35 | 36 | $targetPath = ROOT_PATH . 'htdocs/styles-files/styles.json'; 37 | 38 | $cacheValues = Styles_Repo::getCacheValues(); 39 | $styleList = Styles_Repo::getAllStyles(); 40 | $mainURI = 'https://www.zotero.org/styles'; 41 | 42 | 43 | usort($styleList, function($a, $b) { 44 | $collator = new Collator('en_US'); 45 | return $collator->compare($a['title'], $b['title']); 46 | }); 47 | 48 | $stylesData = []; 49 | foreach($styleList as $key => $style) { 50 | $styleData = []; 51 | date_default_timezone_set('UTC'); 52 | $styleData['title'] = $styleList[$key]['title']; 53 | if($styleList[$key]['titleShort']) { 54 | $styleData['titleShort'] = $styleList[$key]['titleShort']; 55 | } 56 | $styleData['name'] = $styleList[$key]['name']; 57 | $styleData['dependent'] = $styleList[$key]['dependent']; 58 | $styleData['categories'] = $styleList[$key]['categories']; 59 | $styleData['updated'] = date("Y-m-d H:i:s", strtotime($styleList[$key]['updated'])); 60 | $styleData['href'] = $mainURI . (substr($mainURI, -1) == '/' ? '' : '/') . $styleList[$key]['name']; 61 | $stylesData[] = $styleData; 62 | } 63 | 64 | file_put_contents($targetPath, json_encode($stylesData)); 65 | ?> -------------------------------------------------------------------------------- /frontend/src/AppState.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Maintains the state of the application and informs registered handlers 3 | * of any changes that occurred. Also updates current URL to reflect the 4 | * state of the application 5 | */ 6 | export default class AppState { 7 | constructor(properties) { 8 | this._changeHandlers = []; 9 | this.setState(properties); 10 | } 11 | 12 | /** 13 | * Register handler. Handlers are called when state change occurs. 14 | * @param {Function} callback - A callback function to call on change 15 | */ 16 | onChange(callback) { 17 | this._changeHandlers.push(callback); 18 | } 19 | 20 | /** 21 | * Updates current state of the application 22 | * @param {Object} properties - new status properties 23 | * @param {[type]} silent - whether this update should be silent. History is 24 | * not updated on silent updates. 25 | */ 26 | setState(properties, silent) { 27 | let diff = []; 28 | for(let i=0, keys=Object.keys(properties); i handler(diff, this)); 36 | if(window.history && window.history.replaceState) { 37 | let historyEntry = []; 38 | if(properties.query.id && properties.query.id.length) { 39 | historyEntry.push(`id=${encodeURIComponent(properties.query.id)}`); 40 | } 41 | 42 | if(properties.query.search && properties.query.search.length) { 43 | historyEntry.push(`q=${encodeURIComponent(properties.query.search)}`); 44 | } 45 | 46 | if(properties.query.fields && properties.query.fields.length) { 47 | historyEntry.push(`fields=${encodeURIComponent(properties.query.fields)}`); 48 | } 49 | 50 | if(properties.query.format && properties.query.format.length) { 51 | historyEntry.push(`format=${encodeURIComponent(properties.query.format)}`); 52 | } 53 | 54 | if(typeof properties.query.dependent !== 'undefined' && properties.query.dependent !== null) { 55 | historyEntry.push(`dependent=${encodeURIComponent(properties.query.dependent)}`); 56 | } 57 | 58 | // Fails in XUL browser in Firefox 60, so wrap in try/catch 59 | try { 60 | window.history.replaceState( 61 | null, 62 | '', 63 | window.location.pathname 64 | + (historyEntry.length ? '?' + historyEntry.join('&') : '') 65 | + window.location.hash 66 | ); 67 | } 68 | catch (e) {} 69 | } 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /views/index.phtml: -------------------------------------------------------------------------------- 1 | . 22 | 23 | ***** END LICENSE BLOCK ***** 24 | */ 25 | ?> 26 | 27 | 28 | 29 | 30 | Zotero Style Repository 31 | 32 | 33 | 34 | 35 |
36 |

Zotero Style Repository

38 |

Here you can find Citation Style Language 1.0.2 citation styles for use with Zotero and other CSL 1.0.2–compatible software. For more information on using CSL styles with Zotero, see the Zotero wiki.

39 |
40 |
41 |
42 |
43 |

Style Search

44 |

45 | 46 |

47 |

48 |   49 |

50 |
51 |
52 |

Format:Loading…

53 |

Fields:Loading…

54 |
55 |
56 |
57 |
    58 |
    59 |
    60 |
    61 | 62 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /include/data/previews.json: -------------------------------------------------------------------------------- 1 | { 2 | "items": [{ 3 | "id": 3886, 4 | "type": "article-journal", 5 | "title": "An adaptable metric shapes perceptual space", 6 | "container-title": "Current Biology", 7 | "page": "1911-1915", 8 | "volume": "26", 9 | "issue": "14", 10 | "source": "www.cell.com", 11 | "URL": "http://www.cell.com/current-biology/abstract/S0960-9822(16)30544-9", 12 | "DOI": "10.1016/j.cub.2016.05.047", 13 | "ISSN": "0960-9822", 14 | "journalAbbreviation": "Curr. Biol.", 15 | "language": "en", 16 | "author": [{ 17 | "family": "Hisakata", 18 | "given": "Rumi" 19 | }, { 20 | "family": "Nishida", 21 | "given": "Shin'ya" 22 | }, { 23 | "family": "Johnston", 24 | "given": "Alan" 25 | }], 26 | "issued": { 27 | "date-parts": [ 28 | [ 29 | "2016", 30 | 7, 31 | 25 32 | ] 33 | ] 34 | }, 35 | "accessed": { 36 | "date-parts": [ 37 | [ 38 | "2016", 39 | 10, 40 | 3 41 | ] 42 | ] 43 | } 44 | }, { 45 | "id": 3884, 46 | "type": "post-weblog", 47 | "container-title": "Hyperbole and a Half", 48 | "title": "The Alot is Better Than You at Everything", 49 | "URL": "https://hyperboleandahalf.blogspot.com/2010/04/alot-is-better-than-you-at-everything.html", 50 | "author": [ 51 | { 52 | "family": "Brosh", 53 | "given": "Allie" 54 | } 55 | ], 56 | "accessed": { 57 | "date-parts": [ 58 | [ 59 | "2018", 60 | 2, 61 | 6 62 | ] 63 | ] 64 | }, 65 | "issued": { 66 | "date-parts": [ 67 | [ 68 | "2010", 69 | 4, 70 | 13 71 | ] 72 | ] 73 | } 74 | }, { 75 | "id": 3881, 76 | "type": "chapter", 77 | "title": "Structure databases", 78 | "container-title": "Bioinformatics", 79 | "collection-title": "Life Sciences Series", 80 | "publisher": "Wiley-Interscience", 81 | "publisher-place": "New York, NY", 82 | "page": "83-109", 83 | "edition": "2", 84 | "event-place": "New York, NY", 85 | "ISBN": "0471383910", 86 | "language": "en-US", 87 | "author": [{ 88 | "family": "Hogue", 89 | "given": "Christopher W. V." 90 | }], 91 | "editor": [{ 92 | "family": "Baxevanis", 93 | "given": "Andreas D." 94 | }, { 95 | "family": "Ouellette", 96 | "given": "B. F. Francis" 97 | }], 98 | "issued": { 99 | "date-parts": [ 100 | [ 101 | "2001" 102 | ] 103 | ] 104 | } 105 | }, { 106 | "id": 3877, 107 | "type": "book", 108 | "title": "Molecular cloning: a laboratory manual", 109 | "publisher": "CSHL Press", 110 | "publisher-place": "Cold Spring Harbor, NY", 111 | "number-of-pages": "999", 112 | "edition": "3", 113 | "event-place": "Cold Spring Harbor, NY", 114 | "ISBN": "0879695773", 115 | "shortTitle": "Molecular cloning", 116 | "language": "en-US", 117 | "author": [{ 118 | "family": "Sambrook", 119 | "given": "Joe" 120 | }, { 121 | "family": "Russell", 122 | "given": "David William" 123 | }], 124 | "issued": { 125 | "date-parts": [ 126 | [ 127 | "2001", 128 | 1, 129 | 15 130 | ] 131 | ] 132 | } 133 | }], 134 | "citationClusters": [{ 135 | "citationItems": [{ 136 | "id": 3886 137 | }, { 138 | "id": 3884 139 | }, { 140 | "id": 3881 141 | }, { 142 | "id": 3877 143 | }], 144 | "properties": { 145 | "noteIndex": 1 146 | } 147 | }] 148 | } 149 | -------------------------------------------------------------------------------- /htdocs/styles.php: -------------------------------------------------------------------------------- 1 | . 23 | 24 | ***** END LICENSE BLOCK ***** 25 | */ 26 | 27 | require('../include/config.inc.php'); 28 | require('../include/static.inc.php'); 29 | require('../include/Styles_Repo.inc.php'); 30 | 31 | $uri = $_SERVER['REQUEST_URI']; 32 | // Strip query string 33 | $mainURI = preg_replace('/\?.*/', '', $uri); 34 | 35 | if (strpos($uri, '/styles/?s=Harvard/') !== false) { 36 | header("HTTP/1.1 400 Bad Request"); 37 | echo "400 Bad Request"; 38 | exit; 39 | } 40 | 41 | // Set $PATH_INFO 42 | if (isset($_SERVER['PATH_INFO'])) { 43 | $PATH_INFO = explode('/', substr($_SERVER['PATH_INFO'], 1)); 44 | } 45 | if (!isset($PATH_INFO) || $PATH_INFO[0] == '') { 46 | $PATH_INFO = array(); 47 | } 48 | 49 | // Single style 50 | if (isset($PATH_INFO[0])) { 51 | header('Access-Control-Allow-Origin: *'); 52 | header('Access-Control-Allow-Headers: If-Modified-Since'); 53 | header('Cache-Control: max-age=900'); 54 | 55 | if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { 56 | header("HTTP/1.1 200 OK"); 57 | exit; 58 | } 59 | 60 | $name = $PATH_INFO[0]; 61 | $dependent = !empty($_GET['dep']); 62 | $source = !empty($_GET['source']); 63 | 64 | if (!Styles_Repo::isValidName($name) || isset($PATH_INFO[1])) { 65 | header("HTTP/1.1 404 Not Found"); 66 | exit; 67 | } 68 | 69 | $newName = Styles_Repo::getRenamedStyle($name); 70 | if ($newName && $name != $newName) { 71 | header("Location: $newName"); 72 | exit; 73 | } 74 | 75 | $csl = Styles_Repo::getCode($name, $dependent); 76 | // Dependent flag is optional 77 | if ($csl) { 78 | $lastModified = Styles_Repo::getLastModified($name, false); 79 | } 80 | else { 81 | $csl = Styles_Repo::getCode($name, true); 82 | $lastModified = Styles_Repo::getLastModified($name, true); 83 | } 84 | if ((isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) 85 | && $_SERVER['HTTP_IF_MODIFIED_SINCE'] == $lastModified)) { 86 | header("HTTP/1.1 304 Not Modified"); 87 | exit; 88 | } 89 | 90 | // Single style 91 | if (!empty($csl)) { 92 | header("Last-Modified: " . $lastModified); 93 | if (!empty($source)) { 94 | header('Content-Type: text/xml'); 95 | header("Content-Disposition: inline; filename=$name.csl"); 96 | } 97 | else { 98 | header('Content-Type: application/vnd.citationstyles.style+xml'); 99 | header("Content-Disposition: attachment; filename=$name.csl"); 100 | } 101 | echo $csl; 102 | } 103 | // Style not found 104 | else { 105 | header("HTTP/1.0 404 Not Found"); 106 | echo "Style not found"; 107 | } 108 | exit; 109 | } 110 | 111 | // Styles list 112 | $searchString = isset($_GET['q']) ? $_GET['q'] : ''; 113 | $client = !empty($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], "Zotero/") !== false; 114 | require("../views/index.phtml"); 115 | -------------------------------------------------------------------------------- /frontend/scss/style.scss: -------------------------------------------------------------------------------- 1 | $color: #000; 2 | 3 | $accent-color: #999; 4 | $accent-background-color: #f0f0f0; 5 | 6 | $popover-color: #000; 7 | $popover-background-color: #fff; 8 | $popover-box-shadow-color: rgba(0, 0, 0, .15); 9 | 10 | $view-source-button-color: #000; 11 | 12 | $search-pane-button-color: $color; 13 | $search-pane-button-border-color: $accent-color; 14 | $search-pane-button-background-color: $accent-background-color; 15 | $search-pane-button-hover-color: $color; 16 | $search-pane-button-hover-border-color: #6d95e0; 17 | $search-pane-button-hover-background-color: #bbcef1; 18 | $search-pane-button-active-color: #fff; 19 | $search-pane-button-active-border-color: rgb(89, 139, 236); 20 | $search-pane-button-active-background-color: rgb(89, 139, 236); 21 | $search-pane-button-active-hover-color: #fff; 22 | $search-pane-button-active-hover-border-color: rgb(109, 149, 224); 23 | $search-pane-button-active-hover-background-color: rgb(187, 206, 241); 24 | 25 | $search-pane-loading-indicator-color: #fff; 26 | $search-pane-loading-indicator-background-color: #b50000; 27 | 28 | body { 29 | color: $color; 30 | font-family: Georgia, "Times New Roman", Times, serif; 31 | margin: 0; 32 | padding: 0; 33 | } 34 | 35 | h1 { 36 | font-size: 1.7em; 37 | } 38 | 39 | 40 | h2 { 41 | font-size: 1.3em; 42 | margin: 0; 43 | top: 18px; 44 | } 45 | 46 | .page-wrapper { 47 | padding: 0 1em; 48 | } 49 | 50 | 51 | .search-pane { 52 | background: $accent-background-color; 53 | border: 1px $accent-color solid; 54 | display: flex; 55 | flex-direction: row; 56 | margin: 1em 0; 57 | max-width: 1010px; 58 | min-height: 140px; 59 | min-width: 720px; 60 | padding: 0 1em; 61 | position: relative; 62 | 63 | .fields-list, 64 | .formats-list { 65 | display: block; 66 | height: auto; 67 | list-style: none; 68 | overflow: hidden; 69 | width: 90%; 70 | 71 | li { 72 | background-color: $search-pane-button-background-color; 73 | border: 1px $search-pane-button-border-color solid; 74 | border-radius: 8px; 75 | color: $search-pane-button-color; 76 | cursor: default; 77 | display: inline-block; 78 | margin: 4px 7px 4px 0; 79 | padding: 3px 6px; 80 | 81 | &:hover { 82 | background-color: $search-pane-button-hover-background-color; 83 | border: 1px solid $search-pane-button-hover-border-color; 84 | color: $search-pane-button-hover-color; 85 | } 86 | 87 | &.field-active, 88 | &.format-active { 89 | background: $search-pane-button-active-background-color; 90 | border: 1px solid $search-pane-button-active-border-color; 91 | color: $search-pane-button-active-color; 92 | 93 | &:hover { 94 | background: $search-pane-button-active-hover-background-color; 95 | border: 1px solid $search-pane-button-active-hover-border-color; 96 | color: $search-pane-button-active-hover-color; 97 | } 98 | } 99 | } 100 | } 101 | } 102 | 103 | .search-pane-loading-indicator { 104 | background: $search-pane-loading-indicator-background-color; 105 | color: $search-pane-loading-indicator-color; 106 | display: none; 107 | margin: 0; 108 | padding: .1em .2em .2em .6em; 109 | position: absolute; 110 | right: 0; 111 | top: 0; 112 | 113 | .styles-processing & { 114 | display: block; 115 | } 116 | } 117 | 118 | 119 | .search-field { 120 | font-size: 16px; 121 | margin-top: 1em; 122 | max-width: 255px; 123 | width: 255px; 124 | } 125 | 126 | .style-list { 127 | li { 128 | display: inline-list-item; 129 | line-height: 1.2em; 130 | margin-bottom: .6em; 131 | } 132 | 133 | .metadata { 134 | font-size: .85em; 135 | margin-left: 1.5em; 136 | } 137 | } 138 | 139 | .search-pane-col-1 { 140 | flex: 0 0 260px; 141 | padding-top: 1.5em; 142 | } 143 | 144 | .search-pane-col-2 { 145 | max-width: calc(100% - 260px); 146 | 147 | p { 148 | display: flex; 149 | flex-direction: row; 150 | 151 | strong, 152 | span { 153 | min-width: 100px; 154 | padding-top: .5em; 155 | text-align: right; 156 | } 157 | 158 | ul { 159 | margin: 0; 160 | padding: 0 0 0 .5em; 161 | } 162 | } 163 | } 164 | 165 | .styles-loading { 166 | min-height: 50px; 167 | text-align: center; 168 | 169 | @at-root { 170 | @keyframes loading { 171 | to { 172 | transform: rotate(360deg); 173 | } 174 | } 175 | } 176 | 177 | &:after { 178 | animation: loading .75s steps(8, end) infinite; 179 | background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHZlcnNpb249IjEuMSIgeT0iMHB4IiB4PSIwcHgiIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgdmlld0JveD0iMCAwIDUwIDUwIj48cGF0aCBkPSJtMzUuODMgMy43NTljNC4zNzcgMi4yMjUgOC4wODYgNS44NiAxMC4yOSAxMC41M2wtMTAuMjEgNC42NDljLTAuODkwMi0yLjEyNy0yLjg0NC0zLjk1Ni01LjE2OC01LjExOWw1LjA5LTEwLjA2eiIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utd2lkdGg9Ii4zNTYxIiBjbGFzcz0ic3QxIi8+PGcgc3Ryb2tlPSIjZTdlN2U3IiBzdHJva2Utd2lkdGg9Ii4zNTYxIiBmaWxsPSIjZTdlN2U3Ij48cGF0aCBkPSJtNDcuNjcgMTcuNjNjMS41MzMgNC42NzMgMS41ODMgOS44NDEtMC4xNzMxIDE0LjcxbC0xMC41MS0zLjkwN2MwLjg2NTUtMi4xMjcgMC43NjY1LTQuNzk3LTAuMDQ5NDUtNy4yN2wxMC43My0zLjUzNnoiIGNsYXNzPSJzdDAiLz48cGF0aCBkPSJtNDYuMjQgMzUuODNjLTIuMjI1IDQuMzc3LTUuODYgOC4wODYtMTAuNTMgMTAuMjlsLTQuNjQ5LTEwLjE5YzIuMTI3LTAuODkwMiAzLjk1Ni0yLjg0NCA1LjExOS01LjE2OGwxMC4wNiA1LjA2OXoiIGNsYXNzPSJzdDAiLz48cGF0aCBkPSJtMzIuMzcgNDcuNjdjLTQuNjczIDEuNTMzLTkuODQxIDEuNTgzLTE0LjcxLTAuMTczMWwzLjkwNy0xMC41MWMyLjEyNyAwLjg2NTQgNC43OTcgMC43NjY1IDcuMjctMC4wNDk1bDMuNTM2IDEwLjczeiIgY2xhc3M9InN0MCIvPjxwYXRoIGQ9Im0xNC4xNyA0Ni4yNGMtNC4zNzctMi4yMi04LjA4Ni01Ljg2LTEwLjI5LTEwLjUzbDEwLjE5LTQuNjQ5YzAuODkwMiAyLjEyNyAyLjg0NCAzLjk1NiA1LjE2OCA1LjExOWwtNS4wNjkgMTAuMDZ6IiBjbGFzcz0ic3QwIi8+PHBhdGggZD0ibTIuMzI1IDMyLjM3Yy0xLjUzMy00LjY3My0xLjU4My05Ljg0MSAwLjE3MzEtMTQuNzFsMTAuNTEgMy45MDdjLTAuODY1NSAyLjEyNy0wLjc2NjUgNC43OTcgMC4wNDk0NSA3LjI3bC0xMC43MyAzLjUzNnoiIGNsYXNzPSJzdDAiLz48cGF0aCBkPSJtMy43NTkgMTQuMTdjMi4yMjYtNC4zNzcgNS44NjEtOC4wODYgMTAuNTMtMTAuMjlsNC42NDkgMTAuMTljLTIuMTI3IDAuODkwMi0zLjk1NiAyLjg0NC01LjExOSA1LjE2OGwtMTAuMDYtNS4wN3oiIGNsYXNzPSJzdDAiLz48cGF0aCBkPSJtMTcuNjMgMi4zMjVjNC42NzMtMS41MzMgOS44NDEtMS41ODMgMTQuNzEgMC4xNzMxbC0zLjkgMTAuNTFjLTIuMTI3LTAuODY1NC00Ljc5Ny0wLjc2NjUtNy4yNyAwLjA0OTVsLTMuNTQtMTAuNzR6IiBjbGFzcz0ic3QwIi8+PC9nPjwvc3ZnPgo=') 0 0 no-repeat; 180 | content: ''; 181 | display: inline-block; 182 | height: 25px; 183 | left: -62px; 184 | position: relative; 185 | top: .5em; 186 | vertical-align: top; 187 | width: 25px; 188 | } 189 | } 190 | 191 | .drop.style-tooltip { 192 | background: $popover-background-color; 193 | border: 2px $popover-color solid; 194 | box-shadow: 1px 2px 4px 1px $popover-box-shadow-color; 195 | color: $popover-color; 196 | display: none; 197 | margin-left: 40px; 198 | max-width: 700px; 199 | min-width: 50px; 200 | overflow: hidden; 201 | padding: 5px 9px; 202 | position: absolute; 203 | text-align: left; 204 | word-wrap: break-word; 205 | z-index: 15000; 206 | 207 | &.drop-open { 208 | display: block; 209 | } 210 | } 211 | 212 | .drop-content { 213 | overflow: hidden; 214 | word-wrap: break-word; 215 | } 216 | 217 | .csl-bib-body { 218 | margin-bottom: .6em; 219 | position: relative; 220 | word-wrap: normal; 221 | } 222 | 223 | 224 | 225 | .style-view-source, 226 | .style-individual-link { 227 | color: $view-source-button-color; 228 | display: none; 229 | font-size: 11px; 230 | line-height: .9em; 231 | margin-left: 2px; 232 | padding: 2px 6px 3px; 233 | text-align: center; 234 | vertical-align: middle; 235 | cursor: pointer; 236 | text-decoration: underline; 237 | 238 | li:hover & { 239 | display: inline; 240 | } 241 | } 242 | 243 | .style-individual-link { 244 | margin-left: 10px; 245 | } 246 | 247 | .preview-content { 248 | h3:first-child { 249 | margin-top: .25em; 250 | } 251 | 252 | h3 { 253 | font-size: 18px; 254 | } 255 | } 256 | 257 | /* 258 | .inline-citation ul, 259 | .inline-citation li { 260 | margin: 0; 261 | padding: 0; 262 | } 263 | 264 | .inline-citation ul { 265 | list-style: none; 266 | } 267 | */ 268 | -------------------------------------------------------------------------------- /include/Styles_Preview.inc.php: -------------------------------------------------------------------------------- 1 | . 23 | 24 | ***** END LICENSE BLOCK ***** 25 | */ 26 | 27 | require_once("Styles.inc.php"); 28 | 29 | class CSLPreview { 30 | public static function getCitations($code, $data) { 31 | $server = CITEPROC_NODE_URL; 32 | 33 | $url = "$server?responseformat=json&citations=1&bibliography=0"; 34 | 35 | $data->styleXML = $code; 36 | $json = json_encode($data); 37 | 38 | $response = self::callProcessor($url, $json); 39 | 40 | if (!$response) { 41 | throw new Exception("No response generating citations"); 42 | } 43 | 44 | $response = json_decode($response); 45 | $citations = $response->citations; 46 | 47 | $toReturn = array(); 48 | foreach ($citations as $citation) { 49 | $toReturn[] = $citation[1]; 50 | } 51 | return $toReturn; 52 | } 53 | 54 | 55 | /** 56 | * Generate JSON for items and send to citeproc-js web service 57 | * 58 | * From getBibliographyFromCiteServer() in Zotero_Cite data server class 59 | */ 60 | public static function getBibliography($code, $data) { 61 | $server = CITEPROC_NODE_URL; 62 | 63 | $url = "$server?responseformat=json"; 64 | 65 | $data->styleXML = $code; 66 | $json = json_encode($data); 67 | 68 | $response = self::callProcessor($url, $json); 69 | 70 | if (!$response) { 71 | throw new Exception("No response generating bibliography"); 72 | } 73 | 74 | // 75 | // Ported from Zotero.Cite.makeFormattedBibliography() in Zotero client 76 | // 77 | 78 | $bib = json_decode($response); 79 | $bib = $bib->bibliography; 80 | 81 | if (!$bib) { 82 | $url .= "&citations=1"; 83 | $response = self::callProcessor($url, $json); 84 | if (!$response) { 85 | throw new Exception("No response generating citations"); 86 | } 87 | $result = json_decode($response); 88 | $citations = array(); 89 | foreach ($result->citations as $citation) { 90 | $citations[] = $citation[1]; 91 | } 92 | $styleXML = new SimpleXMLElement($code); 93 | if ($styleXML['class'] == 'note') { 94 | return "
      \n\t
    1. " . implode("
    2. \n\t
    3. ", $citations) . "
    4. \n
    "; 95 | } 96 | else { 97 | return implode("
    \n", $citations); 98 | } 99 | } 100 | 101 | $html = $bib[0]->bibstart . implode("", $bib[1]) . $bib[0]->bibend; 102 | 103 | $sfa = "second-field-align"; 104 | 105 | //if (!empty($_GET['citedebug'])) { 106 | // echo "\n\n"; 113 | //} 114 | 115 | // Validate input 116 | if (!is_numeric($bib[0]->maxoffset)) throw new Exception("Invalid maxoffset"); 117 | if (!is_numeric($bib[0]->entryspacing)) throw new Exception("Invalid entryspacing"); 118 | if (!is_numeric($bib[0]->linespacing)) throw new Exception("Invalid linespacing"); 119 | 120 | $maxOffset = (int) $bib[0]->maxoffset; 121 | $entrySpacing = (int) $bib[0]->entryspacing; 122 | $lineSpacing = (int) $bib[0]->linespacing; 123 | $hangingIndent = !empty($bib[0]->hangingindent) ? (int) $bib[0]->hangingindent : 0; 124 | $secondFieldAlign = !empty($bib[0]->$sfa); // 'flush' and 'margin' are the same for HTML 125 | 126 | $xml = new SimpleXMLElement($html); 127 | 128 | $multiField = !!$xml->xpath("//div[@class = 'csl-left-margin']"); 129 | 130 | // One of the characters is usually a period, so we can adjust this down a bit 131 | $maxOffset = max(1, $maxOffset - 2); 132 | 133 | // Force a minimum line height 134 | if ($lineSpacing <= 1.35) $lineSpacing = 1.35; 135 | 136 | $xml['style'] .= "line-height: " . $lineSpacing . "; "; 137 | 138 | if ($hangingIndent) { 139 | if ($multiField && !$secondFieldAlign) { 140 | throw new Exception("second-field-align=false and hangingindent=true combination is not currently supported"); 141 | } 142 | // If only one field, apply hanging indent on root 143 | else if (!$multiField) { 144 | $xml['style'] .= "padding-left: {$hangingIndent}em; text-indent:-{$hangingIndent}em;"; 145 | } 146 | } 147 | 148 | $leftMarginDivs = $xml->xpath("//div[@class = 'csl-left-margin']"); 149 | $clearEntries = sizeOf($leftMarginDivs) > 0; 150 | 151 | // csl-entry 152 | $divs = $xml->xpath("//div[@class = 'csl-entry']"); 153 | $num = sizeOf($divs); 154 | $i = 0; 155 | foreach ($divs as $div) { 156 | $first = $i == 0; 157 | $last = $i == $num - 1; 158 | 159 | if ($clearEntries) { 160 | $div['style'] .= "clear: left; "; 161 | } 162 | 163 | if ($entrySpacing) { 164 | if (!$last) { 165 | $div['style'] .= "margin-bottom: " . $entrySpacing . "em;"; 166 | } 167 | } 168 | 169 | $i++; 170 | } 171 | 172 | // Padding on the label column, which we need to include when 173 | // calculating offset of right column 174 | $rightPadding = .5; 175 | 176 | // div.csl-left-margin 177 | foreach ($leftMarginDivs as $div) { 178 | $div['style'] = "float: left; padding-right: " . $rightPadding . "em; "; 179 | 180 | // Right-align the labels if aligning second line, since it looks 181 | // better and we don't need the second line of text to align with 182 | // the left edge of the label 183 | if ($secondFieldAlign) { 184 | $div['style'] .= "text-align: right; width: " . $maxOffset . "em;"; 185 | } 186 | } 187 | 188 | // div.csl-right-inline 189 | foreach ($xml->xpath("//div[@class = 'csl-right-inline']") as $div) { 190 | $div['style'] .= "margin: 0 .4em 0 " . ($secondFieldAlign ? $maxOffset + $rightPadding : "0") . "em;"; 191 | 192 | if ($hangingIndent) { 193 | $div['style'] .= "padding-left: {$hangingIndent}em; text-indent:-{$hangingIndent}em;"; 194 | } 195 | } 196 | 197 | // div.csl-indent 198 | foreach ($xml->xpath("//div[@class = 'csl-indent']") as $div) { 199 | $div['style'] = "margin: .5em 0 0 2em; padding: 0 0 .2em .5em; border-left: 5px solid #ccc;"; 200 | } 201 | 202 | $xml = $xml->asXML(); 203 | // Strip XML prolog 204 | $xml = substr($xml, strpos($xml, "\n") + 1); 205 | 206 | return $xml; 207 | } 208 | 209 | 210 | private static function callProcessor($url, $postdata) { 211 | $start = microtime(true); 212 | 213 | $ch = curl_init($url); 214 | curl_setopt($ch, CURLOPT_POST, 1); 215 | curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata); 216 | curl_setopt($ch, CURLOPT_HTTPHEADER, array("Expect:")); 217 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 1); 218 | curl_setopt($ch, CURLOPT_TIMEOUT, 4); 219 | curl_setopt($ch, CURLOPT_HEADER, 0); // do not return HTTP headers 220 | curl_setopt($ch, CURLOPT_RETURNTRANSFER , 1); 221 | $response = curl_exec($ch); 222 | 223 | $time = microtime(true) - $start; 224 | 225 | $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); 226 | if ($code == 0) { 227 | throw new Exception("Request timed out"); 228 | } 229 | else if ($code == 404) { 230 | throw new Exception("Invalid style", Z_ERROR_CITESERVER_INVALID_STYLE); 231 | } 232 | 233 | return $response; 234 | } 235 | } 236 | ?> 237 | -------------------------------------------------------------------------------- /frontend/src/zsr.js: -------------------------------------------------------------------------------- 1 | import 'whatwg-fetch'; 2 | 3 | import Drop from 'tether-drop'; 4 | import intersection from 'lodash/intersection'; 5 | import { mountToDom } from 'vidom'; 6 | import AppComponent from './AppComponent.js'; 7 | import AppState from './AppState.js'; 8 | import { closest } from './utils.js'; 9 | 10 | /** 11 | * Application entry point 12 | * @param {HTMLElement} container - DOM element where the application will be rendered 13 | */ 14 | function ZSR(container) { 15 | this.container = container; 16 | this.tooltips = {}; 17 | let query = {}; 18 | let intialParsed = location.search.substr(1).split('&'); 19 | let propSearchField = this.container.querySelector('.search-field'); 20 | intialParsed.forEach(parsedItem => { 21 | parsedItem = parsedItem.split('='); 22 | query[decodeURIComponent(parsedItem[0])] = decodeURIComponent(parsedItem[1] || ''); 23 | }); 24 | 25 | if(query['fields']) { 26 | query.fields = query.fields.split(','); 27 | } 28 | 29 | if(query['q'] || (propSearchField && propSearchField.value)) { 30 | // on slow connection handle user input from before js loaded 31 | if(propSearchField && propSearchField.value) { 32 | query.initialSearch = query.search = propSearchField.value; 33 | } else { 34 | query.initialSearch = query.search = query.q; 35 | } 36 | delete query.q; 37 | } 38 | 39 | if(query['dependent']) { 40 | query['dependent'] = parseInt(query['dependent'], 10); 41 | } 42 | 43 | this.state = new AppState({ 44 | styles: [], 45 | formats: [], 46 | fields: [], 47 | query: query, 48 | fetching: true 49 | }); 50 | 51 | this.state.onChange(() => { 52 | let tooltipKeys = Object.keys(this.tooltips); 53 | tooltipKeys.forEach(tooltipKey => { 54 | this.tooltips[tooltipKey].destroy(); 55 | delete this.tooltips[tooltipKey]; 56 | }); 57 | }); 58 | 59 | this.container.innerHTML = ''; 60 | 61 | this.mount(); 62 | 63 | if(process.env.NODE_ENV === 'development') { 64 | var t0 = performance.now(); 65 | } 66 | fetch('/styles-files/styles.json').then(response => { 67 | if(response.status >= 200 && response.status < 300) { 68 | response.json().then(styles => { 69 | if(process.env.NODE_ENV === 'development') { 70 | let t1 = performance.now(); 71 | console.log('Fetching json took ' + (t1 - t0) + ' ms.'); 72 | } 73 | this.state.setState({ 74 | fetching: false 75 | }, true); 76 | 77 | this.fields = new Set(); 78 | this.formats = new Set(); 79 | 80 | this.styles = styles; 81 | this.styles.forEach(style => { 82 | this.formats.add(style.categories.format); 83 | style.categories.fields.forEach(field => { 84 | this.fields.add(field); 85 | }); 86 | }); 87 | this.search(this.state.query); 88 | }); 89 | } 90 | }); 91 | } 92 | 93 | /** 94 | * Mount vidom to the actual DOM element and attach event listeners 95 | * to fetch and display style previews on mouseover 96 | * @return {[type]} [description] 97 | */ 98 | ZSR.prototype.mount = function() { 99 | if(process.env.NODE_ENV === 'development') { 100 | var t0 = performance.now(); 101 | } 102 | let ac = new AppComponent(this); 103 | 104 | this.container.addEventListener('mouseover', ev => { 105 | let element = ev.target; 106 | let listEl = closest(element, el => el.hasAttribute && el.hasAttribute('data-index')); 107 | if(!listEl) { 108 | return; 109 | } 110 | let index = listEl.getAttribute('data-index'); 111 | 112 | if(element.classList.contains('title')) { 113 | if(!this.tooltips[index]) { 114 | this.tooltips[index] = new Drop({ 115 | target: element, 116 | content: 'Loading Preview...', 117 | classes: 'style-tooltip', 118 | openOn: 'hover', 119 | closeDelay: 50 120 | }); 121 | 122 | let style = this.styles[index]; 123 | let previewUrl = `/styles-files/previews/combined/${style.dependent ? 'dependent/' : ''}${style.name}.json`; 124 | fetch(previewUrl).then(response => { 125 | if(response.status >= 200 && response.status < 300) { 126 | response.json().then(preview => { 127 | this.tooltips[index].content.innerHTML = 128 | '
    ' 129 | + '

    Citations

    ' 130 | + '

    ' + preview.citation.join(' ') + '

    ' 131 | + '

    Bibliography

    ' 132 | + preview.bibliography 133 | + '
    '; 134 | this.tooltips[index].position(); 135 | }); 136 | } 137 | }); 138 | this.tooltips[index].open(); 139 | } 140 | } 141 | }); 142 | 143 | mountToDom(this.container, ac, () => { 144 | if(process.env.NODE_ENV === 'development') { 145 | let t1 = performance.now(); 146 | console.log('Mounting vidom took ' + (t1 - t0) + ' ms.'); 147 | } 148 | }); 149 | }; 150 | 151 | /** 152 | * Filter styles for given query and update the App State with the results 153 | * @param {Object} query - object defining search criteria. Can contain the following keys: 154 | */ 155 | ZSR.prototype.search = function(query) { 156 | if(process.env.NODE_ENV === 'development') { 157 | var t0 = performance.now(); 158 | } 159 | var filtered; 160 | var filteredCounter = this.styles && this.styles.length || 0; 161 | var formats; 162 | var fields; 163 | 164 | 165 | if(!this.styles || !this.styles.length) { 166 | this.state.setState({ 167 | query: query 168 | }); 169 | return; 170 | } 171 | 172 | if(query) { 173 | let queryKeys = Object.keys(query), 174 | queryFormat, 175 | queryId, 176 | queryDependent, 177 | queryFields, 178 | querySearch; 179 | 180 | fields = new Set(); 181 | formats = new Set(); 182 | 183 | if(queryKeys.indexOf('id') > -1 && query.id !== null) { 184 | queryId = query.id; 185 | } 186 | 187 | if(queryKeys.indexOf('format') > -1 && query.format !== null) { 188 | queryFormat = query.format; 189 | } 190 | 191 | if(queryKeys.indexOf('dependent') > -1 && query.dependent !== null) { 192 | queryDependent = query.dependent; 193 | } 194 | 195 | if(queryKeys.indexOf('fields') > -1 && query.fields.length) { 196 | queryFields = query.fields; 197 | } 198 | 199 | if(queryKeys.indexOf('search') > -1 && query.search !== null && query.search.length) { 200 | querySearch = query.search; 201 | let matches = querySearch.match(/id\:\s*([\w\-]*)/i); 202 | if(matches) { 203 | queryId = matches[1].trim(); 204 | querySearch = querySearch.slice(0, matches.index) + querySearch.slice(matches.index + matches[0].length); 205 | querySearch = querySearch.trim(); 206 | } 207 | } 208 | 209 | filtered = this.styles.map(item => { 210 | item.visible = true; 211 | 212 | if(typeof queryId !== 'undefined') { 213 | item.visible = item.visible && item.name === queryId; 214 | } 215 | 216 | if(typeof queryFormat !== 'undefined') { 217 | item.visible = item.visible && item.categories.format === queryFormat; 218 | } 219 | if(typeof queryDependent !== 'undefined') { 220 | item.visible = item.visible && !!item.dependent === !!queryDependent; 221 | } 222 | if(typeof queryFields !== 'undefined') { 223 | item.visible = item.visible && intersection(queryFields, item.categories.fields).length === queryFields.length; 224 | } 225 | if(typeof querySearch !== 'undefined') { 226 | let queryLow = querySearch.toLowerCase(); 227 | let queryLowParts = queryLow.split(/\s+/); 228 | item.visible = item.visible 229 | && queryLowParts.every((part) => { 230 | return item.name.toLowerCase().includes(part) 231 | || item.title.toLowerCase().includes(part) 232 | || (item.titleShort && item.titleShort.toLowerCase().includes(part)); 233 | }); 234 | } 235 | 236 | if(item.visible) { 237 | item.categories.fields.forEach(field => { 238 | fields.add(field); 239 | }); 240 | 241 | formats.add(item.categories.format); 242 | } else { 243 | filteredCounter--; 244 | } 245 | 246 | return item; 247 | 248 | }); 249 | } else { 250 | fields = this.fields; 251 | formats = this.formats; 252 | } 253 | 254 | if(process.env.NODE_ENV === 'development') { 255 | let t1 = performance.now(); 256 | console.log('Filtering took ' + (t1 - t0) + ' ms.'); 257 | } 258 | 259 | this.state.setState({ 260 | styles: filtered, 261 | count: filteredCounter, 262 | fields: Array.from(fields), 263 | formats: Array.from(formats), 264 | query: query 265 | }); 266 | }; 267 | 268 | export default ZSR; -------------------------------------------------------------------------------- /scripts/generate-index: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php 2 | . 24 | 25 | ***** END LICENSE BLOCK ***** 26 | */ 27 | 28 | error_reporting(E_ALL); 29 | ini_set("display_errors", true); 30 | 31 | ini_set('include_path', '.:' . dirname(dirname(__FILE__)) . '/include'); 32 | require('config.inc.php'); 33 | require('Styles.inc.php'); 34 | require("Styles_Repo.inc.php"); 35 | 36 | class CSL_Index_Generator { 37 | private static $initialized = false; 38 | private static $originalStylesPath; 39 | private static $localStylesPath; 40 | private static $dataPath; 41 | 42 | private static function init() { 43 | self::$initialized = true; 44 | 45 | self::$originalStylesPath = ROOT_PATH . "styles/original/"; 46 | self::$localStylesPath = ROOT_PATH . "styles/local/"; 47 | self::$dataPath = ROOT_PATH . "styles/data/"; 48 | 49 | if (!file_exists(self::$originalStylesPath)) { 50 | throw new Exception("Original styles directory not found"); 51 | } 52 | if (!file_exists(self::$originalStylesPath . ".git")) { 53 | chdir(self::$originalStylesPath); 54 | if (file_exists(".gitignore")) { 55 | unlink(".gitignore"); 56 | } 57 | exec("git clone https://github.com/citation-style-language/styles.git ."); 58 | } 59 | if (!file_exists(self::$localStylesPath . "dependent")) { 60 | mkdir(self::$localStylesPath . "dependent"); 61 | } 62 | if (!file_exists(self::$dataPath . "dependent")) { 63 | mkdir(self::$dataPath . "dependent"); 64 | } 65 | } 66 | 67 | public static function run() { 68 | if (!self::$initialized) { 69 | self::init(); 70 | } 71 | 72 | // Update original styles 73 | chdir(self::$originalStylesPath); 74 | exec("/usr/bin/git pull"); 75 | 76 | $keep = array( 77 | 'independent' => array(), 78 | 'dependent' => array() 79 | ); 80 | 81 | $path = self::$originalStylesPath; 82 | $dir = opendir($path); 83 | while (false !== ($filename = readdir($dir))) { 84 | if (fnmatch("*.csl", $filename)) { 85 | $name = self::processOriginalStyle($path . $filename); 86 | if ($name) { 87 | $keep['independent'][] = $name; 88 | } 89 | } 90 | } 91 | closedir($dir); 92 | 93 | $path = self::$originalStylesPath . "dependent/"; 94 | $dir = opendir($path); 95 | while (false !== ($filename = readdir($dir))) { 96 | if (fnmatch("*.csl", $filename)) { 97 | $name = self::processOriginalStyle($path . $filename, true); 98 | if ($name) { 99 | $keep['dependent'][] = $name; 100 | } 101 | } 102 | } 103 | closedir($dir); 104 | 105 | // 106 | // Delete styles that weren't updated 107 | // 108 | $path = self::$localStylesPath; 109 | $dir = opendir($path); 110 | while (false !== ($filename = readdir($dir))) { 111 | if (strpos($filename, ".") !== false || $filename == 'dependent') { 112 | continue; 113 | } 114 | if (!in_array($filename, $keep['independent'])) { 115 | Styles::log("Deleting $filename"); 116 | unlink($path . $filename); 117 | } 118 | } 119 | closedir($dir); 120 | 121 | $path = self::$localStylesPath . "dependent/"; 122 | $dir = opendir($path); 123 | while (false !== ($filename = readdir($dir))) { 124 | if (strpos($filename, ".") !== false) { 125 | continue; 126 | } 127 | if (!in_array($filename, $keep['dependent'])) { 128 | Styles::log("Deleting dependent/$filename"); 129 | unlink($path . $filename); 130 | } 131 | } 132 | closedir($dir); 133 | 134 | 135 | // 136 | // Delete data files that weren't updated 137 | // 138 | $path = self::$dataPath; 139 | $dir = opendir($path); 140 | while (false !== ($filename = readdir($dir))) { 141 | if (strpos($filename, ".") !== false 142 | || $filename == 'dependent' 143 | || $filename == 'cache') { 144 | continue; 145 | } 146 | if (!in_array($filename, $keep['independent'])) { 147 | Styles::log("Deleting $filename"); 148 | unlink($path . $filename); 149 | } 150 | } 151 | closedir($dir); 152 | 153 | $path = self::$dataPath . "dependent/"; 154 | $dir = opendir($path); 155 | while (false !== ($filename = readdir($dir))) { 156 | if (strpos($filename, ".") !== false) { 157 | continue; 158 | } 159 | if (!in_array($filename, $keep['dependent'])) { 160 | Styles::log("Deleting dependent/$filename"); 161 | unlink($path . $filename); 162 | } 163 | } 164 | closedir($dir); 165 | 166 | // Save 'lastModified' and 'etag' values for caching 167 | try { 168 | $styleList = Styles_Repo::getAllStyles(); 169 | Styles_Repo::setCacheValues($styleList); 170 | } 171 | catch (Exception $e) { 172 | error_log($e); 173 | } 174 | } 175 | 176 | 177 | /** 178 | * Update cached file from original 179 | * 180 | * If style doesn't already exist or has changed, set a new timestamp 181 | * 182 | * Returns the parsed style name, or FALSE on error 183 | */ 184 | private static function processOriginalStyle($originalStyle, $dependent=false) { 185 | Styles::log("=========================================\n"); 186 | $filename = substr(strrchr($originalStyle, '/'), 1); 187 | Styles::log("$filename\n"); 188 | 189 | $valid = null; 190 | 191 | $xmlstr = file_get_contents($originalStyle); 192 | 193 | try { 194 | $xml = new SimpleXMLElement($xmlstr); 195 | } 196 | catch (Exception $e) { 197 | Styles::log("$filename is invalid XML"); 198 | return false; 199 | } 200 | 201 | $name = substr(strrchr($xml->info->id, '/'), 1); 202 | 203 | if (strpos($name, ".") !== false) { 204 | Styles::log("Invalid style name '" . $name . "'"); 205 | return false; 206 | } 207 | 208 | // Compare CSL to existing version and skip if identical 209 | $localStyle = self::$localStylesPath . ($dependent ? "dependent/" : "") . $name; 210 | $dataFile = self::$dataPath . ($dependent ? "dependent/" : "") . $name; 211 | if (file_exists($localStyle) && file_exists($dataFile)) { 212 | $code = file_get_contents($localStyle); 213 | if (preg_replace("'.*'", "", $code) 214 | == preg_replace("'.*'", "", $xmlstr)) { 215 | Styles::log("$filename hasn't changed -- skipping\n"); 216 | return $name; 217 | } 218 | } 219 | 220 | // Use timestamp from last git commit 221 | 222 | 223 | // TODO: ability to blacklist certain commit timestamps 224 | 225 | 226 | chdir(self::$originalStylesPath); 227 | $date = shell_exec("git log -n 1 --date=iso " . ($dependent ? 'dependent/' : '') . escapeshellarg($filename) . " | grep Date: | head -n 1"); 228 | if (preg_match('/^Date:\s*([0-9]{4}\-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} [+\-][0-9]{4})/', $date, $matches)) { 229 | $time = strtotime($matches[1]); 230 | } 231 | else { 232 | Styles::log("Error retrieving date from git log"); 233 | $time = filemtime($originalStyle); 234 | } 235 | 236 | $iso8601 = gmdate("c", $time); 237 | 238 | $xmlstr = preg_replace(array("'.*'", "''"), "$iso8601", $xmlstr); 239 | file_put_contents($localStyle, $xmlstr); 240 | 241 | $cmd = "/usr/bin/xmllint --relaxng " . ROOT_PATH . "scripts/schema/csl.rng --noout $localStyle"; 242 | Styles::log($cmd); 243 | exec($cmd, $output, $code); 244 | if ($code != 0) { 245 | Styles::log("\n$filename is invalid\n"); 246 | $valid = false; 247 | } 248 | else { 249 | $valid = true; 250 | } 251 | 252 | // Write data file 253 | $data = array( 254 | 'valid' => $valid 255 | ); 256 | file_put_contents($dataFile, json_encode($data)); 257 | 258 | return $name; 259 | } 260 | } 261 | 262 | CSL_Index_Generator::run(); 263 | ?> 264 | -------------------------------------------------------------------------------- /scripts/generate-previews: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php 2 | . 24 | 25 | ***** END LICENSE BLOCK ***** 26 | */ 27 | 28 | error_reporting(E_ALL); 29 | ini_set("display_errors", true); 30 | 31 | ini_set('include_path', '.:' . dirname(dirname(__FILE__)) . '/include'); 32 | require('config.inc.php'); 33 | require('Styles.inc.php'); 34 | require('Styles_Repo.inc.php'); 35 | require('Styles_Preview.inc.php'); 36 | 37 | $singleStyle = !empty($argv[1]) ? $argv[1] : false; 38 | 39 | $styles = Styles_Repo::getAllStyles(); 40 | 41 | $independents = array(); 42 | $dependents = array(); 43 | $previews = array(); 44 | $lookup = array(); 45 | 46 | const FALLBACK_LOCALE = 'en-US'; 47 | 48 | $data = json_decode(file_get_contents(ROOT_PATH . 'include/data/previews.json')); 49 | 50 | $previewsDir = ROOT_PATH . 'htdocs/styles-files/previews/'; 51 | if (!is_dir($previewsDir)) { 52 | throw new Exception("Previews directory not found"); 53 | } 54 | // Create some directories if they don't exist 55 | $previewCitationDir = $previewsDir . 'citation/'; 56 | if (!is_dir($previewCitationDir)) { 57 | mkdir($previewCitationDir); 58 | } 59 | if (!is_dir($previewCitationDir . 'dependent')) { 60 | mkdir($previewCitationDir . 'dependent'); 61 | } 62 | $previewBibDir = $previewsDir . 'bib/'; 63 | if (!is_dir($previewBibDir)) { 64 | mkdir($previewBibDir); 65 | } 66 | if (!is_dir($previewBibDir . 'dependent')) { 67 | mkdir($previewBibDir . 'dependent'); 68 | } 69 | 70 | $previewCombinedDir = $previewsDir . 'combined/'; 71 | if (!is_dir($previewCombinedDir)) { 72 | mkdir($previewCombinedDir); 73 | } 74 | if (!is_dir($previewCombinedDir . 'dependent')) { 75 | mkdir($previewCombinedDir . 'dependent'); 76 | } 77 | 78 | // Update independents 79 | foreach ($styles as $style) { 80 | $name = $style['name']; 81 | $lookup[$name] = $style; 82 | $xml = new SimpleXMLElement($style['code']); 83 | 84 | if($xml['default-locale']) { 85 | $lookup[$name]['default-locale'] = (string) $xml['default-locale']; 86 | } else { 87 | $lookup[$name]['default-locale'] = FALLBACK_LOCALE; 88 | } 89 | 90 | $lookup[$name]['xml'] = $xml; 91 | 92 | // Save dependents for later 93 | if ($style['dependent']) { 94 | $xml->registerXPathNamespace("csl", "http://purl.org/net/xbiblio/csl"); 95 | $parent = $xml->xpath("/csl:style/csl:info/csl:link[@rel='independent-parent']"); 96 | if ($parent) { 97 | $parentName = substr(strrchr((string) $parent[0]['href'], '/'), 1); 98 | $dependents[] = array( 99 | 'name' => $style['name'], 100 | 'parentName' => $parentName 101 | ); 102 | continue; 103 | } 104 | } 105 | 106 | if ($singleStyle && $name != $singleStyle) { 107 | continue; 108 | } 109 | 110 | Styles::log("============================\n"); 111 | Styles::log("Generating preview for $name\n"); 112 | 113 | // Get the preview 114 | try { 115 | $previewCitations = CSLPreview::getCitations($style['code'], $data); 116 | $previewBib = CSLPreview::getBibliography($style['code'], $data); 117 | } 118 | catch (Exception $e) { 119 | var_dump($e); 120 | $preview = 'Error generating preview'; 121 | continue; 122 | } 123 | foreach ($previewCitations as $citation) { 124 | Styles::log($citation . "\n"); 125 | } 126 | Styles::log($previewBib . "\n"); 127 | 128 | Styles_Repo::setPreviewCitations($name, $previewCitations); 129 | Styles_Repo::setPreviewBibliography($name, $previewBib); 130 | Styles_Repo::setPreviewCombined($name, $previewCitations, $previewBib); 131 | $previews[$name]['citation'] = $previewCitations; 132 | $previews[$name]['bib'] = $previewBib; 133 | $independents[$name] = true; 134 | } 135 | 136 | // Update dependents with parent previews 137 | foreach ($dependents as $dependent) { 138 | $name = $dependent['name']; 139 | 140 | if ($singleStyle && $name != $singleStyle) { 141 | continue; 142 | } 143 | 144 | $parentName = $dependent['parentName']; 145 | $dependentStyle = $lookup[$name]; 146 | $parent = $lookup[$parentName]; 147 | 148 | echo "============================\n\n"; 149 | echo "Generating preview for $name (dep)\n\n"; 150 | 151 | $previewCitations = null; 152 | $previewBib = null; 153 | $okToUseParent = $dependentStyle["default-locale"] == $parent["default-locale"]; 154 | 155 | if($okToUseParent) { 156 | if (isset($previews[$parentName])) { 157 | $previewCitations = $previews[$parentName]['citation']; 158 | $previewBib = $previews[$parentName]['bib']; 159 | } else { 160 | if ($singleStyle) { 161 | $previewCitations = Styles_Repo::getPreviewCitations($parentName); 162 | $previewBib = Styles_Repo::getPreviewBibliography($parentName); 163 | } 164 | 165 | if (empty($previewCitations) || empty($previewBib)) { 166 | Styles::log("Preview of parent $parentName not found"); 167 | continue; 168 | } 169 | } 170 | } else { 171 | $modifiedXML = clone $parent['xml']; 172 | $modifiedXML['default-locale'] = $dependentStyle['default-locale']; 173 | 174 | try { 175 | $previewCitations = CSLPreview::getCitations($modifiedXML->asXML(), $data); 176 | $previewBib = CSLPreview::getBibliography($modifiedXML->asXML(), $data); 177 | } 178 | catch (Exception $e) { 179 | var_dump($e); 180 | $preview = 'Error generating preview'; 181 | continue; 182 | } 183 | } 184 | 185 | Styles_Repo::setPreviewCitations($name, $previewCitations, true); 186 | Styles_Repo::setPreviewBibliography($name, $previewBib, true); 187 | Styles_Repo::setPreviewCombined($name, $previewCitations, $previewBib, true); 188 | $dependents[$name] = true; 189 | } 190 | 191 | if ($singleStyle) { 192 | exit; 193 | } 194 | 195 | if (!$dependents && !$independents) { 196 | Styles::log("\nError generating previews"); 197 | exit; 198 | } 199 | 200 | // 201 | // Delete files we didn't just generate 202 | // 203 | $dir = $previewCitationDir; 204 | if ($dh = opendir($dir)) { 205 | while (($file = readdir($dh)) != false) { 206 | if (preg_match('/^(.+)\.json$/', $file, $matches)) { 207 | if (!in_array($matches[1], $independents)) { 208 | Styles::log("Deleting citation preview $file"); 209 | unlink($dir . $file); 210 | } 211 | } 212 | } 213 | } 214 | 215 | $dir = $previewCitationDir . 'dependent/'; 216 | if ($dh = opendir($dir)) { 217 | while (($file = readdir($dh)) != false) { 218 | if (preg_match('/^(.+)\.json$/', $file, $matches)) { 219 | if (!in_array($matches[1], $dependents)) { 220 | Styles::log("Deleting citation preview dependents/$file"); 221 | unlink($dir . $file); 222 | } 223 | } 224 | } 225 | } 226 | 227 | $dir = $previewBibDir; 228 | if ($dh = opendir($dir)) { 229 | while (($file = readdir($dh)) != false) { 230 | if (preg_match('/^(.+)\.html$/', $file, $matches)) { 231 | if (!in_array($matches[1], $independents)) { 232 | Styles::log("Deleting bib preview $file"); 233 | unlink($dir . $file); 234 | } 235 | } 236 | } 237 | } 238 | 239 | $dir = $previewBibDir . 'dependent/'; 240 | if ($dh = opendir($dir)) { 241 | while (($file = readdir($dh)) != false) { 242 | if (preg_match('/^(.+)\.html$/', $file, $matches)) { 243 | if (!in_array($matches[1], $dependents)) { 244 | Styles::log("Deleting bib preview dependents/$file"); 245 | unlink($dir . $file); 246 | } 247 | } 248 | } 249 | } 250 | 251 | $dir = $previewCombinedDir; 252 | if ($dh = opendir($dir)) { 253 | while (($file = readdir($dh)) != false) { 254 | if (preg_match('/^(.+)\.html$/', $file, $matches)) { 255 | if (!in_array($matches[1], $independents)) { 256 | Styles::log("Deleting combined preview $file"); 257 | unlink($dir . $file); 258 | } 259 | } 260 | } 261 | } 262 | 263 | $dir = $previewCombinedDir . 'dependent/'; 264 | if ($dh = opendir($dir)) { 265 | while (($file = readdir($dh)) != false) { 266 | if (preg_match('/^(.+)\.html$/', $file, $matches)) { 267 | if (!in_array($matches[1], $dependents)) { 268 | Styles::log("Deleting combined preview dependents/$file"); 269 | unlink($dir . $file); 270 | } 271 | } 272 | } 273 | } 274 | ?> 275 | -------------------------------------------------------------------------------- /frontend/src/AppComponent.js: -------------------------------------------------------------------------------- 1 | import extend from 'lodash/extend'; 2 | import debounce from 'lodash/debounce'; 3 | import { node } from 'vidom'; 4 | import { Component } from 'vidom'; 5 | import { numberFormat } from './utils.js'; 6 | 7 | /** 8 | * Maintain & update the virtual dom based on the current state of the application. 9 | */ 10 | export default class AppComponent extends Component { 11 | /** 12 | * Update the virtual dom to reflect current state of the application 13 | * @return {Object} Virtual DOM Node 14 | */ 15 | onRender() { 16 | var formatsList, 17 | fieldsList; 18 | 19 | if(!this.state || this.state.fetching) { 20 | formatsList = node('span').children('Loading...'); 21 | } else { 22 | formatsList = node('ul') 23 | .attrs({ 24 | className: 'formats-list' 25 | }) 26 | .children(this.state && this.state.formats.sort().map(format => { 27 | return node('li') 28 | .attrs({ 29 | className: this.state && this.state.query.format == format ? 'format-active' : 'a' , 30 | onClick: e => this.onClick('format', e) 31 | }) 32 | .children(format); 33 | })); 34 | } 35 | 36 | if(!this.state || this.state.fetching) { 37 | fieldsList = node('span').children('Loading...'); 38 | } else { 39 | fieldsList = node('ul') 40 | .attrs({ 41 | className: 'fields-list' 42 | }) 43 | .children(this.state && this.state.fields.sort().map(field => { 44 | return node('li') 45 | .attrs({ 46 | className: this.state && this.state.query.fields && this.state.query.fields.indexOf(field) > -1 ? 'field-active' : 'a' , 47 | onClick: e => this.onClick('fields', e) 48 | }) 49 | .children(field); 50 | })); 51 | } 52 | 53 | return node('div') 54 | .children([ 55 | node('div') 56 | .attrs({ 57 | className: 'search-pane' 58 | }).children([ 59 | node('div') 60 | .attrs({ 61 | className: 'search-pane-loading-indicator' 62 | }) 63 | .children('Loading...'), 64 | node('div') 65 | .attrs({ 66 | className: 'search-pane-col-1' 67 | }) 68 | .children([ 69 | node('h2') 70 | .children('Style Search'), 71 | node('p').children([ 72 | node('input') 73 | .attrs({ 74 | type: 'search', 75 | className: 'search-field', 76 | id: 'search-field', 77 | placeholder: 'Title Search', 78 | value: this.state && this.state.query.initialSearch || '', 79 | onKeyUp: e => this.onKeyUp(e), 80 | onChange: e => this.onKeyUp(e) 81 | }) 82 | ]), 83 | node('p').children( 84 | node('label') 85 | .attrs({ 86 | className: 'search-unique' 87 | }) 88 | .children([ 89 | node('input') 90 | .attrs({ 91 | type: 'checkbox', 92 | checked: this.state && this.state.query.dependent !== null && typeof this.state.query.dependent !== 'undefined' && !this.state.query.dependent, 93 | onChange: e => this.onClick('unique', e) 94 | }), 95 | node('span') 96 | .children('Show only unique styles') 97 | ]) 98 | ) 99 | ]), 100 | node('div') 101 | .attrs({ 102 | className: 'search-pane-col-2' 103 | }) 104 | .children([ 105 | node('p') 106 | .children([ 107 | node('strong') 108 | .children('Format:'), 109 | formatsList 110 | ]), 111 | node('p') 112 | .children([ 113 | node('strong') 114 | .children('Fields:'), 115 | fieldsList 116 | ]) 117 | ]) 118 | ]), 119 | node('div') 120 | .attrs({ 121 | className: !this.state || this.state.fetching ? 'styles-loading' : 'style-count' 122 | }).children(this.state && !this.state.fetching && this.state.count ? 123 | `${numberFormat(this.state.count)} ${this.state.count > 1 ? 'styles' : 'style'} found:` : 124 | this.state && this.state.fetching ? null : 'No styles found' 125 | ), 126 | node('ul') 127 | .attrs({ 128 | className: 'style-list' 129 | }) 130 | .children(this.items ? this.items : []) 131 | ]); 132 | } 133 | 134 | /** 135 | * Handle keyboard input 136 | * @param {KeyboardEvent} 137 | */ 138 | onKeyUp(e) { 139 | // don't react to modifier keys, tab and arrow keys 140 | if([9, 37, 38, 39, 40, 16, 17, 18, 91, 224].indexOf(e.nativeEvent.keyCode) === -1) { 141 | this._update(); 142 | let query = { 143 | search: e.target.value 144 | }; 145 | this.onQuery(query); 146 | } 147 | } 148 | 149 | /** 150 | * Handle selecting fields and filters 151 | * @param {String} type - Type of the event 'field' or 'format' 152 | * @param {MouseEvent} e 153 | */ 154 | onClick(type, e) { 155 | let query = {}; 156 | let value = e.target.innerText; 157 | 158 | if(type === 'fields') { 159 | query['fields'] = this.state.query.fields || []; 160 | if(this.state.query.fields) { 161 | let pos = this.state.query.fields.indexOf(value); 162 | if(pos > -1) { 163 | query['fields'].splice(pos, 1); 164 | } else { 165 | query['fields'].push(value); 166 | } 167 | } else { 168 | query['fields'].push(value); 169 | } 170 | } else if(type === 'format') { 171 | if(this.state.query.format === value) { 172 | query['format'] = null; 173 | } else { 174 | query['format'] = value; 175 | } 176 | } else if(type === 'unique') { 177 | query['dependent'] = e.target.checked ? 0 : null; 178 | } 179 | this.onQuery(query); 180 | } 181 | 182 | onSelectItem(e, item) { 183 | let search = `id:${item.name}`; 184 | this.onQuery({ 185 | search: search, 186 | initialSearch: search //update input field as well 187 | }); 188 | } 189 | 190 | /** 191 | * Handler called on the initial mount onto the real DOM. 192 | */ 193 | onMount() { 194 | this._update(() => { 195 | this.getDomNode().querySelector('#search-field').focus(); 196 | }); 197 | } 198 | 199 | /** 200 | * Generate a virtual dom for a single style item 201 | * @param {Object} - style 202 | * @param {Number} - index 203 | * @return {Object} - virtual dom node 204 | */ 205 | getItem(style, index) { 206 | return node('li') 207 | .attrs({ 208 | 'data-index': index 209 | }) 210 | .children([ 211 | node('a') 212 | .key('title') 213 | .attrs({ 214 | className: 'title', 215 | href: style.href 216 | }) 217 | .children(style.title), 218 | node('span') 219 | .key('metadata') 220 | .attrs({ 221 | className: 'metadata' 222 | }) 223 | .children(`(${style.updated})`), 224 | node('a') 225 | .attrs({ 226 | className: 'style-individual-link', 227 | onClick: e => this.onSelectItem(e, style) 228 | }) 229 | .children('Link'), 230 | node('a') 231 | .attrs({ 232 | className: 'style-view-source', 233 | href: style.href + '?source=1' 234 | }) 235 | .children('Source') 236 | ]); 237 | } 238 | 239 | /** 240 | * Handler called on application state change 241 | * @param {Array} diff - list of all the properties that has changed 242 | * @param {Object} state - new, up-to-date state object 243 | */ 244 | onStateChange(diff, state) { 245 | if (process.env.NODE_ENV === 'development') { 246 | var t0 = performance.now(); 247 | } 248 | this.state = state; 249 | if(diff.indexOf('styles') > -1) { 250 | this.items = []; 251 | this.state.styles.forEach((style, index) => { 252 | if(style.visible) { 253 | this.items.push(this.getItem(style, index, true)); 254 | } 255 | }); 256 | } 257 | 258 | if (process.env.NODE_ENV === 'development') { 259 | let t1 = performance.now(); 260 | console.log('Building a new virtual dom for items took ' + (t1 - t0) + ' ms.'); 261 | } 262 | this._update(); 263 | } 264 | 265 | /** 266 | * Minimal wrapper around Vidom's update function to give user a visual feedback 267 | * for the duration of the update. 268 | * @param {Function} cb - callback function forwarded to Vidom's update function 269 | */ 270 | _update(cb) { 271 | if (process.env.NODE_ENV === 'development') { 272 | var t0 = performance.now(); 273 | } 274 | this.update(() => { 275 | if (process.env.NODE_ENV === 'development') { 276 | let t1 = performance.now(); 277 | console.log('Rendering took ' + (t1 - t0) + ' ms.'); 278 | } 279 | if(cb) { 280 | cb.apply(this, arguments); 281 | } 282 | window.document.body.classList.remove('styles-processing'); 283 | }); 284 | } 285 | 286 | /** 287 | * Handler called when user makes a query. Starts visual feedback 288 | * and triggers search based on current state and the new query parameters 289 | * @param {Object} query - object containing query parameters 290 | */ 291 | onQuery(query) { 292 | // in modern browsers helps ensure we render visual feedback 293 | if(requestAnimationFrame) { 294 | window.document.body.classList.add('styles-processing'); 295 | window.document.body.offsetHeight; // reflow shenanigans 296 | requestAnimationFrame(() => { 297 | requestAnimationFrame(() => { 298 | this.zsr.search(extend({}, this.state.query, query)); 299 | }); 300 | }); 301 | } else { 302 | window.document.body.classList.add('styles-processing'); 303 | this.zsr.search(extend({}, this.state.query, query)); 304 | } 305 | } 306 | 307 | constructor(zsr) { 308 | super(); 309 | this.onQuery = debounce(this.onQuery, 150); 310 | this.zsr = zsr; 311 | this.state = this.zsr.state; 312 | this.state.onChange(this.onStateChange.bind(this)); 313 | } 314 | } -------------------------------------------------------------------------------- /include/Styles_Repo.inc.php: -------------------------------------------------------------------------------- 1 | . 23 | 24 | ***** END LICENSE BLOCK ***** 25 | */ 26 | 27 | require_once("Styles.inc.php"); 28 | 29 | class Styles_Repo { 30 | private static $renamedStyles; 31 | 32 | public static function getAllStyles() { 33 | $styles = array(); 34 | $names = array(); 35 | 36 | // Independent 37 | $dir = STYLES_PATH; 38 | $dh = opendir($dir); 39 | if (!$dh) { 40 | throw new Exception("Can't open directory"); 41 | } 42 | while (($file = readdir($dh)) !== false) { 43 | if (strpos($file, ".") !== false) { 44 | continue; 45 | } 46 | if ($file == 'dependent') { 47 | continue; 48 | } 49 | 50 | $data = self::parseStyle($file, file_get_contents($dir . $file)); 51 | 52 | $data['disambiguate'] = false; 53 | 54 | $styles[] = $data; 55 | $names[$file] = true; 56 | } 57 | 58 | // Dependent 59 | $dir = STYLES_PATH . 'dependent/'; 60 | $dh = opendir($dir); 61 | if (!$dh) { 62 | throw new Exception("Can't open directory"); 63 | } 64 | while (($file = readdir($dh)) !== false) { 65 | if (strpos($file, ".") !== false) { 66 | continue; 67 | } 68 | 69 | $data = self::parseStyle($file, file_get_contents($dir . $file), 1); 70 | 71 | $data['disambiguate'] = isset($names[$file]); 72 | 73 | $styles[] = $data; 74 | } 75 | 76 | usort($styles, function ($a, $b) { 77 | $aTitle = $a['title']; 78 | $bTitle = $b['title']; 79 | // TEMP: for Österreichische... 80 | if ($aTitle[0] == "\xc3") { 81 | $aTitle[0] = 'O'; 82 | } 83 | if ($bTitle[0] == "\xc3") { 84 | $bTitle[0] = 'O'; 85 | } 86 | return strcasecmp($aTitle, $bTitle); 87 | }); 88 | 89 | return $styles; 90 | } 91 | 92 | 93 | public static function getCacheValues() { 94 | $cacheFile = ROOT_PATH . "styles/data/cache"; 95 | if (!file_exists($cacheFile)) { 96 | return false; 97 | } 98 | return json_decode(file_get_contents($cacheFile), true); 99 | } 100 | 101 | 102 | public static function setCacheValues($styleList) { 103 | $cacheFile = ROOT_PATH . "styles/data/cache"; 104 | $data = array(); 105 | $lastModified = ''; 106 | foreach ($styleList as $style) { 107 | if ($style['updated'] > $lastModified) { 108 | $lastModified = $style['updated']; 109 | } 110 | $data[] = $style['name'] . $style['updated']; 111 | } 112 | $lastModified = gmdate("D, d M Y H:i:s", strtotime($lastModified)) . " GMT"; 113 | $etag = md5(implode('', $data)); 114 | $json = json_encode(array( 115 | 'lastModified' => $lastModified, 116 | 'etag' => $etag 117 | )); 118 | file_put_contents($cacheFile, $json); 119 | } 120 | 121 | 122 | public static function isValidName($name) { 123 | if (strpos($name, ".") !== false) { 124 | return false; 125 | } 126 | return true; 127 | } 128 | 129 | 130 | public static function getFilePath($name, $dependent=false) { 131 | // TEMP 132 | if ($name == 'bluebook-19th') { 133 | return file_get_contents(ROOT_PATH . 'include/bluebook-19th.csl'); 134 | } 135 | 136 | if (!self::isValidName($name)) { 137 | throw new Exception('$name cannot include periods'); 138 | } 139 | 140 | return STYLES_PATH . ($dependent ? 'dependent/' : '') . $name; 141 | } 142 | 143 | 144 | public static function getRenamedStyle($oldName) { 145 | if (!self::$renamedStyles) { 146 | // Get renamed styles from cache, GitHub, or disk 147 | $renamed = apcu_fetch('renamed_styles'); 148 | if (!$renamed) { 149 | if (defined('RENAMED_STYLES_URL')) { 150 | error_log("Fetching " . RENAMED_STYLES_URL); 151 | $renamed = file_get_contents(RENAMED_STYLES_URL); 152 | } 153 | if (!$renamed) { 154 | $renamed = file_get_contents(ROOT_PATH . "include/renamed-styles.json"); 155 | } 156 | apcu_store('renamed_styles', $renamed, 86400); 157 | } 158 | self::$renamedStyles = json_decode($renamed, true); 159 | } 160 | return self::$renamedStyles[$oldName] ?? false; 161 | } 162 | 163 | 164 | public static function getCode($name, $dependent=false) { 165 | $path = self::getFilePath($name, $dependent); 166 | if (!$path) { 167 | return false; 168 | } 169 | return file_exists($path) ? file_get_contents($path) : false; 170 | } 171 | 172 | 173 | public static function getXML($name, $dependent=false) { 174 | $code = self::getCode($name, $dependent); 175 | if (!$code) { 176 | return false; 177 | } 178 | $xml = new SimpleXMLElement($code); 179 | return $xml; 180 | } 181 | 182 | 183 | public static function getTitle($name, $dependent=false) { 184 | $xml = self::getXML($name, $dependent); 185 | if (!$xml) { 186 | return ""; 187 | } 188 | return (string) $xml->info->title; 189 | } 190 | 191 | 192 | public static function getLastModified($name, $dependent=false) { 193 | $xml = self::getXML($name, $dependent); 194 | if (!$xml) { 195 | return ""; 196 | } 197 | $lastUpdated = (string) $xml->info->updated; 198 | return gmdate("D, d M Y H:i:s", strtotime($lastUpdated)) . " GMT"; 199 | } 200 | 201 | 202 | /** 203 | * Gets the preview citations for the style as a JSON array 204 | * 205 | * Independent styles only 206 | */ 207 | public static function getPreviewCitations($name, $asJSON=false) { 208 | if (strpos($name, ".") !== false) { 209 | throw new Exception("Invalid name '" . $name . "'"); 210 | } 211 | 212 | $path = ROOT_PATH . 'htdocs/styles-files/previews/citation/' . $name . '.json'; 213 | 214 | if (!file_exists($path)) { 215 | error_log("Preview citations file '$name.json' not found"); 216 | return ""; 217 | } 218 | 219 | $citations = file_get_contents($path); 220 | 221 | if ($asJSON) { 222 | return $citations; 223 | } 224 | 225 | return json_decode($citations); 226 | } 227 | 228 | 229 | public static function setPreviewCitations($name, $preview, $dependent=false) { 230 | if (strpos($name, ".") !== false) { 231 | throw new Exception("Invalid name '" . $name . "'"); 232 | } 233 | 234 | $path = ROOT_PATH . 'htdocs/styles-files/previews/citation/'; 235 | if ($dependent) { 236 | $path .= 'dependent/'; 237 | } 238 | $path .= $name . '.json'; 239 | $preview = file_put_contents($path, json_encode($preview)); 240 | } 241 | 242 | public static function setPreviewCombined($name, $previewCitation, $previewBibliography, $dependent=false) { 243 | if (strpos($name, ".") !== false) { 244 | throw new Exception("Invalid name '" . $name . "'"); 245 | } 246 | 247 | $path = ROOT_PATH . 'htdocs/styles-files/previews/combined/'; 248 | if ($dependent) { 249 | $path .= 'dependent/'; 250 | } 251 | $path .= $name . '.json'; 252 | 253 | 254 | $preview = array( 255 | "citation" => $previewCitation, 256 | "bibliography" => $previewBibliography 257 | ); 258 | 259 | $preview = file_put_contents($path, json_encode($preview)); 260 | } 261 | 262 | 263 | /** 264 | * Gets the preview HTML for the style 265 | * 266 | * Independent styles only 267 | */ 268 | public static function getPreviewBibliography($name) { 269 | if (strpos($name, ".") !== false) { 270 | throw new Exception("Invalid name '" . $name . "'"); 271 | 272 | } 273 | 274 | $path = ROOT_PATH . 'htdocs/styles-files/previews/bib/' . $name . '.html'; 275 | 276 | if (!file_exists($path)) { 277 | error_log("Preview bibliography file '$name.html' not found"); 278 | return ""; 279 | } 280 | 281 | $preview = file_get_contents($path); 282 | 283 | return $preview; 284 | } 285 | 286 | 287 | public static function setPreviewBibliography($name, $preview, $dependent=false) { 288 | if (strpos($name, ".") !== false) { 289 | throw new Exception("Invalid name '" . $name . "'"); 290 | } 291 | 292 | $path = ROOT_PATH . 'htdocs/styles-files/previews/bib/' 293 | . ($dependent ? 'dependent/' : '') . $name . '.html'; 294 | $preview = file_put_contents($path, $preview); 295 | } 296 | 297 | 298 | private static function parseStyle($name, $code, $dependent=0) { 299 | try { 300 | $xml = new SimpleXMLElement($code); 301 | } 302 | catch (Exception $e) { 303 | error_log("Error parsing $name"); 304 | return false; 305 | } 306 | 307 | $categories = array( 308 | "format" => "", 309 | "fields" => array() 310 | ); 311 | $set = false; 312 | foreach ($xml->info->category as $category) { 313 | if (!empty($category['citation-format'])) { 314 | $categories["format"] = (string) $category['citation-format']; 315 | $set = true; 316 | } 317 | else if (!empty($category['field'])) { 318 | $categories["fields"][] = (string) $category['field']; 319 | $set = true; 320 | } 321 | } 322 | if (!$set) { 323 | $categories = null; 324 | } 325 | 326 | $data = file_get_contents(ROOT_PATH . 'styles/data/' . ($dependent ? 'dependent/' : '') . $name); 327 | if ($data) { 328 | $data = json_decode($data); 329 | } 330 | // Default to valid 331 | else { 332 | $data = new stdClass; 333 | $data->valid = true; 334 | } 335 | 336 | $data = array( 337 | 'name' => $name, 338 | 'dependent' => $dependent, 339 | 'updated' => (string) $xml->info->updated, 340 | 'title' => (string) $xml->info->title, 341 | 'titleShort' => (string) $xml->info->{'title-short'}, 342 | 'valid' => $data->valid, 343 | 'categories' => $categories, 344 | 'code' => $code 345 | ); 346 | 347 | return $data; 348 | } 349 | } 350 | ?> 351 | -------------------------------------------------------------------------------- /include/bluebook-19th.csl: -------------------------------------------------------------------------------- 1 | 2 | 614 | -------------------------------------------------------------------------------- /include/renamed-styles.json: -------------------------------------------------------------------------------- 1 | { 2 | "aaa": "american-anthropological-association", 3 | "acta-theriologica": "mammal-research", 4 | "advances-physiology-education": "advances-in-physiology-education", 5 | "aegean-review-of-the-law-of-the-sea-and-maritime-law": "springer-basic-author-date", 6 | "agriculture-ecosystems-environment": "agriculture-ecosystems-and-environment", 7 | "ajp-heart-circulatory-physiology": "ajp-heart-and-circulatory-physiology", 8 | "ajp-regulatory-integrative-comparative-physiology": "ajp-regulatory-integrative-and-comparative-physiology", 9 | "ama": "american-medical-association", 10 | "american-chemical-society-author-date": "american-chemical-society", 11 | "american-chemical-society-page-first": "american-chemical-society", 12 | "american-chemical-society-with-titles": "american-chemical-society", 13 | "american-chemical-society-with-titles-brackets": "american-chemical-society", 14 | "american-chemical-society-with-titles-doi-no-et-al": "american-chemical-society", 15 | "american-chemical-society-with-titles-no-et-al": "american-chemical-society", 16 | "american-chemical-society-with-titles-page-first": "american-chemical-society", 17 | "american-chemical-society-with-titles-sentence-case": "american-chemical-society", 18 | "american-chemical-society-with-titles-sentence-case-doi": "american-chemical-society", 19 | "american-journal-of-cardiology": "the-american-journal-of-cardiology", 20 | "american-journal-of-clinical-nutrition": "the-american-journal-of-clinical-nutrition", 21 | "american-journal-of-human-genetics": "the-american-journal-of-human-genetics", 22 | "american-journal-of-medicine": "the-american-journal-of-medicine", 23 | "american-journal-of-pathology": "the-american-journal-of-pathology", 24 | "american-journal-of-sports-medicine": "the-american-journal-of-sports-medicine", 25 | "american-journal-of-surgery": "the-american-journal-of-surgery", 26 | "american-journal-of-tropical-medicine-and-hygiene": "the-american-journal-of-tropical-medicine-and-hygiene", 27 | "american-medical-writers-association": "american-medical-writers-association-journal", 28 | "american-surgeon": "the-american-surgeon", 29 | "amiens": "universite-de-picardie-jules-verne-ufr-de-medecine", 30 | "analytical-abstracts": "royal-society-of-chemistry", 31 | "annalen-des-naturhistorischen-museums-wien": "annalen-des-naturhistorischen-museums-in-wien", 32 | "annals-of-allergy": "annals-of-allergy-asthma-and-immunology", 33 | "annals-of-thoracic-surgery": "the-annals-of-thoracic-surgery", 34 | "annual-reviews-alphabetically": "annual-reviews-alphabetical", 35 | "annual-reviews-by-appearance": "annual-reviews", 36 | "apa-fr": "apa-fr-provost", 37 | "apa-fr-universite-de-montreal": "universite-de-montreal-apa", 38 | "apa5th": "apa-5th-edition", 39 | "apsa": "american-political-science-association", 40 | "archives-of-dermatology": "jama-dermatology", 41 | "asa": "american-sociological-association", 42 | "associacao-brasileira-de-normas-tecnicas-ufjf": "universidade-federal-de-juiz-de-fora", 43 | "australian-law-journal": "the-australian-law-journal", 44 | "automated-experimentation": "biomed-central", 45 | "bba-biochimica-et-biophysica-acta": "biochimica-et-biophysica-acta", 46 | "bio-medical-reviews": "biomedical-reviews", 47 | "bmc-blood-disorders": "biomed-central", 48 | "bmc-chemical-biology": "biomed-central", 49 | "bmc-clinical-pharmacology": "biomed-central", 50 | "bmc-pharmacology": "biomed-central", 51 | "bmj-supportive-palliative-care": "bmj-supportive-and-palliative-care", 52 | "brain-and-development-english-language": "brain-and-development", 53 | "british-ecological-society": "apa-old-doi-prefix", 54 | "british-volume-of-the-journal-of-bone-and-joint-surgery": "the-journal-of-bone-and-joint-surgery", 55 | "bulletin-of-materials-science": "springer-humanities-author-date", 56 | "bulletin-of-the-medical-library-association": "journal-of-the-medical-library-association", 57 | "canadian-journal-of-anaesthesia": "canadian-journal-of-anesthesia", 58 | "canadian-journal-of-behavioral-science": "canadian-journal-of-behavioural-science", 59 | "canadian-journal-of-hospital-pharmacy": "the-canadian-journal-of-hospital-pharmacy", 60 | "canadian-medical-association-journal": "cmaj", 61 | "canadian-veterinary-journal": "the-canadian-veterinary-journal", 62 | "cancer-epidemiology-biomarkers-prevention": "cancer-epidemiology-biomarkers-and-prevention", 63 | "cardiovascular-pharmacology-and-therapeutics": "journal-of-cardiovascular-pharmacology-and-therapeutics", 64 | "catalysts-and-catalysed-reactions": "royal-society-of-chemistry", 65 | "central-african-journal-of-medicine": "the-central-african-journal-of-medicine", 66 | "ceylon-journal-of-medical-science": "the-ceylon-journal-of-medical-science", 67 | "ceylon-medical-journal": "the-ceylon-medical-journal", 68 | "chemical-hazards-in-industry": "royal-society-of-chemistry", 69 | "chicago-fullnote-bibliography-no-ibid": "chicago-fullnote-bibliography", 70 | "chicago-note": "chicago-note-bibliography", 71 | "chicago-note-biblio-no-ibid": "chicago-note-bibliography", 72 | "chinese-journal-of-geochemistry": "acta-geochimica", 73 | "chronic-diseases-in-canada": "chronic-diseases-and-injuries-in-canada", 74 | "college-of-physicians-and-surgeons-pakistan": "journal-of-the-college-of-physicians-and-surgeons-pakistan", 75 | "combination-products-in-therapy": "springer-vancouver-brackets", 76 | "comparative-effectiveness-research": "journal-of-comparative-effectiveness-research", 77 | "comparative-hepatology": "biomed-central", 78 | "criminal-law-and-philosophy": "springer-socpsych-author-date", 79 | "cuadernos-filologia-clasica": "cuadernos-de-filologia-clasica", 80 | "current-hepatitis-reports": "current-hepatology-reports", 81 | "current-opinion-biotechnology": "current-opinion-in-biotechnology", 82 | "current-opinion-cell-biology": "current-opinion-in-cell-biology", 83 | "current-opinion-chemical-biology": "current-opinion-in-chemical-biology", 84 | "current-opinion-environmental-sustainability": "current-opinion-in-environmental-sustainability", 85 | "current-opinion-genetics-development": "current-opinion-in-genetics-and-development", 86 | "current-opinion-immunology": "current-opinion-in-immunology", 87 | "current-opinion-microbiology": "current-opinion-in-microbiology", 88 | "current-opinion-neurobiology": "current-opinion-in-neurobiology", 89 | "current-opinion-pharmacology": "current-opinion-in-pharmacology", 90 | "current-opinion-plant-biology": "current-opinion-in-plant-biology", 91 | "current-opinion-structural-biology": "current-opinion-in-structural-biology", 92 | "current-respiratory-care-reports": "current-pulmonology-reports", 93 | "current-translational-geriatrics-and-gerontology-reports": "current-geriatrics-reports", 94 | "danish-dental-journal": "tandlaegebladet", 95 | "danish-medical-bulletin": "danish-medical-journal", 96 | "diabetes-vascular-disease-research": "diabetes-and-vascular-disease-research", 97 | "disease-models-mechanisms": "disease-models-and-mechanisms", 98 | "diseases-aquatic-organisms": "diseases-of-aquatic-organisms", 99 | "edizioni-minerva-medica": "minerva-medica", 100 | "ethics-science-environmental-politics": "ethics-in-science-and-environmental-politics", 101 | "european-journal-of-population-revue-europeenne-de-demographie": "european-journal-of-population", 102 | "expert-review-of-dermatology": "taylor-and-francis-national-library-of-medicine", 103 | "expert-review-of-obstetrics-and-gynecology": "taylor-and-francis-national-library-of-medicine", 104 | "f1000-research": "f1000research", 105 | "fachhochschule-vorarlberg": "fachhochschule-vorarlberg-author-date", 106 | "febs-journal": "the-febs-journal", 107 | "federation-of-european-microbiological-societies": "oxford-university-press-scimed-author-date", 108 | "fems": "oxford-university-press-scimed-author-date", 109 | "firstmonday": "first-monday", 110 | "friedrich-schiller-university-jena-faculty-of-medicine": "friedrich-schiller-universitat-jena-medizinische-fakultat", 111 | "frontiers-in-addictive-disorders": "frontiers", 112 | "frontiers-in-affective-disorders-and-psychosomatic-research": "frontiers", 113 | "frontiers-in-alloimmunity-and-transplantation": "frontiers", 114 | "frontiers-in-antigen-presenting-cell-biology": "frontiers", 115 | "frontiers-in-antimicrobials-resistance-and-chemotherapy": "frontiers", 116 | "frontiers-in-applied-genetic-epidemiology": "frontiers", 117 | "frontiers-in-aquatic-microbiology": "frontiers", 118 | "frontiers-in-aquatic-physiology": "frontiers", 119 | "frontiers-in-auditory-cognitive-neuroscience": "frontiers", 120 | "frontiers-in-autonomic-neuroscience": "frontiers", 121 | "frontiers-in-b-cell-biology": "frontiers", 122 | "frontiers-in-behavioral-and-psychiatric-genetics": "frontiers", 123 | "frontiers-in-bioinformatics-and-computational-biology": "frontiers", 124 | "frontiers-in-bone-research": "frontiers", 125 | "frontiers-in-brain-imaging-methods": "frontiers", 126 | "frontiers-in-cancer-endocrinology": "frontiers", 127 | "frontiers-in-cancer-epidemiology-and-prevention": "frontiers", 128 | "frontiers-in-cancer-genetics": "frontiers", 129 | "frontiers-in-cancer-imaging-and-diagnosis": "frontiers", 130 | "frontiers-in-cancer-molecular-targets-and-therapeutics": "frontiers", 131 | "frontiers-in-cardiac-electrophysiology": "frontiers", 132 | "frontiers-in-cardiovascular-and-smooth-muscle-pharmacology": "frontiers", 133 | "frontiers-in-cellular-endocrinology": "frontiers", 134 | "frontiers-in-chemoattractants": "frontiers", 135 | "frontiers-in-child-and-neurodevelopmental-psychiatry": "frontiers", 136 | "frontiers-in-clinical-and-translational-physiology": "frontiers", 137 | "frontiers-in-cognition": "frontiers", 138 | "frontiers-in-cognitive-science": "frontiers", 139 | "frontiers-in-comparative-psychology": "frontiers", 140 | "frontiers-in-computational-physiology-and-medicine": "frontiers", 141 | "frontiers-in-consciousness-research": "frontiers", 142 | "frontiers-in-craniofacial-biology": "frontiers", 143 | "frontiers-in-crop-science-and-horticulture": "frontiers", 144 | "frontiers-in-cultural-psychology": "frontiers", 145 | "frontiers-in-decision-neuroscience": "frontiers", 146 | "frontiers-in-dementia": "frontiers", 147 | "frontiers-in-developmental-psychology": "frontiers", 148 | "frontiers-in-diabetes": "frontiers", 149 | "frontiers-in-drug-metabolism-and-transport": "frontiers", 150 | "frontiers-in-educational-psychology": "frontiers", 151 | "frontiers-in-emotion-science": "frontiers", 152 | "frontiers-in-endocrinology-of-aging": "frontiers", 153 | "frontiers-in-endovascular-and-interventional-neurology": "frontiers", 154 | "frontiers-in-epigenomics": "frontiers", 155 | "frontiers-in-epilepsy": "frontiers", 156 | "frontiers-in-ethnopharmacology": "frontiers", 157 | "frontiers-in-evolutionary-and-genomic-microbiology": "frontiers", 158 | "frontiers-in-evolutionary-and-population-genetics": "frontiers", 159 | "frontiers-in-evolutionary-psychology": "frontiers", 160 | "frontiers-in-exercise-physiology": "frontiers", 161 | "frontiers-in-experimental-endocrinology": "frontiers", 162 | "frontiers-in-experimental-pharmacology-and-drug-discovery": "frontiers", 163 | "frontiers-in-extreme-microbiology": "frontiers", 164 | "frontiers-in-fatty-acid-and-lipid-physiology": "frontiers", 165 | "frontiers-in-food-microbiology": "frontiers", 166 | "frontiers-in-forensic-psychiatry": "frontiers", 167 | "frontiers-in-fractal-physiology": "frontiers", 168 | "frontiers-in-functional-plant-ecology": "frontiers", 169 | "frontiers-in-fungi-and-their-interactions": "frontiers", 170 | "frontiers-in-gastrointestinal-cancers": "frontiers", 171 | "frontiers-in-gastrointestinal-pharmacology": "frontiers", 172 | "frontiers-in-gastrointestinal-sciences": "frontiers", 173 | "frontiers-in-genetic-architecture": "frontiers", 174 | "frontiers-in-genetics-of-aging": "frontiers", 175 | "frontiers-in-genitourinary-oncology": "frontiers", 176 | "frontiers-in-genomic-assay-technology": "frontiers", 177 | "frontiers-in-genomic-endocrinology": "frontiers", 178 | "frontiers-in-genomic-physiology": "frontiers", 179 | "frontiers-in-head-and-neck-cancer": "frontiers", 180 | "frontiers-in-headache-medicine-and-facial-pain": "frontiers", 181 | "frontiers-in-hematology-oncology": "frontiers", 182 | "frontiers-in-hiv-and-aids": "frontiers", 183 | "frontiers-in-immunological-memory": "frontiers", 184 | "frontiers-in-immunological-tolerance": "frontiers", 185 | "frontiers-in-immunotherapies-and-vaccines": "frontiers", 186 | "frontiers-in-impulsivity-compulsivity-and-behavioral-dyscontrol": "frontiers", 187 | "frontiers-in-inflammation": "frontiers", 188 | "frontiers-in-inflammation-pharmacology": "frontiers", 189 | "frontiers-in-integrative-and-regenerative-pharmacology": "frontiers", 190 | "frontiers-in-integrative-physiology": "frontiers", 191 | "frontiers-in-invertebrate-physiology": "frontiers", 192 | "frontiers-in-language-sciences": "frontiers", 193 | "frontiers-in-livestock-genomics": "frontiers", 194 | "frontiers-in-membrane-physiology-and-biophysics": "frontiers", 195 | "frontiers-in-microbial-immunology": "frontiers", 196 | "frontiers-in-microbial-physiology-and-metabolism": "frontiers", 197 | "frontiers-in-microbiological-chemistry": "frontiers", 198 | "frontiers-in-microbiotechnology-ecotoxicology-and-bioremediation": "frontiers", 199 | "frontiers-in-mitochondrial-research": "frontiers", 200 | "frontiers-in-molecular-and-cellular-oncology": "frontiers", 201 | "frontiers-in-molecular-and-structural-endocrinology": "frontiers", 202 | "frontiers-in-molecular-innate-immunity": "frontiers", 203 | "frontiers-in-molecular-psychiatry": "frontiers", 204 | "frontiers-in-movement-disorders": "frontiers", 205 | "frontiers-in-movement-science-and-sport-psychology": "frontiers", 206 | "frontiers-in-mucosal-immunity": "frontiers", 207 | "frontiers-in-multiple-sclerosis-and-neuroimmunology": "frontiers", 208 | "frontiers-in-neuro-ophthalmology": "frontiers", 209 | "frontiers-in-neuro-otology": "frontiers", 210 | "frontiers-in-neurocritical-and-neurohospitalist-care": "frontiers", 211 | "frontiers-in-neurodegeneration": "frontiers", 212 | "frontiers-in-neuroendocrine-science": "frontiers", 213 | "frontiers-in-neurogenesis": "frontiers", 214 | "frontiers-in-neurogenomics": "frontiers", 215 | "frontiers-in-neurology-education": "frontiers", 216 | "frontiers-in-neuromorphic-engineering": "frontiers", 217 | "frontiers-in-neuromuscular-diseases": "frontiers", 218 | "frontiers-in-neuropharmacology": "frontiers", 219 | "frontiers-in-neuroprosthetics": "frontiers", 220 | "frontiers-in-neuropsychiatric-imaging-and-stimulation": "frontiers", 221 | "frontiers-in-neurotrauma": "frontiers", 222 | "frontiers-in-nk-cell-biology": "frontiers", 223 | "frontiers-in-non-coding-rna": "frontiers", 224 | "frontiers-in-nutrigenomics": "frontiers", 225 | "frontiers-in-oxidant-physiology": "frontiers", 226 | "frontiers-in-pediatric-endocrinology": "frontiers", 227 | "frontiers-in-pediatric-oncology": "frontiers", 228 | "frontiers-in-perception-science": "frontiers", 229 | "frontiers-in-personality-science-and-individual-differences": "frontiers", 230 | "frontiers-in-pharmaceutical-medicine-and-outcomes-research": "frontiers", 231 | "frontiers-in-pharmacogenetics-and-pharmacogenomics": "frontiers", 232 | "frontiers-in-pharmacology-of-anti-cancer-drugs": "frontiers", 233 | "frontiers-in-pharmacology-of-ion-channels-and-channelopathies": "frontiers", 234 | "frontiers-in-pituitary-endocrinology": "frontiers", 235 | "frontiers-in-plant-biophysics-and-modeling": "frontiers", 236 | "frontiers-in-plant-biotechnology": "frontiers", 237 | "frontiers-in-plant-cell-biology": "frontiers", 238 | "frontiers-in-plant-evolution-and-development": "frontiers", 239 | "frontiers-in-plant-genetics-and-genomics": "frontiers", 240 | "frontiers-in-plant-metabolism-and-chemodiversity": "frontiers", 241 | "frontiers-in-plant-microbe-interaction": "frontiers", 242 | "frontiers-in-plant-nutrition": "frontiers", 243 | "frontiers-in-plant-physiology": "frontiers", 244 | "frontiers-in-plant-proteomics": "frontiers", 245 | "frontiers-in-plant-systems-biology": "frontiers", 246 | "frontiers-in-plant-traffic-and-transport": "frontiers", 247 | "frontiers-in-predictive-toxicity": "frontiers", 248 | "frontiers-in-primary-immunodeficiencies": "frontiers", 249 | "frontiers-in-psychoanalysis-and-neuropsychoanalysis": "frontiers", 250 | "frontiers-in-psychology-for-clinical-settings": "frontiers", 251 | "frontiers-in-psychopathology": "frontiers", 252 | "frontiers-in-psychopharmacology": "frontiers", 253 | "frontiers-in-quantitative-psychology-and-measurement": "frontiers", 254 | "frontiers-in-radiation-oncology": "frontiers", 255 | "frontiers-in-renal-and-epithelial-physiology": "frontiers", 256 | "frontiers-in-respiratory-pharmacology": "frontiers", 257 | "frontiers-in-respiratory-physiology": "frontiers", 258 | "frontiers-in-schizophrenia": "frontiers", 259 | "frontiers-in-sleep-and-chronobiology": "frontiers", 260 | "frontiers-in-sleep-disorders": "frontiers", 261 | "frontiers-in-spinal-cord-medicine": "frontiers", 262 | "frontiers-in-sports-neurology": "frontiers", 263 | "frontiers-in-statistical-genetics-and-methodology": "frontiers", 264 | "frontiers-in-striated-muscle-physiology": "frontiers", 265 | "frontiers-in-stroke": "frontiers", 266 | "frontiers-in-systems-and-translational-endocrinology": "frontiers", 267 | "frontiers-in-systems-biology": "frontiers", 268 | "frontiers-in-systems-physiology": "frontiers", 269 | "frontiers-in-t-cell-biology": "frontiers", 270 | "frontiers-in-technical-advances-in-plant-science": "frontiers", 271 | "frontiers-in-teleneurology": "frontiers", 272 | "frontiers-in-terrestrial-microbiology": "frontiers", 273 | "frontiers-in-theoretical-and-philosophical-psychology": "frontiers", 274 | "frontiers-in-thoracic-oncology": "frontiers", 275 | "frontiers-in-thyroid-endocrinology": "frontiers", 276 | "frontiers-in-toxicogenomics": "frontiers", 277 | "frontiers-in-tumor-immunity": "frontiers", 278 | "frontiers-in-vascular-physiology": "frontiers", 279 | "frontiers-in-virology": "frontiers", 280 | "frontiers-in-womens-cancer": "frontiers", 281 | "future-science": "future-science-journals", 282 | "geistes-und-kulturwissenschaften-teilmann": "geistes-und-kulturwissenschaften-heilmann", 283 | "genetic-vaccines-and-therapy": "biomed-central", 284 | "geological-society-america-bulletin": "geological-society-of-america-bulletin", 285 | "geological-society-of-america": "the-geological-society-of-america", 286 | "giornale-italiano-di-health-technology-assessment": "springer-vancouver-brackets", 287 | "gost-r-7-0-5-2008-csl-1-0": "gost-r-7-0-5-2008", 288 | "graefes-archive-and-experimental-ophthalmology": "graefes-archive-for-clinical-and-experimental-ophthalmology", 289 | "gruppendynamik-und-organisationsberatung": "gruppe-interaktion-organisation-zeitschrift-fur-angewandte-organisationspsychologie", 290 | "harvard-anglia-ruskin": "harvard-anglia-ruskin-university", 291 | "harvard-de-montfort-university": "de-montfort-university-harvard", 292 | "harvard-oxford-brookes-university": "harvard-cite-them-right", 293 | "harvard-sheffield": "harvard-the-university-of-sheffield-town-and-regional-planning", 294 | "harvard-sheffield1": "harvard-the-university-of-sheffield-school-of-east-asian-studies", 295 | "harvard-university-of-northampton": "harvard-the-university-of-northampton", 296 | "harvard-university-of-south-africa": "university-of-south-australia-harvard-2011", 297 | "harvard-university-of-south-australia": "university-of-south-australia-harvard-2011", 298 | "harvard-university-of-west-london": "harvard-cite-them-right", 299 | "harvard-university-west-london": "harvard-cite-them-right", 300 | "harvard1-unisa-gbfe": "harvard-gesellschaft-fur-bildung-und-forschung-in-europa", 301 | "harvard3": "harvard-swinburne-university-of-technology", 302 | "harvard7de": "fachhochschule-vorarlberg-author-date", 303 | "head-and-neck-oncology": "biomed-central", 304 | "hwr-berlin": "hochschule-fur-wirtschaft-und-recht-berlin", 305 | "ices-jms": "ices-journal-of-marine-science", 306 | "ieee-w-url": "ieee-with-url", 307 | "indian-journal-of-virology": "virusdisease", 308 | "information-retrieval": "information-retrieval-journal", 309 | "institute-of-electronics-information-and-communication-engineers": "the-institute-of-electronics-information-and-communication-engineers", 310 | "integrative-omics-and-molecular-biology": "biomed-central", 311 | "international-archives-of-allergy-and-applied-immunology": "international-archives-of-allergy-and-immunology", 312 | "international-journal-cross-cultural-management": "international-journal-of-cross-cultural-management", 313 | "international-journal-of-euro-mediterranean-studies": "springer-basic-author-date", 314 | "international-journal-of-health-care-finance-and-economics": "international-journal-of-health-economics-and-management", 315 | "international-journal-of-psychiatry-in-medicine": "the-international-journal-of-psychiatry-in-medicine", 316 | "international-journal-of-psychoanalysis": "the-international-journal-of-psychoanalysis", 317 | "international-journal-of-the-classical-tradition": "springer-humanities-brackets", 318 | "international-journal-of-tropical-biology-and-conservation": "revista-de-biologia-tropical", 319 | "iranian-journal-of-environmental-health-science-and-engineering": "biomed-central", 320 | "iso690-author-date-fr-without-abstract": "iso690-author-date-fr-no-abstract", 321 | "jahrbuch-fur-regionalwissenschaft": "review-of-regional-research", 322 | "jid-symposium-proceedings": "journal-of-investigative-dermatology-symposium-proceedings", 323 | "journal-fur-betriebswirtschaft": "management-review-quarterly", 324 | "journal-of-aapos": "journal-of-american-association-for-pediatric-ophthalmology-and-strabismus", 325 | "journal-of-allergy-and-clinical-immunology": "the-journal-of-allergy-and-clinical-immunology", 326 | "journal-of-astrophysics-and-astronomy": "springer-humanities-author-date", 327 | "journal-of-bioethical-inquiry": "springer-humanities-author-date", 328 | "journal-of-biorheology": "springer-vancouver-brackets", 329 | "journal-of-bioscience-and-medicine": "biomed-central", 330 | "journal-of-bone-and-joint-surgery": "the-journal-of-bone-and-joint-surgery", 331 | "journal-of-cardiovascular-surgery": "the-journal-of-cardiovascular-surgery", 332 | "journal-of-cell-biology": "the-journal-of-cell-biology", 333 | "journal-of-chemical-physics": "the-journal-of-chemical-physics", 334 | "journal-of-chemical-sciences": "springer-humanities-brackets", 335 | "journal-of-circadian-rhythms": "biomed-central", 336 | "journal-of-clinical-endocrinology-and-metabolism": "the-journal-of-clinical-endocrinology-and-metabolism", 337 | "journal-of-clinical-investigation": "the-journal-of-clinical-investigation", 338 | "journal-of-clinical-psychiatry": "the-journal-of-clinical-psychiatry", 339 | "journal-of-earth-system-science": "springer-humanities-author-date", 340 | "journal-of-experimental-medicine": "the-journal-of-experimental-medicine", 341 | "journal-of-experimental-psychology-animal-behavior-processes": "journal-of-experimental-psychology-animal-learning-and-cognition", 342 | "journal-of-general-physiology": "the-journal-of-general-physiology", 343 | "journal-of-genetics": "springer-humanities-author-date", 344 | "journal-of-geometric-analysis": "springer-mathphys-brackets", 345 | "journal-of-global-policy-and-governance": "springer-basic-author-date", 346 | "journal-of-hand-surgery": "the-journal-of-hand-surgery", 347 | "journal-of-heart-and-lung-transplantation": "the-journal-of-heart-and-lung-transplantation", 348 | "journal-of-hellenic-studies": "the-journal-of-hellenic-studies", 349 | "journal-of-hepato-biliary-pancreatic-sciences": "springer-vancouver-brackets", 350 | "journal-of-hong-kong-medical-association": "hong-kong-medical-journal", 351 | "journal-of-indian-prosthodontic-society": "the-journal-of-indian-prosthodontic-society", 352 | "journal-of-juristic-papyrology": "the-journal-of-juristic-papyrology", 353 | "journal-of-medieval-and-early-modern-studies": "the-journal-of-medieval-and-early-modern-studies", 354 | "journal-of-modern-history": "the-journal-of-modern-history", 355 | "journal-of-neuro-interventional-surgery": "journal-of-neurointerventional-surgery", 356 | "journal-of-nuclear-medicine": "the-journal-of-nuclear-medicine", 357 | "journal-of-organic-chemistry": "the-journal-of-organic-chemistry", 358 | "journal-of-pediatrics": "the-journal-of-pediatrics", 359 | "journal-of-pharmacology-and-experimental-therapeutics": "the-journal-of-pharmacology-and-experimental-therapeutics", 360 | "journal-of-pharmacy-technology": "the-journal-of-pharmacy-technology", 361 | "journal-of-physical-chemistry": "the-journal-of-physical-chemistry-a", 362 | "journal-of-prosthetic-dentistry": "the-journal-of-prosthetic-dentistry", 363 | "journal-of-science-teacher-education": "springer-socpsych-author-date", 364 | "journal-of-spinal-disorders-and-techniques": "clinical-spine-surgery", 365 | "journal-of-the-american-academy-of-physician-assistants": "jaapa", 366 | "journal-of-the-american-dental-association": "the-journal-of-the-american-dental-association", 367 | "journal-of-the-american-medical-association": "jama", 368 | "journal-of-the-american-medical-informatics-association": "jamia", 369 | "journal-of-the-american-osteopathic-association": "the-journal-of-the-american-osteopathic-association", 370 | "journal-of-the-geological-society-of-london": "journal-of-the-geological-society", 371 | "journal-of-the-indian-society-of-pedodontics-and-preventative-dentistry": "journal-of-the-indian-society-of-pedodontics-and-preventive-dentistry", 372 | "journal-of-the-institute-of-medicine": "journal-of-institute-of-medicine", 373 | "journal-of-the-torrey-botanical-society": "the-journal-of-the-torrey-botanical-society", 374 | "journal-of-thoracic-and-cardiovascular-surgery": "the-journal-of-thoracic-and-cardiovascular-surgery", 375 | "journal-of-wildlife-management": "the-journal-of-wildlife-management", 376 | "juristische-zitierweise-deutsch": "juristische-zitierweise", 377 | "korean-journal-of-gynecologic-oncology": "journal-of-gynecologic-oncology", 378 | "la-revue-de-linfirmicre": "la-revue-de-linfirmiere", 379 | "laboratory-hazards-bulletin": "royal-society-of-chemistry", 380 | "lancet": "the-lancet", 381 | "lancet-infectious-diseases": "the-lancet-infectious-diseases", 382 | "lancet-neurology": "the-lancet-neurology", 383 | "lancet-oncology": "the-lancet-oncology", 384 | "law1-de": "juristische-zitierweise", 385 | "lichenologist": "the-lichenologist", 386 | "lncs": "springer-lecture-notes-in-computer-science", 387 | "lncs2": "springer-lecture-notes-in-computer-science-alphabetical", 388 | "malaysian-journal-of-pathology": "the-malaysian-journal-of-pathology", 389 | "manedsskrift-for-praktk-laegegerning": "manedsskrift-for-almen-praksis", 390 | "materials-discovery-today": "materials-discovery", 391 | "mcgill-guide-v7": "mcgill-en", 392 | "mcrj7": "mcgill-fr", 393 | "medical-journal-of-australia": "the-medical-journal-of-australia", 394 | "medicina-militar": "sanidad-militar", 395 | "methods-in-organic-synthesis": "royal-society-of-chemistry", 396 | "methods-information-medicine": "methods-of-information-in-medicine", 397 | "mhra": "modern-humanities-research-association", 398 | "mhra-author-date": "modern-humanities-research-association-author-date", 399 | "mhra_note_without_bibliography": "modern-humanities-research-association", 400 | "mla": "modern-language-association", 401 | "mla-notes": "modern-language-association-6th-edition-note", 402 | "mla-underline": "modern-language-association-7th-edition-underline", 403 | "mla-url": "modern-language-association-7th-edition-with-url", 404 | "modern-language-association-8th-edition": "modern-language-association", 405 | "modern-language-association-note": "modern-language-association-6th-edition-note", 406 | "modern-language-association-underline": "modern-language-association-7th-edition-underline", 407 | "modern-language-association-with-url": "modern-language-association-7th-edition-with-url", 408 | "modern-rheumatology": "springer-vancouver-brackets", 409 | "molecular-biochemical-parasitology": "molecular-and-biochemical-parasitology", 410 | "national-library-of-medicine-grant": "national-library-of-medicine-grant-proposals", 411 | "natural-product-updates": "royal-society-of-chemistry", 412 | "nature-neuroscience-brief-communication": "nature-neuroscience-brief-communications", 413 | "nature-sciences-societes": "natures-sciences-societes", 414 | "natureza-and-conservacao": "perspectives-in-ecology-and-conservation", 415 | "natureza-e-conservacao": "perspectives-in-ecology-and-conservation", 416 | "naturwissenschaften": "the-science-of-nature", 417 | "netherlands-journal-of-medicine": "the-netherlands-journal-of-medicine", 418 | "neumologica-y-cirugia-de-torax-neurofibromatosis": "neumologia-y-cirugia-de-torax", 419 | "neural-systems-and-circuits": "biomed-central", 420 | "new-england-journal-of-medicine": "the-new-england-journal-of-medicine", 421 | "new-iraqi-journal-of-medicine": "the-new-iraqi-journal-of-medicine", 422 | "new-zealand-journal-of-medical-laboratory-technology": "new-zealand-journal-of-medical-laboratory-science", 423 | "new-zealand-medical-journal": "the-new-zealand-medical-journal", 424 | "nexus-network-journal": "springer-humanities-author-date", 425 | "nlm": "national-library-of-medicine", 426 | "nonlinear-biomedical-physics": "biomed-central", 427 | "north-west-university-harvard": "harvard-north-west-university", 428 | "nrl-advances": "springer-basic-brackets", 429 | "open-network-biology": "biomed-central", 430 | "ophthalmic-surgery-lasers-and-imaging": "ophthalmic-surgery-lasers-and-imaging-retina", 431 | "optical-society-of-america": "the-optical-society", 432 | "organic-and-medicinal-chemistry-letters": "chemistry-central-journal", 433 | "oxford-brookes-university-faculty-of-health-and-life-sciences": "harvard-oxford-brookes-university-faculty-of-health-and-life-sciences", 434 | "oxford-university-new-south-wales": "oxford-the-university-of-new-south-wales", 435 | "pedobiologia-international-journal-of-soil-biology": "pedobiologia-journal-of-soil-ecology", 436 | "pharmacoeconomics-german-research-articles": "springer-vancouver-brackets", 437 | "physiological-biochemical-zoology": "physiological-and-biochemical-zoology", 438 | "plant-cell": "the-plant-cell", 439 | "polish-botanical-society": "acta-societatis-botanicorum-poloniae", 440 | "polski-przegld-otorynolaryngologiczny": "polski-przeglad-otorynolaryngologiczny", 441 | "pramana": "springer-physics-brackets", 442 | "proceedings-mathematical-sciences": "springer-mathphys-brackets", 443 | "progrcs-en-urologie": "progres-en-urologie", 444 | "progrcs-en-urologie-fmc": "progres-en-urologie", 445 | "quaderni-avogadro-colloquia": "quaderni-degli-avogadro-colloquia", 446 | "queensland-lawyer": "the-queensland-lawyer", 447 | "rare-cancers-and-therapy": "oncology-and-therapy", 448 | "review-of-financial-studies": "the-review-of-financial-studies", 449 | "revista-brasileira-de-botanica": "brazilian-journal-of-botany", 450 | "rockefeller-university-press": "the-rockefeller-university-press", 451 | "sadhana": "springer-humanities-author-date", 452 | "sbl-fullnote-bibliography": "society-of-biblical-literature-fullnote-bibliography", 453 | "scandinavian-journal-of-clinical-and-laboratory-investigation": "the-scandinavian-journal-of-clinical-and-laboratory-investigation", 454 | "science-without-title": "science-without-titles", 455 | "sensing-and-imaging-an-international-journal": "sensing-and-imaging", 456 | "sexuality-and-early-development-in-aquatic-organisms": "inter-research-science-center", 457 | "silence": "biomed-central", 458 | "small-wiley": "small", 459 | "smartt": "biomed-central", 460 | "society-for-general-microbiology": "microbiology-society", 461 | "soil-biology-biochemistry": "soil-biology-and-biochemistry", 462 | "sozialwissenschaften-teilmann": "sozialwissenschaften-heilmann", 463 | "sports-medicine-arthroscopy-rehabilitation-therapy-and-technology": "biomed-central", 464 | "springer-plasmonics": "plasmonics", 465 | "springer-protocols": "springerprotocols", 466 | "sustainable-healthcare": "biomed-central", 467 | "synergy-research": "synergy", 468 | "tah-gkw": "geistes-und-kulturwissenschaften-heilmann", 469 | "tah-soz": "sozialwissenschaften-heilmann", 470 | "taylor-and-francis-american-psychological-association": "taylor-and-francis-apa", 471 | "taylor-and-francis-reference-style-f": "taylor-and-francis-chicago-f", 472 | "technology-operation-management": "springer-humanities-author-date", 473 | "the-academy-of-management-review": "academy-of-management-review", 474 | "thieme-e-journals-vancouver": "thieme-german", 475 | "tort-law-review": "the-tort-law-review", 476 | "transition-studies-review": "springer-basic-author-date", 477 | "trends-journal": "trends-journals", 478 | "tu-wien-dissertation": "technische-universitat-wien", 479 | "ulster-medical-journal": "the-ulster-medical-journal", 480 | "uludag-universitesi-sosyal-bilimler-enstitusu-full-note-no-ibid": "uludag-universitesi-sosyal-bilimler-enstitusu-full-note", 481 | "uludag-universitesi-sosyal-bilimler-enstitusu-note": "uludag-universitesi-sosyal-bilimler-enstitusu-full-note", 482 | "un-eclac-cepal-english": "economic-commission-for-latin-america-and-the-caribbean", 483 | "un-eclac-cepal-spanish": "comision-economica-para-america-latina-y-el-caribe", 484 | "unctad-english": "united-nations-conference-on-trade-and-development", 485 | "uni-freiburg-geschichte-autor-jahr": "universitat-freiburg-geschichte", 486 | "unified-style-linguistics": "unified-style-sheet-for-linguistics", 487 | "unisa-harvard": "university-of-south-australia-harvard-2011", 488 | "unisa-harvard3": "university-of-south-australia-harvard-2011", 489 | "universite-laval-com": "universite-laval-departement-dinformation-et-de-communication", 490 | "university-college-lillebaelt-vancouver-en": "university-college-lillebaelt-vancouver", 491 | "university-of-melbourne": "harvard-the-university-of-melbourne", 492 | "uqam-universite-du-quebec-a-montreal": "universite-du-quebec-a-montreal", 493 | "user-modeling-and-useradapted-interaction": "user-modeling-and-user-adapted-interaction", 494 | "water-quality-exposure-and-health": "exposure-and-health", 495 | "wceam2010": "world-congress-on-engineering-asset-management", 496 | "wirtschaftsinformatik": "springer-basic-author-date", 497 | "wirtschaftsuniversitat-wien-master-management": "wirtschaftsuniversitat-wien-author-date", 498 | "world-journal-of-biological-psychiatry": "the-world-journal-of-biological-psychiatry", 499 | "integration-the-vlsi-journal": "integration", 500 | "lwt-food-science-and-technology": "lwt", 501 | "reach-reviews-in-human-space-exploration": "reach", 502 | "chemie-der-erde-geochemistry-interdisciplinary-journal-for-chemical-problems-of-the-geosciences-and-geoecology": "chemie-der-erde", 503 | "homo-journal-of-comparative-human-biology": "homo", 504 | "optik-international-journal-for-light-and-electron-optics": "optik", 505 | "zoologischer-anzeiger-a-journal-of-comparative-zoology": "zoologischer-anzeiger", 506 | "advances-in-accounting-incorporating-advances-in-international-accounting": "advances-in-accounting", 507 | "chemie-der-erde-geochemistry-interdisciplinary-journal-for-chemical-problems-of-the-geosciences-and-geoecology": "chemie-der-erde", 508 | "homo-journal-of-comparative-human-biology": "homo", 509 | "optik-international-journal-for-light-and-electron-optics": "optik", 510 | "zoologischer-anzeiger-a-journal-of-comparative-zoology": "zoologischer-anzeiger", 511 | "neurophysiologie-clinique-clinical-neurophysiology": "neurophysiologie-clinique", 512 | "explore-the-journal-of-science-and-healing": "explore", 513 | "journal-of-veterinary-behavior-clinical-applications-and-research": "journal-of-veterinary-behavior", 514 | "web-semantics-science-services-and-agents-on-the-world-wide-web": "journal-of-web-semantics", 515 | "investigaciones-de-historia-economica-economic-history-research": "investigaciones-de-historia-economica", 516 | "reach-reviews-in-human-space-exploration": "reach", 517 | "journal-of-oncological-science": "journal-of-oncological-sciences" 518 | } 519 | --------------------------------------------------------------------------------