diff --git a/.hgignore b/.hgignore new file mode 100644 index 000000000..3dfc510dc --- /dev/null +++ b/.hgignore @@ -0,0 +1,13 @@ +syntax: regexp + +^jsdoc.* +^stripped\.js +^REPLACE\.sh +^NAMES_ORIG.js +^\.emacs-desktop +(^|.*/)machines +(^|.*/)csl +\.*\.result +^HOLD +(^|.*/)\.svn +.*~$ diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..c701c7cc2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,196 @@ +citeproc-js is available under *either* the terms of the modified BSD +license *or* the Academic Free License version 2.1. As a recipient of +citeproc-js, you may choose which license to receive this code under +(except as noted in per-module LICENSE files). citeproc-js modules +are not copyright the Dojo Foundation; this LICENSE applies to all +code in this archive not covered by the Dojo Foundation license. No +external contributions are allowed under licenses which are +fundamentally incompatible with the AFL or BSD licenses that Dojo is +distributed under. + +The text of the AFL and BSD licenses is reproduced below. + +------------------------------------------------------------------------------- +The "New" BSD License: +********************** + +Copyright (c) 2005-2008, The Dojo Foundation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the Dojo Foundation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------------- +The Academic Free License, v. 2.1: +********************************** + +This Academic Free License (the "License") applies to any original work of +authorship (the "Original Work") whose owner (the "Licensor") has placed the +following notice immediately following the copyright notice for the Original +Work: + +Licensed under the Academic Free License version 2.1 + +1) Grant of Copyright License. Licensor hereby grants You a world-wide, +royalty-free, non-exclusive, perpetual, sublicenseable license to do the +following: + +a) to reproduce the Original Work in copies; + +b) to prepare derivative works ("Derivative Works") based upon the Original +Work; + +c) to distribute copies of the Original Work and Derivative Works to the +public; + +d) to perform the Original Work publicly; and + +e) to display the Original Work publicly. + +2) Grant of Patent License. Licensor hereby grants You a world-wide, +royalty-free, non-exclusive, perpetual, sublicenseable license, under patent +claims owned or controlled by the Licensor that are embodied in the Original +Work as furnished by the Licensor, to make, use, sell and offer for sale the +Original Work and Derivative Works. + +3) Grant of Source Code License. The term "Source Code" means the preferred +form of the Original Work for making modifications to it and all available +documentation describing how to modify the Original Work. Licensor hereby +agrees to provide a machine-readable copy of the Source Code of the Original +Work along with each copy of the Original Work that Licensor distributes. +Licensor reserves the right to satisfy this obligation by placing a +machine-readable copy of the Source Code in an information repository +reasonably calculated to permit inexpensive and convenient access by You for as +long as Licensor continues to distribute the Original Work, and by publishing +the address of that information repository in a notice immediately following +the copyright notice that applies to the Original Work. + +4) Exclusions From License Grant. Neither the names of Licensor, nor the names +of any contributors to the Original Work, nor any of their trademarks or +service marks, may be used to endorse or promote products derived from this +Original Work without express prior written permission of the Licensor. Nothing +in this License shall be deemed to grant any rights to trademarks, copyrights, +patents, trade secrets or any other intellectual property of Licensor except as +expressly stated herein. No patent license is granted to make, use, sell or +offer to sell embodiments of any patent claims other than the licensed claims +defined in Section 2. No right is granted to the trademarks of Licensor even if +such marks are included in the Original Work. Nothing in this License shall be +interpreted to prohibit Licensor from licensing under different terms from this +License any Original Work that Licensor otherwise would have a right to +license. + +5) This section intentionally omitted. + +6) Attribution Rights. You must retain, in the Source Code of any Derivative +Works that You create, all copyright, patent or trademark notices from the +Source Code of the Original Work, as well as any notices of licensing and any +descriptive text identified therein as an "Attribution Notice." You must cause +the Source Code for any Derivative Works that You create to carry a prominent +Attribution Notice reasonably calculated to inform recipients that You have +modified the Original Work. + +7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that +the copyright in and to the Original Work and the patent rights granted herein +by Licensor are owned by the Licensor or are sublicensed to You under the terms +of this License with the permission of the contributor(s) of those copyrights +and patent rights. Except as expressly stated in the immediately proceeding +sentence, the Original Work is provided under this License on an "AS IS" BASIS +and WITHOUT WARRANTY, either express or implied, including, without limitation, +the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. +This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No +license to Original Work is granted hereunder except under this disclaimer. + +8) Limitation of Liability. Under no circumstances and under no legal theory, +whether in tort (including negligence), contract, or otherwise, shall the +Licensor be liable to any person for any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License +or the use of the Original Work including, without limitation, damages for loss +of goodwill, work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses. This limitation of liability shall not +apply to liability for death or personal injury resulting from Licensor's +negligence to the extent applicable law prohibits such limitation. Some +jurisdictions do not allow the exclusion or limitation of incidental or +consequential damages, so this exclusion and limitation may not apply to You. + +9) Acceptance and Termination. If You distribute copies of the Original Work or +a Derivative Work, You must make a reasonable effort under the circumstances to +obtain the express assent of recipients to the terms of this License. Nothing +else but this License (or another written agreement between Licensor and You) +grants You permission to create Derivative Works based upon the Original Work +or to exercise any of the rights granted in Section 1 herein, and any attempt +to do so except under the terms of this License (or another written agreement +between Licensor and You) is expressly prohibited by U.S. copyright law, the +equivalent laws of other countries, and by international treaty. Therefore, by +exercising any of the rights granted to You in Section 1 herein, You indicate +Your acceptance of this License and all of its terms and conditions. + +10) Termination for Patent Action. This License shall terminate automatically +and You may no longer exercise any of the rights granted to You by this License +as of the date You commence an action, including a cross-claim or counterclaim, +against Licensor or any licensee alleging that the Original Work infringes a +patent. This termination provision shall not apply for an action alleging +patent infringement by combinations of the Original Work with other software or +hardware. + +11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this +License may be brought only in the courts of a jurisdiction wherein the +Licensor resides or in which Licensor conducts its primary business, and under +the laws of that jurisdiction excluding its conflict-of-law provisions. The +application of the United Nations Convention on Contracts for the International +Sale of Goods is expressly excluded. Any use of the Original Work outside the +scope of this License or after its termination shall be subject to the +requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et +seq., the equivalent laws of other countries, and international treaty. This +section shall survive the termination of this License. + +12) Attorneys Fees. In any action to enforce the terms of this License or +seeking damages relating thereto, the prevailing party shall be entitled to +recover its costs and expenses, including, without limitation, reasonable +attorneys' fees and costs incurred in connection with such action, including +any appeal of such action. This section shall survive the termination of this +License. + +13) Miscellaneous. This License represents the complete agreement concerning +the subject matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent necessary to +make it enforceable. + +14) Definition of "You" in This License. "You" throughout this License, whether +in upper or lower case, means an individual or a legal entity exercising rights +under, and complying with all of the terms of, this License. For legal +entities, "You" includes any entity that controls, is controlled by, or is +under common control with you. For purposes of this definition, "control" means +(i) the power, direct or indirect, to cause the direction or management of such +entity, whether by contract or otherwise, or (ii) ownership of fifty percent +(50%) or more of the outstanding shares, or (iii) beneficial ownership of such +entity. + +15) Right to Use. You may use the Original Work in all ways not otherwise +restricted or conditioned by this License or by law, and Licensor promises not +to interfere with or be responsible for such uses by You. + +This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved. +Permission is hereby granted to copy and distribute this license without +modification. This license may not be modified without the express written +permission of its copyright owner. diff --git a/MAKETESTS.sh b/MAKETESTS.sh new file mode 100755 index 000000000..284a95335 --- /dev/null +++ b/MAKETESTS.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +set -e + +cd $(dirname $0) + +# +# Be sure the machine side of the test suite is up to date +# +std/grind.sh + + +# +# Start Gunk +# +OLDIFS=$IFS +IFS="" +HEADER=`cat< "tests/std_"${CATEGORY}".js" + IFS=$OLDIFS + fi +done + +for i in std/machines/*.json; do + BASE=$(basename $i .json) + CATEGORY=$(echo ${BASE} | sed -e "s/^\([^_]\+\)_.*/\\1/") + echo ' function(){' >> "tests/std_"${CATEGORY}".js" + echo ' var test = CSL.System.Tests.getTest("'${BASE}'");' >> "tests/std_"${CATEGORY}".js" + echo ' doh.assertEqual(test.result, test.run());' >> "tests/std_"${CATEGORY}".js" + echo ' },' >> "tests/std_"${CATEGORY}".js" +done + +for i in tests/std_*.js; do + OLDIFS=$IFS + IFS="" + echo $(footer) >> ${i} + IFS=$OLDIFS +done \ No newline at end of file diff --git a/README.txt b/README.txt new file mode 100644 index 000000000..f5c66b177 --- /dev/null +++ b/README.txt @@ -0,0 +1,144 @@ +citeproc-js: Yet Another CSL Processor + +Frank Bennett +Graduate School of Law, Nagoya University +2009.04.18 +========================================= + +This is an effort to implement a fast and robust CSL processor in +Javascript, for use by the Zotero project. + + +---------------- +The architecture +---------------- + +The following link has (dated but to be maintained) JsDoc documentation +that provides some guidance re how things fit together: + + http://gsl-nagoya-u.net/http/pub/citeproc-js-doc/index.html + +In rough outline, there is a two-stage compiler (Build and Configure) +that can be used to construct an object with a few methods useful for +loading CSL styles, and using them to render citations and bibliographies. + +The object has several sub-objects. The most important are "registry", +"citation", "bibliography", "citation_sort" and "bibliography_sort". +The latter four hold option containers and token lists for particular +renderings defined in a CSL style. The top-level methods on the main +object apply execution wrappers to the token lists to produce output +strings. The "registry" object provides a persistent store for +managing the bibliography sort order, disambiguation, and +back-references. + +Output is generated by passing data items to a wrapper function that +scans the appropriate token lists and renders strings based on the +functions registered in the tokens. The output queue is built as +a nested hierarchy which is then collapsed into a formatted string +for output. + + +-------------------- +Testing, testing ... +-------------------- + +As you can see from the sources, tests are kind of important here. +Javascript is notoriously unfriendly when it comes to debugging, +the processor is charged with and extremely complex formatting +task, and the target community is unforgiving. Things have to +work correctly, and the only way to assure that they do is to +test the code thoroughly as it is written. + +Test suites are useful to us in all sorts of ways. Standard tests +(housed under ./std) help to assure that the various CSL +implementations produce identical results. The internal tests +specific to citeproc-js provide insurance against unexpected +side-effects in the event of wholesale refactoring (of which +there has been more than I would like to remember). Tests +are not just about QA; they improve the clarity of program operation, +and reduce the resistance to rewrites that may be needed to reduce +overall complexity. The suites are an integral part of the +development process; if you modify or add code to the processor +(and contributions are welcome!), be sure to complement your changes +with tests. It's the right thing to do. + + +-------------- +Archive layout +-------------- + +The sources of the program are under ./src. The ./locale and ./style +directories contain standard files from the CSL distribution, for +use in testing. The tests are located under ./tests (for those +specific to citeproc-js) and ./std (for the standard CSL test +fixtures). + +The basic testing framework we use is DOH, from the Dojo project, +run via the Rhino JS interpreter that runs atop Java. If your +machine has Java installed, the ./dojo and ./rhino directories +provide the remaining infrastructure needed to run the tests; they +should work out of the box (see below). + +The ./data directory contains input files for running tests. Over +time, this material will be moved into the standard test suite +area, and the directory will go away. The ./ref directory +contains a grab-bag of documents and files stashed or shoved aside +during development. + + +------------- +Running tests +------------- + +After checkout or update, be sure to run the script ./std/grind.sh. +This will generate the machine-readable version of the standard +test cases, required by the test runner. + +The script that runs all the tests is ./runtests.sh in the top-level +directory. Rintze Zelle has very kindly provided a ./runtests.bat file +as well, and the tests reportedly run (and we hope also break) equally +well on Windows boxes. + +If you have a Java interpreter installed and are on Linux (or possibly +a Mac), you can run the tests in a checkout from a terminal by +entering the top directory and just typing ./runtests.sh. + +On Windows, the ./runtests.bat file can be run from the command prompt, +the only caveat being that the command prompt should be set to the drive +harboring the SVN working copy, e.g. "D:\>D:\xbiblio\citeproc-js\ +trunk\runtests.bat" works whereas "C:\>D:\xbiblio\citeproc-js\ +trunk\runtests.bat" gives an error when executed. + + +------------------- +Running the program +------------------- + +While development is mainly aimed at supporting Zotero, the processor +contains no Zotero dependencies, and should work as a standalone +formatting engine. A sample is contained in the ./rpc-stuff directory. + + +---------- +Other info +---------- + +Information on writing tests using the DOH framework can be found here: + + http://www.ibm.com/developerworks/web/library/wa-aj-doh/index.html + +The DOH testing framework is part of the Dojo project. The dojo +framework files under ./dojo are from a release instance of the +product compiled from the original source. (Compiling from scratch +was necessary in order to run DOH from the command line as we do +here.) If you want to use DOH for your own projects, the sources for +Dojo are available here: + + http://download.dojotoolkit.org/ + +I had a small problem with timeouts on my (slow) machine, which +required commenting out one line of the DOH code. That change is +incorporated in the configured instance of DOH included in these +sources. + +Enjoy! diff --git a/REPLACE.sh b/REPLACE.sh new file mode 100755 index 000000000..3c93ea74a --- /dev/null +++ b/REPLACE.sh @@ -0,0 +1,35 @@ +#!/bin/bash + + +if [ "$1" == "--action" ]; then + ACTION="1" + shift +fi + +if [ "$2" == "" ]; then + echo Must give two values. First is the value to replace, the second is the replacement value. + exit 1 +fi +if [ "$3" != "" ]; then + echo Must give ONLY two values. First is the value to replace, the second is the replacement value. + exit 1 +fi + +if [ "$2" == "NOTHING" ]; then + ARG2="" +else + ARG2="$2" +fi +for i in tests/*.js src/*.js std/humans/*.txt; do + if [ $(grep -c "$1" $i) -gt 0 ]; then + if [ "$ACTION" == "1" ]; then + cat $i | sed -e "s~$1~${ARG2}~g" > $i.NEW + mv $i.NEW $i + else + echo "-----OLD-----" + grep "$1" $i + echo "-----NEW-----" + grep "$1" $i | sed -e "s~$1~${ARG2}~" + fi + fi +done diff --git a/TODO.pdf b/TODO.pdf new file mode 100644 index 000000000..5dc6dee0a Binary files /dev/null and b/TODO.pdf differ diff --git a/TODO.txt b/TODO.txt new file mode 100644 index 000000000..7e39afd94 --- /dev/null +++ b/TODO.txt @@ -0,0 +1,81 @@ +# TODO + +- Flip-flops to be cleared with Bruce D'Arcus and CSL group and + implemented. + (pending. fbennett 2009-04-11) + +- Numbers. First off, the current stuff needs to be + implemented, with extensions for ranging. + (pending. fbennett 2009-04-17) + +- Numbers to be handled as rangeable objects in the + output queue. Rintze Zelle's tests of year-suffix + collapsing need to pass. Formatting of number elements + to be implemented somehow. + (pending. fbennett 2009-04-11) + +- Aspiring beyond that, there are CSL issues with numbers to be + proposed. Number could be a span element with per-atom formatting, + as has been done with names. This will allow superscripting + or ordinal suffixes, and maybe some other useful things. + (pending. fbennett 2009-04-13) + +- Handle position evaluation and back-references inside the + processor via the registry. Zotero's own position evaluation + is currently broken, and although it may be fixed soon, demanding + complex evaluation like this is likely to lead to further trouble + in other applications. If the processor receives the note number + from the application, the CSL processor can take care of the rest. + First step will be to draw my positioning patches to + integration.js into the citeproc-js code base, and figure out + how to stitch it in via an extension to the registry. + (pending fbennett 2009-04-17) + +- Various options and special formatting attributes need to be + implemented. + (a very short list of these remain. fbennett 2009-04-11) + +- Deletion support for the registry. + (pending. fbennett 2009-04-11) + +- Processor to report the full list of fields required to render + any item in the compiled style, to permit the application to + optimize database fetches? + (pending. fbennett 2009-04-11) + +- Localized date formatting needs to be implemented? + Maybe implement a proposal, post to xbib list. + (pending. fbennett 2009-04-11) + +--------------- +(Working notes) +--------------- + +/* + * ATTRIBUTES TO COME + * position (pending) + * delimiter-precedes-last (stored, pending) + * plural (pending) + * locator (pending) + * include-period (pending) + * + * + * OPTIONS + * collapse + * citation-number (awaits range support) + * year (done) + * year-suffix (done) + * line-spacing + * [number] (pending) + * entry-spacing + * [number] (pending) + * hanging-indent + * [boolean] (pending) + * second-field-align + * [true/margin] (pending) + * subsequent-author-substitute + * [text] (pending) + * + * CONDITIONAL + * is-numeric (written, untested) + */ diff --git a/bundle.sh b/bundle.sh new file mode 100755 index 000000000..91c7397e5 --- /dev/null +++ b/bundle.sh @@ -0,0 +1,90 @@ +#!/bin/bash + +set -e + +cd $(dirname $0) + +if [ ! -d jsdoc ]; then + echo This script requires jsdoc, which is available here: + echo " http://code.google.com/p/jsdoc-toolkit/w/list" + exit 1 +fi + +if [ -d tmp ]; then + rm -fR tmp +fi +if [ -f stripped.js ]; then + rm stripped.js +fi +mkdir tmp + +cd src + +function makepaths (){ + filepaths="" + for f in $1; do + filepaths="$filepaths tmp/$f.js" + done +} + +files="csl core render build configure util util_token util_dates util_disambiguate util_names util_sort factory state commands blob token stack ambigconfig registry disambiguate lib elements libnames attributes output queue formatters formats range system xml xmle4x xmljs retrieval tests" + + + +makepaths "${files}" + +for i in $files; do + cat ${i}.js | sed -e "0,/^\(CSL\|\/\)/{/^\(CSL\|\/\)/p;d;}" > ../tmp/NEW + mv ../tmp/NEW ../tmp/${i}.js + cat ../tmp/${i}.js | sed -e "/^[[:space:]]*\/\*/,/^[[:space:]]*\*\//d" > ../tmp/NEW + mv ../tmp/NEW ../tmp/NEW.js + cat ../tmp/NEW.js | sed -e "/^[[:space:]]*load/d" > ../tmp/NEW + mv ../tmp/NEW ../tmp/NEW.js + cat ../tmp/NEW.js | sed -e "/^[[:space:]]*$/d" > ../tmp/NEW + mv ../tmp/NEW ../tmp/NEW.js + cat ../tmp/NEW.js | sed -e "/^[[:space:]]\/\/.*$/d" > ../tmp/NEW + mv ../tmp/NEW ../tmp/NEW.js + cat ../tmp/NEW.js | sed -e "/^\/\/SNIP-START/,/^\/\/SNIP-END/d" > ../tmp/NEW + mv ../tmp/NEW ../tmp/NEW.js + cat ../tmp/NEW.js >> ../stripped.js +done +rm ../tmp/NEW* + +cd .. +echo $(cat stripped.js | wc -l) lines in product + +cp stripped.js rpc-stuff/citeproc-js-combined.js + +#cd rpc-stuff +#./citeproc-js-rpc.py +#cd .. + +rm stripped.js + +## JSDoc toolkit is available from: http://code.google.com/p/jsdoc-toolkit/ + +if [ "$1" == "--upload" ]; then + + if [ -f jsdoc/jsdoc.log ]; then + rm jsdoc/jsdoc.log + fi + + if [ "--help" == "$1" ]; then + java -jar jsdoc/jsrun.jar jsdoc/app/run.js --help + else + java -jar jsdoc/jsrun.jar jsdoc/app/run.js \ + -p \ + --out=jsdoc/jsdoc.log \ + --directory=citeproc-js-doc \ + -t=jsdoc/templates/jsdoc \ + $filepaths + fi + + tar cfz citeproc-js-doc.tar.gz citeproc-js-doc + scp citeproc-js-doc.tar.gz gsl-nagoya-u.net:/http/pub + ssh gsl-nagoya-u.net ./citeproc-js-doc.sh + rm citeproc-js-doc.tar.gz + rm -fR citeproc-js-doc +fi + +rm -fR tmp diff --git a/data/ambigs-1.txt b/data/ambigs-1.txt new file mode 100644 index 000000000..12c1405ea --- /dev/null +++ b/data/ambigs-1.txt @@ -0,0 +1,14 @@ +{ + "id":"ambigs-1", + "type": "book", + "author": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Crispin" }, + { "name":"Dropsy, David" }, + { "name":"Ebola, Elvin" }, + { "name":"Fever, Fergus" } + ], + "issued": {"year": "1990"}, + "title": "Book M" +} diff --git a/data/ambigs-10.txt b/data/ambigs-10.txt new file mode 100644 index 000000000..f2a723082 --- /dev/null +++ b/data/ambigs-10.txt @@ -0,0 +1,10 @@ +{ + "id":"ambigs-10", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Janet" } + ], + "issued": {"year": "1990"}, + "title": "Book D" +} diff --git a/data/ambigs-12.txt b/data/ambigs-12.txt new file mode 100644 index 000000000..899cce192 --- /dev/null +++ b/data/ambigs-12.txt @@ -0,0 +1,11 @@ +{ + "id":"ambigs-12", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Jane" }, + { "name":"Jones, Robert" } + ], + "issued": {"year": "1990"}, + "title": "Book C" +} diff --git a/data/ambigs-13.txt b/data/ambigs-13.txt new file mode 100644 index 000000000..a86210d66 --- /dev/null +++ b/data/ambigs-13.txt @@ -0,0 +1,11 @@ +{ + "id":"ambigs-13", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Josephine" }, + { "name":"Jones, Robert" } + ], + "issued": {"year": "1990"}, + "title": "Book B" +} diff --git a/data/ambigs-14.txt b/data/ambigs-14.txt new file mode 100644 index 000000000..f8c331710 --- /dev/null +++ b/data/ambigs-14.txt @@ -0,0 +1,11 @@ +{ + "id":"ambigs-14", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Jane" }, + { "name":"Jones, Richard" } + ], + "issued": {"year": "1990"}, + "title": "Book A" +} diff --git a/data/ambigs-2.txt b/data/ambigs-2.txt new file mode 100644 index 000000000..c9d5f953b --- /dev/null +++ b/data/ambigs-2.txt @@ -0,0 +1,14 @@ +{ + "id":"ambigs-2", + "type": "book", + "author": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Crispin" }, + { "name":"Dropsy, David" }, + { "name":"Enteritis, Ernie" }, + { "name":"Fever, Fergus" } + ], + "issued": {"year": "1990"}, + "title": "Book L" +} diff --git a/data/ambigs-3.txt b/data/ambigs-3.txt new file mode 100644 index 000000000..9ad140b93 --- /dev/null +++ b/data/ambigs-3.txt @@ -0,0 +1,14 @@ +{ + "id":"ambigs-3", + "type": "book", + "author": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Crispin" }, + { "name":"Dropsy, David" }, + { "name":"Ebola, Elvin" }, + { "name":"Fever, Fergus" } + ], + "issued": {"year": "1990"}, + "title": "Book K" +} diff --git a/data/ambigs-4.txt b/data/ambigs-4.txt new file mode 100644 index 000000000..4e16b24ff --- /dev/null +++ b/data/ambigs-4.txt @@ -0,0 +1,11 @@ +{ + "id":"ambigs-4", + "type": "book", + "author": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Crispin" } + ], + "issued": {"year": "1990"}, + "title": "Book J" +} diff --git a/data/ambigs-5.txt b/data/ambigs-5.txt new file mode 100644 index 000000000..1657a35dc --- /dev/null +++ b/data/ambigs-5.txt @@ -0,0 +1,11 @@ +{ + "id":"ambigs-5", + "type": "book", + "author": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Beauregarde" }, + { "name":"Cold, Crispin" } + ], + "issued": {"year": "1990"}, + "title": "Book I" +} diff --git a/data/ambigs-6.txt b/data/ambigs-6.txt new file mode 100644 index 000000000..11110d7b1 --- /dev/null +++ b/data/ambigs-6.txt @@ -0,0 +1,14 @@ +{ + "id":"ambigs-6", + "type": "book", + "author": [ + { "name":"Asthma, Alan" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Crispin" }, + { "name":"Dropsy, David" }, + { "name":"Ebola, Elvin" }, + { "name":"Fever, Fergus" } + ], + "issued": {"year": "1990"}, + "title": "Book H" +} diff --git a/data/ambigs-7.txt b/data/ambigs-7.txt new file mode 100644 index 000000000..4f4c58da3 --- /dev/null +++ b/data/ambigs-7.txt @@ -0,0 +1,10 @@ +{ + "id":"ambigs-7", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Janet" } + ], + "issued": {"year": "1990"}, + "title": "Book G" +} diff --git a/data/ambigs-8.txt b/data/ambigs-8.txt new file mode 100644 index 000000000..d2fbf97ba --- /dev/null +++ b/data/ambigs-8.txt @@ -0,0 +1,10 @@ +{ + "id":"ambigs-8", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Jane" } + ], + "issued": {"year": "1990"}, + "title": "Book F" +} diff --git a/data/ambigs-9.txt b/data/ambigs-9.txt new file mode 100644 index 000000000..0132f7105 --- /dev/null +++ b/data/ambigs-9.txt @@ -0,0 +1,10 @@ +{ + "id":"ambigs-9", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Jane" } + ], + "issued": {"year": "1990"}, + "title": "Book E" +} diff --git a/data/editor-translator-1.txt b/data/editor-translator-1.txt new file mode 100644 index 000000000..0329f60ba --- /dev/null +++ b/data/editor-translator-1.txt @@ -0,0 +1,16 @@ +{ + "id":"editor-translator-1", + "type": "book", + "editor": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Crispin" }, + ], + "translator": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Crispin" }, + ], + "issued": {"year": "1990"}, + "title": "Book One" +} diff --git a/data/editor-translator-2.txt b/data/editor-translator-2.txt new file mode 100644 index 000000000..55276c74d --- /dev/null +++ b/data/editor-translator-2.txt @@ -0,0 +1,16 @@ +{ + "id":"editor-translator-2", + "type": "book", + "editor": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Crispin" }, + ], + "translator": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Constantine" }, + ], + "issued": {"year": "1990"}, + "title": "Book One" +} diff --git a/data/institution-name-1.txt b/data/institution-name-1.txt new file mode 100644 index 000000000..769f209f0 --- /dev/null +++ b/data/institution-name-1.txt @@ -0,0 +1,9 @@ +{ + "id":"institution-name-1", + "type": "book", + "author": [ + { "name":"Ministry of Education, Sports, Culture, Science and Technology !!" } + ], + "issued": "2006", + "title": "White Paper on Education, Sports, Culture, Science and Technology" +} diff --git a/data/seven-names-1.txt b/data/seven-names-1.txt new file mode 100644 index 000000000..01eec3078 --- /dev/null +++ b/data/seven-names-1.txt @@ -0,0 +1,14 @@ +{ + "type": "book", + "author": [ + { "name":"Чайковский, Пётр Ильич" }, + { "name":"van Winkle, Rip" }, + { "name":"我妻, 栄" }, + { "name":"Thucydides, Carl, III" }, + { "name":"Tokugawa, Ieyasu !" }, + { "name":"Ministry of Fear, Loathing and Error !!" }, + { "name":"Prince" } + ], + "issued": "2000", + "title": "Our Story" +} diff --git a/data/seven-names-plus-two-1.txt b/data/seven-names-plus-two-1.txt new file mode 100644 index 000000000..077b02f1b --- /dev/null +++ b/data/seven-names-plus-two-1.txt @@ -0,0 +1,19 @@ +{ + "id":"seven-names-plus-two-1", + "type": "book", + "author": [ + { "name":"Чайковский, Пётр Ильич" }, + { "name":"van Winkle, Rip" }, + { "name":"我妻, 栄" }, + { "name":"Thucydides, Carl, III" }, + { "name":"Tokugawa, Ieyasu !" }, + { "name":"Ministry of Fear, Loathing and Error !!" }, + { "name":"Prince" } + ], + "editor":[ + { "name":"Doe, John" }, + { "name":"Roe, Jane" }, + ], + "issued": "2000", + "title": "Our Story" +} diff --git a/data/simple-japanese-name-1.txt b/data/simple-japanese-name-1.txt new file mode 100644 index 000000000..fe28d9ccc --- /dev/null +++ b/data/simple-japanese-name-1.txt @@ -0,0 +1,8 @@ +{ + "type": "book", + "author": [ + { "name":"我妻, 栄" } + ], + "issued": "1960", + "title": "民法" +} diff --git a/data/simple-mongolian-name-1.txt b/data/simple-mongolian-name-1.txt new file mode 100644 index 000000000..12e8427e0 --- /dev/null +++ b/data/simple-mongolian-name-1.txt @@ -0,0 +1,9 @@ +{ + "id":"simple-mongolian-name-1", + "type": "book", + "author": [ + { "name":"Tserendorj, Balingiin" } + ], + "issued": {"year": "1925", "month":"3", "day":"4"}, + "title": "An Altogether Unknown History of Soviet-Mongolian Relations" +} diff --git a/data/simple-sticky-name-1.txt b/data/simple-sticky-name-1.txt new file mode 100644 index 000000000..5b83bb67c --- /dev/null +++ b/data/simple-sticky-name-1.txt @@ -0,0 +1,9 @@ +{ + "id":"simple-sticky-name-1", + "type": "book", + "author": [ + { "name":"Miyamoto, Musashi !" } + ], + "issued": {"year": "1645", "month":"12", "day":"27"}, + "title": "A Book of Five Rings" +} diff --git a/data/simple-western-editor-1.txt b/data/simple-western-editor-1.txt new file mode 100644 index 000000000..fc8eccfb6 --- /dev/null +++ b/data/simple-western-editor-1.txt @@ -0,0 +1,8 @@ +{ + "type": "book", + "editor": [ + { "name":"Doe, John", "uri":"http://people.org/doej" } + ], + "issued": "2000", + "title": "His Anonymous Life" +} diff --git a/data/simple-western-editor-2.txt b/data/simple-western-editor-2.txt new file mode 100644 index 000000000..a1862ca4a --- /dev/null +++ b/data/simple-western-editor-2.txt @@ -0,0 +1,8 @@ +{ + "type": "book", + "editor": [ + { "name":"Roe, Jane" } + ], + "issued": "2000", + "title": "Her Anonymous Anthology" +} diff --git a/data/simple-western-name-1.txt b/data/simple-western-name-1.txt new file mode 100644 index 000000000..177981dad --- /dev/null +++ b/data/simple-western-name-1.txt @@ -0,0 +1,9 @@ +{ + "id":"simple-western-name-1", + "type": "book", + "author": [ + { "name":"Doe, John", "uri":"http://people.org/doej" } + ], + "issued": {"year": "1965", "month":"6", "day":"1"}, + "title": "His Anonymous Life" +} diff --git a/data/simple-western-name-2.txt b/data/simple-western-name-2.txt new file mode 100644 index 000000000..db9760813 --- /dev/null +++ b/data/simple-western-name-2.txt @@ -0,0 +1,9 @@ +{ + "id":"simple-western-name-2", + "type": "book", + "author": [ + { "name":"Roe, Jane", "uri":"http://people.org/roej" } + ], + "issued": {"year": "1980", "month":"10", "day":"2"}, + "title": "Her Anonymous Life" +} diff --git a/data/simple-western-name-3.txt b/data/simple-western-name-3.txt new file mode 100644 index 000000000..349ce8915 --- /dev/null +++ b/data/simple-western-name-3.txt @@ -0,0 +1,9 @@ +{ + "id":"simple-western-name-3", + "type": "book", + "author": [ + { "name":"Doe, Joseph", "uri":"http://people.org/doej" } + ], + "issued": {"year": "1900", "month":"1", "day":"3"}, + "title": "His Anonymous Life" +} diff --git a/data/two-simple-western-editors-1.txt b/data/two-simple-western-editors-1.txt new file mode 100644 index 000000000..2a4db9f3e --- /dev/null +++ b/data/two-simple-western-editors-1.txt @@ -0,0 +1,9 @@ +{ + "type": "book", + "editor": [ + { "name":"Doe, John", "uri":"http://people.org/doej" }, + { "name":"Roe, Jane", "uri":"http://people.org/doej" } + ], + "issued": "2000", + "title": "His Anonymous Life" +} diff --git a/data/two-simple-western-names-1.txt b/data/two-simple-western-names-1.txt new file mode 100644 index 000000000..644b42160 --- /dev/null +++ b/data/two-simple-western-names-1.txt @@ -0,0 +1,10 @@ +{ + "id":"two-simple-western-names-1", + "type": "book", + "author": [ + { "name":"Doe, John", "uri":"http://people.org/doej" }, + { "name":"Roe, Jane", "uri":"http://people.org/roej" } + ], + "issued": "2000", + "title": "Our Anonymous Lives" +} diff --git a/data/western-name-with-articular-1.txt b/data/western-name-with-articular-1.txt new file mode 100644 index 000000000..7abb51b92 --- /dev/null +++ b/data/western-name-with-articular-1.txt @@ -0,0 +1,9 @@ +{ + "id":"western-name-with-articular-1", + "type": "book", + "author": [ + { "name":"van Doe, Jacques" } + ], + "issued": "1645", + "title": "A Book of Five Rings" +} diff --git a/data/western-name-with-comma-suffix-1.txt b/data/western-name-with-comma-suffix-1.txt new file mode 100644 index 000000000..3e1334fe9 --- /dev/null +++ b/data/western-name-with-comma-suffix-1.txt @@ -0,0 +1,8 @@ +{ + "type": "book", + "author": [ + { "name":"Doe, Jeffrey,! Jr." } + ], + "issued": "2001", + "title": "My Life as an Anonymous Heir" +} diff --git a/data/western-name-with-space-suffix-1.txt b/data/western-name-with-space-suffix-1.txt new file mode 100644 index 000000000..1480bffe5 --- /dev/null +++ b/data/western-name-with-space-suffix-1.txt @@ -0,0 +1,9 @@ +{ + "id":"western-name-with-space-suffix-1", + "type": "book", + "author": [ + { "name":"Doe, James, III" } + ], + "issued": "2001", + "title": "My Anonymous Heritage" +} diff --git a/data/western-name-with-space-suffix-2.txt b/data/western-name-with-space-suffix-2.txt new file mode 100644 index 000000000..29252017c --- /dev/null +++ b/data/western-name-with-space-suffix-2.txt @@ -0,0 +1,9 @@ +{ + "id":"western-name-with-space-suffix-2", + "type": "book", + "author": [ + { "name":"Doe, Jeffrey, Jr." } + ], + "issued": "2001", + "title": "My Life as an Anonymous Heir" +} diff --git a/data/year-suffixes-1.txt b/data/year-suffixes-1.txt new file mode 100644 index 000000000..7fd9fa376 --- /dev/null +++ b/data/year-suffixes-1.txt @@ -0,0 +1,9 @@ +{ + "id":"year-suffixes-1", + "type": "book", + "author": [ + { "name":"Doe, John" } + ], + "issued": {"year": "2000"}, + "title": "Paper 1" +} diff --git a/data/year-suffixes-2.txt b/data/year-suffixes-2.txt new file mode 100644 index 000000000..5de78b1ce --- /dev/null +++ b/data/year-suffixes-2.txt @@ -0,0 +1,9 @@ +{ + "id":"year-suffixes-2", + "type": "book", + "author": [ + { "name":"Doe, John" } + ], + "issued": {"year": "2000"}, + "title": "Paper 2" +} diff --git a/data/year-suffixes-3.txt b/data/year-suffixes-3.txt new file mode 100644 index 000000000..e9973f599 --- /dev/null +++ b/data/year-suffixes-3.txt @@ -0,0 +1,9 @@ +{ + "id":"year-suffixes-3", + "type": "book", + "author": [ + { "name":"Doe, John" } + ], + "issued": {"year": "2001"}, + "title": "Paper 3" +} diff --git a/dojo/LICENSE b/dojo/LICENSE new file mode 100644 index 000000000..3fa27203c --- /dev/null +++ b/dojo/LICENSE @@ -0,0 +1,195 @@ +Dojo is available under *either* the terms of the modified BSD license *or* the +Academic Free License version 2.1. As a recipient of Dojo, you may choose which +license to receive this code under (except as noted in per-module LICENSE +files). Some modules may not be the copyright of the Dojo Foundation. These +modules contain explicit declarations of copyright in both the LICENSE files in +the directories in which they reside and in the code itself. No external +contributions are allowed under licenses which are fundamentally incompatible +with the AFL or BSD licenses that Dojo is distributed under. + +The text of the AFL and BSD licenses is reproduced below. + +------------------------------------------------------------------------------- +The "New" BSD License: +********************** + +Copyright (c) 2005-2008, The Dojo Foundation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the Dojo Foundation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------------- +The Academic Free License, v. 2.1: +********************************** + +This Academic Free License (the "License") applies to any original work of +authorship (the "Original Work") whose owner (the "Licensor") has placed the +following notice immediately following the copyright notice for the Original +Work: + +Licensed under the Academic Free License version 2.1 + +1) Grant of Copyright License. Licensor hereby grants You a world-wide, +royalty-free, non-exclusive, perpetual, sublicenseable license to do the +following: + +a) to reproduce the Original Work in copies; + +b) to prepare derivative works ("Derivative Works") based upon the Original +Work; + +c) to distribute copies of the Original Work and Derivative Works to the +public; + +d) to perform the Original Work publicly; and + +e) to display the Original Work publicly. + +2) Grant of Patent License. Licensor hereby grants You a world-wide, +royalty-free, non-exclusive, perpetual, sublicenseable license, under patent +claims owned or controlled by the Licensor that are embodied in the Original +Work as furnished by the Licensor, to make, use, sell and offer for sale the +Original Work and Derivative Works. + +3) Grant of Source Code License. The term "Source Code" means the preferred +form of the Original Work for making modifications to it and all available +documentation describing how to modify the Original Work. Licensor hereby +agrees to provide a machine-readable copy of the Source Code of the Original +Work along with each copy of the Original Work that Licensor distributes. +Licensor reserves the right to satisfy this obligation by placing a +machine-readable copy of the Source Code in an information repository +reasonably calculated to permit inexpensive and convenient access by You for as +long as Licensor continues to distribute the Original Work, and by publishing +the address of that information repository in a notice immediately following +the copyright notice that applies to the Original Work. + +4) Exclusions From License Grant. Neither the names of Licensor, nor the names +of any contributors to the Original Work, nor any of their trademarks or +service marks, may be used to endorse or promote products derived from this +Original Work without express prior written permission of the Licensor. Nothing +in this License shall be deemed to grant any rights to trademarks, copyrights, +patents, trade secrets or any other intellectual property of Licensor except as +expressly stated herein. No patent license is granted to make, use, sell or +offer to sell embodiments of any patent claims other than the licensed claims +defined in Section 2. No right is granted to the trademarks of Licensor even if +such marks are included in the Original Work. Nothing in this License shall be +interpreted to prohibit Licensor from licensing under different terms from this +License any Original Work that Licensor otherwise would have a right to +license. + +5) This section intentionally omitted. + +6) Attribution Rights. You must retain, in the Source Code of any Derivative +Works that You create, all copyright, patent or trademark notices from the +Source Code of the Original Work, as well as any notices of licensing and any +descriptive text identified therein as an "Attribution Notice." You must cause +the Source Code for any Derivative Works that You create to carry a prominent +Attribution Notice reasonably calculated to inform recipients that You have +modified the Original Work. + +7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that +the copyright in and to the Original Work and the patent rights granted herein +by Licensor are owned by the Licensor or are sublicensed to You under the terms +of this License with the permission of the contributor(s) of those copyrights +and patent rights. Except as expressly stated in the immediately proceeding +sentence, the Original Work is provided under this License on an "AS IS" BASIS +and WITHOUT WARRANTY, either express or implied, including, without limitation, +the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. +This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No +license to Original Work is granted hereunder except under this disclaimer. + +8) Limitation of Liability. Under no circumstances and under no legal theory, +whether in tort (including negligence), contract, or otherwise, shall the +Licensor be liable to any person for any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License +or the use of the Original Work including, without limitation, damages for loss +of goodwill, work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses. This limitation of liability shall not +apply to liability for death or personal injury resulting from Licensor's +negligence to the extent applicable law prohibits such limitation. Some +jurisdictions do not allow the exclusion or limitation of incidental or +consequential damages, so this exclusion and limitation may not apply to You. + +9) Acceptance and Termination. If You distribute copies of the Original Work or +a Derivative Work, You must make a reasonable effort under the circumstances to +obtain the express assent of recipients to the terms of this License. Nothing +else but this License (or another written agreement between Licensor and You) +grants You permission to create Derivative Works based upon the Original Work +or to exercise any of the rights granted in Section 1 herein, and any attempt +to do so except under the terms of this License (or another written agreement +between Licensor and You) is expressly prohibited by U.S. copyright law, the +equivalent laws of other countries, and by international treaty. Therefore, by +exercising any of the rights granted to You in Section 1 herein, You indicate +Your acceptance of this License and all of its terms and conditions. + +10) Termination for Patent Action. This License shall terminate automatically +and You may no longer exercise any of the rights granted to You by this License +as of the date You commence an action, including a cross-claim or counterclaim, +against Licensor or any licensee alleging that the Original Work infringes a +patent. This termination provision shall not apply for an action alleging +patent infringement by combinations of the Original Work with other software or +hardware. + +11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this +License may be brought only in the courts of a jurisdiction wherein the +Licensor resides or in which Licensor conducts its primary business, and under +the laws of that jurisdiction excluding its conflict-of-law provisions. The +application of the United Nations Convention on Contracts for the International +Sale of Goods is expressly excluded. Any use of the Original Work outside the +scope of this License or after its termination shall be subject to the +requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et +seq., the equivalent laws of other countries, and international treaty. This +section shall survive the termination of this License. + +12) Attorneys Fees. In any action to enforce the terms of this License or +seeking damages relating thereto, the prevailing party shall be entitled to +recover its costs and expenses, including, without limitation, reasonable +attorneys' fees and costs incurred in connection with such action, including +any appeal of such action. This section shall survive the termination of this +License. + +13) Miscellaneous. This License represents the complete agreement concerning +the subject matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent necessary to +make it enforceable. + +14) Definition of "You" in This License. "You" throughout this License, whether +in upper or lower case, means an individual or a legal entity exercising rights +under, and complying with all of the terms of, this License. For legal +entities, "You" includes any entity that controls, is controlled by, or is +under common control with you. For purposes of this definition, "control" means +(i) the power, direct or indirect, to cause the direction or management of such +entity, whether by contract or otherwise, or (ii) ownership of fifty percent +(50%) or more of the outstanding shares, or (iii) beneficial ownership of such +entity. + +15) Right to Use. You may use the Original Work in all ways not otherwise +restricted or conditioned by this License or by law, and Licensor promises not +to interfere with or be responsible for such uses by You. + +This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved. +Permission is hereby granted to copy and distribute this license without +modification. This license may not be modified without the express written +permission of its copyright owner. diff --git a/dojo/dojo/LICENSE b/dojo/dojo/LICENSE new file mode 100644 index 000000000..3fa27203c --- /dev/null +++ b/dojo/dojo/LICENSE @@ -0,0 +1,195 @@ +Dojo is available under *either* the terms of the modified BSD license *or* the +Academic Free License version 2.1. As a recipient of Dojo, you may choose which +license to receive this code under (except as noted in per-module LICENSE +files). Some modules may not be the copyright of the Dojo Foundation. These +modules contain explicit declarations of copyright in both the LICENSE files in +the directories in which they reside and in the code itself. No external +contributions are allowed under licenses which are fundamentally incompatible +with the AFL or BSD licenses that Dojo is distributed under. + +The text of the AFL and BSD licenses is reproduced below. + +------------------------------------------------------------------------------- +The "New" BSD License: +********************** + +Copyright (c) 2005-2008, The Dojo Foundation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the Dojo Foundation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------------- +The Academic Free License, v. 2.1: +********************************** + +This Academic Free License (the "License") applies to any original work of +authorship (the "Original Work") whose owner (the "Licensor") has placed the +following notice immediately following the copyright notice for the Original +Work: + +Licensed under the Academic Free License version 2.1 + +1) Grant of Copyright License. Licensor hereby grants You a world-wide, +royalty-free, non-exclusive, perpetual, sublicenseable license to do the +following: + +a) to reproduce the Original Work in copies; + +b) to prepare derivative works ("Derivative Works") based upon the Original +Work; + +c) to distribute copies of the Original Work and Derivative Works to the +public; + +d) to perform the Original Work publicly; and + +e) to display the Original Work publicly. + +2) Grant of Patent License. Licensor hereby grants You a world-wide, +royalty-free, non-exclusive, perpetual, sublicenseable license, under patent +claims owned or controlled by the Licensor that are embodied in the Original +Work as furnished by the Licensor, to make, use, sell and offer for sale the +Original Work and Derivative Works. + +3) Grant of Source Code License. The term "Source Code" means the preferred +form of the Original Work for making modifications to it and all available +documentation describing how to modify the Original Work. Licensor hereby +agrees to provide a machine-readable copy of the Source Code of the Original +Work along with each copy of the Original Work that Licensor distributes. +Licensor reserves the right to satisfy this obligation by placing a +machine-readable copy of the Source Code in an information repository +reasonably calculated to permit inexpensive and convenient access by You for as +long as Licensor continues to distribute the Original Work, and by publishing +the address of that information repository in a notice immediately following +the copyright notice that applies to the Original Work. + +4) Exclusions From License Grant. Neither the names of Licensor, nor the names +of any contributors to the Original Work, nor any of their trademarks or +service marks, may be used to endorse or promote products derived from this +Original Work without express prior written permission of the Licensor. Nothing +in this License shall be deemed to grant any rights to trademarks, copyrights, +patents, trade secrets or any other intellectual property of Licensor except as +expressly stated herein. No patent license is granted to make, use, sell or +offer to sell embodiments of any patent claims other than the licensed claims +defined in Section 2. No right is granted to the trademarks of Licensor even if +such marks are included in the Original Work. Nothing in this License shall be +interpreted to prohibit Licensor from licensing under different terms from this +License any Original Work that Licensor otherwise would have a right to +license. + +5) This section intentionally omitted. + +6) Attribution Rights. You must retain, in the Source Code of any Derivative +Works that You create, all copyright, patent or trademark notices from the +Source Code of the Original Work, as well as any notices of licensing and any +descriptive text identified therein as an "Attribution Notice." You must cause +the Source Code for any Derivative Works that You create to carry a prominent +Attribution Notice reasonably calculated to inform recipients that You have +modified the Original Work. + +7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that +the copyright in and to the Original Work and the patent rights granted herein +by Licensor are owned by the Licensor or are sublicensed to You under the terms +of this License with the permission of the contributor(s) of those copyrights +and patent rights. Except as expressly stated in the immediately proceeding +sentence, the Original Work is provided under this License on an "AS IS" BASIS +and WITHOUT WARRANTY, either express or implied, including, without limitation, +the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. +This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No +license to Original Work is granted hereunder except under this disclaimer. + +8) Limitation of Liability. Under no circumstances and under no legal theory, +whether in tort (including negligence), contract, or otherwise, shall the +Licensor be liable to any person for any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License +or the use of the Original Work including, without limitation, damages for loss +of goodwill, work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses. This limitation of liability shall not +apply to liability for death or personal injury resulting from Licensor's +negligence to the extent applicable law prohibits such limitation. Some +jurisdictions do not allow the exclusion or limitation of incidental or +consequential damages, so this exclusion and limitation may not apply to You. + +9) Acceptance and Termination. If You distribute copies of the Original Work or +a Derivative Work, You must make a reasonable effort under the circumstances to +obtain the express assent of recipients to the terms of this License. Nothing +else but this License (or another written agreement between Licensor and You) +grants You permission to create Derivative Works based upon the Original Work +or to exercise any of the rights granted in Section 1 herein, and any attempt +to do so except under the terms of this License (or another written agreement +between Licensor and You) is expressly prohibited by U.S. copyright law, the +equivalent laws of other countries, and by international treaty. Therefore, by +exercising any of the rights granted to You in Section 1 herein, You indicate +Your acceptance of this License and all of its terms and conditions. + +10) Termination for Patent Action. This License shall terminate automatically +and You may no longer exercise any of the rights granted to You by this License +as of the date You commence an action, including a cross-claim or counterclaim, +against Licensor or any licensee alleging that the Original Work infringes a +patent. This termination provision shall not apply for an action alleging +patent infringement by combinations of the Original Work with other software or +hardware. + +11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this +License may be brought only in the courts of a jurisdiction wherein the +Licensor resides or in which Licensor conducts its primary business, and under +the laws of that jurisdiction excluding its conflict-of-law provisions. The +application of the United Nations Convention on Contracts for the International +Sale of Goods is expressly excluded. Any use of the Original Work outside the +scope of this License or after its termination shall be subject to the +requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et +seq., the equivalent laws of other countries, and international treaty. This +section shall survive the termination of this License. + +12) Attorneys Fees. In any action to enforce the terms of this License or +seeking damages relating thereto, the prevailing party shall be entitled to +recover its costs and expenses, including, without limitation, reasonable +attorneys' fees and costs incurred in connection with such action, including +any appeal of such action. This section shall survive the termination of this +License. + +13) Miscellaneous. This License represents the complete agreement concerning +the subject matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent necessary to +make it enforceable. + +14) Definition of "You" in This License. "You" throughout this License, whether +in upper or lower case, means an individual or a legal entity exercising rights +under, and complying with all of the terms of, this License. For legal +entities, "You" includes any entity that controls, is controlled by, or is +under common control with you. For purposes of this definition, "control" means +(i) the power, direct or indirect, to cause the direction or management of such +entity, whether by contract or otherwise, or (ii) ownership of fifty percent +(50%) or more of the outstanding shares, or (iii) beneficial ownership of such +entity. + +15) Right to Use. You may use the Original Work in all ways not otherwise +restricted or conditioned by this License or by law, and Licensor promises not +to interfere with or be responsible for such uses by You. + +This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved. +Permission is hereby granted to copy and distribute this license without +modification. This license may not be modified without the express written +permission of its copyright owner. diff --git a/dojo/dojo/dojo.js b/dojo/dojo/dojo.js new file mode 100644 index 000000000..15ea738e1 --- /dev/null +++ b/dojo/dojo/dojo.js @@ -0,0 +1,16 @@ +/* + Copyright (c) 2004-2008, The Dojo Foundation All Rights Reserved. + Available via Academic Free License >= 2.1 OR the modified BSD license. + see: http://dojotoolkit.org/license for details +*/ + +/* + This is a compiled version of Dojo, built for deployment and not for + development. To get an editable version, please visit: + + http://dojotoolkit.org + + for documentation and information on getting the source. +*/ + +(function(){var _1=null;if((_1||(typeof djConfig!="undefined"&&djConfig.scopeMap))&&(typeof window!="undefined")){var _2="",_3="",_4="",_5={},_6={};_1=_1||djConfig.scopeMap;for(var i=0;i<_1.length;i++){var _8=_1[i];_2+="var "+_8[0]+" = {}; "+_8[1]+" = "+_8[0]+";"+_8[1]+"._scopeName = '"+_8[1]+"';";_3+=(i==0?"":",")+_8[0];_4+=(i==0?"":",")+_8[1];_5[_8[0]]=_8[1];_6[_8[1]]=_8[0];}eval(_2+"dojo._scopeArgs = ["+_4+"];");dojo._scopePrefixArgs=_3;dojo._scopePrefix="(function("+_3+"){";dojo._scopeSuffix="})("+_4+")";dojo._scopeMap=_5;dojo._scopeMapRev=_6;}(function(){if(!this["console"]){this.console={};}var cn=["assert","count","debug","dir","dirxml","error","group","groupEnd","info","profile","profileEnd","time","timeEnd","trace","warn","log"];var i=0,tn;while((tn=cn[i++])){if(!console[tn]){(function(){var _c=tn+"";console[_c]=("log" in console)?function(){var a=Array.apply({},arguments);a.unshift(_c+":");console["log"](a.join(" "));}:function(){};})();}}if(typeof dojo=="undefined"){this.dojo={_scopeName:"dojo",_scopePrefix:"",_scopePrefixArgs:"",_scopeSuffix:"",_scopeMap:{},_scopeMapRev:{}};}var d=dojo;if(typeof dijit=="undefined"){this.dijit={_scopeName:"dijit"};}if(typeof dojox=="undefined"){this.dojox={_scopeName:"dojox"};}if(!d._scopeArgs){d._scopeArgs=[dojo,dijit,dojox];}d.global=this;d.config={isDebug:false,debugAtAllCosts:false};if(typeof djConfig!="undefined"){for(var _f in djConfig){d.config[_f]=djConfig[_f];}}var _10=["Browser","Rhino","Spidermonkey","Mobile"];var t;while((t=_10.shift())){d["is"+t]=false;}dojo.locale=d.config.locale;var rev="$Rev: 15997 $".match(/\d+/);dojo.version={major:0,minor:0,patch:0,flag:"dev",revision:rev?+rev[0]:999999,toString:function(){with(d.version){return major+"."+minor+"."+patch+flag+" ("+revision+")";}}};if(typeof OpenAjax!="undefined"){OpenAjax.hub.registerLibrary(dojo._scopeName,"http://dojotoolkit.org",d.version.toString());}dojo._mixin=function(obj,_14){var _15={};for(var x in _14){if(_15[x]===undefined||_15[x]!=_14[x]){obj[x]=_14[x];}}if(d["isIE"]&&_14){var p=_14.toString;if(typeof p=="function"&&p!=obj.toString&&p!=_15.toString&&p!="\nfunction toString() {\n [native code]\n}\n"){obj.toString=_14.toString;}}return obj;};dojo.mixin=function(obj,_19){for(var i=1,l=arguments.length;i0){console.warn("files still in flight!");return;}d._callLoaded();};dojo._callLoaded=function(){if(typeof setTimeout=="object"||(dojo.config.useXDomain&&d.isOpera)){if(dojo.isAIR){setTimeout(function(){dojo.loaded();},0);}else{setTimeout(dojo._scopeName+".loaded();",0);}}else{d.loaded();}};dojo._getModuleSymbols=function(_4b){var _4c=_4b.split(".");for(var i=_4c.length;i>0;i--){var _4e=_4c.slice(0,i).join(".");if((i==1)&&!this._moduleHasPrefix(_4e)){_4c[0]="../"+_4c[0];}else{var _4f=this._getModulePrefix(_4e);if(_4f!=_4e){_4c.splice(0,i,_4f);break;}}}return _4c;};dojo._global_omit_module_check=false;dojo.loadInit=function(_50){_50();};dojo._loadModule=dojo.require=function(_51,_52){_52=this._global_omit_module_check||_52;var _53=this._loadedModules[_51];if(_53){return _53;}var _54=this._getModuleSymbols(_51).join("/")+".js";var _55=(!_52)?_51:null;var ok=this._loadPath(_54,_55);if(!ok&&!_52){throw new Error("Could not load '"+_51+"'; last tried '"+_54+"'");}if(!_52&&!this._isXDomain){_53=this._loadedModules[_51];if(!_53){throw new Error("symbol '"+_51+"' is not defined after loading '"+_54+"'");}}return _53;};dojo.provide=function(_57){_57=_57+"";return (d._loadedModules[_57]=d.getObject(_57,true));};dojo.platformRequire=function(_58){var _59=_58.common||[];var _5a=_59.concat(_58[d._name]||_58["default"]||[]);for(var x=0;x<_5a.length;x++){var _5c=_5a[x];if(_5c.constructor==Array){d._loadModule.apply(d,_5c);}else{d._loadModule(_5c);}}};dojo.requireIf=function(_5d,_5e){if(_5d===true){var _5f=[];for(var i=1;i0&&!(j==1&&_70[0]=="")&&_70[j]==".."&&_70[j-1]!=".."){if(j==(_70.length-1)){_70.splice(j,1);_70[j-1]="";}else{_70.splice(j-1,2);j-=2;}}}}_6d.path=_70.join("/");}}}}uri=[];if(_6d.scheme){uri.push(_6d.scheme,":");}if(_6d.authority){uri.push("//",_6d.authority);}uri.push(_6d.path);if(_6d.query){uri.push("?",_6d.query);}if(_6d.fragment){uri.push("#",_6d.fragment);}}this.uri=uri.join("");var r=this.uri.match(ore);this.scheme=r[2]||(r[1]?"":n);this.authority=r[4]||(r[3]?"":n);this.path=r[5];this.query=r[7]||(r[6]?"":n);this.fragment=r[9]||(r[8]?"":n);if(this.authority!=n){r=this.authority.match(ire);this.user=r[3]||n;this.password=r[4]||n;this.host=r[6]||r[7];this.port=r[9]||n;}};dojo._Url.prototype.toString=function(){return this.uri;};dojo.moduleUrl=function(_73,url){var loc=d._getModuleSymbols(_73).join("/");if(!loc){return null;}if(loc.lastIndexOf("/")!=loc.length-1){loc+="/";}var _76=loc.indexOf(":");if(loc.charAt(0)!="/"&&(_76==-1||_76>loc.indexOf("/"))){loc=d.baseUrl+loc;}return new d._Url(loc,url);};})();if(dojo.config["baseUrl"]){dojo.baseUrl=dojo.config["baseUrl"];}else{dojo.baseUrl="./";}dojo.locale=dojo.locale||String(java.util.Locale.getDefault().toString().replace("_","-").toLowerCase());dojo._name="rhino";dojo.isRhino=true;if(typeof print=="function"){console.debug=print;}if(typeof dojo["byId"]=="undefined"){dojo.byId=function(id,doc){if(id&&(typeof id=="string"||id instanceof String)){if(!doc){doc=document;}return doc.getElementById(id);}return id;};}dojo._loadUri=function(uri,cb){try{var _7b=(new java.io.File(uri)).exists();if(!_7b){try{var _7c=(new java.net.URL(uri)).openStream();_7c.close();}catch(e){return false;}}if(cb){var _7d=(_7b?readText:readUri)(uri,"UTF-8");cb(eval("("+_7d+")"));}else{load(uri);}return true;}catch(e){console.debug("rhino load('"+uri+"') failed. Exception: "+e);return false;}};dojo.exit=function(_7e){quit(_7e);};dojo._rhinoCurrentScriptViaJava=function(_7f){var _80=Packages.org.mozilla.javascript.Context.getCurrentContext().getOptimizationLevel();var caw=new java.io.CharArrayWriter();var pw=new java.io.PrintWriter(caw);var exc=new java.lang.Exception();var s=caw.toString();var _85=s.match(/[^\(]*\.js\)/gi);if(!_85){throw Error("cannot parse printStackTrace output: "+s);}var _86=((typeof _7f!="undefined")&&(_7f))?_85[_7f+1]:_85[_85.length-1];_86=_85[3];if(!_86){_86=_85[1];}if(!_86){throw Error("could not find js file in printStackTrace output: "+s);}return _86;};function readText(_87,_88){_88=_88||"utf-8";var jf=new java.io.File(_87);var is=new java.io.FileInputStream(jf);return dj_readInputStream(is,_88);};function readUri(uri,_8c){var _8d=(new java.net.URL(uri)).openConnection();_8c=_8c||_8d.getContentEncoding()||"utf-8";var is=_8d.getInputStream();return dj_readInputStream(is,_8c);};function dj_readInputStream(is,_90){var _91=new java.io.BufferedReader(new java.io.InputStreamReader(is,_90));try{var sb=new java.lang.StringBuffer();var _93="";while((_93=_91.readLine())!==null){sb.append(_93);sb.append(java.lang.System.getProperty("line.separator"));}return sb.toString();}finally{_91.close();}};if((!dojo.config.libraryScriptUri)||(!dojo.config.libraryScriptUri.length)){try{dojo.config.libraryScriptUri=dojo._rhinoCurrentScriptViaJava(1);}catch(e){if(dojo.config["isDebug"]){print("\n");print("we have no idea where Dojo is located.");print("Please try loading rhino in a non-interpreted mode or set a");print("\n\tdjConfig.libraryScriptUri\n");print("Setting the dojo path to './'");print("This is probably wrong!");print("\n");print("Dojo will try to load anyway");}dojo.config.libraryScriptUri="./";}}dojo.doc=typeof (document)!="undefined"?document:null;dojo.body=function(){return document.body;};try{setTimeout;clearTimeout;}catch(e){dojo._timeouts=[];function clearTimeout(idx){if(!dojo._timeouts[idx]){return;}dojo._timeouts[idx].stop();};function setTimeout(_95,_96){var def={sleepTime:_96,hasSlept:false,run:function(){if(!this.hasSlept){this.hasSlept=true;java.lang.Thread.currentThread().sleep(this.sleepTime);}try{_95();}catch(e){console.debug("Error running setTimeout thread:"+e);}}};var _98=new java.lang.Runnable(def);var _99=new java.lang.Thread(_98);_99.start();return dojo._timeouts.push(_99)-1;};}if(dojo.config["modulePaths"]){for(var _9a in dojo.config["modulePaths"]){dojo.registerModulePath(_9a,dojo.config["modulePaths"][_9a]);}}if(!dojo._hasResource["dojo._base.lang"]){dojo._hasResource["dojo._base.lang"]=true;dojo.provide("dojo._base.lang");dojo.isString=function(it){return !!arguments.length&&it!=null&&(typeof it=="string"||it instanceof String);};dojo.isArray=function(it){return it&&(it instanceof Array||typeof it=="array");};dojo.isFunction=(function(){var _9d=function(it){return it&&(typeof it=="function"||it instanceof Function);};return dojo.isSafari?function(it){if(typeof it=="function"&&it=="[object NodeList]"){return false;}return _9d(it);}:_9d;})();dojo.isObject=function(it){return it!==undefined&&(it===null||typeof it=="object"||dojo.isArray(it)||dojo.isFunction(it));};dojo.isArrayLike=function(it){var d=dojo;return it&&it!==undefined&&!d.isString(it)&&!d.isFunction(it)&&!(it.tagName&&it.tagName.toLowerCase()=="form")&&(d.isArray(it)||isFinite(it.length));};dojo.isAlien=function(it){return it&&!dojo.isFunction(it)&&/\{\s*\[native code\]\s*\}/.test(String(it));};dojo.extend=function(_a4,_a5){for(var i=1,l=arguments.length;i2){return dojo._hitchArgs.apply(dojo,arguments);}if(!_af){_af=_ae;_ae=null;}if(dojo.isString(_af)){_ae=_ae||dojo.global;if(!_ae[_af]){throw (["dojo.hitch: scope[\"",_af,"\"] is null (scope=\"",_ae,"\")"].join(""));}return function(){return _ae[_af].apply(_ae,arguments||[]);};}return !_ae?_af:function(){return _af.apply(_ae,arguments||[]);};};dojo.delegate=dojo._delegate=(function(){function TMP(){};return function(obj,_b1){TMP.prototype=obj;var tmp=new TMP();if(_b1){dojo._mixin(tmp,_b1);}return tmp;};})();(function(){var _b3=function(obj,_b5,_b6){return (_b6||[]).concat(Array.prototype.slice.call(obj,_b5||0));};var _b7=function(obj,_b9,_ba){var arr=_ba||[];for(var x=_b9||0;x=0){this._fire();}return this;},_fire:function(){var _130=this.chain;var _131=this.fired;var res=this.results[_131];var self=this;var cb=null;while((_130.length>0)&&(this.paused==0)){var f=_130.shift()[_131];if(!f){continue;}var func=function(){var ret=f(res);if(typeof ret!="undefined"){res=ret;}_131=((res instanceof Error)?1:0);if(res instanceof dojo.Deferred){cb=function(res){self._resback(res);self.paused--;if((self.paused==0)&&(self.fired>=0)){self._fire();}};this.paused++;}};if(dojo.config.isDebug){func.call(this);}else{try{func.call(this);}catch(err){_131=1;res=err;}}}this.fired=_131;this.results[_131]=res;if((cb)&&(this.paused)){res.addBoth(cb);}}});}if(!dojo._hasResource["dojo._base.json"]){dojo._hasResource["dojo._base.json"]=true;dojo.provide("dojo._base.json");dojo.fromJson=function(json){return eval("("+json+")");};dojo._escapeString=function(str){return ("\""+str.replace(/(["\\])/g,"\\$1")+"\"").replace(/[\f]/g,"\\f").replace(/[\b]/g,"\\b").replace(/[\n]/g,"\\n").replace(/[\t]/g,"\\t").replace(/[\r]/g,"\\r");};dojo.toJsonIndentStr="\t";dojo.toJson=function(it,_13c,_13d){if(it===undefined){return "undefined";}var _13e=typeof it;if(_13e=="number"||_13e=="boolean"){return it+"";}if(it===null){return "null";}if(dojo.isString(it)){return dojo._escapeString(it);}var _13f=arguments.callee;var _140;_13d=_13d||"";var _141=_13c?_13d+dojo.toJsonIndentStr:"";var tf=it.__json__||it.json;if(dojo.isFunction(tf)){_140=tf.call(it);if(it!==_140){return _13f(_140,_13c,_141);}}if(it.nodeType&&it.cloneNode){throw new Error("Can't serialize DOM nodes");}var sep=_13c?" ":"";var _144=_13c?"\n":"";if(dojo.isArray(it)){var res=dojo.map(it,function(obj){var val=_13f(obj,_13c,_141);if(typeof val!="string"){val="undefined";}return _144+_141+val;});return "["+res.join(","+sep)+_144+_13d+"]";}if(_13e=="function"){return null;}var _148=[],key;for(key in it){var _14a,val;if(typeof key=="number"){_14a="\""+key+"\"";}else{if(typeof key=="string"){_14a=dojo._escapeString(key);}else{continue;}}val=_13f(it[key],_13c,_141);if(typeof val!="string"){continue;}_148.push(_144+_141+_14a+":"+sep+val);}return "{"+_148.join(","+sep)+_144+_13d+"}";};}if(!dojo._hasResource["dojo._base.array"]){dojo._hasResource["dojo._base.array"]=true;dojo.provide("dojo._base.array");(function(){var _14c=function(arr,obj,cb){return [dojo.isString(arr)?arr.split(""):arr,obj||dojo.global,dojo.isString(cb)?new Function("item","index","array",cb):cb];};dojo.mixin(dojo,{indexOf:function(_150,_151,_152,_153){var step=1,end=_150.length||0,i=0;if(_153){i=end-1;step=end=-1;}if(_152!=undefined){i=_152;}if((_153&&i>end)||i>=bits;t[x]=bits==4?17*c:c;});t.a=1;return t;};dojo.colorFromArray=function(a,obj){var t=obj||new dojo.Color();t._set(Number(a[0]),Number(a[1]),Number(a[2]),Number(a[3]));if(isNaN(t.a)){t.a=1;}return t.sanitize();};dojo.colorFromString=function(str,obj){var a=dojo.Color.named[str];return a&&dojo.colorFromArray(a,obj)||dojo.colorFromRgb(str,obj)||dojo.colorFromHex(str,obj);};}if(!dojo._hasResource["dojo._base"]){dojo._hasResource["dojo._base"]=true;dojo.provide("dojo._base");dojo.requireIf(dojo.isBrowser,"dojo._base.browser");}if(dojo.config.afterOnLoad&&dojo.isBrowser){window.setTimeout(dojo._fakeLoadInit,1000);}})(); diff --git a/dojo/dojo/string.js b/dojo/dojo/string.js new file mode 100644 index 000000000..4240ee13f --- /dev/null +++ b/dojo/dojo/string.js @@ -0,0 +1,148 @@ +/* + Copyright (c) 2004-2008, The Dojo Foundation All Rights Reserved. + Available via Academic Free License >= 2.1 OR the modified BSD license. + see: http://dojotoolkit.org/license for details +*/ + + +if(!dojo._hasResource["dojo.string"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojo.string"] = true; +dojo.provide("dojo.string"); + +/*===== +dojo.string = { + // summary: String utilities for Dojo +}; +=====*/ + +dojo.string.rep = function(/*String*/str, /*Integer*/num){ + // summary: + // Efficiently replicate a string `n` times. + // str: + // the string to replicate + // num: + // number of times to replicate the string + + if(num <= 0 || !str){ return ""; } + + var buf = []; + for(;;){ + if(num & 1){ + buf.push(str); + } + if(!(num >>= 1)){ break; } + str += str; + } + return buf.join(""); // String +}; + +dojo.string.pad = function(/*String*/text, /*Integer*/size, /*String?*/ch, /*Boolean?*/end){ + // summary: + // Pad a string to guarantee that it is at least `size` length by + // filling with the character `ch` at either the start or end of the + // string. Pads at the start, by default. + // text: + // the string to pad + // size: + // length to provide padding + // ch: + // character to pad, defaults to '0' + // end: + // adds padding at the end if true, otherwise pads at start + // example: + // | // Fill the string to length 10 with "+" characters on the right. Yields "Dojo++++++". + // | dojo.string.pad("Dojo", 10, "+", true); + + if(!ch){ + ch = '0'; + } + var out = String(text), + pad = dojo.string.rep(ch, Math.ceil((size - out.length) / ch.length)); + return end ? out + pad : pad + out; // String +}; + +dojo.string.substitute = function( /*String*/ template, + /*Object|Array*/map, + /*Function?*/ transform, + /*Object?*/ thisObject){ + // summary: + // Performs parameterized substitutions on a string. Throws an + // exception if any parameter is unmatched. + // template: + // a string with expressions in the form `${key}` to be replaced or + // `${key:format}` which specifies a format function. + // map: + // hash to search for substitutions + // transform: + // a function to process all parameters before substitution takes + // place, e.g. dojo.string.encodeXML + // thisObject: + // where to look for optional format function; default to the global + // namespace + // example: + // | // returns "File 'foo.html' is not found in directory '/temp'." + // | dojo.string.substitute( + // | "File '${0}' is not found in directory '${1}'.", + // | ["foo.html","/temp"] + // | ); + // | + // | // also returns "File 'foo.html' is not found in directory '/temp'." + // | dojo.string.substitute( + // | "File '${name}' is not found in directory '${info.dir}'.", + // | { name: "foo.html", info: { dir: "/temp" } } + // | ); + // example: + // use a transform function to modify the values: + // | // returns "file 'foo.html' is not found in directory '/temp'." + // | dojo.string.substitute( + // | "${0} is not found in ${1}.", + // | ["foo.html","/temp"], + // | function(str){ + // | // try to figure out the type + // | var prefix = (str.charAt(0) == "/") ? "directory": "file"; + // | return prefix + " '" + str + "'"; + // | } + // | ); + // example: + // use a formatter + // | // returns "thinger -- howdy" + // | dojo.string.substitute( + // | "${0:postfix}", ["thinger"], null, { + // | postfix: function(value, key){ + // | return value + " -- howdy"; + // | } + // | } + // | ); + + thisObject = thisObject||dojo.global; + transform = (!transform) ? + function(v){ return v; } : + dojo.hitch(thisObject, transform); + + return template.replace(/\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g, function(match, key, format){ + var value = dojo.getObject(key, false, map); + if(format){ + value = dojo.getObject(format, false, thisObject).call(thisObject, value, key); + } + return transform(value, key).toString(); + }); // string +}; + +dojo.string.trim = function(/*String*/ str){ + // summary: + // trims whitespaces from both sides of the string + // description: + // This version of trim() was taken from [Steven Levithan's blog](http://blog.stevenlevithan.com/archives/faster-trim-javascript). + // The short yet performant version of this function is dojo.trim(), + // which is part of Dojo base. + str = str.replace(/^\s+/, ''); + for(var i = str.length - 1; i >= 0; i--){ + if(/\S/.test(str.charAt(i))){ + str = str.substring(0, i + 1); + break; + } + } + return str; // String +}; + +} diff --git a/dojo/dojox/LICENSE b/dojo/dojox/LICENSE new file mode 100644 index 000000000..3fa27203c --- /dev/null +++ b/dojo/dojox/LICENSE @@ -0,0 +1,195 @@ +Dojo is available under *either* the terms of the modified BSD license *or* the +Academic Free License version 2.1. As a recipient of Dojo, you may choose which +license to receive this code under (except as noted in per-module LICENSE +files). Some modules may not be the copyright of the Dojo Foundation. These +modules contain explicit declarations of copyright in both the LICENSE files in +the directories in which they reside and in the code itself. No external +contributions are allowed under licenses which are fundamentally incompatible +with the AFL or BSD licenses that Dojo is distributed under. + +The text of the AFL and BSD licenses is reproduced below. + +------------------------------------------------------------------------------- +The "New" BSD License: +********************** + +Copyright (c) 2005-2008, The Dojo Foundation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the Dojo Foundation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------------- +The Academic Free License, v. 2.1: +********************************** + +This Academic Free License (the "License") applies to any original work of +authorship (the "Original Work") whose owner (the "Licensor") has placed the +following notice immediately following the copyright notice for the Original +Work: + +Licensed under the Academic Free License version 2.1 + +1) Grant of Copyright License. Licensor hereby grants You a world-wide, +royalty-free, non-exclusive, perpetual, sublicenseable license to do the +following: + +a) to reproduce the Original Work in copies; + +b) to prepare derivative works ("Derivative Works") based upon the Original +Work; + +c) to distribute copies of the Original Work and Derivative Works to the +public; + +d) to perform the Original Work publicly; and + +e) to display the Original Work publicly. + +2) Grant of Patent License. Licensor hereby grants You a world-wide, +royalty-free, non-exclusive, perpetual, sublicenseable license, under patent +claims owned or controlled by the Licensor that are embodied in the Original +Work as furnished by the Licensor, to make, use, sell and offer for sale the +Original Work and Derivative Works. + +3) Grant of Source Code License. The term "Source Code" means the preferred +form of the Original Work for making modifications to it and all available +documentation describing how to modify the Original Work. Licensor hereby +agrees to provide a machine-readable copy of the Source Code of the Original +Work along with each copy of the Original Work that Licensor distributes. +Licensor reserves the right to satisfy this obligation by placing a +machine-readable copy of the Source Code in an information repository +reasonably calculated to permit inexpensive and convenient access by You for as +long as Licensor continues to distribute the Original Work, and by publishing +the address of that information repository in a notice immediately following +the copyright notice that applies to the Original Work. + +4) Exclusions From License Grant. Neither the names of Licensor, nor the names +of any contributors to the Original Work, nor any of their trademarks or +service marks, may be used to endorse or promote products derived from this +Original Work without express prior written permission of the Licensor. Nothing +in this License shall be deemed to grant any rights to trademarks, copyrights, +patents, trade secrets or any other intellectual property of Licensor except as +expressly stated herein. No patent license is granted to make, use, sell or +offer to sell embodiments of any patent claims other than the licensed claims +defined in Section 2. No right is granted to the trademarks of Licensor even if +such marks are included in the Original Work. Nothing in this License shall be +interpreted to prohibit Licensor from licensing under different terms from this +License any Original Work that Licensor otherwise would have a right to +license. + +5) This section intentionally omitted. + +6) Attribution Rights. You must retain, in the Source Code of any Derivative +Works that You create, all copyright, patent or trademark notices from the +Source Code of the Original Work, as well as any notices of licensing and any +descriptive text identified therein as an "Attribution Notice." You must cause +the Source Code for any Derivative Works that You create to carry a prominent +Attribution Notice reasonably calculated to inform recipients that You have +modified the Original Work. + +7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that +the copyright in and to the Original Work and the patent rights granted herein +by Licensor are owned by the Licensor or are sublicensed to You under the terms +of this License with the permission of the contributor(s) of those copyrights +and patent rights. Except as expressly stated in the immediately proceeding +sentence, the Original Work is provided under this License on an "AS IS" BASIS +and WITHOUT WARRANTY, either express or implied, including, without limitation, +the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. +This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No +license to Original Work is granted hereunder except under this disclaimer. + +8) Limitation of Liability. Under no circumstances and under no legal theory, +whether in tort (including negligence), contract, or otherwise, shall the +Licensor be liable to any person for any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License +or the use of the Original Work including, without limitation, damages for loss +of goodwill, work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses. This limitation of liability shall not +apply to liability for death or personal injury resulting from Licensor's +negligence to the extent applicable law prohibits such limitation. Some +jurisdictions do not allow the exclusion or limitation of incidental or +consequential damages, so this exclusion and limitation may not apply to You. + +9) Acceptance and Termination. If You distribute copies of the Original Work or +a Derivative Work, You must make a reasonable effort under the circumstances to +obtain the express assent of recipients to the terms of this License. Nothing +else but this License (or another written agreement between Licensor and You) +grants You permission to create Derivative Works based upon the Original Work +or to exercise any of the rights granted in Section 1 herein, and any attempt +to do so except under the terms of this License (or another written agreement +between Licensor and You) is expressly prohibited by U.S. copyright law, the +equivalent laws of other countries, and by international treaty. Therefore, by +exercising any of the rights granted to You in Section 1 herein, You indicate +Your acceptance of this License and all of its terms and conditions. + +10) Termination for Patent Action. This License shall terminate automatically +and You may no longer exercise any of the rights granted to You by this License +as of the date You commence an action, including a cross-claim or counterclaim, +against Licensor or any licensee alleging that the Original Work infringes a +patent. This termination provision shall not apply for an action alleging +patent infringement by combinations of the Original Work with other software or +hardware. + +11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this +License may be brought only in the courts of a jurisdiction wherein the +Licensor resides or in which Licensor conducts its primary business, and under +the laws of that jurisdiction excluding its conflict-of-law provisions. The +application of the United Nations Convention on Contracts for the International +Sale of Goods is expressly excluded. Any use of the Original Work outside the +scope of this License or after its termination shall be subject to the +requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et +seq., the equivalent laws of other countries, and international treaty. This +section shall survive the termination of this License. + +12) Attorneys Fees. In any action to enforce the terms of this License or +seeking damages relating thereto, the prevailing party shall be entitled to +recover its costs and expenses, including, without limitation, reasonable +attorneys' fees and costs incurred in connection with such action, including +any appeal of such action. This section shall survive the termination of this +License. + +13) Miscellaneous. This License represents the complete agreement concerning +the subject matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent necessary to +make it enforceable. + +14) Definition of "You" in This License. "You" throughout this License, whether +in upper or lower case, means an individual or a legal entity exercising rights +under, and complying with all of the terms of, this License. For legal +entities, "You" includes any entity that controls, is controlled by, or is +under common control with you. For purposes of this definition, "control" means +(i) the power, direct or indirect, to cause the direction or management of such +entity, whether by contract or otherwise, or (ii) ownership of fifty percent +(50%) or more of the outstanding shares, or (iii) beneficial ownership of such +entity. + +15) Right to Use. You may use the Original Work in all ways not otherwise +restricted or conditioned by this License or by law, and Licensor promises not +to interfere with or be responsible for such uses by You. + +This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved. +Permission is hereby granted to copy and distribute this license without +modification. This license may not be modified without the express written +permission of its copyright owner. diff --git a/dojo/dojox/testing/DocTest.js b/dojo/dojox/testing/DocTest.js new file mode 100644 index 000000000..b7daa5324 --- /dev/null +++ b/dojo/dojox/testing/DocTest.js @@ -0,0 +1,288 @@ +/* + Copyright (c) 2004-2008, The Dojo Foundation All Rights Reserved. + Available via Academic Free License >= 2.1 OR the modified BSD license. + see: http://dojotoolkit.org/license for details +*/ + + +if(!dojo._hasResource["dojox.testing.DocTest"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.testing.DocTest"] = true; +dojo.provide("dojox.testing.DocTest"); +dojo.require("dojo.string"); + +dojo.declare( + "dojox.testing.DocTest", + null, + { + // summary: + // This class executes doctests. + // description: + // DocTests are tests that are defined inside the comment. + // A doctest looks as if it was copied from the shell (which it mostly is). + // A doctest is executed when the following conditions match: + // 1) all lines are comments + // 2) the line always starts with spaces/tabs followed by "//" + // and at least one space + // 3) the line(s) of the test to execute starts with ">>>" + // preceeded by what is described in 2) + // 4) the first line after 3) starting without ">>>" is the exptected result. + // preceeded by what is described in 2) + // 5) the test sequence is terminated by an empty line, or the next + // test in the following line, or a new line that does not start as described in 2) + // (simple said: is not a comment) + // preceeded by what is described in 2) + // + // I.e. the following is a simple doctest, that will actually also be run + // if you run this class against this file here: + // >>> 1+1 // A simple test case. Terminated by an empty line + // 2 + // + // >>> 1==2 + // false + // >>> "a"+"b" // Also without the empty line before, this is a new test. + // "ab" + // + // >>> var anything = "anything" // Multiple commands for one test. + // >>> "something"==anything + // false + // + // DocTests are great for inline documenting a class or method, they also + // are very helpful in understanding what the class/method actually does. + // They don't make sense everywhere, but sometimes they are really handy. + + + // TODO: + // - using console.log() in a test prints something on the + // console (if you do it on the console) but its not accepted + // yet to be the test result, may be override console.log!? + // i.e. here i wanted to: dojo.forEach(["one", 2], + // function(el, index) {console.log(el, index)}) that works on + // the console, but not as a docTest :-( + // - surround the eval for each test case singlely with a + // try-catch, to to catch syntax errors etc (though the + // shouldn't happen if you copy the test from the shell :-)) + + + errors: [], + + getTests:function(/*String*/moduleName){ + // summary: Extract the tests from the given module or string. + // examples: + // >>> dojo.isArray(new dojox.testing.DocTest().getTests("dojox.testing.DocTest")) // Use the module name to extract the tests from. + // true + var path = dojo.moduleUrl(moduleName).path; + // TODO: + // this needs to be done better, this is pretty simple and + // surely not dummy proof + var file = path.substring(0, path.length-1)+".js"; + var xhr = dojo.xhrGet({url:file, handleAs:"text"}); + // Make loading synchronously, mainly so we can use it in doh. + var data = dojo._getText(file); + return this._getTestsFromString(data, true); + }, + + getTestsFromString:function(/*String*/data){ + // examples: + // >>> (new dojox.testing.DocTest().getTestsFromString(">>> 1+1\n2\n>>> 2+2\n4")).length // Do tests from strings get detected properly? + // 2 + return this._getTestsFromString(data, false); + }, + + _getTestsFromString:function(/*String*/data, /*Boolean*/insideComments){ + // summary: Parse the given string for tests. + // insideComments: Boolean, if false "data" contains only the pure tests, comments already stripped. + var trim = dojo.hitch(dojo.string, "trim"); + var lines = data.split("\n"); + var len = lines.length; + var tests = []; + var test = { + commands: [], + expectedResult: [], + line: null + }; + for(var i=0; i>>\s.*/)) || l.match(/^\s*>>>\s.*/)){ + if(!test.line){ + test.line = i+1; + } + // Find the test commands. + if(test.expectedResult.length>0){ + // Start a new test right after the expected result, + // without an empty line. + tests.push({ + commands: test.commands, + expectedResult: test.expectedResult.join("\n"), + line: test.line + }); + test = {commands:[], expectedResult:[], line:i+1}; + } + l = insideComments ? trim(l).substring(2, l.length) : l; // Remove the leading slashes. + l = trim(l).substring(3, l.length); // Remove the ">>>". + test.commands.push(trim(l)); + }else if((!insideComments || l.match(/^\/\/\s+.*/)) && test.commands.length && test.expectedResult.length==0){ + // Detect the lines after the ">>>"-lines, the exptected result. + l = insideComments ? trim(l).substring(3, l.length) : l; // Remove the leading slashes. + test.expectedResult.push(trim(l)); + }else if(test.commands.length>0 && test.expectedResult.length){ + if(!insideComments || l.match(/^\/\/\s*$/)){ + // Detect the empty line. + tests.push({ + commands: test.commands, + expectedResult: test.expectedResult.join("\n"), + line: test.line + }); + } + if(insideComments && !l.match(/^\/\//)){ + // If the next line is not a comment at all (doesn't start with "//"). + tests.push({ + commands: test.commands, + expectedResult: test.expectedResult.join("\n"), + line:test.line + }); + } + test = { + commands: [], + expectedResult: [], + line:0 + }; + } + } + return tests; + }, + + run: function(moduleName){ + // summary: + // Run the doctests in the module given. + // example: + // doctest = new dojox.testing.DocTest(); + // doctest.run("dojox.testing.DocTest"); + // doctest.errors should finally be an empty array. + // // The above is not a doctest, because it just would + // // execute itself in a never ending loop. + // + // >>> true==true // Test a new line terminating the test. + // true + // + // >>> true==true // Test a new test terminating the test. + // true + // >>> true==true // Test a "not a comment"-line, especially an empty line terminating the test. + // true + + // Make sure the result as printed on the console is the same as what + // is returned by the test. An array is printed as follows on the console. + // >>> [1,2,3,4] + // [1,2,3,4] + // + // Test a "not a comment"-line, with some real code(!) terminating the test. + // This used to be a bug, so make sure the line below the test is real + // from this method! Don't write a test after it, always above! + // >>> true==true // Test code on new line terminating the test. + // true + + this.errors = []; + + var tests = this.getTests(moduleName); + if(tests){ + this._run(tests); + } + }, + + _run: function(/*Array*/tests){ + // summary: + // Each element in the array contains the test in the first element, + // and the expected result in the second element. + // tests: + // Make sure that the types are compared properly. There used to be + // the bug that a return value false was compared to "false" which + // made the test fail. This is fixed and should be verified by the + // following tests. + // >>> false + // false + // + // >>> "false" + // "false" + // + // >>> true + // true + // + // >>> 1 + // 1 + // + // >>> "s" + // "s" + // + // >>> dojo.toJson({one:1}) + // "{"one":1}" + // + var len = tests.length; + this.tests = len; + var oks = 0; + for(var i=0; i 50 ? + viewCommands.substr(0,50) + "..." : + viewCommands + ); + if(res.success){ + // the last if-condition, dojo.toJson() adds a quote sign " + // before and after the result, may be we remove it and + // test the result again + console.info(msg+"OK: "+viewCommands); + oks += 1; + }else{ + this.errors.push({ + commands: t.commands, + actual: res.actualResult, + expected: t.expectedResult + }); + console.error(msg+"Failed: "+viewCommands, { + commands: t.commands, + actualResult: res.actualResult, + expectedResult: t.expectedResult + }); + } + } + console.info(len+" tests ran.", oks+" Success,", this.errors.length+" Errors"); + }, + + runTest: function(commands, expected){ + var ret = { + success: false, + actualResult: null + }; + // Concat multiple commands with new lines, so "//" comments at + // the end of a line don't deactivate the next line (which it + // would if we only concatenated with ";"). + var cmds = commands.join("\n"); + ret.actualResult = eval(cmds); + if( (String(ret.actualResult)==expected) || + (dojo.toJson(ret.actualResult)==expected) || + ( + (expected.charAt(0)=='"')&& + (expected.charAt(expected.length-1)=='"')&& + (String(ret.actualResult)==expected.substring(1, expected.length-1)) + ) + ){ + // the last if-condition, dojo.toJson() adds a quote sign " + // before and after the result, may be we remove it and test + // the result again + ret.success = true; + } + return ret; + } + } +); + +} diff --git a/dojo/util/doh/LICENSE b/dojo/util/doh/LICENSE new file mode 100644 index 000000000..3fa27203c --- /dev/null +++ b/dojo/util/doh/LICENSE @@ -0,0 +1,195 @@ +Dojo is available under *either* the terms of the modified BSD license *or* the +Academic Free License version 2.1. As a recipient of Dojo, you may choose which +license to receive this code under (except as noted in per-module LICENSE +files). Some modules may not be the copyright of the Dojo Foundation. These +modules contain explicit declarations of copyright in both the LICENSE files in +the directories in which they reside and in the code itself. No external +contributions are allowed under licenses which are fundamentally incompatible +with the AFL or BSD licenses that Dojo is distributed under. + +The text of the AFL and BSD licenses is reproduced below. + +------------------------------------------------------------------------------- +The "New" BSD License: +********************** + +Copyright (c) 2005-2008, The Dojo Foundation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the Dojo Foundation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------------- +The Academic Free License, v. 2.1: +********************************** + +This Academic Free License (the "License") applies to any original work of +authorship (the "Original Work") whose owner (the "Licensor") has placed the +following notice immediately following the copyright notice for the Original +Work: + +Licensed under the Academic Free License version 2.1 + +1) Grant of Copyright License. Licensor hereby grants You a world-wide, +royalty-free, non-exclusive, perpetual, sublicenseable license to do the +following: + +a) to reproduce the Original Work in copies; + +b) to prepare derivative works ("Derivative Works") based upon the Original +Work; + +c) to distribute copies of the Original Work and Derivative Works to the +public; + +d) to perform the Original Work publicly; and + +e) to display the Original Work publicly. + +2) Grant of Patent License. Licensor hereby grants You a world-wide, +royalty-free, non-exclusive, perpetual, sublicenseable license, under patent +claims owned or controlled by the Licensor that are embodied in the Original +Work as furnished by the Licensor, to make, use, sell and offer for sale the +Original Work and Derivative Works. + +3) Grant of Source Code License. The term "Source Code" means the preferred +form of the Original Work for making modifications to it and all available +documentation describing how to modify the Original Work. Licensor hereby +agrees to provide a machine-readable copy of the Source Code of the Original +Work along with each copy of the Original Work that Licensor distributes. +Licensor reserves the right to satisfy this obligation by placing a +machine-readable copy of the Source Code in an information repository +reasonably calculated to permit inexpensive and convenient access by You for as +long as Licensor continues to distribute the Original Work, and by publishing +the address of that information repository in a notice immediately following +the copyright notice that applies to the Original Work. + +4) Exclusions From License Grant. Neither the names of Licensor, nor the names +of any contributors to the Original Work, nor any of their trademarks or +service marks, may be used to endorse or promote products derived from this +Original Work without express prior written permission of the Licensor. Nothing +in this License shall be deemed to grant any rights to trademarks, copyrights, +patents, trade secrets or any other intellectual property of Licensor except as +expressly stated herein. No patent license is granted to make, use, sell or +offer to sell embodiments of any patent claims other than the licensed claims +defined in Section 2. No right is granted to the trademarks of Licensor even if +such marks are included in the Original Work. Nothing in this License shall be +interpreted to prohibit Licensor from licensing under different terms from this +License any Original Work that Licensor otherwise would have a right to +license. + +5) This section intentionally omitted. + +6) Attribution Rights. You must retain, in the Source Code of any Derivative +Works that You create, all copyright, patent or trademark notices from the +Source Code of the Original Work, as well as any notices of licensing and any +descriptive text identified therein as an "Attribution Notice." You must cause +the Source Code for any Derivative Works that You create to carry a prominent +Attribution Notice reasonably calculated to inform recipients that You have +modified the Original Work. + +7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that +the copyright in and to the Original Work and the patent rights granted herein +by Licensor are owned by the Licensor or are sublicensed to You under the terms +of this License with the permission of the contributor(s) of those copyrights +and patent rights. Except as expressly stated in the immediately proceeding +sentence, the Original Work is provided under this License on an "AS IS" BASIS +and WITHOUT WARRANTY, either express or implied, including, without limitation, +the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. +This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No +license to Original Work is granted hereunder except under this disclaimer. + +8) Limitation of Liability. Under no circumstances and under no legal theory, +whether in tort (including negligence), contract, or otherwise, shall the +Licensor be liable to any person for any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License +or the use of the Original Work including, without limitation, damages for loss +of goodwill, work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses. This limitation of liability shall not +apply to liability for death or personal injury resulting from Licensor's +negligence to the extent applicable law prohibits such limitation. Some +jurisdictions do not allow the exclusion or limitation of incidental or +consequential damages, so this exclusion and limitation may not apply to You. + +9) Acceptance and Termination. If You distribute copies of the Original Work or +a Derivative Work, You must make a reasonable effort under the circumstances to +obtain the express assent of recipients to the terms of this License. Nothing +else but this License (or another written agreement between Licensor and You) +grants You permission to create Derivative Works based upon the Original Work +or to exercise any of the rights granted in Section 1 herein, and any attempt +to do so except under the terms of this License (or another written agreement +between Licensor and You) is expressly prohibited by U.S. copyright law, the +equivalent laws of other countries, and by international treaty. Therefore, by +exercising any of the rights granted to You in Section 1 herein, You indicate +Your acceptance of this License and all of its terms and conditions. + +10) Termination for Patent Action. This License shall terminate automatically +and You may no longer exercise any of the rights granted to You by this License +as of the date You commence an action, including a cross-claim or counterclaim, +against Licensor or any licensee alleging that the Original Work infringes a +patent. This termination provision shall not apply for an action alleging +patent infringement by combinations of the Original Work with other software or +hardware. + +11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this +License may be brought only in the courts of a jurisdiction wherein the +Licensor resides or in which Licensor conducts its primary business, and under +the laws of that jurisdiction excluding its conflict-of-law provisions. The +application of the United Nations Convention on Contracts for the International +Sale of Goods is expressly excluded. Any use of the Original Work outside the +scope of this License or after its termination shall be subject to the +requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et +seq., the equivalent laws of other countries, and international treaty. This +section shall survive the termination of this License. + +12) Attorneys Fees. In any action to enforce the terms of this License or +seeking damages relating thereto, the prevailing party shall be entitled to +recover its costs and expenses, including, without limitation, reasonable +attorneys' fees and costs incurred in connection with such action, including +any appeal of such action. This section shall survive the termination of this +License. + +13) Miscellaneous. This License represents the complete agreement concerning +the subject matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent necessary to +make it enforceable. + +14) Definition of "You" in This License. "You" throughout this License, whether +in upper or lower case, means an individual or a legal entity exercising rights +under, and complying with all of the terms of, this License. For legal +entities, "You" includes any entity that controls, is controlled by, or is +under common control with you. For purposes of this definition, "control" means +(i) the power, direct or indirect, to cause the direction or management of such +entity, whether by contract or otherwise, or (ii) ownership of fifty percent +(50%) or more of the outstanding shares, or (iii) beneficial ownership of such +entity. + +15) Right to Use. You may use the Original Work in all ways not otherwise +restricted or conditioned by this License or by law, and Licensor promises not +to interfere with or be responsible for such uses by You. + +This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved. +Permission is hereby granted to copy and distribute this license without +modification. This license may not be modified without the express written +permission of its copyright owner. diff --git a/dojo/util/doh/_rhinoRunner.js b/dojo/util/doh/_rhinoRunner.js new file mode 100644 index 000000000..ae4759723 --- /dev/null +++ b/dojo/util/doh/_rhinoRunner.js @@ -0,0 +1,17 @@ +if(this["dojo"]){ + dojo.provide("doh._rhinoRunner"); +} + +doh.debug = print; + +// Override the doh._report method to make it quit with an +// appropriate exit code in case of test failures. +(function(){ + var oldReport = doh._report; + doh._report = function(){ + oldReport.apply(doh, arguments); + if(this._failureCount > 0 || this._errorCount > 0){ + quit(1); + } + } +})(); diff --git a/dojo/util/doh/runner.js b/dojo/util/doh/runner.js new file mode 100644 index 000000000..3b4539317 --- /dev/null +++ b/dojo/util/doh/runner.js @@ -0,0 +1,1054 @@ +// package system gunk. +try{ + dojo.provide("doh.runner"); +}catch(e){ + if(!this["doh"]){ + doh = {}; + } +} + +// +// Utility Functions and Classes +// + +doh.selfTest = false; + +doh.global = this; + +doh.hitch = function(/*Object*/thisObject, /*Function|String*/method /*, ...*/){ + var args = []; + for(var x=2; x= 0)) { + this._fire(); + } + }, + + _continue: function(res){ + this._resback(res); + this._unpause(); + }, + + _resback: function(res){ + this.fired = ((res instanceof Error) ? 1 : 0); + this.results[this.fired] = res; + this._fire(); + }, + + _check: function(){ + if(this.fired != -1){ + if(!this.silentlyCancelled){ + throw new Error("already called!"); + } + this.silentlyCancelled = false; + return; + } + }, + + callback: function(res){ + this._check(); + this._resback(res); + }, + + errback: function(res){ + this._check(); + if(!(res instanceof Error)){ + res = new Error(res); + } + this._resback(res); + }, + + addBoth: function(cb, cbfn){ + var enclosed = this.getFunctionFromArgs(cb, cbfn); + if(arguments.length > 2){ + enclosed = doh.hitch(null, enclosed, arguments, 2); + } + return this.addCallbacks(enclosed, enclosed); + }, + + addCallback: function(cb, cbfn){ + var enclosed = this.getFunctionFromArgs(cb, cbfn); + if(arguments.length > 2){ + enclosed = doh.hitch(null, enclosed, arguments, 2); + } + return this.addCallbacks(enclosed, null); + }, + + addErrback: function(cb, cbfn){ + var enclosed = this.getFunctionFromArgs(cb, cbfn); + if(arguments.length > 2){ + enclosed = doh.hitch(null, enclosed, arguments, 2); + } + return this.addCallbacks(null, enclosed); + }, + + addCallbacks: function(cb, eb){ + this.chain.push([cb, eb]); + if(this.fired >= 0){ + this._fire(); + } + return this; + }, + + _fire: function(){ + var chain = this.chain; + var fired = this.fired; + var res = this.results[fired]; + var self = this; + var cb = null; + while(chain.length > 0 && this.paused == 0){ + // Array + var pair = chain.shift(); + var f = pair[fired]; + if(f == null){ + continue; + } + try { + res = f(res); + fired = ((res instanceof Error) ? 1 : 0); + if(res instanceof doh.Deferred){ + cb = function(res){ + self._continue(res); + }; + this._pause(); + } + }catch(err){ + fired = 1; + res = err; + } + } + this.fired = fired; + this.results[fired] = res; + if((cb)&&(this.paused)){ + res.addBoth(cb); + } + } +}); + +// +// State Keeping and Reporting +// + +doh._testCount = 0; +doh._groupCount = 0; +doh._errorCount = 0; +doh._failureCount = 0; +doh._currentGroup = null; +doh._currentTest = null; +doh._paused = true; + +doh._init = function(){ + this._currentGroup = null; + this._currentTest = null; + this._errorCount = 0; + this._failureCount = 0; + this.debug(this._testCount, "tests to run in", this._groupCount, "groups"); +} + +// doh._urls = []; +doh._groups = {}; + +// +// Test Registration +// + +doh.registerTestNs = function(/*String*/ group, /*Object*/ ns){ + // summary: + // adds the passed namespace object to the list of objects to be + // searched for test groups. Only "public" functions (not prefixed + // with "_") will be added as tests to be run. If you'd like to use + // fixtures (setUp(), tearDown(), and runTest()), please use + // registerTest() or registerTests(). + for(var x in ns){ + if( (x.charAt(0) != "_") && + (typeof ns[x] == "function") ){ + this.registerTest(group, ns[x]); + } + } +} + +doh._testRegistered = function(group, fixture){ + // slot to be filled in +} + +doh._groupStarted = function(group){ + // slot to be filled in +} + +doh._groupFinished = function(group, success){ + // slot to be filled in +} + +doh._testStarted = function(group, fixture){ + // slot to be filled in +} + +doh._testFinished = function(group, fixture, success){ + // slot to be filled in +} + +doh.registerGroup = function( /*String*/ group, + /*Array||Function||Object*/ tests, + /*Function*/ setUp, + /*Function*/ tearDown){ + // summary: + // registers an entire group of tests at once and provides a setUp and + // tearDown facility for groups. If you call this method with only + // setUp and tearDown parameters, they will replace previously + // installed setUp or tearDown functions for the group with the new + // methods. + // group: + // string name of the group + // tests: + // either a function or an object or an array of functions/objects. If + // an object, it must contain at *least* a "runTest" method, and may + // also contain "setUp" and "tearDown" methods. These will be invoked + // on either side of the "runTest" method (respectively) when the test + // is run. If an array, it must contain objects matching the above + // description or test functions. + // setUp: a function for initializing the test group + // tearDown: a function for initializing the test group + if(tests){ + this.register(group, tests); + } + if(setUp){ + this._groups[group].setUp = setUp; + } + if(tearDown){ + this._groups[group].tearDown = tearDown; + } +} + +doh._getTestObj = function(group, test){ + var tObj = test; + if(typeof test == "string"){ + if(test.substr(0, 4)=="url:"){ + return this.registerUrl(group, test); + }else{ + tObj = { + name: test.replace("/\s/g", "_") // FIXME: bad escapement + }; + tObj.runTest = new Function("t", test); + } + }else if(typeof test == "function"){ + // if we didn't get a fixture, wrap the function + tObj = { "runTest": test }; + if(test["name"]){ + tObj.name = test.name; + }else{ + try{ + var fStr = "function "; + var ts = tObj.runTest+""; + if(0 <= ts.indexOf(fStr)){ + tObj.name = ts.split(fStr)[1].split("(", 1)[0]; + } + // doh.debug(tObj.runTest.toSource()); + }catch(e){ + } + } + // FIXME: try harder to get the test name here + } + return tObj; +} + +doh.registerTest = function(/*String*/ group, /*Function||Object*/ test){ + // summary: + // add the provided test function or fixture object to the specified + // test group. + // group: + // string name of the group to add the test to + // test: + // either a function or an object. If an object, it must contain at + // *least* a "runTest" method, and may also contain "setUp" and + // "tearDown" methods. These will be invoked on either side of the + // "runTest" method (respectively) when the test is run. + if(!this._groups[group]){ + this._groupCount++; + this._groups[group] = []; + this._groups[group].inFlight = 0; + } + var tObj = this._getTestObj(group, test); + if(!tObj){ return null; } + this._groups[group].push(tObj); + this._testCount++; + this._testRegistered(group, tObj); + return tObj; +} + +doh.registerTests = function(/*String*/ group, /*Array*/ testArr){ + // summary: + // registers a group of tests, treating each element of testArr as + // though it were being (along with group) passed to the registerTest + // method. + for(var x=0; x 1) ? "s" : "")+" to run"); +} + +doh._handleFailure = function(groupName, fixture, e){ + // this.debug("FAILED test:", fixture.name); + // mostly borrowed from JUM + this._groups[groupName].failures++; + var out = ""; + if(e instanceof this._AssertFailure){ + this._failureCount++; + if(e["fileName"]){ out += e.fileName + ':'; } + if(e["lineNumber"]){ out += e.lineNumber + ' '; } + out += e+": "+e.message; + this.debug("\t_AssertFailure:", out); + }else{ + this._errorCount++; + } + this.debug(e); + if(fixture.runTest["toSource"]){ + var ss = fixture.runTest.toSource(); + this.debug("\tERROR IN:\n\t\t", ss); + }else{ + this.debug("\tERROR IN:\n\t\t", fixture.runTest); + } + + if(e.rhinoException){ + e.rhinoException.printStackTrace(); + }else if(e.javaException){ + e.javaException.printStackTrace(); + } +} + +try{ + setTimeout(function(){}, 0); +}catch(e){ + setTimeout = function(func){ + return func(); + } +} + +doh._runFixture = function(groupName, fixture){ + var tg = this._groups[groupName]; + this._testStarted(groupName, fixture); + var threw = false; + var err = null; + // run it, catching exceptions and reporting them + try{ + // let doh reference "this.group.thinger..." which can be set by + // another test or group-level setUp function + fixture.group = tg; + // only execute the parts of the fixture we've got + if(fixture["setUp"]){ fixture.setUp(this); } + if(fixture["runTest"]){ // should we error out of a fixture doesn't have a runTest? + fixture.startTime = new Date(); + var ret = fixture.runTest(this); + fixture.endTime = new Date(); + // if we get a deferred back from the test runner, we know we're + // gonna wait for an async result. It's up to the test code to trap + // errors and give us an errback or callback. + if(ret instanceof doh.Deferred){ + + tg.inFlight++; + ret.groupName = groupName; + ret.fixture = fixture; + + ret.addErrback(function(err){ + doh._handleFailure(groupName, fixture, err); + }); + + var retEnd = function(){ + if(fixture["tearDown"]){ fixture.tearDown(doh); } + tg.inFlight--; + if((!tg.inFlight)&&(tg.iterated)){ + doh._groupFinished(groupName, (!tg.failures)); + } + doh._testFinished(groupName, fixture, ret.results[0]); + if(doh._paused){ + doh.run(); + } + } + + var timer = setTimeout(function(){ + // ret.cancel(); + // retEnd(); + ret.errback(new Error("test timeout in "+fixture.name.toString())); + }, fixture["timeout"]||1000); + + ret.addBoth(function(arg){ + clearTimeout(timer); + retEnd(); + }); + if(ret.fired < 0){ + doh.pause(); + } + return ret; + } + } + if(fixture["tearDown"]){ fixture.tearDown(this); } + }catch(e){ + threw = true; + err = e; + if(!fixture.endTime){ + fixture.endTime = new Date(); + } + } + var d = new doh.Deferred(); + setTimeout(this.hitch(this, function(){ + if(threw){ + this._handleFailure(groupName, fixture, err); + } + this._testFinished(groupName, fixture, (!threw)); + + if((!tg.inFlight)&&(tg.iterated)){ + doh._groupFinished(groupName, (!tg.failures)); + }else if(tg.inFlight > 0){ + setTimeout(this.hitch(this, function(){ + doh.runGroup(groupName); // , idx); + }), 100); + this._paused = true; + } + if(doh._paused){ + doh.run(); + } + }), 300); + // doh.pause(); // commented out prevent tests from dropping on + // decrepit fbennett laptop + return d; +} + +doh._testId = 0; +doh.runGroup = function(/*String*/ groupName, /*Integer*/ idx){ + // summary: + // runs the specified test group + + // the general structure of the algorithm is to run through the group's + // list of doh, checking before and after each of them to see if we're in + // a paused state. This can be caused by the test returning a deferred or + // the user hitting the pause button. In either case, we want to halt + // execution of the test until something external to us restarts it. This + // means we need to pickle off enough state to pick up where we left off. + + // FIXME: need to make fixture execution async!! + + var tg = this._groups[groupName]; + if(tg.skip === true){ return; } + if(this._isArray(tg)){ + if(idx<=tg.length){ + if((!tg.inFlight)&&(tg.iterated == true)){ + if(tg["tearDown"]){ tg.tearDown(this); } + doh._groupFinished(groupName, (!tg.failures)); + return; + } + } + if(!idx){ + tg.inFlight = 0; + tg.iterated = false; + tg.failures = 0; + } + doh._groupStarted(groupName); + if(!idx){ + this._setupGroupForRun(groupName, idx); + if(tg["setUp"]){ tg.setUp(this); } + } + for(var y=(idx||0); y"); + } + } + } + } + }catch(e){ + print("\n"+doh._line); + print("The Dojo Unit Test Harness, $Rev$"); + print("Copyright (c) 2007, The Dojo Foundation, All Rights Reserved"); + print(doh._line, "\n"); + + load("_rhinoRunner.js"); + + try{ + var dojoUrl = "../../dojo/dojo.js"; + var testUrl = ""; + var testModule = "dojo.tests.module"; + for(x=0; x + + + at + in + ibid + toegang verkry + opgehaal + van + voorhande + Verwysings + n.d. + en + et al. + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + reël + reëls + + + note + notes + + + opus + opera + + + bladsy + bladsye + + + paragraaf + paragrawe + + + part + parts + + + section + sections + + + volume + volumes + + + verse + verses + + bk + chap + col + fig + f + no + op + + bl + bll + + para + pt + sec + + v + vv + + vol + + + ¶¶ + + + § + §§ + + + redakteur + redakteurs + + + vertaler + vertalers + + + red + reds + + + vert + verts + + onder redaksie van + vertaal deur + red + verts + Januarie + Februarie + Maart + April + Mei + Junie + Julie + Augustus + September + Oktober + November + Desember + Jan + Feb + Mrt + Apr + Mei + Jun + Jul + Aug + Sep + Okt + Nov + Des + + diff --git a/locale/locales-af-ZA.xml b/locale/locales-af-ZA.xml new file mode 100644 index 000000000..fa3f6a1eb --- /dev/null +++ b/locale/locales-af-ZA.xml @@ -0,0 +1,207 @@ + + + + at + in + ibid + toegang verkry + opgehaal + van + voorhande + Verwysings + n.d. + en + et al. + interview + letter + anonymous + anon + and others + in press + online + cited + internet + presented at the + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + reël + reëls + + + note + notes + + + opus + opera + + + bladsy + bladsye + + + paragraaf + paragrawe + + + part + parts + + + section + sections + + + volume + volumes + + + edition + editions + + + verse + verses + + + sub verbo + s.vv + + bk + chap + col + fig + f + no + op + + bl + bll + + para + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + redakteur + redakteurs + + + vertaler + vertalers + + + + + + + red + reds + + + vert + verts + + onder redaksie van + vertaal deur + to + interview by + red + verts + Januarie + Februarie + Maart + April + Mei + Junie + Julie + Augustus + September + Oktober + November + Desember + Jan + Feb + Mrt + Apr + Mei + Jun + Jul + Aug + Sep + Okt + Nov + Des + + diff --git a/locale/locales-ar-AR.xml b/locale/locales-ar-AR.xml new file mode 100644 index 000000000..0fffa264b --- /dev/null +++ b/locale/locales-ar-AR.xml @@ -0,0 +1,207 @@ + + + + عند + في + آيبيد + زير + جلب + من + القادم + مراجع + + و + et al. + مقابلة + رسالة + مجهول + مجهول + وآخرون + تحت الطبع + ربط مباشر + وثِّقَ + الإنترنت + قُدَّم في + علم الإنسان + علم الفلك + علم الأحياء + علم النبات + علم الكيمياء + الهندسة + أساس عام + جغرافيا + علم الأرض + التاريخ + الإنسانيات + الأدب + الرياضيات + الطب + الفلسفة + الفيزياء + علم النفس + علم الإجتماع + العلوم + العلوم السياسية + العلوم الإجتماعية + العلوم الإلهية + علم الحيوان + + كتاب + كُتُب + + + فصل + فصول + + + عمود + أعمدة + + + رسم توضيحي + رسوم توضيحية + + + ورقة + أوراق + + + عدد + أعداد + + + سطر + أسطر + + + ملاحظة + ملاحظات + + + قطعة موسيقية + أوبرا + + + صفحة + صفحات + + + فقرة + فقرات + + + جزء + أجزاء + + + قسم + أقسام + + + مجلد + مجلدات + + + الطبعة + الطبعات + + + بيت + أبيات + + + sub verbo + s.vv + + ك + ف + عم + ر + و + عد + مم + + ص + ص.ص + + فق + جز + ق + + s.v + s.vv + + + ب + بب + + + مج + مجج + + edition + ط + + + ¶¶ + + + § + §§ + + + + + + + تحرير + تحرير + + + ترجمة + ترجمة + + + + + + + مح + محح + + + تر + ترر + + حرره + ترجمه + إلى + مقابلة بواسطة + مح + مت + يناير + فبراير + مارس + ابريل + مايو + يونيو + يوليو + اغسطس + سبتمبر + اكتوبر + نوفمبر + ديسمبر + يناير + فبراير + مارس + ابريل + مايو + يونيو + يوليو + اغسطس + سبتمبر + اكتوبر + نوفمبر + ديسمبر + + diff --git a/locale/locales-bg-BG.xml b/locale/locales-bg-BG.xml new file mode 100644 index 000000000..dfafde826 --- /dev/null +++ b/locale/locales-bg-BG.xml @@ -0,0 +1,207 @@ + + + + в + в + пак там + отворен на + изтеглен на + от + предстоящ + цитати + без дата + и + и съавт. + интервю + писмо + анонимен + анон + и други + под печат + онлайн + цитиран + интернет + представен на + антропология + астрономия + биология + ботаника + химия + инженерство + обща база + география + геология + история + хуманитарни науки + литература + математика + медицина + философия + физика + физиология + социология + наука + политически науки + обществени науки + теология + зоология + + книга + книги + + + глава + глави + + + колона + колони + + + фигура + фигури + + + фолио + фолия + + + брой + броеве + + + ред + редове + + + бележка + бележки + + + опус + опуси + + + страница + страници + + + параграф + параграфи + + + част + части + + + раздел + раздели + + + том + томове + + + издание + издания + + + стих + стихове + + + sub verbo + s.vv + + кн + гл + кол + фиг + фол + бр + оп + + с + с-ци + + п + ч + разд + + s.v + s.vv + + + ст + ст-ове + + + том + т-ове + + edition + изд + + + ¶¶ + + + § + §§ + + + автор + автори + + + редактор + редактори + + + преводач + преводачи + + + авт + авт-ри + + + ред + ред-ри + + + прев + прев-чи + + редактиран от + преведен от + до + интервюиран от + ред + прев + Януари + Февруари + Март + Април + Май + Юни + Юли + Август + Септември + Октомври + Ноември + Декември + Яну + Фев + Мар + Апр + Май + Юни + Юли + Авг + Сеп + Окт + Ное + Дек + + diff --git a/locale/locales-ca-AD.xml b/locale/locales-ca-AD.xml new file mode 100644 index 000000000..5f2a820aa --- /dev/null +++ b/locale/locales-ca-AD.xml @@ -0,0 +1,207 @@ + + + + at + in + ibid + accessed + retrieved + from + forthcoming + References + nd + and + et al. + interview + letter + anonymous + anon + and others + in press + online + cited + internet + presented at the + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + line + line + + + note + notes + + + opus + opera + + + page + pages + + + paragraph + paragraph + + + part + parts + + + section + sections + + + volume + volumes + + + edition + editions + + + verse + verses + + + sub verbo + s.vv + + bk + chap + col + fig + f + no + op + + p + pp + + para + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + editor + editors + + + translator + translators + + + + + + + ed + eds + + + tran + trans + + edited by + translated by + to + interview by + ed + trans + January + February + March + April + May + June + July + August + September + October + November + December + Jan + Feb + Mar + Apr + May + Jun + Jul + Aug + Sep + Oct + Nov + Dec + + diff --git a/locale/locales-cs-CZ.xml b/locale/locales-cs-CZ.xml new file mode 100644 index 000000000..281e6a0da --- /dev/null +++ b/locale/locales-cs-CZ.xml @@ -0,0 +1,207 @@ + + + + v + v + ibid + přístup + získáno + z + nadcházející + reference + bez data + a + et al. + interview + dopis + anonymous + anon + a další + v tisku + online + citován + internet + prezentován v + antropologie + astronomie + biologie + botanika + chemie + technika + všeobecný základ + geografie + geologie + historie + humanitní + literatura + matematika + medicína + filosofie + fyzika + psychologie + sociologie + věda + politologie + sociální věda + teologie + zoologie + + kniha + knihy + + + kapitola + kapitoly + + + sloupec + sloupce + + + obrázek + obrázky + + + list + listy + + + číslo + číslo + + + řádek + řádky + + + poznámka + poznámky + + + opus + opera + + + strana + strany + + + odstavec + odstavce + + + část + části + + + sekce + sekce + + + ročník + ročníky + + + edice + edice + + + verš + verše + + + sub verbo + s.vv + + kn + kap + sl + obr + l + čís + op + + s + s + + odst + č + sek + + s.v + s.vv + + + v + v + + + roč + roč + + edition + ed + + + ¶¶ + + + § + §§ + + + autor + autoři + + + editor + editoři + + + překladatel + překladatelé + + + + + + + ed + ed + + + překl + překl + + editoval + přeložil + pro + rozhovor vedl + ed + překl + leden + únor + březen + duben + květen + červen + červenec + srpen + září + říjen + listopad + prosinec + led + úno + bře + dub + kvě + čer + čvc + srp + zář + říj + lis + pro + + diff --git a/locale/locales-da-DK.xml b/locale/locales-da-DK.xml new file mode 100644 index 000000000..22a11ec04 --- /dev/null +++ b/locale/locales-da-DK.xml @@ -0,0 +1,207 @@ + + + + at + in + ibid + accessed + retrieved + from + forthcoming + References + nd + and + et al. + interview + letter + anonymous + anon + and others + in press + online + cited + internet + presented at the + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + line + line + + + note + notes + + + opus + opera + + + page + pages + + + paragraph + paragraph + + + part + parts + + + section + sections + + + volume + volumes + + + edition + editions + + + verse + verses + + + sub verbo + s.vv + + bk + chap + col + fig + f + no + op + + p + pp + + para + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + editor + editors + + + translator + translators + + + + + + + ed + eds + + + tran + trans + + edited by + translated by + to + interview by + ed + trans + January + February + March + April + May + June + July + August + September + October + November + December + Jan + Feb + Mar + Apr + May + Jun + Jul + Aug + Sep + Oct + Nov + Dec + + diff --git a/locale/locales-de-AT.xml b/locale/locales-de-AT.xml new file mode 100644 index 000000000..74a8e07ca --- /dev/null +++ b/locale/locales-de-AT.xml @@ -0,0 +1,207 @@ + + + + at + in + ebd. + zugegriffen + abgerufen + von + i.E. + Quellenangabe + o.J. + und + u.a. + interview + letter + anonymous + anon + and others + in press + online + cited + internet + presented at the + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + Zeile + Zeilen + + + note + notes + + + opus + opera + + + Seite + Seiten + + + Absatz + Absätze + + + part + parts + + + section + sections + + + volume + volumes + + + edition + editions + + + verse + verses + + + sub verbo + s.vv + + bk + chap + col + fig + f + Nr + op + + S + S + + para + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + Herausgeber + Herausgeber + + + Übersetzer + Übersetzer + + + + + + + Hrsg + Hrsg + + + Übers + Übers + + Hg. v + Übers. v + to + interview by + ed + trans + Jänner + Februar + März + April + Mai + Juni + Juli + August + September + Oktober + November + Dezember + Jän + Feb + Mar + Apr + Mai + Jun + Jul + Aug + Sep + Okt + Nov + Dez + + diff --git a/locale/locales-de-CH.xml b/locale/locales-de-CH.xml new file mode 100644 index 000000000..b80807f90 --- /dev/null +++ b/locale/locales-de-CH.xml @@ -0,0 +1,207 @@ + + + + at + in + ebd. + zugegriffen + abgerufen + von + i.E. + Quellenangabe + o.J. + und + u.a. + interview + letter + anonymous + anon + and others + in press + online + cited + internet + presented at the + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + Zeile + Zeilen + + + note + notes + + + opus + opera + + + Seite + Seiten + + + Absatz + Absätze + + + part + parts + + + section + sections + + + volume + volumes + + + edition + editions + + + verse + verses + + + sub verbo + s.vv + + bk + chap + col + fig + f + Nr + op + + S + S + + para + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + Herausgeber + Herausgeber + + + Übersetzer + Übersetzer + + + + + + + Hrsg + Hrsg + + + Übers + Übers + + Hg. v + Übers. v + to + interview by + ed + trans + Januar + Februar + März + April + Mai + Juni + Juli + August + September + Oktober + November + Dezember + Jan + Feb + Mar + Apr + Mai + Jun + Jul + Aug + Sep + Okt + Nov + Dez + + diff --git a/locale/locales-de-DE.xml b/locale/locales-de-DE.xml new file mode 100644 index 000000000..8933677ee --- /dev/null +++ b/locale/locales-de-DE.xml @@ -0,0 +1,207 @@ + + + + auf + in + ebd + zugegriffen + abgerufen + von + i. E. + Quellenangabe + o. J. + und + u. a. + Interview + Brief + ohne Autor + o. A. + und andere + im Druck + online + zitiert + Internet + gehalten auf der + Anthropologie + Astronomie + Biologie + Botanik + Chemie + Ingenieurswissenschaften + generischer Stil + Geographie + Geologie + Geschichte + Geisteswissenschaften + Literatur + Mathematik + Medizin + Philosophie + Physik + Psychologie + Soziologie + Naturwissenschaften + Politikwissenschaft + Sozialwissenschaften + Theologie + Zoologie + + Buch + Bücher + + + Kapitel + Kapitel + + + Spalte + Spalten + + + Abbildung + Abbildungen + + + Blatt + Blätter + + + Nummer + Nummern + + + Zeile + Zeilen + + + Note + Noten + + + Opus + Opera + + + Seite + Seiten + + + Absatz + Absätze + + + Teil + Teile + + + Abschnitt + Abschnitte + + + Band + Bände + + + Auflage + Auflagen + + + Vers + Verse + + + sub verbo + s.vv + + B + Kap + Sp + Abb + Fol + Nr + op + + S + S + + Abs + Teil + Abschn + + s.v + s.vv + + + V + Vv + + + Bd + Bd + + edition + Aufl + + + ¶¶ + + + § + §§ + + + + + + + Herausgeber + Herausgeber + + + Übersetzer + Übersetzer + + + + + + + Hrsg + Hrsg + + + Übers + Übers + + herausgegeben von + übersetzt von + an + interviewt von + hg. v + übers. v + Januar + Februar + März + April + Mai + Juni + Juli + August + September + Oktober + November + Dezember + Jan + Feb + März + Apr + Mai + Juni + Juli + Aug + Sep + Okt + Nov + Dez + + diff --git a/locale/locales-el-GR.xml b/locale/locales-el-GR.xml new file mode 100644 index 000000000..059d4201e --- /dev/null +++ b/locale/locales-el-GR.xml @@ -0,0 +1,207 @@ + + + + at + in + ibid + accessed + retrieved + from + forthcoming + references + n.d. + and + et al. + interview + letter + anonymous + anon + and others + in press + online + cited + internet + presented at the + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + line + lines + + + note + notes + + + opus + opera + + + page + pages + + + paragraph + paragraph + + + part + parts + + + section + sections + + + volume + volumes + + + edition + editions + + + verse + verses + + + sub verbo + s.vv + + bk + chap + col + fig + f + no + op + + p + pp + + para + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + editor + editors + + + translator + translators + + + + + + + ed + eds + + + tran + trans + + edited by + translated by + to + interview by + ed + trans + January + February + March + April + May + June + July + August + September + October + November + December + Jan + Feb + Mar + Apr + May + Jun + Jul + Aug + Sep + Oct + Nov + Dec + + diff --git a/locale/locales-en-US.xml b/locale/locales-en-US.xml new file mode 100644 index 000000000..962aabaff --- /dev/null +++ b/locale/locales-en-US.xml @@ -0,0 +1,230 @@ + + + + at + in + ibid + accessed + retrieved + from + forthcoming + references + n.d. + and + et al. + interview + letter + anonymous + anon + and others + in press + online + cited + internet + presented at the + filed + slip op. + rev'd + + + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + line + lines + + + note + notes + + + opus + opera + + + page + pages + + + paragraph + paragraph + + + part + parts + + + section + sections + + + volume + volumes + + + edition + editions + + + verse + verses + + + sub verbo + s.vv + + + + bk + chap + col + fig + f + no + op + + p + pp + + para + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + + + ¶¶ + + + § + §§ + + + + + + + + + editor + editors + + + translator + translators + + + + + + + + + ed + eds + + + tran + trans + + + + edited by + translated by + to + interview by + + + ed + trans + + + January + February + March + April + May + June + July + August + September + October + November + December + + + Jan + Feb + Mar + Apr + May + Jun + Jul + Aug + Sep + Oct + Nov + Dec + + diff --git a/locale/locales-es-ES.xml b/locale/locales-es-ES.xml new file mode 100644 index 000000000..b7ecab283 --- /dev/null +++ b/locale/locales-es-ES.xml @@ -0,0 +1,207 @@ + + + + en + en + ibid + accedido + recuperado + a partir de + previsto + Referencias + s.d. + y + et al. + interview + letter + anonymous + anon + and others + in press + online + cited + internet + presented at the + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + libro + libros + + + capítulo + capítulos + + + columna + columnas + + + figura + figuras + + + folio + folios + + + número + números + + + línea + líneas + + + nota + notas + + + opus + opera + + + página + páginas + + + párrafo + párrafos + + + parte + partes + + + sección + secciones + + + volumen + volúmenes + + + edition + editions + + + verso + versos + + + sub verbo + s.vv + + lib + cap + col + fig + f + + op + + pág + págs + + para + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + editor + editores + + + traductor + traductores + + + + + + + ed + eds + + + trad + trads + + editado por + traducido por + to + interview by + ed + trad + Enero + Febrero + Marzo + Abril + Mayo + Junio + Julio + Agosto + Septiembre + Octubre + Noviembre + Diciembre + Ene + Feb + Mar + Abr + May + Jun + Jul + Ago + Sep + Oct + Nov + Dic + + diff --git a/locale/locales-et-EE.xml b/locale/locales-et-EE.xml new file mode 100644 index 000000000..e88516e3d --- /dev/null +++ b/locale/locales-et-EE.xml @@ -0,0 +1,207 @@ + + + + at + in + ibid + accessed + retrieved + from + forthcoming + references + n.d. + and + et al. + interview + letter + anonymous + anon + and others + in press + online + cited + internet + presented at the + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + line + lines + + + note + notes + + + opus + opera + + + page + pages + + + paragraph + paragraph + + + part + parts + + + section + sections + + + volume + volumes + + + edition + editions + + + verse + verses + + + sub verbo + s.vv + + bk + chap + col + fig + f + no + op + + p + pp + + para + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + editor + editors + + + translator + translators + + + + + + + ed + eds + + + tran + trans + + edited by + translated by + to + interview by + ed + trans + January + February + March + April + May + June + July + August + September + October + November + December + Jan + Feb + Mar + Apr + May + Jun + Jul + Aug + Sep + Oct + Nov + Dec + + diff --git a/locale/locales-fr-FR.xml b/locale/locales-fr-FR.xml new file mode 100644 index 000000000..8db30ad2d --- /dev/null +++ b/locale/locales-fr-FR.xml @@ -0,0 +1,207 @@ + + + + à + dans + ibid + accédé + retrouvé + de + à venir + références + pas de date + et + et coll. + interview + lettre + anonyme + anon + et autres + sous presse + en ligne + cité + Internet + présenté au + anthropologie + astronomie + biologie + botanique + chimie + ingénierie + base générique + géographie + géologie + histoire + sciences humaines + littérature + mathématiques + médecine + philosophie + physique + psychologie + sociologie + science + science politique + science sociale + théologie + zoologie + + livre + livres + + + chapitre + chapitres + + + colonne + colonnes + + + figure + figures + + + folio + folios + + + numéro + numéros + + + ligne + lignes + + + note + notes + + + opus + opus + + + page + pages + + + paragraphe + paragraphes + + + partie + parties + + + section + sections + + + volume + volumes + + + edition + editions + + + verset + versets + + + sub verbo + s.vv + + liv + chap + col + fig + f + + op + + p + pp + + par + part + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + éd + + § + §§ + + + § + §§ + + + + + + + éditeur + éditeurs + + + traducteur + traducteurs + + + + + + + éd + éd + + + trad + trad + + édité par + traduit par + vers + interview par + éd + trad + Janvier + Février + Mars + Avril + Mai + Juin + Juillet + Août + Septembre + Octobre + Novembre + Décembre + Jan + Fév + Mar + Avr + Mai + Jun + Jul + Aoû + Sep + Oct + Nov + Déc + + diff --git a/locale/locales-he-IL.xml b/locale/locales-he-IL.xml new file mode 100644 index 000000000..13036a1d5 --- /dev/null +++ b/locale/locales-he-IL.xml @@ -0,0 +1,207 @@ + + + + + בתוך + שם + גישה + אוחזר + מתוך + forthcoming + References + nd + ו + ואחרים + interview + letter + anonymous + anon + and others + in press + online + cited + internet + presented at the + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + ספר + ספרים + + + פרק + פרקים + + + טור + טורים + + + figure + figures + + + folio + folios + + + מספר + מספרים + + + שורה + שורות + + + note + notes + + + אופוס + אופרה + + + עמוד + עמודים + + + paragraph + פיסקה + + + part + parts + + + section + sections + + + כרך + כרכים + + + edition + editions + + + בית + בתים + + + sub verbo + s.vv + + bk + chap + col + fig + f + no + op + + 'עמ + 'עמ + + para + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + עורך + עורכים + + + מתרגם + מתרגמים + + + + + + + ed + eds + + + tran + trans + + נערך ע"י + תורגם ע"י + to + interview by + ed + trans + ינואר + פברואר + מרץ + אפריל + מאי + יוני + יולי + אוגוסט + ספטמבר + אוקטובר + נובמבר + דצמבר + Jan + Feb + Mar + Apr + May + Jun + Jul + Aug + Sep + Oct + Nov + Dec + + diff --git a/locale/locales-hu-HU.xml b/locale/locales-hu-HU.xml new file mode 100644 index 000000000..f8aaa7d50 --- /dev/null +++ b/locale/locales-hu-HU.xml @@ -0,0 +1,207 @@ + + + + + in + ibid + elérés + elérés + forrás + megjelenés alatt + hivatkozások + nd + és + et al. + interjú + levél + név nélkül + nn + és mások + nyomtatás alatt + online + idézi + internet + előadás + antropológia + csillagászat + biológia + botanika + kémia + mérnöki tudományok + általános + földrajz + geológia + történelem + bölcsésztudományok + irodalom + matematika + orvostudomány + filozófia + fizika + pszichológia + szociológia + tudomány + politikatudomány + társadalomtudomány + teológia + zoológia + + könyv + könyv + + + fejezet + fejezet + + + oszlop + oszlop + + + ábra + ábra + + + fóliáns + fóliáns + + + szám + szám + + + sor + sor + + + jegyzet + jegyzet + + + opus + opera + + + oldal + oldal + + + bekezdés + bekezdés + + + rész + rész + + + szakasz + szakasz + + + kötet + kötet + + + edition + editions + + + versszak + versszak + + + sub verbo + s.vv + + könyv + fej + oszl + ábr + fol + sz + op + + o + o + + bek + rész + szak + + s.v + s.vv + + + vsz + vsz + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + szerkesztő + szerkesztő + + + fordító + fordító + + + + + + + szerk + szerk + + + ford + ford + + szerkesztette + fordította + címzett + interjúkészítő + szerk + ford + január + február + március + április + május + június + július + augusztus + szeptember + október + november + december + jan + febr + márc + ápr + máj + jún + júl + aug + szept + okt + nov + dec + + diff --git a/locale/locales-is-IS.xml b/locale/locales-is-IS.xml new file mode 100644 index 000000000..05e92e160 --- /dev/null +++ b/locale/locales-is-IS.xml @@ -0,0 +1,207 @@ + + + + at + in + ibid + accessed + retrieved + from + forthcoming + References + nd + and + et al. + interview + letter + anonymous + anon + and others + in press + online + cited + internet + presented at the + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + line + line + + + note + notes + + + opus + opera + + + page + pages + + + paragraph + paragraph + + + part + parts + + + section + sections + + + volume + volumes + + + edition + editions + + + verse + verses + + + sub verbo + s.vv + + bk + chap + col + fig + f + no + op + + p + pp + + para + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + editor + editors + + + translator + translators + + + + + + + ed + eds + + + tran + trans + + edited by + translated by + to + interview by + ed + trans + January + February + March + April + May + June + July + August + September + October + November + December + Jan + Feb + Mar + Apr + May + Jun + Jul + Aug + Sep + Oct + Nov + Dec + + diff --git a/locale/locales-it-IT.xml b/locale/locales-it-IT.xml new file mode 100644 index 000000000..ec40943f9 --- /dev/null +++ b/locale/locales-it-IT.xml @@ -0,0 +1,207 @@ + + + + a + in + ibid + consultato + recuperato + da + futuro + Citazioni bibliografiche + S.d. + e + et al. + intervista + lettera + anonimo + anon + e altri + in stampa + in linea + citato + internet + presentato al + antropologia + astronomia + biologia + botanica + chimica + ingegneria + generica + geografia + geologia + storia + discipline umanistiche + letteratura + matematica + medicina + filosofia + fisica + psicologia + sociologia + scienze + scienze politiche + sociologia + teologia + zoologia + + libro + libri + + + capitolo + capitoli + + + colonna + colonne + + + figura + figure + + + foglio + fogli + + + numero + numeri + + + riga + righe + + + nota + note + + + opera + opere + + + pagina + pagine + + + capoverso + capoversi + + + parte + parti + + + paragrafo + paragrafi + + + volume + volumi + + + edizione + edizioni + + + verso + versi + + + sub verbo + s.vv + + lib + cap + col + fig + fgl + + op + + pag + pagg + + cpv + pt + par + + s.v + s.vv + + + v + vv + + + vol + vol + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + curatore + curatori + + + traduttore + traduttori + + + + + + + cur + cur + + + trad + trad + + a cura di + tradotto da + a + intervista di + cur. da + trad. da + Gennaio + Febbraio + Marzo + Aprile + Maggio + Giugno + Luglio + Agosto + Settembre + Ottobre + Novembre + Dicembre + Gen + Feb + Mar + Apr + Mag + Giu + Lug + Ago + Set + Ott + Nov + Dic + + diff --git a/locale/locales-ja-JP.xml b/locale/locales-ja-JP.xml new file mode 100644 index 000000000..c1feacbfe --- /dev/null +++ b/locale/locales-ja-JP.xml @@ -0,0 +1,207 @@ + + + + at + + 前掲 + アクセス + 読み込み + から + 近刊 + 参考文献 + 日付なし + + + interview + letter + anonymous + anon + and others + in press + online + cited + internet + presented at the + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + + + + + note + notes + + + opus + opera + + + ページ + ページ + + + 段落 + 段落 + + + part + parts + + + section + sections + + + volume + volumes + + + edition + editions + + + verse + verses + + + sub verbo + s.vv + + bk + chap + col + fig + f + + op + + p + p + + para + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + 編集者 + 編集者 + + + 翻訳者 + 翻訳者 + + + + + + + 編集者 + 編集者 + + + 翻訳者 + 翻訳者 + + 編集者: + 翻訳者: + to + interview by + ed + trans + 1月 + 2月 + 3月 + 4月 + 5月 + 6月 + 7月 + 8月 + 9月 + 10月 + 11月 + 12月 + 1月 + 2月 + 3月 + 4月 + 5月 + 6月 + 7月 + 8月 + 9月 + 10月 + 11月 + 12月 + + diff --git a/locale/locales-ko-KR.xml b/locale/locales-ko-KR.xml new file mode 100644 index 000000000..9254be404 --- /dev/null +++ b/locale/locales-ko-KR.xml @@ -0,0 +1,207 @@ + + + + at + in + ibid + 접근된 + retrieved + (으)로부터 + 근간 + 참고 문헌 + 일자 없음 + 와/과 + 기타 + interview + letter + anonymous + anon + and others + in press + online + cited + internet + presented at the + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + + + + + note + notes + + + opus + opera + + + 페이지 + 페이지 + + + 단락 + 단락 + + + part + parts + + + section + sections + + + volume + volumes + + + edition + editions + + + verse + verses + + + sub verbo + s.vv + + bk + chap + col + fig + f + + op + + p + pp + + para + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + 편집자 + 편집자 + + + 번역자 + 번역자 + + + + + + + 편집자 + 편집자 + + + 번역자 + 번역자 + + 편집자: + 번역자: + to + interview by + ed + trans + 1월 + 2월 + 3월 + 4월 + 5월 + 6월 + 7월 + 8월 + 9월 + 10월 + 11월 + 12월 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + + diff --git a/locale/locales-mn-MN.xml b/locale/locales-mn-MN.xml new file mode 100644 index 000000000..dd3c5edb0 --- /dev/null +++ b/locale/locales-mn-MN.xml @@ -0,0 +1,207 @@ + + + + at + in + ibid + accessed + retrieved + from + forthcoming + references + n.d. + and + et al. + interview + letter + anonymous + anon + and others + in press + online + cited + internet + presented at the + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + line + lines + + + note + notes + + + opus + opera + + + page + pages + + + paragraph + paragraph + + + part + parts + + + section + sections + + + volume + volumes + + + edition + editions + + + verse + verses + + + sub verbo + s.vv + + bk + chap + col + fig + f + no + op + + p + pp + + para + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + editor + editors + + + translator + translators + + + + + + + ed + eds + + + tran + trans + + edited by + translated by + to + interview by + ed + trans + January + February + March + April + May + June + July + August + September + October + November + December + Jan + Feb + Mar + Apr + May + Jun + Jul + Aug + Sep + Oct + Nov + Dec + + diff --git a/locale/locales-nb-NO.xml b/locale/locales-nb-NO.xml new file mode 100644 index 000000000..f99007393 --- /dev/null +++ b/locale/locales-nb-NO.xml @@ -0,0 +1,207 @@ + + + + + i + ibid + aksessert + hentet + fra + kommende + referanser + udatert + og + mfl + intervju + brev + anonym + anon + med flere + i trykk + online + cited + Internett + presentert på + antropologi + astronomi + biologi + botanikk + kjemi + ingeniørvitenskap + generic base + geografi + geologi + historie + humanistiske fag + litteratur + matte + medisin + filosofi + fysikk + fysiologi + sosiologi + naturvitenskap + political science + sosialvitenskap + teologi + zoologi + + bok + bøker + + + kapittel + kapitler + + + kolonne + kolenner + + + figur + figurer + + + folio + folioer + + + nummer + numre + + + linje + linjer + + + note + noter + + + opus + opus + + + side + sider + + + avsnitt + avsnitt + + + del + deler + + + seksjon + seksjoner + + + bind + bind + + + utgave + utgaver + + + vers + vers + + + sub verbo + s.vv + + b + kap + kol + fig + fol + nr + op + + s + s + + avsn + d + sek + + s.v + s.vv + + + v + v + + + bd + bd + + edition + utg + + + ¶¶ + + + § + §§ + + + + + + + redaktør + redaktører + + + oversetter + oversettere + + + + + + + red + red + + + overs + overs + + redigert av + oversatt av + mottatt av + intervjuet av + utg + overs + Januar + Februar + Mars + April + Mai + Juni + Juli + August + September + Oktober + November + Desember + Jan + Feb + Mar + Apr + Mai + Jun + Jul + Aug + Sep + Okt + Nov + Des + + diff --git a/locale/locales-nl-NL.xml b/locale/locales-nl-NL.xml new file mode 100644 index 000000000..43b2d931b --- /dev/null +++ b/locale/locales-nl-NL.xml @@ -0,0 +1,207 @@ + + + + bij + in + ibid + bezocht + verkregen + van + in voorbereiding + referenties + geen datum + en + e.a. + interview + brief + anoniem + anon + en anderen + in druk + online + geciteerd + internet + gepresenteerd bij + anthropologie + astronomie + biologie + botanie + scheikunde + techniek + generiek + geografie + geologie + geschiedenis + geesteswetenschappen + literatuur + wiskunde + medicijnen + filosofie + natuurkunde + psychologie + sociologie + wetenschap + politieke wetenschappen + sociale wetenschappen + theologie + zoologie + + boek + boeken + + + hoofdstuk + hoofdstukken + + + column + columns + + + figuur + figuren + + + folio + folio's + + + nummer + nummers + + + regel + regels + + + aantekening + aantekeningen + + + opus + opera + + + pagina + pagina's + + + paragraaf + paragrafen + + + deel + delen + + + sectie + secties + + + volume + volumes + + + editie + edities + + + vers + versen + + + sub verbo + s.vv + + bk + hfdst + col + fig + f + nr + op + + p + pp + + par + deel + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + redacteur + redacteuren + + + vertaler + vertalers + + + + + + + red + red + + + vert + vert + + bewerkt door + vertaald door + ontvangen door + geinterviewd door + red + vert + januari + februari + maart + april + mei + juni + juli + augustus + september + oktober + november + december + jan + feb + mrt + apr + mei + jun + jul + aug + sep + okt + nov + dec + + diff --git a/locale/locales-pl-PL.xml b/locale/locales-pl-PL.xml new file mode 100644 index 000000000..89dc3956e --- /dev/null +++ b/locale/locales-pl-PL.xml @@ -0,0 +1,207 @@ + + + + at + w + ibid + udostępniono + pobrano + z + w druku + Referencje + bez daty + i + et al. + wywiad + list + anonim + anonim + i inni + w druku + online + cytowane + internet + zaprezentowano + antropologia + astronomia + biologia + botanika + chemia + inżynieria + generic base + geografia + geologia + historia + humanistyka + literatura + matematyka + medycyna + filozofia + fizyka + psychologia + socjologia + nauki ścisłe + nauki polityczne + nauki społeczne + teologia + zoologia + + książka + książki + + + rozdział + rozdziały + + + kolumna + kolumny + + + rycina + ryciny + + + folio + folios + + + numer + numery + + + wers + wersy + + + notatka + notatki + + + opus + opera + + + strona + strony + + + akapit + akapity + + + część + części + + + sekcja + sekcja + + + tom + tomy + + + wydanie + wydania + + + wers + wersy + + + sub verbo + s.vv + + książka + rozdz + kolumna + ryc + folio + nr + op + + s + s + + akapit + część + sekcja + + s.v + s.vv + + + wers + wersy + + + t + t + + edition + wyd + + + ¶¶ + + + § + §§ + + + + + + + redaktor + redaktorzy + + + tłumacz + tłumacze + + + + + + + red + red + + + tłum + tłum + + zredagowane przez + przetłumaczone przez + dla + przeprowadzony przez + red + tłum + styczeń + luty + marzec + kwiecień + maj + czerwiec + lipiec + sierpień + wrzesień + październik + listopad + grudzień + styczeń + luty + marzec + kwiecień + maj + czerwiec + lipiec + sierpień + wrzesień + październik + listopad + grudzień + + diff --git a/locale/locales-pt-BR.xml b/locale/locales-pt-BR.xml new file mode 100644 index 000000000..07ae87b82 --- /dev/null +++ b/locale/locales-pt-BR.xml @@ -0,0 +1,207 @@ + + + + em + in + ibidem + acessado + recuperado + de + a ser publicado + referências + [s.d.] + e + et al. + entrevista + carta + anônimo + anon + e outros + no prelo + online + citado + internet + apresentado em + antropologia + astronomia + biologia + botânica + química + engenharia + base genérica + geografia + geologia + história + humanidades + literatura + matemática + medicina + philosofia + física + psicologia + sociologia + ciências + ciências políticas + ciências sociais + teologia + zoologia + + livro + livros + + + capítulo + capítulos + + + coluna + colunas + + + figura + figuras + + + folio + folios + + + número + números + + + linha + linhas + + + nota + notas + + + opus + opera + + + página + páginas + + + parágrafo + parágrafos + + + parte + partes + + + seção + seções + + + volume + volumes + + + edição + edições + + + verso + versos + + + sub verbo + s.vv + + liv + cap + col + fig + f + n + op + + p + pp + + para + pt + seç + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + organizador + organizadores + + + tradutor + tradutores + + + + + + + org + orgs + + + trad + trads + + organizado por + traduzido por + para + intrevista de + org + trad + janeiro + fevereiro + março + abril + maio + junho + julho + agosto + setembro + outubro + novembro + dezembro + jan + fev + mar + abr + maio + jun + jul + ago + set + out + nov + dez + + diff --git a/locale/locales-pt-PT.xml b/locale/locales-pt-PT.xml new file mode 100644 index 000000000..1f23e7f36 --- /dev/null +++ b/locale/locales-pt-PT.xml @@ -0,0 +1,207 @@ + + + + em + em + ibid + acedido + obtido + de + a publicar + Referências + sem data + e + et al. + entrevista + carta + anónimo + anón + e outros + no prelo + em linha + citado + internet + apresentado na + antropologia + astronomia + biologia + botânica + química + engenharia + base genérica + geografia + geologia + história + humanidades + literatura + matemática + medicina + filosofia + física + psicologia + sociologia + ciência + ciência política + ciência social + teologia + zoologia + + livro + livros + + + capítulo + capítulos + + + coluna + colunas + + + figura + figuras + + + fólio + fólios + + + número + número + + + linha + linhas + + + nota + notas + + + opus + opera + + + página + páginas + + + parágrafo + parágrafos + + + parte + partes + + + secção + secções + + + volume + volumes + + + edição + edições + + + versículo + versículos + + + sub verbo + s.vv + + liv + cap + col + fig + f + n + op + + p + pp + + par + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + editor + editores + + + tradutor + tradutores + + + + + + + ed + eds + + + trad + trads + + editado por + traduzido por + para + entrevistado por + ed + trad + Janeiro + Fevereiro + Março + Abril + Maio + Junho + Julho + Agosto + Setembro + Outubro + Novembro + Dezembro + Jan + Fev + Mar + Abr + Mai + Jun + Jul + Ago + Set + Out + Nov + Dez + + diff --git a/locale/locales-ro-RO.xml b/locale/locales-ro-RO.xml new file mode 100644 index 000000000..0e6bd271b --- /dev/null +++ b/locale/locales-ro-RO.xml @@ -0,0 +1,207 @@ + + + + la + în + ibidem + accesat în + preluat în + din + în curs de apariţie + Bibliografie + f.a. + şi + et al. + interviu + scrisoare + anonim + anon + şi alţii + sub tipar + online + citat + internet + prezentat la + antropologie + astronomie + biologie + botanică + chimie + inginerie + general (de bază) + geografie + geologie + istorie + umanioare + literatură + matematică + medicină + filosofie + fizică + psihologie + sociologie + ştiinţă + ştiinţe politice + ştiinţe sociale + teologie + zoologie + + cartea + cărţile + + + capitolul + capitolele + + + coloana + coloanele + + + figura + figurile + + + folio + folio + + + numărul + numerele + + + linia + liniile + + + nota + notele + + + opusul + opusurile + + + pagina + paginile + + + paragraful + paragrafele + + + partea + părţile + + + secţiunea + secţiunile + + + volumul + volumele + + + ediţia + ediţiile + + + versetul + versetele + + + sub verbo + s.vv + + cart + cap + col + fig + fol + nr + op + + p + pp + + par + part + sec + + s.v + s.vv + + + v + vv + + + vol + vol + + edition + ed + + + ¶¶ + + + § + §§ + + + autor + autori + + + editor + editori + + + traducător + traducători + + + aut + aut + + + ed + ed + + + trad + trad + + ediţie de + traducere de + în + interviu de + ed + trad + ianuarie + februarie + martie + aprilie + mai + iunie + iulie + august + septembrie + octombrie + noiembrie + decembrie + ian + feb + mar + apr + mai + iun + iul + aug + sep + oct + nov + dec + + diff --git a/locale/locales-ru-RU.xml b/locale/locales-ru-RU.xml new file mode 100644 index 000000000..0111b04b4 --- /dev/null +++ b/locale/locales-ru-RU.xml @@ -0,0 +1,207 @@ + + + + at + в + так же + вызвано + извлечено + от + грядущие + Ссылки + нет даты + и + и др. + interview + letter + anonymous + anon + and others + in press + online + cited + internet + presented at the + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + линия + линии + + + note + notes + + + opus + opera + + + страницы + страницы + + + параграф + параграфы + + + part + parts + + + section + sections + + + volume + volumes + + + edition + editions + + + verse + verses + + + sub verbo + s.vv + + bk + chap + col + fig + f + ном + op + + стр-а + стр-ы + + para + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + редактор + редакторы + + + переводчик + переводчики + + + + + + + ред-р + ред-ры + + + перев-к + перев-и + + отредактировано + переведено + to + interview by + ред + перев + Январь + Февраль + Март + Апрель + Май + Июнь + Июль + Август + Сентябрь + Октябрь + Ноябрь + Декабрь + Янв + Фев + Мар + Апр + Май + Июн + Июл + Авг + Сен + Окт + Ноя + Дек + + diff --git a/locale/locales-sk-SK.xml b/locale/locales-sk-SK.xml new file mode 100644 index 000000000..b293eb34f --- /dev/null +++ b/locale/locales-sk-SK.xml @@ -0,0 +1,207 @@ + + + + v + v + ibid + cit + cit + z + nadchádzajúci + referencie + n.d. + a + et al + osobná komunikácia + list + anonym + anon + and ďalší + v tlači + online + cit + internet + prezentované na + antropológia + astronómia + biológia + botanika + chémia + strojárstvo/technika + všeobecný základ + geografia + geológia + história + humanitné vedy + literatúra + matematika + medicína + filozofia + fyzika + psychológia + sociológia + veda + politické vedy + sociálne vedy + teológia + zoológia + + kniha + knihy + + + kapitola + kapitoly + + + stĺpec + stĺpce + + + obrázok + obrázky + + + list + listy + + + číslo + čísla + + + riadok + riadky + + + poznámka + poznámky + + + opus + opera + + + strana + strany + + + odstavec + odstavce + + + časť + časti + + + sekcia + sekcie + + + ročník + ročníky + + + vydanie + vydania + + + verš + verše + + + sub verbo + s.vv + + k + kap + stĺp + obr + l + č + op + + s + s + + par + č + sek + + s.v + s.vv + + + v + v + + + roč + roč + + edition + vyd + + + + + + § + § + + + + + + + editor + editori + + + prekladateľ + prekladatelia + + + + + + + ed + ed + + + prek + prek + + editoval + preložil + adresát + rozhovor urobil + ed + prel + január + február + marec + apríl + máj + jún + júl + august + september + október + november + december + jan + feb + mar + apr + máj + jún + júl + aug + sep + okt + nov + dec + + diff --git a/locale/locales-sl-SI.xml b/locale/locales-sl-SI.xml new file mode 100644 index 000000000..e66b68a82 --- /dev/null +++ b/locale/locales-sl-SI.xml @@ -0,0 +1,207 @@ + + + + pri + v + isto + dostopano + pridobljeno + od + pred izidom + sklici + b.d. + in + idr. + intervju + pismo + anonimni + anon + in drugi + v tisku + na spletu + citirano + internet + predstavljeno na + antropologija + astronomija + biologija + botanika + kemija + strojništvo + splošno + geografija + geologija + zgodovina + humanistika + literatura + matematika + medicina + filozofija + fizika + psihologija + sociologija + znanost + politologija + družbene vede + teologija + zoologija + + knjiga + knjige + + + poglavje + poglavja + + + stolpec + stolpci + + + slika + slike + + + folio + folii + + + številka + številke + + + vrstica + vrstice + + + opomba + opombe + + + opus + opera + + + stran + strani + + + odstavek + odstavki + + + del + deli + + + odsek + odseki + + + letnik + letniki + + + izdaja + izdaje + + + verz + verzi + + + sub verbo + s.vv + + knj + pogl + sto + sl + f + št + op + + str + str + + odst + del + odsk + + s.v + s.vv + + + v + v + + + let + let + + edition + iz + + + ¶¶ + + + § + §§ + + + + + + + urednik + uredniki + + + prevajalec + prevajalci + + + + + + + ur + ur + + + prev + prev + + uredil + prevedel + za + intervjuval + ur + prev + januar + februar + marec + april + maj + junij + julij + avgust + september + oktober + november + december + jan + feb + mar + apr + maj + jun + jul + avg + sep + okt + nov + dec + + diff --git a/locale/locales-sr-RS.xml b/locale/locales-sr-RS.xml new file mode 100644 index 000000000..38007dd21 --- /dev/null +++ b/locale/locales-sr-RS.xml @@ -0,0 +1,207 @@ + + + + на + у + ibid + приступљено + преузето + од + долазећи + референце + без датума + и + и остали + интервју + писмо + анонимна + анон. + и остали + у штампи + на Интернету + цитирано + Интернет + представљено на + антропологија + астрономија + биологија + ботаника + хемија + инжињерство + уопштена основа + географија + геологија + историја + култура и уметност + литература + математика + медицина + филозофија + физика + психологија + социологија + наука + политичка наука + друштвена наука + теологија + зоологија + + књига + књиге + + + поглавље + поглавља + + + колона + колоне + + + цртеж + цртежи + + + фолио + фолији + + + број + бројеви + + + линија + линије + + + белешка + белешке + + + опус + опера + + + страница + странице + + + параграф + параграфи + + + део + делова + + + одељак + одељака + + + том + томова + + + издање + издања + + + строфа + строфе + + + sub verbo + s.vv + + књига + Пог. + кол. + црт. + фолио + изд. + оп. + + стр. + стр. + + пар. + део + од. + + s.v + s.vv + + + стр. + стр. + + + том + томови + + edition + изд. + + + ¶¶ + + + § + §§ + + + + + + + уредник + урединици + + + преводилац + преводиоци + + + + + + + ур. + ур. + + + прев. + прев. + + уредио + превео + прима + интервјуисао + ур. + прев. + Јануар + Фебруар + Март + Април + Мај + Јуни + Јули + Август + Септембар + Октобар + Новембар + Децембар + Јан. + Феб. + Март + Апр. + Мај + Јуни + Јули + Авг. + Сеп. + Окт. + Нов. + Дец. + + diff --git a/locale/locales-sv-SE.xml b/locale/locales-sv-SE.xml new file mode 100644 index 000000000..ab75b4a0b --- /dev/null +++ b/locale/locales-sv-SE.xml @@ -0,0 +1,207 @@ + + + + vid + i + ibid + åtkomstdatum + hämtad + från + kommande + Referenser + nd + och + m.fl. + intervju + brev + anonym + anon + och andra + i tryck + online + citerad + internet + presenterad vid + antropologi + astronomi + biologi + botanik + kemi + teknik + generic base + geografi + geologi + historia + humaniora + litteraturvetenskap + matematik + medicin + filosofi + fysik + psykologi + sociologi + vetenskap + statsvetenskap + samhällsvetenskap + teologi + zoologi + + bok + böcker + + + kapitel + kapitel + + + kolumn + kolumner + + + figur + figurer + + + folio + folios + + + nummer + nummer + + + rad + rader + + + not + noter + + + opus + opera + + + sida + sidor + + + stycke + stycken + + + dek + delar + + + avnitt + avsnitt + + + volym + volumer + + + upplaga + upplagor + + + vers + verser + + + sub verbo + s.vv + + bok + kap + kol + fig + f + num + op + + s + ss + + st + del + avs + + s.v + s.vv + + + vers + verser + + + vol + vols + + edition + uppl + + + ¶¶ + + + § + §§ + + + + + + + redaktör + redaktörer + + + översättare + översättare + + + + + + + red + reds + + + övers + övers + + redigerad av + översatt av + till + intervju av + red + övers + Januari + Februari + Mars + April + Maj + Juni + Juli + Augusti + September + Oktober + November + December + Jan + Feb + Mar + Apr + Maj + Jun + Jul + Aug + Sep + Okt + Nov + Dec + + diff --git a/locale/locales-th-TH.xml b/locale/locales-th-TH.xml new file mode 100644 index 000000000..d2ac94562 --- /dev/null +++ b/locale/locales-th-TH.xml @@ -0,0 +1,207 @@ + + + + at + in + ibid + accessed + retrieved + from + forthcoming + references + n.d. + and + et al. + interview + letter + anonymous + anon + and others + in press + online + cited + internet + presented at the + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + line + lines + + + note + notes + + + opus + opera + + + page + pages + + + paragraph + paragraph + + + part + parts + + + section + sections + + + volume + volumes + + + edition + editions + + + verse + verses + + + sub verbo + s.vv + + bk + chap + col + fig + f + no + op + + p + pp + + para + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + editor + editors + + + translator + translators + + + + + + + ed + eds + + + tran + trans + + edited by + translated by + to + interview by + ed + trans + January + February + March + April + May + June + July + August + September + October + November + December + Jan + Feb + Mar + Apr + May + Jun + Jul + Aug + Sep + Oct + Nov + Dec + + diff --git a/locale/locales-tr-TR.xml b/locale/locales-tr-TR.xml new file mode 100644 index 000000000..6b3ccdc60 --- /dev/null +++ b/locale/locales-tr-TR.xml @@ -0,0 +1,207 @@ + + + + de + içinde + ibid + erişildi + erişildi + den + gelecek + referans + tarih yok + ve + ve diğ. + interview + letter + isimsiz + isimsiz + ve diğ. + basımda + çevrimiçi + kaynak + internet + sunulan + antropoloji + astronomi + biyoloji + botanik + kimya + mühendislik + generic-base + coğrafya + jeoloji + tarih + humanities + edebiyat + matematik + tıp + felsefe + fizik + pisikoloji + sosyoloji + bilim + siyaset bilimi + sosyal bilimler + din bilimi + hayvanbilimi + + kitap + kitaplar + + + bölüm + bölümler + + + sütun + sütunlar + + + şekil + şekiller + + + folyo + folyo + + + sayı + sayılar + + + satır + satırlar + + + not + notlar + + + opus + opera + + + sayfa + sayfalar + + + paragraf + paragraflar + + + kısım + kısımlar + + + bölüm + bölümler + + + cilt + ciltler + + + edition + editions + + + dize + dizeler + + + sub verbo + s.vv + + kit + böl + süt + şek + f + sayı + op + + s + ss + + para + kıs + böl + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + editör + editörler + + + çevirmen + çevirmenler + + + + + + + ed + ed + + + çev + çev + + editör + çeviren + to + Röportaj yapan + ed + çev + Ocak + Şubat + Mart + Nisan + Mayıs + Haziran + Temmuz + Ağustos + Eylül + Ekim + Kasım + Aralık + Oca + Şub + Mar + Nis + May + Haz + Tem + Ağu + Eyl + Eki + Kas + Ara + + diff --git a/locale/locales-uk-UA.xml b/locale/locales-uk-UA.xml new file mode 100644 index 000000000..3e1840757 --- /dev/null +++ b/locale/locales-uk-UA.xml @@ -0,0 +1,207 @@ + + + + на + в + ibid + accessed + retrieved + із + forthcoming + посилання + n.d. + і + et al. + інтервю + лист + анонімний + анон. + та інші + у пресі + online + cited + інтернет + presented at the + антропологія + астрономія + біологія + ботаніка + хімія + інженерія + generic base + географія + геологія + історія + гуманітарні + література + математика + медицина + філософія + фізика + психологія + соціологія + наука + політичні науки + соціальні науки + теологія + зоологія + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + line + lines + + + note + notes + + + opus + opera + + + page + pages + + + paragraph + paragraph + + + part + parts + + + section + sections + + + volume + volumes + + + edition + editions + + + verse + verses + + + sub verbo + s.vv + + bk + chap + col + fig + f + no + op + + p + pp + + para + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + editor + editors + + + translator + translators + + + + + + + ed + eds + + + tran + trans + + edited by + translated by + to + interview by + ed + trans + Січень + Лютий + Березень + Квітень + Травень + Червень + Липень + Серпень + Вересень + Жовтень + Листопад + Грудень + Січ + Лют + Бер + Квіт + Трав + Чер + Лип + Сер + Вер + Жов + Лис + Груд + + diff --git a/locale/locales-vi-VN.xml b/locale/locales-vi-VN.xml new file mode 100644 index 000000000..bf34518c8 --- /dev/null +++ b/locale/locales-vi-VN.xml @@ -0,0 +1,207 @@ + + + + at + trong + n.t. + truy cập + truy vấn + từ + sắp tới + tham khảo + không ngày + + và c.s. + interview + letter + anonymous + anon + and others + in press + online + cited + internet + presented at the + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + dòng + dòng + + + note + notes + + + opus + opera + + + trang + trang + + + đoạn văn + đoạn văn + + + part + parts + + + section + sections + + + volume + volumes + + + edition + editions + + + verse + verses + + + sub verbo + s.vv + + bk + chap + col + fig + f + số p.h + op + + tr + tr + + para + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + biên tập viên + biên tập viên + + + biên dịch viên + biên dịch viên + + + + + + + b.t.v + b.t.v + + + b.d.v + b.d.v + + biên tập bởi + biên dịch bởi + to + interview by + b.t + b.d + Tháng Giêng + Tháng Hai + Tháng Ba + Tháng Tư + Tháng Năm + Tháng Sáu + Tháng Bảy + Tháng Tám + Tháng Chín + Tháng Mười + Tháng Mười-Một + Tháng Chạp + tháng 1 + tháng 2 + tháng 3 + tháng 4 + tháng 5 + tháng 6 + tháng 7 + tháng 8 + tháng 9 + tháng 10 + tháng 11 + tháng 12 + + diff --git a/locale/locales-zh-CN.xml b/locale/locales-zh-CN.xml new file mode 100644 index 000000000..0567635cf --- /dev/null +++ b/locale/locales-zh-CN.xml @@ -0,0 +1,207 @@ + + + + at + in + ibid + accessed + retrieved + from + forthcoming + References + nd + and + et al. + interview + letter + anonymous + anon + and others + in press + online + cited + internet + presented at the + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + line + line + + + note + notes + + + opus + opera + + + page + pages + + + paragraph + paragraph + + + part + parts + + + section + sections + + + volume + volumes + + + edition + editions + + + verse + verses + + + sub verbo + s.vv + + bk + chap + col + fig + f + no + op + + p + pp + + para + pt + sec + + s.v + s.vv + + + v + vv + + + vol + vols + + edition + ed + + + ¶¶ + + + § + §§ + + + + + + + editor + editors + + + translator + translators + + + + + + + ed + eds + + + tran + trans + + edited by + translated by + to + interview by + ed + trans + January + February + March + April + May + June + July + August + September + October + November + December + Jan + Feb + Mar + Apr + May + Jun + Jul + Aug + Sep + Oct + Nov + Dec + + diff --git a/locale/locales-zh-TW.xml b/locale/locales-zh-TW.xml new file mode 100644 index 000000000..ae167868a --- /dev/null +++ b/locale/locales-zh-TW.xml @@ -0,0 +1,207 @@ + + + + + + 同上出處 + 被取用 + 被取回 + + 將來的 + 參考資料 + 無日期 + + 等人 + 訪問 + 信件 + 不具名的 + 無名 + 及其他 + 印行中 + 在線上 + 被引用 + 網際網路 + 簡報於 + 人類學 + 天文學 + 生物學 + 植物學 + 化學 + 工程學 + 一般基礎 + 地理學 + 地質學 + 歷史學 + 人文學科 + 文學 + 數學 + 醫學 + 哲學 + 物理學 + 心理學 + 社會學 + 自然科學 + 政治科學 + 社會科學 + 神學 + 動物學 + + + + + + + + + + + + + + + + + + 對開紙 + 對開紙 + + + 期數 + 期數 + + + + + + + 筆記 + 筆記 + + + 作品 + 作品 + + + + + + + 段落 + 段落 + + + + + + + + + + + + + + + 版本 + 版本 + + + 詩句 + 詩句 + + + sub verbo + s.vv + + + + + + + + + + + + + + + + + s.v + s.vv + + + + + + + + + + edition + + + + ¶¶ + + + § + §§ + + + 作者 + 作者 + + + 編輯 + 編輯 + + + 翻譯 + 翻譯 + + + + + + + + + + + + + + 編者是 + 譯者是 + 授與 + 訪問者是 + + + 一月 + 二月 + 三月 + 四月 + 五月 + 六月 + 七月 + 八月 + 九月 + 十月 + 十一月 + 十二月 + 1月 + 2月 + 3月 + 4月 + 5月 + 6月 + 7月 + 8月 + 9月 + 10月 + 11月 + 12月 + + diff --git a/names_nesting.txt b/names_nesting.txt new file mode 100644 index 000000000..004560fd8 --- /dev/null +++ b/names_nesting.txt @@ -0,0 +1,40 @@ +Namesets (decor from names, provides delimiters between "author" and "editor", say) + TermAndNameset (no decor, no delimiter) + Term (if label before name) + /Term + EtAlAndNameset (no decor, delimiter of space if no et-al formatting element) + Nameset (decor from name, optionally uses AND term as delimiter) + MainSeries + FirstAndArticular (no decor at all, delimiter controlled by articular option) + Name (decor follows charset) + Namepart (decor from namepart+name= ) + /Namepart + /Name + Articular + /Articular + /FirstAndArticular + MiddlesAndArticular (no decor at all, delimiter controlled by articular option) + Name (decor follows charset) + Namepart (decor from namepart+name= ) + /Namepart + /Name + Articular + /Articular + /MiddlesAndArticular + /MainSeries + LastAndArticular + Name (decor follows charset) + Namepart (decor from namepart+name= ) + /Namepart + /Name + Articular + /Articular + /LastAndArticular + /Nameset + EtAl + /EtAl + /EtAlAndNameset + Term (if label after name) + /Term + /TermAndNameset +/Namesets diff --git a/ref/FLIP-FLOP.txt b/ref/FLIP-FLOP.txt new file mode 100644 index 000000000..d0dcf653a --- /dev/null +++ b/ref/FLIP-FLOP.txt @@ -0,0 +1,7 @@ + s = 'one*two \\*three\\*four five* six' + one*two \*three\*four five* six + js> ss = s.split(/*/); var ret = []; var buf = []; for each (str in +ss) { if (str[(str.length-1)] == '\\'){ buf.push(str); } else { +buf.push(""); var addstr = buf.join("*")+ str; buf = []; +ret.push(addstr); } }; print(ret); + diff --git a/ref/cite2.js b/ref/cite2.js new file mode 100644 index 000000000..ee8043edd --- /dev/null +++ b/ref/cite2.js @@ -0,0 +1,234 @@ +Zotero.CSL_old = Zotero.CSL; + +Zotero.CSL = function(csl) { + // "with ({});" needed to fix default namespace scope issue + // See https://bugzilla.mozilla.org/show_bug.cgi?id=330572 + default xml namespace = "http://purl.org/net/xbiblio/csl"; with ({}); + + this._csl = new XML(Zotero.CSL.Global.cleanXML(csl)); + + // load class and styleID + this.styleID = this._csl.info.id.toString(); + this['class'] = this._csl["@class"].toString(); + Zotero.debug("CSL: style class is "+this['class']); + + this.hasBibliography = (this._csl.bibliography.length() ? 1 : 0); + this._formatter = Zotero.CSL.Compiler.compile(this._csl); + + for (var macro in csl.macro) { + //Zotero.CSL.Compiler.macro(macro); + } + //Zotero.CSL.Compiler.bibliography(csl.bibliography); + //Zotero.CSL.Compiler.bibliography(csl.citation); +}; + +Zotero.CSL.Global = Zotero.CSL_old.Global; + +Zotero.CSL.Text = function (children,options) { + this._children = children; + if (options == null) { + this._options = new Zotero.CSL.TextOptions(); + } + this._options = options; +}; + +Zotero.CSL.Text.prototype.toHTML = function () { + return this.toString(); +}; + +Zotero.CSL.Text.prototype.toRTF = function () { + return this.toString(); +}; + +Zotero.CSL.Text.prototype.toString = function () { + return this._options.prefix + this._children.join(this._options.delimeter) + this._options.suffix; +}; + +Zotero.CSL.TextOptions = function (csl) { + if (csl == null) { + csl = {}; + } + + this._defaults = { + '@font-family': 'serif', + '@font-style': 'normal', + '@font-variant': 'normal', + '@font-weight': 'normal', + '@text-decoration': 'none', + '@text-case': '', + '@vertical-align': 'baseline', + '@display': '', + '@quotes': '', + '@prefix': '', + '@suffix': '', + '@delimeter': '' + }; + + this._orDefault = function (csl, attr) { + if (csl[attr] != undefined) { + return csl[attr]; + } else { + return this._defaults[attr]; + } + }; + + this.fontFamily = this._orDefault(csl, '@font-family'); + this.fontStyle = this._orDefault(csl, '@font-style'); + this.fontVariant = this._orDefault(csl, '@font-variant'); + this.fontWeight = this._orDefault(csl, '@font-weight'); + this.textDecoration = this._orDefault(csl, '@text-decoration'); + this.textCase = this._orDefault(csl, '@text-case'); + this.verticalAlign = this._orDefault(csl, '@vertical-align'); + this.display = this._orDefault(csl, '@display'); + this.quotes = this._orDefault(csl, '@quotes'); + this.prefix = this._orDefault(csl, '@prefix'); + this.suffix = this._orDefault(csl, '@suffix'); + this.delimeter = this._orDefault(csl, '@delimeter'); +}; + +Zotero.CSL.prototype.createItemSet = function(items) { + return new Zotero.CSL.ItemSet(items, this); +}; + +Zotero.CSL.ItemSet = function (items, csl) { + this._csl = csl; + this._items = items; +}; + +Zotero.CSL.Compiler = { +}; + +Zotero.CSL.Compiler.noop = function (csl, helper) { + return Zotero.CSL.Text("", Zotero.CSL.Text.Options()); +}; + +Zotero.CSL.Compiler.compile = function (csl, helper) { + if (helper == null) { + helper = {}; + helper.macros = {}; + } + switch (csl.localName()) { + case "macro": + return Zotero.CSL.Compiler.macro(csl); + case "group": + return Zotero.CSL.Compiler.group(csl); + case "style": + return Zotero.CSL.Compiler.noop;//(csl); + case "text": + return Zotero.CSL.Compiler.text(csl); + case "dates": + return Zotero.CSL.Compiler.dates(csl); + default: + return Zotero.CSL.Compiler.noop; + } +}; + +Zotero.CSL.Compiler.each = function (ar, helper) { + var funcs = ar.map (function (i) { + append(Zotero.CSL.Compiler.compile(i,helper)); + }); + return function (citation) { + var t = funcs.map(function (f) { f (citation); }); + return Zotero.Text(t, Zotero.CSL.Text.Options()); + }; +}; + +Zotero.CSL.Compiler.macro = function (csl, helper) { + helper.macros[csl['@name']] = Zotero.CSL.Compiler.each(csl.children(), helper); +}; + +Zotero.CSL.Compiler.group = function (csl, helper) { + return Zotero.CSL.Compiler.each(csl.children(), helper); +}; + +Zotero.CSL.getVariable = function (citation, form) { + +}; + +Zotero.CSL.Compiler.text = function (csl, helper) { + var options = getOptions(csl); + if (csl['@variable']) { + var variable = csl['@variable']; + return function (citation) { + return Zotero.CSL.Text(prefix + citation.getVariable(variable) + suffix, options); + }; + } else if (csl['@macro']) { + var macro = csl['@macro']; + return function (citation) { + return Zotero.CSL.Text(prefix + macro(citation) + suffix, options); + }; + } else if (csl['@term']) { + var term = csl['@term']; + return function (citation) { + return Zotero.CSL.Text(prefix + localize(citation) + suffix, options); + }; + } else if (csl['@value']) { + var value = csl['@value']; + return function (citation) { + return Zotero.CSL.Text(prefix + value + suffix, options); + }; + } +}; + +Zotero.CSL.Compiler.date = function (csl, helper) { + var options = getOptions(csl); + var variable = csl['@variable']; + var parts = children.map( function (child) { + Zotero.CSL.compile_date_part(child); + } ); + return function (citation) { + var t = parts.map( function (part) { + part(citation); + }); + return Zotero.CSL.Text(t,options); + }; +}; + +Zotero.CSL.Compiler.datePart = function (csl, helper) { + var options = getOptions(csl); + var name = this._orDefault(csl, '@name'); + if (name == 'month') { + return function (citation) { + citation.getMonth(); + }; + } else if (name == 'day') { + + } else if (name == 'year') { + + } else if (name == 'other') { + + } +}; + +Zotero.CSL.Compiler.layout = function (csl, helper) { + var options = getOptions (csl); + var childrenFunctions = children.map( function (child) { + Zotero.CSL.compile(child); + } ); + return function (citation) { + return Zotero.CSL.Text(childrenFunctions.map(function(f) { f(citation); }), options); + }; +}; + +Zotero.CSL.Item = {}; + +Zotero.CSL.Item['_zoteroRomanNumerals'] = { + "digits" : [ "", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix" ], + "tens" : [ "", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc" ], + "hundreds" : [ "", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm" ], + "thousands" : [ "", "m", "mm", "mmm", "mmmm", "mmmmm"] +}; + +Zotero.CSL.Item['makeRoman'] = function(value) { + var number = parseInt(value); + if (number > 5000) { + return ""; + } else { + return Zotero.CSL.Item._zoteroRomanNumerals["thousands"][Math.floor(number/1000)] + Zotero.CSL.Item._zoteroRomanNumerals["hundreds"][Math.floor((number % 1000)/100)] + Zotero.CSL.Item._zoteroRomanNumerals["tens"][Math.floor((number % 100)/10)] + Zotero.CSL.Item._zoteroRomanNumerals["digits"][number % 10]; + } +}; + +Zotero.CSL.prototype.formatBibliography = function(itemSet, format) { + default xml namespace = "http://purl.org/net/xbiblio/csl"; with({}); + return ""; +}; diff --git a/ref/collapse_JoinPrefix.txt b/ref/collapse_JoinPrefix.txt new file mode 100644 index 000000000..edf676286 --- /dev/null +++ b/ref/collapse_JoinPrefix.txt @@ -0,0 +1,98 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.9 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Brown 2000; Jones 2000a,b; Smith 2000a-c, 2001 +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[ + { + "id":"ITEM-1", + "type": "book", + "author": [ + { "name":"Brown" } + ], + "issued": {"year": "2000"}, + "title": "Book A" + }, + { + "id":"ITEM-2", + "type": "book", + "author": [ + { "name":"Jones" } + ], + "issued": {"year": "2000"}, + "title": "Book B" + }, + { + "id":"ITEM-3", + "type": "book", + "author": [ + { "name":"Jones" } + ], + "issued": {"year": "2000"}, + "title": "Book C" + }, + { + "id":"ITEM-4", + "type": "book", + "author": [ + { "name":"Smith" } + ], + "issued": {"year": "2000"}, + "title": "Book D" + }, + { + "id":"ITEM-5", + "type": "book", + "author": [ + { "name":"Smith" } + ], + "issued": {"year": "2000"}, + "title": "Book E" + }, + { + "id":"ITEM-6", + "type": "book", + "author": [ + { "name":"Smith" } + ], + "issued": {"year": "2000"}, + "title": "Book F" + }, + { + "id":"ITEM-7", + "type": "book", + "author": [ + { "name":"Smith" } + ], + "issued": {"year": "2001"}, + "title": "Book G" + } +] +<<===== INPUT =====<< diff --git a/ref/hetzner.pdf b/ref/hetzner.pdf new file mode 100644 index 000000000..7c9aa9e03 Binary files /dev/null and b/ref/hetzner.pdf differ diff --git a/ref/locators.txt b/ref/locators.txt new file mode 100644 index 000000000..12c9f1e16 --- /dev/null +++ b/ref/locators.txt @@ -0,0 +1,54 @@ +[{ + "source": "ITEM-1", + "note-number": "100", + "locator" : [ + [ + { "page" : "10" } + ] + ] +}, +// +// The above becomes: "p. 10" +// +{ + "source": "ITEM-2", + "note-number": "200", + "locator" : [ + [ + { "page" : "10" } + { "note" : "1" } + ] + ] +}, +// +// The above becomes: "p. 10 n. 1" +// +{ + "source": "ITEM-3", + "note-number": "300", + "locator" : [ + [ + { "page" : [ "10", "15" ] } + ] + ] +}, +// +// +// The above becomes: "pp. 10-15" +// +{ + "source": "ITEM-4", + "note-number": "400", + "locator" : [ + [ + { "page" : [ "10", "15" ] } + ], + [ + { "section" : "10" }, + ( "page" : "7" } + ] + ] +}, +// +// The above becomes: "pp. 10-15, sec. 10 p. 7" +// diff --git a/ref/sort_NumberOfAuthorsAsKeyCountMinMax.txt b/ref/sort_NumberOfAuthorsAsKeyCountMinMax.txt new file mode 100644 index 000000000..8edea5dcf --- /dev/null +++ b/ref/sort_NumberOfAuthorsAsKeyCountMinMax.txt @@ -0,0 +1,134 @@ +>>===== MODE =====>> +bibliography +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.9 experimental +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Book One +Book Two +Book Three +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[ + { + "id":"item-1", + "type": "book", + "author": [ + { "name":"Doe, John" }, + ], + "issued": {"year": "2000"}, + "title": "Book One" + }, + { + "id":"item-2", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Doe, Jake" }, + { "name":"Jones, Robert" } + ], + "issued": {"year": "2000"}, + "title": "Book Three" + }, + { + "id":"item-3", + "type": "book", + "editor": [ + { "name":"Doe, John" }, + { "name":"Roe, Jane" }, + ], + "issued": {"year": "2000"}, + "title": "Book Two" + } +] +<<===== INPUT =====<< diff --git a/ref/speed.sh b/ref/speed.sh new file mode 100755 index 000000000..9d10201d5 --- /dev/null +++ b/ref/speed.sh @@ -0,0 +1,12 @@ +#!/bin/sh +START="$(date) <--------------START" +cd $(dirname $0) +RHINO="${PWD}"/rhino/js-1.7R1.jar +DOJO="${PWD}"/dojo/dojo/dojo.js +DOH="${PWD}"/dojo/util/doh/ + +TARGET="${PWD}"/tests/test_speed.js + +java -client -jar "${RHINO}" "${TARGET}" dojoUrl="${DOJO}" testModule="" +echo $START +echo $(date) \<--------------END diff --git a/rhino/js-1.7R1.jar b/rhino/js-1.7R1.jar new file mode 100644 index 000000000..c081d16b8 Binary files /dev/null and b/rhino/js-1.7R1.jar differ diff --git a/rpc-stuff/README.txt b/rpc-stuff/README.txt new file mode 100644 index 000000000..4e83d0956 --- /dev/null +++ b/rpc-stuff/README.txt @@ -0,0 +1,78 @@ +JSON RPC server demo + +This is a simple wrapper that runs citeproc-js as an RPC web service. +It is provided only as an example, to give integrators a starting point +to work from. + +The demo requires the following facilities in order to run: + + python 2.5 + If you find that other versions work, let me know. + cjson, simplejson, or Python 2.6 json + Trials were done with version 1.0.5, other versions should work. + python-spidermonkey + A bridge to run Javascript code in Python, using the + spidermonkey JS interpreter from the Mozilla project. + libjs.so + This is a dependency of the python-spidermonkey bridge. + It provides Javascript, which is kind of central to + the ultimate objective. + wget + Required only because I'm too lazy to build a proper + client. I sincerely hope that someone somewhere will + replace this with something more elegant. Meanwhile, + hey, it's a demo. + +Once you have the above items installed on a Linux system, you should +be able to run the server in a terminal window: + + ./citeproc-js-rpc.py + +To configure and control the processor, send commands as JSON objects +via HTTP POST requests. Requests have two elements, "method" (a +string) and "params" (a list). This API could be tidied up, and +it is by no means any sort of standard. The ./wgetdemo.sh script +sends a series of hard-wired requests to the running server, and +reports the results to the terminal. + +Transactions with the server are all done in JSON, which means that +the XML of the CSL file needs to be encoded before it is sent. The +human-readable form of the CSL applied to the sample bib items +is in set_style.csl. If you modify the CSL code, be sure to regenerate +the companion JSON file by running ./gen_set_style.py -- otherwise +your changes will be ignored. + +Here is a short description of the sample transactions: + + set_style.json + Prepares a processor loaded with a simple CSL style. + + insert_items.json + Inserts a couple of items into the processor registry. + These will appear in the bibliography when it is rendered. + + make_bibliography.json (first invocation) + Delivers a rendered bibliography containing the first two + entries loaded, sorted by author name and year. + + make_citation_cluster.json + Delivers a rendered citation cluster for two additional + entries. These items are automatically inserted into + the processor registry, and will appear in the bibliography. + Note that, as declared in the sample CSL style, the cites + within the citation are sorted by year. + + make_bibliography.json (second invocation) + The second invocation of this command delivers a bibliography + of four items, correctly sorted. + +If you have questions concerning the remainder of the API (the names +API is currently specific to citeproc-js, as it has not yet been +agreed and finalized in the CSL group), let me know. Happy to +provide details. + + +Enjoy! + +FB +2009-04-17 diff --git a/rpc-stuff/citeproc-js-combined.js b/rpc-stuff/citeproc-js-combined.js new file mode 100644 index 000000000..1c2a0a9e3 --- /dev/null +++ b/rpc-stuff/citeproc-js-combined.js @@ -0,0 +1,3957 @@ +CSL = new function () { + this.START = 0; + this.END = 1; + this.SINGLETON = 2; + this.SUCCESSOR = 3; + this.SUCCESSOR_OF_SUCCESSOR = 4; + this.SUPPRESS = 5; + this.SINGULAR = 0; + this.PLURAL = 1; + this.LITERAL = true; + this.BEFORE = 1; + this.AFTER = 2; + this.DESCENDING = 1; + this.ASCENDING = 2; + this.FINISH = 1; + this.POSITION_FIRST = 0; + this.POSITION_SUBSEQUENT = 1; + this.POSITION_IBID = 2; + this.POSITION_IBID_WITH_LOCATOR = 3; + this.COLLAPSE_VALUES = ["citation-number","year","year-suffix"]; + this.ET_AL_NAMES = ["et-al-min","et-al-use-first"]; + this.ET_AL_NAMES = this.ET_AL_NAMES.concat( ["et-al-subsequent-min","et-al-subsequent-use-first"] ); + this.DISAMBIGUATE_OPTIONS = ["disambiguate-add-names","disambiguate-add-givenname"]; + this.DISAMBIGUATE_OPTIONS.push("disambiguate-add-year-suffix"); + this.PREFIX_PUNCTUATION = /.*[.;:]\s*$/; + this.SUFFIX_PUNCTUATION = /^\s*[.;:,\(\)].*/; + this.NUMBER_REGEXP = /(?:^\d+|\d+$|\d{3,})/; // avoid evaluating "F.2d" as numeric + this.QUOTED_REGEXP = /^".+"$/; + this.NAME_INITIAL_REGEXP = /^([A-Z\u0400-\u042f])([A-Z\u0400-\u042f])*.*$/; + var x = new Array(); + x = x.concat(["edition","volume","number-of-volumes","number"]); + x = x.concat(["issue","title","container-title","issued","page"]); + x = x.concat(["locator","collection-number","original-date"]); + x = x.concat(["reporting-date","decision-date","filing-date"]); + x = x.concat(["revision-date"]); + this.NUMERIC_VARIABLES = x.slice(); + this.DATE_VARIABLES = ["issued","event","accessed","container","original-date"]; + var x = new Array(); + x = x.concat(["@text-case","@font-family","@font-style","@font-variant"]); + x = x.concat(["@font-weight","@text-decoration","@vertical-align"]); + x = x.concat(["@display","@quotes"]); + this.FORMAT_KEY_SEQUENCE = x.slice(); + this.SUFFIX_CHARS = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"; + this.ROMAN_NUMERALS = [ + [ "", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix" ], + [ "", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc" ], + [ "", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm" ], + [ "", "m", "mm", "mmm", "mmmm", "mmmmm"] + ]; +}; +CSL.Core = {}; +CSL.Core.Render = {}; +CSL.Core.Render.getAmbiguousCite = function(Item,disambig){ + if (disambig){ + this.tmp.disambig_request = disambig; + } else { + this.tmp.disambig_request = false; + } + this.tmp.area = "citation"; + this.tmp.suppress_decorations = true; + this.tmp.force_subsequent = true; + CSL.Core.Render._cite.call(this,Item); + this.tmp.force_subsequent = false; + var ret = this.output.string(this,this.output.queue); + this.tmp.suppress_decorations = false; + if (false){ + print("ok"); + } + return ret; +} +CSL.Core.Render.getSortKeys = function(Item,key_type){ + if (false){ + print("KEY TYPE: "+key_type); + } + var area = this.tmp.area; + var strip_prepositions = CSL.Util.Sort.strip_prepositions; + this.tmp.area = key_type; + this.tmp.disambig_request = false; + this.tmp.suppress_decorations = true; + CSL.Core.Render._cite.call(this,Item); + this.tmp.suppress_decorations = false; + for (var i in this[key_type].keys){ + this[key_type].keys[i] = strip_prepositions(this[key_type].keys[i]); + } + if (false){ + print("sort keys ("+key_type+"): "+this[key_type].keys); + } + this.tmp.area = area; + return this[key_type].keys; +}; +CSL.Core.Render.getAmbigConfig = function(){ + var config = this.tmp.disambig_request; + if (!config){ + config = this.tmp.disambig_settings; + } + var ret = this.fun.clone_ambig_config(config); + return ret; +}; +CSL.Core.Render.getMaxVals = function(){ + return this.tmp.names_max.mystack.slice(); +}; +CSL.Core.Render.getMinVal = function(){ + return this.tmp["et-al-min"]; +}; +CSL.Core.Render.getSpliceDelimiter = function(){ + return this.tmp.splice_delimiter; +}; +CSL.Core.Render.getModes = function(){ + var ret = new Array(); + if (this[this.tmp.area].opt["disambiguate-add-names"]){ + ret.push("names"); + } + if (this[this.tmp.area].opt["disambiguate-add-givenname"]){ + ret.push("givens"); + } + return ret; +}; +CSL.Core.Render._bibliography_entries = function (){ + this.tmp.area = "bibliography"; + var input = this.fun.retriever.getInput(this.registry.getSortedIds()); + this.tmp.disambig_override = true; + this.output.addToken("bibliography","\n"); + this.output.openLevel("bibliography"); + for each (item in input){ + if (false){ + print("BIB: "+item.id); + } + CSL.Core.Render._cite.call(this,item); + //this.output.squeeze(); + } + this.output.closeLevel(); + this.tmp.disambig_override = false; + return this.output.string(this,this.output.queue); +}; +CSL.Core.Render.registerItemKeys = function() { +}; +CSL.Core.Render._unit_of_reference = function (inputList){ + this.tmp.area = "citation"; + var delimiter = ""; + var result = ""; + var objects = []; + for each (var Item in inputList){ + CSL.Core.Render._cite.call(this,Item); + // + // This will produce a stack with one + // layer, and exactly one or two items. + // We merge these as we go along, to get + // the joins right for the pairs. + delimiter = this.getSpliceDelimiter(); + this.tmp.delimiter.replace(delimiter); + this.tmp.handle_ranges = true; + var composite = this.output.string(this,this.output.queue); + this.tmp.handle_ranges = false; + // + // At last! Compose the trailing blobs here. + var blobstr = ""; + if (composite["obj"].length){ + objects = objects.concat(composite["obj"]); + } + if (result){ + result += this.tmp.splice_delimiter; + } + result += composite["str"]; + } + result += this.output.renderBlobs(objects); + result = this.citation.opt.layout_prefix + result + this.citation.opt.layout_suffix; + return result; +}; +CSL.Core.Render._cite = function(Item){ + for each (var func in this.init){ + func(this,Item); + } + var next = 0; + while(next < this[this.tmp.area].tokens.length){ + next = CSL.Core.Render._render.call(this[this.tmp.area].tokens[next],this,Item); + } + for each (func in this.stop){ + func(this,Item); + } +}; +CSL.Core.Render._render = function(state,Item){ + var next = this.next; + var maybenext = false; + if (false){ + print("---> Token: "+this.name+" ("+state.tmp.area+")"); + print(" next is: "+next+", success is: "+this.succeed+", fail is: "+this.fail); + } + if (this.evaluator){ + next = this.evaluator.call(this,state,Item); + }; + for each (var exec in this.execs){ + maybenext = exec.call(this,state,Item); + if (maybenext){ + next = maybenext; + }; + }; + if (false){ + print("---> done"); + } + return next; +}; +CSL.Core.Build = function(stylexml,xmlLingo) { + this._builder = _builder; + this.showXml = showXml; // for testing + this._getNavi = _getNavi; // exposed for testing + if (!xmlLingo){ + //xmlLingo = "JunkyardJavascript"; + xmlLingo = "E4X"; + } + var xmlParser = CSL.System.Xml[xmlLingo]; + var xml = xmlParser.parse(stylexml); + var xmlCommandInterface = CSL.System.Xml[xmlLingo].commandInterface; + var state = new CSL.Factory.State(xmlCommandInterface,xml); + this.state = state; + function _builder(state){ + this._build = _build; // exposed for testing + this.navi = navi; // exposed for testing + this.getObject = getObject; + var nodelist = state.build.nodeList; + var navi = new _getNavi(state); + function _build(){ // used to accept nodelist as arg + if (navi.getkids()){ + _build(navi.getXml()); + } else { + if (navi.getbro()){ + _build(navi.getXml()); + } else { + while (state.build.nodeList.length > 1) { + if (navi.remember()){ + _build(navi.getXml()); + } + } + } + } + return state; + } + function getObject(){ + // These startup loops are too complex + var state = this._build(); // used to have nodelist as arg + return state; + } + }; + function _getNavi(state){ + this.getkids = getkids; + this.getbro = getbro; + this.remember = remember; + this.getXml = getXml; + var depth = 0; + this.depth = depth; + function remember(){ + depth += -1; + state.build.nodeList.pop(); + // closing node, process result of children + var node = state.build.nodeList[depth][1][(state.build.nodeList[depth][0])]; + CSL.Factory.XmlToToken.call(node,state,CSL.END); + return getbro(); + } + function getbro(){ + var sneakpeek = state.build.nodeList[depth][1][(state.build.nodeList[depth][0]+1)]; + if (sneakpeek){ + state.build.nodeList[depth][0] += 1; + return true; + } else { + return false; + } + } + function getkids (){ + var currnode = state.build.nodeList[depth][1][state.build.nodeList[depth][0]]; + var sneakpeek = state.build.xmlCommandInterface.children.call(currnode); + if (state.build.xmlCommandInterface.numberofnodes.call(sneakpeek) == 0){ + // singleton, process immediately + CSL.Factory.XmlToToken.call(currnode,state,CSL.SINGLETON); + return false; + } else { + // if first node of a span, process it, then descend + CSL.Factory.XmlToToken.call(currnode,state,CSL.START); + depth += 1; + state.build.nodeList.push([0,sneakpeek]); + return true; + } + } + function getXml(){ + return state.build.nodeList[depth][1]; + } + } + function showXml(){ + return xml; + } +}; +CSL.Core.Build.prototype.build = function(locale){ + this.state.opt.locale = locale; + var engine = new this._builder(this.state); + var ret = engine.getObject(); + ret.registry = new CSL.Factory.Registry(ret); + return ret; +}; +CSL.Core.Configure = function(state,mode) { + this.state = state; + if (!mode){ + mode = "html"; + } + if (this.state.build){ + delete this.state.build; + } + this.state.fun.decorate = CSL.Factory.Mode(mode); + this.state.opt.mode = mode; +}; +CSL.Core.Configure.prototype.configure = function(){ + for each (var area in ["citation", "citation_sort", "bibliography","bibliography_sort"]){ + for (var pos=(this.state[area].tokens.length-1); pos>-1; pos--){ + var token = this.state[area].tokens[pos]; + token["next"] = (pos+1); + if (token.name && CSL.Lib.Elements[token.name].configure){ + CSL.Lib.Elements[token.name].configure.call(token,this.state,pos); + } + } + } + this.state["version"] = CSL.Factory.version; + return this.state; +}; +CSL.Util = {}; +CSL.Util.Dates = new function(){}; +CSL.Util.Dates.year = new function(){}; +CSL.Util.Dates.year["long"] = function(state,num){ + return num.toString(); +} +CSL.Util.Dates.year["short"] = function(state,num){ + num = num.toString(); + if (num && num.length == 4){ + return num.substr(2); + } +} +CSL.Util.Dates["month"] = new function(){}; +CSL.Util.Dates.month["numeric"] = function(state,num){ + return num.toString(); +} +CSL.Util.Dates.month["numeric-leading-zeros"] = function(state,num){ + num = num.toString(); + while (num.length < 2){ + num = "0"+num; + } + return num.toString(); +} +CSL.Util.Dates.month["long"] = function(state,num){ + num = num.toString(); + while (num.length < 2){ + num = "0"+num; + } + num = "month-"+num; + return state.opt.term[num]["long"][0]; +} +CSL.Util.Dates.month["short"] = function(state,num){ + num = num.toString(); + while (num.length < 2){ + num = "0"+num; + } + num = "month-"+num; + return state.opt.term[num]["short"][0]; +} +CSL.Util.Dates["day"] = new function(){}; +CSL.Util.Dates.day["numeric"] = function(state,num){ + return num.toString(); +} +CSL.Util.Dates.day["numeric-leading-zeros"] = function(state,num){ + num = num.toString(); + while (num.length < 2){ + num = "0"+num; + } + return num.toString(); +} +CSL.Util.Dates.day["ordinal"] = function(state,num){ + var suffixes = ["st","nd","rd","th"]; + var str = num.toString(); + if ( (num/10)%10 == 1){ + str += suffixes[3]; + } else if ( num%10 == 1) { + str += suffixes[0]; + } else if ( num%10 == 2){ + str += suffixes[1]; + } else if ( num%10 == 3){ + str += suffixes[2]; + } else { + str += suffixes[3]; + } + return str; +} +// +// This will probably become CSL.Util.Numbers +// +CSL.Util.Disambiguate = new function(){}; +CSL.Util.Disambiguate.Romanizer = function (){}; +CSL.Util.Disambiguate.Romanizer.prototype.format = function(num){ + var ret = ""; + if (num < 6000) { + var numstr = num.toString().split(""); + numstr.reverse(); + var pos = 0; + var n = 0; + for (var pos in numstr){ + n = parseInt(numstr[pos],10); + ret = CSL.ROMAN_NUMERALS[pos][n] + ret; + } + } + return ret; +}; +CSL.Util.Disambiguate.Suffixator = function(slist){ + this.slist = slist.split(","); +}; +CSL.Util.Disambiguate.Suffixator.prototype.format = function(num){ + var suffixes = this.get_suffixes(num); + return suffixes[(suffixes.length-1)]; +} +CSL.Util.Disambiguate.Suffixator.prototype.get_suffixes = function(num){ + var suffixes = new Array(); + for (var i=0; i <= num; i++){ + if (!i){ + suffixes.push([0]); + } else { + suffixes.push( this.incrementArray(suffixes[(suffixes.length-1)],this.slist) ); + } + }; + for (pos in suffixes){ + var digits = suffixes[pos]; + var chrs = ""; + for each (digit in digits){ + chrs = chrs+this.slist[digit]; + } + suffixes[pos] = chrs; + }; + return suffixes; +}; +CSL.Util.Disambiguate.Suffixator.prototype.incrementArray = function (array){ + array = array.slice(); + var incremented = false; + for (var i=(array.length-1); i > -1; i--){ + if (array[i] < (this.slist.length-1)){ + array[i] += 1; + if (i < (array.length-1)){ + array[(i+1)] = 0; + } + incremented = true; + break; + } + } + if (!incremented){ + for (var i in array){ + array[i] = 0; + } + var newdigit = [0]; + array = newdigit.concat(array); + } + return array; +}; +CSL.Util.Names = new function(){}; +CSL.Util.Names.outputNames = function(state,display_names){ + var segments = new this.StartMiddleEnd(state,display_names); + var sort_order = state.output.getToken("name").strings["name-as-sort-order"]; + if (sort_order == "first"){ + state.output.addToken("start"); + state.output.getToken("start").strings.name_as_sort_order = true; + } else if (sort_order == "all"){ + state.output.addToken("start"); + state.output.getToken("start").strings.name_as_sort_order = true; + state.output.addToken("middle"); + state.output.getToken("middle").strings.name_as_sort_order = true; + state.output.addToken("end"); + state.output.getToken("end").strings.name_as_sort_order = true; + } + state.output.openLevel("name"); + state.output.openLevel("inner"); + segments.outputSegmentNames("start"); + segments.outputSegmentNames("middle"); + state.output.closeLevel(); + segments.outputSegmentNames("end"); + state.output.closeLevel(); +}; +CSL.Util.Names.StartMiddleEnd = function(state,names){ + this.state = state; + this.nameoffset = 0; + var start = names.slice(0,1); + var middle = names.slice(1,(names.length-1)); + var endstart = 1; + if (names.length > 1){ + endstart = (names.length-1); + } + var end = names.slice(endstart,(names.length)); + var ret = {}; + ret["start"] = start; + ret["middle"] = middle; + ret["end"] = end; + this.segments = ret; +}; +CSL.Util.Names.StartMiddleEnd.prototype.outputSegmentNames = function(seg){ + var state = this.state; + for (var namenum in this.segments[seg]){ + this.namenum = parseInt(namenum,10); + this.name = this.segments[seg][namenum]; + if (this.name.literal){ + // + // XXXXX Separate formatting for institution names? + // XXXXX This needs to be firmly settled in xbib. + // + state.output.append(this.name.literal); + } else { + var sequence = CSL.Util.Names.getNamepartSequence(this.name,state.output.getToken(seg)); + state.output.openLevel(sequence[0][0]); + state.output.openLevel(sequence[0][1]); + state.output.openLevel(sequence[0][2]); + this.outputNameParts(sequence[1]); + state.output.closeLevel(); + state.output.openLevel(sequence[0][2]); + // XXX cloned code! make this a function. + this.outputNameParts(sequence[2]); + state.output.closeLevel(); + state.output.closeLevel(); + // + // articular goes here // + // + this.outputNameParts(sequence[3]); + state.output.closeLevel(); + // + // the articular goes in at a different level, but + // is nonetheless part of the name, so it goes into + // this function to avoid repetition. + // (special handling when comma is to be included) + //if (name.suffix){ + // state.output.squeeze(); + // if (name.comma_suffix){ + // state.tmp.delimiter.replace(", "); + // } + // state.output.append(name.suffix); + //} + } + }; + this.nameoffset += this.segments[seg].length; +} +CSL.Util.Names.StartMiddleEnd.prototype.outputNameParts = function(subsequence){ + var state = this.state; + for each (var key in subsequence){ + var namepart = this.name[key]; + if ("secondary-key" == key && !this.name.sticky){ + if (0 == state.tmp.disambig_settings["givens"][state.tmp.nameset_counter][(this.namenum+this.nameoffset)]){ + continue; + } else if (1 == state.tmp.disambig_settings["givens"][state.tmp.nameset_counter][(this.namenum+this.nameoffset)]){ + namepart = state.fun.initialize_with(namepart,state.tmp["initialize-with"]); + } + } + //state.output.openLevel(key); + state.output.append(namepart,key); + //state.output.closeLevel(); + } +} +CSL.Util.Names.getNamepartSequence = function(name,token){ + if (name.comma_suffix){ + var suffix_sep = "commasep"; + } else { + var suffix_sep = "space"; + } + var romanesque = name["primary-key"].match(/.*[a-zA-Z\u0400-\u052f].*/); + if (!romanesque ){ // neither roman nor Cyrillic characters + var sequence = [["empty","empty","empty"],["prefix", "primary-key"],["secondary-key"],[]]; + } else if (name.sticky) { // entry likes sort order + var sequence = [["space","space","space"],["prefix", "primary-key"],["secondary-key"],[]]; + } else if (token && token.strings.name_as_sort_order){ + var sequence = [["sortsep","sortsep","space"],["prefix", "primary-key"],["secondary-key"],["suffix"]]; + } else { // plain vanilla + var sequence = [[suffix_sep,"space","space"],["secondary-key"],["prefix","primary-key"],["suffix"]]; + } + return sequence; +}; +CSL.Util.Names.deep_copy = function(nameset){ + var nameset2 = new Array(); + for each (name in nameset){ + var name2 = new Object(); + for (var i in name){ + name2[i] = name[i]; + } + nameset2.push(name2); + } + return nameset2; +} +// +// XXXX A handy guide to variable assignments that need +// XXXX to be eliminated. :) +// +CSL.Util.Names.reinit = function(state,Item){ + for each (namevar in state.tmp.value){ + state.tmp.name_quash[namevar.type] = true; + } + state.tmp.value = new Array(); + state.tmp.names_substituting = false; + state.tmp.name_et_al_term = false; + state.tmp.name_et_al_decorations = false; + state.tmp.name_et_al_form = "long"; + state.tmp["et-al-min"] = false; + state.tmp["et-al-use-first"] = false; + state.tmp["initialize-with"] = false; + state.tmp["name-as-sort-order"] = false; + state.tmp.et_al_prefix = false; +}; +CSL.Util.Names.getCommonTerm = function(state,namesets){ + if (namesets.length < 2){ + return false; + } + var base_nameset = namesets[0]; + var varnames = new Array(); + if (varnames.indexOf(base_nameset.type) == -1){ + varnames.push(base_nameset.type); + } + var name; + for each (nameset in namesets.slice(1)){ + if (base_nameset.length != nameset.length){ + return false; + } + if (varnames.indexOf(nameset.type) == -1){ + varnames.push(nameset.type); + } + for (var n in nameset.names){ + name = nameset.names[n]; + for each (var part in ["primary-key","secondary-key","prefix","suffix"]){ + if (base_nameset.names[n][part] != name[part]){ + return false; + } + } + } + } + varnames.sort(); + return state.opt.term[varnames.join("")]; +}; +CSL.Util.Names.initialize_with = function(name,terminator){ + var namelist = name.split(/\s+/); + var nstring = ""; + for each (var n in namelist){ + var m = n.match( CSL.NAME_INITIAL_REGEXP); + if (m){ + var extra = ""; + if (m[2]){ + extra = m[2].toLocaleLowerCase(); + } + nstring = nstring + m[1].toLocaleUpperCase() + extra + terminator; + }; + }; + if (nstring){ + return nstring; + } + return name; +}; +CSL.Util.Sort = new function(){}; +CSL.Util.Sort.strip_prepositions = function(str){ + var m = str.toLocaleLowerCase().match(/((a|an|the)\s+)/); + if (m){ + str = str.substr(m[1].length); + }; + return str; +}; +CSL.Factory = {}; +CSL.Factory.version = function(){ + var msg = "\"Entropy\" citation processor (a.k.a. citeproc-js) ver.0.01"; + print(msg); + return msg; +}; +CSL.Factory.XmlToToken = function(state,tokentype){ + var name = state.build.xmlCommandInterface.nodename.call(this); + if (state.build.skip && state.build.skip != name){ + return; + } + if (!name){ + var txt = state.build.xmlCommandInterface.content.call(this); + if (txt){ + state.build.text = txt; + } + return; + } + if ( ! CSL.Lib.Elements[state.build.xmlCommandInterface.nodename.call(this)]){ + throw "Undefined node name \""+name+"\"."; + } + var attrfuncs = new Array(); + var attributes = state.build.xmlCommandInterface.attributes.call(this); + var decorations = CSL.Factory.setDecorations.call(this,state,attributes); + var token = new CSL.Factory.Token(name,tokentype); + for (var key in attributes){ + try { + var attrfunc = CSL.Lib.Attributes[key].call(token,state,attributes[key]); + } catch (e) { + if (e == "TypeError: Cannot call method \"call\" of undefined"){ + throw "Unknown attribute \""+key+"\" in node \""+name+"\" while processing CSL file"; + } else { + throw "CSL processor error, "+key+" attribute: "+e; + } + } + if (attrfunc){ + attrfuncs.push(attrfunc); + } + } + token.decorations = decorations; + if (state.build.children.length){ + var target = state.build.children[0]; + } else { + var target = state[state.build.area].tokens; + } + CSL.Lib.Elements[name].build.call(token,state,target); +}; +CSL.Factory.mark_output = function(state,content){ + if (content){ + state.tmp.term_sibling.replace( true ); + } else { + if (undefined == state.tmp.term_sibling.value()) { + state.tmp.term_sibling.replace( false, CSL.LITERAL ); + } + } +} +CSL.Factory.setDecorations = function(state,attributes){ + var ret = new Array(); + for each (var key in CSL.FORMAT_KEY_SEQUENCE){ + if (attributes[key]){ + ret.push([key,attributes[key]]); + delete attributes[key]; + } + } + return ret; +}; +CSL.Factory.renderDecorations = function(state){ + var ret = new Array(); + for each (hint in this.decorations){ + ret.push(state.fun.decorate[hint[0]][hint[1]]); + } + this.decorations = ret; +}; +CSL.Factory.substituteOne = function(template) { + return function(list) { + if ("string" == typeof list){ + return template.replace("%%STRING%%",list); + } + var decor = template.split("%%STRING%%"); + var ret = [{"is_delimiter":true,"value":decor[0]}].concat(list); + ret.push({"is_delimiter":true,"value":decor[1]}); + return ret; + }; +}; +CSL.Factory.substituteTwo = function(template) { + return function(param) { + var template2 = template.replace("%%PARAM%%", param); + return function(list) { + if ("string" == typeof list){ + return template2.replace("%%STRING%%",list); + } + var decor = template2.split("%%STRING"); + var ret = [{"is_delimiter":true,"value":decor[0]}].concat(list); + ret.push({"is_delimiter":true,"value":decor[1]}); + return ret; + }; + }; +}; +CSL.Factory.Mode = function(mode){ + var decorations = new Object(); + var params = CSL.Output.Formats[mode]; + for (var param in params) { + var func = false; + var val = params[param]; + var args = param.split('/'); + if (typeof val == "string" && val.indexOf("%%STRING%%") > -1) { + if (val.indexOf("%%PARAM%%") > -1) { + func = CSL.Factory.substituteTwo(val); + } else { + func = CSL.Factory.substituteOne(val); + } + } else if (typeof val == "boolean" && !val) { + func = CSL.Output.Formatters.passthrough; + } else if (typeof val == "function") { + func = val; + } else { + throw "CSL.Compiler: Bad "+mode+" config entry for "+param+": "+val; + } + if (args.length == 1) { + decorations[args[0]] = func; + } else if (args.length == 2) { + if (!decorations[args[0]]) { + decorations[args[0]] = new Object(); + } + decorations[args[0]][args[1]] = func; + } + } + return decorations; +}; +CSL.Factory.expandMacro = function(macro_key_token){ + var mkey = macro_key_token.postponed_macro; + if (this.build.macro_stack.indexOf(mkey) > -1){ + throw "CSL processor error: call to macro \""+mkey+"\" would cause an infinite loop"; + } else { + this.build.macro_stack.push(mkey); + } + var ret = new Array(); + var start_token = new CSL.Factory.Token("group",CSL.START); + ret.push(start_token); + for (var i in this.build.macro[mkey]){ + // + // could use for each; this was an attempt to get a + // fresh copy of the token to defeat a loop involving + // interaction between sort and citation render. had + // no effect, probably not needed. + var token = this.build.macro[mkey][i]; + if (token.postponed_macro){ + // + // nested expansion + ret.concat(CSL.Factory.expandMacro.call(this,token)); + } else { + // + // clone the token, so that navigation pointers are + // specific to the token list into which the macro + // is being expanded. + var newtoken = new Object(); + for (i in token) { + newtoken[i] = token[i]; + } + ret.push(newtoken); + } + } + var end_token = new CSL.Factory.Token("group",CSL.END); + ret.push(end_token); + this.build.macro_stack.pop(); + return ret; +}; +CSL.Factory.cloneAmbigConfig = function(config){ + var ret = new Object(); + ret["names"] = new Array(); + ret["givens"] = new Array(); + ret["year_suffix"] = false; + ret["disambiguate"] = false; + for (var i in config["names"]){ + var param = config["names"][i]; + ret["names"][i] = param; + } + for (var i in config["givens"]){ + var param = new Array(); + for (var j in config["givens"][i]){ + param.push(config["givens"][i][j]); + } + ret["givens"].push(param); + } + ret["year_suffix"] = config["year_suffix"]; + ret["disambiguate"] = config["disambiguate"]; + return ret; +}; +CSL.Factory.State = function (xmlCommandInterface,nodelist){ + this.init = new Array(); + this.stop = new Array(); + this.opt = new Object(); + this.tmp = new Object(); + this.fun = new Object(); + this.fun.retriever = new CSL.System.Retrieval.GetInput(); + this.build = new Object(); + this.build["alternate-term"] = false; + this.configure = new Object(); + this.citation = new Object(); + this.citation.opt = new Object(); + this.citation.tokens = new Array(); + this.bibliography = new Object(); + this.bibliography.opt = new Object(); + this.bibliography.tokens = new Array(); + this.citation.opt["et-al-min"] = 0; + this.citation.opt["et-al-use-first"] = 1; + this.citation.opt["et-al-subsequent-min"] = false; + this.citation.opt["et-al-subsequent-use-first"] = false; + this.bibliography.opt["et-al-min"] = 0; + this.bibliography.opt["et-al-use-first"] = 1; + this.bibliography.opt["et-al-subsequent-min"] = 0; + this.bibliography.opt["et-al-subsequent-use-first"] = 1; + this.bibliography_sort = new Object(); + this.citation_sort = new Object(); + this.bibliography_sort.tokens = new Array(); + this.bibliography_sort.opt = new Object(); + this.bibliography_sort.opt.sort_directions = new Array(); + this.bibliography_sort.keys = new Array(); + this.citation_sort.tokens = new Array(); + this.citation_sort.opt = new Object(); + this.citation_sort.opt.sort_directions = new Array(); + this.citation_sort.keys = new Array(); + this.opt.lang = false; + this.opt.term = new Object(); + this.citation.opt.collapse = new Array(); + this.bibliography.opt.collapse = new Array(); + this.citation.opt["disambiguate-add-names"] = false; + this.citation.opt["disambiguate-add-givenname"] = false; + this.bibliography.opt["disambiguate-add-names"] = false; + this.bibliography.opt["disambiguate-add-givenname"] = false; + this.tmp.names_max = new CSL.Factory.Stack(); + this.tmp.names_base = new CSL.Factory.Stack(); + this.tmp.givens_base = new CSL.Factory.Stack(); + this.build.in_bibliography = false; + this.tmp.disambig_request = false; + this.tmp["name-as-sort-order"] = false; + this.tmp.suppress_decorations = false; + this.tmp.disambig_settings = new CSL.Factory.AmbigConfig(); + this.tmp.bib_sort_keys = new Array(); + this.tmp.prefix = new CSL.Factory.Stack("",CSL.LITERAL); + this.tmp.suffix = new CSL.Factory.Stack("",CSL.LITERAL); + this.tmp.delimiter = new CSL.Factory.Stack("",CSL.LITERAL); + this.fun.names_reinit = CSL.Util.Names.reinit; + this.fun.initialize_with = CSL.Util.Names.initialize_with; + this.fun.clone_ambig_config = CSL.Factory.cloneAmbigConfig; + this.tmp.initialize_with = new CSL.Factory.Stack(); + this.fun.get_common_term = CSL.Util.Names.getCommonTerm; + this.fun.suffixator = new CSL.Util.Disambiguate.Suffixator(CSL.SUFFIX_CHARS); + this.fun.romanizer = new CSL.Util.Disambiguate.Romanizer(); + this.tmp.tokenstore_stack = new CSL.Factory.Stack(); + this.tmp.name_quash = new Object(); + this.tmp.last_suffix_used = ""; + this.tmp.last_names_used = new Array(); + this.tmp.last_years_used = new Array(); + this.tmp.years_used = new Array(); + this.tmp.names_used = new Array(); + this.splice_delimiter = false; + this.tmp.names_substituting = false; + this.tmp.nameset_counter = 0; + this.fun.mark_output = CSL.Factory.mark_output; + this.tmp.term_sibling = new CSL.Factory.Stack( undefined, CSL.LITERAL); + this.tmp.term_predecessor = false; + this.tmp.jump = new CSL.Factory.Stack(0,CSL.LITERAL); + this.tmp.decorations = new CSL.Factory.Stack(); + this.fun.decorate = false; + this.tmp.area = "citation"; + this.build.area = "citation"; + this.tmp.value = new Array(); + this.tmp.namepart_decorations = new Object(); + this.tmp.namepart_type = false; + this.output = new CSL.Output.Queue(this); + this.configure.fail = new Array(); + this.configure.succeed = new Array(); + this.build.xmlCommandInterface = xmlCommandInterface; + this.build.text = false; + this.build.lang = false; + this.opt["class"] = false; + this.build.in_style = false; + this.build.skip = false; + this.build.postponed_macro = false; + this.build.layout_flag = false; + this.build.children = new Array(); + this.build.name = false; + this.build.form = false; + this.build.term = false; + this.build.macro = new Object(); + this.build.macro_stack = new Array(); + this.build.nodeList = new Array(); + this.build.nodeList.push([0, nodelist]); +}; +CSL.Factory.State.prototype.getAmbiguousCite = CSL.Core.Render.getAmbiguousCite; +CSL.Factory.State.prototype.getSortKeys = CSL.Core.Render.getSortKeys; +CSL.Factory.State.prototype.getAmbigConfig = CSL.Core.Render.getAmbigConfig; +CSL.Factory.State.prototype.getMaxVals = CSL.Core.Render.getMaxVals; +CSL.Factory.State.prototype.getMinVal = CSL.Core.Render.getMinVal; +CSL.Factory.State.prototype.getModes = CSL.Core.Render.getModes; +CSL.Factory.State.prototype.getSpliceDelimiter = CSL.Core.Render.getSpliceDelimiter; +CSL.makeStyle = function(xml,locale){ + var builder = new CSL.Core.Build(xml); + var raw = builder.build(locale); + var conf = new CSL.Core.Configure(raw); + var ret = conf.configure(); + return ret; +} +CSL.Factory.State.prototype.makeCitationCluster = function(inputList){ + this.insertItems(inputList); + if (inputList && inputList.length > 1 && this["citation_sort"].tokens.length > 0){ + var newlist = new Array(); + var keys_list = new Array(); + for each (var Item in inputList){ + var keys = this.getSortKeys(Item,"citation_sort"); + keys["cheaters_hack"] = Item; + keys_list.push(keys); + } + var srt = new CSL.Factory.Registry.Comparifier(this,"citation_sort"); + keys_list.sort(srt.compareKeys); + for each (key in keys_list){ + newlist.push(key.cheaters_hack); + } + // + // XXXXX this is all one-time, one-way, slice probably isn't needed here? + inputList = newlist; + } + this.tmp.last_suffix_used = ""; + this.tmp.last_names_used = new Array(); + this.tmp.last_years_used = new Array(); + var str = CSL.Core.Render._unit_of_reference.call(this,inputList); + return str; +}; +CSL.Factory.State.prototype.makeBibliography = function(){ + var debug = false; + if (debug){ + for each (tok in this.bibliography.tokens){ + print("bibtok: "+tok.name); + } + print("---"); + for each (tok in this.citation.tokens){ + print("cittok: "+tok.name); + } + print("---"); + for each (tok in this.bibliography_sort.tokens){ + print("bibsorttok: "+tok.name); + } + } + return CSL.Core.Render._bibliography_entries.call(this); +}; +CSL.Factory.State.prototype.insertItems = function(inputList){ + for each (item in inputList){ + this.fun.retriever.input[item.id] = item; + this.registry.insert(this,item); + }; +}; +CSL.Factory.Blob = function(token,str){ + if (token){ + this.strings = token.strings; + this.decorations = token.decorations; + } else { + this.strings = new Object(); + }; + if ("string" == typeof str){ + this.blobs = str; + } else { + this.blobs = new Array(); + }; +}; +CSL.Factory.Token = function(name,tokentype){ + this.name = name; + this.strings = new Object(); + this.strings["delimiter"] = ""; + this.strings["prefix"] = ""; + this.strings["suffix"] = ""; + this.decorations = false; + this.variables = []; + this.execs = new Array(); + this.tokentype = tokentype; + this.evaluator = false; + this.tests = new Array(); + this.succeed = false; + this.fail = false; + this.next = false; +}; +CSL.Factory.Stack = function(val,literal){ + this.mystack = new Array(); + if (literal || val){ + this.mystack.push(val); + } +}; +CSL.Factory.Stack.prototype.clear = function(){ + this.mystack = new Array(); +}; +CSL.Factory.Stack.prototype.push = function(val,literal){ + if (literal || val){ + this.mystack.push(val); + } else { + this.mystack.push(""); + } +}; +CSL.Factory.Stack.prototype.replace = function(val,literal){ + if (this.mystack.length == 0){ + throw "Internal CSL processor error: attempt to replace nonexistent stack item"; + } + if (literal || val){ + this.mystack[(this.mystack.length-1)] = val; + } else { + this.mystack[(this.mystack.length-1)] = ""; + } +}; +CSL.Factory.Stack.prototype.pop = function(){ + this.mystack.pop(); +}; +CSL.Factory.Stack.prototype.value = function(){ + return this.mystack[(this.mystack.length-1)]; +}; +CSL.Factory.Stack.prototype.length = function(){ + return this.mystack.length; +}; +CSL.Factory.AmbigConfig = function(){ + this.maxvals = new Array(); + this.minval = 1; + this.names = new Array(); + this.givens = new Array(); + this.year_suffix = 0; + this.disambiguate = 0; +}; +// +// should allow batched registration of items by +// key. should behave as an update, with deletion +// of items and the tainting of disambiguation +// partner sets affected by a deletes and additions. +// +// +// we'll need a reset method, to clear the decks +// in the citation area and start over. +CSL.Factory.Registry = function(state){ + this.debug = false; + this.debug_sort = false; + if (this.debug){ + print("---> Instantiate registry"); + } + this.registry = new Object(); + this.ambigs = new Object(); + this.start = false; + this.end = false; + this.initialized = false; + this.skip = false; + this.maxlength = 0; + this.sorter = new CSL.Factory.Registry.Comparifier(state,"bibliography_sort"); + this.getSortedIds = function(){ + var step = "next"; + var item_id = this.start; + var ret = new Array(); + while (true){ + ret.push(item_id); + item_id = this.registry[item_id][step]; + if ( ! item_id){ + break; + } + } + return ret; + }; +}; +CSL.Factory.Registry.prototype.insert = function(state,Item){ + if (this.debug){ + print("---> Start of insert"); + } + if (this.registry[Item.id]){ + return; + } + var sortkeys = state.getSortKeys(Item,"bibliography_sort"); + var akey = state.getAmbiguousCite(Item); + var abase = state.getAmbigConfig(); + var modes = state.getModes(); + var newitem = { + "id":Item.id, + "seq":1, + "dseq":0, + "sortkeys":sortkeys, + "disambig":abase, + "prev":false, + "next":false + }; + if (this.debug){ + print("---> Begin manipulating registry"); + } + var breakme = false; + if (!this.initialized){ + if (this.debug_sort){ + print("-->initializing registry with "+newitem.id); + } + this.registry[newitem.id] = newitem; + this.start = newitem.id; + this.end = newitem.id; + this.initialized = true; + // + // XXXXX + //this.registerAmbigToken(state,akey,Item.id,abase.slice()); + this.registerAmbigToken(state,akey,Item.id,abase); + return; + } + if (-1 == this.sorter.compareKeys(newitem.sortkeys,this.registry[this.start].sortkeys)){ + if (this.debug_sort){ + print("-->inserting "+newitem.id+" before "+this.start+" as first entry"); + } + newitem.next = this.registry[this.start].id; + this.registry[this.start].prev = newitem.id; + newitem.prev = false; + newitem.seq = 1; + var tok = this.registry[this.start]; + this.incrementSubsequentTokens(tok); + this.start = newitem.id; + this.registry[newitem.id] = newitem; + breakme = true; + } + if (-1 == this.sorter.compareKeys(this.registry[this.end].sortkeys,newitem.sortkeys) && !breakme){ + if (this.debug_sort){ + print("-->inserting "+newitem.id+" after "+this.end+" as last entry"); + } + newitem.prev = this.registry[this.end].id; + this.registry[this.end].next = newitem.id; + newitem.next = false; + newitem.seq = (this.registry[this.end].seq + 1); + this.end = newitem.id; + this.registry[newitem.id] = newitem; + breakme = true; + } + var curr = this.registry[this.end]; + while (true && !breakme){ + // compare the new token to be added with + // the one we're thinking about placing it after. + var cmp = this.sorter.compareKeys(curr.sortkeys,newitem.sortkeys); + if (cmp == -1){ + if (this.debug_sort){ + print("-->inserting "+newitem.id+" after "+curr.id); + } + // insert mid-list, after the tested item + this.registry[curr.next].prev = newitem.id; + newitem.next = curr.next; + newitem.prev = curr.id; + curr.next = newitem.id; + newitem.seq = (curr.seq+1); + this.incrementSubsequentTokens(this.registry[newitem.next]); + this.registry[newitem.id] = newitem; + breakme = true; + break; + } else if (cmp == 2){ + breakme = true; + } else if (cmp == 0) { + // insert _after_, but this one is equivalent + // to the comparison partner for sortkey purposes + // (so we needed to provide for cases where the + // inserted object ends up at the end of + // the virtual list.) + if (false == curr.next){ + if (this.debug_sort){ + print("-->inserting "+newitem.id+" after "+curr.id+" as last entry, although equal"); + } + newitem.next = false; + newitem.prev = curr.id; + curr.next = newitem.id; + newitem.seq = (curr.seq+1); + //this.incrementSubsequentTokens(curr); + this.registry[newitem.id] = newitem; + this.end = newitem.id; + breakme = true; + break; + } else { + if (this.debug_sort){ + print("-->inserting "+newitem.id+" after "+curr.id+", although equal"); + } + this.registry[curr.next].prev = newitem.id; + newitem.next = curr.next; + newitem.prev = curr.id; + curr.next = newitem.id; + newitem.seq = curr.seq; + this.registry[newitem.id] = newitem; + this.incrementSubsequentTokens(newitem); + breakme = true; + break; + } + } + if (breakme){ + break; + } + // + // we scan in reverse order, because working + // from the initial draft of the code, this + // makes it simpler to order cites in submission + // order, when no sort keys are available. + curr = this.registry[curr.prev]; + }; + if (this.debug){ + print("---> End of registry insert"); + } + this.registerAmbigToken(state,akey,Item.id,abase); + if (this.ambigs[akey].length > 1){ + if (modes.length){ + if (this.debug){ + print("---> Names disambiguation begin"); + } + var leftovers = this.disambiguateCites(state,akey,modes); + if (this.debug){ + print("---> Names disambiguation done"); + } + // + // leftovers is a list of registry tokens. sort them. + leftovers.sort(this.compareRegistryTokens); + } else { + // + // if we didn't disambiguate with names, everything is + // a leftover. + var leftovers = new Array(); + for each (var key in this.ambigs[akey]){ + leftovers.push(this.registry[key]); + leftovers.sort(this.compareRegistryTokens); + } + } + } + if (leftovers && leftovers.length && state.opt.has_disambiguate){ + var leftovers = this.disambiguateCites(state,akey,modes,leftovers); + } + if ( leftovers && leftovers.length && state[state.tmp.area].opt["disambiguate-add-year-suffix"]){ + var suffixes = state.fun.suffixator.get_suffixes(leftovers.length); + for (var i in leftovers){ + this.registry[ leftovers[i].id ].disambig[2] = suffixes[i]; + this.registry[ leftovers[i].id ].dseq = i; + } + } + if (this.debug) { + print("---> End of registry cleanup"); + } +}; +CSL.Factory.Registry.Comparifier = function(state,keyset){ + var sort_directions = state[keyset].opt.sort_directions.slice(); + this.compareKeys = function(a,b){ + for (var i=0; i < a.length; i++){ + // + // for ascending sort 1 uses 1, -1 uses -1. + // For descending sort, the values are reversed. + var cmp = a[i].toLocaleLowerCase().localeCompare(b[i].toLocaleLowerCase()); + if (0 < cmp){ + return sort_directions[i][1]; + } else if (0 > cmp){ + return sort_directions[i][0]; + } + } + return 0; + }; +}; +CSL.Factory.Registry.prototype.compareRegistryTokens = function(a,b){ + if (a.seq > b.seq){ + return 1; + } else if (a.seq < b.seq){ + return -1; + } + return 0; +}; +CSL.Factory.Registry.prototype.incrementSubsequentTokens = function (tok){ + while (tok.next){ + tok.seq += 1; + tok = this.registry[tok.next]; + } + tok.seq += 1; +}; +CSL.Factory.Registry.prototype.disambiguateCites = function (state,akey,modes,candidate_list){ + if ( ! candidate_list){ + // + // We start with the state and an ambig key. + // We acquire a copy of the list of ambigs that relate to the key from state. + var ambigs = this.ambigs[akey].slice(); + // + // We clear the list of ambigs so it can be rebuilt + this.ambigs[akey] = new Array(); + } else { + // candidate list consists of registry tokens. + // extract the ids and build an ambigs list. + // This is roundabout -- we already collected + // these once for the first-phase disambiguation. + // Maybe it can be cleaned up later. + var ambigs = new Array(); + for each (var reg_token in candidate_list){ + ambigs.push(reg_token.id); + } + } + var id_vals = new Array(); + for each (var a in ambigs){ + id_vals.push(a); + } + var tokens = state.fun.retriever.getInput(id_vals); + var checkerator = new this.Checkerator(tokens,modes); + checkerator.lastclashes = (ambigs.length-1); + var base = false; + checkerator.pos = 0; + while (checkerator.run()){ + var token = tokens[checkerator.pos]; + if (debug){ + print("<<<<<<<<<<<<<<<<<<<<<<<<< "+ token.id +" >>>>>>>>>>>>>>>>>>>>>>>>>>>"); + } + // + // skip items that have been finally resolved. + if (this.ambigs[akey].indexOf(token.id) > -1){ + if (debug){ + print("---> Skip registered token for: "+token.id); + } + checkerator.pos += 1; + continue; + } + checkerator.candidate = token.id; + if (base == false){ + checkerator.mode = modes[0]; + } + if (debug){ + print (" ---> Mode: "+checkerator.mode); + } + if (debug){ + print("base in (givens):"+base["givens"]); + } + var str = state.getAmbiguousCite(token,base); + var maxvals = state.getMaxVals(); + var minval = state.getMinVal(); + base = state.getAmbigConfig(); + if (debug){ + print("base out (givens):"+base["givens"]); + } + if (candidate_list && candidate_list.length){ + base["disambiguate"] = true; + } + checkerator.setBase(base); + checkerator.setMaxVals(maxvals); + checkerator.setMinVal(minval); + for each (testpartner in tokens){ + if (token.id == testpartner.id){ + continue; + } + var otherstr = state.getAmbiguousCite(testpartner,base); + if (debug){ + print(" ---> last clashes: "+checkerator.lastclashes); + print(" ---> master: "+token.id); + print(" ---> master: "+str); + print(" ---> partner: "+testpartner.id); + print(" ---> partner: "+otherstr); + } + if(checkerator.checkForClash(str,otherstr)){ + break; + } + } + if (checkerator.evaluateClashes()){ + var base_return = this.decrementNames(state,base); + this.registerAmbigToken(state,akey,token.id,base_return); + checkerator.seen.push(token.id); + if (debug){ + print(" ---> Evaluate: storing token config: "+base); + } + continue; + } + if (checkerator.maxAmbigLevel()){ + if ( ! state["citation"].opt["disambiguate-add-year-suffix"]){ + //this.registerAmbigToken(state,akey,token.id,base); + checkerator.mode1_counts = false; + checkerator.maxed_out_bases[token.id] = base; + if (debug){ + print(" ---> Max out: remembering token config for: "+token.id); + print(" ("+base["names"]+":"+base["givens"]+")"); + } + } else { + if (debug){ + print(" ---> Max out: NOT storing token config for: "+token.id); + print(" ("+base["names"]+":"+base["givens"]+")"); + } + } + checkerator.seen.push(token.id); + base = false; + continue; + } + if (debug){ + print(" ---> Incrementing"); + } + checkerator.incrementAmbigLevel(); + } + var ret = new Array(); + for each (id in checkerator.ids){ + if (id){ + ret.push(this.registry[id]); + } + } + for (i in checkerator.maxed_out_bases){ + this.registry[i].disambig = checkerator.maxed_out_bases[i]; + } + return ret; +}; +CSL.Factory.Registry.prototype.Checkerator = function(tokens,modes){ + this.seen = new Array(); + this.modes = modes; + this.mode = this.modes[0]; + this.tokens_length = tokens.length; + this.pos = 0; + this.clashes = 0; + this.maxvals = false; + this.base = false; + this.ids = new Array(); + this.maxed_out_bases = new Object(); + for each (token in tokens){ + this.ids.push(token.id); + } + this.lastclashes = -1; + this.namepos = 0; + this.modepos = 0; + this.mode1_counts = false; +}; +CSL.Factory.Registry.prototype.Checkerator.prototype.run = function(){ + if (this.seen.length < this.tokens_length){ + return true; + } + return false; +} +CSL.Factory.Registry.prototype.Checkerator.prototype.setMaxVals = function(maxvals){ + this.maxvals = maxvals; +}; +CSL.Factory.Registry.prototype.Checkerator.prototype.setMinVal = function(minval){ + this.minval = minval; +}; +CSL.Factory.Registry.prototype.Checkerator.prototype.setBase = function(base){ + this.base = base; + if (! this.mode1_counts){ + this.mode1_counts = new Array(); + for each (i in this.base["givens"]){ + this.mode1_counts.push(0); + } + } +}; +CSL.Factory.Registry.prototype.Checkerator.prototype.setMode = function(mode){ + this.mode = mode; +}; +CSL.Factory.Registry.prototype.Checkerator.prototype.checkForClash = function(str,otherstr){ + if (str == otherstr){ + if (this.mode == "names"){ + this.clashes += 1; + if (debug){ + print(" (mode 0 clash, returning true)"); + } + return true; + } + if (this.mode == "givens"){ + this.clashes += 1; + if (debug){ + print(" (mode 1 clash, returning false)"); + } + } + return false; + } +}; +CSL.Factory.Registry.prototype.Checkerator.prototype.evaluateClashes = function(){ + if (!this.maxvals.length){ + return false; + } + if (this.mode == "names"){ + if (this.clashes){ + this.lastclashes = this.clashes; + this.clashes = 0; + return false; + } else { + // cleared, so increment. also quash the id as done. + this.ids[this.pos] = false; + this.pos += 1; + this.lastclashes = this.clashes; + return true; + } + } + if (this.mode == "givens"){ + var ret = true; + if (debug){ + print(" ---> Comparing in mode 1: clashes="+this.clashes+"; lastclashes="+this.lastclashes); + } + var namepos = this.mode1_counts[this.modepos]; + if (this.clashes && this.clashes == this.lastclashes){ + if (debug){ + print(" ---> Applying mode 1 defaults: "+this.mode1_defaults); + } + if (this.mode1_defaults){ + var old = this.mode1_defaults[(namepos-1)]; + if (debug){ + print(" ---> Resetting to default: ("+old+")"); + } + this.base["givens"][this.modepos][(namepos-1)] = old; + } + ret = false; + } else if (this.clashes) { + if (debug){ + print(" ---> Expanding given name helped a little, retaining it"); + } + ret = false; + } else { // only non-clash should be possible + if (debug){ + print(" ---> No clashes, storing token config and going to next"); + } + this.mode1_counts = false; + ret = true; + } + this.lastclashes = this.clashes; + this.clashes = 0; + if (ret){ + this.ids[this.pos] = false; + } + return ret; + } +}; +CSL.Factory.Registry.prototype.Checkerator.prototype.maxAmbigLevel = function (){ + if (!this.maxvals.length){ + return true; + } + if (this.mode == "names"){ + //print(this.modepos+" : "+this.base[0].length+" : "+this.base[0][this.modepos]); + if (this.modepos == (this.base["names"].length-1) && this.base["names"][this.modepos] == this.maxvals[this.modepos]){ + if (this.modes.length == 2){ + this.mode = "givens"; + this.modepos = 0; + //this.pos = 0; + } else { + this.pos += 1; + return true; + } + } + } + if (this.mode == "givens"){ + if (this.modepos == (this.mode1_counts.length-1) && this.mode1_counts[this.modepos] == (this.maxvals[this.modepos])){ + if (debug){ + print("----- Item maxed out -----"); + } + if (this.modes.length == 2){ + this.mode = "givens"; + this.pos += 1; + } else { + this.pos += 1; + } + //this.ids[this.pos] = false; + return true; + } + } + return false; +}; +CSL.Factory.Registry.prototype.Checkerator.prototype.incrementAmbigLevel = function (){ + if (this.mode == "names"){ + var val = this.base["names"][this.modepos]; + if (val < this.maxvals[this.modepos]){ + this.base["names"][this.modepos] += 1; + } else if (this.modepos < (this.base["names"].length-1)){ + this.modepos +=1; + this.base["names"][this.modepos] = 0; + } + } + if (this.mode == "givens"){ + var val = (this.mode1_counts[this.modepos]); + if (val < this.maxvals[this.modepos]){ + this.mode1_counts[this.modepos] += 1; + this.mode1_defaults = this.base["givens"][this.modepos].slice(); + this.base["givens"][this.modepos][val] += 1; + if (debug){ + print(" ---> (A) Set expanded givenname param with base: "+this.base["givens"]); + } + } else if (this.modepos < (this.base["givens"].length-1)){ + this.modepos +=1; + this.base["givens"][this.modepos][0] += 1; + this.mode1_defaults = this.base["givens"][this.modepos].slice(); + if (debug){ + print(" ---> (B) Set expanded givenname param with base: "+this.base["givens"]); + } + } else { + this.mode = "names"; + this.pos += 1; + } + } +}; +CSL.Factory.Registry.prototype.registerAmbigToken = function (state,akey,id,ambig_config){ + if ( ! this.ambigs[akey]){ + this.ambigs[akey] = new Array(); + }; + var found = false; + for (var i in this.ambigs[akey]){ + if (this.ambigs[akey].indexOf(id) > -1){ + found = true; + } + } + if (!found){ + this.ambigs[akey].push(id); + } + this.registry[id].disambig = state.fun.clone_ambig_config(ambig_config); +}; +CSL.Factory.Registry.prototype.decrementNames = function(state,base){ + var base_return = state.fun.clone_ambig_config(base); + var do_me = false; + for (var i=(base_return["givens"].length-1); i > -1; i--){ + for (var j=(base_return["givens"][i].length-1); j > -1; j--){ + if (base_return["givens"][i][j] == 2){ + do_me = true; + } + } + } + if (do_me){ + for (var i=(base_return["givens"].length-1); i > -1; i--){ + for (var j=(base_return["givens"][i].length-1); j > -1; j--){ + if (base_return["givens"][i][j] == 2){ + i = -1; + break; + } + base_return["names"][i] += -1; + } + } + } + return base_return; +}; +CSL.Lib = {}; +// +// XXXXX Fix initialization of given name count. +// Should this be removed from the base? not sure. +// +CSL.Lib.Elements = {}; +CSL.Lib.Elements.style = new function(){ + this.build = build; + function build (state,target){ + if (this.tokentype == CSL.START){ + if (!state.build.lang){ + state.build.lang = "en"; + } + state.opt.lang = state.build.lang; + state.build.in_style = true; + state.build.lang = false; + state.opt.term = CSL.System.Retrieval.getLocaleObjects(state.opt.lang,state.opt.locale); + state.tmp.term_predecessor = false; + } else { + state.tmp.disambig_request = false; + state.build.in_style = false; + } + if (this.tokentype == CSL.START){ + var func = function(state,Item){ + if (state.tmp.disambig_request && ! state.tmp.disambig_override){ + state.tmp.disambig_settings = state.tmp.disambig_request; + } else if (state.registry.registry[Item.id] && ! state.tmp.disambig_override) { + state.tmp.disambig_request = state.registry.registry[Item.id].disambig; + state.tmp.disambig_settings = state.registry.registry[Item.id].disambig; + } else { + state.tmp.disambig_settings = new CSL.Factory.AmbigConfig(); + } + }; + state["init"].push(func); + var tracking_info_init = function(state,Item){ + state.tmp.names_used = new Array(); + state.tmp.nameset_counter = 0; + state.tmp.years_used = new Array(); + }; + state["init"].push(tracking_info_init); + var splice_init = function(state,Item) { + state.tmp.splice_delimiter = state[state.tmp.area].opt.delimiter; + }; + state["init"].push(splice_init); + var sort_keys_init = function(state,Item) { + state["bibliography_sort"].keys = new Array(); + state["citation_sort"].keys = new Array(); + }; + state["init"].push(sort_keys_init); + }; + if (this.tokentype == CSL.END){ + var set_splice = function(state,Item){ + // + // set the inter-cite join delimiter + // here. + if (state.tmp.last_suffix_used && state.tmp.last_suffix_used.match(/.*[-.,;:]$/)){ + state.tmp.splice_delimiter = " "; + } else if (state.tmp.prefix.value() && state.tmp.prefix.value().match(/^[,,:;a-z].*/)){ + state.tmp.splice_delimiter = " "; + } else if (state.tmp.last_suffix_used || state.tmp.prefix.value()){ + // + // forcing the delimiter back to normal if a + // suffix or prefix touch the join, even if + // a year-suffix is the only output. + state.tmp.splice_delimiter = state[state.tmp.area].opt.delimiter; + } else { + // XXXX year-suffix must have been used for special + // XXXX delimiter to be invoked here. + } + }; + state["stop"].push(set_splice); + var set_lastvals = function(state,Item){ + state.tmp.last_suffix_used = state.tmp.suffix.value(); + state.tmp.last_years_used = state.tmp.years_used.slice(); + state.tmp.last_names_used = state.tmp.names_used.slice(); + }; + state["stop"].push(set_lastvals); + var func = function(state,Item){ + state.tmp.disambig_request = false; + }; + state["stop"].push(func); + } + } +}; +CSL.Lib.Elements.info = new function(){ + this.build = build; + function build (state,target){ + if (this.tokentype == CSL.START){ + state.build.skip = "info"; + } else { + state.build.skip = false; + } + }; +}; +CSL.Lib.Elements.text = new function(){ + this.build = build; + function build (state,target){ + // + // CSL permits macros to be called before they + // are declared. We file a placeholder token unless we are + // in the layout area, and when in the layout area we scan + // any inserted macros for nested macro calls, and explode + // them. + if (state.build.postponed_macro){ + // + // XXXX Could catch undeclared macros here. + // + if ( ! state.build.layout_flag && ! state.build.sort_flag){ + // + // Fudge it with a placeholder if we're not yet + // inside the layout area. + this.postponed_macro = state.build.postponed_macro; + target.push(this); + } else { + // + // tag this token with the name of the postponed macro + this.postponed_macro = state.build.postponed_macro; + // + // push an implict group token with the strings and + // decorations of the invoking text tag + var start_token = new CSL.Factory.Token("group",CSL.START); + for (i in this.strings){ + start_token.strings[i] = this.strings[i]; + } + start_token.decorations = this.decorations; + var newoutput = function(state,Item){ + state.output.startTag("group",this); + //state.tmp.decorations.push(this.decorations); + }; + start_token["execs"].push(newoutput); + target.push(start_token); + // + // Special handling for text macros inside a substitute + // environment. + if (state.build.names_substituting){ + // + // A text macro inside a substitute environment is + // treated as a special conditional. + var choose_start = new CSL.Factory.Token("choose",CSL.START); + target.push(choose_start); + var if_start = new CSL.Factory.Token("if",CSL.START); + // + // Here's the Clever Part. + // Set a test of the shadow if token to skip this + // macro if we have acquired a name value. + var check_for_variable = function(state,Item){ + if (state.tmp.value){ + return true; + } + return false; + }; + if_start.tests.push(check_for_variable); + // + // this is cut-and-paste of the "any" evaluator + // function, from Attributes. These functions + // should be defined in a namespace for reuse. + var evaluator = function(state,Item){ + var res = this.fail; + state.tmp.jump.replace("fail"); + for each (var func in this.tests){ + if (func.call(this,state,Item)){ + res = this.succeed; + state.tmp.jump.replace("succeed"); + break; + } + } + return res; + }; + if_start.evaluator = evaluator; + target.push(if_start); + var macro = CSL.Factory.expandMacro.call(state,this); + for each (var t in macro){ + target.push(t); + } + var if_end = new CSL.Factory.Token("if",CSL.END); + target.push(if_end); + var choose_end = new CSL.Factory.Token("choose",CSL.END); + target.push(choose_end); + } else { + var macro = CSL.Factory.expandMacro.call(state,this); + for each (var t in macro){ + target.push(t); + } + } + var end_token = new CSL.Factory.Token("group",CSL.END); + var mergeoutput = function(state,Item){ + // + // rendering happens inside the + // merge method, by applying decorations to + // each token to be merged. + state.output.endTag(); + }; + end_token["execs"].push(mergeoutput); + target.push(end_token); + state.build.names_substituting = false; + } + state.build.postponed_macro = false; + } else { + // ... + // + // Do non-macro stuff + var variable = this.variables[0]; + if ("citation-number" == variable || "year-suffix" == variable){ + // + // citation-number and year-suffix are super special, + // because they are rangeables, and require a completely + // different set of formatting parameters on the output + // queue. + if (variable == "citation-number"){ + this.strings.is_rangeable = true; + var func = function(state,Item){ + var id = Item["id"]; + if (!state.tmp.force_subsequent){ + var num = state.registry.registry[id].seq; + // + // DO SOMETHING USEFUL HERE + // + var number = new CSL.Output.Number(num,this); + state.output.append(number,"literal"); + } + }; + this["execs"].push(func); + } else if (variable == "year-suffix"){ + var func = function(state,Item){ + if (state.registry.registry[Item.id] && state.registry.registry[Item.id].disambig[2]){ + state.tmp.delimiter.replace(""); + state.output.append(state.registry.registry[Item.id].disambig[2],this); + // + // don't ask :) + // obviously the variable naming scheme needs + // a little touching up + var firstoutput = state.tmp.term_sibling.mystack.indexOf(true) == -1; + var specialdelimiter = state[state.tmp.area].opt["year-suffix-delimiter"]; + if (firstoutput && specialdelimiter && !state.tmp.sort_key_flag){ + state.tmp.splice_delimiter = state[state.tmp.area].opt["year-suffix-delimiter"]; + } + } + }; + this["execs"].push(func); + } + } else { + if (state.build.term){ + var term = state.build.term; + var form = "long"; + var plural = 0; + if (state.build.form){ + form = state.build.form; + } + if (state.build.plural){ + plural = state.build.plural; + } + term = state.opt.term[term][form][plural]; + var printterm = function(state,Item){ + // capitalize the first letter of a term, if it is the + // first thing rendered in a citation (or if it is + // being rendered immediately after terminal punctuation, + // I guess, actually). + if (!state.tmp.term_predecessor){ + //print("Capitalize"); + term = CSL.Output.Formatters.capitalize_first(term); + state.tmp.term_predecessor = false; + }; + state.output.append(term,this); + }; + this["execs"].push(printterm); + state.build.term = false; + state.build.form = false; + state.build.plural = false; + } else if (variable){ + var func = function(state,Item){ + if (this.variables.length){ + state.fun.mark_output(state,Item[variable]); + state.output.append(Item[variable],this); + //state.tmp.value.push(Item[variable]); + } + }; + this["execs"].push(func); + } else if (this.strings.value){ + var func = function(state,Item){ + state.output.append(this.strings.value,this); + }; + this["execs"].push(func); + } else { + var weird_output_function = function(state,Item){ + if (state.tmp.value.length){ + print("Weird output pattern. Can this be revised?"); + for each (var val in state.tmp.value){ + state.output.append(val,this); + } + state.tmp.value = new Array(); + } + }; + this["execs"].push(weird_output_function); + } + } + target.push(this); + }; + } +}; +CSL.Lib.Elements.macro = new function(){ + this.build = build; + function build (state,target){ + if (this.tokentype == CSL.START){ + state.build.name = this.strings.name; + var bufferlist = new Array(); + state.build.children.push(bufferlist); + } else { + // + // catch repeated declarations of the same macro name + if (state.build.macro[state.build.name]){ + throw "CSL processor error: repeated declaration of macro \""+state.build.name+"\""; + } + // + // is this slice really needed? + state.build.macro[state.build.name] = target.slice(); + state.build.name = false; + state.build.children = new Array();; + } + } +}; +CSL.Lib.Elements.locale = new function(){ + this.build = build; + function build(state,target){ + if (this.tokentype == CSL.START){ + if (state.opt.lang && state.build.lang != state.opt.lang){ + state.build.skip = true; + } else { + state.build.skip = false; + } + } + } +}; +CSL.Lib.Elements.terms = new function(){ + this.build = build; + function build(state,target){ + } +}; +CSL.Lib.Elements.term = new function(){ + this.build = build; + function build (state,target){ + if (this.tokentype == CSL.START){ + var bufferlist = new Array(); + state.build.children.push(bufferlist); + state.build.name = this.strings.name; + state.build.form = this.strings.form; + } else { + if (state.build.text){ + var single = new CSL.Factory.Token("single",CSL.SINGLETON); + var multiple = new CSL.Factory.Token("multiple",CSL.SINGLETON); + target.push(single); + target.push(multiple); + for (i in target){ + target[i]["string"] = state.build.text; + } + state.build.text = false; + } + // set strings from throwaway tokens to term object + var termstrings = new Array(); + // target should be pointing at the state.build.children + // array, set by the start tag above + for (i in target){ + termstrings.push(target[i].string); + } + // initialize object for this term + if (!state.opt.term[state.build.name]){ + state.opt.term[state.build.name] = new Object(); + } + // + // long writes to long and any unused form key. + // + // short writes to short and to symbol if it is unused + // + // verb writes to verb and to verb-short if it is unused + // + // symbol and verb-short write only to themselves + if (!state.build.form){ + state.build.form = "long"; + } + var keywrites = new Object(); + keywrites["long"] = ["verb-short","symbol","verb","short","long"]; + keywrites["short"] = ["symbol"]; + keywrites["verb"] = ["verb-short"]; + keywrites["symbol"] = []; + keywrites["verb-short"] = []; + // forced write + state.opt.term[state.build.name][state.build.form] = termstrings; + if ( !state.build.in_style ){ + // shy write, performed only when external locale + // is loaded. + for each (var key in keywrites[state.build.form]){ + if (!state.opt.term[state.build.name][key]){ + state.opt.term[state.build.name][key] = termstrings; + } + } + } + state.build.name = false; + state.build.form = false; + state.build.children = new Array(); + } + } +}; +CSL.Lib.Elements.single = new function(){ + this.build = build; + function build(state,target){ + if (this.tokentype == CSL.END){ + this["string"] = state.build.text; + this["key"] = state.build.name; + state.build.text = false; + target.push(this); + } + } +}; +CSL.Lib.Elements.multiple = new function(){ + this.build = build; + function build(state,target){ + if (this.tokentype == CSL.END){ + this["string"] = state.build.text; + this["key"] = state.build.name; + state.build.text = false; + target.push(this); + } + } +}; +CSL.Lib.Elements.group = new function(){ + this.build = build; + function build (state,target){ + if (this.tokentype == CSL.START){ + var newoutput = function(state,Item){ + state.output.startTag("group",this); + }; + // + // Paranoia. Assure that this init function is the first executed. + var execs = new Array(); + execs.push(newoutput); + this.execs = execs.concat(this.execs); + var fieldcontentflag = function(state,Item){ + state.tmp.term_sibling.push( undefined, CSL.LITERAL ); + }; + this["execs"].push(fieldcontentflag); + } else { + var quashnonfields = function(state,Item){ + var flag = state.tmp.term_sibling.value(); + if (false == flag){ + state.output.clearlevel(); + } + state.tmp.term_sibling.pop(); + }; + this["execs"].push(quashnonfields); + var mergeoutput = function(state,Item){ + // + // rendering happens inside the + // merge method, by applying decorations to + // each token to be merged. + state.output.endTag(); + }; + this["execs"].push(mergeoutput); + } + target.push(this); + } +}; +CSL.Lib.Elements.citation = new function(){ + this.build = build; + function build (state,target){ + if (this.tokentype == CSL.START) { + state.build.area_return = state.build.area; + state.build.area = "citation"; + } + if (this.tokentype == CSL.END) { + state.build.area = state.build.area_return; + } + } +}; +CSL.Lib.Elements.choose = new function(){ + this.build = build; + this.configure = configure; + function build (state,target){ + if (this.tokentype == CSL.START){ + var func = function(state,Item){ //open condition + state.tmp.jump.push(undefined, CSL.LITERAL); + }; + } + if (this.tokentype == CSL.END){ + var func = function(state,Item){ //close condition + state.tmp.jump.pop(); + }; + } + this["execs"].push(func); + target.push(this); + } + function configure(state,pos){ + if (this.tokentype == CSL.END){ + state.configure["fail"].push((pos+1)); + state.configure["succeed"].push((pos+1)); + } else { + state.configure["fail"].pop(); + state.configure["succeed"].pop(); + } + } +}; +CSL.Lib.Elements["if"] = new function(){ + this.build = build; + this.configure = configure; + function build (state,target){ + if (this.tokentype == CSL.START){ + if (! this.evaluator){ + // + // cut and paste of "any" + this.evaluator = function(state,Item){ + var res = this.fail; + state.tmp.jump.replace("fail"); + for each (var func in this.tests){ + if (func.call(this,state,Item)){ + res = this.succeed; + state.tmp.jump.replace("succeed"); + break; + } + } + return res; + }; + }; + } + if (this.tokentype == CSL.END){ + var closingjump = function(state,Item){ + var next = this[state.tmp.jump.value()]; + return next; + }; + this["execs"].push(closingjump); + }; + target.push(this); + } + function configure(state,pos){ + if (this.tokentype == CSL.START){ + // jump index on failure + this["fail"] = state.configure["fail"][(state.configure["fail"].length-1)]; + this["succeed"] = this["next"]; + } else { + // jump index on success + this["succeed"] = state.configure["succeed"][(state.configure["succeed"].length-1)]; + this["fail"] = this["next"]; + } + } +}; +CSL.Lib.Elements["else-if"] = new function(){ + this.build = build; + this.configure = configure; + function build (state,target){ + if (this.tokentype == CSL.START){ + if (! this.evaluator){ + // + // cut and paste of "any" + this.evaluator = function(state,Item){ + var res = this.fail; + state.tmp.jump.replace("fail"); + for each (var func in this.tests){ + if (func.call(this,state,Item)){ + res = this.succeed; + state.tmp.jump.replace("succeed"); + break; + } + } + return res; + }; + }; + } + if (this.tokentype == CSL.END){ + var closingjump = function(state,Item){ + var next = this[state.tmp.jump.value()]; + return next; + }; + this["execs"].push(closingjump); + }; + target.push(this); + } + function configure(state,pos){ + if (this.tokentype == CSL.START){ + // jump index on failure + this["fail"] = state.configure["fail"][(state.configure["fail"].length-1)]; + this["succeed"] = this["next"]; + state.configure["fail"][(state.configure["fail"].length-1)] = pos; + } else { + // jump index on success + this["succeed"] = state.configure["succeed"][(state.configure["succeed"].length-1)]; + this["fail"] = this["next"]; + } + } +}; +CSL.Lib.Elements["else"] = new function(){ + this.build = build; + this.configure = configure; + function build (state,target){ + target.push(this); + } + function configure(state,pos){ + if (this.tokentype == CSL.START){ + state.configure["fail"][(state.configure["fail"].length-1)] = pos; + } + } +}; +CSL.Lib.Elements.name = new function(){ + this.build = build; + function build(state,target){ + state.build.form = this.strings.form; + state.build.name_flag = true; + var func = function(state,Item){ + state.output.addToken("name",false,this); + }; + this["execs"].push(func); + var set_initialize_with = function(state,Item){ + state.tmp["initialize-with"] = this.strings["initialize-with"]; + }; + this["execs"].push(set_initialize_with); + target.push(this); + }; +}; +CSL.Lib.Elements["name-part"] = new function(){ + this.build = build; + function build(state,target){ + // XXXXX problem. can't be global. don't want to remint + // for every rendering. somehow get tokens stored on + // closing names tag static. always safe, b/c + // no conditional branching inside names. + // same treatment for etal styling element. + var set_namepart_format = function(state,Item){ + state.output.addToken(state.tmp.namepart_type,false,this); + }; + this["execs"].push(set_namepart_format); + target.push(this); + }; +}; +CSL.Lib.Elements.label = new function(){ + this.build = build; + function build(state,target){ + if (state.build.name_flag){ + this.strings.label_position = CSL.AFTER; + } else { + this.strings.label_position = CSL.BEFORE; + } + var set_label_info = function(state,Item){ + if (!this.strings.form){ + this.strings.form = "long"; + } + state.output.addToken("label",false,this); + }; + this["execs"].push(set_label_info); + target.push(this); + }; +}; +CSL.Lib.Elements.substitute = new function(){ + this.build = build; + function build(state,target){ + if (this.tokentype == CSL.START){ + state.build.names_substituting = true; + var declare_thyself = function(state,Item){ + state.tmp.names_substituting = true; + }; + this["execs"].push(declare_thyself); + }; + target.push(this); + }; +}; +CSL.Lib.Elements["et-al"] = new function(){ + this.build = build; + function build(state,target){ + var set_et_al_format = function(state,Item){ + state.output.addToken("etal",false,this); + }; + this["execs"].push(set_et_al_format); + target.push(this); + }; +}; +CSL.Lib.Elements.layout = new function(){ + this.build = build; + function build(state,target){ + if (this.tokentype == CSL.START){ + state.build.layout_flag = true; + var set_opt_delimiter = function(state,Item){ + // just in case + state.tmp.sort_key_flag = false; + state[state.tmp.area].opt.delimiter = ""; + if (this.strings.delimiter){ + state[state.tmp.area].opt.delimiter = this.strings.delimiter; + }; + }; + this["execs"].push(set_opt_delimiter); + var reset_nameset_counter = function(state,Item){ + state.tmp.nameset_counter = 0; + }; + this["execs"].push(reset_nameset_counter); + var declare_thyself = function(state,Item){ + // + // This is not very pretty. + // + //state.tmp.delimiter.mystack[0] = this.strings.delimiter; + //state.tmp.prefix.mystack[0] = this.strings.prefix; + //state.tmp.suffix.mystack[0] = this.strings.suffix; + //state.tmp.tokenstore["layout"] = new CSL.Factory.Token("layout"); + state[state.tmp.area].opt.layout_prefix = this.strings.prefix; + state[state.tmp.area].opt.layout_suffix = this.strings.suffix; + state.output.openLevel("empty"); + }; + this["execs"].push(declare_thyself); + }; + if (this.tokentype == CSL.END){ + state.build.layout_flag = false; + var mergeoutput = function(state,Item){ + state.output.closeLevel(); + state.tmp.name_quash = new Object(); + }; + this["execs"].push(mergeoutput); + } + target.push(this); + }; +}; +CSL.Lib.Elements.number = new function(){ + this.build = build; + function build(state,target){ + target.push(this); + }; +}; +CSL.Lib.Elements.date = new function(){ + this.build = build; + function build(state,target){ + if (this.tokentype == CSL.START){ + var set_value = function(state,Item){ + state.tmp.value.push(Item[this.variables[0]]); + }; + this["execs"].push(set_value); + var newoutput = function(state,Item){ + state.output.startTag("date",this); + }; + this["execs"].push(newoutput); + } else if (this.tokentype == CSL.END){ + var mergeoutput = function(state,Item){ + state.output.endTag(); + }; + this["execs"].push(mergeoutput); + } + target.push(this); + }; +}; +CSL.Lib.Elements["date-part"] = new function(){ + this.build = build; + function build(state,target){ + var value = ""; + if (!this.strings.form){ + this.strings.form = "long"; + } + var render_date_part = function(state,Item){ + for each (var val in state.tmp.value){ + value = val[this.strings.name]; + break; + }; + var real = !state.tmp.suppress_decorations; + var invoked = state[state.tmp.area].opt.collapse == "year-suffix"; + var precondition = state[state.tmp.area].opt["disambiguate-add-year-suffix"]; + if (real && precondition && invoked){ + state.tmp.years_used.push(value); + var known_year = state.tmp.last_years_used.length >= state.tmp.years_used.length; + if (known_year){ + if (state.tmp.last_years_used[(state.tmp.years_used.length-1)] == value){ + value = false; + } + } + } + if (value){ + if (this.strings.form){ + value = CSL.Util.Dates[this.strings.name][this.strings.form](state,value); + } + //state.output.startTag(this.strings.name,this); + state.output.append(value,this); + //state.output.endTag(); + }; + state.tmp.value = new Array(); + }; + this["execs"].push(render_date_part); + target.push(this); + }; +}; +CSL.Lib.Elements.option = new function(){ + this.build = build; + function build(state,target){ + if (this.strings.name == "collapse"){ + // only one collapse value will be honoured. + if (this.strings.value){ + state[state.tmp.area].opt.collapse = this.strings.value; + } + } + if (CSL.ET_AL_NAMES.indexOf(this.strings.name) > -1){ + if (this.strings.value){ + state[state.tmp.area].opt[this.strings.name] = parseInt(this.strings.value, 10); + } + } + if (CSL.DISAMBIGUATE_OPTIONS.indexOf(this.strings.name) > -1){ + state[state.tmp.area].opt[this.strings.name] = true; + } + if ("year-suffix-delimiter" == this.strings.name){ + state[state.tmp.area].opt["year-suffix-delimiter"] = this.strings.value; + } + target.push(this); + }; +}; +CSL.Lib.Elements.bibliography = new function(){ + this.build = build; + function build(state,target){ + if (this.tokentype == CSL.START){ + state.build.area_return = state.build.area; + state.build.area = "bibliography"; + //var init_sort_keys = function(state,Item){ + // state.tmp.sort_keys = new Array(); + //}; + //this["execs"].push(init_sort_keys); + } + if (this.tokentype == CSL.END){ + state.build.area = state.build.area_return; + } + target.push(this); + }; +}; +CSL.Lib.Elements.sort = new function(){ + this.build = build; + function build(state,target){ + if (this.tokentype == CSL.START){ + state.build.sort_flag = true; + state.build.area_return = state.build.area; + state.build.area = state.build.area+"_sort"; + } + if (this.tokentype == CSL.END){ + state.build.area = state.build.area_return; + state.build.sort_flag = false; + } + }; +}; +CSL.Lib.Elements.key = new function(){ + this.build = build; + function build(state,target){ + var start_key = new CSL.Factory.Token("key",CSL.START); + start_key.strings["et-al-min"] = this.strings["et-al-min"]; + start_key.strings["et-al-use-first"] = this.strings["et-al-use-first"]; + var sort_direction = new Array(); + if (this.strings.sort_direction == CSL.DESCENDING){ + sort_direction.push(1); + sort_direction.push(-1); + } else { + sort_direction.push(-1); + sort_direction.push(1); + } + state[state.build.area].opt.sort_directions.push(sort_direction); + var et_al_init = function(state,Item){ + // + // should default to the area value, with these as override. + // be sure that the area-level value is set correctly, then + // do this up. lots of inheritance, so lots of explicit + // conditions, but it's all very systematic and boring. + // + state.tmp.sort_key_flag = true; + if (this.strings["et-al-min"]){ + state.tmp["et-al-min"] = this.strings["et-al-min"]; + } + if (this.strings["et-al-use-first"]){ + state.tmp["et-al-use-first"] = this.strings["et-al-use-first"]; + } + }; + start_key["execs"].push(et_al_init); + target.push(start_key); + // + // ops to initialize the key's output structures + if (state.build.key_is_variable){ + state.build.key_is_variable = false; + var single_text = new CSL.Factory.Token("text",CSL.SINGLETON); + single_text["execs"] = this["execs"].slice(); + var output_variables = function(state,Item){ + for each(var val in state.tmp.value){ + if (val == "citation-number"){ + state.output.append(state.registry.registry[Item["id"]].seq.toString(),"empty"); + } else { + state.output.append(val,"empty"); + } + } + }; + single_text["execs"].push(output_variables); + target.push(single_text); + } else { + // + // if it's not a variable, it's a macro + var token = new CSL.Factory.Token("text",CSL.SINGLETON); + token.postponed_macro = state.build.postponed_macro; + var macro = CSL.Factory.expandMacro.call(state,token); + for each (var t in macro){ + target.push(t); + } + state.build.postponed_macro = false; + } + // + // ops to output the key string result to an array go + // on the closing "key" tag before it is pushed. + // Do not close the level. + var end_key = new CSL.Factory.Token("key",CSL.END); + var store_key_for_use = function(state,Item){ + var keystring = state.output.string(state,state.output.queue); + if (false){ + print("keystring: "+keystring); + } + state[state.tmp.area].keys.push(keystring); + state.tmp.value = new Array(); + }; + end_key["execs"].push(store_key_for_use); + var reset_key_params = function(state,Item){ + state.tmp.name_quash = new Object(); + state.tmp["et-al-min"] = false; + state.tmp["et-al-use-first"] = false; + state.tmp.sort_key_flag = false; + }; + end_key["execs"].push(reset_key_params); + target.push(end_key); + }; +}; +CSL.Lib.Elements.names = new function(){ + this.build = build; + function build(state,target){ + if (this.tokentype == CSL.START || this.tokentype == CSL.SINGLETON){ + var init_names = function(state,Item){ + if (state.tmp.value.length == 0){ + for each (var variable in this.variables){ + // + // If the item has been marked for quashing, skip it. + if (Item[variable] && ! state.tmp.name_quash[variable]){ + state.fun.mark_output(state,Item[variable]); + state.tmp.names_max.push(Item[variable].length); + state.tmp.value.push({"type":variable,"names":Item[variable]}); + // saving relevant names separately, for reference + // in splice collapse + state.tmp.names_used.push(state.tmp.value.slice()); + } + }; + } + }; + this["execs"].push(init_names); + }; + if (this.tokentype == CSL.START){ + state.build.names_flag = true; + var set_et_al_params = function(state,Item){ + state.output.startTag("names",this); + // + // No value or zero means a first reference, + // anything else is a subsequent reference. + if (Item.position || state.tmp.force_subsequent){ + if (! state.tmp["et-al-min"]){ + if (state[state.tmp.area].opt["et-al-subsequent-min"]){ + state.tmp["et-al-min"] = state[state.tmp.area].opt["et-al-subsequent-min"]; + } else { + state.tmp["et-al-min"] = state[state.tmp.area].opt["et-al-min"]; + } + } + if (! state.tmp["et-al-use-first"]){ + if (state[state.tmp.area].opt["et-al-subsequent-use-first"]){ + state.tmp["et-al-use-first"] = state[state.tmp.area].opt["et-al-subsequent-use-first"]; + } else { + state.tmp["et-al-use-first"] = state[state.tmp.area].opt["et-al-use-first"]; + } + } + } else { + if (! state.tmp["et-al-min"]){ + state.tmp["et-al-min"] = state[state.tmp.area].opt["et-al-min"]; + } + if (! state.tmp["et-al-use-first"]){ + state.tmp["et-al-use-first"] = state[state.tmp.area].opt["et-al-use-first"]; + } + } + }; + this["execs"].push(set_et_al_params); + }; + if (this.tokentype == CSL.END){ + var handle_names = function(state,Item){ + var namesets = new Array(); + var common_term = state.fun.get_common_term(state,state.tmp.value); + if (common_term){ + namesets = state.tmp.value.slice(0,1); + } else { + namesets = state.tmp.value; + } + var local_count = 0; + var nameset = new Object(); + state.output.addToken("space"," "); + state.output.addToken("sortsep",state.output.getToken("name").strings["sort-separator"]); + if (!state.output.getToken("etal")){ + state.output.addToken("etal-join",", "); + state.output.addToken("etal"); + } else { + state.output.addToken("etal-join",""); + } + if (!state.output.getToken("label")){ + state.output.addToken("label"); + } + if (!state.output.getToken("etal").strings.et_al_term){ + state.output.getToken("etal").strings.et_al_term = state.opt.term["et-al"]["long"][0]; + } + state.output.addToken("commasep",", "); + for each (namepart in ["secondary-key","primary-key","prefix","suffix"]){ + if (!state.output.getToken(namepart)){ + state.output.addToken(namepart); + } + } + for (var namesetIndex in namesets){ + nameset = namesets[namesetIndex]; + if (!state.tmp.suppress_decorations && (state[state.tmp.area].opt.collapse == "year" || state[state.tmp.area].opt.collapse == "year-suffix")){ + if (state.tmp.last_names_used.length == state.tmp.names_used.length){ + var lastones = state.tmp.last_names_used[state.tmp.nameset_counter]; + var currentones = state.tmp.names_used[state.tmp.nameset_counter]; + var compset = currentones.concat(lastones); + if (state.fun.get_common_term(state,compset)){ + continue; + } + } + } + if (!state.tmp.disambig_request){ + state.tmp.disambig_settings["givens"][state.tmp.nameset_counter] = new Array(); + } + // + // Here is where we maybe truncate the list of + // names, to satisfy the et-al constraints. + var display_names = nameset.names.slice(); + var sane = state.tmp["et-al-min"] >= state.tmp["et-al-use-first"]; + // + // if there is anything on name request, we assume that + // it was configured correctly via state.names_request + // by the function calling the renderer. + var discretionary_names_length = state.tmp["et-al-min"]; + // + // if rendering for display, do not honor a disambig_request + // to set names length below et-al-use-first + // + if (state.tmp.suppress_decorations){ + if (state.tmp.disambig_request){ + discretionary_names_length = state.tmp.disambig_request["names"][state.tmp.nameset_counter]; + } else if (display_names.length >= state.tmp["et-al-min"]){ + discretionary_names_length = state.tmp["et-al-use-first"]; + } + } else { + if (state.tmp.disambig_request && state.tmp["et-al-use-first"] < state.tmp.disambig_request["names"][state.tmp.nameset_counter]){ + discretionary_names_length = state.tmp.disambig_request["names"][state.tmp.nameset_counter]; + } else if (display_names.length >= state.tmp["et-al-min"]){ + discretionary_names_length = state.tmp["et-al-use-first"]; + } + } + var overlength = display_names.length > discretionary_names_length; + var et_al = false; + var and_term = false; + if (sane && overlength){ + if (! state.tmp.sort_key_flag){ + et_al = state.output.getToken("etal").strings.et_al_term; + } + display_names = display_names.slice(0,discretionary_names_length); + } else { + if (state.output.getToken("name").strings["and"] && ! state.tmp.sort_key_flag && display_names.length > 1){ + and_term = state.output.getToken("name").strings["and"]; + } + } + state.tmp.disambig_settings["names"][state.tmp.nameset_counter] = display_names.length; + local_count += display_names.length; + // + // "name" is the format for the outermost nesting of a nameset + // "inner" is a format consisting only of a delimiter, used for + // joining all but the last name in the set together. + var delim = state.output.getToken("name").strings.delimiter; + state.output.addToken("inner",delim); + //state.tmp.tokenstore["and"] = new CSL.Factory.Token("and"); + if (and_term){ + state.output.formats.value()["name"].strings.delimiter = and_term; + } + for (var i in nameset.names){ + // + // set the display mode default for givennames if required + if (state.tmp.disambig_request){ + // + // fix a request for initials that makes no sense. + // can't do this in disambig, because the availability + // of initials is not a global parameter. + var val = state.tmp.disambig_settings["givens"][state.tmp.nameset_counter][i]; + if (val == 1 && ! state.tmp["initialize-with"]){ + val = 2; + } + var param = val; + } else { + var param = 2; + if (state.output.getToken("name").strings.form == "short"){ + param = 0; + } else if ("string" == typeof state.tmp["initialize-with"]){ + param = 1; + } + } + state.tmp.disambig_settings["givens"][state.tmp.nameset_counter][i] = param; + } + // + // configure label if poss + var label = false; + if (state.output.getToken("label").strings.label_position){ + var term; + if (common_term){ + term = common_term; + } else { + term = state.opt.term[nameset.type]; + } + if (nameset.names.length > 1){ + label = term[state.output.getToken("label").strings.form][1]; + } else { + label = term[state.output.getToken("label").strings.form][0]; + } + }; + // + // Nesting levels are opened to control joins with + // content at the end of the names block + // + // Gotcha. Don't want to use startTag here, it pushes + // a fresh format token namespace, and we lose our pointer.] + // Use openLevel (and possibly addToken) instead. + state.output.openLevel("empty"); // for term join + if (label && state.output.getToken("label").strings.label_position == CSL.BEFORE){ + state.output.append(label,"label"); + } + state.output.openLevel("etal-join"); // join for etal + CSL.Util.Names.outputNames(state,display_names); + if (et_al){ + state.output.append(et_al,"etal"); + } + state.output.closeLevel(); // etal + if (label && state.tmp.name_label_position != CSL.BEFORE){ + state.output.append(label,"label"); + } + state.output.closeLevel(); // term + state.tmp.nameset_counter += 1; + }; + if (state.output.getToken("name").strings.form == "count"){ + state.output.clearlevel(); + state.output.append(local_count.toString()); + state.tmp["et-al-min"] = false; + state.tmp["et-al-use-first"] = false; + } + }; + this["execs"].push(handle_names); + }; + if (this.tokentype == CSL.END && state.build.form == "count" && false){ + state.build.form = false; + var output_name_count = function(state,Item){ + var name_count = 0; + for each (var v in this.variables){ + if(Item[v] && Item[v].length){ + name_count += Item[v].length; + } + } + state.output.append(name_count.toString()); + }; + this["execs"].push(output_name_count); + }; + if (this.tokentype == CSL.END){ + var unsets = function(state,Item){ + state.fun.names_reinit(state,Item); + state.output.endTag(); // names + }; + this["execs"].push(unsets); + state.build.names_flag = false; + state.build.name_flag = false; + } + target.push(this); + } +};CSL.Lib.Attributes = {}; +CSL.Lib.Attributes["@value"] = function(state,arg){ + this.strings.value = arg; +}; +CSL.Lib.Attributes["@name"] = function(state,arg){ + this.strings.name = arg; +}; +CSL.Lib.Attributes["@form"] = function(state,arg){ + this.strings.form = arg; +}; +CSL.Lib.Attributes["@macro"] = function(state,arg){ + state.build.postponed_macro = arg; +}; +CSL.Lib.Attributes["@term"] = function(state,arg){ + if (this.name == "et-al"){ + if (state.opt.term[arg]){ + this.strings.et_al_term = state.opt.term[arg]["long"][0]; + } else { + this.strings.et_al_term = arg; + } + } + state.build.term = arg; +}; +CSL.Lib.Attributes["@xmlns"] = function(state,arg){}; +CSL.Lib.Attributes["@lang"] = function(state,arg){ + if (arg){ + state.build.lang = arg; + } +}; +CSL.Lib.Attributes["@class"] = function(state,arg){ + state.opt["class"] = arg; +}; +CSL.Lib.Attributes["@type"] = function(state,arg){ + if (this.name == "name-part") { + // + // Note that there will be multiple name-part items, + // and they all need to be collected before doing anything. + // So this must be picked up when the + // element is processed, and used as a key on an + // object holding the formatting attribute functions. + state.tmp.namepart_type = arg; + } else { + var func = function(state,Item){ + if(Item.type == arg){ + return true; + } + return false; + }; + this["tests"].push(func); + } +}; +CSL.Lib.Attributes["@variable"] = function(state,arg){ + if (this.tokentype == CSL.SINGLETON){ + if (this.name == "text"){ + this.variables = arg.split(/\s+/); + }; + if (this.name == "key"){ + // + // this one is truly wild. the key element + // will be recast as a start and end tag, so this + // function will be copied across to the TEXT + // tag that the key tags will enclose. the text + // of the variable will render to an output queue + // that is dedicated to producing sort keys. + state.build.key_is_variable = true; + var func = function(state,Item){ + if ("citation-number" == arg){ + state.tmp.value.push("citation-number"); + } else { + state.tmp.value.push(Item[arg]); + } + }; + this["execs"].push(func); + }; + if (this.name == "label"){ + // + // labels treat the "locator" variable specially. + print("Note to self: do something for variable= on label elements."); + } + }; + if (this.tokentype == CSL.START){ + if (["if","else-if"].indexOf(this.name) > -1){ + var variables = arg.split(/\s+/); + for each (var variable in variables){ + var func = function(state,Item){ + if (Item[variable]){ + return true; + } + return false; + }; + this["tests"].push(func); + }; + }; + if (this.name == "date"){ + var func = function(state,Item){ + state.fun.mark_output(state,Item[arg]); + state.tmp.value.push(Item[arg]); + }; + this["execs"].push(func); + }; + }; + if (this.name == "names" && (this.tokentype == CSL.START || this.tokentype == CSL.SINGLETON)){ + if (arg){ + this.variables = arg.split(/\s+/); + }; + }; +}; +CSL.Lib.Attributes["@and"] = function(state,arg){ + if ("symbol" == arg){ + this.strings["and"] = " & "; + } else { + var and = state.opt.term["and"]["long"][0]; + if (and.match(/.*[a-zA-Z\u0400-\u052f].*/)){ + and = ", "+and+" "; + } + this.strings["and"] = and; + } +}; +CSL.Lib.Attributes["@initialize-with"] = function(state,arg){ + this.strings["initialize-with"] = arg; +}; +CSL.Lib.Attributes["@suffix"] = function(state,arg){ + this.strings.suffix = arg; +}; +CSL.Lib.Attributes["@prefix"] = function(state,arg){ + this.strings.prefix = arg; +}; +CSL.Lib.Attributes["@delimiter"] = function(state,arg){ + this.strings.delimiter = arg; +}; +CSL.Lib.Attributes["@match"] = function(state,arg){ + if (this.tokentype == CSL.START){ + if ("none" == arg){ + var evaluator = function(state,Item){ + var res = this.succeed; + state.tmp.jump.replace("succeed"); + for each (var func in this.tests){ + if (func.call(this,state,Item)){ + res = this.fail; + state.tmp.jump.replace("fail"); + break; + } + } + return res; + }; + } else if ("any" == arg){ + var evaluator = function(state,Item){ + var res = this.fail; + state.tmp.jump.replace("fail"); + for each (var func in this.tests){ + if (func.call(this,state,Item)){ + res = this.succeed; + state.tmp.jump.replace("succeed"); + break; + } + } + return res; + }; + } else if ("all" == arg){ + var evaluator = function(state,Item){ + var res = this.succeed; + state.tmp.jump.replace("succeed"); + for each (var func in this.tests){ + if (!func.call(this,state,Item)){ + res = this.fail; + state.tmp.jump.replace("fail"); + break; + } + } + return res; + }; + } else { + throw "Unknown match condition \""+arg+"\" in @match"; + } + this.evaluator = evaluator; + }; +}; +CSL.Lib.Attributes["@sort-separator"] = function(state,arg){ + this.strings["sort-separator"] = arg; +}; +CSL.Lib.Attributes["@delimiter-precedes-last"] = function(state,arg){ + this.strings["delimiter-precedes-last"] = arg; +}; +CSL.Lib.Attributes["@name-as-sort-order"] = function(state,arg){ + this.strings["name-as-sort-order"] = arg; +}; +CSL.Lib.Attributes["@is-numeric"] = function(state,arg){ + var variables = arg.split(/\s+/); + for each (var variable in variables){ + var func = function(state,Item){ + if (CSL.NUMERIC_VARIABLES.indexOf(variable) == -1){ + return false; + } + var val = Item[variable]; + if (typeof val == "undefined"){ + return false; + } + if (typeof val == "number"){ + val = val.toString(); + } + if (typeof val != "string"){ + return false; + } + if (val.match(CSL.QUOTED_REGEXP)){ + return false; + } + if (val.match(CSL.NUMBER_REGEXP)){ + return true; + } + return false; + }; + this["tests"].push(func); + }; +}; +CSL.Lib.Attributes["@names-min"] = function(state,arg){ + this.strings["et-al-min"] = parseInt(arg, 10); +}; +CSL.Lib.Attributes["@names-use-first"] = function(state,arg){ + this.strings["et-al-use-first"] = parseInt(arg,10); +}; +CSL.Lib.Attributes["@sort"] = function(state,arg){ + if (arg == "descending"){ + this.strings.sort_direction = CSL.DESCENDING; + } +} +CSL.Lib.Attributes["@plural"] = function(state,arg){ +}; +CSL.Lib.Attributes["@locator"] = function(state,arg){ +}; +CSL.Lib.Attributes["@include-period"] = function(state,arg){ +}; +CSL.Lib.Attributes["@position"] = function(state,arg){ +}; +CSL.Lib.Attributes["@disambiguate"] = function(state,arg){ + if (this.tokentype == CSL.START && ["if","else-if"].indexOf(this.name) > -1){ + if (arg == "true"){ + state.opt.has_disambiguate = true; + var func = function(state,Item){ + if (state.tmp.disambig_settings["disambiguate"]){ + return true; + } + return false; + }; + this["tests"].push(func); + }; + }; +}; +CSL.Output = {}; +CSL.Output.Queue = function(state){ + this.state = state; + this.queue = new Array(); + this.empty = new CSL.Factory.Token("empty"); + var tokenstore = {}; + tokenstore["empty"] = this.empty; + this.formats = new CSL.Factory.Stack( tokenstore ); + this.current = new CSL.Factory.Stack( this.queue ); + this.suppress_join_punctuation = false; +}; +CSL.Output.Queue.prototype.getToken = function(name){ + var ret = this.formats.value()[name]; + return ret; +}; +// Store a new output format token based on another +CSL.Output.Queue.prototype.addToken = function(name,modifier,token){ + var newtok = new CSL.Factory.Token("output"); + if ("string" == typeof token){ + token = this.formats.value()[token]; + } + if (token && token.strings){ + for (attr in token.strings){ + newtok.strings[attr] = token.strings[attr]; + } + newtok.decorations = token.decorations; + } + if ("string" == typeof modifier){ + newtok.strings.delimiter = modifier; + } + this.formats.value()[name] = newtok; +}; +// +// newFormat adds a new bundle of formatting tokens to +// the queue's internal stack of such bundles +CSL.Output.Queue.prototype.pushFormats = function(tokenstore){ + if (!tokenstore){ + tokenstore = new Object(); + } + tokenstore["empty"] = this.empty; + this.formats.push(tokenstore); +}; +CSL.Output.Queue.prototype.popFormats = function(tokenstore){ + this.formats.pop(); +}; +CSL.Output.Queue.prototype.startTag = function(name,token){ + var tokenstore = {}; + tokenstore[name] = token; + this.pushFormats( tokenstore ); + this.openLevel(name); +} +CSL.Output.Queue.prototype.endTag = function(){ + this.closeLevel(); + this.popFormats(); +} +// +// newlevel adds a new blob object to the end of the current +// list, and adjusts the current pointer so that subsequent +// appends are made to blob list of the new object. +CSL.Output.Queue.prototype.openLevel = function(token){ + if (!this.formats.value()[token]){ + throw "CSL processor error: call to nonexistent format token \""+token+"\""; + } + var blob = new CSL.Factory.Blob(this.formats.value()[token]); + var curr = this.current.value(); + curr.push( blob ); + this.current.push( blob.blobs ); +}; +CSL.Output.Queue.prototype.closeLevel = function(name){ + this.current.pop(); +} +// +// append does the same thing as newlevel, except +// that the blob it pushes has text content, +// and the current pointer is not moved after the push. +CSL.Output.Queue.prototype.append = function(str,tokname){ + var blob = false; + if (!tokname){ + var token = this.formats.value()["empty"]; + } else if (tokname == "literal"){ + var token = true; + blob = str; + } else if ("string" == typeof tokname){ + var token = this.formats.value()[tokname]; + } else { + var token = tokname; + } + if (!token){ + throw "CSL processor error: unknown format token name: "+tokname; + } + if (!blob){ + blob = new CSL.Factory.Blob(token,str); + } + var curr = this.current.value(); + curr.push( blob ); + this.state.tmp.term_predecessor = true; +} +CSL.Output.Queue.prototype.string = function(state,blobs,blob){ + var ret; + ret = { "str": [], "obj": [] }; + if (blobs.length == 1 && "string" == blobs[0].blobs){ + ret["str"] = blobs[0]; + } else { + for each (var blobjr in blobs){ + var strPlus = {"str":"","obj":[]}; + if ("string" == typeof blobjr.blobs){ + if ("number" == typeof blobjr.num){ + strPlus["obj"] = blobjr; + } else { + strPlus["str"] = blobjr.blobs; + } + } else { + strPlus = this.string(state,blobjr.blobs,blobjr); + }; + // + // If there is a suffix, or any decorations, trailing rangeable + // objects must be rendered immediately here. + // + if (strPlus["str"]){ + if (!state.tmp.suppress_decorations){ + for each (var params in blobjr.decorations){ + strPlus["str"] = state.fun.decorate[params[0]][params[1]](strPlus["str"]); + } + } + //print(str+" (with is_rangeable="+blobjr.strings.is_rangeable+")"); + strPlus["str"] = blobjr.strings.prefix + strPlus["str"] + blobjr.strings.suffix; + ret["str"].push(strPlus["str"]); + } + // + // this passes rangeable objects through + ret["obj"] = ret["obj"].concat(strPlus["obj"]); + }; + // + // The join only applies to non-rangeable objects. + // + if (blob) { + ret["str"] = ret["str"].join(blob.strings.delimiter); + } else { + // + // The list always seems to consist of a single string when this happens, + // which is fine by me. + // + //ret["str"] = ret["str"].join(""); + // XXX Obviously something needs to be done with rangeable + // XXX objects here! + // (will need to reverse the condition below after + // providing for force_render) + if (state.tmp.handle_ranges){ + ret["str"] = ret["str"].join(""); + //ret = ret["str"].join("") + this.renderBlobs(ret["obj"]); + } else { + ret = ret["str"].join(""); + } + //if (state.tmp.handle_ranges){ + // ret = ret["str"].join("") + this.renderBlobs(ret["obj"]); + // //ret = "OK"; + //} else { + // ret = ret["str"].join("") + this.renderBlobs(ret["obj"]); + //} + } + }; + this.queue = new Array(); + this.current.mystack = new Array(); + this.current.mystack.push( this.queue ); + return ret; +}; +CSL.Output.Queue.prototype.clearlevel = function(){ + var blobs = this.current.value(); + for (var i=(blobs.length-1); i > -1; i--){ + blobs.pop(); + } +}; +CSL.Output.Queue.prototype.dumbBlobs = function(state,blobs){ +}; +CSL.Output.Queue.prototype.renderBlobs = function(blobs){ + var state = this.state; + var ret = ""; + for (var i=0; i < blobs.length; i++){ + blobs[i].checkNext(blobs[(i+1)]); + } + for each (var blob in blobs){ + if (blob.status != CSL.SUPPRESS){ + // print("doing rangeable blob"); + var str = blob.blobs; + if (!state.tmp.suppress_decorations){ + for each (var params in blob.decorations){ + str = state.fun.decorate[params[0]][params[1]](str); + } + } + str = blob.strings.prefix + str + blob.strings.suffix; + if (blob.status == CSL.END){ + // + // XXXXX needs to be drawn from the object + ret += "-"; + } else if (blob.status == CSL.SUCCESSOR){ + // + // XXXXX needs to be drawn from the object + ret += ", "; + } else if (blob.status == CSL.START){ + // + // XXXXX needs to be drawn from the object + ret += ""; + } + ret += str; + } + } + return ret; +}; +CSL.Output.Formatters = new function(){}; +CSL.Output.Formatters.passthrough = function(string){ + return string; +}; +// +// XXXXX +// A bit of interest coming up with vertical-align. +// This needs to include the prefixes and suffixes +// in its scope, so it's applied last, AFTER they +// are appended to the string. I think it's the +// only one that will need to work that way. +CSL.Output.Formatters.lowercase = function(string) { + if ("object" == typeof string){ + var ret = new Array(); + for each (item in string){ + ret.push(item.LowerCase()); + } + return ret; + } + return string.LowerCase(); +}; +CSL.Output.Formatters.uppercase = function(string) { + if ("object" == typeof string){ + var ret = new Array(); + for each (item in string){ + ret.push(item.toUpperCase()); + } + return ret; + } + return string.toUpperCase(); +}; +CSL.Output.Formatters.capitalize_first = function(string) { + return string[0].toUpperCase()+string.substr(1); +}; +CSL.Output.Formatters.sentence_capitalization = function(string) { + return string[0].toUpperCase()+string.substr(1).toLowerCase(); +}; +CSL.Output.Formatters.capitalize_all = function(string) { + var strings = string.split(" "); + for(var i=0; i 1) { + strings[i] = strings[i][0].toUpperCase()+strings[i].substr(1).toLowerCase(); + } else if(strings[i].length == 1) { + strings[i] = strings[i].toUpperCase(); + } + } + return strings.join(" "); +}; +CSL.Output.Formatters.title_capitalization = function(string) { + if (!string) { + return ""; + } + var words = string.split(delimiterRegexp); + var isUpperCase = string.toUpperCase() == string; + var newString = ""; + var delimiterOffset = words[0].length; + var lastWordIndex = words.length-1; + var previousWordIndex = -1; + for(var i=0; i<=lastWordIndex; i++) { + // only do manipulation if not a delimiter character + if(words[i].length != 0 && (words[i].length != 1 || !delimiterRegexp.test(words[i]))) { + var upperCaseVariant = words[i].toUpperCase(); + var lowerCaseVariant = words[i].toLowerCase(); + // only use if word does not already possess some capitalization + if(isUpperCase || words[i] == lowerCaseVariant) { + if( + // a skip word + skipWords.indexOf(lowerCaseVariant.replace(/[^a-zA-Z]+/, "")) != -1 + // not first or last word + && i != 0 && i != lastWordIndex + // does not follow a colon + && (previousWordIndex == -1 || words[previousWordIndex][words[previousWordIndex].length-1] != ":") + ) { + words[i] = lowerCaseVariant; + } else { + // this is not a skip word or comes after a colon; + // we must capitalize + words[i] = upperCaseVariant[0] + lowerCaseVariant.substr(1); + } + } + previousWordIndex = i; + } + newString += words[i]; + } + return newString; +}; +CSL.Output.Formats = function(){}; +CSL.Output.Formats.prototype.html = { + "@font-family":"%%STRING%%", + "@font-style/italic":"%%STRING%%", + "@font-style/normal":false, + "@font-style/oblique":"%%STRING%%", + "@font-variant/small-caps":"%%STRING%%", + "@font-variant/normal":false, + "@font-weight/bold":"%%STRING%%", + "@font-weight/normal":false, + "@font-weight/light":false, + "@text-decoration/none":false, + "@text-decoration/underline":"%%STRING%%", + "@vertical-align/baseline":false, + "@vertical-align/sup":"%%STRING%%", + "@vertical-align/sub":"%%STRING%%", + "@text-case/lowercase":CSL.Output.Formatters.lowercase, + "@text-case/uppercase":CSL.Output.Formatters.uppercase, + "@text-case/capitalize-first":CSL.Output.Formatters.capitalize_first, + "@text-case/capitalize-all":CSL.Output.Formatters.capitalize_all, + "@text-case/title":CSL.Output.Formatters.title_capitalization, + "@text-case/sentence":CSL.Output.Formatters.sentence_capitalization, + "@quotes":"&lquo;%%STRING%%&rquo;" +}; +CSL.Output.Formats = new CSL.Output.Formats();CSL.Output.Number = function(num,mother_token){ + this.num = num; + this.blobs = num.toString(); + this.status = CSL.START; + this.strings = new Object(); + if (mother_token){ + this.decorations = mother_token.decorations; + this.strings.prefix = mother_token.strings.prefix; + this.strings.suffix = mother_token.strings.suffix; + this.successor_prefix = mother_token.successor_prefix; + this.range_prefix = mother_token.range_prefix; + this.formatter = mother_token.formatter; + if (this.formatter){ + this.type = this.formatter.format(1); + } + } else { + this.decorations = new Array(); + this.strings.prefix = ""; + this.strings.suffix = ""; + this.successor_prefix = ""; + this.range_prefix = ""; + this.formatter = new CSL.Output.DefaultFormatter(); + } +}; +CSL.Output.Number.prototype.setFormatter = function(formatter){ + this.formatter = formatter; + this.type = this.formatter.format(1); +}; +CSL.Output.DefaultFormatter = function (){}; +CSL.Output.DefaultFormatter.prototype.format = function (num){ + return num.toString(); +}; +CSL.Output.Number.prototype.checkNext = function(next){ + if ( ! next || ! next.num || this.type != next.type || next.num != (this.num+1)){ + if (this.status == CSL.SUCCESSOR_OF_SUCCESSOR){ + this.status = CSL.END; + } + } else { // next number is in the sequence + if (this.status == CSL.START){ + next.status = CSL.SUCCESSOR; + } else if (this.status == CSL.SUCCESSOR || this.status == CSL.SUCCESSOR_OF_SUCCESSOR){ + next.status = CSL.SUCCESSOR_OF_SUCCESSOR; + this.status = CSL.SUPPRESS; + } + }; +}; +CSL.System = {}; +CSL.System.Xml = {}; +CSL.System.Xml.E4X = function(){}; +CSL.System.Xml.E4X.prototype.clean = function(xml){ + xml = xml.replace(/<\?[^?]+\?>/g,""); + xml = xml.replace(/]+>/g,""); + xml = xml.replace(/^\s+/g,""); + xml = xml.replace(/\s+$/g,""); + return xml; +}; +CSL.System.Xml.E4X.prototype.parse = function(xml){ + default xml namespace = "http://purl.org/net/xbiblio/csl"; + return XML( this.clean(xml) ); +}; +CSL.System.Xml.E4X.prototype.commandInterface = new function(){ + this.children = children; + this.nodename = nodename; + this.attributes = attributes; + this.content = content; + this.numberofnodes = numberofnodes; + function children(){ + return this.children(); + }; + function nodename(){ + return this.localName(); + } + function attributes(){ + var ret = new Object(); + var attrs = this.attributes(); + for (var idx in attrs){ + var key = "@"+attrs[idx].localName(); + var value = attrs[idx].toString(); + ret[key] = value; + } + return ret; + } + function content(){ + return this.toString(); + } + function numberofnodes(){ + return this.length(); + } +}; +CSL.System.Xml.E4X = new CSL.System.Xml.E4X(); +CSL.System.Xml.JunkyardJavascript = function(){}; +CSL.System.Xml.JunkyardJavascript.prototype.clean = function(xml) { + xml = xml.replace(/\n/g,""); + xml = xml.replace(/\>\s+/g,">"); + xml = xml.replace(/\s+\]+>)/); + var newlist = new Array(); + var i; + var tag = false; + var tagname = false; + for (i=0; i 12) { + // swap day and month + var tmp = date.day; + date.day = date.month; + date.month = tmp; + } + } + if((!date.month || date.month <= 12) && (!date.day || date.day <= 31)) { + if(date.year && date.year < 100) { // for two digit years, determine proper + // four digit year + var today = new Date(); + var year = today.getFullYear(); + var twoDigitYear = year % 100; + var century = year - twoDigitYear; + if(date.year <= twoDigitYear) { + // assume this date is from our century + date.year = century + date.year; + } else { + // assume this date is from the previous century + date.year = century - 100 + date.year; + } + } + // subtract one for JS style + if(date.month){ + date.month--; + } + date.part = pre+post; + } else { + // + // give up; we failed the sanity check + date = {"part":string}; + } + } else { + date.part = string; + } + } else { + date.part = string; + } + if(!date.year) { + var m = _yearRe.exec(date.part); + if(m) { + date.year = num1; + date.part = pre+d1_2; + } + } + if(!date.month) { + // compile month regular expression + var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', + 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + // If using a non-English bibliography locale, try those too + if (Zotero.CSL.Global.locale != 'en-US') { + months = months.concat(Zotero.CSL.Global.getMonthStrings("short")); + } + if(!_monthRe) { + _monthRe = new RegExp("^(.*)\\b("+months.join("|")+")[^ ]*(?: (.*)$|$)", "i"); + } + var m = _monthRe.exec(date.part); + if(m) { + // Modulo 12 in case we have multiple languages + date.month = months.indexOf(m[2][0].toUpperCase()+m[2].substr(1).toLowerCase()) % 12; + date.part = m[1]+m[3]; + } + } + if(!date.day) { + // compile day regular expression + if(!_dayRe) { + var daySuffixes = Zotero.getString("date.daySuffixes").replace(/, ?/g, "|"); + _dayRe = new RegExp("\\b([0-9]{1,2})(?:"+daySuffixes+")?\\b(.*)", "i"); + } + var m = _dayRe.exec(date.part); + if(m) { + var day = parseInt(m[1], 10); + // Sanity check + if (day <= 31) { + date.day = day; + if(m.index > 0) { + date.part = date.part.substr(0, m.index); + if(m[2]) { + date.part += " "+m[2];; + } + } else { + date.part = m[2]; + } + } + } + } + if(date.part) { + date.part = date.part.replace(/^[^A-Za-z0-9]+/, "").replace(/[^A-Za-z0-9]+$/, ""); + if(!date.part.length) { + date.part = undefined; + } + } + return date; +}; +CSL.System.Tests = function(){}; +CSL.System.Tests.getTest = function(myname){ + var test; + var filename = "std/machines/" + myname + ".json"; + var teststring = readFile(filename); + try { + eval( "test = "+teststring ); + } catch(e){ + throw e + teststring; + } + if (test.mode == "bibliography"){ + var render = "makeBibliography"; + } else { + var render = "makeCitationCluster"; + } + test.run = function(){ + var builder = new CSL.Core.Build(this.csl); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + CSL.System.Tests.fixNames(this.input,myname); + for each (var item in this.input){ + style.fun.retriever.setInput(style,item); + style.registry.insert(style,item); + } + var ret = style[render](this.input); + return ret; + }; + return test; +}; +CSL.System.Tests.fixNames = function(itemlist,myname){ + for each (obj in itemlist){ + if (!obj.id){ + throw "No id for object in: "+myname; + } + for each (key in ["author","editor","translator"]){ + if (obj[key]){ + for each (var entry in obj[key]){ + var one_char = entry.name.length-1; + var two_chars = one_char-1; + entry.sticky = false; + if ("!!" == entry.name.substr(two_chars)){ + entry.literal = entry.name.substr(0,two_chars).replace(/\s+$/,""); + } else { + var parsed = entry.name; + if ("!" == entry.name.substr(one_char)){ + entry.sticky = true; + parsed = entry.name.substr(0,one_char).replace(/\s+$/,""); + } + parsed = parsed.split(/\s*,\s*/); + if (parsed.length > 0){ + var m = parsed[0].match(/^\s*([a-z]+)\s+(.*)/); + if (m){ + entry.prefix = m[1]; + entry["primary-key"] = m[2]; + } else { + entry["primary-key"] = parsed[0]; + } + } + if (parsed.length > 1){ + entry["secondary-key"] = parsed[1]; + } + if (parsed.length > 2){ + var m = parsed[2].match(/\!\s*(.*)/); + if (m){ + entry.suffix = m[1]; + entry.comma_suffix = true; + } else { + entry.suffix = parsed[2]; + } + } + } + } + } + } + } + return itemlist; +}; diff --git a/rpc-stuff/citeproc-js-rpc.py b/rpc-stuff/citeproc-js-rpc.py new file mode 100755 index 000000000..dc201bc95 --- /dev/null +++ b/rpc-stuff/citeproc-js-rpc.py @@ -0,0 +1,329 @@ +#! /usr/bin/env python +"""Simple JSON-RPC Server. + +This module can be used to create simple JSON-RPC servers +by creating a server and either installing functions, a +class instance, or by extending the SimpleJSONRPCServer +class. + +It can also be used to handle JSON-RPC requests in a CGI +environment using CGIJSONRPCRequestHandler. + +A list of possible usage patterns follows: + +1. Install functions: + +server = SimpleJSONRPCServer(("localhost", 8000)) +server.register_function(pow) +server.register_function(lambda x,y: x+y, 'add') +server.serve_forever() + +2. Install an instance: + +class MyFuncs: + def __init__(self): + # make all of the string functions available through + # string.func_name + import string + self.string = string + def _listMethods(self): + # implement this method so that system.listMethods + # knows to advertise the strings methods + return list_public_methods(self) + \ + ['string.' + method for method in list_public_methods(self.string)] + def pow(self, x, y): return pow(x, y) + def add(self, x, y) : return x + y + +server = SimpleJSONRPCServer(("localhost", 8000)) +server.register_introspection_functions() +server.register_instance(MyFuncs()) +server.serve_forever() + +3. Install an instance with custom dispatch method: + +class Math: + def _listMethods(self): + # this method must be present for system.listMethods + # to work + return ['add', 'pow'] + def _methodHelp(self, method): + # this method must be present for system.methodHelp + # to work + if method == 'add': + return "add(2,3) => 5" + elif method == 'pow': + return "pow(x, y[, z]) => number" + else: + # By convention, return empty + # string if no help is available + return "" + def _dispatch(self, method, params): + if method == 'pow': + return pow(*params) + elif method == 'add': + return params[0] + params[1] + else: + raise 'bad method' + +server = SimpleXMLRPCServer(("localhost", 8000)) +server.register_introspection_functions() +server.register_instance(Math()) +server.serve_forever() + +4. Subclass SimpleJSONRPCServer: + +class MathServer(SimpleJSONRPCServer): + def _dispatch(self, method, params): + try: + # We are forcing the 'export_' prefix on methods that are + # callable through JSON-RPC to prevent potential security + # problems + func = getattr(self, 'export_' + method) + except AttributeError: + raise Exception('method "%s" is not supported' % method) + else: + return func(*params) + + def export_add(self, x, y): + return x + y + +server = MathServer(("localhost", 8000)) +server.serve_forever() + +5. CGI script: + +server = CGIJSONRPCRequestHandler() +server.register_function(pow) +server.handle_request() +""" + +# This implementation was converted from SimpleXMLRPCServer by +# David McNab (david@rebirthing.co.nz) + +# Original SimpleXMLRPCServer module was written by Brian +# Quinlan (brian@sweetapp.com), Based on code written by Fredrik Lundh. + +import xmlrpclib +from xmlrpclib import Fault +import SocketServer +import BaseHTTPServer +import sys +import os + +import SimpleXMLRPCServer +try: + import json +except: + import simplejson as json + +import traceback + + +class SimpleJSONRPCDispatcher(SimpleXMLRPCServer.SimpleXMLRPCDispatcher): + """Mix-in class that dispatches JSON-RPC requests. + Based on SimpleXMLRPCDispatcher, but overrides + _marshaled_dispatch for JSON-RPC + + This class is used to register JSON-RPC method handlers + and then to dispatch them. There should never be any + reason to instantiate this class directly. + """ + def _marshaled_dispatch(self, data, dispatch_method = None): + """Dispatches a JSON-RPC method from marshalled (JSON) data. + + JSON-RPC methods are dispatched from the marshalled (JSON) data + using the _dispatch method and the result is returned as + marshalled data. For backwards compatibility, a dispatch + function can be provided as an argument (see comment in + SimpleJSONRPCRequestHandler.do_POST) but overriding the + existing method through subclassing is the prefered means + of changing method dispatch behavior. + """ + rawreq = json.loads(data) + + + #params, method = xmlrpclib.loads(data) + id = rawreq.get('id', 0) + method = rawreq['method'] + params = rawreq.get('params', []) + + responseDict = {'id':id} + + # generate response + try: + if dispatch_method is not None: + response = dispatch_method(method, params) + else: + response = self._dispatch(method, params) + ## wrap response in a singleton tuple + #response = (response,) + #response = xmlrpclib.dumps(response, methodresponse=1) + responseDict['result'] = response + except Fault, fault: + #response = xmlrpclib.dumps(fault) + responseDict['error'] = repr(response) + except: + # report exception back to server + #response = xmlrpclib.dumps( + # xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value)) + # ) + responseDict['error'] = "%s:%s" % (sys.exc_type, sys.exc_value) + + return json.dumps(responseDict) + + +#class SimpleXMLRPCRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): +class SimpleJSONRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): + """Simple JSON-RPC request handler class. + + Handles all HTTP POST requests and attempts to decode them as + XML-RPC requests. + """ + def do_POST(self): + """Handles the HTTP POST request. + + Attempts to interpret all HTTP POST requests as JSON-RPC calls, + which are forwarded to the server's _dispatch method for handling. + """ + try: + # get arguments + data = self.rfile.read(int(self.headers["content-length"])) + # In previous versions of SimpleXMLRPCServer, _dispatch + # could be overridden in this class, instead of in + # SimpleXMLRPCDispatcher. To maintain backwards compatibility, + # check to see if a subclass implements _dispatch and dispatch + # using that method if present. + response = self.server._marshaled_dispatch( + data, getattr(self, '_dispatch', None) + ) + except: # This should only happen if the module is buggy + # internal error, report as HTTP server error + self.send_response(500) + self.end_headers() + else: + # got a valid XML RPC response + self.send_response(200) + self.send_header("Content-type", "text/json") + self.send_header("Content-length", str(len(response))) + self.end_headers() + self.wfile.write(response) + + # shut down the connection + self.wfile.flush() + self.connection.shutdown(1) + +class SimpleJSONRPCServer(SocketServer.TCPServer, + SimpleJSONRPCDispatcher): + """Simple JSON-RPC server. + + Simple JSON-RPC server that allows functions and a single instance + to be installed to handle requests. The default implementation + attempts to dispatch JSON-RPC calls to the functions or instance + installed in the server. Override the _dispatch method inhereted + from SimpleJSONRPCDispatcher to change this behavior. + """ + def __init__(self, addr, requestHandler=SimpleJSONRPCRequestHandler, + logRequests=1): + self.logRequests = logRequests + + SimpleJSONRPCDispatcher.__init__(self,addr[0],addr[1]) + SocketServer.TCPServer.__init__(self, addr, requestHandler) + +class CGIJSONRPCRequestHandler(SimpleJSONRPCDispatcher): + """Simple handler for JSON-RPC data passed through CGI.""" + def __init__(self): + SimpleJSONRPCDispatcher.__init__(self) + + def handle_get(self): + """Handle a single HTTP GET request. + + Default implementation indicates an error because + XML-RPC uses the POST method. + """ + + code = 400 + message, explain = \ + BaseHTTPServer.BaseHTTPRequestHandler.responses[code] + + response = BaseHTTPServer.DEFAULT_ERROR_MESSAGE % \ + { + 'code' : code, + 'message' : message, + 'explain' : explain + } + print 'Status: %d %s' % (code, message) + print 'Content-Type: text/html' + print 'Content-Length: %d' % len(response) + print + sys.stdout.write(response) + + def handle_request(self, request_text = None): + """Handle a single JSON-RPC request passed through a CGI post method. + + If no JSON data is given then it is read from stdin. The resulting + JSON-RPC response is printed to stdout along with the correct HTTP + headers. + """ + if request_text is None and \ + os.environ.get('REQUEST_METHOD', None) == 'GET': + self.handle_get() + else: + # POST data is normally available through stdin + if request_text is None: + request_text = sys.stdin.read() + + self.handle_jsonrpc(request_text) + + def handle_jsonrpc(self, request_text): + """Handle a single JSON-RPC request""" + + response = self._marshaled_dispatch(request_text) + + print 'Content-Type: text/json' + print 'Content-Length: %d' % len(response) + print + sys.stdout.write(response) + +if __name__ == '__main__': + + server = SimpleJSONRPCServer(("localhost", 8027)) + server.register_function(pow) + + from spidermonkey import Runtime + rt = Runtime() + cx = rt.new_context() + + cslcode = open("citeproc-js-combined.js").read() + cx.eval_script(cslcode) + + ## Hack in English locale. Should inspect the + ## CSL for other locales needed. + locale_en = open("../locale/locales-en-US.xml").read() + locale_en = json.dumps(locale_en) + + def makeStyle(csl): + csl = json.dumps(csl) + #print 'style = CSL.makeStyle(%s,%s)' %(csl,locale_en) + cx.eval_script('var style = CSL.makeStyle(%s,%s)' %(csl,locale_en)) + return "Style init OK" + + def insertItems(input): + theinput = json.dumps(input) + cx.eval_script("style.insertItems(%s)" %(theinput,)) + return "Insert items OK" + + def makeCitationCluster(input): + theinput = json.dumps(input) + result = cx.eval_script("style.makeCitationCluster(%s)" %(theinput,)) + return result + + def makeBibliography(): + result = cx.eval_script("style.makeBibliography()") + return result + # + # Register citeproc-js control functions here. + server.register_function(lambda csl: makeStyle(csl), 'setStyle') + server.register_function(lambda input: insertItems(input), 'insertItems') + server.register_function(lambda input: makeCitationCluster(input), 'makeCitationCluster') + server.register_function(lambda: makeBibliography(), 'makeBibliography') + server.serve_forever() diff --git a/rpc-stuff/citeproc-js.py b/rpc-stuff/citeproc-js.py new file mode 100755 index 000000000..b2a386588 --- /dev/null +++ b/rpc-stuff/citeproc-js.py @@ -0,0 +1,17 @@ +#!/usr/bin/python + +from spidermonkey import Runtime +rt = Runtime() +cx = rt.new_context() + +cslcode = open("stripped.js").read() + +cx.eval_script(cslcode) + +test = ''' +var builder = new CSL.Core.Build(''); +var obj = builder.build(); +obj.citation.tokens.length +''' + +cx.eval_script(test) diff --git a/rpc-stuff/gen_set_style_json.py b/rpc-stuff/gen_set_style_json.py new file mode 100755 index 000000000..1ee924615 --- /dev/null +++ b/rpc-stuff/gen_set_style_json.py @@ -0,0 +1,16 @@ +#! /usr/bin/env python + +try: + import json +except: + import simplejson as json + + +style = open("./set_style.csl").read() + +method = "setStyle" +params = [style] + +command = { "method": method, "params": params } + +open("./set_style.json","w+").write( json.dumps(command) ) diff --git a/rpc-stuff/insert_items.json b/rpc-stuff/insert_items.json new file mode 100644 index 000000000..d5ea32a01 --- /dev/null +++ b/rpc-stuff/insert_items.json @@ -0,0 +1,23 @@ +{ + "method": "insertItems", + "params": [[ + { + "id": "ITEM-1", + "type": "book", + "author": [ + { "name":"Doe, John", "primary-key":"Doe", "secondary-key":"John" } + ], + "title": "Book A", + "issued": { "year": "2006" } + }, + { + "id": "ITEM-2", + "type": "book", + "author": [ + { "name":" Roe, Jane", "primary-key":"Roe", "secondary-key":"Jane" } + ], + "title": "Book B", + "issued": { "year": "2007" } + } + ]] +} diff --git a/rpc-stuff/make_bibliography.json b/rpc-stuff/make_bibliography.json new file mode 100644 index 000000000..35e868259 --- /dev/null +++ b/rpc-stuff/make_bibliography.json @@ -0,0 +1,4 @@ +{ + "method": "makeBibliography", + "params": [] +} diff --git a/rpc-stuff/make_citation_cluster.json b/rpc-stuff/make_citation_cluster.json new file mode 100644 index 000000000..344d40ee0 --- /dev/null +++ b/rpc-stuff/make_citation_cluster.json @@ -0,0 +1,25 @@ +{ + "method": "makeCitationCluster", + "params": [[ + { + "id": "ITEM-3", + "type": "book", + "author": [ + { "name":"Anderson, Margaret", "primary-key":"Anderson", "secondary-key":"Margaret" } + ], + "title": "Book D", + "issued": { "year": "1950" } + }, + { + "id": "ITEM-4", + "type": "book", + "author": [ + { "name":"Zinfandel, William", "primary-key":"Zinfandel", "secondary-key":"William" } + ], + "title": "Book C", + "issued": { "year": "1945" } + } + ]] +} + + diff --git a/rpc-stuff/set_style.csl b/rpc-stuff/set_style.csl new file mode 100644 index 000000000..d1b649aba --- /dev/null +++ b/rpc-stuff/set_style.csl @@ -0,0 +1,61 @@ + diff --git a/rpc-stuff/set_style.json b/rpc-stuff/set_style.json new file mode 100644 index 000000000..cf3367b4f --- /dev/null +++ b/rpc-stuff/set_style.json @@ -0,0 +1 @@ +{"params": ["\n"], "method": "setStyle"} \ No newline at end of file diff --git a/rpc-stuff/wgetdemo.sh b/rpc-stuff/wgetdemo.sh new file mode 100755 index 000000000..551871b46 --- /dev/null +++ b/rpc-stuff/wgetdemo.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +rm -f *.result + +## +## Configure processor +## +wget -q --post-file set_style.json -O set_style.result http://localhost:8027/ + + +echo ------------------------- +echo result of set_style.json +echo ------------------------- + +echo -n '---> ' +cat set_style.result +echo +echo + +## +## Insert items to bibliography without rendering citations +## +wget -q --post-file insert_items.json -O insert_items.result http://localhost:8027/ + + +echo --------------------------- +echo result of insert_items.json +echo --------------------------- + +echo -n '---> ' +cat insert_items.result +echo +echo + +## +## Render bibliography +## +wget -q --post-file make_bibliography.json -O make_bibliography.result http://localhost:8027/ + +echo -------------------------------- +echo result of make_bibliography.json +echo -------------------------------- + +echo -n '---> ' +cat make_bibliography.result +echo +echo + +## +## Render citations +## +wget -q --post-file make_citation_cluster.json -O make_citation_cluster.result http://localhost:8027/ + +echo ------------------------------------ +echo result of make_citation_cluster.json +echo ------------------------------------ + +echo -n '---> ' +cat make_citation_cluster.result +echo +echo + +## +## Render bibliography +## +wget -q --post-file make_bibliography.json -O make_bibliography.result http://localhost:8027/ + +echo -------------------------------- +echo result of make_bibliography.json +echo -------------------------------- + +echo -n '---> ' +cat make_bibliography.result +echo +echo + diff --git a/runtests.bat b/runtests.bat new file mode 100644 index 000000000..da4760ce6 --- /dev/null +++ b/runtests.bat @@ -0,0 +1,19 @@ +@echo off +setlocal + +echo Started test-run +set starttime=%time% + +cd %~dp0 + +set RHINO=%~dp0\rhino\js-1.7R1.jar +set DOJO=%~dp0\dojo\dojo\dojo.js +set DOH=%~dp0\dojo\util\doh\ + +set TARGET=%~dp0\tests\run.js + +java -client -jar %RHINO% %TARGET% dojoUrl=%DOJO% testModule="" + +echo Finished test-run +echo Start Time = %starttime% +echo End Time = %time% diff --git a/runtests.sh b/runtests.sh new file mode 100755 index 000000000..5c72e4a61 --- /dev/null +++ b/runtests.sh @@ -0,0 +1,28 @@ +#!/bin/sh +START="$(date) <--------------START" +cd $(dirname $0) +RHINO="${PWD}"/rhino/js-1.7R1.jar +DOJO="${PWD}"/dojo/dojo/dojo.js +DOH="${PWD}"/dojo/util/doh/ + +TARGET="${PWD}"/tests/run.js + +java -client -jar "${RHINO}" -opt 1 "${TARGET}" dojoUrl="${DOJO}" testModule="" + +# +# Ah, Spidermonkey has no I/O capabilities. How very interesting. +# +#if [ $(which smjs | grep -c "/" ) -gt 0 ]; then +# echo "Using spidermonkey" +# rm dojo +# ln -sf dojo-spidermonkey dojo +# smjs "${TARGET}" dojoUrl="${DOJO}" testModule="" +#else +# echo "Using java/rhino" +# rm dojo +# ln -sf dojo-rhino dojo +# java -client -jar "${RHINO}" "${TARGET}" dojoUrl="${DOJO}" testModule="" +#fi + +echo $START +echo $(date) \<--------------END diff --git a/src/ambigconfig.js b/src/ambigconfig.js new file mode 100644 index 000000000..281b130b3 --- /dev/null +++ b/src/ambigconfig.js @@ -0,0 +1,17 @@ +dojo.provide("csl.ambigconfig"); +if (!CSL) { + load("./src/csl.js"); +} + +/** + * Ambiguous Cite Configuration Object + * @class + */ +CSL.Factory.AmbigConfig = function(){ + this.maxvals = new Array(); + this.minval = 1; + this.names = new Array(); + this.givens = new Array(); + this.year_suffix = 0; + this.disambiguate = 0; +}; diff --git a/src/attributes.js b/src/attributes.js new file mode 100644 index 000000000..698b5e4aa --- /dev/null +++ b/src/attributes.js @@ -0,0 +1,430 @@ +dojo.provide("csl.attributes"); +if (!CSL) { + load("./src/csl.js"); +} + +/** + * Functions corresponding to CSL attribute + * names (no idea why JsDoc insists on printing + * the function names twice). + *

Used by Build. + * Non-formatting attributes are distilled into + * functions ready to execute without arguments + * when {@link CSL.Core.Build} is run.

+ *

JsDoc is definitely not happy with my coding + * style here; none of the attribute functions come + * through in the online documentation. You'll have + * to refer directly to the source code for information + * on these.

+ * @class + */ +CSL.Lib.Attributes = {}; + + +/** + * Store the value attribute on the token. + * @name CSL.Lib.Attributes.@value + * @function + */ +CSL.Lib.Attributes["@value"] = function(state,arg){ + this.strings.value = arg; +}; + + +/** + * Store the name attribute (of a macro or term node) + * on the state object. + *

For reference when the closing node of a macro + * or locale definition is encountered.

+ * @name CSL.Lib.Attributes.@name + * @function + */ +CSL.Lib.Attributes["@name"] = function(state,arg){ + this.strings.name = arg; +}; + + +/** + * Store the form attribute (of a term node) on the state object. + *

For reference when the closing node of a macro + * or locale definition is encountered.

+ * @name CSL.Lib.Attributes.@form + * @function + */ +CSL.Lib.Attributes["@form"] = function(state,arg){ + // + // This looks meaningless + // + //if (!arg){ + // arg = "long"; + //} + this.strings.form = arg; +}; + +/** + * Store macro tokens in a buffer on the state object. + *

For reference when the enclosing text token is + * processed.

+ * @name CSL.Lib.Attributes.@macro + * @function + */ +CSL.Lib.Attributes["@macro"] = function(state,arg){ + state.build.postponed_macro = arg; +}; + + +/* + * Store the term tokens on the singleton buffer. + *

This works the same as a macro

+ * XXXXX Terms have to be + * carried in a hash object anyway, to account for + * singular and plural forms. This should be a function + * that ends up in execs, the same as value and + * variable. the string content should come from + * state.opt.term[key][key][0 or 1]. + * @name CSL.Lib.Attributes.@suffix + * @function + */ +CSL.Lib.Attributes["@term"] = function(state,arg){ + if (this.name == "et-al"){ + if (state.opt.term[arg]){ + this.strings.et_al_term = state.opt.term[arg]["long"][0]; + } else { + this.strings.et_al_term = arg; + } + } + state.build.term = arg; +}; + + +/* + * Ignore xmlns attribute. + *

This should always be

http://purl.org/net/xbiblio/csl + * anyway. At least for the present we will blindly assume + * that it is.

+ * @name CSL.Lib.Attributes.@xmlns + * @function + */ +CSL.Lib.Attributes["@xmlns"] = function(state,arg){}; + + +/* + * Store language attribute to a buffer field. + *

Will be placed in the appropriate location + * when the element is processed.

+ * @name CSL.Lib.Attributes.@lang + * @function + */ +CSL.Lib.Attributes["@lang"] = function(state,arg){ + if (arg){ + state.build.lang = arg; + } +}; + +/* + * Store class attribute in state config object. + * @name CSL.Lib.Attributes.@class + * @function + */ +CSL.Lib.Attributes["@class"] = function(state,arg){ + state.opt["class"] = arg; +}; + + + +/* + * Store item type evaluation function on token. + * @name CSL.Lib.Attributes.@type + * @function + */ +CSL.Lib.Attributes["@type"] = function(state,arg){ + if (this.name == "name-part") { + // + // Note that there will be multiple name-part items, + // and they all need to be collected before doing anything. + // So this must be picked up when the + // element is processed, and used as a key on an + // object holding the formatting attribute functions. + state.tmp.namepart_type = arg; + } else { + var func = function(state,Item){ + if(Item.type == arg){ + return true; + } + return false; + }; + this["tests"].push(func); + } + +}; + + +/* + * Store variable retrieval function on token. + *

Returned function will return the variable value + * or values as an array.

+ * @name CSL.Lib.Attributes.@variable + * @function + */ +CSL.Lib.Attributes["@variable"] = function(state,arg){ + + if (this.tokentype == CSL.SINGLETON){ + if (this.name == "text"){ + this.variables = arg.split(/\s+/); + }; + if (this.name == "key"){ + // + // this one is truly wild. the key element + // will be recast as a start and end tag, so this + // function will be copied across to the TEXT + // tag that the key tags will enclose. the text + // of the variable will render to an output queue + // that is dedicated to producing sort keys. + state.build.key_is_variable = true; + var func = function(state,Item){ + if ("citation-number" == arg){ + state.tmp.value.push("citation-number"); + } else { + state.tmp.value.push(Item[arg]); + } + }; + this["execs"].push(func); + }; + if (this.name == "label"){ + // + // labels treat the "locator" variable specially. + print("Note to self: do something for variable= on label elements."); + } + }; + if (this.tokentype == CSL.START){ + if (["if","else-if"].indexOf(this.name) > -1){ + var variables = arg.split(/\s+/); + for each (var variable in variables){ + var func = function(state,Item){ + if (Item[variable]){ + return true; + } + return false; + }; + this["tests"].push(func); + }; + }; + if (this.name == "date"){ + var func = function(state,Item){ + state.fun.mark_output(state,Item[arg]); + state.tmp.value.push(Item[arg]); + }; + this["execs"].push(func); + }; + }; + if (this.name == "names" && (this.tokentype == CSL.START || this.tokentype == CSL.SINGLETON)){ + if (arg){ + this.variables = arg.split(/\s+/); + }; + }; +}; + + +/** + * Store "and" flag on the token + * @name CSL.Lib.Attributes.@and + * @function + */ +CSL.Lib.Attributes["@and"] = function(state,arg){ + if ("symbol" == arg){ + this.strings["and"] = " & "; + } else { + var and = state.opt.term["and"]["long"][0]; + if (and.match(/.*[a-zA-Z\u0400-\u052f].*/)){ + and = ", "+and+" "; + } + this.strings["and"] = and; + } +}; + +/** + * Store "initialize-with" string in build object + * @name CSL.Lib.Attributes.@initialize_with + * @function + */ +CSL.Lib.Attributes["@initialize-with"] = function(state,arg){ + this.strings["initialize-with"] = arg; +}; + + +/* + * Store suffix string on token. + * @name CSL.Lib.Attributes.@suffix + * @function + */ +CSL.Lib.Attributes["@suffix"] = function(state,arg){ + this.strings.suffix = arg; +}; + + +/* + * Store prefix string on token. + * @name CSL.Lib.Attributes.@prefix + * @function + */ +CSL.Lib.Attributes["@prefix"] = function(state,arg){ + this.strings.prefix = arg; +}; + + +/* + * Store delimiter string on token. + * @name CSL.Lib.Attributes.@delimiter + * @function + */ +CSL.Lib.Attributes["@delimiter"] = function(state,arg){ + this.strings.delimiter = arg; +}; + + +/* + * Store match evaluator on token. + */ +CSL.Lib.Attributes["@match"] = function(state,arg){ + if (this.tokentype == CSL.START){ + if ("none" == arg){ + var evaluator = function(state,Item){ + var res = this.succeed; + state.tmp.jump.replace("succeed"); + for each (var func in this.tests){ + if (func.call(this,state,Item)){ + res = this.fail; + state.tmp.jump.replace("fail"); + break; + } + } + return res; + }; + } else if ("any" == arg){ + var evaluator = function(state,Item){ + var res = this.fail; + state.tmp.jump.replace("fail"); + for each (var func in this.tests){ + if (func.call(this,state,Item)){ + res = this.succeed; + state.tmp.jump.replace("succeed"); + break; + } + } + return res; + }; + } else if ("all" == arg){ + var evaluator = function(state,Item){ + var res = this.succeed; + state.tmp.jump.replace("succeed"); + for each (var func in this.tests){ + if (!func.call(this,state,Item)){ + res = this.fail; + state.tmp.jump.replace("fail"); + break; + } + } + return res; + }; + } else { + throw "Unknown match condition \""+arg+"\" in @match"; + } + this.evaluator = evaluator; + }; +}; + +CSL.Lib.Attributes["@sort-separator"] = function(state,arg){ + this.strings["sort-separator"] = arg; +}; + + +CSL.Lib.Attributes["@delimiter-precedes-last"] = function(state,arg){ + this.strings["delimiter-precedes-last"] = arg; +}; + + +CSL.Lib.Attributes["@name-as-sort-order"] = function(state,arg){ + this.strings["name-as-sort-order"] = arg; +}; + + +CSL.Lib.Attributes["@is-numeric"] = function(state,arg){ + var variables = arg.split(/\s+/); + for each (var variable in variables){ + var func = function(state,Item){ + if (CSL.NUMERIC_VARIABLES.indexOf(variable) == -1){ + return false; + } + var val = Item[variable]; + if (typeof val == "undefined"){ + return false; + } + if (typeof val == "number"){ + val = val.toString(); + } + if (typeof val != "string"){ + return false; + } + if (val.match(CSL.QUOTED_REGEXP)){ + return false; + } + if (val.match(CSL.NUMBER_REGEXP)){ + return true; + } + return false; + }; + this["tests"].push(func); + }; + +}; + + +CSL.Lib.Attributes["@names-min"] = function(state,arg){ + this.strings["et-al-min"] = parseInt(arg, 10); +}; + +CSL.Lib.Attributes["@names-use-first"] = function(state,arg){ + this.strings["et-al-use-first"] = parseInt(arg,10); +}; + +CSL.Lib.Attributes["@sort"] = function(state,arg){ + if (arg == "descending"){ + this.strings.sort_direction = CSL.DESCENDING; + } +} + + +CSL.Lib.Attributes["@plural"] = function(state,arg){ + +}; + + +CSL.Lib.Attributes["@locator"] = function(state,arg){ + +}; + + +CSL.Lib.Attributes["@include-period"] = function(state,arg){ + +}; + + +CSL.Lib.Attributes["@position"] = function(state,arg){ + +}; + + +CSL.Lib.Attributes["@disambiguate"] = function(state,arg){ + if (this.tokentype == CSL.START && ["if","else-if"].indexOf(this.name) > -1){ + if (arg == "true"){ + state.opt.has_disambiguate = true; + var func = function(state,Item){ + if (state.tmp.disambig_settings["disambiguate"]){ + return true; + } + return false; + }; + this["tests"].push(func); + }; + }; +}; diff --git a/src/blob.js b/src/blob.js new file mode 100644 index 000000000..b2988ae66 --- /dev/null +++ b/src/blob.js @@ -0,0 +1,16 @@ +dojo.provide("csl.blob"); + +CSL.Factory.Blob = function(token,str){ + if (token){ + this.strings = token.strings; + this.decorations = token.decorations; + } else { + this.strings = new Object(); + }; + if ("string" == typeof str){ + this.blobs = str; + } else { + this.blobs = new Array(); + }; +}; + diff --git a/src/build.js b/src/build.js new file mode 100644 index 000000000..48244cfd4 --- /dev/null +++ b/src/build.js @@ -0,0 +1,258 @@ +dojo.provide("csl.build"); + + +/** + * First-stage compiler. + *

After instantiation, this object provides a method + * for creating the tokenized representation of the style + * used in onward processing. Note that an alternative + * to the default E4X parser for XML may be specified + * when the object is instantiated. The comment to + * {@link CSL} provides an overview of the processing flow.

+ * @param {String} stylexml A serialized CSL style definition in + * XML format. + * @param {String} xmlLingo XML processor to use for parsing. + * Parsers are defined in the {@link CSL.System.Xml} namespace. + * @example + * builder = Build(myxml) + * @example + * builder = Build(myxml,"JQuery") + * @example + * builder = CSL.Core.Build(myxml); + * raw_engine = builder.build(); + * + * @class Raw style generator. + */ +CSL.Core.Build = function(stylexml,xmlLingo) { + this._builder = _builder; + this.showXml = showXml; // for testing + this._getNavi = _getNavi; // exposed for testing + if (!xmlLingo){ + //xmlLingo = "JunkyardJavascript"; + xmlLingo = "E4X"; + } + var xmlParser = CSL.System.Xml[xmlLingo]; + var xml = xmlParser.parse(stylexml); + + var xmlCommandInterface = CSL.System.Xml[xmlLingo].commandInterface; + var state = new CSL.Factory.State(xmlCommandInterface,xml); + this.state = state; + + + /* + * First-stage build function. + * + * This function performs a + * depth-first walk of an XML tree, using wrapper functions + * drawn from {@link CSL.System.Xml}. This _builder function controls + * the recursion loop. Navigation and action-points during the + * walk are peformed by an instance of {@link CSL.Core.Build._getNavi} + * (see below). + * + * @param {Object} state An instance of the {@link CSL.Factory.State} + * object, configured with a parsed XML object and a + * corresponding set of wrapper functions for manipulating + * it. + */ + function _builder(state){ + this._build = _build; // exposed for testing + this.navi = navi; // exposed for testing + this.getObject = getObject; + var nodelist = state.build.nodeList; + var navi = new _getNavi(state); + function _build(){ // used to accept nodelist as arg + if (navi.getkids()){ + _build(navi.getXml()); + } else { + if (navi.getbro()){ + _build(navi.getXml()); + } else { + while (state.build.nodeList.length > 1) { + if (navi.remember()){ + _build(navi.getXml()); + } + } + } + } + return state; + } + function getObject(){ + // These startup loops are too complex + var state = this._build(); // used to have nodelist as arg + return state; + } + }; + + /* + * Navigation and action for XML tree walk. + * + * This function performs the three navigation + * actions needed for a depth-first tree walk (find + * children, find sibling, retrace to parent), and + * builds a token list by applying {@link CSL.Factory.XmlToToken} + * to the appropriate nodes. + * + * @param {Object} state The freshly minted state object + * from {@link CSL.Factory.State} that will represent the style. + */ + function _getNavi(state){ + this.getkids = getkids; + this.getbro = getbro; + this.remember = remember; + this.getXml = getXml; + var depth = 0; + this.depth = depth; + + function remember(){ + depth += -1; + state.build.nodeList.pop(); + // closing node, process result of children + var node = state.build.nodeList[depth][1][(state.build.nodeList[depth][0])]; + CSL.Factory.XmlToToken.call(node,state,CSL.END); + return getbro(); + } + function getbro(){ + var sneakpeek = state.build.nodeList[depth][1][(state.build.nodeList[depth][0]+1)]; + if (sneakpeek){ + state.build.nodeList[depth][0] += 1; + return true; + } else { + return false; + } + } + + function getkids (){ + var currnode = state.build.nodeList[depth][1][state.build.nodeList[depth][0]]; + var sneakpeek = state.build.xmlCommandInterface.children.call(currnode); + if (state.build.xmlCommandInterface.numberofnodes.call(sneakpeek) == 0){ + // singleton, process immediately + CSL.Factory.XmlToToken.call(currnode,state,CSL.SINGLETON); + return false; + } else { + // if first node of a span, process it, then descend + CSL.Factory.XmlToToken.call(currnode,state,CSL.START); + depth += 1; + state.build.nodeList.push([0,sneakpeek]); + + return true; + } + } + + function getXml(){ + return state.build.nodeList[depth][1]; + } + } + + /* + * Expose tokens for testing. + */ + function showXml(){ + return xml; + } + +}; + + +/** + * Tokenize the CSL style. + *

This method casts a CSL style file as a state + * object with the properties listed below (see the + * code of {@link CSL.Factory.State} for more + * particulars on the sub-fields inside this object). The state + * object is passed to {@link CSL.Core.Configure} for the final + * preparation of the style engine.

+ *
+ *
build
+ *
Holds scratch variables and + * stacks used during the first stage of compilation, + * including the XML command interface wrapper. + * This area is deleted after the Build phase is complete. + *
+ *
configure
+ *
Holds stacks used when setting + * jump points on tokens during the second stage of + * compilation. This area is deleted after the Configure + * phase is complete. + *
+ *
registry
+ *
Persistent item registry providing bibliography + * sort order and disambiguated title hints for use by + * rendering functions.
+ *
opt
+ *
Holds global configuration options, + * the hash of localized terms, and output rendering + * functions. It also contains scratch variables used + * to pass state information from an opening tag and its children + * to the relevant closing tag. + *
+ *
citation
+ *
Holds the token list and output + * queue for the <citation> object defined in the CSL + * style file. + *
+ *
tokens
+ *
The token list representing the citation definition + * of the style.
+ *
opt
+ *
Holds the output queue + * (formatted) for this formatting area, + * and configuration options specific to <citation>.
+ *
+ *
+ *
bibliography
+ *
Holds the token list and output + * queue for the <bibliography> object defined in CSL. + *
+ *
tokens
+ *
The token list representing the bibliography definition + * of the style.
+ *
opt
+ *
Holds the output queue + * (formatted) and configuration options specific + * to <bibliography>.
+ *
+ *
+ *
citation-sortkey
+ *
Holds the token list and output + * queue for the <sort> object (if any) defined in + * the CSL <citation> object. This is + * called by, and the keys are registered in, the persistent + * item registry. + *
+ *
tokens
+ *
The token list representing the sort key definition.
+ *
opt
+ *
Holds the output queue + * (formatted) and configuration options specific + * to sort key generation. This should suppress all output + * decorations, supplying only a plain text string for use + * as the item sort key.
+ *
+ *
+ *
bibliography-sortkey
+ *
Holds the token list and output + * queue for the <sort> object (if any) defined in + * the CSL <bibliography> object. This is + * called by, and the keys are registered in, the persistent + * item registry. + *
+ *
tokens
+ *
The token list representing the sort key definition.
+ *
opt
+ *
Holds the output queue + * (formatted) and configuration options specific + * to sort key generation. This should suppress all output + * decorations, supplying only a plain text string for use + * as the item sort key.
+ *
+ *
+ *
+ * @function + */ +CSL.Core.Build.prototype.build = function(locale){ + this.state.opt.locale = locale; + var engine = new this._builder(this.state); + var ret = engine.getObject(); + ret.registry = new CSL.Factory.Registry(ret); + return ret; +}; diff --git a/src/commands.js b/src/commands.js new file mode 100644 index 000000000..e72f78337 --- /dev/null +++ b/src/commands.js @@ -0,0 +1,96 @@ +dojo.provide("csl.commands"); + +/** + * This module provides the commands used to instantiate + * and control the processor. For integration purposes, + * this should provide everything you need, once System + * and Retrieval have been adapted to your environment. + */ +CSL.makeStyle = function(xml,locale){ + var builder = new CSL.Core.Build(xml); + var raw = builder.build(locale); + var conf = new CSL.Core.Configure(raw); + var ret = conf.configure(); + return ret; +} + + +/** + * Compose a citation "cluster". + *

Accepts an Item object or a list of Item objects as a + * single argument. Citation clusters are typically used in the + * body of a document. Because locator information may be + * needed to correctly render cites within a cluster, the + * argument should be a list of actual objects, rather + * than item keys. (The code in {@link CSL.System.Retrieval} + * does recognize keys, but this is intended only for testing + * purposes.)

+ */ +CSL.Factory.State.prototype.makeCitationCluster = function(inputList){ + this.insertItems(inputList); + // + // don't bother sorting unless there is more than one item. + // this is really ugly and hackish. uses a hashed reference + // tacked onto the end of an array to squeeze the object + // ID into the sorted list. + if (inputList && inputList.length > 1 && this["citation_sort"].tokens.length > 0){ + var newlist = new Array(); + var keys_list = new Array(); + for each (var Item in inputList){ + var keys = this.getSortKeys(Item,"citation_sort"); + keys["cheaters_hack"] = Item; + keys_list.push(keys); + } + var srt = new CSL.Factory.Registry.Comparifier(this,"citation_sort"); + keys_list.sort(srt.compareKeys); + for each (key in keys_list){ + newlist.push(key.cheaters_hack); + } + // + // XXXXX this is all one-time, one-way, slice probably isn't needed here? + inputList = newlist; + } + + // + // sort thingie goes here + // + this.tmp.last_suffix_used = ""; + this.tmp.last_names_used = new Array(); + this.tmp.last_years_used = new Array(); + var str = CSL.Core.Render._unit_of_reference.call(this,inputList); + return str; +}; + + +/** + * Compose a bibliography. + *

Returns the bibliography for the session as + * a single string. Entries in the bibliography are + * sorted according to the system locale, with + * disambiguation adjustments requested by the style.

+ */ +CSL.Factory.State.prototype.makeBibliography = function(){ + var debug = false; + if (debug){ + for each (tok in this.bibliography.tokens){ + print("bibtok: "+tok.name); + } + print("---"); + for each (tok in this.citation.tokens){ + print("cittok: "+tok.name); + } + print("---"); + for each (tok in this.bibliography_sort.tokens){ + print("bibsorttok: "+tok.name); + } + } + return CSL.Core.Render._bibliography_entries.call(this); +}; + + +CSL.Factory.State.prototype.insertItems = function(inputList){ + for each (item in inputList){ + this.fun.retriever.input[item.id] = item; + this.registry.insert(this,item); + }; +}; diff --git a/src/configure.js b/src/configure.js new file mode 100644 index 000000000..c2a22d4f0 --- /dev/null +++ b/src/configure.js @@ -0,0 +1,62 @@ +dojo.provide("csl.configure"); +if (!CSL) { + load("./src/csl.js"); +} + + +/** + * Second-stage compiler. + *

Instantiates with the raw style object returned by + * {@link CSL.Core.Build#build}, and provides a method that + * returns a copy of the object stripped of its build + * and configure areas, and complete with token jump + * points for conditional branching, output rendering + * functions, and methods for processing data items.

+ * @namespace Style configuration + * @param {Object} builderobject The object output + * by {@link CSL.Core.Build#build}. + * @param {String} mode Optional. Default is "html". + * @example + * builder = CSL.Core.Build(myxml) + * raw_engine = builder.build() + * configurator = CSL.Core.Configure(raw_engine,"rtf") + * style_engine = configurator.configure() + */ +CSL.Core.Configure = function(state,mode) { + this.state = state; + if (!mode){ + mode = "html"; + } + + if (this.state.build){ + delete this.state.build; + } + this.state.fun.decorate = CSL.Factory.Mode(mode); + this.state.opt.mode = mode; +}; + + +/** + * Configure the citation style. + *

In a single back-to-front pass over the token list, this sets + * jump positions on conditional tokens (if, + * else-if, else), installs rendering + * functions used to generate output, + * deletes the build and + * configure areas, and attaches the iterface methods + * from {@link CSL.Core.Render} that are needed for processing data + * items.

+ */ +CSL.Core.Configure.prototype.configure = function(){ + for each (var area in ["citation", "citation_sort", "bibliography","bibliography_sort"]){ + for (var pos=(this.state[area].tokens.length-1); pos>-1; pos--){ + var token = this.state[area].tokens[pos]; + token["next"] = (pos+1); + if (token.name && CSL.Lib.Elements[token.name].configure){ + CSL.Lib.Elements[token.name].configure.call(token,this.state,pos); + } + } + } + this.state["version"] = CSL.Factory.version; + return this.state; +}; diff --git a/src/core.js b/src/core.js new file mode 100644 index 000000000..f065d9409 --- /dev/null +++ b/src/core.js @@ -0,0 +1,14 @@ +dojo.provide("csl.core"); +if (!CSL) { + load("./src/csl.js"); +} + +/** + * Core logic for building and rendering. + *

This contains the three core tools for building + * a compiled representation of the CSL style, and + * rendering one or more data items with it. + * @namespace Core facilities. + */ +CSL.Core = {}; + diff --git a/src/disambiguate.js b/src/disambiguate.js new file mode 100644 index 000000000..2eedd75e6 --- /dev/null +++ b/src/disambiguate.js @@ -0,0 +1,429 @@ +dojo.provide("csl.disambiguate"); + +var debug = false; + +/** + * Disambiguate a list of cites + */ +CSL.Factory.Registry.prototype.disambiguateCites = function (state,akey,modes,candidate_list){ + if ( ! candidate_list){ + // + // We start with the state and an ambig key. + // We acquire a copy of the list of ambigs that relate to the key from state. + var ambigs = this.ambigs[akey].slice(); + // + // We clear the list of ambigs so it can be rebuilt + this.ambigs[akey] = new Array(); + } else { + // candidate list consists of registry tokens. + // extract the ids and build an ambigs list. + // This is roundabout -- we already collected + // these once for the first-phase disambiguation. + // Maybe it can be cleaned up later. + var ambigs = new Array(); + for each (var reg_token in candidate_list){ + ambigs.push(reg_token.id); + } + } + // + // We get the ids of the partners from the copy + // (what's the point of this? why not just push + // ambigs itself?) + var id_vals = new Array(); + for each (var a in ambigs){ + id_vals.push(a); + } + // + // We get the tokens of the partners + var tokens = state.fun.retriever.getInput(id_vals); + + // The processing sequence is the same for all modes, + // but there are important differences at the decision + // points. + var checkerator = new this.Checkerator(tokens,modes); + + checkerator.lastclashes = (ambigs.length-1); + + // We iterate through every cite in the list, front to back. + // But we use a while loop, because repeated renderings + // of the same cite might be needed. + var base = false; + checkerator.pos = 0; + + // + // OKAY! It's now all working right, but the loop isn't + // exiting. We need to know which items we have seen, + // and exit when we've seen them all. + // + while (checkerator.run()){ + var token = tokens[checkerator.pos]; + if (debug){ + print("<<<<<<<<<<<<<<<<<<<<<<<<< "+ token.id +" >>>>>>>>>>>>>>>>>>>>>>>>>>>"); + } + // + // skip items that have been finally resolved. + if (this.ambigs[akey].indexOf(token.id) > -1){ + if (debug){ + print("---> Skip registered token for: "+token.id); + } + checkerator.pos += 1; + continue; + } + checkerator.candidate = token.id; + + if (base == false){ + checkerator.mode = modes[0]; + } + if (debug){ + print (" ---> Mode: "+checkerator.mode); + } + if (debug){ + print("base in (givens):"+base["givens"]); + } + var str = state.getAmbiguousCite(token,base); + var maxvals = state.getMaxVals(); + var minval = state.getMinVal(); + base = state.getAmbigConfig(); + if (debug){ + print("base out (givens):"+base["givens"]); + } + if (candidate_list && candidate_list.length){ + base["disambiguate"] = true; + } + checkerator.setBase(base); + checkerator.setMaxVals(maxvals); + checkerator.setMinVal(minval); + + for each (testpartner in tokens){ + + if (token.id == testpartner.id){ + continue; + } + var otherstr = state.getAmbiguousCite(testpartner,base); + if (debug){ + print(" ---> last clashes: "+checkerator.lastclashes); + print(" ---> master: "+token.id); + print(" ---> master: "+str); + print(" ---> partner: "+testpartner.id); + print(" ---> partner: "+otherstr); + } + + if(checkerator.checkForClash(str,otherstr)){ + break; + } + } + if (checkerator.evaluateClashes()){ + var base_return = this.decrementNames(state,base); + this.registerAmbigToken(state,akey,token.id,base_return); + checkerator.seen.push(token.id); + if (debug){ + print(" ---> Evaluate: storing token config: "+base); + } + continue; + } + if (checkerator.maxAmbigLevel()){ + if ( ! state["citation"].opt["disambiguate-add-year-suffix"]){ + //this.registerAmbigToken(state,akey,token.id,base); + checkerator.mode1_counts = false; + checkerator.maxed_out_bases[token.id] = base; + if (debug){ + print(" ---> Max out: remembering token config for: "+token.id); + print(" ("+base["names"]+":"+base["givens"]+")"); + } + } else { + if (debug){ + print(" ---> Max out: NOT storing token config for: "+token.id); + print(" ("+base["names"]+":"+base["givens"]+")"); + } + } + checkerator.seen.push(token.id); + base = false; + continue; + } + if (debug){ + print(" ---> Incrementing"); + } + checkerator.incrementAmbigLevel(); + } + // return tuples of registry tokens and item tokens. + // the former are useful for second-run disambiguation, + // the latter for sorting. + var ret = new Array(); + for each (id in checkerator.ids){ + if (id){ + ret.push(this.registry[id]); + } + } + // if we don't have year-suffix available, we may + // have maxed out bases lying around + for (i in checkerator.maxed_out_bases){ + this.registry[i].disambig = checkerator.maxed_out_bases[i]; + } + return ret; +}; + +/** + * Management object to support the disambiguation control loop. + */ +CSL.Factory.Registry.prototype.Checkerator = function(tokens,modes){ + this.seen = new Array(); + this.modes = modes; + this.mode = this.modes[0]; + this.tokens_length = tokens.length; + this.pos = 0; + this.clashes = 0; + this.maxvals = false; + this.base = false; + this.ids = new Array(); + this.maxed_out_bases = new Object(); + for each (token in tokens){ + this.ids.push(token.id); + } + // + // used in givens mode (mode 1) + this.lastclashes = -1; + // + // used to address into the base array in both modes + this.namepos = 0; + this.modepos = 0; + this.mode1_counts = false; +}; + +CSL.Factory.Registry.prototype.Checkerator.prototype.run = function(){ + if (this.seen.length < this.tokens_length){ + return true; + } + return false; +} + +CSL.Factory.Registry.prototype.Checkerator.prototype.setMaxVals = function(maxvals){ + this.maxvals = maxvals; +}; + + +CSL.Factory.Registry.prototype.Checkerator.prototype.setMinVal = function(minval){ + this.minval = minval; +}; + +CSL.Factory.Registry.prototype.Checkerator.prototype.setBase = function(base){ + this.base = base; + if (! this.mode1_counts){ + this.mode1_counts = new Array(); + for each (i in this.base["givens"]){ + this.mode1_counts.push(0); + } + } +}; + + +CSL.Factory.Registry.prototype.Checkerator.prototype.setMode = function(mode){ + this.mode = mode; +}; + +CSL.Factory.Registry.prototype.Checkerator.prototype.checkForClash = function(str,otherstr){ + if (str == otherstr){ + if (this.mode == "names"){ + this.clashes += 1; + if (debug){ + print(" (mode 0 clash, returning true)"); + } + return true; + } + if (this.mode == "givens"){ + this.clashes += 1; + if (debug){ + print(" (mode 1 clash, returning false)"); + } + } + return false; + } +}; + +CSL.Factory.Registry.prototype.Checkerator.prototype.evaluateClashes = function(){ + // + // necessary for the odd case of static cites with no authors + if (!this.maxvals.length){ + return false; + } + // mode 0 is pretty simple + if (this.mode == "names"){ + if (this.clashes){ + this.lastclashes = this.clashes; + this.clashes = 0; + return false; + } else { + // cleared, so increment. also quash the id as done. + this.ids[this.pos] = false; + this.pos += 1; + this.lastclashes = this.clashes; + return true; + } + } + // compare the clash counts + // if clash counts not reduced, reverse change in base + // if clash counts reduced, hold the change steady + // in the above two cases, just return false. leave the incementing to the + // incrementing function + // if no clashes at all on expanded pass, just return true, it's a wrap + if (this.mode == "givens"){ + var ret = true; + if (debug){ + print(" ---> Comparing in mode 1: clashes="+this.clashes+"; lastclashes="+this.lastclashes); + } + var namepos = this.mode1_counts[this.modepos]; + if (this.clashes && this.clashes == this.lastclashes){ + if (debug){ + print(" ---> Applying mode 1 defaults: "+this.mode1_defaults); + } + if (this.mode1_defaults){ + var old = this.mode1_defaults[(namepos-1)]; + if (debug){ + print(" ---> Resetting to default: ("+old+")"); + } + this.base["givens"][this.modepos][(namepos-1)] = old; + } + ret = false; + } else if (this.clashes) { + if (debug){ + print(" ---> Expanding given name helped a little, retaining it"); + } + ret = false; + } else { // only non-clash should be possible + if (debug){ + print(" ---> No clashes, storing token config and going to next"); + } + this.mode1_counts = false; + ret = true; + } + this.lastclashes = this.clashes; + this.clashes = 0; + if (ret){ + this.ids[this.pos] = false; + } + return ret; + } +}; + +CSL.Factory.Registry.prototype.Checkerator.prototype.maxAmbigLevel = function (){ + // + // like the above, necessary for the odd case of static cites with no authors + if (!this.maxvals.length){ + return true; + } + + if (this.mode == "names"){ + //print(this.modepos+" : "+this.base[0].length+" : "+this.base[0][this.modepos]); + if (this.modepos == (this.base["names"].length-1) && this.base["names"][this.modepos] == this.maxvals[this.modepos]){ + if (this.modes.length == 2){ + this.mode = "givens"; + this.modepos = 0; + //this.pos = 0; + } else { + this.pos += 1; + return true; + } + } + } + if (this.mode == "givens"){ + if (this.modepos == (this.mode1_counts.length-1) && this.mode1_counts[this.modepos] == (this.maxvals[this.modepos])){ + if (debug){ + print("----- Item maxed out -----"); + } + if (this.modes.length == 2){ + this.mode = "givens"; + this.pos += 1; + } else { + this.pos += 1; + } + //this.ids[this.pos] = false; + return true; + } + } + return false; +}; + + +/** + * Increment disambiguation level + */ +CSL.Factory.Registry.prototype.Checkerator.prototype.incrementAmbigLevel = function (){ + // + // this is a little tricky. the counters are arrays. + // ... and for mode 1, this only gives us the position, + // not the values of the array of booleans, which of + // course are not subject to incrementing in this + // sense. + if (this.mode == "names"){ + var val = this.base["names"][this.modepos]; + if (val < this.maxvals[this.modepos]){ + this.base["names"][this.modepos] += 1; + } else if (this.modepos < (this.base["names"].length-1)){ + this.modepos +=1; + this.base["names"][this.modepos] = 0; + } + } + if (this.mode == "givens"){ + var val = (this.mode1_counts[this.modepos]); + if (val < this.maxvals[this.modepos]){ + this.mode1_counts[this.modepos] += 1; + this.mode1_defaults = this.base["givens"][this.modepos].slice(); + this.base["givens"][this.modepos][val] += 1; + if (debug){ + print(" ---> (A) Set expanded givenname param with base: "+this.base["givens"]); + } + } else if (this.modepos < (this.base["givens"].length-1)){ + this.modepos +=1; + this.base["givens"][this.modepos][0] += 1; + this.mode1_defaults = this.base["givens"][this.modepos].slice(); + if (debug){ + print(" ---> (B) Set expanded givenname param with base: "+this.base["givens"]); + } + } else { + this.mode = "names"; + this.pos += 1; + } + } +}; + +CSL.Factory.Registry.prototype.registerAmbigToken = function (state,akey,id,ambig_config){ + if ( ! this.ambigs[akey]){ + this.ambigs[akey] = new Array(); + }; + var found = false; + for (var i in this.ambigs[akey]){ + if (this.ambigs[akey].indexOf(id) > -1){ + found = true; + } + } + if (!found){ + this.ambigs[akey].push(id); + } + this.registry[id].disambig = state.fun.clone_ambig_config(ambig_config); +}; + +CSL.Factory.Registry.prototype.decrementNames = function(state,base){ + // two reverse scans, one to determine if there are any expanded + // names to stop the unwind, and another to perform the + // unwind + var base_return = state.fun.clone_ambig_config(base); + var do_me = false; + for (var i=(base_return["givens"].length-1); i > -1; i--){ + for (var j=(base_return["givens"][i].length-1); j > -1; j--){ + if (base_return["givens"][i][j] == 2){ + do_me = true; + } + } + } + if (do_me){ + for (var i=(base_return["givens"].length-1); i > -1; i--){ + for (var j=(base_return["givens"][i].length-1); j > -1; j--){ + if (base_return["givens"][i][j] == 2){ + i = -1; + break; + } + base_return["names"][i] += -1; + } + } + } + return base_return; +}; diff --git a/src/elements.js b/src/elements.js new file mode 100644 index 000000000..dd1dd8f70 --- /dev/null +++ b/src/elements.js @@ -0,0 +1,1138 @@ +dojo.provide("csl.elements"); +if (!CSL) { + load("./src/csl.js"); +} + +// +// XXXXX Fix initialization of given name count. +// Should this be removed from the base? not sure. +// + + +/** + * Functions corresponding to CSL element names. + *

These are static function used during build and + * configuration. The build method is called + * on a token generated from the XML node at build time, and + * may manipulate either the content of the state object or that + * of the token.

+ *

The configure method is invoked on the + * node during a back-to-front pass through the tokens, + * and sets skip positions for conditionals.

+ *

Tokens that do not affect citation rendering in any + * way can be discarded by not pushing them to the target. + * In this case, the configure method need + * not be defined.

+ * @class + */ +CSL.Lib.Elements = {}; + + +/** + * The style element. + * @name CSL.Lib.Elements.style + * @function + */ +CSL.Lib.Elements.style = new function(){ + this.build = build; + function build (state,target){ + if (this.tokentype == CSL.START){ + if (!state.build.lang){ + state.build.lang = "en"; + } + state.opt.lang = state.build.lang; + state.build.in_style = true; + state.build.lang = false; + state.opt.term = CSL.System.Retrieval.getLocaleObjects(state.opt.lang,state.opt.locale); + state.tmp.term_predecessor = false; + } else { + state.tmp.disambig_request = false; + state.build.in_style = false; + } + if (this.tokentype == CSL.START){ + var func = function(state,Item){ + if (state.tmp.disambig_request && ! state.tmp.disambig_override){ + state.tmp.disambig_settings = state.tmp.disambig_request; + } else if (state.registry.registry[Item.id] && ! state.tmp.disambig_override) { + state.tmp.disambig_request = state.registry.registry[Item.id].disambig; + state.tmp.disambig_settings = state.registry.registry[Item.id].disambig; + } else { + + state.tmp.disambig_settings = new CSL.Factory.AmbigConfig(); + } + }; + state["init"].push(func); + var tracking_info_init = function(state,Item){ + state.tmp.names_used = new Array(); + state.tmp.nameset_counter = 0; + state.tmp.years_used = new Array(); + }; + state["init"].push(tracking_info_init); + + var splice_init = function(state,Item) { + state.tmp.splice_delimiter = state[state.tmp.area].opt.delimiter; + }; + state["init"].push(splice_init); + + var sort_keys_init = function(state,Item) { + state["bibliography_sort"].keys = new Array(); + state["citation_sort"].keys = new Array(); + }; + state["init"].push(sort_keys_init); + + }; + if (this.tokentype == CSL.END){ + var set_splice = function(state,Item){ + // + // set the inter-cite join delimiter + // here. + if (state.tmp.last_suffix_used && state.tmp.last_suffix_used.match(/.*[-.,;:]$/)){ + state.tmp.splice_delimiter = " "; + } else if (state.tmp.prefix.value() && state.tmp.prefix.value().match(/^[,,:;a-z].*/)){ + state.tmp.splice_delimiter = " "; + } else if (state.tmp.last_suffix_used || state.tmp.prefix.value()){ + // + // forcing the delimiter back to normal if a + // suffix or prefix touch the join, even if + // a year-suffix is the only output. + state.tmp.splice_delimiter = state[state.tmp.area].opt.delimiter; + } else { + // XXXX year-suffix must have been used for special + // XXXX delimiter to be invoked here. + } + }; + state["stop"].push(set_splice); + var set_lastvals = function(state,Item){ + state.tmp.last_suffix_used = state.tmp.suffix.value(); + state.tmp.last_years_used = state.tmp.years_used.slice(); + state.tmp.last_names_used = state.tmp.names_used.slice(); + }; + state["stop"].push(set_lastvals); + var func = function(state,Item){ + state.tmp.disambig_request = false; + }; + state["stop"].push(func); + } + } +}; + + +/** + * The info element. + *

Everything in this scope is a total + * noop.

+ * @name CSL.Lib.Elements.info + */ +CSL.Lib.Elements.info = new function(){ + this.build = build; + function build (state,target){ + if (this.tokentype == CSL.START){ + state.build.skip = "info"; + } else { + state.build.skip = false; + } + }; +}; + +/** + * The text element. + * @name CSL.Lib.Elements.text + * @function + */ +CSL.Lib.Elements.text = new function(){ + this.build = build; + function build (state,target){ + // + // CSL permits macros to be called before they + // are declared. We file a placeholder token unless we are + // in the layout area, and when in the layout area we scan + // any inserted macros for nested macro calls, and explode + // them. + if (state.build.postponed_macro){ + // + // XXXX Could catch undeclared macros here. + // + if ( ! state.build.layout_flag && ! state.build.sort_flag){ + // + // Fudge it with a placeholder if we're not yet + // inside the layout area. + this.postponed_macro = state.build.postponed_macro; + target.push(this); + } else { + // + // tag this token with the name of the postponed macro + this.postponed_macro = state.build.postponed_macro; + // + // push an implict group token with the strings and + // decorations of the invoking text tag + var start_token = new CSL.Factory.Token("group",CSL.START); + for (i in this.strings){ + start_token.strings[i] = this.strings[i]; + } + start_token.decorations = this.decorations; + var newoutput = function(state,Item){ + state.output.startTag("group",this); + //state.tmp.decorations.push(this.decorations); + }; + start_token["execs"].push(newoutput); + target.push(start_token); + + // + // Special handling for text macros inside a substitute + // environment. + if (state.build.names_substituting){ + // + // A text macro inside a substitute environment is + // treated as a special conditional. + var choose_start = new CSL.Factory.Token("choose",CSL.START); + target.push(choose_start); + var if_start = new CSL.Factory.Token("if",CSL.START); + // + // Here's the Clever Part. + // Set a test of the shadow if token to skip this + // macro if we have acquired a name value. + var check_for_variable = function(state,Item){ + if (state.tmp.value){ + return true; + } + return false; + }; + if_start.tests.push(check_for_variable); + // + // this is cut-and-paste of the "any" evaluator + // function, from Attributes. These functions + // should be defined in a namespace for reuse. + var evaluator = function(state,Item){ + var res = this.fail; + state.tmp.jump.replace("fail"); + for each (var func in this.tests){ + if (func.call(this,state,Item)){ + res = this.succeed; + state.tmp.jump.replace("succeed"); + break; + } + } + return res; + }; + if_start.evaluator = evaluator; + target.push(if_start); + + var macro = CSL.Factory.expandMacro.call(state,this); + for each (var t in macro){ + target.push(t); + } + + var if_end = new CSL.Factory.Token("if",CSL.END); + target.push(if_end); + var choose_end = new CSL.Factory.Token("choose",CSL.END); + target.push(choose_end); + } else { + var macro = CSL.Factory.expandMacro.call(state,this); + for each (var t in macro){ + target.push(t); + } + } + + var end_token = new CSL.Factory.Token("group",CSL.END); + var mergeoutput = function(state,Item){ + // + // rendering happens inside the + // merge method, by applying decorations to + // each token to be merged. + state.output.endTag(); + }; + end_token["execs"].push(mergeoutput); + target.push(end_token); + + state.build.names_substituting = false; + } + state.build.postponed_macro = false; + } else { + // ... + // + // Do non-macro stuff + var variable = this.variables[0]; + if ("citation-number" == variable || "year-suffix" == variable){ + // + // citation-number and year-suffix are super special, + // because they are rangeables, and require a completely + // different set of formatting parameters on the output + // queue. + if (variable == "citation-number"){ + this.strings.is_rangeable = true; + var func = function(state,Item){ + var id = Item["id"]; + if (!state.tmp.force_subsequent){ + var num = state.registry.registry[id].seq; + // + // DO SOMETHING USEFUL HERE + // + var number = new CSL.Output.Number(num,this); + state.output.append(number,"literal"); + } + }; + this["execs"].push(func); + } else if (variable == "year-suffix"){ + var func = function(state,Item){ + if (state.registry.registry[Item.id] && state.registry.registry[Item.id].disambig[2]){ + state.tmp.delimiter.replace(""); + state.output.append(state.registry.registry[Item.id].disambig[2],this); + // + // don't ask :) + // obviously the variable naming scheme needs + // a little touching up + var firstoutput = state.tmp.term_sibling.mystack.indexOf(true) == -1; + var specialdelimiter = state[state.tmp.area].opt["year-suffix-delimiter"]; + if (firstoutput && specialdelimiter && !state.tmp.sort_key_flag){ + state.tmp.splice_delimiter = state[state.tmp.area].opt["year-suffix-delimiter"]; + } + } + }; + this["execs"].push(func); + } + + } else { + if (state.build.term){ + var term = state.build.term; + var form = "long"; + var plural = 0; + if (state.build.form){ + form = state.build.form; + } + if (state.build.plural){ + plural = state.build.plural; + } + term = state.opt.term[term][form][plural]; + var printterm = function(state,Item){ + // capitalize the first letter of a term, if it is the + // first thing rendered in a citation (or if it is + // being rendered immediately after terminal punctuation, + // I guess, actually). + if (!state.tmp.term_predecessor){ + //print("Capitalize"); + term = CSL.Output.Formatters.capitalize_first(term); + state.tmp.term_predecessor = false; + }; + state.output.append(term,this); + }; + this["execs"].push(printterm); + state.build.term = false; + state.build.form = false; + state.build.plural = false; + } else if (variable){ + var func = function(state,Item){ + if (this.variables.length){ + state.fun.mark_output(state,Item[variable]); + state.output.append(Item[variable],this); + //state.tmp.value.push(Item[variable]); + } + }; + this["execs"].push(func); + } else if (this.strings.value){ + var func = function(state,Item){ + state.output.append(this.strings.value,this); + }; + this["execs"].push(func); + } else { + var weird_output_function = function(state,Item){ + if (state.tmp.value.length){ + print("Weird output pattern. Can this be revised?"); + for each (var val in state.tmp.value){ + state.output.append(val,this); + } + state.tmp.value = new Array(); + } + }; + this["execs"].push(weird_output_function); + } + } + target.push(this); + }; + } +}; + + +/** + * Macro node, start and end. + *

Because macros are expanded into the body of the style, + * their element function requires only a build method.

+ * @name CSL.Lib.Elements.macro + * @function + */ +CSL.Lib.Elements.macro = new function(){ + this.build = build; + /* + * Executed on token + */ + function build (state,target){ + if (this.tokentype == CSL.START){ + state.build.name = this.strings.name; + var bufferlist = new Array(); + state.build.children.push(bufferlist); + } else { + // + // catch repeated declarations of the same macro name + if (state.build.macro[state.build.name]){ + throw "CSL processor error: repeated declaration of macro \""+state.build.name+"\""; + } + // + // is this slice really needed? + state.build.macro[state.build.name] = target.slice(); + state.build.name = false; + state.build.children = new Array();; + } + } +}; + + +/** + * Locale node, start and end. + *

Sets a flag on the state, to cause terms to + * be stored in a state object for later processing.

+ * @name CSL.Lib.Elements.locale + */ +CSL.Lib.Elements.locale = new function(){ + this.build = build; + function build(state,target){ + if (this.tokentype == CSL.START){ + if (state.opt.lang && state.build.lang != state.opt.lang){ + state.build.skip = true; + } else { + state.build.skip = false; + } + } + } +}; + + +/** + * Terms node. + *

This is a noop.

+ * @name CSL.Lib.Elements.terms + * @function + */ +CSL.Lib.Elements.terms = new function(){ + this.build = build; + function build(state,target){ + } +}; + + +/** + * Term node, start and end. + * @name CSL.Lib.Elements.term + * @function + */ +CSL.Lib.Elements.term = new function(){ + this.build = build; + function build (state,target){ + if (this.tokentype == CSL.START){ + var bufferlist = new Array(); + state.build.children.push(bufferlist); + state.build.name = this.strings.name; + state.build.form = this.strings.form; + + } else { + if (state.build.text){ + var single = new CSL.Factory.Token("single",CSL.SINGLETON); + var multiple = new CSL.Factory.Token("multiple",CSL.SINGLETON); + target.push(single); + target.push(multiple); + for (i in target){ + target[i]["string"] = state.build.text; + } + state.build.text = false; + } + // set strings from throwaway tokens to term object + var termstrings = new Array(); + // target should be pointing at the state.build.children + // array, set by the start tag above + for (i in target){ + termstrings.push(target[i].string); + } + // initialize object for this term + if (!state.opt.term[state.build.name]){ + state.opt.term[state.build.name] = new Object(); + } + // + // long writes to long and any unused form key. + // + // short writes to short and to symbol if it is unused + // + // verb writes to verb and to verb-short if it is unused + // + // symbol and verb-short write only to themselves + if (!state.build.form){ + state.build.form = "long"; + } + var keywrites = new Object(); + keywrites["long"] = ["verb-short","symbol","verb","short","long"]; + keywrites["short"] = ["symbol"]; + keywrites["verb"] = ["verb-short"]; + keywrites["symbol"] = []; + keywrites["verb-short"] = []; + // forced write + state.opt.term[state.build.name][state.build.form] = termstrings; + if ( !state.build.in_style ){ + // shy write, performed only when external locale + // is loaded. + for each (var key in keywrites[state.build.form]){ + if (!state.opt.term[state.build.name][key]){ + state.opt.term[state.build.name][key] = termstrings; + } + } + } + state.build.name = false; + state.build.form = false; + state.build.children = new Array(); + } + } +}; + + +/** + * Single term node. + * @name CSL.Lib.Elements.single + * @function + */ +CSL.Lib.Elements.single = new function(){ + this.build = build; + function build(state,target){ + if (this.tokentype == CSL.END){ + this["string"] = state.build.text; + this["key"] = state.build.name; + state.build.text = false; + target.push(this); + } + } +}; + +/** + * Multiple term node. + * @name CSL.Lib.Elements.multiple + * @function + */ +CSL.Lib.Elements.multiple = new function(){ + this.build = build; + function build(state,target){ + if (this.tokentype == CSL.END){ + this["string"] = state.build.text; + this["key"] = state.build.name; + state.build.text = false; + target.push(this); + } + } +}; + +/** + * The group node, start and end. + * @name CSL.Lib.Elements.group + * @function + */ +CSL.Lib.Elements.group = new function(){ + this.build = build; + function build (state,target){ + if (this.tokentype == CSL.START){ + + var newoutput = function(state,Item){ + state.output.startTag("group",this); + }; + // + // Paranoia. Assure that this init function is the first executed. + var execs = new Array(); + execs.push(newoutput); + this.execs = execs.concat(this.execs); + + var fieldcontentflag = function(state,Item){ + state.tmp.term_sibling.push( undefined, CSL.LITERAL ); + }; + this["execs"].push(fieldcontentflag); + } else { + var quashnonfields = function(state,Item){ + var flag = state.tmp.term_sibling.value(); + if (false == flag){ + state.output.clearlevel(); + } + state.tmp.term_sibling.pop(); + }; + this["execs"].push(quashnonfields); + + var mergeoutput = function(state,Item){ + // + // rendering happens inside the + // merge method, by applying decorations to + // each token to be merged. + state.output.endTag(); + }; + this["execs"].push(mergeoutput); + } + target.push(this); + } +}; + +/** + * Citation element + */ +CSL.Lib.Elements.citation = new function(){ + this.build = build; + function build (state,target){ + if (this.tokentype == CSL.START) { + state.build.area_return = state.build.area; + state.build.area = "citation"; + } + if (this.tokentype == CSL.END) { + state.build.area = state.build.area_return; + } + } +}; + +/** + * The choose node, start and end. + * @name CSL.Lib.Elements.choose + * @function + */ +CSL.Lib.Elements.choose = new function(){ + this.build = build; + this.configure = configure; + function build (state,target){ + if (this.tokentype == CSL.START){ + var func = function(state,Item){ //open condition + state.tmp.jump.push(undefined, CSL.LITERAL); + }; + } + if (this.tokentype == CSL.END){ + var func = function(state,Item){ //close condition + state.tmp.jump.pop(); + }; + } + this["execs"].push(func); + target.push(this); + } + function configure(state,pos){ + if (this.tokentype == CSL.END){ + state.configure["fail"].push((pos+1)); + state.configure["succeed"].push((pos+1)); + } else { + state.configure["fail"].pop(); + state.configure["succeed"].pop(); + } + } +}; + + +/** + * The if node, start and end. + * @name CSL.Lib.Elements.if + * @function + */ +CSL.Lib.Elements["if"] = new function(){ + this.build = build; + this.configure = configure; + function build (state,target){ + if (this.tokentype == CSL.START){ + if (! this.evaluator){ + // + // cut and paste of "any" + this.evaluator = function(state,Item){ + var res = this.fail; + state.tmp.jump.replace("fail"); + for each (var func in this.tests){ + if (func.call(this,state,Item)){ + res = this.succeed; + state.tmp.jump.replace("succeed"); + break; + } + } + return res; + }; + }; + } + if (this.tokentype == CSL.END){ + var closingjump = function(state,Item){ + var next = this[state.tmp.jump.value()]; + return next; + }; + this["execs"].push(closingjump); + }; + target.push(this); + } + function configure(state,pos){ + if (this.tokentype == CSL.START){ + // jump index on failure + this["fail"] = state.configure["fail"][(state.configure["fail"].length-1)]; + this["succeed"] = this["next"]; + } else { + // jump index on success + this["succeed"] = state.configure["succeed"][(state.configure["succeed"].length-1)]; + this["fail"] = this["next"]; + } + } +}; + + +/** + * The else-if node, start and end. + * @name CSL.Lib.Elements.else-if + * @function + */ +CSL.Lib.Elements["else-if"] = new function(){ + this.build = build; + this.configure = configure; + // + // these function are the same as those in if, might just clone + function build (state,target){ + if (this.tokentype == CSL.START){ + if (! this.evaluator){ + // + // cut and paste of "any" + this.evaluator = function(state,Item){ + var res = this.fail; + state.tmp.jump.replace("fail"); + for each (var func in this.tests){ + if (func.call(this,state,Item)){ + res = this.succeed; + state.tmp.jump.replace("succeed"); + break; + } + } + return res; + }; + }; + } + if (this.tokentype == CSL.END){ + var closingjump = function(state,Item){ + var next = this[state.tmp.jump.value()]; + return next; + }; + this["execs"].push(closingjump); + }; + target.push(this); + } + function configure(state,pos){ + if (this.tokentype == CSL.START){ + // jump index on failure + this["fail"] = state.configure["fail"][(state.configure["fail"].length-1)]; + this["succeed"] = this["next"]; + state.configure["fail"][(state.configure["fail"].length-1)] = pos; + } else { + // jump index on success + this["succeed"] = state.configure["succeed"][(state.configure["succeed"].length-1)]; + this["fail"] = this["next"]; + } + } +}; + + +/** + * The else node, start and end. + * @name CSL.Lib.Elements.else + * @function + */ +CSL.Lib.Elements["else"] = new function(){ + this.build = build; + this.configure = configure; + function build (state,target){ + target.push(this); + } + function configure(state,pos){ + if (this.tokentype == CSL.START){ + state.configure["fail"][(state.configure["fail"].length-1)] = pos; + } + } +}; + + +/** + * The name node. + * @name CSL.Lib.Elements.name + * @function + */ +CSL.Lib.Elements.name = new function(){ + this.build = build; + function build(state,target){ + + state.build.form = this.strings.form; + state.build.name_flag = true; + + var func = function(state,Item){ + state.output.addToken("name",false,this); + }; + this["execs"].push(func); + + var set_initialize_with = function(state,Item){ + state.tmp["initialize-with"] = this.strings["initialize-with"]; + }; + this["execs"].push(set_initialize_with); + + + target.push(this); + }; +}; + + +/** + * The name node. + * @name CSL.Lib.Elements.name-part + * @function + */ +CSL.Lib.Elements["name-part"] = new function(){ + this.build = build; + function build(state,target){ + // XXXXX problem. can't be global. don't want to remint + // for every rendering. somehow get tokens stored on + // closing names tag static. always safe, b/c + // no conditional branching inside names. + // same treatment for etal styling element. + var set_namepart_format = function(state,Item){ + state.output.addToken(state.tmp.namepart_type,false,this); + }; + this["execs"].push(set_namepart_format); + target.push(this); + }; +}; + + +/** + * The label node. + *

A plural-sensitive localized label.

+ * @name CSL.Lib.Elements.label + * @function + */ +CSL.Lib.Elements.label = new function(){ + this.build = build; + /* + * Account for form option. + */ + function build(state,target){ + if (state.build.name_flag){ + this.strings.label_position = CSL.AFTER; + } else { + this.strings.label_position = CSL.BEFORE; + } + var set_label_info = function(state,Item){ + if (!this.strings.form){ + this.strings.form = "long"; + } + state.output.addToken("label",false,this); + }; + this["execs"].push(set_label_info); + target.push(this); + }; +}; + + +/** + * The substitute node. + *

A special conditional environment for use inside a names node.

+ * @name CSL.Lib.Elements.substitute + * @function + */ +CSL.Lib.Elements.substitute = new function(){ + this.build = build; + function build(state,target){ + if (this.tokentype == CSL.START){ + state.build.names_substituting = true; + var declare_thyself = function(state,Item){ + state.tmp.names_substituting = true; + }; + this["execs"].push(declare_thyself); + }; + target.push(this); + }; +}; + + +/** + * The et-al node. + *

This is a formatting hook for the et-al string + * that is appended to truncated name sets. It also + * permits the specification of the "and others" localized + * term for use instead of the standard et-al string.

+ */ +CSL.Lib.Elements["et-al"] = new function(){ + this.build = build; + function build(state,target){ + var set_et_al_format = function(state,Item){ + state.output.addToken("etal",false,this); + }; + this["execs"].push(set_et_al_format); + target.push(this); + }; +}; + + +/** + * The layout node. + *

The tag environment that marks the end of option declarations + * and encloses the renderable tags.

+ * @name CSL.Lib.Elements.layout + * @function + */ +CSL.Lib.Elements.layout = new function(){ + this.build = build; + function build(state,target){ + if (this.tokentype == CSL.START){ + state.build.layout_flag = true; + + var set_opt_delimiter = function(state,Item){ + // just in case + state.tmp.sort_key_flag = false; + state[state.tmp.area].opt.delimiter = ""; + if (this.strings.delimiter){ + state[state.tmp.area].opt.delimiter = this.strings.delimiter; + }; + }; + this["execs"].push(set_opt_delimiter); + + var reset_nameset_counter = function(state,Item){ + state.tmp.nameset_counter = 0; + }; + this["execs"].push(reset_nameset_counter); + + var declare_thyself = function(state,Item){ + // + // This is not very pretty. + // + state[state.tmp.area].opt.layout_prefix = this.strings.prefix; + state[state.tmp.area].opt.layout_suffix = this.strings.suffix; + state[state.tmp.area].opt.layout_decorations = this.decorations; + state.output.openLevel("empty"); + }; + this["execs"].push(declare_thyself); + + }; + if (this.tokentype == CSL.END){ + state.build.layout_flag = false; + var mergeoutput = function(state,Item){ + state.output.closeLevel(); + state.tmp.name_quash = new Object(); + }; + this["execs"].push(mergeoutput); + } + target.push(this); + }; +}; + + +CSL.Lib.Elements.number = new function(){ + this.build = build; + function build(state,target){ + target.push(this); + }; +}; + + +CSL.Lib.Elements.date = new function(){ + this.build = build; + function build(state,target){ + if (this.tokentype == CSL.START){ + var set_value = function(state,Item){ + state.tmp.value.push(Item[this.variables[0]]); + }; + this["execs"].push(set_value); + + var newoutput = function(state,Item){ + state.output.startTag("date",this); + }; + this["execs"].push(newoutput); + + } else if (this.tokentype == CSL.END){ + var mergeoutput = function(state,Item){ + state.output.endTag(); + }; + this["execs"].push(mergeoutput); + } + target.push(this); + }; +}; + + +CSL.Lib.Elements["date-part"] = new function(){ + this.build = build; + function build(state,target){ + var value = ""; + if (!this.strings.form){ + this.strings.form = "long"; + } + var render_date_part = function(state,Item){ + for each (var val in state.tmp.value){ + value = val[this.strings.name]; + break; + }; + var real = !state.tmp.suppress_decorations; + var invoked = state[state.tmp.area].opt.collapse == "year-suffix"; + var precondition = state[state.tmp.area].opt["disambiguate-add-year-suffix"]; + if (real && precondition && invoked){ + state.tmp.years_used.push(value); + var known_year = state.tmp.last_years_used.length >= state.tmp.years_used.length; + if (known_year){ + if (state.tmp.last_years_used[(state.tmp.years_used.length-1)] == value){ + value = false; + } + } + } + if (value){ + if (this.strings.form){ + value = CSL.Util.Dates[this.strings.name][this.strings.form](state,value); + } + //state.output.startTag(this.strings.name,this); + state.output.append(value,this); + //state.output.endTag(); + }; + state.tmp.value = new Array(); + }; + this["execs"].push(render_date_part); + target.push(this); + }; +}; + + +CSL.Lib.Elements.option = new function(){ + this.build = build; + function build(state,target){ + if (this.strings.name == "collapse"){ + // only one collapse value will be honoured. + if (this.strings.value){ + state[state.tmp.area].opt.collapse = this.strings.value; + } + } + if (CSL.ET_AL_NAMES.indexOf(this.strings.name) > -1){ + if (this.strings.value){ + state[state.tmp.area].opt[this.strings.name] = parseInt(this.strings.value, 10); + } + } + if (CSL.DISAMBIGUATE_OPTIONS.indexOf(this.strings.name) > -1){ + state[state.tmp.area].opt[this.strings.name] = true; + } + if ("year-suffix-delimiter" == this.strings.name){ + state[state.tmp.area].opt["year-suffix-delimiter"] = this.strings.value; + } + target.push(this); + }; +}; + + +CSL.Lib.Elements.bibliography = new function(){ + this.build = build; + function build(state,target){ + if (this.tokentype == CSL.START){ + state.build.area_return = state.build.area; + state.build.area = "bibliography"; + + //var init_sort_keys = function(state,Item){ + // state.tmp.sort_keys = new Array(); + //}; + //this["execs"].push(init_sort_keys); + } + if (this.tokentype == CSL.END){ + state.build.area = state.build.area_return; + } + target.push(this); + }; +}; + + +CSL.Lib.Elements.sort = new function(){ + this.build = build; + function build(state,target){ + if (this.tokentype == CSL.START){ + state.build.sort_flag = true; + state.build.area_return = state.build.area; + state.build.area = state.build.area+"_sort"; + } + if (this.tokentype == CSL.END){ + state.build.area = state.build.area_return; + state.build.sort_flag = false; + } + }; +}; + + +CSL.Lib.Elements.key = new function(){ + this.build = build; + function build(state,target){ + var start_key = new CSL.Factory.Token("key",CSL.START); + start_key.strings["et-al-min"] = this.strings["et-al-min"]; + start_key.strings["et-al-use-first"] = this.strings["et-al-use-first"]; + + var sort_direction = new Array(); + if (this.strings.sort_direction == CSL.DESCENDING){ + sort_direction.push(1); + sort_direction.push(-1); + } else { + sort_direction.push(-1); + sort_direction.push(1); + } + state[state.build.area].opt.sort_directions.push(sort_direction); + + var et_al_init = function(state,Item){ + // + // should default to the area value, with these as override. + // be sure that the area-level value is set correctly, then + // do this up. lots of inheritance, so lots of explicit + // conditions, but it's all very systematic and boring. + // + state.tmp.sort_key_flag = true; + if (this.strings["et-al-min"]){ + state.tmp["et-al-min"] = this.strings["et-al-min"]; + } + if (this.strings["et-al-use-first"]){ + state.tmp["et-al-use-first"] = this.strings["et-al-use-first"]; + } + }; + start_key["execs"].push(et_al_init); + target.push(start_key); + // + // ops to initialize the key's output structures + if (state.build.key_is_variable){ + state.build.key_is_variable = false; + var single_text = new CSL.Factory.Token("text",CSL.SINGLETON); + single_text["execs"] = this["execs"].slice(); + var output_variables = function(state,Item){ + for each(var val in state.tmp.value){ + if (val == "citation-number"){ + state.output.append(state.registry.registry[Item["id"]].seq.toString(),"empty"); + } else { + state.output.append(val,"empty"); + } + } + }; + single_text["execs"].push(output_variables); + target.push(single_text); + } else { + // + + + // if it's not a variable, it's a macro + var token = new CSL.Factory.Token("text",CSL.SINGLETON); + token.postponed_macro = state.build.postponed_macro; + var macro = CSL.Factory.expandMacro.call(state,token); + for each (var t in macro){ + target.push(t); + } + state.build.postponed_macro = false; + } + // + // ops to output the key string result to an array go + // on the closing "key" tag before it is pushed. + // Do not close the level. + var end_key = new CSL.Factory.Token("key",CSL.END); + var store_key_for_use = function(state,Item){ + var keystring = state.output.string(state,state.output.queue); + if (false){ + print("keystring: "+keystring); + } + state[state.tmp.area].keys.push(keystring); + state.tmp.value = new Array(); + }; + end_key["execs"].push(store_key_for_use); + var reset_key_params = function(state,Item){ + state.tmp.name_quash = new Object(); + state.tmp["et-al-min"] = false; + state.tmp["et-al-use-first"] = false; + state.tmp.sort_key_flag = false; + }; + end_key["execs"].push(reset_key_params); + target.push(end_key); + }; +}; diff --git a/src/factory.js b/src/factory.js new file mode 100644 index 000000000..e4ab99633 --- /dev/null +++ b/src/factory.js @@ -0,0 +1,293 @@ +dojo.provide("csl.factory"); +if (!CSL) { + load("./src/csl.js"); +} + +/** + * Factory functions to build the token list representation of a style. + *

The functions here are invoked via {@link CSL.Core.Build} and {@link CSL.Core.Configure}.

+ * @namespace Factory functions to create precompiled token objects from XML source. + */ +CSL.Factory = {}; + + +CSL.Factory.version = function(){ + var msg = "\"Entropy\" citation processor (a.k.a. citeproc-js) ver.0.01"; + print(msg); + return msg; +}; + + +/** + * Convert XML node to token. + *

This is called on an XML node. After extracting the name and attribute + * information from the node, it performs three operations. Attribute information + * relating to output formatting is stored on the node as an array of tuples, + * which fixes the sequence of execution of output functions to be invoked + * in the next phase of processing. Other attribute information is reduced + * to functions, and is pushed into an array on the token in no particular + * order, for later execution. The element name is used as a key to + * invoke the relevant build method of the target element. + * Element methods are defined in {@link CSL.Lib.Elements}.

+ * @param {Object} state The state object returned by {@link CSL.Factory.State}. + * @param {Int} tokentype A CSL namespace constant (CSL.START, + * CSL.END or CSL.SINGLETON. + */ +CSL.Factory.XmlToToken = function(state,tokentype){ + var name = state.build.xmlCommandInterface.nodename.call(this); + // print(tokentype + " : " + name); + if (state.build.skip && state.build.skip != name){ + return; + } + if (!name){ + var txt = state.build.xmlCommandInterface.content.call(this); + if (txt){ + state.build.text = txt; + } + return; + } + if ( ! CSL.Lib.Elements[state.build.xmlCommandInterface.nodename.call(this)]){ + throw "Undefined node name \""+name+"\"."; + } + var attrfuncs = new Array(); + var attributes = state.build.xmlCommandInterface.attributes.call(this); + var decorations = CSL.Factory.setDecorations.call(this,state,attributes); + var token = new CSL.Factory.Token(name,tokentype); + for (var key in attributes){ + try { + var attrfunc = CSL.Lib.Attributes[key].call(token,state,attributes[key]); + } catch (e) { + if (e == "TypeError: Cannot call method \"call\" of undefined"){ + throw "Unknown attribute \""+key+"\" in node \""+name+"\" while processing CSL file"; + } else { + throw "CSL processor error, "+key+" attribute: "+e; + } + } + if (attrfunc){ + attrfuncs.push(attrfunc); + } + } + token.decorations = decorations; + if (state.build.children.length){ + var target = state.build.children[0]; + } else { + var target = state[state.build.area].tokens; + } + CSL.Lib.Elements[name].build.call(token,state,target); +}; + + +CSL.Factory.mark_output = function(state,content){ + if (content){ + state.tmp.term_sibling.replace( true ); + } else { + if (undefined == state.tmp.term_sibling.value()) { + state.tmp.term_sibling.replace( false, CSL.LITERAL ); + } + } +} + +/** + * Generate a separate list of formatting attributes. + *

This generates a list of tuples containing attribute + * information relevant to output formatting, in the order + * fixed in the constant {@link CSL.FORMAT_KEY_SEQUENCE}. + * This function is called during {@link CSL.Core.Build}. + * Formatting hints are distilled to functions + * later, in the second compilation pass ({@link CSL.Core.Configure}).

+ * @param {Object} state The state object returned by + * {@link CSL.Factory.State}. + * @param {Object} attributes The hash object containing + * the attributes and values extracted from an XML node. + */ +CSL.Factory.setDecorations = function(state,attributes){ + // This applies a fixed processing sequence + var ret = new Array(); + for each (var key in CSL.FORMAT_KEY_SEQUENCE){ + if (attributes[key]){ + ret.push([key,attributes[key]]); + delete attributes[key]; + } + } + return ret; +}; + +/** + * Generate string formatting functions. + *

This function is executed in the context of a token + * by {@link CSL.Core.Configure}. + * The list of formatting attributes stored on the token + * is replaced with a list of compiled functions. + * This is applied by {@link CSL.Core.Configure}. + * @param {Array} state The state object returned by + * {@link CSL.Factory.State}. + */ +CSL.Factory.renderDecorations = function(state){ + var ret = new Array(); + for each (hint in this.decorations){ + ret.push(state.fun.decorate[hint[0]][hint[1]]); + } + this.decorations = ret; +}; + + +/** + * Substitution gadget. + *

Creates a function for + * delivering a string merged to a pre-defined template + * with a minimum of fuss.

+ * @param {String} template A template containing + * a %%STRING%% placeholder. See + * {@link CSL.Output.Formats.html} for examples. + */ +CSL.Factory.substituteOne = function(template) { + return function(list) { + if ("string" == typeof list){ + return template.replace("%%STRING%%",list); + } + var decor = template.split("%%STRING%%"); + var ret = [{"is_delimiter":true,"value":decor[0]}].concat(list); + ret.push({"is_delimiter":true,"value":decor[1]}); + return ret; + }; +}; + + +/** + * Two-tiered substitutions gadget. + *

This is used for + * options like "font-family", where the option value + * cannot be determined until the attribute is processed.

+ * @param {String} template A template containing + * %%STRING%% and %%PARAM%% + * placeholders. See {@link CSL.Output.Formats.html} for + * examples. + */ +CSL.Factory.substituteTwo = function(template) { + return function(param) { + var template2 = template.replace("%%PARAM%%", param); + return function(list) { + if ("string" == typeof list){ + return template2.replace("%%STRING%%",list); + } + var decor = template2.split("%%STRING"); + var ret = [{"is_delimiter":true,"value":decor[0]}].concat(list); + ret.push({"is_delimiter":true,"value":decor[1]}); + return ret; + }; + }; +}; + +/** + * Generate string functions for designated output mode. + *

Only "html" (the default) is supported at present.

+ * @param {String} mode Either "html" or "rtf", eventually. + */ +CSL.Factory.Mode = function(mode){ + var decorations = new Object(); + + var params = CSL.Output.Formats[mode]; + for (var param in params) { + var func = false; + var val = params[param]; + var args = param.split('/'); + + if (typeof val == "string" && val.indexOf("%%STRING%%") > -1) { + if (val.indexOf("%%PARAM%%") > -1) { + func = CSL.Factory.substituteTwo(val); + } else { + func = CSL.Factory.substituteOne(val); + } + } else if (typeof val == "boolean" && !val) { + func = CSL.Output.Formatters.passthrough; + } else if (typeof val == "function") { + func = val; + } else { + throw "CSL.Compiler: Bad "+mode+" config entry for "+param+": "+val; + } + + if (args.length == 1) { + decorations[args[0]] = func; + } else if (args.length == 2) { + if (!decorations[args[0]]) { + decorations[args[0]] = new Object(); + } + decorations[args[0]][args[1]] = func; + } + } + return decorations; +}; + + +/** + * Macro expander. + *

Called on the state object.

+ */ +CSL.Factory.expandMacro = function(macro_key_token){ + var mkey = macro_key_token.postponed_macro; + if (this.build.macro_stack.indexOf(mkey) > -1){ + throw "CSL processor error: call to macro \""+mkey+"\" would cause an infinite loop"; + } else { + this.build.macro_stack.push(mkey); + } + var ret = new Array(); + // + // XXXXX This implicit group stuff can be dropped, I think. + // XXXXX Macros don't take decorations or anything. + var start_token = new CSL.Factory.Token("group",CSL.START); + ret.push(start_token); + + for (var i in this.build.macro[mkey]){ + // + // could use for each; this was an attempt to get a + // fresh copy of the token to defeat a loop involving + // interaction between sort and citation render. had + // no effect, probably not needed. + var token = this.build.macro[mkey][i]; + if (token.postponed_macro){ + // + // nested expansion + ret.concat(CSL.Factory.expandMacro.call(this,token)); + } else { + // + // clone the token, so that navigation pointers are + // specific to the token list into which the macro + // is being expanded. + var newtoken = new Object(); + for (i in token) { + newtoken[i] = token[i]; + } + ret.push(newtoken); + } + } + + var end_token = new CSL.Factory.Token("group",CSL.END); + ret.push(end_token); + + this.build.macro_stack.pop(); + + return ret; +}; + + +CSL.Factory.cloneAmbigConfig = function(config){ + var ret = new Object(); + ret["names"] = new Array(); + ret["givens"] = new Array(); + ret["year_suffix"] = false; + ret["disambiguate"] = false; + for (var i in config["names"]){ + var param = config["names"][i]; + ret["names"][i] = param; + } + for (var i in config["givens"]){ + var param = new Array(); + for (var j in config["givens"][i]){ + param.push(config["givens"][i][j]); + } + ret["givens"].push(param); + } + ret["year_suffix"] = config["year_suffix"]; + ret["disambiguate"] = config["disambiguate"]; + return ret; +}; diff --git a/src/formats.js b/src/formats.js new file mode 100644 index 000000000..7ea28ee30 --- /dev/null +++ b/src/formats.js @@ -0,0 +1,42 @@ +dojo.provide("csl.formats"); +if (!CSL) { + load("./src/csl.js"); +} + +/** + * Output specifications. + * @class + */ +CSL.Output.Formats = function(){}; + +/** + * HTML output format specification. + *

The headline says it all. The source code for this + * object can be used as a template for producing other + * output modes.

+ */ +CSL.Output.Formats.prototype.html = { + "@font-family":"%%STRING%%", + "@font-style/italic":"%%STRING%%", + "@font-style/normal":false, + "@font-style/oblique":"%%STRING%%", + "@font-variant/small-caps":"%%STRING%%", + "@font-variant/normal":false, + "@font-weight/bold":"%%STRING%%", + "@font-weight/normal":false, + "@font-weight/light":false, + "@text-decoration/none":false, + "@text-decoration/underline":"%%STRING%%", + "@vertical-align/baseline":false, + "@vertical-align/sup":"%%STRING%%", + "@vertical-align/sub":"%%STRING%%", + "@text-case/lowercase":CSL.Output.Formatters.lowercase, + "@text-case/uppercase":CSL.Output.Formatters.uppercase, + "@text-case/capitalize-first":CSL.Output.Formatters.capitalize_first, + "@text-case/capitalize-all":CSL.Output.Formatters.capitalize_all, + "@text-case/title":CSL.Output.Formatters.title_capitalization, + "@text-case/sentence":CSL.Output.Formatters.sentence_capitalization, + "@quotes":"&lquo;%%STRING%%&rquo;" +}; + +CSL.Output.Formats = new CSL.Output.Formats(); \ No newline at end of file diff --git a/src/formatters.js b/src/formatters.js new file mode 100644 index 000000000..ccf5ca778 --- /dev/null +++ b/src/formatters.js @@ -0,0 +1,156 @@ +dojo.provide("csl.formatters"); +if (!CSL) { + load("./src/csl.js"); +} + +/** + * A bundle of handy functions for text processing. + *

Several of these are ripped off from various + * locations in the Zotero source code.

+ * @namespace Toolkit of string functions + */ +CSL.Output.Formatters = new function(){}; + +/** + * A noop that just delivers the string. + */ +CSL.Output.Formatters.passthrough = function(string){ + return string; +}; + +// +// XXXXX +// A bit of interest coming up with vertical-align. +// This needs to include the prefixes and suffixes +// in its scope, so it's applied last, AFTER they +// are appended to the string. I think it's the +// only one that will need to work that way. + + +/** + * Force all letters in the string to lowercase. + */ +CSL.Output.Formatters.lowercase = function(string) { + // + // XXXXX + // this listiness in lowercase and uppercase should + // be handled when decorations are applied; these + // functions should not have to worry about it. + // XXXXX + // the listiness stuff can go away now. + if ("object" == typeof string){ + var ret = new Array(); + for each (item in string){ + ret.push(item.LowerCase()); + } + return ret; + } + return string.LowerCase(); +}; + + +/** + * Force all letters in the string to uppercase. + */ +CSL.Output.Formatters.uppercase = function(string) { + if ("object" == typeof string){ + var ret = new Array(); + for each (item in string){ + ret.push(item.toUpperCase()); + } + return ret; + } + return string.toUpperCase(); +}; + + +/** + * Force capitalization of the first letter in the string, leave + * the rest of the characters untouched. + */ +CSL.Output.Formatters.capitalize_first = function(string) { + return string[0].toUpperCase()+string.substr(1); +}; + + +/** + * Similar to capitalize_first, but force the + * subsequent characters to lowercase. + */ +CSL.Output.Formatters.sentence_capitalization = function(string) { + return string[0].toUpperCase()+string.substr(1).toLowerCase(); +}; + + +/** + * Force the first letter of each space-delimited + * word in the string to uppercase, and force remaining + * letters to lowercase. Single characters are forced + * to uppercase. + */ +CSL.Output.Formatters.capitalize_all = function(string) { + var strings = string.split(" "); + for(var i=0; i 1) { + strings[i] = strings[i][0].toUpperCase()+strings[i].substr(1).toLowerCase(); + } else if(strings[i].length == 1) { + strings[i] = strings[i].toUpperCase(); + } + } + return strings.join(" "); +}; + + +/** + * A complex function that attempts to produce a pattern + * of capitalization appropriate for use in a title. + * Will not touch words that have some capitalization + * already; to force reformatting, convert the string + * to all uppercase or lowercase before passing it to + * this function. + */ +CSL.Output.Formatters.title_capitalization = function(string) { + if (!string) { + return ""; + } + + // split words + var words = string.split(delimiterRegexp); + var isUpperCase = string.toUpperCase() == string; + + var newString = ""; + var delimiterOffset = words[0].length; + var lastWordIndex = words.length-1; + var previousWordIndex = -1; + for(var i=0; i<=lastWordIndex; i++) { + // only do manipulation if not a delimiter character + if(words[i].length != 0 && (words[i].length != 1 || !delimiterRegexp.test(words[i]))) { + var upperCaseVariant = words[i].toUpperCase(); + var lowerCaseVariant = words[i].toLowerCase(); + + // only use if word does not already possess some capitalization + if(isUpperCase || words[i] == lowerCaseVariant) { + if( + // a skip word + skipWords.indexOf(lowerCaseVariant.replace(/[^a-zA-Z]+/, "")) != -1 + // not first or last word + && i != 0 && i != lastWordIndex + // does not follow a colon + && (previousWordIndex == -1 || words[previousWordIndex][words[previousWordIndex].length-1] != ":") + ) { + words[i] = lowerCaseVariant; + } else { + // this is not a skip word or comes after a colon; + // we must capitalize + words[i] = upperCaseVariant[0] + lowerCaseVariant.substr(1); + } + } + previousWordIndex = i; + } + + newString += words[i]; + } + return newString; +}; + + diff --git a/src/lib.js b/src/lib.js new file mode 100644 index 000000000..3ee3b317f --- /dev/null +++ b/src/lib.js @@ -0,0 +1,12 @@ +dojo.provide("csl.lib"); +if (!CSL) { + load("./src/csl.js"); +} +/** + * Functions for processing CSL node elements and attributes. + *

Function names correspond to CSL element + * and attribute names.

+ * @namespace Functions corresponding CSL elements and attributes. + */ +CSL.Lib = {}; + diff --git a/src/libnames.js b/src/libnames.js new file mode 100644 index 000000000..3f462e65b --- /dev/null +++ b/src/libnames.js @@ -0,0 +1,287 @@ +dojo.provide("csl.libnames"); +if (!CSL) { + load("./src/csl.js"); +} + +/** + * The names node, start and end. + *

Name handling happens here. It's ... complicated.

+ * @name CSL.Lib.Elements.names + * @function + */ +CSL.Lib.Elements.names = new function(){ + this.build = build; + function build(state,target){ + if (this.tokentype == CSL.START || this.tokentype == CSL.SINGLETON){ + + var init_names = function(state,Item){ + if (state.tmp.value.length == 0){ + for each (var variable in this.variables){ + // + // If the item has been marked for quashing, skip it. + if (Item[variable] && ! state.tmp.name_quash[variable]){ + state.fun.mark_output(state,Item[variable]); + state.tmp.names_max.push(Item[variable].length); + state.tmp.value.push({"type":variable,"names":Item[variable]}); + // saving relevant names separately, for reference + // in splice collapse + state.tmp.names_used.push(state.tmp.value.slice()); + } + }; + } + }; + this["execs"].push(init_names); + }; + + if (this.tokentype == CSL.START){ + + state.build.names_flag = true; + + var set_et_al_params = function(state,Item){ + state.output.startTag("names",this); + // + // No value or zero means a first reference, + // anything else is a subsequent reference. + if (Item.position || state.tmp.force_subsequent){ + if (! state.tmp["et-al-min"]){ + if (state[state.tmp.area].opt["et-al-subsequent-min"]){ + state.tmp["et-al-min"] = state[state.tmp.area].opt["et-al-subsequent-min"]; + } else { + state.tmp["et-al-min"] = state[state.tmp.area].opt["et-al-min"]; + } + } + if (! state.tmp["et-al-use-first"]){ + if (state[state.tmp.area].opt["et-al-subsequent-use-first"]){ + state.tmp["et-al-use-first"] = state[state.tmp.area].opt["et-al-subsequent-use-first"]; + } else { + state.tmp["et-al-use-first"] = state[state.tmp.area].opt["et-al-use-first"]; + } + } + } else { + if (! state.tmp["et-al-min"]){ + state.tmp["et-al-min"] = state[state.tmp.area].opt["et-al-min"]; + } + if (! state.tmp["et-al-use-first"]){ + state.tmp["et-al-use-first"] = state[state.tmp.area].opt["et-al-use-first"]; + } + } + }; + this["execs"].push(set_et_al_params); + }; + + if (this.tokentype == CSL.END){ + + var handle_names = function(state,Item){ + var namesets = new Array(); + var common_term = state.fun.get_common_term(state,state.tmp.value); + if (common_term){ + namesets = state.tmp.value.slice(0,1); + } else { + namesets = state.tmp.value; + } + var local_count = 0; + var nameset = new Object(); + + state.output.addToken("space"," "); + state.output.addToken("sortsep",state.output.getToken("name").strings["sort-separator"]); + + if (!state.output.getToken("etal")){ + state.output.addToken("etal-join",", "); + state.output.addToken("etal"); + } else { + state.output.addToken("etal-join",""); + } + if (!state.output.getToken("label")){ + state.output.addToken("label"); + } + if (!state.output.getToken("etal").strings.et_al_term){ + state.output.getToken("etal").strings.et_al_term = state.opt.term["et-al"]["long"][0]; + } + state.output.addToken("commasep",", "); + for each (namepart in ["secondary-key","primary-key","prefix","suffix"]){ + if (!state.output.getToken(namepart)){ + state.output.addToken(namepart); + } + } + for (var namesetIndex in namesets){ + nameset = namesets[namesetIndex]; + if (!state.tmp.suppress_decorations && (state[state.tmp.area].opt.collapse == "year" || state[state.tmp.area].opt.collapse == "year-suffix")){ + if (state.tmp.last_names_used.length == state.tmp.names_used.length){ + var lastones = state.tmp.last_names_used[state.tmp.nameset_counter]; + var currentones = state.tmp.names_used[state.tmp.nameset_counter]; + var compset = currentones.concat(lastones); + if (state.fun.get_common_term(state,compset)){ + continue; + } + } + } + if (!state.tmp.disambig_request){ + state.tmp.disambig_settings["givens"][state.tmp.nameset_counter] = new Array(); + } + // + // Here is where we maybe truncate the list of + // names, to satisfy the et-al constraints. + var display_names = nameset.names.slice(); + var sane = state.tmp["et-al-min"] >= state.tmp["et-al-use-first"]; + // + // if there is anything on name request, we assume that + // it was configured correctly via state.names_request + // by the function calling the renderer. + var discretionary_names_length = state.tmp["et-al-min"]; + + // + // if rendering for display, do not honor a disambig_request + // to set names length below et-al-use-first + // + if (state.tmp.suppress_decorations){ + if (state.tmp.disambig_request){ + discretionary_names_length = state.tmp.disambig_request["names"][state.tmp.nameset_counter]; + } else if (display_names.length >= state.tmp["et-al-min"]){ + discretionary_names_length = state.tmp["et-al-use-first"]; + } + } else { + if (state.tmp.disambig_request && state.tmp["et-al-use-first"] < state.tmp.disambig_request["names"][state.tmp.nameset_counter]){ + discretionary_names_length = state.tmp.disambig_request["names"][state.tmp.nameset_counter]; + } else if (display_names.length >= state.tmp["et-al-min"]){ + discretionary_names_length = state.tmp["et-al-use-first"]; + } + } + var overlength = display_names.length > discretionary_names_length; + var et_al = false; + var and_term = false; + if (sane && overlength){ + if (! state.tmp.sort_key_flag){ + et_al = state.output.getToken("etal").strings.et_al_term; + } + display_names = display_names.slice(0,discretionary_names_length); + } else { + if (state.output.getToken("name").strings["and"] && ! state.tmp.sort_key_flag && display_names.length > 1){ + and_term = state.output.getToken("name").strings["and"]; + } + + } + state.tmp.disambig_settings["names"][state.tmp.nameset_counter] = display_names.length; + local_count += display_names.length; + + // + // "name" is the format for the outermost nesting of a nameset + // "inner" is a format consisting only of a delimiter, used for + // joining all but the last name in the set together. + var delim = state.output.getToken("name").strings.delimiter; + state.output.addToken("inner",delim); + //state.tmp.tokenstore["and"] = new CSL.Factory.Token("and"); + if (and_term){ + state.output.formats.value()["name"].strings.delimiter = and_term; + } + for (var i in nameset.names){ + // + // set the display mode default for givennames if required + if (state.tmp.disambig_request){ + // + // fix a request for initials that makes no sense. + // can't do this in disambig, because the availability + // of initials is not a global parameter. + var val = state.tmp.disambig_settings["givens"][state.tmp.nameset_counter][i]; + if (val == 1 && ! state.tmp["initialize-with"]){ + val = 2; + } + var param = val; + } else { + var param = 2; + if (state.output.getToken("name").strings.form == "short"){ + param = 0; + } else if ("string" == typeof state.tmp["initialize-with"]){ + param = 1; + } + } + state.tmp.disambig_settings["givens"][state.tmp.nameset_counter][i] = param; + } + // + // configure label if poss + var label = false; + if (state.output.getToken("label").strings.label_position){ + var term; + if (common_term){ + term = common_term; + } else { + term = state.opt.term[nameset.type]; + } + if (nameset.names.length > 1){ + label = term[state.output.getToken("label").strings.form][1]; + } else { + label = term[state.output.getToken("label").strings.form][0]; + } + }; + // + // Nesting levels are opened to control joins with + // content at the end of the names block + // + + // Gotcha. Don't want to use startTag here, it pushes + // a fresh format token namespace, and we lose our pointer.] + // Use openLevel (and possibly addToken) instead. + + state.output.openLevel("empty"); // for term join + + if (label && state.output.getToken("label").strings.label_position == CSL.BEFORE){ + state.output.append(label,"label"); + } + + + state.output.openLevel("etal-join"); // join for etal + + CSL.Util.Names.outputNames(state,display_names); + + if (et_al){ + state.output.append(et_al,"etal"); + } + + state.output.closeLevel(); // etal + + if (label && state.tmp.name_label_position != CSL.BEFORE){ + state.output.append(label,"label"); + } + + state.output.closeLevel(); // term + + state.tmp.nameset_counter += 1; + }; + + if (state.output.getToken("name").strings.form == "count"){ + state.output.clearlevel(); + state.output.append(local_count.toString()); + state.tmp["et-al-min"] = false; + state.tmp["et-al-use-first"] = false; + } + }; + this["execs"].push(handle_names); + }; + + if (this.tokentype == CSL.END && state.build.form == "count" && false){ + state.build.form = false; + + var output_name_count = function(state,Item){ + var name_count = 0; + for each (var v in this.variables){ + if(Item[v] && Item[v].length){ + name_count += Item[v].length; + } + } + state.output.append(name_count.toString()); + }; + this["execs"].push(output_name_count); + }; + + if (this.tokentype == CSL.END){ + var unsets = function(state,Item){ + state.fun.names_reinit(state,Item); + state.output.endTag(); // names + }; + this["execs"].push(unsets); + + state.build.names_flag = false; + state.build.name_flag = false; + } + target.push(this); + } +}; \ No newline at end of file diff --git a/src/output.js b/src/output.js new file mode 100644 index 000000000..934459259 --- /dev/null +++ b/src/output.js @@ -0,0 +1,13 @@ +dojo.provide("csl.output"); +if (!CSL){ + load("./src/csl.js"); +} + +/** + * Output functions and specifications. + *

Various bits and pieces related to output are + * collected here. To create or modify a format, check + * out the file formats.js.

+ * @namespace Output formats and configuration bundles. + */ +CSL.Output = {}; diff --git a/src/queue.js b/src/queue.js new file mode 100644 index 000000000..854da2b03 --- /dev/null +++ b/src/queue.js @@ -0,0 +1,248 @@ +dojo.provide("csl.queue"); +if (!CSL) { + load("./src/csl.js"); +} + + +/** + * Output queue object. + * @class + */ +CSL.Output.Queue = function(state){ + this.state = state; + this.queue = new Array(); + this.empty = new CSL.Factory.Token("empty"); + var tokenstore = {}; + tokenstore["empty"] = this.empty; + this.formats = new CSL.Factory.Stack( tokenstore ); + this.current = new CSL.Factory.Stack( this.queue ); + this.suppress_join_punctuation = false; +}; + +CSL.Output.Queue.prototype.getToken = function(name){ + var ret = this.formats.value()[name]; + return ret; +}; + +// Store a new output format token based on another +CSL.Output.Queue.prototype.addToken = function(name,modifier,token){ + var newtok = new CSL.Factory.Token("output"); + if ("string" == typeof token){ + token = this.formats.value()[token]; + } + if (token && token.strings){ + for (attr in token.strings){ + newtok.strings[attr] = token.strings[attr]; + } + newtok.decorations = token.decorations; + + } + if ("string" == typeof modifier){ + newtok.strings.delimiter = modifier; + } + this.formats.value()[name] = newtok; +}; + +// +// newFormat adds a new bundle of formatting tokens to +// the queue's internal stack of such bundles +CSL.Output.Queue.prototype.pushFormats = function(tokenstore){ + if (!tokenstore){ + tokenstore = new Object(); + } + tokenstore["empty"] = this.empty; + this.formats.push(tokenstore); +}; + + +CSL.Output.Queue.prototype.popFormats = function(tokenstore){ + this.formats.pop(); +}; + +CSL.Output.Queue.prototype.startTag = function(name,token){ + var tokenstore = {}; + tokenstore[name] = token; + this.pushFormats( tokenstore ); + this.openLevel(name); +} + +CSL.Output.Queue.prototype.endTag = function(){ + this.closeLevel(); + this.popFormats(); +} + +// +// newlevel adds a new blob object to the end of the current +// list, and adjusts the current pointer so that subsequent +// appends are made to blob list of the new object. + +CSL.Output.Queue.prototype.openLevel = function(token){ + if (!this.formats.value()[token]){ + throw "CSL processor error: call to nonexistent format token \""+token+"\""; + } + //print("newlevel: "+token); + // + // delimiter, prefix, suffix, decorations from token + var blob = new CSL.Factory.Blob(this.formats.value()[token]); + var curr = this.current.value(); + curr.push( blob ); + this.current.push( blob.blobs ); +}; + +/** + * "merge" used to be real complicated, now it's real simple. + */ +CSL.Output.Queue.prototype.closeLevel = function(name){ + //print("merge"); + this.current.pop(); +} + +// +// append does the same thing as newlevel, except +// that the blob it pushes has text content, +// and the current pointer is not moved after the push. + +CSL.Output.Queue.prototype.append = function(str,tokname){ + //print("append: "+str); + var blob = false; + if (!tokname){ + var token = this.formats.value()["empty"]; + } else if (tokname == "literal"){ + var token = true; + blob = str; + } else if ("string" == typeof tokname){ + var token = this.formats.value()[tokname]; + } else { + var token = tokname; + } + if (!token){ + throw "CSL processor error: unknown format token name: "+tokname; + } + if (!blob){ + blob = new CSL.Factory.Blob(token,str); + } + var curr = this.current.value(); + curr.push( blob ); + this.state.tmp.term_predecessor = true; +} + +CSL.Output.Queue.prototype.string = function(state,blobs,blob){ + //print("string"); + var ret; + ret = { "str": [], "obj": [] }; + if (blobs.length == 1 && "string" == blobs[0].blobs){ + ret["str"] = blobs[0]; + } else { + for each (var blobjr in blobs){ + var strPlus = {"str":"","obj":[]}; + if ("string" == typeof blobjr.blobs){ + if ("number" == typeof blobjr.num){ + strPlus["obj"] = blobjr; + } else { + strPlus["str"] = blobjr.blobs; + } + } else { + strPlus = this.string(state,blobjr.blobs,blobjr); + }; + // + // If there is a suffix, or any decorations, trailing rangeable + // objects must be rendered immediately here. + // + if (strPlus["str"]){ + if (!state.tmp.suppress_decorations){ + for each (var params in blobjr.decorations){ + strPlus["str"] = state.fun.decorate[params[0]][params[1]](strPlus["str"]); + } + } + //print(str+" (with is_rangeable="+blobjr.strings.is_rangeable+")"); + strPlus["str"] = blobjr.strings.prefix + strPlus["str"] + blobjr.strings.suffix; + ret["str"].push(strPlus["str"]); + } + // + // this passes rangeable objects through + ret["obj"] = ret["obj"].concat(strPlus["obj"]); + }; + // + // The join only applies to non-rangeable objects. + // + if (blob) { + ret["str"] = ret["str"].join(blob.strings.delimiter); + } else { + // + // The list always seems to consist of a single string when this happens, + // which is fine by me. + // + //ret["str"] = ret["str"].join(""); + // XXX Obviously something needs to be done with rangeable + // XXX objects here! + // (will need to reverse the condition below after + // providing for force_render) + if (state.tmp.handle_ranges){ + ret["str"] = ret["str"].join(""); + //ret = ret["str"].join("") + this.renderBlobs(ret["obj"]); + } else { + ret = ret["str"].join(""); + } + //if (state.tmp.handle_ranges){ + // ret = ret["str"].join("") + this.renderBlobs(ret["obj"]); + // //ret = "OK"; + //} else { + // ret = ret["str"].join("") + this.renderBlobs(ret["obj"]); + //} + } + }; + this.queue = new Array(); + this.current.mystack = new Array(); + this.current.mystack.push( this.queue ); + return ret; +}; + +CSL.Output.Queue.prototype.clearlevel = function(){ + var blobs = this.current.value(); + for (var i=(blobs.length-1); i > -1; i--){ + blobs.pop(); + } +}; + +CSL.Output.Queue.prototype.dumbBlobs = function(state,blobs){ + +}; + +CSL.Output.Queue.prototype.renderBlobs = function(blobs){ + var state = this.state; + var ret = ""; + for (var i=0; i < blobs.length; i++){ + if (blobs[i].checkNext){ + blobs[i].checkNext(blobs[(i+1)]); + } + } + for each (var blob in blobs){ + if ("string" == typeof blob){ + ret += blob; + } else if (blob.status != CSL.SUPPRESS){ + // print("doing rangeable blob"); + var str = blob.blobs; + if (!state.tmp.suppress_decorations){ + for each (var params in blob.decorations){ + str = state.fun.decorate[params[0]][params[1]](str); + } + } + str = blob.strings.prefix + str + blob.strings.suffix; + if (blob.status == CSL.END){ + // + // XXXXX needs to be drawn from the object + ret += "-"; + } else if (blob.status == CSL.SUCCESSOR){ + // + // XXXXX needs to be drawn from the object + ret += ", "; + } else if (blob.status == CSL.START){ + // + // XXXXX needs to be drawn from the object + ret += ""; + } + ret += str; + } + } + return ret; +}; diff --git a/src/range.js b/src/range.js new file mode 100644 index 000000000..9d01dc548 --- /dev/null +++ b/src/range.js @@ -0,0 +1,69 @@ +dojo.provide("csl.range"); +if (!CSL) { + load("./src/csl.js"); +} + +/** + * An output instance object representing a number or a range + * + * with attributes next and start, and + * methods isRange(), renderStart(), renderEnd() and renderRange(). + * At render time, the output queue will perform optional + * collapsing of these objects in the queue, according to + * configurable options, and apply any decorations registered + * in the object to the output elements. + * @namespace Range object and friends. + */ + +CSL.Output.Number = function(num,mother_token){ + this.num = num; + this.blobs = num.toString(); + this.status = CSL.START; + this.strings = new Object(); + if (mother_token){ + this.decorations = mother_token.decorations; + this.strings.prefix = mother_token.strings.prefix; + this.strings.suffix = mother_token.strings.suffix; + this.successor_prefix = mother_token.successor_prefix; + this.range_prefix = mother_token.range_prefix; + this.formatter = mother_token.formatter; + if (this.formatter){ + this.type = this.formatter.format(1); + } + } else { + this.decorations = new Array(); + this.strings.prefix = ""; + this.strings.suffix = ""; + this.successor_prefix = ""; + this.range_prefix = ""; + this.formatter = new CSL.Output.DefaultFormatter(); + } +}; + + +CSL.Output.Number.prototype.setFormatter = function(formatter){ + this.formatter = formatter; + this.type = this.formatter.format(1); +}; + + +CSL.Output.DefaultFormatter = function (){}; +CSL.Output.DefaultFormatter.prototype.format = function (num){ + return num.toString(); +}; + + +CSL.Output.Number.prototype.checkNext = function(next){ + if ( ! next || ! next.num || this.type != next.type || next.num != (this.num+1)){ + if (this.status == CSL.SUCCESSOR_OF_SUCCESSOR){ + this.status = CSL.END; + } + } else { // next number is in the sequence + if (this.status == CSL.START){ + next.status = CSL.SUCCESSOR; + } else if (this.status == CSL.SUCCESSOR || this.status == CSL.SUCCESSOR_OF_SUCCESSOR){ + next.status = CSL.SUCCESSOR_OF_SUCCESSOR; + this.status = CSL.SUPPRESS; + } + }; +}; diff --git a/src/registry.js b/src/registry.js new file mode 100644 index 000000000..324ad17d4 --- /dev/null +++ b/src/registry.js @@ -0,0 +1,310 @@ +dojo.provide("csl.registry"); + +// +// should allow batched registration of items by +// key. should behave as an update, with deletion +// of items and the tainting of disambiguation +// partner sets affected by a deletes and additions. +// +// +// we'll need a reset method, to clear the decks +// in the citation area and start over. + +/** + * Registry of cited items. + *

This is a persistent store of disambiguation and + * sort order information relating to individual items + * for which rendering is requested. Item data is stored + * in a hash, with the item key as hash key, for quick + * retrieval. A virtual sequence within the hashed store + * is maintained on the fly as items are added to the + * store, using *_next and *_prev + * attributes on each item. A separate hash of items + * based on their undisambiguated cite form is + * maintained, and the item id list and disambiguation + * level for each set of disambiguation partners is shared + * through the registry item.

+ * @class + */ +CSL.Factory.Registry = function(state){ + this.debug = false; + this.debug_sort = false; + // + // each entry has a sort key, navigation vectors, + // and a disambiguation config object + if (this.debug){ + print("---> Instantiate registry"); + } + this.registry = new Object(); + // + // each ambig is a list of the ids of other objects + // that have the same base-level rendering + this.ambigs = new Object(); + this.start = false; + this.end = false; + this.initialized = false; + this.skip = false; + this.maxlength = 0; + this.sorter = new CSL.Factory.Registry.Comparifier(state,"bibliography_sort"); + + this.getSortedIds = function(){ + var step = "next"; + var item_id = this.start; + var ret = new Array(); + while (true){ + ret.push(item_id); + item_id = this.registry[item_id][step]; + if ( ! item_id){ + break; + } + } + return ret; + }; +}; + +CSL.Factory.Registry.prototype.insert = function(state,Item){ + // + // abort if we've already inserted + if (this.debug){ + print("---> Start of insert"); + } + if (this.registry[Item.id]){ + return; + } + // + // get the sort key (it's an array containing + // multiple key strings). + var sortkeys = state.getSortKeys(Item,"bibliography_sort"); + // + // get the disambiguation key and register it + // + var akey = state.getAmbiguousCite(Item); + var abase = state.getAmbigConfig(); + var modes = state.getModes(); + // + // registryItem instantiates an object with a copy of the + // sort key, and a list shared with + // disambiguation partners, if any, maintained + // in sort key order. + // (after this, we're ready to roll for the insert) + var newitem = { + "id":Item.id, + "seq":1, + "dseq":0, + "sortkeys":sortkeys, + "disambig":abase, + "prev":false, + "next":false + }; + // + // if the registry is empty, initialize it with + // this object. + if (this.debug){ + print("---> Begin manipulating registry"); + } + var breakme = false; + if (!this.initialized){ + if (this.debug_sort){ + print("-->initializing registry with "+newitem.id); + } + this.registry[newitem.id] = newitem; + this.start = newitem.id; + this.end = newitem.id; + this.initialized = true; + // + // XXXXX + //this.registerAmbigToken(state,akey,Item.id,abase.slice()); + this.registerAmbigToken(state,akey,Item.id,abase); + return; + } + // if this object is less than the first one, + // insert it as the first. + if (-1 == this.sorter.compareKeys(newitem.sortkeys,this.registry[this.start].sortkeys)){ + if (this.debug_sort){ + print("-->inserting "+newitem.id+" before "+this.start+" as first entry"); + } + newitem.next = this.registry[this.start].id; + this.registry[this.start].prev = newitem.id; + newitem.prev = false; + newitem.seq = 1; + var tok = this.registry[this.start]; + this.incrementSubsequentTokens(tok); + this.start = newitem.id; + this.registry[newitem.id] = newitem; + breakme = true; + } + // if this object is greater than the + // last one, insert it as the last. + if (-1 == this.sorter.compareKeys(this.registry[this.end].sortkeys,newitem.sortkeys) && !breakme){ + if (this.debug_sort){ + print("-->inserting "+newitem.id+" after "+this.end+" as last entry"); + } + newitem.prev = this.registry[this.end].id; + this.registry[this.end].next = newitem.id; + newitem.next = false; + newitem.seq = (this.registry[this.end].seq + 1); + this.end = newitem.id; + this.registry[newitem.id] = newitem; + breakme = true; + } + // + // if we reach this, it's safe to iterate + var curr = this.registry[this.end]; + while (true && !breakme){ + // compare the new token to be added with + // the one we're thinking about placing it after. + var cmp = this.sorter.compareKeys(curr.sortkeys,newitem.sortkeys); + if (cmp == -1){ + if (this.debug_sort){ + print("-->inserting "+newitem.id+" after "+curr.id); + } + // insert mid-list, after the tested item + this.registry[curr.next].prev = newitem.id; + newitem.next = curr.next; + newitem.prev = curr.id; + curr.next = newitem.id; + newitem.seq = (curr.seq+1); + this.incrementSubsequentTokens(this.registry[newitem.next]); + this.registry[newitem.id] = newitem; + breakme = true; + break; + } else if (cmp == 2){ + breakme = true; + } else if (cmp == 0) { + // insert _after_, but this one is equivalent + // to the comparison partner for sortkey purposes + // (so we needed to provide for cases where the + // inserted object ends up at the end of + // the virtual list.) + if (false == curr.next){ + if (this.debug_sort){ + print("-->inserting "+newitem.id+" after "+curr.id+" as last entry, although equal"); + } + newitem.next = false; + newitem.prev = curr.id; + curr.next = newitem.id; + newitem.seq = (curr.seq+1); + //this.incrementSubsequentTokens(curr); + this.registry[newitem.id] = newitem; + this.end = newitem.id; + breakme = true; + break; + } else { + if (this.debug_sort){ + print("-->inserting "+newitem.id+" after "+curr.id+", although equal"); + } + this.registry[curr.next].prev = newitem.id; + newitem.next = curr.next; + newitem.prev = curr.id; + curr.next = newitem.id; + newitem.seq = curr.seq; + this.registry[newitem.id] = newitem; + this.incrementSubsequentTokens(newitem); + breakme = true; + break; + } + } + if (breakme){ + break; + } + // + // we scan in reverse order, because working + // from the initial draft of the code, this + // makes it simpler to order cites in submission + // order, when no sort keys are available. + curr = this.registry[curr.prev]; + }; + if (this.debug){ + print("---> End of registry insert"); + } + // + // register the notional ambiguation config + this.registerAmbigToken(state,akey,Item.id,abase); + // + // if there are multiple ambigs, disambiguate them + if (this.ambigs[akey].length > 1){ + if (modes.length){ + if (this.debug){ + print("---> Names disambiguation begin"); + } + var leftovers = this.disambiguateCites(state,akey,modes); + if (this.debug){ + print("---> Names disambiguation done"); + } + // + // leftovers is a list of registry tokens. sort them. + leftovers.sort(this.compareRegistryTokens); + } else { + // + // if we didn't disambiguate with names, everything is + // a leftover. + var leftovers = new Array(); + for each (var key in this.ambigs[akey]){ + leftovers.push(this.registry[key]); + leftovers.sort(this.compareRegistryTokens); + } + } + } + // + // for anything left over, set disambiguate to true, and + // try again from the base. + if (leftovers && leftovers.length && state.opt.has_disambiguate){ + var leftovers = this.disambiguateCites(state,akey,modes,leftovers); + } + + if ( leftovers && leftovers.length && state[state.tmp.area].opt["disambiguate-add-year-suffix"]){ + var suffixes = state.fun.suffixator.get_suffixes(leftovers.length); + for (var i in leftovers){ + this.registry[ leftovers[i].id ].disambig[2] = suffixes[i]; + this.registry[ leftovers[i].id ].dseq = i; + } + } + if (this.debug) { + print("---> End of registry cleanup"); + } +}; + +/** + * Compare two sort keys + *

Nested, because keys are an array.

+ */ +CSL.Factory.Registry.Comparifier = function(state,keyset){ + var sort_directions = state[keyset].opt.sort_directions.slice(); + this.compareKeys = function(a,b){ + for (var i=0; i < a.length; i++){ + // + // for ascending sort 1 uses 1, -1 uses -1. + // For descending sort, the values are reversed. + var cmp = a[i].toLocaleLowerCase().localeCompare(b[i].toLocaleLowerCase()); + if (0 < cmp){ + return sort_directions[i][1]; + } else if (0 > cmp){ + return sort_directions[i][0]; + } + } + return 0; + }; +}; + + +/** + * Compare two disambiguation tokens by their registry sort order + *

Disambiguation lists need to be sorted this way, to + * obtain the correct year-suffix when that's used.

+ */ +CSL.Factory.Registry.prototype.compareRegistryTokens = function(a,b){ + if (a.seq > b.seq){ + return 1; + } else if (a.seq < b.seq){ + return -1; + } + return 0; +}; + +CSL.Factory.Registry.prototype.incrementSubsequentTokens = function (tok){ + while (tok.next){ + tok.seq += 1; + tok = this.registry[tok.next]; + } + tok.seq += 1; +}; diff --git a/src/render.js b/src/render.js new file mode 100644 index 000000000..933906da9 --- /dev/null +++ b/src/render.js @@ -0,0 +1,265 @@ +dojo.provide("csl.render"); +if (!CSL) { + load("./src/csl.js"); +} + +/** + * Rendering functions. + *

This is a bundle of methods that are attached to the + * completed style object, and offer facilities for rendering + * citations and bibliographies.

+ * @namespace Rendering functions. + */ +CSL.Core.Render = {}; + +/** + * Get the undisambiguated version of a cite, without decorations + *

This is used internally by the Registry.

+ */ +CSL.Core.Render.getAmbiguousCite = function(Item,disambig){ + if (disambig){ + this.tmp.disambig_request = disambig; + } else { + this.tmp.disambig_request = false; + } + this.tmp.area = "citation"; + this.tmp.suppress_decorations = true; + this.tmp.force_subsequent = true; + CSL.Core.Render._cite.call(this,Item); + this.tmp.force_subsequent = false; + var ret = this.output.string(this,this.output.queue); + this.tmp.suppress_decorations = false; + if (false){ + print("ok"); + } + return ret; +} + + +/** + * Get the sort key of an item, without decorations + *

This is used internally by the Registry.

+ */ +CSL.Core.Render.getSortKeys = function(Item,key_type){ + if (false){ + print("KEY TYPE: "+key_type); + } + var area = this.tmp.area; + var strip_prepositions = CSL.Util.Sort.strip_prepositions; + this.tmp.area = key_type; + this.tmp.disambig_request = false; + this.tmp.suppress_decorations = true; + CSL.Core.Render._cite.call(this,Item); + this.tmp.suppress_decorations = false; + for (var i in this[key_type].keys){ + this[key_type].keys[i] = strip_prepositions(this[key_type].keys[i]); + } + if (false){ + print("sort keys ("+key_type+"): "+this[key_type].keys); + } + this.tmp.area = area; + return this[key_type].keys; +}; + +/** + * Return current base configuration for disambiguation + */ +CSL.Core.Render.getAmbigConfig = function(){ + var config = this.tmp.disambig_request; + if (!config){ + config = this.tmp.disambig_settings; + } + var ret = this.fun.clone_ambig_config(config); + return ret; +}; + + +/** + * Return max values for disambiguation + */ +CSL.Core.Render.getMaxVals = function(){ + return this.tmp.names_max.mystack.slice(); +}; + +/** + * Return min value for disambiguation + */ +CSL.Core.Render.getMinVal = function(){ + return this.tmp["et-al-min"]; +}; + +/** + * Return delimiter for use in join + *

Splice evaluation is done during cite + * rendering, and this method returns the + * result. Evaluation requires three items + * of information from the preceding cite, if + * one is present: the names used; the years + * used; and the suffix appended to the + * citation. These details are copied into + * the state object before processing begins, + * and are cleared by the processor on + * completion of the run.

+ */ +CSL.Core.Render.getSpliceDelimiter = function(){ + return this.tmp.splice_delimiter; +}; + +/** + * Return available modes for disambiguation + */ +CSL.Core.Render.getModes = function(){ + var ret = new Array(); + if (this[this.tmp.area].opt["disambiguate-add-names"]){ + ret.push("names"); + } + if (this[this.tmp.area].opt["disambiguate-add-givenname"]){ + ret.push("givens"); + } + return ret; +}; + + +/* + * Compose individual cites into a single string. (This requires + * further work to accomodate various adjustments to inter-cite + * splicing. There are lots of possibilities, which will require + * careful planning.) + */ +CSL.Core.Render._bibliography_entries = function (){ + this.tmp.area = "bibliography"; + var input = this.fun.retriever.getInput(this.registry.getSortedIds()); + this.tmp.disambig_override = true; + this.output.addToken("bibliography","\n"); + this.output.openLevel("bibliography"); + for each (item in input){ + if (false){ + print("BIB: "+item.id); + } + CSL.Core.Render._cite.call(this,item); + //this.output.squeeze(); + } + this.output.closeLevel(); + this.tmp.disambig_override = false; + return this.output.string(this,this.output.queue); +}; + +/** + * Register one or more citation items. + *

Accepts a single item key or a list of item keys as + * a single argument, fetches the relevant Items using the + * appropriate wrapper in {@link CSL.System.Retrieval}, + * and enters each Item into the persistent session + * registry.

+ */ +CSL.Core.Render.registerItemKeys = function() { + +}; + + +/* + * Compose individual cites into a single string. (This requires + * further work to accomodate various adjustments to inter-cite + * splicing. There are lots of possibilities, which will require + * careful planning.) + */ +CSL.Core.Render._unit_of_reference = function (inputList){ + this.tmp.area = "citation"; + var delimiter = ""; + + var result = ""; + + var objects = []; + + for each (var Item in inputList){ + CSL.Core.Render._cite.call(this,Item); + // + // This will produce a stack with one + // layer, and exactly one or two items. + // We merge these as we go along, to get + // the joins right for the pairs. + delimiter = this.getSpliceDelimiter(); + this.tmp.delimiter.replace(delimiter); + this.tmp.handle_ranges = true; + var composite = this.output.string(this,this.output.queue); + this.tmp.handle_ranges = false; + // + // At last! Ready to compose trailing blobs. + // We convert "string" output object to an array + // before collapsing blobs. + if (composite["str"]){ + if ("string" == typeof objects[(objects.length-1)]){ + var newstr = objects.pop() + this.tmp.splice_delimiter + composite["str"]; + objects.push(newstr); + } else { + objects.push(composite["str"]); + } + } + if (composite["obj"].length){ + objects = objects.concat(composite["obj"]); + } + } + result += this.output.renderBlobs(objects); + result = this.citation.opt.layout_prefix + result + this.citation.opt.layout_suffix; + if (!this.tmp.suppress_decorations){ + for each (var params in this.citation.opt.layout_decorations){ + result = this.fun.decorate[params[0]][params[1]](result); + } + } + return result; +}; + + +/* + * Render a single cite item. + * + * This is called on the state object, with a single + * Item as input. It iterates exactly once over the style + * citation tokens, and leaves the result of rendering in + * the top-level list in the relevant *.opt.output + * stack, as a list item consisting of a single string. + * + * (This might be dual-purposed for generating individual + * entries in a bibliography.) + */ +CSL.Core.Render._cite = function(Item){ + for each (var func in this.init){ + func(this,Item); + } + var next = 0; + while(next < this[this.tmp.area].tokens.length){ + next = CSL.Core.Render._render.call(this[this.tmp.area].tokens[next],this,Item); + } + for each (func in this.stop){ + func(this,Item); + } +}; + + +/* + * Render one style token. + * + * This is called on a token, with the state object + * and an Item object as arguments. + */ +CSL.Core.Render._render = function(state,Item){ + var next = this.next; + var maybenext = false; + if (false){ + print("---> Token: "+this.name+" ("+state.tmp.area+")"); + print(" next is: "+next+", success is: "+this.succeed+", fail is: "+this.fail); + } + if (this.evaluator){ + next = this.evaluator.call(this,state,Item); + }; + for each (var exec in this.execs){ + maybenext = exec.call(this,state,Item); + if (maybenext){ + next = maybenext; + }; + }; + if (false){ + print("---> done"); + } + return next; +}; diff --git a/src/retrieval.js b/src/retrieval.js new file mode 100644 index 000000000..94661e68a --- /dev/null +++ b/src/retrieval.js @@ -0,0 +1,304 @@ +dojo.provide("csl.retrieval"); +if (!CSL){ + load("./src/csl.js"); +} + +/** + * Static functions for retrieving field content. + *

What goes here will depend on the environment + * in which this is deployed. Functions take an item + * and a fieldname as argument.

+ * @namespace Retrieval + */ +CSL.System.Retrieval = function(){}; + +CSL.System.Retrieval.GetInput = function(){ + this.input = new Object(); +}; + +CSL.System.Retrieval.GetInput.prototype.setInput = function(state,item){ + this.input[item.id] = item; +} + +CSL.System.Retrieval.GetInput.prototype.getInput = function(name){ + var ret = new Array(); + if ("object" == typeof name && name.length){ + for each (filename in name){ + if (this.input[filename]){ + ret.push(this.input[filename]); + } else { + var datastring = readFile("data/" + filename + ".txt"); + eval( "obj = " + datastring ); + CSL.System.Tests.fixNames([obj],filename); + this.input[filename] = obj; + ret.push(obj); + } + } + } else if ("object" == typeof name){ + if (this.input[filename]){ + ret.push(this.input[filename]); + } else { + var datastring = readFile("data/" + filename + ".txt"); + this.input[filename] = obj; + eval( "obj = " + datastring ); + CSL.System.Tests.fixNames([obj],filename); + ret.push(obj); + } + } else { + throw "Failure reading test data file, WTF?"; + } + return ret; +} + +/** + * Get locale data for a specific language and return + * as a token list. + */ +CSL.System.Retrieval.getLocaleObjects = function(lang,locale){ + // + // we're a static function, so this refers to the + // global object + if ( ! locale ){ + try { + var locale = readFile( "./locale/"+localeRegistry()[lang] ); + } catch (e){ + throw "Unable to load locale for "+lang+"."; + } + } + var builder = new CSL.Core.Build(locale); + builder.build(); + return builder.state.opt.term; + + function localeRegistry (){ + return { + "af":"locales-af-AZ.xml", + "af":"locales-af-ZA.xml", + "ar":"locales-ar-AR.xml", + "bg":"locales-bg-BG.xml", + "ca":"locales-ca-AD.xml", + "cs":"locales-cs-CZ.xml", + "da":"locales-da-DK.xml", + "de":"locales-de-AT.xml", + "de":"locales-de-CH.xml", + "de":"locales-de-DE.xml", + "el":"locales-el-GR.xml", + "en":"locales-en-US.xml", + "es":"locales-es-ES.xml", + "et":"locales-et-EE.xml", + "fr":"locales-fr-FR.xml", + "he":"locales-he-IL.xml", + "hu":"locales-hu-HU.xml", + "is":"locales-is-IS.xml", + "it":"locales-it-IT.xml", + "ja":"locales-ja-JP.xml", + "ko":"locales-ko-KR.xml", + "mn":"locales-mn-MN.xml", + "nb":"locales-nb-NO.xml", + "nl":"locales-nl-NL.xml", + "pl":"locales-pl-PL.xml", + "pt":"locales-pt-BR.xml", + "pt":"locales-pt-PT.xml", + "ro":"locales-ro-RO.xml", + "ru":"locales-ru-RU.xml", + "sk":"locales-sk-SK.xml", + "sl":"locales-sl-SI.xml", + "sr":"locales-sr-RS.xml", + "sv":"locales-sv-SE.xml", + "th":"locales-th-TH.xml", + "tr":"locales-tr-TR.xml", + "uk":"locales-uk-UA.xml", + "vi":"locales-vi-VN.xml", + "zh":"locales-zh-CN.xml", + "zh":"locales-zh-TW.xml" + }; + }; +}; + +var _slashRe = /^(.*?)\b([0-9]{1,4})(?:([\-\/\.\u5e74])([0-9]{1,2}))?(?:([\-\/\.\u6708])([0-9]{1,4}))?\b(.*?)$/; +var _yearRe = /^(.*?)\b((?:circa |around |about |c\.? ?)?[0-9]{1,4}(?: ?B\.? ?C\.?(?: ?E\.?)?| ?C\.? ?E\.?| ?A\.? ?D\.?)|[0-9]{3,4})\b(.*?)$/i; +var _monthRe = null; +var _dayRe = null; + +/** + * Convert a string to an hash object + *

Object has the following content: + *

+ *
day
integer form of the day
+ *
month
integer form of the month (indexed from 0, not 1)
+ *
year
4 digit year (or, year + BC/AD/etc.)
+ *
part
anything that does not fall under any of the above categories + * (e.g., "Summer," etc.)
+ *
+ *

Note: the returned object is *not* a JS Date object

+ * + *

(shamelessly lifted from Zotero source)

+ */ +CSL.System.Retrieval.strToDate = function(string) { + var date = new Object(); + + // skip empty things + if(!string) { + return date; + } + + string = string.toString().replace(/^\s+/, "").replace(/\s+$/, "").replace(/\s+/, " "); + + // first, directly inspect the string + var m = _slashRe.exec(string); + var pre = m[1]; + var num1 = m[2]; + var div1_2 = m[3]; + var num2 = m[4]; + var div2_3 = m[5]; + var num3 = m[6]; + var post = m[7]; + if(m){ + var sane = (!m[5] || m[3] == m[5] || (m[3] == "\u5e74" && m[5] == "\u6708")); + var got_data = ((m[2] && m[4] && m[6]) || (!m[1] && !m[7])); + if (sane && got_data){ + // figure out date based on parts + if(num1.length == 3 || num1.length == 4 || div1_2 == "\u5e74") { + // ISO 8601 style date (big endian) + date.year = num1; + date.month = num2; + date.day = num3; + } else { + // local style date (middle or little endian) + date.year = num3; + // + // XXXX This is going to need some help + var country = "US"; + if(country == "US" || // The United States + country == "FM" || // The Federated States of Micronesia + country == "PW" || // Palau + country == "PH") { // The Philippines + date.month = num1; + date.day = num2; + } else { + date.month = num2; + date.day = num1; + } + } + + if(date.year) { + date.year = parseInt(date.year, 10); + } + + if(date.day) { + date.day = parseInt(date.day, 10); + } + + if(date.month) { + date.month = parseInt(date.month, 10); + + if(date.month > 12) { + // swap day and month + var tmp = date.day; + date.day = date.month; + date.month = tmp; + } + } + + if((!date.month || date.month <= 12) && (!date.day || date.day <= 31)) { + if(date.year && date.year < 100) { // for two digit years, determine proper + // four digit year + var today = new Date(); + var year = today.getFullYear(); + var twoDigitYear = year % 100; + var century = year - twoDigitYear; + + if(date.year <= twoDigitYear) { + // assume this date is from our century + date.year = century + date.year; + } else { + // assume this date is from the previous century + date.year = century - 100 + date.year; + } + } + + // subtract one for JS style + if(date.month){ + date.month--; + } + date.part = pre+post; + } else { + // + // give up; we failed the sanity check + date = {"part":string}; + } + } else { + date.part = string; + } + } else { + date.part = string; + } + + // couldn't find something with the algorithms; use regexp + // YEAR + if(!date.year) { + var m = _yearRe.exec(date.part); + if(m) { + date.year = num1; + date.part = pre+d1_2; + } + } + + // MONTH + if(!date.month) { + // compile month regular expression + var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', + 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + // If using a non-English bibliography locale, try those too + if (Zotero.CSL.Global.locale != 'en-US') { + months = months.concat(Zotero.CSL.Global.getMonthStrings("short")); + } + if(!_monthRe) { + _monthRe = new RegExp("^(.*)\\b("+months.join("|")+")[^ ]*(?: (.*)$|$)", "i"); + } + + var m = _monthRe.exec(date.part); + if(m) { + // Modulo 12 in case we have multiple languages + date.month = months.indexOf(m[2][0].toUpperCase()+m[2].substr(1).toLowerCase()) % 12; + date.part = m[1]+m[3]; + } + } + + // DAY + if(!date.day) { + // compile day regular expression + if(!_dayRe) { + var daySuffixes = Zotero.getString("date.daySuffixes").replace(/, ?/g, "|"); + _dayRe = new RegExp("\\b([0-9]{1,2})(?:"+daySuffixes+")?\\b(.*)", "i"); + } + + var m = _dayRe.exec(date.part); + if(m) { + var day = parseInt(m[1], 10); + // Sanity check + if (day <= 31) { + date.day = day; + if(m.index > 0) { + date.part = date.part.substr(0, m.index); + if(m[2]) { + date.part += " "+m[2];; + } + } else { + date.part = m[2]; + } + } + } + } + + // clean up date part + if(date.part) { + date.part = date.part.replace(/^[^A-Za-z0-9]+/, "").replace(/[^A-Za-z0-9]+$/, ""); + if(!date.part.length) { + date.part = undefined; + } + } + return date; +}; + + + diff --git a/src/stack.js b/src/stack.js new file mode 100644 index 000000000..c3d22511b --- /dev/null +++ b/src/stack.js @@ -0,0 +1,87 @@ +dojo.provide("csl.stack"); +if (!CSL) { + load("./src/csl.js"); +} + + +/** + * String stack object. + *

Numerous string stacks are used to track nested + * parameters at runtime. This class provides methods + * that remove some of the aggravation of managing + * them.

+ * @class + */ +CSL.Factory.Stack = function(val,literal){ + this.mystack = new Array(); + if (literal || val){ + this.mystack.push(val); + } +}; + +/** + * Clear the stack + */ +CSL.Factory.Stack.prototype.clear = function(){ + this.mystack = new Array(); +}; + +/** + * Push a value onto the stack. + *

This just does what it says.

+ */ +CSL.Factory.Stack.prototype.push = function(val,literal){ + if (literal || val){ + this.mystack.push(val); + } else { + this.mystack.push(""); + } +}; + +/** + * Replace the top value on the stack. + *

This removes some ugly syntax from the + * main code.

+ */ +CSL.Factory.Stack.prototype.replace = function(val,literal){ + // + // safety fix after a bug was chased down. Rhino + // JS will process a negative index without error (!). + if (this.mystack.length == 0){ + throw "Internal CSL processor error: attempt to replace nonexistent stack item"; + } + if (literal || val){ + this.mystack[(this.mystack.length-1)] = val; + } else { + this.mystack[(this.mystack.length-1)] = ""; + } +}; + + +/** + * Remove the top value from the stack. + *

Just does what it says.

+ */ +CSL.Factory.Stack.prototype.pop = function(){ + this.mystack.pop(); +}; + + +/** + * Return the top value on the stack. + *

Removes a little hideous complication from + * the main code.

+ */ +CSL.Factory.Stack.prototype.value = function(){ + return this.mystack[(this.mystack.length-1)]; +}; + + +/** + * Return length (depth) of stack. + *

Used to identify if there is content to + * be handled on the stack

+ */ +CSL.Factory.Stack.prototype.length = function(){ + return this.mystack.length; +}; diff --git a/src/state.js b/src/state.js new file mode 100644 index 000000000..a4f086ce1 --- /dev/null +++ b/src/state.js @@ -0,0 +1,402 @@ +dojo.provide("csl.state"); +if (!CSL) { + load("./src/csl.js"); +} + +/** + * State object for storing options and tokens. + *

A container for objects passed between functions + * during processing.

+ * @param {Class} xmlCommandInterface The appropriate + * XML DOM interface class from {@link CSL.System.Xml}. + * @class + * @param {XML} xml A parsed XML object or XMLList. + */ +CSL.Factory.State = function (xmlCommandInterface,nodelist){ + this.init = new Array(); + this.stop = new Array(); + /** + * Global options. + *

Available in Render.

+ */ + this.opt = new Object(); + /** + * Scratch variables and stacks. + *

Available in Render.

+ */ + this.tmp = new Object(); + /** + * Generic functions. + *

Available in Render.

+ */ + this.fun = new Object(); + this.fun.retriever = new CSL.System.Retrieval.GetInput(); + /** + * Build-time scratch area. + *

Discarded after Build is complete.

+ */ + this.build = new Object(); + /** + * Alternate et-al term + *

Holds the localization key of the alternative term + * to be used for et-al in a names environment. Reduced + * to a term object when the element tag is processed during + * Build.

+ */ + this.build["alternate-term"] = false; + /** + * Configure-time scratch area. + *

Discarded after Configure is complete.

+ */ + this.configure = new Object(); + /** + * Item registry. + *

A persistent item registry. Each cite + * item is registered here before its first + * rendering. The registry can be queried for + * sort order information (for producing + * bibliographies) and for disambiguation + * hints (needed for producing citations + * in all styles, and for bibliographies in + * many styles). This registry does not + * carry all details of a citation; only the + * essential details needed to establish + * sort order and determine disambiguation + * handling is held here. + */ + // XXXXX MOVED to build.js. Registry now installed + // after initial build phase, so that comparison + // function can be instantiated with sort key + // configuration derived from initial token scan. + // + // this.registry = new CSL.Factory.Registry(); + // + /** + * Citation area. + *

Holds the options and token list for the style + * citation format (the form of a reference to be + * used in the body of a document).

+ */ + this.citation = new Object(); + /** + * Citation options area. + *

Holds a mixture of persistent and ephemeral + * options and scratch data used during processing of + * a citation.

+ */ + this.citation.opt = new Object(); + this.citation.tokens = new Array(); + /** + * Bibliography area. + *

Holds the options and token list for the + * style bibliography entry format (the form of + * a source reference to be used in a bibliography + * included in a document).

+ */ + this.bibliography = new Object(); + /** + * Bibliography options area. + *

Holds a mixture of persistent and ephemeral + * options and scratch data used during processing of + * a bibliography.

+ */ + this.bibliography.opt = new Object(); + this.bibliography.tokens = new Array(); + /** + * Default values. + *

The various et-al values are set globally, + * and the appropriate value is set by the names start + * tag at runtime, depending on whether the Item is a + * first or a subsequent reference.

+ */ + this.citation.opt["et-al-min"] = 0; + this.citation.opt["et-al-use-first"] = 1; + this.citation.opt["et-al-subsequent-min"] = false; + this.citation.opt["et-al-subsequent-use-first"] = false; + + this.bibliography.opt["et-al-min"] = 0; + this.bibliography.opt["et-al-use-first"] = 1; + this.bibliography.opt["et-al-subsequent-min"] = 0; + this.bibliography.opt["et-al-subsequent-use-first"] = 1; + /** + * Bibliography sort area. + *

Holds the options and token list for the + * style bibliography sort key format.

+ */ + this.bibliography_sort = new Object(); + this.citation_sort = new Object(); + /** + * Sort options area. + *

Holds a mixture of persistent and ephemeral + * options and scratch data used during processing of + * a bibliography.

+ */ + // + // XXXXX Hmm. This needs to be subdivided, with + // separate rendering areas for each key. Should + // permit an arbitrary number of keys, so the whole + // structure needs to be generated programmatically. + // Either that, or (MUCH more sensible!) wrap the + // rendering tokens in a key element that stores the + // strings separately. Ah, that's much better. + // So the key element will not be a noop. + + this.bibliography_sort.tokens = new Array(); + this.bibliography_sort.opt = new Object(); + this.bibliography_sort.opt.sort_directions = new Array(); + this.bibliography_sort.keys = new Array(); + + this.citation_sort.tokens = new Array(); + this.citation_sort.opt = new Object(); + this.citation_sort.opt.sort_directions = new Array(); + this.citation_sort.keys = new Array(); + + // + // the language setting will not be needed for processing, + // but the compiled object should be able to report it. + this.opt.lang = false; + // + // terms are needed globally for rendering, so this + // is saved into opt. + this.opt.term = new Object(); + // + // configuration array to hold the collapse + // options, if any. + this.citation.opt.collapse = new Array(); + this.bibliography.opt.collapse = new Array(); + // + // disambiguate options + this.citation.opt["disambiguate-add-names"] = false; + this.citation.opt["disambiguate-add-givenname"] = false; + this.bibliography.opt["disambiguate-add-names"] = false; + this.bibliography.opt["disambiguate-add-givenname"] = false; + // + // scratch variable to display the total + // number of names in all rendered variables + // in a cite. initialized to zero by the + // citation element, incremented by each + // name variable actually rendered + this.tmp.names_max = new CSL.Factory.Stack(); + this.tmp.names_base = new CSL.Factory.Stack(); + this.tmp.givens_base = new CSL.Factory.Stack(); + + // + // flags that we are in the bibliography area. + // used by sort. + this.build.in_bibliography = false; + // + // this is used to set a requested set of + // disambiguation parameters in the output. + // for the array elements, the base array + // (either zero for each nameset, or full-up + // if givens are already used) is set + // during names processing, if no value + // is set in the processor before a rendering + // run. to simplify things for the calling + // function, these are just bog-standard arrays, + // and can be safely overwritten. + this.tmp.disambig_request = false; + // + // scratch variable to toggle an attempt to set a + // name in sort order rather than display + // order. + this.tmp["name-as-sort-order"] = false; + // + // suppress decorations (used for generating + // sort keys and disambiguation keys) + this.tmp.suppress_decorations = false; + // + // empty settings array, used to report settings used + // if disambig_request is not set at runtime + this.tmp.disambig_settings = new CSL.Factory.AmbigConfig(); + // + // sort key array + this.tmp.bib_sort_keys = new Array(); + // + // holds the prefix between the start of a group + // and the closing token. + this.tmp.prefix = new CSL.Factory.Stack("",CSL.LITERAL); + // + // holds the suffix between the start of a group + // and the closing token. + this.tmp.suffix = new CSL.Factory.Stack("",CSL.LITERAL); + // + // holds the group delimiter between the start of a group + // and the closing token. + this.tmp.delimiter = new CSL.Factory.Stack("",CSL.LITERAL); + // + // reinitialize scratch variables used by names + this.fun.names_reinit = CSL.Util.Names.reinit; + // + // reduce a name to an initial. + this.fun.initialize_with = CSL.Util.Names.initialize_with; + // + // "deep" copy of nested array in very specific format + this.fun.clone_ambig_config = CSL.Factory.cloneAmbigConfig; + // + // scratch stack containing initialize-with strings or null values + this.tmp.initialize_with = new CSL.Factory.Stack(); + // + // return a common term iff namesets are all identical + // and a common term for them exists + this.fun.get_common_term = CSL.Util.Names.getCommonTerm; + // + // utility to get standard suffixes for disambiguation + this.fun.suffixator = new CSL.Util.Disambiguate.Suffixator(CSL.SUFFIX_CHARS); + this.fun.romanizer = new CSL.Util.Disambiguate.Romanizer(); + // + // token store stack. + this.tmp.tokenstore_stack = new CSL.Factory.Stack(); + + this.tmp.name_quash = new Object(); + // + // for collapsing + this.tmp.last_suffix_used = ""; + this.tmp.last_names_used = new Array(); + this.tmp.last_years_used = new Array(); + this.tmp.years_used = new Array(); + this.tmp.names_used = new Array(); + this.splice_delimiter = false; + // + // substituting flag. triggers creation of a special conditional + // wrapper around text tags when in force. + this.tmp.names_substituting = false; + // + // counter for total namesets + this.tmp.nameset_counter = 0; + // + // function to mark output. used to satisfy requirement + // that terms cannot render by themselves unless no + // attempt has been made to render a non-term variable + // within the same group or citation. + this.fun.mark_output = CSL.Factory.mark_output; + // + // stack flag used for term handling. Set to true + // if at least one variable has tried to render, and + // no variables had content. + this.tmp.term_sibling = new CSL.Factory.Stack( undefined, CSL.LITERAL); + // + // boolean flag used to control first-letter capitalization + // of terms. Set to true if any item preceding the term + // being handled has rendered successfully, otherwise + // false. + this.tmp.term_predecessor = false; + // + // stack flag used to control jumps in the closing + // token of a conditional. + this.tmp.jump = new CSL.Factory.Stack(0,CSL.LITERAL); + // + // holds string parameters for group formatting, between + // the start of a group and the closing token. + this.tmp.decorations = new CSL.Factory.Stack(); + // + // decorate contains font and formatting functions + // that are fixed during configure and used during + // render + this.fun.decorate = false; + // + // scratch variable to flag whether we are processing + // a citation or a bibiliography. this diverts token and + // configuration to the appropriateo objects inside + // state. the default is "citation". + this.tmp.area = "citation"; + // + // should be able to run uninitialized; may attract some + // cruft this way. + this.build.area = "citation"; + // + // this holds the field values collected by the @value + // and @variable attributes, for processing by the + // element functions. + this.tmp.value = new Array(); + /** + * Object to hold the decorations declared by a name-part + * element. + */ + this.tmp.namepart_decorations = new Object(); + /** + * String variable to hold the type of a name-part + * element. + */ + this.tmp.namepart_type = false; + /** + * Output queue. + *

A special list stack for the final collation + * and output of strings.

+ */ + this.output = new CSL.Output.Queue(this); + // + // the fail and succeed arrays are used for stack + // processing during configure. + this.configure.fail = new Array(); + this.configure.succeed = new Array(); + // + // We're not going to need this after the first phase + this.build.xmlCommandInterface = xmlCommandInterface; + // + // stores the content of an XML text node during processing + this.build.text = false; + // + // this is a scratch variable for holding an attribute + // value during processing + this.build.lang = false; + // + // this holds the class of the style (w/bib, author-date) + this.opt["class"] = false; + // + // scratch variable to alter behaviour when processing + // locale files + this.build.in_style = false; + // + // used to ignore info + this.build.skip = false; + // + // the macro ATTRIBUTE stores a macro name on this + // scratch variable anywhere outside the layout area + // during build. The macro name is picked up when + // the token is encountered inside the layout area, + // either through a direct call, or as part of a nested + // macro expansion, and the macro content is exploded + // into the token list. + this.build.postponed_macro = false; + // + // used especially for controlling macro expansion + // during Build. + this.build.layout_flag = false; + // + // (was stack.buffer) + // this is a stack for collecting child tokens + // during processing of macro ELEMENTS and locale + // term ELEMENTS. + this.build.children = new Array(); + // + // (was buffer_name) + // scratch variable to hold the name of a macro + // or a term until its children have been collected. + this.build.name = false; + // + // scratch variable to hold the value of a form + // attribute until other attributes needed for + // processing have been collected. + this.build.form = false; + this.build.term = false; + // + // the macros themselves are discarded after Build + this.build.macro = new Object(); + // + // the macro build stack. used to raise an error + // when macros would attempt to call themselves. + this.build.macro_stack = new Array(); + // + // XML-wise node navigation is needed only during Build. + this.build.nodeList = new Array(); + this.build.nodeList.push([0, nodelist]); +}; + +CSL.Factory.State.prototype.getAmbiguousCite = CSL.Core.Render.getAmbiguousCite; +CSL.Factory.State.prototype.getSortKeys = CSL.Core.Render.getSortKeys; +CSL.Factory.State.prototype.getAmbigConfig = CSL.Core.Render.getAmbigConfig; +CSL.Factory.State.prototype.getMaxVals = CSL.Core.Render.getMaxVals; +CSL.Factory.State.prototype.getMinVal = CSL.Core.Render.getMinVal; +CSL.Factory.State.prototype.getModes = CSL.Core.Render.getModes; +CSL.Factory.State.prototype.getSpliceDelimiter = CSL.Core.Render.getSpliceDelimiter; diff --git a/src/system.js b/src/system.js new file mode 100644 index 000000000..fd57ae910 --- /dev/null +++ b/src/system.js @@ -0,0 +1,13 @@ +dojo.provide("csl.retrieval"); +if (!CSL){ + load("./src/csl.js"); +} + +/** + * System localization wrappers. + *

Wrappers for commands that may require adaptation + * depending upon the environment in which citeproc-js + * is deployed. + * @namespace System wrappers + */ +CSL.System = {}; diff --git a/src/tests.js b/src/tests.js new file mode 100644 index 000000000..df11dd464 --- /dev/null +++ b/src/tests.js @@ -0,0 +1,99 @@ +dojo.provide("csl.tests"); +if (!CSL){ + load("./src/csl.js"); +} + +/** + * Static functions for reading and running standard CSL tests. + *

The functions here are specifically designed for test-bed + * operation of the distribution source. Implementors may wish + * to reimplement this module to confirm operation in their + * local environment.

+ * @namespace Tests + */ +CSL.System.Tests = function(){}; + +CSL.System.Tests.getTest = function(myname){ + var test; + var filename = "std/machines/" + myname + ".json"; + // + // Clean up the CSL token string. + var teststring = readFile(filename); + try { + eval( "test = "+teststring ); + } catch(e){ + throw e + teststring; + } + // + // Set up the token string to use for formatting. + if (test.mode == "bibliography"){ + var render = "makeBibliography"; + } else { + var render = "makeCitationCluster"; + } + // Build run function. + test.run = function(){ + var builder = new CSL.Core.Build(this.csl); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + CSL.System.Tests.fixNames(this.input,myname); + for each (var item in this.input){ + style.fun.retriever.setInput(style,item); + style.registry.insert(style,item); + } + var ret = style[render](this.input); + return ret; + }; + return test; +}; + + +CSL.System.Tests.fixNames = function(itemlist,myname){ + for each (obj in itemlist){ + if (!obj.id){ + throw "No id for object in: "+myname; + } + for each (key in ["author","editor","translator"]){ + if (obj[key]){ + for each (var entry in obj[key]){ + var one_char = entry.name.length-1; + var two_chars = one_char-1; + entry.sticky = false; + if ("!!" == entry.name.substr(two_chars)){ + entry.literal = entry.name.substr(0,two_chars).replace(/\s+$/,""); + } else { + var parsed = entry.name; + if ("!" == entry.name.substr(one_char)){ + entry.sticky = true; + parsed = entry.name.substr(0,one_char).replace(/\s+$/,""); + } + parsed = parsed.split(/\s*,\s*/); + if (parsed.length > 0){ + var m = parsed[0].match(/^\s*([a-z]+)\s+(.*)/); + if (m){ + entry.prefix = m[1]; + entry["primary-key"] = m[2]; + } else { + entry["primary-key"] = parsed[0]; + } + } + if (parsed.length > 1){ + entry["secondary-key"] = parsed[1]; + } + if (parsed.length > 2){ + var m = parsed[2].match(/\!\s*(.*)/); + if (m){ + entry.suffix = m[1]; + entry.comma_suffix = true; + } else { + entry.suffix = parsed[2]; + } + } + } + } + } + } + } + return itemlist; +}; diff --git a/src/token.js b/src/token.js new file mode 100644 index 000000000..924e6fee8 --- /dev/null +++ b/src/token.js @@ -0,0 +1,105 @@ +dojo.provide("csl.token"); +if (!CSL) { + load("./src/csl.js"); +} + +/** + * Style token. + *

This function generates the tokens in the list that defines + * the style. Note that tokens are initially generated by + * {@link CSL.Core.Build}, but must be post-processed with + * {@link CSL.Core.Configure} before they can be used to generate + * citations.

+ * @param {String} name The node name represented by this token. + * @param {Int} tokentype A flag indicating whether this token + * marks the start of a node, the end of a node, or is a singleton. + * @class + */ +CSL.Factory.Token = function(name,tokentype){ + /** + * Name of the element. + *

This corresponds to the element name of the + * relevant tag in the CSL file. + */ + this.name = name; + /** + * Default strings. + */ + this.strings = new Object(); + this.strings["delimiter"] = ""; + this.strings["prefix"] = ""; + this.strings["suffix"] = ""; + /** + * Formatting parameters. + *

This is a placeholder at instantiation. It is + * replaced by the result of {@link CSL.Factory.setDecorations} + * when the tag is created and configured during {@link CSL.Core.Build} + * by {@link CSL.Factory.XmlToToken}. The parameters for particular + * formatting attributes are stored as string arrays, which + * map to formatting functions in the {@link CSL.Core.Render} phase, + * when the output format is known. Note that the order in which + * parameters are registered is fixed by the constant + * {@link CSL.FORMAT_KEY_SEQUENCE}. + */ + this.decorations = false; + this.variables = []; + /** + * Element functions. + *

Functions implementing the styling behaviour of the element + * are pushed into this array in the {@link CSL.Core.Build} phase. + */ + this.execs = new Array(); + /** + * Token type. + *

This is a flag constant indicating whether the token represents + * a start tag, an end tag, or is a singleton.

+ */ + this.tokentype = tokentype; + /** + * Condition evaluator. + *

This is a placeholder that receives a single function, and is + * only relevant for a conditional branching tag (if or + * else-if). The function implements the argument to + * the match= attribute (any, all + * or none), by executing the functions registered in the + * tests array (see below), and reacting accordingly. This + * function is invoked by the execution wrapper found in + * {@link CSL.Core.Render}.

+ */ + this.evaluator = false; + /** + * Conditions. + *

Functions that evaluate to true or false, implementing + * various posisble attributes to the conditional branching tags, + * are registered here during {@link CSL.Core.Build}. + *

+ */ + this.tests = new Array(); + /** + * Jump point on success. + *

This holds the list jump point to be used when the + * evaluator function of a conditional tag + * returns true (success). The jump index value is set during the + * back-to-front token pass performed during {@link CSL.Core.Configure}. + *

+ */ + this.succeed = false; + /** + * Jump point on failure. + *

This holds the list jump point to be used when the + * evaluator function of a conditional tag + * returns false (failure). Jump index values are set during the + * back-to-front token pass performed during {@link CSL.Core.Configure}. + *

+ */ + this.fail = false; + /** + * Index of next token. + *

This holds the index of the next token in the + * token list, which is the default "jump-point" for ordinary + * processing. Jump index values are set during the + * back-to-front token pass performed during {@link CSL.Core.Configure}. + *

+ */ + this.next = false; +}; diff --git a/src/util.js b/src/util.js new file mode 100644 index 000000000..f7a5464bc --- /dev/null +++ b/src/util.js @@ -0,0 +1,10 @@ +dojo.provide("csl.util"); +if (!CSL){ + load("./src/csl.js"); +} + +/** + * Utilities for various things. + * @namespace Utilities + */ +CSL.Util = {}; diff --git a/src/util_dates.js b/src/util_dates.js new file mode 100644 index 000000000..924fd4ac6 --- /dev/null +++ b/src/util_dates.js @@ -0,0 +1,140 @@ +dojo.provide("csl.util_dates"); +if (!CSL) { + load("./src/csl.js"); +} + +/** + * Date mangling functions. + * @namespace Date construction utilities + */ +CSL.Util.Dates = new function(){}; + +/** + * Year manglers + *

short, long

+ */ +CSL.Util.Dates.year = new function(){}; + +/** + * Convert year to long form + *

This just passes the number back as a string.

+ */ +CSL.Util.Dates.year["long"] = function(state,num){ + return num.toString(); +} + +/** + * Convert year to short form + *

Just crops any 4-digit year to the last two digits.

+ */ +CSL.Util.Dates.year["short"] = function(state,num){ + num = num.toString(); + if (num && num.length == 4){ + return num.substr(2); + } +} + + +/* + * MONTH manglers + * long, short, numeric, numeric-leading-zeros + */ +CSL.Util.Dates["month"] = new function(){}; + +/** + * Convert month to numeric form + *

This just passes the number back as a string.

+ */ +CSL.Util.Dates.month["numeric"] = function(state,num){ + return num.toString(); +} + +/** + * Convert month to numeric-leading-zeros form + *

This just passes the number back as string padded with zeros.

+ */ +CSL.Util.Dates.month["numeric-leading-zeros"] = function(state,num){ + num = num.toString(); + while (num.length < 2){ + num = "0"+num; + } + return num.toString(); +} + +/** + * Convert month to long form + *

This passes back the month of the locale in long form.

+ */ +CSL.Util.Dates.month["long"] = function(state,num){ + num = num.toString(); + while (num.length < 2){ + num = "0"+num; + } + num = "month-"+num; + return state.opt.term[num]["long"][0]; +} + +/** + * Convert month to long form + *

This passes back the month of the locale in short form.

+ */ +CSL.Util.Dates.month["short"] = function(state,num){ + num = num.toString(); + while (num.length < 2){ + num = "0"+num; + } + num = "month-"+num; + return state.opt.term[num]["short"][0]; +} + + +/* + * DAY manglers + * numeric, numeric-leading-zeros, ordinal + */ +CSL.Util.Dates["day"] = new function(){}; + +/** + * Convert day to numeric form + *

This just passes the number back as a string.

+ */ +CSL.Util.Dates.day["numeric"] = function(state,num){ + return num.toString(); +} + +/** + * Convert day to numeric-leading-zeros form + *

This just passes the number back as a string padded with zeros.

+ */ +CSL.Util.Dates.day["numeric-leading-zeros"] = function(state,num){ + num = num.toString(); + while (num.length < 2){ + num = "0"+num; + } + return num.toString(); +} + +/** + * Convert day to ordinal form + *

This will one day pass back the number as a string with the + * ordinal suffix appropriate to the locale. For the present, + * it just does what is most of the time right for English.

+ */ +CSL.Util.Dates.day["ordinal"] = function(state,num){ + var suffixes = ["st","nd","rd","th"]; + var str = num.toString(); + if ( (num/10)%10 == 1){ + str += suffixes[3]; + } else if ( num%10 == 1) { + str += suffixes[0]; + } else if ( num%10 == 2){ + str += suffixes[1]; + } else if ( num%10 == 3){ + str += suffixes[2]; + } else { + str += suffixes[3]; + } + return str; +} + + diff --git a/src/util_disambiguate.js b/src/util_disambiguate.js new file mode 100644 index 000000000..1a139058a --- /dev/null +++ b/src/util_disambiguate.js @@ -0,0 +1,97 @@ +dojo.provide("csl.util_disambiguate"); +if (!CSL) { + load("./src/csl.js"); +} + +// +// This will probably become CSL.Util.Numbers +// + +/** + * Auxiliary helper functions for disambiguation. + * @namespace Disambiguation utilities + */ +CSL.Util.Disambiguate = new function(){}; + +CSL.Util.Disambiguate.Romanizer = function (){}; + +CSL.Util.Disambiguate.Romanizer.prototype.format = function(num){ + var ret = ""; + if (num < 6000) { + var numstr = num.toString().split(""); + numstr.reverse(); + var pos = 0; + var n = 0; + for (var pos in numstr){ + n = parseInt(numstr[pos],10); + ret = CSL.ROMAN_NUMERALS[pos][n] + ret; + } + } + return ret; +}; + + +/** + * Create a suffix formed from a list of arbitrary characters of arbitrary length. + *

This is a lot harder than it seems.

+ */ +CSL.Util.Disambiguate.Suffixator = function(slist){ + this.slist = slist.split(","); +}; + +/** + * The format method. + *

This method is used in generating ranges. Every numeric + * formatter (of which Suffixator is one) must be an instantiated + * object with such a "format" method.

+ */ + +CSL.Util.Disambiguate.Suffixator.prototype.format = function(num){ + var suffixes = this.get_suffixes(num); + return suffixes[(suffixes.length-1)]; +} + +CSL.Util.Disambiguate.Suffixator.prototype.get_suffixes = function(num){ + var suffixes = new Array(); + + for (var i=0; i <= num; i++){ + if (!i){ + suffixes.push([0]); + } else { + suffixes.push( this.incrementArray(suffixes[(suffixes.length-1)],this.slist) ); + } + }; + for (pos in suffixes){ + var digits = suffixes[pos]; + var chrs = ""; + for each (digit in digits){ + chrs = chrs+this.slist[digit]; + } + suffixes[pos] = chrs; + }; + return suffixes; +}; + + +CSL.Util.Disambiguate.Suffixator.prototype.incrementArray = function (array){ + array = array.slice(); + var incremented = false; + for (var i=(array.length-1); i > -1; i--){ + if (array[i] < (this.slist.length-1)){ + array[i] += 1; + if (i < (array.length-1)){ + array[(i+1)] = 0; + } + incremented = true; + break; + } + } + if (!incremented){ + for (var i in array){ + array[i] = 0; + } + var newdigit = [0]; + array = newdigit.concat(array); + } + return array; +}; diff --git a/src/util_names.js b/src/util_names.js new file mode 100644 index 000000000..499fe891a --- /dev/null +++ b/src/util_names.js @@ -0,0 +1,245 @@ +dojo.provide("csl.util_names"); +if (!CSL) { + load("./src/csl.js"); +} + +/** + * Helper functions for constructing names and namesets. + * @namespace Name construction utilities + */ +CSL.Util.Names = new function(){}; + +/** + * Build a set of names, less any label or et al. tag + */ +CSL.Util.Names.outputNames = function(state,display_names){ + + var segments = new this.StartMiddleEnd(state,display_names); + var sort_order = state.output.getToken("name").strings["name-as-sort-order"]; + if (sort_order == "first"){ + state.output.addToken("start"); + state.output.getToken("start").strings.name_as_sort_order = true; + } else if (sort_order == "all"){ + state.output.addToken("start"); + state.output.getToken("start").strings.name_as_sort_order = true; + state.output.addToken("middle"); + state.output.getToken("middle").strings.name_as_sort_order = true; + state.output.addToken("end"); + state.output.getToken("end").strings.name_as_sort_order = true; + } + + state.output.openLevel("name"); + state.output.openLevel("inner"); + segments.outputSegmentNames("start"); + segments.outputSegmentNames("middle"); + state.output.closeLevel(); + segments.outputSegmentNames("end"); + state.output.closeLevel(); +}; + +CSL.Util.Names.StartMiddleEnd = function(state,names){ + this.state = state; + this.nameoffset = 0; + // + // what to do here? we need config for this, tokens to + // control the joining that will come. how do we get + // them into this function? + var start = names.slice(0,1); + var middle = names.slice(1,(names.length-1)); + var endstart = 1; + if (names.length > 1){ + endstart = (names.length-1); + } + var end = names.slice(endstart,(names.length)); + var ret = {}; + ret["start"] = start; + ret["middle"] = middle; + ret["end"] = end; + this.segments = ret; +}; + +CSL.Util.Names.StartMiddleEnd.prototype.outputSegmentNames = function(seg){ + var state = this.state; + for (var namenum in this.segments[seg]){ + this.namenum = parseInt(namenum,10); + this.name = this.segments[seg][namenum]; + if (this.name.literal){ + // + // XXXXX Separate formatting for institution names? + // XXXXX This needs to be firmly settled in xbib. + // + state.output.append(this.name.literal); + } else { + var sequence = CSL.Util.Names.getNamepartSequence(this.name,state.output.getToken(seg)); + + state.output.openLevel(sequence[0][0]); + state.output.openLevel(sequence[0][1]); + state.output.openLevel(sequence[0][2]); + this.outputNameParts(sequence[1]); + + state.output.closeLevel(); + state.output.openLevel(sequence[0][2]); + + // XXX cloned code! make this a function. + this.outputNameParts(sequence[2]); + + state.output.closeLevel(); + state.output.closeLevel(); + // + // articular goes here // + // + this.outputNameParts(sequence[3]); + + state.output.closeLevel(); + + // + // the articular goes in at a different level, but + // is nonetheless part of the name, so it goes into + // this function to avoid repetition. + // (special handling when comma is to be included) + //if (name.suffix){ + // state.output.squeeze(); + // if (name.comma_suffix){ + // state.tmp.delimiter.replace(", "); + // } + // state.output.append(name.suffix); + //} + } + }; + this.nameoffset += this.segments[seg].length; +} + +CSL.Util.Names.StartMiddleEnd.prototype.outputNameParts = function(subsequence){ + var state = this.state; + for each (var key in subsequence){ + var namepart = this.name[key]; + if ("secondary-key" == key && !this.name.sticky){ + if (0 == state.tmp.disambig_settings["givens"][state.tmp.nameset_counter][(this.namenum+this.nameoffset)]){ + continue; + } else if (1 == state.tmp.disambig_settings["givens"][state.tmp.nameset_counter][(this.namenum+this.nameoffset)]){ + namepart = state.fun.initialize_with(namepart,state.tmp["initialize-with"]); + } + } + //state.output.openLevel(key); + state.output.append(namepart,key); + //state.output.closeLevel(); + } +} + +CSL.Util.Names.getNamepartSequence = function(name,token){ + // Set the rendering order and separators of the core nameparts + // sequence[0][0] separates elements inside each of the the two lists + // sequence[0][1] separates the two lists + if (name.comma_suffix){ + var suffix_sep = "commasep"; + } else { + var suffix_sep = "space"; + } + var romanesque = name["primary-key"].match(/.*[a-zA-Z\u0400-\u052f].*/); + if (!romanesque ){ // neither roman nor Cyrillic characters + var sequence = [["empty","empty","empty"],["prefix", "primary-key"],["secondary-key"],[]]; + } else if (name.sticky) { // entry likes sort order + var sequence = [["space","space","space"],["prefix", "primary-key"],["secondary-key"],[]]; + } else if (token && token.strings.name_as_sort_order){ + var sequence = [["sortsep","sortsep","space"],["prefix", "primary-key"],["secondary-key"],["suffix"]]; + } else { // plain vanilla + var sequence = [[suffix_sep,"space","space"],["secondary-key"],["prefix","primary-key"],["suffix"]]; + } + return sequence; +}; + +CSL.Util.Names.deep_copy = function(nameset){ + var nameset2 = new Array(); + for each (name in nameset){ + var name2 = new Object(); + for (var i in name){ + name2[i] = name[i]; + } + nameset2.push(name2); + } + return nameset2; +} + + +/** + * Reinitialize scratch variables used by names machinery. + */ +// +// XXXX A handy guide to variable assignments that need +// XXXX to be eliminated. :) +// +CSL.Util.Names.reinit = function(state,Item){ + // + // Author vars should render only once. This flag + // can be used to quash unwanted renderings. + for each (namevar in state.tmp.value){ + state.tmp.name_quash[namevar.type] = true; + } + state.tmp.value = new Array(); + state.tmp.names_substituting = false; + state.tmp.name_et_al_term = false; + state.tmp.name_et_al_decorations = false; + + + state.tmp.name_et_al_form = "long"; + state.tmp["et-al-min"] = false; + state.tmp["et-al-use-first"] = false; + state.tmp["initialize-with"] = false; + state.tmp["name-as-sort-order"] = false; + state.tmp.et_al_prefix = false; +}; + +CSL.Util.Names.getCommonTerm = function(state,namesets){ + if (namesets.length < 2){ + return false; + } + var base_nameset = namesets[0]; + var varnames = new Array(); + if (varnames.indexOf(base_nameset.type) == -1){ + varnames.push(base_nameset.type); + } + var name; + for each (nameset in namesets.slice(1)){ + if (base_nameset.length != nameset.length){ + return false; + } + if (varnames.indexOf(nameset.type) == -1){ + varnames.push(nameset.type); + } + for (var n in nameset.names){ + name = nameset.names[n]; + for each (var part in ["primary-key","secondary-key","prefix","suffix"]){ + if (base_nameset.names[n][part] != name[part]){ + return false; + } + } + } + } + varnames.sort(); + return state.opt.term[varnames.join("")]; +}; + + +/** + * Initialize a name. + */ +CSL.Util.Names.initialize_with = function(name,terminator){ + var namelist = name.split(/\s+/); + var nstring = ""; + for each (var n in namelist){ + var m = n.match( CSL.NAME_INITIAL_REGEXP); + if (m){ + var extra = ""; + if (m[2]){ + extra = m[2].toLocaleLowerCase(); + } + nstring = nstring + m[1].toLocaleUpperCase() + extra + terminator; + }; + }; + if (nstring){ + return nstring; + } + return name; +}; + + diff --git a/src/util_sort.js b/src/util_sort.js new file mode 100644 index 000000000..d6fe9c8cd --- /dev/null +++ b/src/util_sort.js @@ -0,0 +1,23 @@ +dojo.provide("csl.util_sort"); +if (!CSL) { + load("./src/csl.js"); +} + +/** + * Helper functions for constructing sort keys. + * @namespace Sort key utilities + */ +CSL.Util.Sort = new function(){}; + +/** + * Strip prepositions from a string + *

Used when generating sort keys.

+ */ +CSL.Util.Sort.strip_prepositions = function(str){ + var m = str.toLocaleLowerCase().match(/((a|an|the)\s+)/); + if (m){ + str = str.substr(m[1].length); + }; + return str; +}; + diff --git a/src/util_token.js b/src/util_token.js new file mode 100644 index 000000000..eb8d4f8a6 --- /dev/null +++ b/src/util_token.js @@ -0,0 +1,3 @@ +dojo.provide("csl.util_token"); + + diff --git a/src/xml.js b/src/xml.js new file mode 100644 index 000000000..188c690a2 --- /dev/null +++ b/src/xml.js @@ -0,0 +1,13 @@ +dojo.provide("csl.xml"); + +if (!CSL) { + load("./src/csl.js"); +} + +/** + * Parser modules. + *

A namespace container for wrappers implementing basic + * commands needed for depth-first navigation of an XML object.

+ * @namespace XML parsers + */ +CSL.System.Xml = {}; diff --git a/src/xmle4x.js b/src/xmle4x.js new file mode 100644 index 000000000..409ce55ef --- /dev/null +++ b/src/xmle4x.js @@ -0,0 +1,69 @@ +dojo.provide("csl.xmle4x"); + +if (!CSL) { + load("./src/csl.js"); +} + +/** + * Functions for parsing an XML object using E4X. + */ +CSL.System.Xml.E4X = function(){}; + + +/** + * E4X can't handle XML declarations, so we lose them here. + */ +CSL.System.Xml.E4X.prototype.clean = function(xml){ + xml = xml.replace(/<\?[^?]+\?>/g,""); + xml = xml.replace(/]+>/g,""); + xml = xml.replace(/^\s+/g,""); + xml = xml.replace(/\s+$/g,""); + return xml; +}; + + +/** + * Make an E4X object from a style. + */ +CSL.System.Xml.E4X.prototype.parse = function(xml){ + default xml namespace = "http://purl.org/net/xbiblio/csl"; + return XML( this.clean(xml) ); +}; + + +/** + * Called on a node. + */ +CSL.System.Xml.E4X.prototype.commandInterface = new function(){ + this.children = children; + this.nodename = nodename; + this.attributes = attributes; + this.content = content; + this.numberofnodes = numberofnodes; + + function children(){ + return this.children(); + }; + function nodename(){ + return this.localName(); + } + function attributes(){ + var ret = new Object(); + var attrs = this.attributes(); + for (var idx in attrs){ + var key = "@"+attrs[idx].localName(); + var value = attrs[idx].toString(); + ret[key] = value; + } + return ret; + } + function content(){ + return this.toString(); + } + function numberofnodes(){ + return this.length(); + } +}; + + +CSL.System.Xml.E4X = new CSL.System.Xml.E4X(); diff --git a/src/xmljs.js b/src/xmljs.js new file mode 100644 index 000000000..8240717f7 --- /dev/null +++ b/src/xmljs.js @@ -0,0 +1,228 @@ +dojo.provide("csl.xmljs"); + +if (!CSL) { + load("./src/csl.js"); +} + +/** + * A barebones parser for CSL format files. + *

This parser was the end product of difficulties I + * experienced in working out the basics of the E4X XML + * parser. It is unnecessary where E4X is available, + * but I've retained it as a demonstration of how the + * wrapper code works. It's not really meant for production + * use (it's slower than E4X, and one could probably construct + * a valid CSL style file that would break it).

+ */ +CSL.System.Xml.JunkyardJavascript = function(){}; + + +/* + * Clean the XML string in preparation for parsing. + * + * Most parser implementations will have something like this. + * In most cases it will be a lot less complex, though. + */ +CSL.System.Xml.JunkyardJavascript.prototype.clean = function(xml) { + xml = xml.replace(/\n/g,""); + xml = xml.replace(/\>\s+/g,">"); + xml = xml.replace(/\s+\]+>)/); + var newlist = new Array(); + var i; + var tag = false; + var tagname = false; + for (i=0; i>= or <<= and the block name (which must be in all caps) are +signficant. Everything outside of the block delimiters is ignored, +but you may wish to set of comments with a comment character, for +clarity. + + +## Test ## + +# The MODE block is a single string, either "citation" or "bibliography" +# (without quotes). This specifies the type of output that the processor +# should deliver for testing. + + >>===== MODE =====>> +citation + <<===== MODE =====<< + + +# The RESULT block is a simple string. If quotes are included in the +# result, they should not be escaped; just write what would appear +# on the monitor if the result of processing were dumped to standard +# output. + + + >>===== RESULT =====>> +Doe 2000a,b;2001 + <<===== RESULT =====<< + + +# The CSL block should be a valid CSL style file. These blocks +# are separately saved to the ./csl subdirectory in the test +# archive, so that they can be validated if desired. + +>>===== CSL =====>> + +<<===== CSL =====<< + +# The INPUT block is a list of input objects, written as +# valid JSON. +# +# Note that names are written as a simple string that must +# be parsed into the internal representation required by the +# processor being tested. The hinting syntax of name strings +# is as follows: +# +# Literal name (for institutions and the like): +# name="Ministry of Fear, Loathing and Error !!" +# +# Simple western name: +# name="Doe, John" +# +# Western name with articular: +# name="van Doe, John" +# +# Western name with capitalized articular: +# name="VAN Doe, John" +# +# Western name with suffix (no comma in output): +# name="Doe, John, III" +# +# Western name with suffix (comma delimiter in output): +# name="Doe, John,! Jr." +# +# Names fixed in sort ordering (common in East and Southeast Asia): +# name="Takeda, Shingen !" +# +# Names in non-Roman, non-Cyrillic fonts are to be combined +# to single joined-up strings in sort ordering, with no other +# processing. + +>>===== INPUT =====>> +[ + { + "id":"ITEM-1", + "type": "book", + "author": [ + { "name":"Doe, John" } + ], + "issued": {"year": "2000"}, + "title": "Paper 1" + }, + { + "id":"ITEM-2", + "type": "book", + "author": [ + { "name":"Doe, John" } + ], + "issued": {"year": "2000"}, + "title": "Paper 2" + }, + { + "id":"ITEM-3", + "type": "book", + "author": [ + { "name":"Doe, John" } + ], + "issued": {"year": "2001"}, + "title": "Paper 3" + } +] +<<===== INPUT =====<< diff --git a/std/grind.sh b/std/grind.sh new file mode 100755 index 000000000..eea8f9387 --- /dev/null +++ b/std/grind.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +set -e + +if [ $(which gsed | grep -c "/" ) -gt 0 ]; then + SED="gsed" +else + SED="sed" +fi + +echo using $SED + +cd $(dirname $0) + +for d in tmp csl machines; do + if [ ! -d ${d} ]; then + mkdir ${d} + fi +done + +rm -f csl/*.csl +rm -f machines/*.json + +for filename in humans/*.txt; do + BASENAME=$(basename ${filename} .txt) + SRC=humans/${BASENAME}.txt + RES=machines/${BASENAME}.json + + if [ $(echo ${BASENAME} | grep -c "_") -eq 0 ]; then + echo ERROR $(basename $0): bad filename \"${BASENAME}\": must contain a _ character. + exit 1 + fi + + CATEGORY=$(echo ${BASENAME} | $SED -e "s/^\([^_]*\)_.*/\\1/") + NAME=$(echo ${BASENAME} | $SED -e "s/^[^_]*_\(.*\)/\\1/;s/\(.\)\([A-Z]\)/\\1 \\2/g") + + cat ${SRC} | $SED -e "s/^[[:space:]]*<<=/<<=/;s/^[[:space:]]*>>=/>>=/" > tmp/TMP.txt + cat tmp/TMP.txt | $SED -e "/^>>=.*CSL/,/^<<=.*CSL/!d" | $SED -e "/^\(>>=\|<<=\)/d" > csl/${BASENAME}.csl + CSL=$(cat csl/${BASENAME}.csl | $SED -e 's~"~\\"~g' | $SED -e "s/$/\\\\n/" | tr -d '\r\n' | $SED -e "s/\\\\n$//") + RESULT=$(cat tmp/TMP.txt | $SED -e "/^>>=.*RESULT/,/^<<=.*RESULT/!d" | $SED -e "/^\(>>=\|<<=\)/d" | $SED -e 's~"~\\"~g' |$SED -e '$!s~$~\\n~' | tr -d '\r\n') + MODE=$(cat tmp/TMP.txt | $SED -e "/^>>=.*MODE/,/^<<=.*MODE/!d" | $SED -e "/^\(>>=\|<<=\)/d") + INPUT=$(cat tmp/TMP.txt | $SED -e "/^>>=.*INPUT/,/^<<=.*INPUT/!d" | $SED -e "/^\(>>=\|<<=\)/d") + SCHEMA=$(cat tmp/TMP.txt | $SED -e "/^>>=.*SCHEMA/,/^<<=.*SCHEMA/!d" | $SED -e "/^\(>>=\|<<=\)/d") + + echo '{' > ${RES} + + echo ' "name": "'${NAME}'",' >> ${RES} + echo ' "category": "'${CATEGORY}'",' >> ${RES} + echo ' "mode": "'${MODE}'",' >> ${RES} + echo ' "schema":"'${SCHEMA}'",' >> ${RES} + echo ' "result": "'${RESULT}'",' >> ${RES} + echo ' "csl": "'${CSL}'",' >> ${RES} + echo ' "input": '${INPUT} >> ${RES} + echo '}' >> ${RES} +done + +rm tmp/* +rmdir tmp diff --git a/std/humans/collapse_CitationNumberRangesWithAffixes.txt b/std/humans/collapse_CitationNumberRangesWithAffixes.txt new file mode 100644 index 000000000..8db126720 --- /dev/null +++ b/std/humans/collapse_CitationNumberRangesWithAffixes.txt @@ -0,0 +1,52 @@ +# CSL test file: testYearSuffix001.txt +# Rintze Zelle circa 2009.04.10 + +>>===== MODE =====>> +citation +<<===== MODE =====<< + + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +([1]-[3]) +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[ + { + "id":"ITEM-1", + "type": "book", + "title": "Paper 1" + }, + { + "id":"ITEM-2", + "type": "book", + "title": "Paper 2" + }, + { + "id":"ITEM-3", + "type": "book", + "title": "Paper 3" + } +] +<<===== INPUT =====<< diff --git a/std/humans/collapse_YearSuffixCollapse.txt b/std/humans/collapse_YearSuffixCollapse.txt new file mode 100644 index 000000000..740373a93 --- /dev/null +++ b/std/humans/collapse_YearSuffixCollapse.txt @@ -0,0 +1,92 @@ +# CSL test file: testYearSuffix001.txt +# Rintze Zelle circa 2009.04.10 + +>>===== MODE =====>> +citation +<<===== MODE =====<< + + +>>===== SCHEMA =====>> +0.9 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Smith 2000a,c-e, 2001 +<<===== RESULT =====<< + + +>>===== CITATION =====>> +[{ "id": "ITEM-1" },{"id":"ITEM-3"},{"id":"ITEM-4"},{"id":"ITEM-5"},{"id":"ITEM-6"}] +<<===== CITATION =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[ + { + "id":"ITEM-1", + "type": "book", + "author": [{"name":"John Smith","primary-key":"Smith","secondary-key":"John"}], + "title": "Paper 1", + "issued": {"year":"2000"} + }, + { + "id":"ITEM-2", + "type": "book", + "author": [{"name":"John Smith","primary-key":"Smith","secondary-key":"John"}], + "title": "Paper 2", + "issued": {"year":"2000"} + }, + { + "id":"ITEM-3", + "type": "book", + "author": [{"name":"John Smith","primary-key":"Smith","secondary-key":"John"}], + "title": "Paper 3", + "issued": {"year":"2000"} + }, + { + "id":"ITEM-4", + "type": "book", + "author": [{"name":"John Smith","primary-key":"Smith","secondary-key":"John"}], + "title": "Paper 4", + "issued": {"year":"2000"} + }, + { + "id":"ITEM-5", + "type": "book", + "author": [{"name":"John Smith","primary-key":"Smith","secondary-key":"John"}], + "title": "Paper 5", + "issued": {"year":"2000"} + }, + { + "id":"ITEM-6", + "type": "book", + "author": [{"name":"John Smith","primary-key":"Smith","secondary-key":"John"}], + "title": "Paper 6", + "issued": {"year":"2001"} + } +] +<<===== INPUT =====<< diff --git a/std/humans/condition_RefTypeBranching.txt b/std/humans/condition_RefTypeBranching.txt new file mode 100644 index 000000000..cba247a09 --- /dev/null +++ b/std/humans/condition_RefTypeBranching.txt @@ -0,0 +1,162 @@ +>>===== MODE =====>> +bibliography +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Work 1 (John Doe), 2000. +John Doe, 2000. Work 2. +2000. Work 3, John Doe. +Work 4 (2000), John Doe. +Work 5, John Doe, 2000. +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[ + { + "id":"ITEM-1", + "type": "book", + "author": [ + { "name":"Doe, John" } + ], + "issued": {"year": "2000"}, + "title": "Work 1" + }, + { + "id":"ITEM-2", + "type": "article", + "author": [ + { "name":"Doe, John" } + ], + "issued": {"year": "2000"}, + "title": "Work 2" + }, + { + "id":"ITEM-3", + "type": "section-book", + "author": [ + { "name":"Doe, John" } + ], + "issued": {"year": "2000"}, + "title": "Work 3" + }, + { + "id":"ITEM-4", + "type": "paper-conference", + "author": [ + { "name":"Doe, John" } + ], + "issued": {"year": "2000"}, + "title": "Work 4" + }, + { + "id":"ITEM-5", + "type": "chapter", + "author": [ + { "name":"Doe, John" } + ], + "issued": {"year": "2000"}, + "title": "Work 5" + } +] +<<===== INPUT =====<< diff --git a/std/humans/date_YearSuffixDelimiter.txt b/std/humans/date_YearSuffixDelimiter.txt new file mode 100644 index 000000000..6b4b12fbd --- /dev/null +++ b/std/humans/date_YearSuffixDelimiter.txt @@ -0,0 +1,136 @@ +# CSL test file: testYearSuffix001.txt +# Frank Bennett 2009.04.05 + +### Intro ### + +This is a test source file for use in testing processors of the +Citation Style Language (CSL) + +Test source files (like this one) are ground into valid JSON by +the ./grind.sh script in the root directory of the test archive. + + +A test consists of four required blocks: MODE, RESULT, CSL and INPUT + +Blocks of the test are delimited as show below. Only the leading +>>= or <<= and the block name (which must be in all caps) are +signficant. Everything outside of the block delimiters is ignored, +but you may wish to set of comments with a comment character, for +clarity. + + +## Test ## + +# The MODE block is a single string, either "citation" or "bibliography" +# (without quotes). This specifies the type of output that the processor +# should deliver for testing. + + >>===== MODE =====>> +citation + <<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +# The RESULT block is a simple string. If quotes are included in the +# result, they should not be escaped; just write what would appear +# on the monitor if the result of processing were dumped to standard +# output. + + + >>===== RESULT =====>> +Doe 2000a,b;2001 + <<===== RESULT =====<< + + +# The CSL block should be a valid CSL style file. These blocks +# are separately saved to the ./csl subdirectory in the test +# archive, so that they can be validated if desired. + +>>===== CSL =====>> + +<<===== CSL =====<< + +# The INPUT block is a list of input objects, written as +# valid JSON. +# +# Note that names are written as a simple string that must +# be parsed into the internal representation required by the +# processor being tested. The hinting syntax of name strings +# is as follows: +# +# Literal name (for institutions and the like): +# name="Ministry of Fear, Loathing and Error !!" +# +# Simple western name: +# name="Doe, John" +# +# Western name with articular: +# name="van Doe, John" +# +# Western name with capitalized articular: +# name="VAN Doe, John" +# +# Western name with suffix (no comma in output): +# name="Doe, John, III" +# +# Western name with suffix (comma delimiter in output): +# name="Doe, John,! Jr." +# +# Names fixed in sort ordering (common in East and Southeast Asia): +# name="Takeda, Shingen !" +# +# Names in non-Roman, non-Cyrillic fonts are to be combined +# to single joined-up strings in sort ordering, with no other +# processing. + +>>===== INPUT =====>> +[ + { + "id":"ITEM-1", + "type": "book", + "author": [ + { "name":"Doe, John" } + ], + "issued": {"year": "2000"}, + "title": "Paper 1" + }, + { + "id":"ITEM-2", + "type": "book", + "author": [ + { "name":"Doe, John" } + ], + "issued": {"year": "2000"}, + "title": "Paper 2" + }, + { + "id":"ITEM-3", + "type": "book", + "author": [ + { "name":"Doe, John" } + ], + "issued": {"year": "2001"}, + "title": "Paper 3" + } +] +<<===== INPUT =====<< diff --git a/std/humans/disambiguate_BaseNameCountOnFailureIfYearSuffixAvailable.txt b/std/humans/disambiguate_BaseNameCountOnFailureIfYearSuffixAvailable.txt new file mode 100644 index 000000000..741005ccf --- /dev/null +++ b/std/humans/disambiguate_BaseNameCountOnFailureIfYearSuffixAvailable.txt @@ -0,0 +1,86 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.9 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Asthma, et al. (1990a); Asthma, et al. (1990b); Dropsy, Enteritis, X. Fever (2000); Dropsy, Enteritis, Y. Fever (2000) +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[ + { + "id":"ITEM-1", + "type": "book", + "author": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Crispin" } + ], + "issued": {"year": "1990"}, + "title": "Book A" +}, +{ + "id":"ITEM-2", + "type": "book", + "author": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Beauregarde" }, + { "name":"Cold, Crispin" } + ], + "issued": {"year": "1990"}, + "title": "Book B" + }, +{ + "id":"ITEM-3", + "type": "book", + "author": [ + { "name":"Dropsy, Devon" }, + { "name":"Enteritis, Edward" }, + { "name":"Fever, Xavier" } + ], + "issued": {"year": "2000"}, + "title": "Book C" + }, +{ + "id":"ITEM-4", + "type": "book", + "author": [ + { "name":"Dropsy, Devon" }, + { "name":"Enteritis, Ernie" }, + { "name":"Fever, Yves" } + ], + "issued": {"year": "2000"}, + "title": "Book D" + } +] +<<===== INPUT =====<< diff --git a/std/humans/disambiguate_BasedOnEtAlSubsequent.txt b/std/humans/disambiguate_BasedOnEtAlSubsequent.txt new file mode 100644 index 000000000..b00242008 --- /dev/null +++ b/std/humans/disambiguate_BasedOnEtAlSubsequent.txt @@ -0,0 +1,118 @@ +This test illustrates a use case for the following rule, discussed on the Zotero forums: + + "When different groups of authors with the same first author and date + occur, they should be cited thus: (Able, Baker & Charles 1986a; Able, + David & Edwards 1986b), then subsequently abbreviated to (Able et al. + 1986a; Able et al. 1986b)." + + "Italicized letters 'a', 'b', 'c', etc., should be added to the date of + papers with the same first authorship and year" + +The test illustrates that the first rule can be satisfied with the CSL 0.8 +feature set, and the second using the year-suffix text variable introduced +in CSL 0.9. It differs slightly from the example given by the poster +(asplundj) in that the cites do not include author initials, but this conforms +to the cited style guide. + + +The discussion can be found at: + http://forums.zotero.org/discussion/5290/collapse-year-suffix/ + +The style guide containing the rule quoted above can be found +at: + http://www.wiley.com/bw/submit.asp?ref=0269-8463&site=1 + + +The point in all of this for implementers is that evaluation of +an in-text key for disambiguation purposes should be based on the +subsequent form of the cite, even if it occurs only once in the +text. + + +Frank Bennett +2009-04-14 + + + +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.9 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +(Baur, Fröberg, Baur, et al. 2000a; Baur, Schileyko & Baur 2000b; Doe 2000) +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[ + { + "id":"ITEM-1", + "type": "article-journal", + "author": [ + { "name":"Baur, Bruno" }, + { "name": "Fröberg, Lars" }, + { "name": "Baur, Anette" }, + { "name": "Guggenheim, Richard" }, + { "name": "Haase, Martin" } + ], + "issued": { "year": "2000" }, + "title": "Ultrastructure of snail grazing damage to calcicolous lichens", + "container-title": "Nordic Journal of Botany", + "volume": "20", + "page-range": "119-128" + }, + { + "id":"ITEM-2", + "type":"article-journal", + "author": [ + { "name": "Baur, Bruno" }, + { "name": "Schileyko, Anatoly A." }, + { "name": "Baur, Anette" } + ], + "issued": { "year": "2000" }, + "title": "Ecological observations on _Arianta aethiops aethiops_ (Helicidae), a land snail endemic to the South Carpathian mountains, Romania", + "container-title": "Journal of Molluscan Studies", + "volume": "66", + "page-range": "285-289" + }, + { + "id":"ITEM-3", + "type":"article-journal", + "author": [ + { "name": "Doe, John" } + ], + "issued": { "year": "2000" }, + "title": "Some bogus title", + "container-title": "Journal of Irreproducible Results", + "volume": "666", + "page-range": "000-1" + } +] +<<===== INPUT =====<< diff --git a/std/humans/disambiguate_DisambiguateCondition.txt b/std/humans/disambiguate_DisambiguateCondition.txt new file mode 100644 index 000000000..516554707 --- /dev/null +++ b/std/humans/disambiguate_DisambiguateCondition.txt @@ -0,0 +1,70 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Doe, et al., Book A (2000); Doe, et al., Book B (2000) +<<===== RESULT =====<< + + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[ + { + "id":"ITEM-1", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Jane" } + ], + "issued": {"year": "2000"}, + "title": "Book A" + }, + { + "id":"ITEM-2", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Jane" } + ], + "issued": {"year": "2000"}, + "title": "Book B" + } +] +<<===== INPUT =====<< diff --git a/std/humans/disambiguate_GivennameExpandCrossNestedNames.txt b/std/humans/disambiguate_GivennameExpandCrossNestedNames.txt new file mode 100644 index 000000000..3df3ade00 --- /dev/null +++ b/std/humans/disambiguate_GivennameExpandCrossNestedNames.txt @@ -0,0 +1,66 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +J. Doe, Jane Roe, Robert Jones; J. Doe, Josephine Roe, Robert Jones; J. Doe, Jane Roe, Richard Jones +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"ambigs-12", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Jane" }, + { "name":"Jones, Robert" } + ], + "issued": {"year": "1990"}, + "title": "Book C" +}, +{ + "id":"ambigs-13", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Josephine" }, + { "name":"Jones, Robert" } + ], + "issued": {"year": "1990"}, + "title": "Book B" +}, +{ + "id":"ambigs-14", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Jane" }, + { "name":"Jones, Richard" } + ], + "issued": {"year": "1990"}, + "title": "Book A" +}] +<<===== INPUT =====<< diff --git a/std/humans/disambiguate_MinimalGivennameExpandMinimalNames.txt b/std/humans/disambiguate_MinimalGivennameExpandMinimalNames.txt new file mode 100644 index 000000000..4e0015067 --- /dev/null +++ b/std/humans/disambiguate_MinimalGivennameExpandMinimalNames.txt @@ -0,0 +1,60 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +A. Asthma, Brandon Bronchitis, et al.; A. Asthma, Biff Bronchitis, et al. +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"ambigs-16", + "type": "book", + "author": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Brandon" }, + { "name":"Cold, Charles" } + ], + "issued": {"year": "1990"}, + "title": "Book M" +}, +{ + "id":"ambigs-17", + "type": "book", + "author": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Biff" }, + { "name":"Cold, Curtis" } + ], + "issued": {"year": "1990"}, + "title": "Book M" +}] +<<===== INPUT =====<< diff --git a/std/humans/disambiguate_RetainNamesOnFailureIfYearSuffixNotAvailable.txt b/std/humans/disambiguate_RetainNamesOnFailureIfYearSuffixNotAvailable.txt new file mode 100644 index 000000000..a40894c42 --- /dev/null +++ b/std/humans/disambiguate_RetainNamesOnFailureIfYearSuffixNotAvailable.txt @@ -0,0 +1,85 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.9 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Asthma, Bronchitis, Cold (1990); Asthma, Bronchitis, Cold (1990); Dropsy, Enteritis, X. Fever (2000); Dropsy, Enteritis, Y. Fever (2000) +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[ + { + "id":"ITEM-1", + "type": "book", + "author": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Crispin" } + ], + "issued": {"year": "1990"}, + "title": "Book A" +}, +{ + "id":"ITEM-2", + "type": "book", + "author": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Beauregarde" }, + { "name":"Cold, Crispin" } + ], + "issued": {"year": "1990"}, + "title": "Book B" + }, +{ + "id":"ITEM-3", + "type": "book", + "author": [ + { "name":"Dropsy, Devon" }, + { "name":"Enteritis, Edward" }, + { "name":"Fever, Xavier" } + ], + "issued": {"year": "2000"}, + "title": "Book C" + }, +{ + "id":"ITEM-4", + "type": "book", + "author": [ + { "name":"Dropsy, Devon" }, + { "name":"Enteritis, Ernie" }, + { "name":"Fever, Yves" } + ], + "issued": {"year": "2000"}, + "title": "Book D" + } +] +<<===== INPUT =====<< diff --git a/std/humans/disambiguate_YearSuffixAndSort.txt b/std/humans/disambiguate_YearSuffixAndSort.txt new file mode 100644 index 000000000..6fbac65db --- /dev/null +++ b/std/humans/disambiguate_YearSuffixAndSort.txt @@ -0,0 +1,191 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +1990m!; 1990l!; 1990k!; 1990j!; 1990i!; 1990h!; 1990g!; 1990f!; 1990e!; 1990d!; 1990c!; 1990b!; 1990a! +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"ambigs-1", + "type": "book", + "author": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Crispin" }, + { "name":"Dropsy, David" }, + { "name":"Ebola, Elvin" }, + { "name":"Fever, Fergus" } + ], + "issued": {"year": "1990"}, + "title": "Book M" +}, +{ + "id":"ambigs-2", + "type": "book", + "author": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Crispin" }, + { "name":"Dropsy, David" }, + { "name":"Enteritis, Ernie" }, + { "name":"Fever, Fergus" } + ], + "issued": {"year": "1990"}, + "title": "Book L" +}, +{ + "id":"ambigs-3", + "type": "book", + "author": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Crispin" }, + { "name":"Dropsy, David" }, + { "name":"Ebola, Elvin" }, + { "name":"Fever, Fergus" } + ], + "issued": {"year": "1990"}, + "title": "Book K" +}, +{ + "id":"ambigs-4", + "type": "book", + "author": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Crispin" } + ], + "issued": {"year": "1990"}, + "title": "Book J" +}, +{ + "id":"ambigs-5", + "type": "book", + "author": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Beauregarde" }, + { "name":"Cold, Crispin" } + ], + "issued": {"year": "1990"}, + "title": "Book I" +}, +{ + "id":"ambigs-6", + "type": "book", + "author": [ + { "name":"Asthma, Alan" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Crispin" }, + { "name":"Dropsy, David" }, + { "name":"Ebola, Elvin" }, + { "name":"Fever, Fergus" } + ], + "issued": {"year": "1990"}, + "title": "Book H" +}, +{ + "id":"ambigs-7", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Janet" } + ], + "issued": {"year": "1990"}, + "title": "Book G" +}, +{ + "id":"ambigs-8", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Jane" } + ], + "issued": {"year": "1990"}, + "title": "Book F" +}, +{ + "id":"ambigs-9", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Jane" } + ], + "issued": {"year": "1990"}, + "title": "Book E" +}, +{ + "id":"ambigs-10", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Janet" } + ], + "issued": {"year": "1990"}, + "title": "Book D" +}, +{ + "id":"ambigs-11", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Jane" }, + { "name":"Jones, Robert" } + ], + "issued": {"year": "1990"}, + "title": "Book C" +}, +{ + "id":"ambigs-12", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Josephine" }, + { "name":"Jones, Robert" } + ], + "issued": {"year": "1990"}, + "title": "Book B" +}, +{ + "id":"ambigs-13", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Jane" }, + { "name":"Jones, Richard" } + ], + "issued": {"year": "1990"}, + "title": "Book A" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_ArticularPlain.txt b/std/humans/name_ArticularPlain.txt new file mode 100644 index 000000000..4fbbdb2f4 --- /dev/null +++ b/std/humans/name_ArticularPlain.txt @@ -0,0 +1,38 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +James Doe III +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"item-1", + "type": "book", + "author": [ + { "name":"Doe, James, III" } + ], + "issued": "2001", + "title": "My Anonymous Heritage" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_ArticularWithComma.txt b/std/humans/name_ArticularWithComma.txt new file mode 100644 index 000000000..98ba46651 --- /dev/null +++ b/std/humans/name_ArticularWithComma.txt @@ -0,0 +1,38 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Jeffrey Doe, Jr. +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id": "item-1", + "type": "book", + "author": [ + { "name":"Doe, Jeffrey,! Jr." } + ], + "issued": "2001", + "title": "My Life as an Anonymous Heir" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_Asian.txt b/std/humans/name_Asian.txt new file mode 100644 index 000000000..7e80de919 --- /dev/null +++ b/std/humans/name_Asian.txt @@ -0,0 +1,38 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Miyamoto Musashi +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"simple-sticky-name-1", + "type": "book", + "author": [ + { "name":"Miyamoto, Musashi !" } + ], + "issued": {"year": "1645", "month":"12", "day":"27"}, + "title": "A Book of Five Rings" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_AsianGlyphs.txt b/std/humans/name_AsianGlyphs.txt new file mode 100644 index 000000000..dbdb6718c --- /dev/null +++ b/std/humans/name_AsianGlyphs.txt @@ -0,0 +1,38 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +我妻栄 +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id": "item-1", + "type": "book", + "author": [ + { "name":"我妻, 栄" } + ], + "issued": "1960", + "title": "民法" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_AuthorCount.txt b/std/humans/name_AuthorCount.txt new file mode 100644 index 000000000..ee907fa2d --- /dev/null +++ b/std/humans/name_AuthorCount.txt @@ -0,0 +1,76 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.9 experimental +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +33210 +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[ + { + "id":"item-1", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Roe, Jane" }, + { "name":"Brown, Robert" }, + { "name":"Smith, Tom" } + ] + }, + { + "id":"item-2", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Doe, Jake" }, + { "name":"Brown, Robert" } + ] + }, + { + "id":"item-3", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Doe, Jake" } + ] + }, + { + "id":"item-4", + "type": "book", + "author": [ + { "name":"Doe, John" } + ] + }, + { + "id":"item-5", + "type": "book", + "editor": [ + { "name":"Doe, John" } + ] + } +] +<<===== INPUT =====<< diff --git a/std/humans/name_CollapseRoleLabels.txt b/std/humans/name_CollapseRoleLabels.txt new file mode 100644 index 000000000..1e5115e77 --- /dev/null +++ b/std/humans/name_CollapseRoleLabels.txt @@ -0,0 +1,56 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Albert Asthma, et al. (eds. & trans.) +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"editor-translator-1", + "type": "book", + "editor": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Crispin" } + ], + "translator": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Crispin" } + ], + "issued": {"year": "1990"}, + "title": "Book One" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_Delimiter.txt b/std/humans/name_Delimiter.txt new file mode 100644 index 000000000..c91dc111f --- /dev/null +++ b/std/humans/name_Delimiter.txt @@ -0,0 +1,40 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +John Doe; Jane Roe +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"item-1", + "type": "book", + "author": [ + { "name":"Doe, John", "uri":"http://people.org/doej" }, + { "name":"Roe, Jane", "uri":"http://people.org/roej" } + ], + "issued": "2000", + "title": "Our Anonymous Lives" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_Institution.txt b/std/humans/name_Institution.txt new file mode 100644 index 000000000..f00b7d761 --- /dev/null +++ b/std/humans/name_Institution.txt @@ -0,0 +1,38 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Ministry of Education, Sports, Culture, Science and Technology +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"institution-name-1", + "type": "book", + "author": [ + { "name":"Ministry of Education, Sports, Culture, Science and Technology !!" } + ], + "issued": "2006", + "title": "White Paper on Education, Sports, Culture, Science and Technology" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_LabelAfterPlural.txt b/std/humans/name_LabelAfterPlural.txt new file mode 100644 index 000000000..fb43e15d6 --- /dev/null +++ b/std/humans/name_LabelAfterPlural.txt @@ -0,0 +1,40 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +John DoeJane Roeeditors +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"item-1", + "type": "book", + "editor": [ + { "name":"Doe, John", "uri":"http://people.org/doej" }, + { "name":"Roe, Jane", "uri":"http://people.org/doej" } + ], + "issued": "2000", + "title": "His Anonymous Life" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_LabelAfterPluralDecorations.txt b/std/humans/name_LabelAfterPluralDecorations.txt new file mode 100644 index 000000000..e539dce7c --- /dev/null +++ b/std/humans/name_LabelAfterPluralDecorations.txt @@ -0,0 +1,42 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +John Doe, et al. (editors) +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"item-1", + "type": "book", + "editor": [ + { "name":"Doe, John", "uri":"http://people.org/doej" }, + { "name":"Roe, Jane", "uri":"http://people.org/doej" } + ], + "issued": "2000", + "title": "His Anonymous Life" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_LongAbbreviation.txt b/std/humans/name_LongAbbreviation.txt new file mode 100644 index 000000000..807d55f3b --- /dev/null +++ b/std/humans/name_LongAbbreviation.txt @@ -0,0 +1,38 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Ts. Tserendorj +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"simple-mongolian-name-1", + "type": "book", + "author": [ + { "name":"Tserendorj, TSerendorjiin" } + ], + "issued": {"year": "1925", "month":"3", "day":"4"}, + "title": "An Altogether Unknown History of Soviet-Mongolian Relations" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_MixedFormatsInitialSortOrderAllWithDecorationsEtAl.txt b/std/humans/name_MixedFormatsInitialSortOrderAllWithDecorationsEtAl.txt new file mode 100644 index 000000000..ca226cf24 --- /dev/null +++ b/std/humans/name_MixedFormatsInitialSortOrderAllWithDecorationsEtAl.txt @@ -0,0 +1,47 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +ЧАЙКОВСКИЙ, П.И., van WINKLE, R., 我妻栄, THUCYDIDES, C., III, TOKUGAWA Ieyasu, et al. +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"item-1", + "type": "book", + "author": [ + { "name":"Чайковский, Пётр Ильич" }, + { "name":"van Winkle, Rip" }, + { "name":"我妻, 栄" }, + { "name":"Thucydides, Carl, III" }, + { "name":"Tokugawa, Ieyasu !" }, + { "name":"Ministry of Fear, Loathing and Error !!" }, + { "name":"Prince" } + ], + "issued": "2000", + "title": "Our Story" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_MixedFormatsInitialSortOrderFirstWithDecorationsEtAl.txt b/std/humans/name_MixedFormatsInitialSortOrderFirstWithDecorationsEtAl.txt new file mode 100644 index 000000000..459c953b1 --- /dev/null +++ b/std/humans/name_MixedFormatsInitialSortOrderFirstWithDecorationsEtAl.txt @@ -0,0 +1,47 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +ЧАЙКОВСКИЙ, П.И., R. van WINKLE, 我妻栄, C. THUCYDIDES III, TOKUGAWA Ieyasu, et al. +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"item-1", + "type": "book", + "author": [ + { "name":"Чайковский, Пётр Ильич" }, + { "name":"van Winkle, Rip" }, + { "name":"我妻, 栄" }, + { "name":"Thucydides, Carl, III" }, + { "name":"Tokugawa, Ieyasu !" }, + { "name":"Ministry of Fear, Loathing and Error !!" }, + { "name":"Prince" } + ], + "issued": "2000", + "title": "Our Story" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_MixedFormatsInitialsWithDecorationsEtAl.txt b/std/humans/name_MixedFormatsInitialsWithDecorationsEtAl.txt new file mode 100644 index 000000000..5668e37cc --- /dev/null +++ b/std/humans/name_MixedFormatsInitialsWithDecorationsEtAl.txt @@ -0,0 +1,47 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +П.И. ЧАЙКОВСКИЙ, R. van WINKLE, 我妻栄, C. THUCYDIDES III, TOKUGAWA Ieyasu, et al. +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"item-1", + "type": "book", + "author": [ + { "name":"Чайковский, Пётр Ильич" }, + { "name":"van Winkle, Rip" }, + { "name":"我妻, 栄" }, + { "name":"Thucydides, Carl, III" }, + { "name":"Tokugawa, Ieyasu !" }, + { "name":"Ministry of Fear, Loathing and Error !!" }, + { "name":"Prince" } + ], + "issued": "2000", + "title": "Our Story" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_MixedFormatsPrimaryDecorations.txt b/std/humans/name_MixedFormatsPrimaryDecorations.txt new file mode 100644 index 000000000..b0467ef94 --- /dev/null +++ b/std/humans/name_MixedFormatsPrimaryDecorations.txt @@ -0,0 +1,45 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Пётр Ильич ЧАЙКОВСКИЙ, Rip van WINKLE, 我妻栄, Carl THUCYDIDES III, TOKUGAWA Ieyasu, Ministry of Fear, Loathing and Error, PRINCE +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"item-1", + "type": "book", + "author": [ + { "name":"Чайковский, Пётр Ильич" }, + { "name":"van Winkle, Rip" }, + { "name":"我妻, 栄" }, + { "name":"Thucydides, Carl, III" }, + { "name":"Tokugawa, Ieyasu !" }, + { "name":"Ministry of Fear, Loathing and Error !!" }, + { "name":"Prince" } + ], + "issued": "2000", + "title": "Our Story" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_MixedFormatsWithDecorationsEtAl.txt b/std/humans/name_MixedFormatsWithDecorationsEtAl.txt new file mode 100644 index 000000000..fbff2ec19 --- /dev/null +++ b/std/humans/name_MixedFormatsWithDecorationsEtAl.txt @@ -0,0 +1,47 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Пётр Ильич ЧАЙКОВСКИЙ, Rip van WINKLE, 我妻栄, Carl THUCYDIDES III, TOKUGAWA Ieyasu, et al. +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"item-1", + "type": "book", + "author": [ + { "name":"Чайковский, Пётр Ильич" }, + { "name":"van Winkle, Rip" }, + { "name":"我妻, 栄" }, + { "name":"Thucydides, Carl, III" }, + { "name":"Tokugawa, Ieyasu !" }, + { "name":"Ministry of Fear, Loathing and Error !!" }, + { "name":"Prince" } + ], + "issued": "2000", + "title": "Our Story" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_MixedFormatsWithDecorationsPlusAlternateEtAlDecorations.txt b/std/humans/name_MixedFormatsWithDecorationsPlusAlternateEtAlDecorations.txt new file mode 100644 index 000000000..cd9a3d3c2 --- /dev/null +++ b/std/humans/name_MixedFormatsWithDecorationsPlusAlternateEtAlDecorations.txt @@ -0,0 +1,48 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Пётр Ильич ЧАЙКОВСКИЙ, Rip van WINKLE, 我妻栄, Carl THUCYDIDES III, TOKUGAWA Ieyasu and others +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"item-1", + "type": "book", + "author": [ + { "name":"Чайковский, Пётр Ильич" }, + { "name":"van Winkle, Rip" }, + { "name":"我妻, 栄" }, + { "name":"Thucydides, Carl, III" }, + { "name":"Tokugawa, Ieyasu !" }, + { "name":"Ministry of Fear, Loathing and Error !!" }, + { "name":"Prince" } + ], + "issued": "2000", + "title": "Our Story" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_MixedFormatsWithDecorationsPlusEtAlDecorations.txt b/std/humans/name_MixedFormatsWithDecorationsPlusEtAlDecorations.txt new file mode 100644 index 000000000..b60d35890 --- /dev/null +++ b/std/humans/name_MixedFormatsWithDecorationsPlusEtAlDecorations.txt @@ -0,0 +1,48 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Пётр Ильич ЧАЙКОВСКИЙ, Rip van WINKLE, 我妻栄, Carl THUCYDIDES III, TOKUGAWA Ieyasuet al. +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"item-1", + "type": "book", + "author": [ + { "name":"Чайковский, Пётр Ильич" }, + { "name":"van Winkle, Rip" }, + { "name":"我妻, 栄" }, + { "name":"Thucydides, Carl, III" }, + { "name":"Tokugawa, Ieyasu !" }, + { "name":"Ministry of Fear, Loathing and Error !!" }, + { "name":"Prince" } + ], + "issued": "2000", + "title": "Our Story" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_SubsituteName.txt b/std/humans/name_SubsituteName.txt new file mode 100644 index 000000000..dd3237e75 --- /dev/null +++ b/std/humans/name_SubsituteName.txt @@ -0,0 +1,41 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +John Doe +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"item-1", + "type": "book", + "editor": [ + { "name":"Doe, John", "uri":"http://people.org/doej" } + ], + "issued": "2000", + "title": "His Anonymous Life" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_SubstituteInheritLabel.txt b/std/humans/name_SubstituteInheritLabel.txt new file mode 100644 index 000000000..48fca196f --- /dev/null +++ b/std/humans/name_SubstituteInheritLabel.txt @@ -0,0 +1,51 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +[[X]Jane Roe (ed.); [X]John Doe] +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"item-1", + "type": "book", + "editor": [ + { "name":"Roe, Jane" } + ], + "issued": "2000", + "title": "Her Anonymous Anthology" +}, +{ + "id":"simple-western-name-1", + "type": "book", + "author": [ + { "name":"Doe, John", "uri":"http://people.org/doej" } + ], + "issued": {"year": "1965", "month":"6", "day":"1"}, + "title": "His Anonymous Life" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_SubstituteMacroInheritDecorations.txt b/std/humans/name_SubstituteMacroInheritDecorations.txt new file mode 100644 index 000000000..043c3ce6b --- /dev/null +++ b/std/humans/name_SubstituteMacroInheritDecorations.txt @@ -0,0 +1,45 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +[I AM A BLOB] +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"simple-western-name-1", + "type": "book", + "author": [ + { "name":"Doe, John", "uri":"http://people.org/doej" } + ], + "issued": {"year": "1965", "month":"6", "day":"1"}, + "title": "His Anonymous Life" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_TwoRolesSameRenderingSeparateRoleLabels.txt b/std/humans/name_TwoRolesSameRenderingSeparateRoleLabels.txt new file mode 100644 index 000000000..d802f9fe9 --- /dev/null +++ b/std/humans/name_TwoRolesSameRenderingSeparateRoleLabels.txt @@ -0,0 +1,56 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Albert Asthma, et al. (eds.), Albert Asthma, et al. (trans.) +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"editor-translator-2", + "type": "book", + "editor": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Crispin" } + ], + "translator": [ + { "name":"Asthma, Albert" }, + { "name":"Bronchitis, Bosworth" }, + { "name":"Cold, Constantine" } + ], + "issued": {"year": "1990"}, + "title": "Book One" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_WesternArticularLowercase.txt b/std/humans/name_WesternArticularLowercase.txt new file mode 100644 index 000000000..67b082ca7 --- /dev/null +++ b/std/humans/name_WesternArticularLowercase.txt @@ -0,0 +1,38 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Jacques van Doe +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"item-1", + "type": "book", + "author": [ + { "name":"van Doe, Jacques" } + ], + "issued": "1645", + "title": "A Book of Five Rings" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_WesternPrimaryFontStyle.txt b/std/humans/name_WesternPrimaryFontStyle.txt new file mode 100644 index 000000000..4b2d48a38 --- /dev/null +++ b/std/humans/name_WesternPrimaryFontStyle.txt @@ -0,0 +1,39 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +John Doe +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"simple-western-name-1", + "type": "book", + "author": [ + { "name":"Doe, John", "uri":"http://people.org/doej" } + ], + "issued": {"year": "1965", "month":"6", "day":"1"}, + "title": "His Anonymous Life" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_WesternPrimaryFontStyleTwoAuthors.txt b/std/humans/name_WesternPrimaryFontStyleTwoAuthors.txt new file mode 100644 index 000000000..08cb73d4a --- /dev/null +++ b/std/humans/name_WesternPrimaryFontStyleTwoAuthors.txt @@ -0,0 +1,40 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +John Doe; Jane Roe +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"item-1", + "type": "book", + "author": [ + { "name":"Doe, John", "uri":"http://people.org/doej" }, + { "name":"Roe, Jane", "uri":"http://people.org/roej" } + ], + "issued": "2000", + "title": "Our Anonymous Lives" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_WesternSimple.txt b/std/humans/name_WesternSimple.txt new file mode 100644 index 000000000..c4cac3b1f --- /dev/null +++ b/std/humans/name_WesternSimple.txt @@ -0,0 +1,38 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +John Doe +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"simple-western-name-1", + "type": "book", + "author": [ + { "name":"Doe, John", "uri":"http://people.org/doej" } + ], + "issued": {"year": "1965", "month":"6", "day":"1"}, + "title": "His Anonymous Life" +}] +<<===== INPUT =====<< diff --git a/std/humans/name_WesternTwoAuthors.txt b/std/humans/name_WesternTwoAuthors.txt new file mode 100644 index 000000000..4f35a4636 --- /dev/null +++ b/std/humans/name_WesternTwoAuthors.txt @@ -0,0 +1,39 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +John DoeJane Roe +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"item-1", + "type": "book", + "author": [ + { "name":"Doe, John", "uri":"http://people.org/doej" }, + { "name":"Roe, Jane", "uri":"http://people.org/roej" } + ], + "issued": "2000", + "title": "Our Anonymous Lives" +}] +<<===== INPUT =====<< diff --git a/std/humans/sort_AguStyle.txt b/std/humans/sort_AguStyle.txt new file mode 100644 index 000000000..bd7c5d28d --- /dev/null +++ b/std/humans/sort_AguStyle.txt @@ -0,0 +1,175 @@ +>>===== MODE =====>> +bibliography +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.9 experimental +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Smith, A. (1989a) +Smith, A. (1989b) +Smith, A. (1991) +Smith, A., and C. Allen (1992) +Smith, A., and B. Frank (1995) +Smith, A., and B. Frank (1997) +Smith, A., L. Roberts, and T. Jones (1993) +Smith, A., T. Jones, and L. Roberts (1997) +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[ + { + "id":"item-1", + "type": "book", + "author": [ + { "name":"Smith, Al" }, + ], + "issued": {"year": "1989"}, + "title": "Book One" + }, + { + "id":"item-3", + "type": "book", + "editor": [ + { "name":"Smith, Al" } + ], + "issued": {"year": "1991"}, + "title": "Book Three" + }, + { + "id":"item-4", + "type": "book", + "editor": [ + { "name":"Smith, Al" }, + { "name":"Allen, Carl" } + ], + "issued": {"year": "1992"}, + "title": "Book Four" + }, + { + "id":"item-6", + "type": "book", + "editor": [ + { "name":"Smith, Al" }, + { "name":"Frank, Beauregarde" } + ], + "issued": {"year": "1997"}, + "title": "Book Six" + }, + { + "id":"item-2", + "type": "book", + "author": [ + { "name":"Smith, Al" } + ], + "issued": {"year": "1989"}, + "title": "Book Two" + }, + { + "id":"item-5", + "type": "book", + "editor": [ + { "name":"Smith, Al" }, + { "name":"Frank, Beauregarde" } + ], + "issued": {"year": "1995"}, + "title": "Book Five" + }, + { + "id":"item-7", + "type": "book", + "editor": [ + { "name":"Smith, Al" }, + { "name":"Roberts, Lionel" }, + { "name":"Jones, Theresa" } + ], + "issued": {"year": "1993"}, + "title": "Book Seven" + }, + { + "id":"item-8", + "type": "book", + "editor": [ + { "name":"Smith, Al" }, + { "name":"Jones, Theresa" }, + { "name":"Roberts, Lionel" } + ], + "issued": {"year": "1997"}, + "title": "Book Eight" + } +] +<<===== INPUT =====<< diff --git a/std/humans/sort_AguStyleReverseGroups.txt b/std/humans/sort_AguStyleReverseGroups.txt new file mode 100644 index 000000000..c5d4ad2a4 --- /dev/null +++ b/std/humans/sort_AguStyleReverseGroups.txt @@ -0,0 +1,175 @@ +>>===== MODE =====>> +bibliography +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.9 experimental +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Smith, A., L. Roberts, and T. Jones (1993) +Smith, A., T. Jones, and L. Roberts (1997) +Smith, A., and C. Allen (2000) +Smith, A., and B. Frank (1995) +Smith, A., and B. Frank (1997) +Smith, A. (1989a) +Smith, A. (1989b) +Smith, A. (1991) +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[ + { + "id":"item-1", + "type": "book", + "author": [ + { "name":"Smith, Al" }, + ], + "issued": {"year": "1989"}, + "title": "Book One" + }, + { + "id":"item-2", + "type": "book", + "author": [ + { "name":"Smith, Al" } + ], + "issued": {"year": "1989"}, + "title": "Book Two" + }, + { + "id":"item-3", + "type": "book", + "editor": [ + { "name":"Smith, Al" } + ], + "issued": {"year": "1991"}, + "title": "Book Three" + }, + { + "id":"item-4", + "type": "book", + "editor": [ + { "name":"Smith, Al" }, + { "name":"Allen, Carl" } + ], + "issued": {"year": "2000"}, + "title": "Book Four" + }, + { + "id":"item-5", + "type": "book", + "editor": [ + { "name":"Smith, Al" }, + { "name":"Frank, Beauregarde" } + ], + "issued": {"year": "1995"}, + "title": "Book Five" + }, + { + "id":"item-6", + "type": "book", + "editor": [ + { "name":"Smith, Al" }, + { "name":"Frank, Beauregarde" } + ], + "issued": {"year": "1997"}, + "title": "Book Six" + }, + { + "id":"item-7", + "type": "book", + "editor": [ + { "name":"Smith, Al" }, + { "name":"Roberts, Lionel" }, + { "name":"Jones, Theresa" } + ], + "issued": {"year": "1993"}, + "title": "Book Seven" + }, + { + "id":"item-8", + "type": "book", + "editor": [ + { "name":"Smith, Al" }, + { "name":"Jones, Theresa" }, + { "name":"Roberts, Lionel" } + ], + "issued": {"year": "1997"}, + "title": "Book Eight" + } +] +<<===== INPUT =====<< diff --git a/std/humans/sort_Citation.txt b/std/humans/sort_Citation.txt new file mode 100644 index 000000000..4cea5c1f6 --- /dev/null +++ b/std/humans/sort_Citation.txt @@ -0,0 +1,56 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.8 +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Doe; Roe +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[ + { + "id":"ITEM-1", + "type": "book", + "author": [ + { "name":"Roe, Jane" } + ] + }, + { + "id":"ITEM-2", + "type": "book", + "author": [ + { "name":"Doe, John" } + ] + } +] diff --git a/std/humans/sort_NumberOfAuthorsAsKey.txt b/std/humans/sort_NumberOfAuthorsAsKey.txt new file mode 100644 index 000000000..016d37e57 --- /dev/null +++ b/std/humans/sort_NumberOfAuthorsAsKey.txt @@ -0,0 +1,96 @@ +>>===== MODE =====>> +bibliography +<<===== MODE =====<< + +>>===== SCHEMA =====>> +0.9 experimental +<<===== SCHEMA =====<< + + +>>===== RESULT =====>> +Book One +Book Two +Book Three +<<===== RESULT =====<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[ + { + "id":"item-1", + "type": "book", + "author": [ + { "name":"Doe, John" }, + ], + "issued": {"year": "2000"}, + "title": "Book One" + }, + { + "id":"item-2", + "type": "book", + "author": [ + { "name":"Doe, John" }, + { "name":"Doe, Jake" }, + { "name":"Jones, Robert" } + ], + "issued": {"year": "2000"}, + "title": "Book Three" + }, + { + "id":"item-3", + "type": "book", + "editor": [ + { "name":"Doe, John" }, + { "name":"Roe, Jane" }, + ], + "issued": {"year": "2000"}, + "title": "Book Two" + } +] +<<===== INPUT =====<< diff --git a/std/humans/term_MagicCapitalization.txt b/std/humans/term_MagicCapitalization.txt new file mode 100644 index 000000000..29b059bc3 --- /dev/null +++ b/std/humans/term_MagicCapitalization.txt @@ -0,0 +1,32 @@ +>>== MODE ==>> +citation +<<== MODE ==<< + +>>== SCHEMA ==>> +0.8 +<<== SCHEMA ==<< + + +>>== RESULT ==>> +And +<<== RESULT ==<< + + +>>===== CSL =====>> + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[{ + "id":"item-1", + "type": "book", + "title": "Ignore me" +}] +<<===== INPUT =====<< diff --git a/style/ama.csl b/style/ama.csl new file mode 100644 index 000000000..8346c2257 --- /dev/null +++ b/style/ama.csl @@ -0,0 +1,184 @@ + + diff --git a/style/apa.csl b/style/apa.csl new file mode 100644 index 000000000..7f8e65f53 --- /dev/null +++ b/style/apa.csl @@ -0,0 +1,254 @@ + + + diff --git a/style/apsa.csl b/style/apsa.csl new file mode 100644 index 000000000..a8ff417de --- /dev/null +++ b/style/apsa.csl @@ -0,0 +1,175 @@ + + diff --git a/style/asa.csl b/style/asa.csl new file mode 100644 index 000000000..b66076a0e --- /dev/null +++ b/style/asa.csl @@ -0,0 +1,215 @@ + + diff --git a/style/bluebook_lawrev.csl b/style/bluebook_lawrev.csl new file mode 100644 index 000000000..604dd86ac --- /dev/null +++ b/style/bluebook_lawrev.csl @@ -0,0 +1,1150 @@ + + + diff --git a/style/chicago-author-date.csl b/style/chicago-author-date.csl new file mode 100644 index 000000000..53a4fbe5a --- /dev/null +++ b/style/chicago-author-date.csl @@ -0,0 +1,369 @@ + + diff --git a/style/chicago-fullnote-bibliography.csl b/style/chicago-fullnote-bibliography.csl new file mode 100644 index 000000000..2eedf105b --- /dev/null +++ b/style/chicago-fullnote-bibliography.csl @@ -0,0 +1,666 @@ + diff --git a/style/chicago-note-bibliography.csl b/style/chicago-note-bibliography.csl new file mode 100644 index 000000000..fc7a160dd --- /dev/null +++ b/style/chicago-note-bibliography.csl @@ -0,0 +1,446 @@ + + + diff --git a/style/chicago-note.csl b/style/chicago-note.csl new file mode 100644 index 000000000..fba372fcb --- /dev/null +++ b/style/chicago-note.csl @@ -0,0 +1,387 @@ + + + diff --git a/style/harvard1.csl b/style/harvard1.csl new file mode 100644 index 000000000..7edbfb1bc --- /dev/null +++ b/style/harvard1.csl @@ -0,0 +1,192 @@ + + diff --git a/style/ieee.csl b/style/ieee.csl new file mode 100644 index 000000000..8a366cf53 --- /dev/null +++ b/style/ieee.csl @@ -0,0 +1,135 @@ + + + diff --git a/style/mhra.csl b/style/mhra.csl new file mode 100644 index 000000000..07351789c --- /dev/null +++ b/style/mhra.csl @@ -0,0 +1,317 @@ + diff --git a/style/mhra_note_without_bibliography.csl b/style/mhra_note_without_bibliography.csl new file mode 100644 index 000000000..6a47079fb --- /dev/null +++ b/style/mhra_note_without_bibliography.csl @@ -0,0 +1,337 @@ + + + \ No newline at end of file diff --git a/style/mla.csl b/style/mla.csl new file mode 100644 index 000000000..1def5ba8d --- /dev/null +++ b/style/mla.csl @@ -0,0 +1,188 @@ + + diff --git a/style/nature.csl b/style/nature.csl new file mode 100644 index 000000000..3f8316dbb --- /dev/null +++ b/style/nature.csl @@ -0,0 +1,87 @@ + + + diff --git a/style/nlm.csl b/style/nlm.csl new file mode 100644 index 000000000..4c6d4d884 --- /dev/null +++ b/style/nlm.csl @@ -0,0 +1,116 @@ + + + diff --git a/style/schemas.xml b/style/schemas.xml new file mode 100644 index 000000000..1046b8b5f --- /dev/null +++ b/style/schemas.xml @@ -0,0 +1,4 @@ + + + + diff --git a/tests/run.js b/tests/run.js new file mode 100644 index 000000000..4d4478d66 --- /dev/null +++ b/tests/run.js @@ -0,0 +1,65 @@ +//This file is the command-line entry point for running the tests in +//Rhino + +/*===== +dojo.tests = { + // summary: D.O.H. Test files for Dojo unit testing. +}; +=====*/ + +load("./dojo/dojo/dojo.js"); +dojo.registerModulePath("dojo","./dojo/dojo"); +dojo.registerModulePath("dojox","./dojo/dojox"); +dojo.registerModulePath("tests","./tests"); +//dojo.registerModulePath("tests","/home/bennett/src/citeproc-js-fbennett/tests"); +dojo.registerModulePath("csl","./src"); +dojo.registerModulePath("csl.output","./src/output"); +dojo.registerModulePath("doh","./dojo/util/doh"); + +dojo.require("doh.runner"); +dojo.require("csl.csl"); + +// +// requested tests go here +if(true){ + dojo.require("tests.std_collapse"); + dojo.require("tests.test_registry"); + dojo.require("tests.test_term"); + dojo.require("tests.test_build"); + dojo.require("tests.test_configure"); + dojo.require("tests.std_condition"); + dojo.require("tests.std_name"); + + dojo.require("tests.test_dates"); + dojo.require("tests.test_render"); + dojo.require("tests.test_names_import"); + dojo.require("tests.test_formatters"); + dojo.require("tests.test_build_internals"); + dojo.require("tests.test_output"); + dojo.require("tests.test_range"); + dojo.require("tests.test_build_integration"); + dojo.require("tests.test_csl"); + dojo.require("tests.test_sequence"); + dojo.require("tests.test_factory"); + dojo.require("tests.test_xmljs"); + dojo.require("tests.test_conditions"); + dojo.require("tests.test_locale"); + dojo.require("tests.test_retrieval"); + dojo.require("tests.test_xmle4x"); + dojo.require("tests.test_list"); + dojo.require("tests.test_groups"); + dojo.require("tests.test_failing"); + dojo.require("tests.test_load_styles"); + dojo.require("tests.std_term"); + dojo.require("tests.test_commands"); + dojo.require("tests.std_disambiguate"); + dojo.require("tests.std_date"); + dojo.require("tests.test_util_names"); + dojo.require("tests.std_sort"); + dojo.require("tests.test_sort"); +} else { + + print("Nothing here"); +} + +tests.run(); diff --git a/tests/std_collapse.js b/tests/std_collapse.js new file mode 100644 index 000000000..6bd369cd1 --- /dev/null +++ b/tests/std_collapse.js @@ -0,0 +1,14 @@ +dojo.provide("tests.std_collapse"); + +dojo.require("csl.csl"); + +doh.register("tests.std_collapse", [ + function(){ + var test = CSL.System.Tests.getTest("collapse_CitationNumberRangesWithAffixes"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("collapse_YearSuffixCollapse"); + doh.assertEqual(test.result, test.run()); + }, +]); diff --git a/tests/std_condition.js b/tests/std_condition.js new file mode 100644 index 000000000..42a22b42d --- /dev/null +++ b/tests/std_condition.js @@ -0,0 +1,10 @@ +dojo.provide("tests.std_condition"); + +dojo.require("csl.csl"); + +doh.register("tests.std_condition", [ + function(){ + var test = CSL.System.Tests.getTest("condition_RefTypeBranching"); + doh.assertEqual(test.result, test.run()); + }, +]); diff --git a/tests/std_date.js b/tests/std_date.js new file mode 100644 index 000000000..e835c8e55 --- /dev/null +++ b/tests/std_date.js @@ -0,0 +1,10 @@ +dojo.provide("tests.std_date"); + +dojo.require("csl.csl"); + +doh.register("tests.std_date", [ + function(){ + var test = CSL.System.Tests.getTest("date_YearSuffixDelimiter"); + doh.assertEqual(test.result, test.run()); + }, +]); diff --git a/tests/std_disambiguate.js b/tests/std_disambiguate.js new file mode 100644 index 000000000..a4926806f --- /dev/null +++ b/tests/std_disambiguate.js @@ -0,0 +1,34 @@ +dojo.provide("tests.std_disambiguate"); + +dojo.require("csl.csl"); + +doh.register("tests.std_disambiguate", [ + function(){ + var test = CSL.System.Tests.getTest("disambiguate_BasedOnEtAlSubsequent"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("disambiguate_BaseNameCountOnFailureIfYearSuffixAvailable"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("disambiguate_DisambiguateCondition"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("disambiguate_GivennameExpandCrossNestedNames"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("disambiguate_MinimalGivennameExpandMinimalNames"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("disambiguate_RetainNamesOnFailureIfYearSuffixNotAvailable"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("disambiguate_YearSuffixAndSort"); + doh.assertEqual(test.result, test.run()); + }, +]); diff --git a/tests/std_name.js b/tests/std_name.js new file mode 100644 index 000000000..3056ae011 --- /dev/null +++ b/tests/std_name.js @@ -0,0 +1,114 @@ +dojo.provide("tests.std_name"); + +dojo.require("csl.csl"); + +doh.register("tests.std_name", [ + function(){ + var test = CSL.System.Tests.getTest("name_ArticularPlain"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_ArticularWithComma"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_AsianGlyphs"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_Asian"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_AuthorCount"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_CollapseRoleLabels"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_Delimiter"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_Institution"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_LabelAfterPluralDecorations"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_LabelAfterPlural"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_LongAbbreviation"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_MixedFormatsInitialSortOrderAllWithDecorationsEtAl"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_MixedFormatsInitialSortOrderFirstWithDecorationsEtAl"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_MixedFormatsInitialsWithDecorationsEtAl"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_MixedFormatsPrimaryDecorations"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_MixedFormatsWithDecorationsEtAl"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_MixedFormatsWithDecorationsPlusAlternateEtAlDecorations"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_MixedFormatsWithDecorationsPlusEtAlDecorations"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_SubsituteName"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_SubstituteInheritLabel"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_SubstituteMacroInheritDecorations"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_TwoRolesSameRenderingSeparateRoleLabels"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_WesternArticularLowercase"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_WesternPrimaryFontStyle"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_WesternPrimaryFontStyleTwoAuthors"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_WesternSimple"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("name_WesternTwoAuthors"); + doh.assertEqual(test.result, test.run()); + }, +]); diff --git a/tests/std_sort.js b/tests/std_sort.js new file mode 100644 index 000000000..28fbd140f --- /dev/null +++ b/tests/std_sort.js @@ -0,0 +1,22 @@ +dojo.provide("tests.std_sort"); + +dojo.require("csl.csl"); + +doh.register("tests.std_sort", [ + function(){ + var test = CSL.System.Tests.getTest("sort_AguStyle"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("sort_AguStyleReverseGroups"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("sort_Citation"); + doh.assertEqual(test.result, test.run()); + }, + function(){ + var test = CSL.System.Tests.getTest("sort_NumberOfAuthorsAsKey"); + doh.assertEqual(test.result, test.run()); + }, +]); diff --git a/tests/std_term.js b/tests/std_term.js new file mode 100644 index 000000000..8b94a898d --- /dev/null +++ b/tests/std_term.js @@ -0,0 +1,10 @@ +dojo.provide("tests.std_term"); + +dojo.require("csl.csl"); + +doh.register("tests.std_term", [ + function(){ + var test = CSL.System.Tests.getTest("term_MagicCapitalization"); + doh.assertEqual(test.result, test.run()); + }, +]); diff --git a/tests/test_build.js b/tests/test_build.js new file mode 100644 index 000000000..333fc9785 --- /dev/null +++ b/tests/test_build.js @@ -0,0 +1,134 @@ +dojo.provide("tests.test_build"); + + +var nestedsingleton = ""; +var complex = ""; + +var Item = { + "title":"My Aunt Sally" +}; + +doh.register("tests.build", [ + + function testBuild(){ + var builder = new CSL.Core.Build(nestedsingleton); + function testme(){ + try { + builder.build(); + return "Success"; + } catch(e) { + return e; + } + } + var res = testme(); + doh.assertEqual("Success", res); + }, + function testExistence() { + function testme () { + try { + var obj = CSL.Core.Build; + return "Success"; + } catch (e) { + return e; + } + } + var res = testme(); + doh.assertEqual( "Success", res ); + }, + + function testInstantiation() { + function testme () { + try { + var obj = new CSL.Core.Build(nestedsingleton); + return "Success"; + } catch (e) { + return e; + } + } + var res = testme(); + doh.assertEqual( "Success", res ); + }, + + function testXmlParseOkJS(){ + var obj = new CSL.Core.Build(nestedsingleton,"JunkyardJavascript"); + var cmd = CSL.System.Xml.JunkyardJavascript.commandInterface; + function testme (){ + try { + var name = cmd.nodename.call(cmd.children.call(obj.showXml())[0][0]); + return name; + } catch (e) { + return e; + } + } + var res = testme(); + doh.assertEqual("text", res); + }, + + function testOptGetsCreated (){ + var builder = new CSL.Core.Build(nestedsingleton); + var obj = builder.build(); + doh.assertTrue( obj.opt ); + }, + function testCitationGetsCreated (){ + var builder = new CSL.Core.Build(nestedsingleton); + var obj = builder.build(); + doh.assertTrue( obj.citation ); + }, + function testBibliographyGetsCreated (){ + var builder = new CSL.Core.Build(nestedsingleton); + var obj = builder.build(); + doh.assertTrue( obj.bibliography ); + }, + function testCitationOptGetsCreated (){ + var builder = new CSL.Core.Build(nestedsingleton); + var obj = builder.build(); + doh.assertTrue( obj.citation.opt ); + }, + function testCitationTokensGetsCreated (){ + var builder = new CSL.Core.Build(nestedsingleton); + var obj = builder.build(); + doh.assertTrue( obj.citation.tokens ); + }, + function testBibliographyOptGetsCreated (){ + var builder = new CSL.Core.Build(nestedsingleton); + var obj = builder.build(); + doh.assertTrue( obj.bibliography.opt ); + }, + function testBibliographyTokensGetsCreated (){ + var builder = new CSL.Core.Build(nestedsingleton); + var obj = builder.build(); + doh.assertTrue( obj.bibliography.tokens ); + }, + + + function testSetXmlInstantiation (){ + var obj = new CSL.Core.Build(nestedsingleton); + function proc(){} + function testme (){ + try { + var setxml = new obj._getNavi(obj.showXml(),proc,true); + return "Success"; + } catch (e){ + return e; + } + } + var res = testme(); + doh.assertEqual("Success", res); + }, + + function testRunnerInstantiation (){ + var obj = new CSL.Core.Build(nestedsingleton); + var state = obj.state; + function testme (){ + try { + var build = new obj._builder(state); + return "Success"; + } catch (e){ + return e; + } + } + var res = testme(); + doh.assertEqual("Success", res); + }, + +]); diff --git a/tests/test_build_integration.js b/tests/test_build_integration.js new file mode 100644 index 000000000..65898bee5 --- /dev/null +++ b/tests/test_build_integration.js @@ -0,0 +1,27 @@ +dojo.provide("tests.test_build_integration"); + + + +doh.registerGroup("tests.build_integration", + [ + function testBuildObject(t){ + var textwithvalue = ''; + var build = new CSL.Core.Build(textwithvalue); + var obj = build.build(); + t.assertEqual("object", typeof obj ); + }, + function testBuildLength(t){ + var textwithvalue = ''; + var build = new CSL.Core.Build(textwithvalue); + var obj = build.build(); + t.assertEqual(1, obj.citation.tokens.length ); + }, + function testBuild(t){ + var textwithvalue = ''; + var build = new CSL.Core.Build(textwithvalue); + var obj = build.build(); + t.assertEqual("italic", obj.citation.tokens[0].decorations[0][1] ); + } + ] +); + diff --git a/tests/test_build_internals.js b/tests/test_build_internals.js new file mode 100644 index 000000000..22ae68717 --- /dev/null +++ b/tests/test_build_internals.js @@ -0,0 +1,177 @@ +dojo.provide("tests.test_build_internals"); + +var nestedsingleton = ""; +var decoratedtags = ""; +var textwithvalue = ""; + +var Item = { + "title":"My Aunt Sally" +}; + +doh.register("tests.builder_internals", [ + + function testValueAttributeAction(){ + var obj = new CSL.Core.Build(textwithvalue); + var builder = new obj._builder(obj.state,true); + var res = builder._build(obj.showXml()); + var dummy = { }; + var res = res.citation.tokens[0].strings.value; + doh.assertEqual( "My Aunt Sally" , res); + }, + function testMacroLoop(){ + var t = ''; + try { + var builder = new CSL.Core.Build(t); + var res = builder.build(); + } catch(e){ + print(e+" (this error is correct)"); + } + doh.assertFalse( res ); + }, + function testMacro(){ + var t = ''; + var obj = new CSL.Core.Build(t); + var builder = new obj._builder(obj.state,true); + var res = builder._build(obj.showXml()); + doh.assertEqual(9, res.citation.tokens.length ); + doh.assertEqual("function", typeof res.citation.tokens[4].execs[0]); + doh.assertEqual("function", typeof res.citation.tokens[5].execs[0]); + + }, + function testInit(){ + var obj = new CSL.Core.Build(nestedsingleton); + var builder = new obj._builder(obj.state,true); + var res = builder._build(obj.showXml()); + // + // note that the style tag is stripped by Build + doh.assertEqual( 1, res.citation.tokens.length); + }, + function testDecorationLength(){ + var obj = new CSL.Core.Build(decoratedtags); + var builder = new obj._builder(obj.state,true); + var res = builder._build(obj.showXml()); + doh.assertEqual( 1, res.citation.tokens[0].decorations.length ); + }, + function testDecorationValue(){ + var obj = new CSL.Core.Build(decoratedtags); + var builder = new obj._builder(obj.state,true); + var res = builder._build(obj.showXml()); + doh.assertEqual( "italic", res.citation.tokens[0].decorations[0][1]); + doh.assertEqual( "@font-style", res.citation.tokens[0].decorations[0][0]); + }, + function testValueAttributeType(){ + var obj = new CSL.Core.Build(textwithvalue); + var builder = new obj._builder(obj.state,true); + var res = builder._build(obj.showXml()); + doh.assertEqual( "function" , typeof res.citation.tokens[0].execs[0]); + }, + function testBadTag(){ + var t = ''; + var obj = new CSL.Core.Build(t); + var builder = new obj._builder(obj.state,true); + function tryme() { + try { + builder._build(obj.showXml()); + return "Succeeded wrongly"; + } catch (e) { + if ("Unknown tag name \"badtagname\" encountered while attempting to process CSL file"){ + return "Failed correctly"; + } else { + return "Failed wrongly"; + } + } + } + var res = tryme(); + doh.assertEqual("Failed correctly", res ); + }, + function testBadAttribute(){ + var t = ''; + var obj = new CSL.Core.Build(t); + var builder = new obj._builder(obj.state,true); + function tryme() { + try { + builder._build(obj.showXml()); + return "Succeeded wrongly"; + } catch (e) { + if ("Unknown attribute \"@badattribute\" in node \"text\" while processing CSL file"){ + return "Failed correctly"; + } else { + return "Failed wrongly"; + } + } + } + var res = tryme(); + doh.assertEqual("Failed correctly", res ); + }, + + function testGroup(){ + var t = ''; + var obj = new CSL.Core.Build(t); + var builder = new obj._builder(obj.state,true); + var res = builder._build(obj.showXml()); + doh.assertEqual(3, res.citation.tokens.length ); + doh.assertEqual("function", typeof res.citation.tokens[1].execs[0]); + var dummy = {}; + res.citation.tokens[1].execs[0].call(res.citation.tokens[1],obj.state,dummy); + doh.assertEqual("hello", obj.state.citation.tokens[1].strings.value); + }, + + function testConditional(){ + var t = ''; + var obj = new CSL.Core.Build(t); + var build = new obj._builder(obj.state,true); + var res = build._build(obj.showXml()); + doh.assertEqual(11, res.citation.tokens.length ); + doh.assertEqual("function", typeof res.citation.tokens[8].execs[0]); + var dummy = {}; + res.citation.tokens[8].execs[0].call(res.citation.tokens[8],obj.state,dummy); + doh.assertEqual("three", obj.state.citation.tokens[8].strings.value); + }, + + +]); diff --git a/tests/test_commands.js b/tests/test_commands.js new file mode 100644 index 000000000..dc75d4859 --- /dev/null +++ b/tests/test_commands.js @@ -0,0 +1,14 @@ +dojo.provide("tests.test_commands"); + + +doh.register("tests.commands", [ + function testMakeStyle() { + try { + var ret = CSL.makeStyle(""); + } catch (e) { + print(e); + var ret = false; + }; + doh.assertTrue(ret); + } +]); diff --git a/tests/test_compiler.js b/tests/test_compiler.js new file mode 100644 index 000000000..53e0d2899 --- /dev/null +++ b/tests/test_compiler.js @@ -0,0 +1,19 @@ +dojo.provide("tests.test_compiler"); + + +doh.register("tests.compiler", [ + + function testInstantiateCompiler() { + function testme () { + try { + var fmt = CSL.Compiler("html"); + return "Success"; + } catch (e) { + return "Instantiation failure: " + e; + } + } + var res = testme(); + doh.assertEqual( "Success", res ); + }, + +]); diff --git a/tests/test_conditions.js b/tests/test_conditions.js new file mode 100644 index 000000000..9f095e1db --- /dev/null +++ b/tests/test_conditions.js @@ -0,0 +1,175 @@ +dojo.provide("tests.test_conditions"); + + +doh.registerGroup("tests.conditions", + [ + function testNone(){ + var xml = ""; + + var Item = [{}]; + var cite = tests.test_conditions.makeCite(xml,Item); + doh.assertEqual("Omote",cite); + }, + function testAny(){ + var xml = ""; + + var Item = [{ "title":"Some value" }]; + var cite = tests.test_conditions.makeCite(xml,Item); + doh.assertEqual("Omote",cite); + }, + function testElseIf(){ + var xml = ""; + + var Item = [{}]; + var cite = tests.test_conditions.makeCite(xml,Item); + doh.assertEqual("Omote",cite); + }, + function testMultipleElseIfFirstIsTrue(){ + var xml = ""; + + var Item = [{}]; + var cite = tests.test_conditions.makeCite(xml,Item); + doh.assertEqual("Mikake",cite); + }, + function testMultipleElseIfSecondIsTrue(){ + var xml = ""; + + var Item = [{}]; + var cite = tests.test_conditions.makeCite(xml,Item); + doh.assertEqual("Omote",cite); + }, + function testNested(){ + var xml = ""; + + var Item = [{}]; + var cite = tests.test_conditions.makeCite(xml,Item); + doh.assertEqual("Ura",cite); + } + ], + function(){ //setup + tests.test_conditions.makeCite = function(xml,Item){ + if (!Item){ + var Item = [{}]; + } + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + return style.makeCitationCluster(Item); + }; + }, + function(){ // teardown + } + +); + + diff --git a/tests/test_configure.js b/tests/test_configure.js new file mode 100644 index 000000000..72a37abda --- /dev/null +++ b/tests/test_configure.js @@ -0,0 +1,110 @@ +dojo.provide("tests.test_configure"); + + +var nestedsingleton = ""; +var xmlif = ""; +var xmlifnested = ""; + +var build = false; +var obj = false; +var conf = false; +var newobj = false; + +doh.registerGroup("tests.conditions_build", + [ + function testBuildLength(){ + doh.assertEqual(1, obj["citation"]["tokens"].length); + } + + ], + function(){ // setup + build = new CSL.Core.Build(nestedsingleton); + obj = build.build(); + }, + function(){ // teardown + build = false; + obj = false; + } +); + + +doh.registerGroup("tests.conditions_simple_jumps", + [ + function testConfigureReturnsSomething(){ + doh.assertEqual(11, newobj["citation"]["tokens"].length); + }, + + function testConfigureJumpHasValue(){ + doh.assertEqual( 11, newobj["citation"]["tokens"][3]["succeed"]); + } + ], + function(){ // setup + build = new CSL.Core.Build(xmlif); + obj = build.build(); + conf = new CSL.Core.Configure(obj); + newobj = conf.configure(); + }, + function(){ // teardown + build = false; + obj = false; + conf = false; + newobj = false; + } +); + +doh.registerGroup("tests.conditions_complex_jumps", + [ + function testConfigureReturnsSomething(){ + doh.assertEqual(19, newobj["citation"]["tokens"].length); + }, + + function testConfigureJumpHasValue(){ + doh.assertEqual( 12, newobj["citation"]["tokens"][1]["fail"]); + } + ], + function(){ // setup + build = new CSL.Core.Build(xmlifnested); + obj = build.build(); + conf = new CSL.Core.Configure(obj); + newobj = conf.configure(); + + }, + function(){ // teardown + build = false; + obj = false; + conf = false; + newobj = false; + } +); diff --git a/tests/test_csl.js b/tests/test_csl.js new file mode 100644 index 000000000..6b16f136d --- /dev/null +++ b/tests/test_csl.js @@ -0,0 +1,22 @@ +dojo.provide("tests.test_csl"); +dojo.require("doh.runner"); + + +doh.register("tests.csl", [ + + + function testInstantiateCsl() { + function testme () { + try { + // CSL is pre-instantiated + var csl = CSL; + return "Success"; + } catch (e) { + return "Instantiation failure: " + e; + } + } + var res = testme(); + doh.assertEqual( "Success", res ); + }, + +]); diff --git a/tests/test_dates.js b/tests/test_dates.js new file mode 100644 index 000000000..5c3009fda --- /dev/null +++ b/tests/test_dates.js @@ -0,0 +1,213 @@ +dojo.provide("tests.test_dates"); + + +doh.register("tests.dates", [ + function testThatItWorksAtAll(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-western-name-1"]); + var res = style.makeCitationCluster(input); + doh.assertEqual("1965",res); + }, + function testYearFormShort(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-western-name-1"]); + var res = style.makeCitationCluster(input); + doh.assertEqual("65",res); + }, + function testMonthFormNumeric(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-western-name-1"]); + var res = style.makeCitationCluster(input); + doh.assertEqual("6",res); + }, + function testMonthFormNumericLeadingZeros(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-western-name-1"]); + var res = style.makeCitationCluster(input); + doh.assertEqual("06",res); + }, + function testMonthFormShort(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-western-name-1"]); + var res = style.makeCitationCluster(input); + doh.assertEqual("Jun",res); + }, + function testMonthFormLong(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-western-name-1"]); + var res = style.makeCitationCluster(input); + doh.assertEqual("June",res); + }, + function testDayFormNumeric(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-western-name-1"]); + var res = style.makeCitationCluster(input); + doh.assertEqual("1",res); + }, + function testDayFormNumericLeadingZeros(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-western-name-1"]); + var res = style.makeCitationCluster(input); + doh.assertEqual("01",res); + }, + function testDayFormOrdinalOne(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-western-name-1"]); + var res = style.makeCitationCluster(input); + doh.assertEqual("1st",res); + }, + function testDayFormOrdinalTwo(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-western-name-2"]); + var res = style.makeCitationCluster(input); + doh.assertEqual("2nd",res); + }, + function testDayFormOrdinalThree(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-western-name-3"]); + var res = style.makeCitationCluster(input); + doh.assertEqual("3rd",res); + }, + function testDayFormOrdinalFour(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-mongolian-name-1"]); + var res = style.makeCitationCluster(input); + doh.assertEqual("4th",res); + }, + +]); + + + diff --git a/tests/test_factory.js b/tests/test_factory.js new file mode 100644 index 000000000..f259d95bc --- /dev/null +++ b/tests/test_factory.js @@ -0,0 +1,51 @@ +dojo.provide("tests.test_factory"); + + +doh.register("tests.factory", [ + + function testIfItWorksAtAll() { + function testme () { + try { + var fmt = CSL.Factory.substituteOne; + return "Success"; + } catch (e) { + return "Instantiation failure: " + e; + } + } + var res = testme(); + doh.assertEqual( "Success", res ); + }, + + function testFactoryStack (){ + doh.assertEqual( "bogus", new CSL.Factory.State("bogus").build.xmlCommandInterface ); + }, + function testSubstituteOne() { + var template = "%%STRING%%"; + var func = CSL.Factory.substituteOne(template); + doh.assertEqual( "My Aunt Sally", func("My Aunt Sally")); + }, + + function testSubstituteTwo() { + var template = "%%STRING%%"; + var func = CSL.Factory.substituteTwo(template); + var func2 = func("courier"); + doh.assertEqual( "My Aunt Sally", func2("My Aunt Sally")); + }, + + function testOutputModeCompilerAttribute(){ + var res = CSL.Factory.Mode("html"); + doh.assertTrue( res["@font-style"] ); + }, + function testOutputModeCompilerValue(){ + var res = CSL.Factory.Mode("html"); + doh.assertTrue( res["@font-style"]["italic"] ); + }, + function testOutputModeCompilerFunction(){ + var res = CSL.Factory.Mode("html"); + doh.assertEqual( "function", typeof res["@font-style"]["italic"] ); + }, + function testOutputModeCompilerAction(){ + var res = CSL.Factory.Mode("html"); + doh.assertEqual( "My Aunt Sally", res["@font-style"]["italic"]("My Aunt Sally") ); + } +]); diff --git a/tests/test_failing.js b/tests/test_failing.js new file mode 100644 index 000000000..7502a04f8 --- /dev/null +++ b/tests/test_failing.js @@ -0,0 +1,37 @@ +dojo.provide("tests.test_failing"); + + +var style = false; +var Item = false; + +doh.registerGroup("tests.failing", + [ + function testTwoHello(){ + var xml = ""; + + var cite = tests.test_failing.makeCite(xml); + doh.assertEqual("Hello again, world!Hello world!",cite); + } + ], + function(){ //setup + tests.test_failing.makeCite = function(xml){ + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + style = configurator.configure(); + var Item = [{}]; + var ret = style.makeCitationCluster(Item); + return ret; + }; + }, + function(){ // teardown + } + +); diff --git a/tests/test_formatters.js b/tests/test_formatters.js new file mode 100644 index 000000000..59b467378 --- /dev/null +++ b/tests/test_formatters.js @@ -0,0 +1,42 @@ +dojo.provide("tests.test_formatters"); + + +doh.register("tests.formatters", [ + function testGetSuffix(){ + var list = "a,b,c,d"; + var suffixator = new CSL.Util.Disambiguate.Suffixator(list); + doh.assertEqual("c",suffixator.format(2)); + }, + function testSuffixize(){ + + var list = "a,b,c,d"; + var suffixator = new CSL.Util.Disambiguate.Suffixator(list); + + var res = suffixator.get_suffixes(34,list); + doh.assertEqual("adc", res[(res.length-1)]); + + var res = suffixator.get_suffixes(350,list); + doh.assertEqual("acbbd", res[(res.length-1)]); + + var res = suffixator.get_suffixes(351,list); + doh.assertEqual("acbca", res[(res.length-1)]); + }, + function testIfItWorksAtAll() { + function testme () { + try { + var fmt = CSL.Utilities; + return "Success"; + } catch (e) { + return "Instantiation failure: " + e; + } + } + var res = testme(); + doh.assertEqual( "Success", res ); + }, + + function testCaps() { + doh.assertEqual( 'CAPS', CSL.Output.Formatters.uppercase("caps") ); + }, + +]); + diff --git a/tests/test_groups.js b/tests/test_groups.js new file mode 100644 index 000000000..81c7dda9a --- /dev/null +++ b/tests/test_groups.js @@ -0,0 +1,83 @@ +dojo.provide("tests.test_groups"); + + +var style = false; +var Item = false; + +doh.registerGroup("tests.groups", + [ + function testGroupSiblingDecoration(){ + var xml = ""; + var cite = tests.test_groups.makeCite(xml); + for (i in cite[0]){ + print(i+":"+cite[0][i]); + } + doh.assertEqual("@HelloGoodbye@",cite); + }, + function testGroup(){ + var xml = ""; + var cite = tests.test_groups.makeCite(xml); + doh.assertEqual("Hello",cite); + }, + function testGroupDecoration(){ + var xml = ""; + var cite = tests.test_groups.makeCite(xml); + doh.assertEqual("Hello",cite); + }, + function testGroupDelimiters(){ + var xml = ""; + var cite = tests.test_groups.makeCite(xml); + doh.assertEqual("(one[y] =two[x] three=)", cite); + } + + ], + function(){ + tests.test_groups.makeCite = function(xml){ + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + style = configurator.configure(); + var Item = [{}]; + return style.makeCitationCluster(Item); + }; + }, + function(){ + } +); diff --git a/tests/test_list.js b/tests/test_list.js new file mode 100644 index 000000000..84caedb9a --- /dev/null +++ b/tests/test_list.js @@ -0,0 +1,90 @@ +dojo.provide("tests.test_list"); + + +doh.registerGroup("tests.list", + [ + function testListAppend () { + var state = new tests.test_list.state(); + var res = new CSL.Output.Queue(state); + + var token = CSL.Factory.Token("someelement",CSL.START); + + res.append("one",token); + doh.assertEqual("one", res.queue[0].blobs ); + }, + + function testListNewlevel () { + var state = new tests.test_list.state(); + var res = new CSL.Output.Queue(state); + var token = CSL.Factory.Token("someelement",CSL.START); + + res.addToken("myformatbundle",false,token); + res.openLevel("myformatbundle"); + res.append("one"); + doh.assertEqual("one", res.queue[0].blobs[0].blobs ); + }, + + function testString () { + var state = new tests.test_list.state(); + var res = new CSL.Output.Queue(state); + + var token1 = new CSL.Factory.Token("sometype",CSL.START); + token1.strings.delimiter = " [X] "; + + var token2 = new CSL.Factory.Token("someothertype",CSL.START); + token2.strings.delimiter = " [Y] "; + + res.addToken("withtokenone",false,token1); + res.addToken("withtokentwo",false,token2); + + res.openLevel("withtokenone"); // provides delimiter for group + res.append("one"); + res.openLevel("withtokentwo"); // provides delimiter for subgroup + res.append("two"); + res.append("three"); + res.closeLevel(); + res.closeLevel(); + + doh.assertEqual("one [X] two [Y] three", res.string(state,res.queue) ); + }, + function testListMerge () { + var token = tests.test_list.token(); + var state = new tests.test_list.state(); + var res = new CSL.Output.Queue(state); + + res.addToken("newlevel",false,token); + + res.append("one"); + res.openLevel("newlevel"); + res.append("two"); + res.append("three"); + doh.assertEqual("two", res.current.value()[0].blobs ); + res.closeLevel(); + doh.assertEqual("one", res.current.value()[0].blobs ); + } + ], + function(){ + tests.test_list.token = function(){ + return { + "decorations": new Array(), + "strings":{ + "prefix":"", + "suffix":"", + "delimiter":"" + } + }; + }; + tests.test_list.state = function(){ + this.tmp = new Object(); + this.tmp.delimiter = new CSL.Factory.Stack(); + this.tmp.prefix = new CSL.Factory.Stack(); + this.tmp.suffix = new CSL.Factory.Stack(); + this.tmp.decorations = new CSL.Factory.Stack(); + }; + }, + function(){ + + } +); + + diff --git a/tests/test_load_styles.js b/tests/test_load_styles.js new file mode 100644 index 000000000..42ebd1083 --- /dev/null +++ b/tests/test_load_styles.js @@ -0,0 +1,79 @@ +dojo.provide("tests.test_load_styles"); + + +var tryStyle = function(style){ + try { + var sty = readFile("style/"+style+".csl"); + if (!sty){ + throw "Did not find style file: style/"+style+".csl"; + } + var builder = new CSL.Core.Build(sty); + var res = builder.build(); + } catch(e) { + print("oops: "+e); + } + return res; +} + +doh.register("tests.load_styles", [ + function(){ + var res = tryStyle("mhra"); + doh.assertTrue( res ); + }, + function(){ + var res = tryStyle("ama"); + doh.assertTrue( res ); + }, + function(){ + var res = tryStyle("apa"); + doh.assertTrue( res ); + }, + function(){ + var res = tryStyle("apsa"); + doh.assertTrue( res ); + }, + function(){ + var res = tryStyle("asa"); + doh.assertTrue( res ); + }, + function(){ + var res = tryStyle("chicago-author-date"); + doh.assertTrue( res ); + }, + function(){ + var res = tryStyle("chicago-fullnote-bibliography"); + doh.assertTrue( res ); + }, + function(){ + var res = tryStyle("chicago-note-bibliography"); + doh.assertTrue( res ); + }, + function(){ + var res = tryStyle("chicago-note"); + doh.assertTrue( res ); + }, + function(){ + var res = tryStyle("harvard1"); + doh.assertTrue( res ); + }, + function(){ + var res = tryStyle("ieee"); + doh.assertTrue( res ); + }, + function(){ + var res = tryStyle("mhra_note_without_bibliography"); + doh.assertTrue( res ); + }, + function(){ + var res = tryStyle("mla"); + doh.assertTrue( res ); + }, + function(){ + var res = tryStyle("nature"); + doh.assertTrue( res ); + }, + function(){ + var res = tryStyle("nlm"); + doh.assertTrue( res ); + }, +]); diff --git a/tests/test_locale.js b/tests/test_locale.js new file mode 100644 index 000000000..806ce497d --- /dev/null +++ b/tests/test_locale.js @@ -0,0 +1,56 @@ +dojo.provide("tests.test_locale"); + + +doh.register("tests.locale", + [ + function testManualLoad(){ + var xml = readFile("./locale/locales-en-US.xml"); + var builder = new CSL.Core.Build(xml); + var tokens = builder.build(); + doh.assertEqual("¶",builder.state.opt.term["paragraph"]["symbol"][0]); + }, + function testImplicitLoad(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + builder.build(); + doh.assertEqual("段落", builder.state.opt.term["paragraph"]["verb"][0]); + }, + + function testFailedOverload(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + builder.build(); + doh.assertEqual("段落", builder.state.opt.term["paragraph"]["verb"][0]); + }, + + + function testOverloadNotGreedy(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + builder.build(); + doh.assertEqual("段落", builder.state.opt.term["paragraph"]["verb"][0]); + }, + function testOverloadTakesEffect(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + builder.build(); + doh.assertEqual("parrie", builder.state.opt.term["paragraph"]["long"][0]); + } + // add a test for default locale loading sometime. + + ] +); + + diff --git a/tests/test_names_import.js b/tests/test_names_import.js new file mode 100644 index 000000000..ebf6a2e46 --- /dev/null +++ b/tests/test_names_import.js @@ -0,0 +1,65 @@ +dojo.provide("tests.test_names_import"); + + +doh.register("tests.names_import", [ + function testSimpleWesternName(){ + var source = ["simple-western-name-1"]; + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(source); + doh.assertEqual("Doe", input[0]["author"][0]["primary-key"]); + doh.assertEqual("John", input[0]["author"][0]["secondary-key"]); + }, + function testTwoSimpleWesternNames(){ + var source = ["two-simple-western-names-1"]; + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(source); + doh.assertEqual("Doe", input[0]["author"][0]["primary-key"]); + doh.assertEqual("John", input[0]["author"][0]["secondary-key"]); + doh.assertEqual("Roe", input[0]["author"][1]["primary-key"]); + doh.assertEqual("Jane", input[0]["author"][1]["secondary-key"]); + }, + function testWesternNameWithArticular(){ + var source = ["western-name-with-articular-1"]; + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(source); + doh.assertEqual("Doe", input[0]["author"][0]["primary-key"]); + doh.assertEqual("Jacques", input[0]["author"][0]["secondary-key"]); + doh.assertEqual("van", input[0]["author"][0].prefix); + }, + function testWesternNameWithSuffix(){ + var source = ["western-name-with-space-suffix-1"]; + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(source); + doh.assertEqual("Doe", input[0]["author"][0]["primary-key"]); + doh.assertEqual("James", input[0]["author"][0]["secondary-key"]); + doh.assertEqual("III", input[0]["author"][0].suffix); + }, + function testWesternNameWithPeriodSuffix(){ + var source = ["western-name-with-space-suffix-2"]; + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(source); + doh.assertEqual("Doe", input[0]["author"][0]["primary-key"]); + doh.assertEqual("Jeffrey", input[0]["author"][0]["secondary-key"]); + doh.assertEqual("Jr.", input[0]["author"][0].suffix); + }, + function testSimpleAsianName(){ + var source = ["simple-sticky-name-1"]; + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(source); + doh.assertEqual("Miyamoto", input[0]["author"][0]["primary-key"]); + doh.assertEqual("Musashi", input[0]["author"][0]["secondary-key"]); + }, + function testSimpleMongolianName(){ + var source = ["simple-mongolian-name-1"]; + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(source); + doh.assertEqual("Tserendorj", input[0]["author"][0]["primary-key"]); + doh.assertEqual("Balingiin", input[0]["author"][0]["secondary-key"]); + }, + function testInstitutionalName(){ + var source = ["institution-name-1"]; + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(source); + doh.assertEqual("Ministry of Education, Sports, Culture, Science and Technology", input[0]["author"][0].literal); + } +]); diff --git a/tests/test_output.js b/tests/test_output.js new file mode 100644 index 000000000..95625e0c6 --- /dev/null +++ b/tests/test_output.js @@ -0,0 +1,23 @@ +dojo.provide("tests.test_output"); + + +doh.register("tests.output", [ + + function testInstantiateOutput() { + function testme () { + try { + var fmt = CSL.Output; + return "Success"; + } catch (e) { + return "Instantiation failure: " + e; + } + } + var res = testme(); + doh.assertEqual( "Success", res ); + }, + + function testHtmlLoad() { + doh.assertEqual( '&lquo;%%STRING%%&rquo;', CSL.Output.Formats.html["@quotes"] ); + }, + +]); diff --git a/tests/test_range.js b/tests/test_range.js new file mode 100644 index 000000000..b05e58f2b --- /dev/null +++ b/tests/test_range.js @@ -0,0 +1,94 @@ +dojo.provide("tests.test_range"); + +var test = new Object(); + +doh.registerGroup("tests.range", [ + function testYearSuffixFormatter() { + var token = new CSL.Factory.Token("bogus",CSL.START); + token.formatter = test.fun.suffixator; + var number = new CSL.Output.Number(0,token); + doh.assertEqual( "object", typeof number.formatter ); + doh.assertEqual( "function", typeof number.formatter.format ); + doh.assertEqual( "k", number.formatter.format(10) ); + }, + function testThatItWorksAtAll() { + try { + CSL.Output.Number(2); + var res = true; + } catch (e){ + print(e); + var res = false; + } + doh.assertTrue( res ); + }, + function testRomanFormatter() { + var token = new CSL.Factory.Token("bogus",CSL.START); + token.formatter = test.fun.romanizer; + var number = new CSL.Output.Number(0,token); + doh.assertEqual( "object", typeof number.formatter ); + doh.assertEqual( "function", typeof number.formatter.format ); + doh.assertEqual( "x", number.formatter.format(10) ); + }, + function testDefaultFormatter() { + var number = new CSL.Output.Number(0); + doh.assertEqual( "object", typeof number.formatter ); + doh.assertEqual( "function", typeof number.formatter.format ); + doh.assertEqual( "10", number.formatter.format(10) ); + }, + function testType() { + var token = new CSL.Factory.Token("bogus",CSL.START); + token.formatter = test.fun.suffixator; + var number = new CSL.Output.Number(10,token); + doh.assertEqual( "b", number.type ); + }, + function testNum() { + var number = new CSL.Output.Number(2); + doh.assertEqual( 2, number.num ); + }, + function testCheckNextSuccessor() { + var number1 = new CSL.Output.Number(1); + var number2 = new CSL.Output.Number(2); + var numlist = [number1,number2]; + numlist[0].checkNext(numlist[1]); + doh.assertEqual( CSL.SUCCESSOR, numlist[1].status ); + }, + function testCheckNextSuppress() { + var number1 = new CSL.Output.Number(1); + var number2 = new CSL.Output.Number(2); + var number3 = new CSL.Output.Number(3); + var numlist = [number1,number2,number3]; + numlist[0].checkNext(numlist[1]); + numlist[1].checkNext(numlist[2]); + doh.assertEqual( CSL.SUPPRESS, numlist[1].status ); + }, + function testCheckNextEndOnText() { + var number1 = new CSL.Output.Number(1); + var number2 = new CSL.Output.Number(2); + var number3 = new CSL.Output.Number(3); + var numlist = [number1,number2,number3,"Text"]; + numlist[0].checkNext(numlist[1]); + numlist[1].checkNext(numlist[2]); + numlist[2].checkNext(numlist[3]); + doh.assertEqual( CSL.END, numlist[2].status ); + }, + function testCheckNextEndOnEOL() { + var number1 = new CSL.Output.Number(1); + var number2 = new CSL.Output.Number(2); + var number3 = new CSL.Output.Number(3); + var numlist = [number1,number2,number3]; + numlist[0].checkNext(numlist[1]); + numlist[1].checkNext(numlist[2]); + numlist[2].checkNext(numlist[3]); + doh.assertEqual( CSL.END, numlist[2].status ); + }, + ], + function(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + test.fun = builder.build().fun; + }, + function(){ + test = new Object(); + } +); + diff --git a/tests/test_registry.js b/tests/test_registry.js new file mode 100644 index 000000000..9799c4990 --- /dev/null +++ b/tests/test_registry.js @@ -0,0 +1,444 @@ +dojo.provide("tests.test_registry"); + +doh.register("tests.registry", [ + function testRegistrationSortWithSingleKey(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-western-name-1","simple-western-name-2","simple-western-name-3"]); + style.registry.insert(style,input[0]); + style.registry.insert(style,input[1]); + style.registry.insert(style,input[0]); + //print(style.registry.registry["simple-western-name-2"].sortkeys); + doh.assertEqual( "simple-western-name-1", style.registry.registry["simple-western-name-2"].next ); + doh.assertEqual( "simple-western-name-2", style.registry.registry["simple-western-name-1"].prev ); + doh.assertEqual( false, style.registry.registry["simple-western-name-2"].prev ); + doh.assertEqual( false, style.registry.registry["simple-western-name-1"].next ); + }, + function testGetSortKeyMacro(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-western-name-1"]); + var res = style.getSortKeys(input[0],"bibliography_sort"); + doh.assertEqual("My Macro Text::AAA", res[0]); + }, + function testMaxNamesDetection(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["seven-names-plus-two-1"]); + var ambig = style.getAmbiguousCite(input[0]); + doh.assertEqual(7,style.tmp.names_max.mystack[0]); + }, + function testGetSortKeyVariable(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-western-name-1"]); + var res = style.getSortKeys(input[0],"bibliography_sort"); + doh.assertEqual("His Anonymous Life", res[0]); + }, + function testDisambiguateAddGivensInternals(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["ambigs-1","ambigs-2","ambigs-6"]); + style.registry.insert(style,input[0]); + style.registry.insert(style,input[1]); + style.registry.insert(style,input[2]); + style.getAmbiguousCite(input[0]); + var res = style.getAmbigConfig(); + doh.assertEqual({"names":[6],"givens":[[1,1,1,1,1,1]],"year_suffix":false,"disambiguate":false},res); + + }, + + function testConfigureNumberOfNames(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["ambigs-2"]); + var disambig = {"names":[3],"givens":[[2,2,2]],"year_suffix":false,"disambiguate":false}; + var res = style.getAmbiguousCite(input[0],disambig); + doh.assertEqual("Albert Asthma, Bosworth Bronchitis, Crispin Cold, et al.",res); + }, + function testRegistration(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-western-name-1","simple-western-name-2","simple-western-name-3"]); + style.registry.insert(style,input[0]); + doh.assertTrue( style.registry.registry["simple-western-name-1"] ); + }, + function testRegistrationContent(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-western-name-1","simple-western-name-2","simple-western-name-3"]); + style.registry.insert(style,input[0]); + var res = style.registry.registry["simple-western-name-1"]; + doh.assertEqual( "simple-western-name-1", res.id ); + doh.assertEqual( "His Anonymous Life", res.sortkeys ); + }, + function testDisabiguationGetDefaultVals(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["ambigs-1"]); + var res = style.getAmbiguousCite(input[0]); + doh.assertEqual(2,style.getAmbigConfig()["givens"][0][0]); + doh.assertEqual(2,style.getAmbigConfig()["givens"][0][1]); + }, + function testDisambiguationGivens(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["ambigs-4","ambigs-5"]); + style.registry.insert(style,input[0]); + style.registry.insert(style,input[1]); + style.getAmbiguousCite(input[0]); + doh.assertEqual(1 ,style.registry.registry["ambigs-4"].disambig["givens"].length); + }, + + + + + + function testDisambiguateAddGivensSimpleWithInitials(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["ambigs-7","ambigs-8"]); + style.registry.insert(style,input[0]); + style.registry.insert(style,input[1]); + var res = style.getAmbiguousCite(input[0]); + doh.assertEqual("J. Doe, Janet Roe",res); + }, + function testDisambiguateAddNamesSimple(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["ambigs-9","ambigs-10"]); + //print("input[0] (ambigs-9) ================= "); + style.registry.insert(style,input[0]); + //print("input[1] (ambigs-10) ================="); + style.registry.insert(style,input[1]); + //print("end ================="); + var res0 = style.getAmbiguousCite(input[0]); + doh.assertEqual("John Doe, Jane Roe",res0); + //print("t0 passed"); + }, + function testGetUndecoratedCite(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var res = style.getAmbiguousCite([{}]); + doh.assertEqual("hello", res); + }, + function testInstantiation(){ + var state = new CSL.Factory.State(); + var obj = new CSL.Factory.Registry(state); + doh.assertTrue(obj); + }, + function testDisambiguateAddGivensSimple(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["ambigs-7","ambigs-8"]); + style.registry.insert(style,input[0]); + style.registry.insert(style,input[1]); + var res = style.getAmbiguousCite(input[0]); + doh.assertEqual("J. Doe, Janet Roe",res); + }, + function testMultipleRegistration(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-western-name-1","simple-western-name-2","simple-western-name-3"]); + style.registry.insert(style,input[0]); + style.registry.insert(style,input[1]); + style.registry.insert(style,input[0]); + doh.assertTrue( style.registry.registry["simple-western-name-1"] ); + doh.assertTrue( style.registry.registry["simple-western-name-2"] ); + }, + function testAmbiguityDetection(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-western-name-1","simple-western-name-2","simple-western-name-3"]); + var akey = style.getAmbiguousCite(input[0]); + style.registry.insert(style,input[0]); + style.registry.insert(style,input[1]); + style.registry.insert(style,input[2]); + doh.assertEqual(2, style.registry.ambigs[akey].length); + }, + function testDisambiguateAddNamesComplicated(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["ambigs-1","ambigs-2","ambigs-3"]); + //print("input[0] (ambigs-1) ================="); + style.registry.insert(style,input[0]); + //print("input[1] (ambigs-2) ================="); + style.registry.insert(style,input[1]); + //print("input[2] (ambigs-3) ================="); + style.registry.insert(style,input[2]); + //print("end ================="); + var res0 = style.getAmbiguousCite(input[0]); + var res1 = style.getAmbiguousCite(input[1]); + var res2 = style.getAmbiguousCite(input[2]); + doh.assertEqual("Albert Asthma, Bosworth Bronchitis, Crispin Cold, David Dropsy, Elvin Ebola, Fergus Fever",res0); + //print("t0 passed"); + doh.assertEqual("Albert Asthma, Bosworth Bronchitis, Crispin Cold, David Dropsy, Ernie Enteritis, et al.",res1); + //print("t1 passed"); + doh.assertEqual("Albert Asthma, Bosworth Bronchitis, Crispin Cold, David Dropsy, Elvin Ebola, Fergus Fever",res2); + //print("t2 passed"); + }, + + +]); diff --git a/tests/test_render.js b/tests/test_render.js new file mode 100644 index 000000000..5250a9711 --- /dev/null +++ b/tests/test_render.js @@ -0,0 +1,25 @@ +dojo.provide("tests.test_render"); + +doh.registerGroup("tests.render", + [ + function testHello(){ + var xml = ""; + var cite = tests.test_render.makeCite(xml); + doh.assertEqual("Hello world!",cite); + } + ], + function(){ //setup + tests.test_render.makeCite = function (xml){ + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var Item = [{}]; + var ret = style.makeCitationCluster(Item); + return ret; + }; + }, + function(){ //teardown + + } +); diff --git a/tests/test_retrieval.js b/tests/test_retrieval.js new file mode 100644 index 000000000..cc5ae0792 --- /dev/null +++ b/tests/test_retrieval.js @@ -0,0 +1,31 @@ +dojo.provide("tests.test_retrieval"); + + +doh.register("tests.retrieval", + [ + function testLocaleReturnSomething(t){ + t.assertTrue( CSL.System.Retrieval.getLocaleObjects("en")); + }, + function testItemGetFile(){ + var Source = ["simple-western-name-1"]; + var getter = new CSL.System.Retrieval.GetInput(); + var res = getter.getInput(Source); + doh.assertEqual("His Anonymous Life", res[0].title); + }, + function testItemGetListOfFiles(){ + var Source = ["simple-western-name-1", "simple-western-name-2"]; + var getter = new CSL.System.Retrieval.GetInput(); + var res = getter.getInput(Source); + doh.assertEqual("His Anonymous Life", res[0].title); + doh.assertEqual("Her Anonymous Life", res[1].title); + }, + function testLocaleReturnCorrectLength(t){ + var count = 0; + for (var i in CSL.System.Retrieval.getLocaleObjects("en")){ + count += 1; + } + t.assertEqual(80, count); + }, + ] +); + diff --git a/tests/test_sequence.js b/tests/test_sequence.js new file mode 100644 index 000000000..7fcdf0e57 --- /dev/null +++ b/tests/test_sequence.js @@ -0,0 +1,23 @@ +dojo.provide("tests.test_sequence"); + +doh.register("tests.sequence", [ + + function testIfItWorksAtAll() { + function testme () { + try { + var fmt = CSL.FORMAT_KEY_SEQUENCE; + return "Success"; + } catch (e) { + return e; + } + } + var res = testme(); + doh.assertEqual( "Success", res ); + }, + + function testContents() { + var key = CSL.FORMAT_KEY_SEQUENCE[0]; + doh.assertEqual( "@text-case", key); + }, + +]); diff --git a/tests/test_sort.js b/tests/test_sort.js new file mode 100644 index 000000000..d30a2c0ae --- /dev/null +++ b/tests/test_sort.js @@ -0,0 +1,61 @@ +dojo.provide("tests.test_sort"); + +doh.register("tests.sort", [ + + function testRegistrationSortKeyReturn(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-sticky-name-1","simple-western-name-1","simple-mongolian-name-1"]); + style.registry.insert(style,input[0]); + style.registry.insert(style,input[1]); + style.registry.insert(style,input[2]); + var res = style.registry.getSortedIds(); + // An Altogether Unknown History of Soviet-Mongolian Relations + doh.assertEqual( "simple-mongolian-name-1", res[0] ); + // A Book of Five Rings + doh.assertEqual( "simple-sticky-name-1", res[1] ); + // His Anonymous Life + doh.assertEqual( "simple-western-name-1", res[2] ); + }, + function testRegistryCiteNumber(){ + var xml = ""; + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + var getter = new CSL.System.Retrieval.GetInput(); + var input = getter.getInput(["simple-sticky-name-1","simple-western-name-1","simple-mongolian-name-1"]); + style.registry.insert(style,input[0]); + style.registry.insert(style,input[1]); + style.registry.insert(style,input[2]); + // An Altogether Unknown History of Soviet-Mongolian Relations + doh.assertEqual( 1, style.registry.registry["simple-mongolian-name-1"].seq ); + // A Book of Five Rings + doh.assertEqual( 2, style.registry.registry["simple-sticky-name-1"].seq ); + // His Anonymous Life + doh.assertEqual( 3, style.registry.registry["simple-western-name-1"].seq ); + }, + +]); diff --git a/tests/test_speed.js b/tests/test_speed.js new file mode 100644 index 000000000..aa604527a --- /dev/null +++ b/tests/test_speed.js @@ -0,0 +1,176 @@ +load("./dojo/dojo/dojo.js"); +dojo.registerModulePath("dojo","./dojo/dojo"); +dojo.registerModulePath("dojox","./dojo/dojox"); +dojo.registerModulePath("csl","./src"); +dojo.registerModulePath("doh","./dojo/util/doh"); + +dojo.require("doh.runner"); + +dojo.provide("tests.test_speed"); + +dojo.require("csl.csl"); + +doh.registerGroup("tests.speed", + [ + function testSpeed(){ + print("iterate over sorted list and print"); + tests.test_speed.registry.iterate(); + } + + ], + function(){ //setup + + print ("loading functions"); + + var Registry = function(){ + this.registry = new Object(); + this.start = false; + this.end = false; + this.initialized = false; + this.skip = false; + this.maxlength = 0; + this.insert = function(newitem){ + if (newitem.phoneytitle.length > this.maxlength){ + this.maxlength = newitem.phoneytitle.length; + } + // if the registry is empty, initialize it with + // this object. + if (!this.initialized){ + this.registry[newitem.id] = newitem; + this.start = newitem.id; + this.end = newitem.id; + this.initialized = true; + return; + } + // if this object is less than the first one, + // insert it as the first. + if (-1 == this.compareStrings(newitem.phoneytitle,this.registry[this.start].phoneytitle)){ + //print("Sequence at the beginning: "+newitem.phoneytitle+", "+this.registry[this.start].phoneytitle); + newitem.next = this.registry[this.start].id; + this.registry[this.start].prev = newitem.id; + newitem.prev = false; + this.start = newitem.id; + this.registry[newitem.id] = newitem; + return; + } + // if this object is greater than the + // last one, insert it as the last. + if (-1 == this.compareStrings(this.registry[this.end].phoneytitle,newitem.phoneytitle)){ + //print("Sequence at the end: "+this.registry[this.end].phoneytitle+", "+newitem.phoneytitle); + newitem.prev = this.registry[this.end].id; + this.registry[this.end].next = newitem.id; + newitem.next = false; + this.end = newitem.id; + this.registry[newitem.id] = newitem; + return; + } + // + // if we reach this, it's safe to iterate + var curr = this.registry[this.start]; + while (true){ + // compare the new token to be added with + // the one we're thinking about placing it before. + var cmp = this.compareStrings(curr.phoneytitle,newitem.phoneytitle); + if (cmp > 0){ + // insert mid-list, before the tested item + //print("Inserting mid-list: "+newitem.phoneytitle+", next is "+curr.phoneytitle); + this.registry[curr.prev].next = newitem.id; + newitem.prev = curr.prev; + newitem.next = curr.id; + curr.prev = newitem.id; + this.registry[newitem.id] = newitem; + return; + } else if (cmp == 0) { + // also insert before, but this is a duplicate, + // so we need to provide for cases where the + // inserted object ends up at the beginning of + // the virtual list. + // + //print("I'm a dupe: "+curr.phoneytitle); + // (disambiguation handling would slot in here) + // + if (false == curr.prev){ + newitem.prev = false; + newitem.next = curr.id; + curr.prev = newitem.id; + this.registry[newitem.id] = newitem; + return; + } else { + this.registry[curr.prev].next = newitem.id; + newitem.prev = curr.prev; + newitem.next = curr.id; + curr.prev = newitem.id; + this.registry[newitem.id] = newitem; + return; + } + } + curr = this.registry[curr.next]; + }; + }; + + this.compareStrings = function(a,b){ + return a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase()); + }; + + this.iterate = function(){ + var curr = this.registry[this.start]; + //print("starting iterate at: "+printme); + while(curr.next != false){ + var printme = curr.phoneytitle; + while (printme.length < this.maxlength){ + printme = " "+printme; + } + print(printme); + curr = this.registry[curr.next]; + } + }; + }; + + var makeThing = function(key,phoneytitle,transfat){ + this.id = key; + this.phoneytitle = phoneytitle; + this.transfat = transfat; + this.next = false; + this.prev = false; + }; + + function makePhoneyTitle(){ + var ret = ""; + var mylen = (Math.floor(Math.random()*25)+1); + for (var i=0; i" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + + var Item = [{"title":"My Title"}]; + var cite = tests.test_term.makeCite(xml,Item); + doh.assertEqual("My Name and My Title",cite); + }, + function testTermGroupSuppressOnEmpty(){ + var xml = ""; + + var Item = [{"title":""}]; + var cite = tests.test_term.makeCite(xml,Item); + doh.assertEqual("",cite); + }, + function testTermGroupSuppressOnNull(){ + var xml = ""; + + var Item = [{}]; + var cite = tests.test_term.makeCite(xml,Item); + doh.assertEqual("",cite); + }, + + ], + function(){ //setup + tests.test_term.makeCite = function(xml,Item){ + if (!Item){ + var Item = [{}]; + } + var builder = new CSL.Core.Build(xml); + var raw = builder.build(); + var configurator = new CSL.Core.Configure(raw); + var style = configurator.configure(); + return style.makeCitationCluster(Item); + }; + }, + function(){ // teardown + } + +); diff --git a/tests/test_util_names.js b/tests/test_util_names.js new file mode 100644 index 000000000..4bd1cd9d4 --- /dev/null +++ b/tests/test_util_names.js @@ -0,0 +1,114 @@ +dojo.provide("tests.test_util_names"); + +var display_names = [ + { "primary-key":"Doe", + "secondary-key":"John" + }, + { "secondary-key":"Gwen", + "primary-key":"Roe" + }, + { "secondary-key":"Tom", + "primary-key":"Smith" + } +]; + +var state = CSL.makeStyle(""); + +// +// Delimiters and formatting decorations are +// controlled by cloned tokens derived from +// the token list that expresses the style. +// The nesting structure is considerably more +// complex than the visual appearance of CSL, +// in order to give effect, through nesting and +// simple joins, to the various CSL inter-element +// splice parameters. +// This test shows which of these clone tokens +// do what in the formatting of names. +// + +// the "name" token here carries only +// the "and" token carries all the formatting +// decorations of the compiler "name" element. +// its delimiter is either that of the "name" +// element or, if the @and attribute is set +// on it, the string appropriate to its value. +var name = new CSL.Factory.Token("name"); +name.strings.delimiter = ", and "; +name.strings.prefix ="["; +name.strings.suffix ="]"; +name.strings["name-as-sort-order"] = "first"; +state.output.addToken("name",false,name); + +// the delimiter value of the "name" element +// from the compiler's token list. the formatting +// decorations and affixes are copied to +// the "and" token. +var inner = new CSL.Factory.Token("inner"); +//inner.strings.prefix ="<"; +//inner.strings.suffix =">"; +inner.strings.delimiter = ", "; +state.output.addToken("inner",false,inner); + +// the sort-separator token carries the +// value of the "name" element @sort-separator +// attribute as its delimiter. it is otherwise +// empty. +var sortsep = new CSL.Factory.Token("sortsep"); +sortsep.strings.delimiter = ", "; +state.output.addToken("sortsep",false,sortsep); + +// the name-as-sort-order param from the +// name element is set on an otherwise +// empty token for "start", "middle" and +// "end", as appropriate to its value. +var start = new CSL.Factory.Token("start"); +state.output.addToken("start",false,start); + +var middle = new CSL.Factory.Token("middle"); +state.output.addToken("middle",false,middle); + +var end = new CSL.Factory.Token("end"); +state.output.addToken("end",false,end); + +// token params of the optional "primary-key", +// "secondary-key", "prefix" and "articular" elements +// token params are taken from the token +// list, with no changes +var primary = new CSL.Factory.Token("primary-key"); +primary.strings.prefix="("; +primary.strings.suffix=")"; +state.output.addToken("primary-key",false,primary); + +var secondary = new CSL.Factory.Token("secondary-key"); +state.output.addToken("secondary-key",false,secondary); + +// +// This should be changed to "articular" in the code +var suffix = new CSL.Factory.Token("suffix"); +state.output.addToken("suffix",false,suffix); + +var prefix = new CSL.Factory.Token("prefix"); +state.output.addToken("prefix",false,prefix); + +// the "empty" and "space" tokens are standard +// pre-defined tokens that provide standard +// delimiters without other formatting. +var empty = new CSL.Factory.Token("empty"); +state.output.addToken("empty",false,empty); + +var space = new CSL.Factory.Token("space"); +space.strings.delimiter = " "; +state.output.addToken("space",false,space); + +state.tmp.disambig_settings["givens"] = [[[1],[1],[1]]]; +state.tmp["initialize-with"] = "."; + +state.tmp.nameset_counter = 0; + +doh.register("tests.util_names", [ + function testBuildNames (){ + CSL.Util.Names.outputNames(state,display_names); + doh.assertEqual("[(Doe), J., G. (Roe), and T. (Smith)]", state.output.string(state,state.output.queue)); + } +]); diff --git a/tests/test_xmle4x.js b/tests/test_xmle4x.js new file mode 100644 index 000000000..81aba4432 --- /dev/null +++ b/tests/test_xmle4x.js @@ -0,0 +1,30 @@ +dojo.provide("tests.test_xmle4x"); + + +var str = readFile("./style/apa.csl"); + + + +doh.registerGroup("tests.xml", [ + + function testClean(){ + var tag = "\n"; + var res = CSL.System.Xml.E4X.clean(tag); + doh.assertEqual("", res); + }, + + function testParse(){ + var tag = ""; + function tryme (){ + try { + var res = CSL.System.Xml.E4X.parse(tag); + return "Success"; + } catch(e) { + return e; + } + } + var res = tryme(); + doh.assertEqual("Success", res); + } + +]); diff --git a/tests/test_xmljs.js b/tests/test_xmljs.js new file mode 100644 index 000000000..3889cecc0 --- /dev/null +++ b/tests/test_xmljs.js @@ -0,0 +1,200 @@ +dojo.provide("tests.test_xmljs"); + +doh.registerGroup("tests.xml", [ + + function testNestingEndPoint(){ + var tag = ''; + function tryme (){ + try { + var res = CSL.System.Xml.JunkyardJavascript.parse(tag); + return res; + } catch(e) { + print (e); + return e; + } + } + var res = tryme(); + // [[]] + var cmd = CSL.System.Xml.JunkyardJavascript.commandInterface; + doh.assertEqual( "mymacro", res[0][0].attributes["@value"] ); + doh.assertEqual( "one", res[0][0][0].attributes["@value"] ); + doh.assertEqual( "three", res[0][0][1].attributes["@value"] ); + doh.assertEqual( "two", res[0][1].attributes["@value"] ); + doh.assertEqual( "boo", res[0][2].attributes["@value"] ); + }, + function testAttributes(){ + var tag = ""; + function tryme (){ + try { + var res = CSL.System.Xml.JunkyardJavascript.parse(tag); + return res; + } catch(e) { + print (e); + return e; + } + } + var res = tryme(); + var cmd = CSL.System.Xml.JunkyardJavascript.commandInterface; + doh.assertEqual( 2, cmd.children.call(res[0]).length ); + doh.assertEqual( "text", cmd.children.call(res[0])[0].name ); + doh.assertEqual( "other thing", cmd.children.call(res[0])[1].text ); + }, + + function testChildren(){ + var tag = ""; + function tryme (){ + try { + var res = CSL.System.Xml.JunkyardJavascript.parse(tag); + return res; + } catch(e) { + print (e); + return e; + } + } + var res = tryme(); + var cmd = CSL.System.Xml.JunkyardJavascript.commandInterface; + doh.assertEqual( 2, cmd.children.call(res[0]).length ); + }, + + + function testGetTextString(){ + var tag = ""; + function tryme (){ + try { + var res = CSL.System.Xml.JunkyardJavascript.parse(tag); + return res; + } catch(e) { + print (e); + return e; + } + } + var res = tryme(); + doh.assertEqual("and some text here", res[0][1].text ); + }, + + function testParseWithTextNode(){ + var tag = ""; + function tryme (){ + try { + var res = CSL.System.Xml.JunkyardJavascript.parse(tag); + return res; + } catch(e) { + print (e); + return e; + } + } + var res = tryme(); + doh.assertEqual(null, res[0][1].name ); + }, + + function testParseHasAttributes(){ + var tag = ""; + function tryme (){ + try { + var res = CSL.System.Xml.JunkyardJavascript.parse(tag); + return res; + } catch(e) { + return e; + } + } + var res = tryme(); + doh.assertEqual("hello", res[0][0].attributes["@value"] ); + }, + + function testParseHasContent(){ + var tag = ""; + function tryme (){ + try { + var res = CSL.System.Xml.JunkyardJavascript.parse(tag); + return res; + } catch(e) { + return e; + } + } + var res = tryme(); + doh.assertEqual("style", res[0].name ); + doh.assertEqual("text", res[0][0].name ); + }, + + function testParseReturnsCorrectLength(){ + var tag = ""; + function tryme (){ + try { + var res = CSL.System.Xml.JunkyardJavascript.parse(tag); + return res; + } catch(e) { + return e; + } + } + var res = tryme(); + doh.assertEqual(1, res[0].length ); + }, + + function testParseReturnsSomething(){ + var tag = ""; + function tryme (){ + try { + var res = CSL.System.Xml.JunkyardJavascript.parse(tag); + return res; + } catch(e) { + return e; + } + } + var res = tryme(); + doh.assertTrue( res[0] ); + }, + + function testParseSuccess(){ + var tag = ""; + function tryme (){ + try { + var res = CSL.System.Xml.JunkyardJavascript.parse(tag); + return "Success"; + } catch(e) { + return e; + } + } + var res = tryme(); + doh.assertEqual("Success", res); + }, + + function testNodename(){ + var tag = ""; + function tryme (){ + try { + var res = CSL.System.Xml.JunkyardJavascript.parse(tag); + return res; + } catch(e) { + print (e); + return e; + } + } + var res = tryme(); + var cmd = CSL.System.Xml.JunkyardJavascript.commandInterface; + doh.assertEqual( "text", cmd.nodename.call(res[0][0]) ); + }, + + function testContent(){ + var tag = ""; + function tryme (){ + try { + var res = CSL.System.Xml.JunkyardJavascript.parse(tag); + return res; + } catch(e) { + print (e); + return e; + } + } + var res = tryme(); + var cmd = CSL.System.Xml.JunkyardJavascript.commandInterface; + doh.assertEqual( "other thing", cmd.content.call(res[0][1]) ); + }, + +]);