Compare commits
13 Commits
Author | SHA1 | Date |
---|---|---|
autodocs | 662dcb26d7 | |
autodocs | b6a8904a67 | |
autodocs | b641f2a099 | |
autodocs | d58fdf6376 | |
autodocs | ca9852249b | |
autodocs | 6501933384 | |
autodocs | d943df5a2a | |
autodocs | 09e781bf12 | |
autodocs | c4a11c4883 | |
autodocs | ab90d0459f | |
autodocs | cec36e896f | |
autodocs | e572db8472 | |
autodocs | c29ced6256 |
|
@ -1,3 +0,0 @@
|
|||
*.jl.cov
|
||||
*.jl.*.cov
|
||||
*.jl.mem
|
14
.travis.yml
14
.travis.yml
|
@ -1,14 +0,0 @@
|
|||
# Documentation: http://docs.travis-ci.com/user/languages/julia/
|
||||
language: julia
|
||||
os:
|
||||
- linux
|
||||
julia:
|
||||
- 0.6
|
||||
- nightly
|
||||
notifications:
|
||||
email: false
|
||||
after_success:
|
||||
# build documentation
|
||||
- julia -e 'cd(Pkg.dir("BibTeX")); Pkg.add("Documenter"); include(joinpath("docs", "make.jl"))'
|
||||
# push coverage results to Codecov
|
||||
- julia -e 'cd(Pkg.dir("BibTeX")); Pkg.add("Coverage"); using Coverage; Codecov.submit(Codecov.process_folder())'
|
41
LICENSE.md
41
LICENSE.md
|
@ -1,41 +0,0 @@
|
|||
The BibTeX.jl package is licensed under the MIT "Expat" License:
|
||||
|
||||
|
||||
> Copyright (c) 2017: Brandon Taylor.
|
||||
>
|
||||
>
|
||||
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
>
|
||||
> of this software and associated documentation files (the "Software"), to deal
|
||||
>
|
||||
> in the Software without restriction, including without limitation the rights
|
||||
>
|
||||
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
>
|
||||
> copies of the Software, and to permit persons to whom the Software is
|
||||
>
|
||||
> furnished to do so, subject to the following conditions:
|
||||
>
|
||||
>
|
||||
>
|
||||
> The above copyright notice and this permission notice shall be included in all
|
||||
>
|
||||
> copies or substantial portions of the Software.
|
||||
>
|
||||
>
|
||||
>
|
||||
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
>
|
||||
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
>
|
||||
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
>
|
||||
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
>
|
||||
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
>
|
||||
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
>
|
||||
> SOFTWARE.
|
||||
>
|
||||
>
|
20
README.md
20
README.md
|
@ -1,20 +0,0 @@
|
|||
# BibTeX
|
||||
|
||||
[![travis badge][travis_badge]][travis_url]
|
||||
[![codecov badge][codecov_badge]][codecov_url]
|
||||
|
||||
## Documentation [here][documenter_latest]
|
||||
|
||||
Change documentation link to `documenter_stable` once published!
|
||||
|
||||
[travis_badge]: https://travis-ci.org/bramtayl/BibTeX.jl.svg?branch=master
|
||||
[travis_url]: https://travis-ci.org/bramtayl/BibTeX.jl
|
||||
|
||||
[appveyor_badge]: https://ci.appveyor.com/api/projects/status/github/bramtayl/BibTeX.jl?svg=true&branch=master
|
||||
[appveyor_url]: https://ci.appveyor.com/project/bramtayl/bibtex-jl
|
||||
|
||||
[codecov_badge]: http://codecov.io/github/bramtayl/BibTeX.jl/coverage.svg?branch=master
|
||||
[codecov_url]: http://codecov.io/github/bramtayl/BibTeX.jl?branch=master
|
||||
|
||||
[documenter_stable]: https://bramtayl.github.io/BibTeX.jl/stable
|
||||
[documenter_latest]: https://bramtayl.github.io/BibTeX.jl/latest
|
26
appveyor.yml
26
appveyor.yml
|
@ -1,26 +0,0 @@
|
|||
environment:
|
||||
matrix:
|
||||
- JULIAVERSION: "julialang/bin/winnt/x86/0.6/julia-0.6-latest-win32.exe"
|
||||
- JULIAVERSION: "julialang/bin/winnt/x64/0.6/julia-0.6-latest-win64.exe"
|
||||
- JULIAVERSION: "julianightlies/bin/winnt/x86/julia-latest-win32.exe"
|
||||
- JULIAVERSION: "julianightlies/bin/winnt/x64/julia-latest-win64.exe"
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /release-.*/
|
||||
notifications:
|
||||
- provider: Email
|
||||
on_build_success: false
|
||||
on_build_failure: false
|
||||
on_build_status_changed: false
|
||||
install:
|
||||
- ps: (new-object net.webclient).DownloadFile(
|
||||
$("http://s3.amazonaws.com/"+$env:JULIAVERSION),
|
||||
"C:\projects\julia-binary.exe")
|
||||
- C:\projects\julia-binary.exe /S /D=C:\projects\julia
|
||||
build_script:
|
||||
- IF EXIST .git\shallow (git fetch --unshallow)
|
||||
- C:\projects\julia\bin\julia -e "versioninfo();
|
||||
Pkg.clone(pwd(), \"BibTeX\"); Pkg.build(\"BibTeX\")"
|
||||
test_script:
|
||||
- C:\projects\julia\bin\julia -e "Pkg.test(\"BibTeX\")"
|
|
@ -1,2 +0,0 @@
|
|||
build/
|
||||
site/
|
|
@ -1,8 +0,0 @@
|
|||
import Documenter
|
||||
|
||||
Documenter.deploydocs(
|
||||
repo = "github.com/bramtayl/BibTeX.jl.git",
|
||||
target = "build",
|
||||
deps = nothing,
|
||||
make = nothing
|
||||
)
|
|
@ -1,8 +0,0 @@
|
|||
# BibTeX.jl
|
||||
|
||||
```@index
|
||||
```
|
||||
|
||||
```@autodocs
|
||||
Modules = [BibTeX]
|
||||
```
|
1674
example/examples.bib
1674
example/examples.bib
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,63 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16.5mm"
|
||||
height="8.6603003mm"
|
||||
viewBox="0 0 58.464567 30.686103"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="arrow.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11.2"
|
||||
inkscape:cx="14.209234"
|
||||
inkscape:cy="29.780479"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1053"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1021.6761)">
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 0,1021.6761 35.433071,0 -17.716536,30.6861 z"
|
||||
id="path4140"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
|
@ -0,0 +1,541 @@
|
|||
/*
|
||||
* The default CSS style for Documenter.jl generated sites
|
||||
*
|
||||
* Heavily inspired by the Julia Sphinx theme
|
||||
* https://github.com/JuliaLang/JuliaDoc
|
||||
* which extends the sphinx_rtd_theme
|
||||
* https://github.com/snide/sphinx_rtd_theme
|
||||
*
|
||||
* Part of Documenter.jl
|
||||
* https://github.com/JuliaDocs/Documenter.jl
|
||||
*
|
||||
* License: MIT
|
||||
*/
|
||||
|
||||
/* fonts */
|
||||
body, input {
|
||||
font-family: 'Lato', 'Helvetica Neue', Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
color: #222;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
pre, code {
|
||||
font-family: 'Roboto Mono', Monaco, courier, monospace;
|
||||
font-size: 0.90em;
|
||||
}
|
||||
|
||||
pre code {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #2980b9;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #3091d1;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #9b59b6;
|
||||
}
|
||||
|
||||
body {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
h1 { font-size: 1.75em; }
|
||||
h2 { font-size: 1.50em; }
|
||||
h3 { font-size: 1.25em; }
|
||||
h4 { font-size: 1.15em; }
|
||||
h5 { font-size: 1.10em; }
|
||||
h6 { font-size: 1em; }
|
||||
|
||||
h4, h5, h6 {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
th, td {
|
||||
border: 1px solid #e1e4e5;
|
||||
padding: 0.5em 1em;
|
||||
}
|
||||
|
||||
th {
|
||||
border-bottom-width: 2px;
|
||||
}
|
||||
|
||||
tr:nth-child(even) {
|
||||
background-color: #f3f6f6;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
border-top: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
/* Inline code and code blocks */
|
||||
|
||||
code {
|
||||
padding: 0.1em;
|
||||
background-color: rgba(0,0,0,.04);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: #f5f5f5;
|
||||
border: 1px solid #dddddd;
|
||||
border-radius: 3px;
|
||||
padding: 0.5em;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
pre code {
|
||||
padding: 0;
|
||||
background-color: initial;
|
||||
}
|
||||
|
||||
/* Headers in admonitions and docstrings */
|
||||
.admonition h1,
|
||||
article section.docstring h1 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
.admonition h2,
|
||||
article section.docstring h2 {
|
||||
font-size: 1.10em;
|
||||
}
|
||||
|
||||
.admonition h3,
|
||||
.admonition h4,
|
||||
.admonition h5,
|
||||
.admonition h6,
|
||||
article section.docstring h3,
|
||||
article section.docstring h4,
|
||||
article section.docstring h5,
|
||||
article section.docstring h6 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* Navigation */
|
||||
nav.toc {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 20em;
|
||||
overflow-y: auto;
|
||||
padding: 1em 0;
|
||||
background-color: #fcfcfc;
|
||||
box-shadow: inset -14px 0px 5px -12px rgb(210,210,210);
|
||||
}
|
||||
|
||||
nav.toc .logo {
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
max-height: 6em;
|
||||
max-width: 18em;
|
||||
}
|
||||
|
||||
nav.toc h1 {
|
||||
text-align: center;
|
||||
margin-top: .57em;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
nav.toc select {
|
||||
display: block;
|
||||
height: 2em;
|
||||
padding: 0 1.6em 0 1em;
|
||||
min-width: 7em;
|
||||
max-width: 90%;
|
||||
max-width: calc(100% - 5em);
|
||||
margin: 0 auto;
|
||||
font-size: .83em;
|
||||
border: 1px solid #c9c9c9;
|
||||
border-radius: 1em;
|
||||
|
||||
/* TODO: doesn't seem to be centered on Safari */
|
||||
text-align: center;
|
||||
text-align-last: center;
|
||||
|
||||
appearance: none;
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
|
||||
background: white url("arrow.svg");
|
||||
background-size: 1.155em;
|
||||
background-repeat: no-repeat;
|
||||
background-position: right;
|
||||
}
|
||||
|
||||
nav.toc select:hover {
|
||||
border: 1px solid #a0a0a0;
|
||||
}
|
||||
|
||||
nav.toc select option {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
nav.toc input {
|
||||
display: block;
|
||||
height: 2em;
|
||||
width: 90%;
|
||||
width: calc(100% - 5em);
|
||||
margin: 1.2em auto;
|
||||
padding: 0 1em;
|
||||
border: 1px solid #c9c9c9;
|
||||
border-radius: 1em;
|
||||
font-size: .83em;
|
||||
}
|
||||
|
||||
nav.toc > ul * {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
nav.toc ul {
|
||||
color: #404040;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
nav.toc ul .toctext {
|
||||
color: inherit;
|
||||
display: block;
|
||||
}
|
||||
|
||||
nav.toc ul a:hover {
|
||||
color: #fcfcfc;
|
||||
background-color: #4e4a4a;
|
||||
}
|
||||
|
||||
nav.toc ul.internal a {
|
||||
color: inherit;
|
||||
display: block;
|
||||
}
|
||||
|
||||
nav.toc ul.internal a:hover {
|
||||
background-color: #d6d6d6;
|
||||
}
|
||||
|
||||
nav.toc ul.internal {
|
||||
background-color: #e3e3e3;
|
||||
box-shadow: inset -14px 0px 5px -12px rgb(210,210,210);
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
nav.toc ul.internal li.toplevel {
|
||||
border-top: 1px solid #c9c9c9;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
nav.toc ul.internal li.toplevel:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
nav.toc .toctext {
|
||||
padding-top: 0.3em;
|
||||
padding-bottom: 0.3em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
nav.toc ul .toctext {
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
nav.toc ul ul .toctext {
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
nav.toc ul ul ul .toctext {
|
||||
padding-left: 3em;
|
||||
}
|
||||
|
||||
nav.toc li.current > .toctext {
|
||||
border-top: 1px solid #c9c9c9;
|
||||
border-bottom: 1px solid #c9c9c9;
|
||||
color: #404040;
|
||||
font-weight: bold;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
article {
|
||||
margin-left: 20em;
|
||||
min-width: 20em;
|
||||
max-width: 48em;
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
article > header {}
|
||||
|
||||
article > header div#topbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
article > header nav ul {
|
||||
display: inline-block;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
article > header nav li {
|
||||
display: inline-block;
|
||||
padding-right: 0.2em;
|
||||
}
|
||||
|
||||
article > header nav li:before {
|
||||
content: "»";
|
||||
padding-right: 0.2em;
|
||||
}
|
||||
|
||||
article > header .edit-page {
|
||||
float: right;
|
||||
}
|
||||
|
||||
article > footer {}
|
||||
|
||||
article > footer a.prev {
|
||||
float: left;
|
||||
}
|
||||
article > footer a.next {
|
||||
float: right;
|
||||
}
|
||||
|
||||
article > footer a .direction:after {
|
||||
content: ": ";
|
||||
}
|
||||
|
||||
article hr {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
article section.docstring {
|
||||
border: 1px solid #ddd;
|
||||
margin: 0.5em 0;
|
||||
padding: 0.5em;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
article section.docstring .docstring-header {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
article section.docstring .docstring-binding {
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
article section.docstring .docstring-category {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
article section.docstring a.source-link {
|
||||
float: left;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.nav-anchor,
|
||||
.nav-anchor:hover,
|
||||
.nav-anchor:visited {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/*
|
||||
* Admonitions
|
||||
*
|
||||
* Colors (title, body)
|
||||
* warning: #f0b37e #ffedcc (orange)
|
||||
* note: #6ab0de #e7f2fa (blue)
|
||||
* tip: #1abc9c #dbfaf4 (green)
|
||||
*/
|
||||
.admonition {
|
||||
border-radius: 3px;
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
|
||||
.admonition-title {
|
||||
border-radius: 3px 3px 0 0;
|
||||
background-color: #9b9b9b;
|
||||
padding: 0.15em 0.5em;
|
||||
}
|
||||
|
||||
.admonition-text {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.admonition-text > :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.admonition-text > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.admonition > .admonition-title:before {
|
||||
font-family: "FontAwesome";
|
||||
margin-right: 5px;
|
||||
content: "\f06a";
|
||||
}
|
||||
|
||||
.admonition.warning > .admonition-title {
|
||||
background-color: #f0b37e;
|
||||
}
|
||||
|
||||
.admonition.warning {
|
||||
background-color: #ffedcc;
|
||||
}
|
||||
|
||||
.admonition.note > .admonition-title {
|
||||
background-color: #6ab0de;
|
||||
}
|
||||
|
||||
.admonition.note {
|
||||
background-color: #e7f2fa;
|
||||
}
|
||||
|
||||
.admonition.tip > .admonition-title {
|
||||
background-color: #1abc9c;
|
||||
}
|
||||
|
||||
.admonition.tip {
|
||||
background-color: #dbfaf4;
|
||||
}
|
||||
|
||||
|
||||
/* footnotes */
|
||||
.footnote {
|
||||
padding-left: 0.8em;
|
||||
border-left: 2px solid #ccc;
|
||||
}
|
||||
|
||||
/* Search page */
|
||||
#search-results .category {
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
#search-results .category:before {
|
||||
content: " ";
|
||||
}
|
||||
|
||||
/* Overriding the <code> block style of highligh.js.
|
||||
* We have to override the padding and the background-color, since we style this
|
||||
* part ourselves. Specifically, we style the <pre> surrounding the <code>, while
|
||||
* highlight.js applies the .hljs style directly to the <code> tag.
|
||||
*/
|
||||
.hljs {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 768px) {
|
||||
nav.toc {
|
||||
position: fixed;
|
||||
overflow-y: scroll;
|
||||
width: 16em;
|
||||
left: -16em;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
-webkit-transition-property: left; /* Safari */
|
||||
-webkit-transition-duration: 0.3s; /* Safari */
|
||||
transition-property: left;
|
||||
transition-duration: 0.3s;
|
||||
-webkit-transition-timing-function: ease-out; /* Safari */
|
||||
transition-timing-function: ease-out;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
nav.toc.show {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
article {
|
||||
margin-left: 0;
|
||||
padding: 3em 0.9em 0 0.9em; /* top right bottom left */
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
article > header {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
article > header nav, hr {
|
||||
display: none;
|
||||
}
|
||||
|
||||
article > header div#topbar {
|
||||
display: block; /* is mobile */
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 1.5em;
|
||||
padding-top: 1em;
|
||||
padding-bottom: 1em;
|
||||
background-color: #fcfcfc;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.26);
|
||||
top: 0;
|
||||
-webkit-transition-property: top; /* Safari */
|
||||
-webkit-transition-duration: 0.3s; /* Safari */
|
||||
transition-property: top;
|
||||
transition-duration: 0.3s;
|
||||
}
|
||||
|
||||
article > header div#topbar.headroom--unpinned.headroom--not-top.headroom--not-bottom {
|
||||
top: -4em;
|
||||
-webkit-transition-property: top; /* Safari */
|
||||
-webkit-transition-duration: 0.7s; /* Safari */
|
||||
transition-property: top;
|
||||
transition-duration: 0.7s;
|
||||
}
|
||||
|
||||
article > header div#topbar span {
|
||||
position: fixed;
|
||||
width: 80%;
|
||||
height: 1.5em;
|
||||
margin-top: -0.1em;
|
||||
margin-left: 0.9em;
|
||||
font-size: 1.2em;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
article > header div#topbar a.fa-bars {
|
||||
float: right;
|
||||
padding: 0.6em;
|
||||
margin-top: -0.6em;
|
||||
margin-right: 0.3em;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
article > header div#topbar a.fa-bars:visited {
|
||||
color: #3091d1;
|
||||
}
|
||||
|
||||
article table {
|
||||
overflow-x: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
article div.MathJax_Display {
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
article span.MathJax {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 320px) {
|
||||
body {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Part of Documenter.jl
|
||||
* https://github.com/JuliaDocs/Documenter.jl
|
||||
*
|
||||
* License: MIT
|
||||
*/
|
||||
|
||||
requirejs.config({
|
||||
paths: {
|
||||
'jquery': 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min',
|
||||
'jqueryui': 'https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.0/jquery-ui.min',
|
||||
'headroom': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.9.3/headroom.min',
|
||||
'mathjax': 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS_HTML',
|
||||
'highlight': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min',
|
||||
'highlight-julia': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/julia.min',
|
||||
'highlight-julia-repl': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/julia-repl.min',
|
||||
},
|
||||
shim: {
|
||||
'mathjax' : {
|
||||
exports: "MathJax"
|
||||
},
|
||||
'highlight-julia': ['highlight'],
|
||||
'highlight-julia-repl': ['highlight'],
|
||||
}
|
||||
});
|
||||
|
||||
// Load MathJax
|
||||
require(['mathjax'], function(MathJax) {
|
||||
MathJax.Hub.Config({
|
||||
"tex2jax": {
|
||||
inlineMath: [['$','$'], ['\\(','\\)']],
|
||||
processEscapes: true
|
||||
}
|
||||
});
|
||||
MathJax.Hub.Config({
|
||||
config: ["MMLorHTML.js"],
|
||||
jax: [
|
||||
"input/TeX",
|
||||
"output/HTML-CSS",
|
||||
"output/NativeMML"
|
||||
],
|
||||
extensions: [
|
||||
"MathMenu.js",
|
||||
"MathZoom.js",
|
||||
"TeX/AMSmath.js",
|
||||
"TeX/AMSsymbols.js",
|
||||
"TeX/autobold.js",
|
||||
"TeX/autoload-all.js"
|
||||
]
|
||||
});
|
||||
MathJax.Hub.Config({
|
||||
TeX: { equationNumbers: { autoNumber: "AMS" } }
|
||||
});
|
||||
})
|
||||
|
||||
require(['jquery', 'highlight', 'highlight-julia', 'highlight-julia-repl'], function($, hljs) {
|
||||
$(document).ready(function() {
|
||||
hljs.initHighlighting();
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
// update the version selector with info from the siteinfo.js and ../versions.js files
|
||||
require(['jquery'], function($) {
|
||||
$(document).ready(function() {
|
||||
var version_selector = $("#version-selector");
|
||||
|
||||
// add the current version to the selector based on siteinfo.js, but only if the selector is empty
|
||||
if (typeof DOCUMENTER_CURRENT_VERSION !== 'undefined' && $('#version-selector > option').length == 0) {
|
||||
var option = $("<option value='#' selected='selected'>" + DOCUMENTER_CURRENT_VERSION + "</option>");
|
||||
version_selector.append(option);
|
||||
}
|
||||
|
||||
if (typeof DOC_VERSIONS !== 'undefined') {
|
||||
var existing_versions = $('#version-selector > option');
|
||||
var existing_versions_texts = existing_versions.map(function(i,x){return x.text});
|
||||
DOC_VERSIONS.forEach(function(each) {
|
||||
var version_url = documenterBaseURL + "/../" + each;
|
||||
var existing_id = $.inArray(each, existing_versions_texts);
|
||||
// if not already in the version selector, add it as a new option,
|
||||
// otherwise update the old option with the URL and enable it
|
||||
if (existing_id == -1) {
|
||||
var option = $("<option value='" + version_url + "'>" + each + "</option>");
|
||||
version_selector.append(option);
|
||||
} else {
|
||||
var option = existing_versions[existing_id];
|
||||
option.value = version_url;
|
||||
option.disabled = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// only show the version selector if the selector has been populated
|
||||
if ($('#version-selector > option').length > 0) {
|
||||
version_selector.css("visibility", "visible");
|
||||
}
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
// mobile
|
||||
require(['jquery', 'headroom'], function($, Headroom) {
|
||||
$(document).ready(function() {
|
||||
var navtoc = $("nav.toc");
|
||||
$("nav.toc li.current a.toctext").click(function() {
|
||||
navtoc.toggleClass('show');
|
||||
});
|
||||
$("article > header div#topbar a.fa-bars").click(function(ev) {
|
||||
ev.preventDefault();
|
||||
navtoc.toggleClass('show');
|
||||
if (navtoc.hasClass('show')) {
|
||||
var title = $("article > header div#topbar span").text();
|
||||
$("nav.toc ul li a:contains('" + title + "')").focus();
|
||||
}
|
||||
});
|
||||
$("article#docs").bind('click', function(ev) {
|
||||
if ($(ev.target).is('div#topbar a.fa-bars')) {
|
||||
return;
|
||||
}
|
||||
if (navtoc.hasClass('show')) {
|
||||
navtoc.removeClass('show');
|
||||
}
|
||||
});
|
||||
if ($("article > header div#topbar").css('display') == 'block') {
|
||||
var headroom = new Headroom(document.querySelector("article > header div#topbar"), {"tolerance": {"up": 10, "down": 10}});
|
||||
headroom.init();
|
||||
}
|
||||
})
|
||||
})
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Part of Documenter.jl
|
||||
* https://github.com/JuliaDocs/Documenter.jl
|
||||
*
|
||||
* License: MIT
|
||||
*/
|
||||
|
||||
// parseUri 1.2.2
|
||||
// (c) Steven Levithan <stevenlevithan.com>
|
||||
// MIT License
|
||||
function parseUri (str) {
|
||||
var o = parseUri.options,
|
||||
m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
|
||||
uri = {},
|
||||
i = 14;
|
||||
|
||||
while (i--) uri[o.key[i]] = m[i] || "";
|
||||
|
||||
uri[o.q.name] = {};
|
||||
uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
|
||||
if ($1) uri[o.q.name][$1] = $2;
|
||||
});
|
||||
|
||||
return uri;
|
||||
};
|
||||
parseUri.options = {
|
||||
strictMode: false,
|
||||
key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
|
||||
q: {
|
||||
name: "queryKey",
|
||||
parser: /(?:^|&)([^&=]*)=?([^&]*)/g
|
||||
},
|
||||
parser: {
|
||||
strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
|
||||
loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
|
||||
}
|
||||
};
|
||||
|
||||
requirejs.config({
|
||||
paths: {
|
||||
'jquery': 'https://code.jquery.com/jquery-3.1.0.js?',
|
||||
'lunr': 'https://cdnjs.cloudflare.com/ajax/libs/lunr.js/0.7.1/lunr.min',
|
||||
}
|
||||
});
|
||||
|
||||
var currentScript = document.currentScript;
|
||||
|
||||
require(["jquery", "lunr"], function($, lunr) {
|
||||
var index = lunr(function () {
|
||||
this.ref('location')
|
||||
this.field('title', {boost: 10})
|
||||
this.field('text')
|
||||
})
|
||||
var store = {}
|
||||
|
||||
documenterSearchIndex['docs'].forEach(function(e) {
|
||||
index.add(e)
|
||||
store[e.location] = e
|
||||
})
|
||||
|
||||
$(function(){
|
||||
function update_search(query) {
|
||||
results = index.search(query)
|
||||
$('#search-info').text("Number of results: " + results.length)
|
||||
$('#search-results').empty()
|
||||
results.forEach(function(result) {
|
||||
data = store[result.ref]
|
||||
link = $('<a>')
|
||||
link.text(data.title)
|
||||
link.attr('href', documenterBaseURL+'/'+result.ref)
|
||||
cat = $('<span class="category">('+data.category+')</span>')
|
||||
li = $('<li>').append(link).append(cat)
|
||||
$('#search-results').append(li)
|
||||
})
|
||||
}
|
||||
|
||||
function update_search_box() {
|
||||
query = $('#search-query').val()
|
||||
update_search(query)
|
||||
}
|
||||
|
||||
$('#search-query').keyup(update_search_box)
|
||||
$('#search-query').change(update_search_box)
|
||||
|
||||
search_query = parseUri(window.location).queryKey["q"]
|
||||
if(search_query !== undefined) {
|
||||
$("#search-query").val(search_query)
|
||||
}
|
||||
update_search_box();
|
||||
})
|
||||
})
|
|
@ -0,0 +1,54 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Home · BibTeX.jl</title><link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/4.2.0/normalize.min.css" rel="stylesheet" type="text/css"/><link href="https://fonts.googleapis.com/css?family=Lato|Roboto+Mono" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css" rel="stylesheet" type="text/css"/><script>documenterBaseURL="."</script><script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.2.0/require.min.js" data-main="assets/documenter.js"></script><script src="siteinfo.js"></script><script src="../versions.js"></script><link href="assets/documenter.css" rel="stylesheet" type="text/css"/></head><body><nav class="toc"><h1>BibTeX.jl</h1><select id="version-selector" onChange="window.location.href=this.value" style="visibility: hidden"></select><form class="search" action="search.html"><input id="search-query" name="q" type="text" placeholder="Search docs"/></form><ul><li class="current"><a class="toctext" href="index.html">Home</a><ul class="internal"></ul></li></ul></nav><article id="docs"><header><nav><ul><li><a href="index.html">Home</a></li></ul><a class="edit-page" href="https://github.com/bramtayl/BibTeX.jl/tree/673e30ce1f3bcd42b4f9f5735b49f13fa6f4037f/docs/src/index.md"><span class="fa"></span> Edit on GitHub</a></nav><hr/><div id="topbar"><span>Home</span><a class="fa fa-bars" href="#"></a></div></header><h1><a class="nav-anchor" id="BibTeX.jl-1" href="#BibTeX.jl-1">BibTeX.jl</a></h1><ul><li><a href="index.html#BibTeX.Bibliography-Tuple{String}"><code>BibTeX.Bibliography</code></a></li><li><a href="index.html#BibTeX.Citation"><code>BibTeX.Citation</code></a></li><li><a href="index.html#BibTeX.parse_bibtex-Tuple{Any}"><code>BibTeX.parse_bibtex</code></a></li><li><a href="index.html#BibTeX.search_latex_directive"><code>BibTeX.search_latex_directive</code></a></li><li><a href="index.html#BibTeX.simplify_latex"><code>BibTeX.simplify_latex</code></a></li><li><a href="index.html#BibTeX.strip_argument"><code>BibTeX.strip_argument</code></a></li></ul><section class="docstring"><div class="docstring-header"><a class="docstring-binding" id="BibTeX.Citation" href="#BibTeX.Citation"><code>BibTeX.Citation</code></a> — <span class="docstring-category">Type</span>.</div><div><pre><code class="language-none">Citation{S}(data::Dict{String,String})</code></pre><p>A bibliography item in a bibTeX database, based on a dictionary of strings to values. It is parameterized by a symbol <code>S</code> giving the type of the item (<code>:article</code> etcetera). A <code>b::Citation</code> supports <code>b[key]</code> access to retrieve the data and in general acts like a dictionary from <code>String</code> to <code>String</code>.</p></div><a class="source-link" target="_blank" href="https://github.com/bramtayl/BibTeX.jl/tree/673e30ce1f3bcd42b4f9f5735b49f13fa6f4037f/src/citation.jl#L1-L9">source</a><br/></section><section class="docstring"><div class="docstring-header"><a class="docstring-binding" id="BibTeX.Bibliography-Tuple{String}" href="#BibTeX.Bibliography-Tuple{String}"><code>BibTeX.Bibliography</code></a> — <span class="docstring-category">Method</span>.</div><div><pre><code class="language-none">Bibliography(bibtex::String)
|
||||
Bibliography(io::IO)</code></pre><p>Given a string (or IO stream) of bibtex-format bibliography data, parses the data and returns a <code>Dict</code>-like object <code>b::Bibliography</code> that behaves as a dictionary mapping strings to bibliography items <a href="index.html#BibTeX.Citation"><code>Citation</code></a>.</p></div><a class="source-link" target="_blank" href="https://github.com/bramtayl/BibTeX.jl/tree/673e30ce1f3bcd42b4f9f5735b49f13fa6f4037f/src/bibliography.jl#L6-L14">source</a><br/></section><section class="docstring"><div class="docstring-header"><a class="docstring-binding" id="BibTeX.parse_bibtex-Tuple{Any}" href="#BibTeX.parse_bibtex-Tuple{Any}"><code>BibTeX.parse_bibtex</code></a> — <span class="docstring-category">Method</span>.</div><div><pre><code class="language-none">parse_bibtex(text)</code></pre><p>This is a simple input parser for BibTex. I had trouble finding a standard specification, but I've included several features of real BibTex. Returns a preamble (or an empty string) and a dict of dicts.</p><pre><code class="language-julia-repl">julia> using BibTeX: parse_bibtex
|
||||
|
||||
julia> preamble, result = parse_bibtex("""
|
||||
@preamble{some instructions}
|
||||
@comment blah blah
|
||||
@string{short = long}
|
||||
@a{b,
|
||||
c = {{c} c},
|
||||
d = "d {"} d",
|
||||
e = f # short
|
||||
}
|
||||
""");
|
||||
|
||||
julia> preamble
|
||||
"some instructions"
|
||||
|
||||
julia> result["b"]["__type__"]
|
||||
"a"
|
||||
|
||||
julia> result["b"]["c"]
|
||||
"{c} c"
|
||||
|
||||
julia> result["b"]["d"]
|
||||
"d {\"} d"
|
||||
|
||||
julia> result["b"]["e"]
|
||||
"f short"
|
||||
|
||||
julia> parse_bibtex("@book")
|
||||
ERROR: Expected { on line 1
|
||||
[...]
|
||||
|
||||
julia> parse_bibtex("@book@")
|
||||
ERROR: Expected { on line 1
|
||||
[...]</code></pre><p>Repeated fields and keys are not allowed:</p><pre><code class="language-julia-repl">julia> using BibTeX: parse_bibtex
|
||||
|
||||
julia> parse_bibtex("""
|
||||
@book{abook,
|
||||
title = A}
|
||||
@book{abook,
|
||||
title = B}
|
||||
""")
|
||||
ERROR: Duplicated id abook on line 3
|
||||
[...]
|
||||
|
||||
julia> parse_bibtex("""
|
||||
@book{abook,
|
||||
title = A,
|
||||
title = B}
|
||||
""")
|
||||
ERROR: Duplicated field title on line 3
|
||||
[...]</code></pre></div><a class="source-link" target="_blank" href="https://github.com/bramtayl/BibTeX.jl/tree/673e30ce1f3bcd42b4f9f5735b49f13fa6f4037f/src/parser.jl#L120-L187">source</a><br/></section><section class="docstring"><div class="docstring-header"><a class="docstring-binding" id="BibTeX.search_latex_directive" href="#BibTeX.search_latex_directive"><code>BibTeX.search_latex_directive</code></a> — <span class="docstring-category">Function</span>.</div><div><pre><code class="language-none">search_latex_directive(astring, start_position = 1, inbrace=false)</code></pre><p>Search for a LaTeX directive \directive{argument} or similar in <code>string</code>, returning <code>(start_position, directive_end, argument_end)</code> such that <code>string[start_position:directive_end]</code> gives <code>\directive</code> and <code>string[directive_end+1:argument_end]</code> gives <code>{argument}</code>. Use <a href="index.html#BibTeX.strip_argument"><code>strip_argument</code></a> to remove surrounding braces and whitespace from the <code>argument</code>.</p></div><a class="source-link" target="_blank" href="https://github.com/bramtayl/BibTeX.jl/tree/673e30ce1f3bcd42b4f9f5735b49f13fa6f4037f/src/latex.jl#L22-L29">source</a><br/></section><section class="docstring"><div class="docstring-header"><a class="docstring-binding" id="BibTeX.simplify_latex" href="#BibTeX.simplify_latex"><code>BibTeX.simplify_latex</code></a> — <span class="docstring-category">Function</span>.</div><div><pre><code class="language-none">simplify_latex(astring, extra_directives)</code></pre><p>Simplify a LaTeX string <code>astring</code> into "plain text" if possible, stripping/converting known LaTeX directives in favor of e.g Unicode.</p><p><code>extra_directives</code> is a dictionary (<code>String=>String</code>) that maps LaTeX directives to replacements. It defaults to <code>BibTeX.text_directives</code>, which simply strips out things like bold and italics. Alternatively, you can pass <code>BibTeX.markdown_directives</code>, which uses Markdown syntax for such directives.</p></div><a class="source-link" target="_blank" href="https://github.com/bramtayl/BibTeX.jl/tree/673e30ce1f3bcd42b4f9f5735b49f13fa6f4037f/src/latex.jl#L349-L359">source</a><br/></section><section class="docstring"><div class="docstring-header"><a class="docstring-binding" id="BibTeX.strip_argument" href="#BibTeX.strip_argument"><code>BibTeX.strip_argument</code></a> — <span class="docstring-category">Function</span>.</div><div><pre><code class="language-none">strip_argument(astring, start_position = start(astring), end_position = endof(astring))</code></pre><p>Return the substring of <code>astring</code> corresponding to the argument from <code>start_position:end_position</code>, stripping leading/trailing whitespace and braces.</p></div><a class="source-link" target="_blank" href="https://github.com/bramtayl/BibTeX.jl/tree/673e30ce1f3bcd42b4f9f5735b49f13fa6f4037f/src/latex.jl#L139-L144">source</a><br/></section><footer><hr/></footer></article></body></html>
|
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Search · BibTeX.jl</title><link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/4.2.0/normalize.min.css" rel="stylesheet" type="text/css"/><link href="https://fonts.googleapis.com/css?family=Lato|Roboto+Mono" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css" rel="stylesheet" type="text/css"/><script>documenterBaseURL="."</script><script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.2.0/require.min.js" data-main="assets/documenter.js"></script><script src="siteinfo.js"></script><script src="../versions.js"></script><link href="assets/documenter.css" rel="stylesheet" type="text/css"/></head><body><nav class="toc"><h1>BibTeX.jl</h1><select id="version-selector" onChange="window.location.href=this.value" style="visibility: hidden"></select><form class="search" action="search.html"><input id="search-query" name="q" type="text" placeholder="Search docs"/></form><ul><li><a class="toctext" href="index.html">Home</a></li></ul></nav><article><header><nav><ul><li>Search</li></ul></nav><hr/><div id="topbar"><span>Search</span><a class="fa fa-bars" href="#"></a></div></header><h1>Search</h1><p id="search-info">Number of results: <span id="search-results-number">loading...</span></p><ul id="search-results"></ul></article></body><script src="search_index.js"></script><script src="assets/search.js"></script></html>
|
|
@ -0,0 +1,67 @@
|
|||
var documenterSearchIndex = {"docs": [
|
||||
|
||||
{
|
||||
"location": "index.html#",
|
||||
"page": "Home",
|
||||
"title": "Home",
|
||||
"category": "page",
|
||||
"text": ""
|
||||
},
|
||||
|
||||
{
|
||||
"location": "index.html#BibTeX.Citation",
|
||||
"page": "Home",
|
||||
"title": "BibTeX.Citation",
|
||||
"category": "Type",
|
||||
"text": "Citation{S}(data::Dict{String,String})\n\nA bibliography item in a bibTeX database, based on a dictionary of strings to values. It is parameterized by a symbol S giving the type of the item (:article etcetera). A b::Citation supports b[key] access to retrieve the data and in general acts like a dictionary from String to String.\n\n\n\n"
|
||||
},
|
||||
|
||||
{
|
||||
"location": "index.html#BibTeX.Bibliography-Tuple{String}",
|
||||
"page": "Home",
|
||||
"title": "BibTeX.Bibliography",
|
||||
"category": "Method",
|
||||
"text": "Bibliography(bibtex::String)\nBibliography(io::IO)\n\nGiven a string (or IO stream) of bibtex-format bibliography data, parses the data and returns a Dict-like object b::Bibliography that behaves as a dictionary mapping strings to bibliography items Citation.\n\n\n\n"
|
||||
},
|
||||
|
||||
{
|
||||
"location": "index.html#BibTeX.parse_bibtex-Tuple{Any}",
|
||||
"page": "Home",
|
||||
"title": "BibTeX.parse_bibtex",
|
||||
"category": "Method",
|
||||
"text": "parse_bibtex(text)\n\nThis is a simple input parser for BibTex. I had trouble finding a standard specification, but I've included several features of real BibTex. Returns a preamble (or an empty string) and a dict of dicts.\n\njulia> using BibTeX: parse_bibtex\n\njulia> preamble, result = parse_bibtex(\"\"\"\n @preamble{some instructions}\n @comment blah blah\n @string{short = long}\n @a{b,\n c = {{c} c},\n d = \"d {\"} d\",\n e = f # short\n }\n \"\"\");\n\njulia> preamble\n\"some instructions\"\n\njulia> result[\"b\"][\"__type__\"]\n\"a\"\n\njulia> result[\"b\"][\"c\"]\n\"{c} c\"\n\njulia> result[\"b\"][\"d\"]\n\"d {\\\"} d\"\n\njulia> result[\"b\"][\"e\"]\n\"f short\"\n\njulia> parse_bibtex(\"@book\")\nERROR: Expected { on line 1\n[...]\n\njulia> parse_bibtex(\"@book@\")\nERROR: Expected { on line 1\n[...]\n\nRepeated fields and keys are not allowed:\n\njulia> using BibTeX: parse_bibtex\n\njulia> parse_bibtex(\"\"\"\n @book{abook,\n title = A}\n @book{abook,\n title = B}\n \"\"\")\nERROR: Duplicated id abook on line 3\n[...]\n\njulia> parse_bibtex(\"\"\"\n @book{abook,\n title = A,\n title = B}\n \"\"\")\nERROR: Duplicated field title on line 3\n[...]\n\n\n\n"
|
||||
},
|
||||
|
||||
{
|
||||
"location": "index.html#BibTeX.search_latex_directive",
|
||||
"page": "Home",
|
||||
"title": "BibTeX.search_latex_directive",
|
||||
"category": "Function",
|
||||
"text": "search_latex_directive(astring, start_position = 1, inbrace=false)\n\nSearch for a LaTeX directive \\directive{argument} or similar in string, returning (start_position, directive_end, argument_end) such that string[start_position:directive_end] gives \\directive and string[directive_end+1:argument_end] gives {argument}. Use strip_argument to remove surrounding braces and whitespace from the argument.\n\n\n\n"
|
||||
},
|
||||
|
||||
{
|
||||
"location": "index.html#BibTeX.simplify_latex",
|
||||
"page": "Home",
|
||||
"title": "BibTeX.simplify_latex",
|
||||
"category": "Function",
|
||||
"text": "simplify_latex(astring, extra_directives)\n\nSimplify a LaTeX string astring into \"plain text\" if possible, stripping/converting known LaTeX directives in favor of e.g Unicode.\n\nextra_directives is a dictionary (String=>String) that maps LaTeX directives to replacements. It defaults to BibTeX.text_directives, which simply strips out things like bold and italics. Alternatively, you can pass BibTeX.markdown_directives, which uses Markdown syntax for such directives.\n\n\n\n"
|
||||
},
|
||||
|
||||
{
|
||||
"location": "index.html#BibTeX.strip_argument",
|
||||
"page": "Home",
|
||||
"title": "BibTeX.strip_argument",
|
||||
"category": "Function",
|
||||
"text": "strip_argument(astring, start_position = start(astring), end_position = endof(astring))\n\nReturn the substring of astring corresponding to the argument from start_position:end_position, stripping leading/trailing whitespace and braces.\n\n\n\n"
|
||||
},
|
||||
|
||||
{
|
||||
"location": "index.html#BibTeX.jl-1",
|
||||
"page": "Home",
|
||||
"title": "BibTeX.jl",
|
||||
"category": "section",
|
||||
"text": "Modules = [BibTeX]"
|
||||
},
|
||||
|
||||
]}
|
|
@ -0,0 +1 @@
|
|||
var DOCUMENTER_CURRENT_VERSION = "latest";
|
|
@ -1,9 +0,0 @@
|
|||
module BibTeX
|
||||
export Bibliography, Citation
|
||||
|
||||
include("parser.jl")
|
||||
include("citation.jl")
|
||||
include("bibliography.jl")
|
||||
include("latex.jl")
|
||||
|
||||
end
|
|
@ -1,39 +0,0 @@
|
|||
struct Bibliography <: Associative{String,Citation}
|
||||
preamble::String
|
||||
data::Dict{String,Citation}
|
||||
end
|
||||
|
||||
"""
|
||||
Bibliography(bibtex::String)
|
||||
Bibliography(io::IO)
|
||||
|
||||
Given a string (or IO stream) of bibtex-format bibliography data,
|
||||
parses the data and returns a `Dict`-like object `b::Bibliography` that
|
||||
behaves as a dictionary mapping strings to bibliography items
|
||||
[`Citation`](@ref).
|
||||
"""
|
||||
function Bibliography(bibtex::String)
|
||||
preamble, data = parse_bibtex(bibtex)
|
||||
return Bibliography(preamble, Dict(k=>Citation!(v) for (k,v) in data))
|
||||
end
|
||||
Bibliography(io::IO) = Bibliography(readstring(io))
|
||||
Base.open(::Type{Bibliography}, args...) = open(io -> Bibliography(io), args...)
|
||||
|
||||
Base.similar(b::Bibliography) = Bibliography("", Dict{String,Citation}())
|
||||
Base.rehash!(b::Bibliography, n=length(b.data)) = begin Base.rehash!(b.data, n); b; end
|
||||
Base.sizehint!(b::Bibliography, n) = begin sizehint!(b.data, n); b; end
|
||||
Base.empty!(b::Bibliography) = begin empty!(b.data); b; end
|
||||
Base.copy(b::Bibliography) = Bibliography(b.preamble, copy(b.data))
|
||||
|
||||
function Base.setindex!(b::Bibliography, v::Citation, k::AbstractString)
|
||||
b.data[String(k)] = v
|
||||
return b
|
||||
end
|
||||
Base.get(b::Bibliography, k::AbstractString, default) = get(b.data, String(k), default)
|
||||
|
||||
Base.start(b::Bibliography) = start(b.data)
|
||||
Base.done(b::Bibliography, i) = done(b.data, i)
|
||||
Base.next(b::Bibliography, i) = next(b.data, i)
|
||||
Base.length(b::Bibliography) = length(b.data)
|
||||
|
||||
# todo: add specialized Base.show methods for MIME"text/bibtex" etc.
|
|
@ -1,42 +0,0 @@
|
|||
"""
|
||||
Citation{S}(data::Dict{String,String})
|
||||
|
||||
A bibliography item in a bibTeX database, based on a dictionary of
|
||||
strings to values. It is parameterized by a symbol `S` giving the
|
||||
type of the item (`:article` etcetera). A `b::Citation` supports
|
||||
`b[key]` access to retrieve the data and in general acts like
|
||||
a dictionary from `String` to `String`.
|
||||
"""
|
||||
struct Citation{S} <: Associative{String,String}
|
||||
data::Dict{String,String}
|
||||
end
|
||||
Citation{S}() where {S} = Citation{S}(Dict{String,String}())
|
||||
|
||||
function Citation!(data::Dict{String,String})
|
||||
S = Symbol(pop!(data, "__type__"))
|
||||
return Citation{S}(data)
|
||||
end
|
||||
|
||||
Base.similar(b::Citation{S}) where {S} = Citation{S}(Dict{String,String}())
|
||||
Base.rehash!(b::Citation, n=length(b.data)) = begin Base.rehash!(b.data, n); b; end
|
||||
Base.sizehint!(b::Citation, n) = begin sizehint!(b.data, n); b; end
|
||||
Base.empty!(b::Citation) = begin empty!(b.data); b; end
|
||||
Base.copy(b::Citation{S}) where {S} = Citation{S}(copy(b.data))
|
||||
|
||||
Base.get(b::Citation, k::AbstractString, default) = get(b.data, String(k), default)
|
||||
Base.getindex(b::Citation, k::AbstractString) = getindex(b.data, String(k))
|
||||
function Base.setindex!(b::Citation, v::AbstractString, k::AbstractString)
|
||||
b.data[String(k)] = String(v)
|
||||
return b
|
||||
end
|
||||
|
||||
Base.start(b::Citation) = start(b.data)
|
||||
Base.done(b::Citation, i) = done(b.data, i)
|
||||
Base.next(b::Citation, i) = next(b.data, i)
|
||||
Base.length(b::Citation) = length(b.data)
|
||||
|
||||
function Base.show{S}(io::IO, b::Citation{S})
|
||||
print(io, "Citation{:$S}(", length(b), " entries)")
|
||||
end
|
||||
|
||||
# TODO: add Base.show text/plain and text/markdown for formatted citation
|
361
src/latex.jl
361
src/latex.jl
|
@ -1,361 +0,0 @@
|
|||
# conversion of LaTeX directives to plain text, markdown, etc.
|
||||
#
|
||||
# The basic idea is that we search for `\foo{argument}`, `{\foo argument}`,
|
||||
# or `{\foo{argument}}`, and look up `foo` in a dictionary of substitutions
|
||||
# like `\textit` -> `*#1*` where #1 is where the (first) argument is
|
||||
# substituted. Then we have separate dictionary entries for text/plain,
|
||||
# text/markdown, etcetera.
|
||||
|
||||
###########################################################################
|
||||
# parsing LaTeX directives:
|
||||
|
||||
const BACKSLASH = UInt8('\\')
|
||||
const BRACE_OPEN = UInt8('{')
|
||||
const BRACE_CLOSE = UInt8('}')
|
||||
const SPACE = UInt8(' ')
|
||||
const DOLLAR = UInt8('$')
|
||||
const CARET = UInt8('^')
|
||||
const UNDERSCORE = UInt8('_')
|
||||
is_letter(x::UInt8) = UInt8('a') ≤ x ≤ UInt8('z') || UInt8('A') ≤ x ≤ UInt8('Z')
|
||||
is_alphanumeric(x::UInt8) = UInt8('0') ≤ x ≤ UInt8('9') || is_letter(x)
|
||||
|
||||
"""
|
||||
search_latex_directive(astring, start_position = 1, inbrace=false)
|
||||
|
||||
Search for a LaTeX directive \\directive{argument} or similar in `string`, returning
|
||||
`(start_position, directive_end, argument_end)` such that `string[start_position:directive_end]` gives `\\directive` and `string[directive_end+1:argument_end]`
|
||||
gives `{argument}`. Use [`strip_argument`](@ref) to remove surrounding braces and whitespace
|
||||
from the `argument`.
|
||||
"""
|
||||
function search_latex_directive(astring, start_position = 1)
|
||||
string_length = sizeof(astring)
|
||||
if !(0 < start_position ≤ string_length)
|
||||
0, 0, 0
|
||||
else
|
||||
character_vector = Vector{UInt8}(astring)
|
||||
index = start_position
|
||||
all_spaces = true
|
||||
|
||||
# find \foo directive or {...}:
|
||||
character = UInt8(0)
|
||||
while index ≤ string_length
|
||||
character = character_vector[index]
|
||||
if (character == BACKSLASH || character == BRACE_OPEN || character == CARET || character == UNDERSCORE)
|
||||
break
|
||||
end
|
||||
if character != SPACE
|
||||
all_spaces = false
|
||||
end
|
||||
index += 1
|
||||
end
|
||||
if index ≤ string_length && character != BRACE_OPEN
|
||||
directive_start = index
|
||||
if character == BACKSLASH
|
||||
index += 2
|
||||
if index - 1 > string_length
|
||||
return 0,0,0
|
||||
end
|
||||
if is_letter(character_vector[index - 1])
|
||||
while index ≤ string_length && is_letter(character_vector[index])
|
||||
index += 1
|
||||
end
|
||||
end
|
||||
directive_end = index - 1
|
||||
else
|
||||
directive_end = directive_start # ^ or _
|
||||
index += 1
|
||||
end
|
||||
|
||||
# look for optional opening brace
|
||||
while index ≤ string_length && character_vector[index] == SPACE
|
||||
index += 1
|
||||
end
|
||||
if index > string_length
|
||||
return directive_start, directive_end, string_length
|
||||
end
|
||||
in_braces = character_vector[index] == BRACE_OPEN
|
||||
if !in_braces
|
||||
# search backwards from \foo to look for { \foo ...}
|
||||
backwards_index = directive_start - 1
|
||||
while backwards_index ≥ start_position && character_vector[backwards_index] == SPACE
|
||||
backwards_index -= 1
|
||||
end
|
||||
if backwards_index < start_position || character_vector[backwards_index] != BRACE_OPEN
|
||||
if character_vector[index] == BACKSLASH
|
||||
# argument is another latex directive
|
||||
inner_start_position, inner_directive_end, inner_argument_end = search_latex_directive(astring, index)
|
||||
return directive_start, directive_end, inner_argument_end
|
||||
elseif character != BACKSLASH
|
||||
# in an equation, token is a single char
|
||||
return directive_start, directive_end, index
|
||||
elseif all_spaces
|
||||
# if `\directive ...` was preceded only
|
||||
# by whitespace, then assume arguments
|
||||
# extend to the end of the string. This
|
||||
# happens when we recurse on `{\directive ...}`.
|
||||
return directive_start, directive_end, string_length
|
||||
else
|
||||
# argument is not in braces … get next token
|
||||
while index ≤ string_length && is_alphanumeric(character_vector[index])
|
||||
index += 1
|
||||
end
|
||||
return directive_start, directive_end, index - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
index += 1
|
||||
elseif index > string_length
|
||||
return 0, 0, 0
|
||||
else # { ... }
|
||||
directive_start = index
|
||||
directive_end = index - 1
|
||||
in_braces = true
|
||||
index += 1
|
||||
end
|
||||
|
||||
# search for end of argument (closing brace)
|
||||
number_of_braces = 1
|
||||
while index ≤ string_length
|
||||
character = character_vector[index]
|
||||
if character == BRACE_OPEN
|
||||
number_of_braces += 1
|
||||
elseif character == BRACE_CLOSE
|
||||
number_of_braces -= 1
|
||||
if number_of_braces == 0
|
||||
argument_end = if in_braces
|
||||
index
|
||||
else
|
||||
index - 1
|
||||
end
|
||||
return directive_start, directive_end, argument_end
|
||||
end
|
||||
end
|
||||
index += 1
|
||||
end
|
||||
directive_start, directive_end, string_length
|
||||
end
|
||||
end
|
||||
|
||||
"""
|
||||
strip_argument(astring, start_position = start(astring), end_position = endof(astring))
|
||||
|
||||
Return the substring of `astring` corresponding to the argument from `start_position:end_position`, stripping
|
||||
leading/trailing whitespace and braces.
|
||||
"""
|
||||
function strip_argument(astring, start_position = start(astring), end_position = endof(astring))
|
||||
if start_position > end_position
|
||||
SubString(astring, 1, 0)
|
||||
else
|
||||
string_length = endof(astring)
|
||||
if !(1 ≤ start_position ≤ string_length && 1 ≤ end_position ≤ string_length)
|
||||
throw(BoundsError())
|
||||
else
|
||||
character_vector = Vector{UInt8}(astring)
|
||||
if character_vector[end_position] == BRACE_CLOSE
|
||||
end_position -= 1 # omit brace
|
||||
while start_position ≤ end_position && character_vector[start_position] != BRACE_OPEN
|
||||
start_position += 1
|
||||
end
|
||||
if start_position > end_position
|
||||
error("malformed argument")
|
||||
end
|
||||
start_position += 1 # omit brace
|
||||
end
|
||||
while start_position ≤ end_position && character_vector[end_position] == SPACE
|
||||
end_position -= 1
|
||||
end
|
||||
while start_position ≤ end_position && character_vector[start_position] == SPACE
|
||||
start_position += 1
|
||||
end
|
||||
SubString(astring, start_position, end_position)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# to make replace work for LaTeX directives with our
|
||||
# custom search function, all we need to do is to define
|
||||
# a LaTeXDirectiveSearch type such that search(s, ::LaTeXDirectiveSearch, index)
|
||||
# returns the range of the directive
|
||||
struct LaTeXDirectiveSearch; end
|
||||
function Base.search(s::AbstractString, ::LaTeXDirectiveSearch, index)
|
||||
start_position, directive_end, argument_end = search_latex_directive(s, index)
|
||||
if start_position < index
|
||||
0:-1
|
||||
else
|
||||
start_position:argument_end
|
||||
end
|
||||
end
|
||||
###########################################################################
|
||||
|
||||
# Unicode substitutions for LaTeX directives
|
||||
const latex_unicode = Dict(
|
||||
# accent escapes like `\"u` for `ü`, from the list at
|
||||
# https://en.wikibooks.org/wiki/LaTeX/Special_Characters
|
||||
# converted to LaTeX characters (mostly combining marks)
|
||||
"\\`" => "#1\u0300",
|
||||
"\\'" => "#1\u0301",
|
||||
"\\^" => "#1\u0302",
|
||||
"\\\"" => "#1\u0308",
|
||||
"\\H" => "#1\u030b",
|
||||
"\\~" => "#1\u0303",
|
||||
"\\c" => "#1\u0327",
|
||||
"\\k" => "#1\u0328",
|
||||
"\\l" => "\u0142",
|
||||
"\\=" => "#1\u0304",
|
||||
"\\b" => "#1\u0331",
|
||||
"\\." => "#1\u0307",
|
||||
"\\d" => "#1\u0323",
|
||||
"\\r" => "#1\u030a",
|
||||
"\\u" => "#1\u0306",
|
||||
"\\v" => "#1\u030c",
|
||||
"\\t" => "#1\u0361", # fixme: u+0361 should go after first char in #1
|
||||
"\\o" => "\u00f8",
|
||||
"\\i" => "\u0131",
|
||||
"\\j" => "\u0237",
|
||||
|
||||
# other backslash escapes
|
||||
"\\\\" => "\\",
|
||||
"\\{" => "{", "\\}" => "}",
|
||||
"\\%" => "%",
|
||||
# "\\\$" => "\$" -- dollar signs will be unescaped in strip_dollars
|
||||
|
||||
# We parse {....} quoting as an empty directive:
|
||||
"" => "#1",
|
||||
|
||||
# many other substitutions can be found in
|
||||
# Base.REPLCompletions.latex_symbols
|
||||
)
|
||||
|
||||
# LaTeX directives converted to Markdown
|
||||
const markdown_directives = Dict(
|
||||
"\\emph" => "_#1_",
|
||||
"\\textit" => "_#1_",
|
||||
"\\it" => "_#1_",
|
||||
"\\mathit" => "_#1_",
|
||||
"\\textbf" => "**#1**",
|
||||
"\\bf" => "**#1**",
|
||||
"\\mathbf" => "**#1**",
|
||||
"\\texttt" => "`#1`",
|
||||
"\\mathrm" => "#1",
|
||||
"\\url" => "[#1](#1)",
|
||||
"\\sout" => "~~#1~~",
|
||||
"\\st" => "~~#1~~",
|
||||
"\\cancel" => "~~#1~~",
|
||||
)
|
||||
|
||||
# directives that are stripped when converting
|
||||
# to text/plain
|
||||
const text_directives = Dict(
|
||||
"\\emph" => "#1",
|
||||
"\\textit" => "#1",
|
||||
"\\it" => "#1",
|
||||
"\\mathit" => "#1",
|
||||
"\\textbf" => "#1",
|
||||
"\\bf" => "#1",
|
||||
"\\mathbf" => "#1",
|
||||
"\\texttt" => "#1",
|
||||
"\\mathrm" => "#1",
|
||||
"\\url" => "#1",
|
||||
)
|
||||
|
||||
# Unicode includes an incomplete set of super/subscript characters:
|
||||
const superscripts = Dict(
|
||||
'0'=>'⁰', '1'=>'¹', '2'=>'²', '3'=>'³', '4'=>'⁴', '5'=>'⁵', '6'=>'⁶', '7'=>'⁷', '8'=>'⁸', '9'=>'⁹',
|
||||
'a'=>'ᵃ', 'b'=>'ᵇ', 'c'=>'ᶜ', 'd'=>'ᵈ', 'e'=>'ᵉ', 'f'=>'ᶠ', 'g'=>'ᵍ', 'h'=>'ʰ',
|
||||
'i'=>'ⁱ', 'j'=>'ʲ', 'k'=>'ᵏ', 'l'=>'ˡ', 'm'=>'ᵐ', 'n'=>'ⁿ', 'o'=>'ᵒ', 'p'=>'ᵖ',
|
||||
'r'=>'ʳ', 's'=>'ˢ', 't'=>'ᵗ', 'u'=>'ᵘ', 'v'=>'ᵛ', 'w'=>'ʷ', 'x'=>'ˣ', 'y'=>'ʸ', 'z'=>'ᶻ',
|
||||
'A'=>'ᴬ', 'B'=>'ᴮ', 'C'=>'ᶜ', 'D'=>'ᴰ', 'E'=>'ᴱ', 'G'=>'ᴳ', 'H'=>'ᴴ', 'I'=>'ᴵ', 'J'=>'ᴶ',
|
||||
'K'=>'ᴷ', 'L'=>'ᴸ', 'M'=>'ᴹ', 'N'=>'ᴺ', 'O'=>'ᴼ', 'P'=>'ᴾ', 'R'=>'ᴿ', 'S'=>'ˢ', 'T'=>'ᵀ',
|
||||
'U'=>'ᵁ', 'V'=>'ⱽ', 'W'=>'ᵂ', 'β'=>'ᵝ', 'γ'=>'ᵞ', 'δ'=>'ᵟ', 'ψ'=>'ᵠ', 'χ'=>'ᵡ', 'Θ'=>'ᶿ',
|
||||
'+'=>'⁺', '-'=>'⁻', '='=>'⁼', '('=>'⁽', ')'=>'⁾', ' '=>' ', '∘'=>'°',
|
||||
)
|
||||
const subscripts = Dict(
|
||||
'0'=>'₀', '1'=>'₁', '2'=>'₂', '3'=>'₃', '4'=>'₄', '5'=>'₅', '6'=>'₆', '7'=>'₇', '8'=>'₈', '9'=>'₉',
|
||||
'a'=>'ₐ', 'e'=>'ₑ', 'h'=>'ₕ', 'i'=>'ᵢ', 'j'=>'ⱼ', 'k'=>'ₖ', 'l'=>'ₗ', 'm'=>'ₘ',
|
||||
'n'=>'ₙ', 'o'=>'ₒ', 'p'=>'ₚ', 'r'=>'ᵣ', 's'=>'ₛ', 't'=>'ₜ', 'u'=>'ᵤ', 'v'=>'ᵥ', 'x'=>'ₓ',
|
||||
'β'=>'ᵦ', 'γ'=>'ᵧ', 'ρ'=>'ᵨ', 'ψ'=>'ᵩ', 'χ'=>'ᵪ',
|
||||
'-'=>'₋', '+'=>'₊', '='=>'₌', '('=>'₍', ')'=>'₎', ' '=>' ',
|
||||
)
|
||||
|
||||
function replace_characters(astring, character_map)
|
||||
buffer = IOBuffer()
|
||||
for character in astring
|
||||
mapped_character = get(character_map, character, '\0')
|
||||
if mapped_character == '\0'
|
||||
return ""
|
||||
end
|
||||
print(buffer, mapped_character)
|
||||
end
|
||||
String(take!(buffer))
|
||||
end
|
||||
|
||||
# Given a (sub)string `s` that represents a LaTeX directive matched
|
||||
# by search_latex_directive, performs our Unicode substitutions and
|
||||
# also any additional substitutions given by extra_directives.
|
||||
function directive_substitution(astring, extra_directives)
|
||||
start_position, directive_end, argument_end = search_latex_directive(astring)
|
||||
string_length = endof(astring)
|
||||
directive = SubString(astring, start_position, directive_end)
|
||||
for dict in (extra_directives, latex_unicode, Base.REPLCompletions.latex_symbols)
|
||||
if haskey(dict, directive)
|
||||
substitution = dict[directive]
|
||||
if contains(substitution, "#1")
|
||||
argument = strip_argument(replace_directives(strip_argument(astring, directive_end + 1, string_length), extra_directives))
|
||||
return replace(substitution, "#1", argument)
|
||||
else
|
||||
argument = replace_directives(SubString(astring, directive_end+1, string_length), extra_directives)
|
||||
if strwidth(substitution) == 0 # \hat{...} etc: combining chars go after argument
|
||||
return string(strip_argument(argument), substitution)
|
||||
else
|
||||
return string(substitution, argument) # don't strip for 0-arg macros
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if directive == "^" || directive == "_" # super/subscripts
|
||||
argument = strip_argument(replace_directives(strip_argument(astring, directive_end + 1, string_length), extra_directives))
|
||||
dict = if directive == "^"
|
||||
superscripts
|
||||
else
|
||||
subscripts
|
||||
end
|
||||
substitution = replace_characters(argument, dict)
|
||||
if !isempty(substitution)
|
||||
return substitution
|
||||
end
|
||||
end
|
||||
astring # ignore unrecognized directives
|
||||
end
|
||||
|
||||
# replace all latex directives in `s` via `directive_substitution`
|
||||
replace_directives(astring, extra_directives) =
|
||||
replace(astring, LaTeXDirectiveSearch(), substitution -> directive_substitution(substitution, extra_directives))
|
||||
|
||||
# strip unescaped $ signs from s
|
||||
function strip_dollars(astring)
|
||||
buffer = IOBuffer()
|
||||
character_vector = Vector{UInt8}(astring)
|
||||
for index = 1:sizeof(astring)
|
||||
character = character_vector[index]
|
||||
if character == BACKSLASH && index < sizeof(astring) && character_vector[index + 1] == DOLLAR
|
||||
write(buffer, DOLLAR) # \$ -> $
|
||||
elseif character != DOLLAR
|
||||
write(buffer, character)
|
||||
end
|
||||
end
|
||||
return String(take!(buffer))
|
||||
end
|
||||
|
||||
"""
|
||||
simplify_latex(astring, extra_directives)
|
||||
|
||||
Simplify a LaTeX string `astring` into "plain text" if possible, stripping/converting
|
||||
known LaTeX directives in favor of e.g Unicode.
|
||||
|
||||
`extra_directives` is a dictionary (`String=>String`) that maps LaTeX directives
|
||||
to replacements. It defaults to `BibTeX.text_directives`, which simply strips
|
||||
out things like bold and italics. Alternatively, you can pass `BibTeX.markdown_directives`,
|
||||
which uses Markdown syntax for such directives.
|
||||
"""
|
||||
simplify_latex(astring, extra_directives = text_directives) =
|
||||
strip_dollars(replace_directives(astring, extra_directives))
|
218
src/parser.jl
218
src/parser.jl
|
@ -1,218 +0,0 @@
|
|||
mutable struct Parser{T}
|
||||
tokens::T
|
||||
substitutions::Dict{String, String}
|
||||
records::Dict{String, Dict{String, String}}
|
||||
line::Int
|
||||
bracket_counter::Int
|
||||
end
|
||||
|
||||
Base.eltype(p::Parser) = eltype(p.tokens)
|
||||
Base.one(p::Parser) = eltype(p)("")
|
||||
|
||||
Parser(tokens::T, substitutions, records, line, bracket_counter) where T =
|
||||
Parser{T}(tokens, substitutions, records, line, bracket_counter)
|
||||
|
||||
Parser(tokens) = Parser(tokens, Dict{String, String}(), Dict{String, Dict{String, String}}(), 1, 0)
|
||||
|
||||
parse_text(text) = matchall(r"[^\s\"#{}@,=\\]+|\s+|\"|#|{|}|@|,|=|\\", text) |> Parser
|
||||
|
||||
location(parser) = "on line $(parser.line)"
|
||||
|
||||
Base.isempty(p::Parser) = isempty(p.tokens)
|
||||
|
||||
next_token_default!(parser) =
|
||||
if isempty(parser.tokens)
|
||||
one(parser)
|
||||
else
|
||||
result = shift!(parser.tokens)
|
||||
parser.line = parser.line + count(x -> x == '\n', result)
|
||||
if all(isspace, result)
|
||||
eltype(parser)(" ")
|
||||
else
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
next_token_with_space!(parser, eol = "additional tokens") = begin
|
||||
result = next_token_default!(parser)
|
||||
if result == ""
|
||||
error("Expected $eol $(location(parser))")
|
||||
else
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
next_token!(parser, eol = "additional tokens") = begin
|
||||
result = next_token_with_space!(parser, eol)
|
||||
if all(isspace, result)
|
||||
next_token_with_space!(parser, eol)
|
||||
else
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
expect(parser, result, eol) =
|
||||
if result != eol
|
||||
error("Expected $eol $(location(parser))")
|
||||
end
|
||||
|
||||
expect!(parser, eol) =
|
||||
expect(parser, next_token!(parser, eol), eol)
|
||||
|
||||
token_and_counter!(parser, eol = "}") = begin
|
||||
token = next_token_with_space!(parser, eol)
|
||||
if token == "{"
|
||||
parser.bracket_counter += 1
|
||||
elseif token == "}"
|
||||
parser.bracket_counter -= 1
|
||||
end
|
||||
if parser.bracket_counter < 0
|
||||
error("} without corresponding { $(location(parser))")
|
||||
else
|
||||
token
|
||||
end
|
||||
end
|
||||
|
||||
value!(parser, values = eltype(parser)[]) = begin
|
||||
token = next_token!(parser)
|
||||
if token == "\""
|
||||
token = token_and_counter!(parser, "\"")
|
||||
while !(token == "\"" && parser.bracket_counter == 0)
|
||||
push!(values, token)
|
||||
token = token_and_counter!(parser, "\" or }")
|
||||
end
|
||||
elseif token == "{"
|
||||
parser.bracket_counter += 1
|
||||
token = token_and_counter!(parser)
|
||||
while parser.bracket_counter > 0
|
||||
push!(values, token)
|
||||
token = token_and_counter!(parser)
|
||||
end
|
||||
else
|
||||
push!(values, getkey(parser.substitutions, token, String(token) ) )
|
||||
end
|
||||
token = next_token!(parser, ", or }")
|
||||
if token == "#"
|
||||
push!(values, " ")
|
||||
value!(parser, values)
|
||||
else
|
||||
token, join(values)
|
||||
end
|
||||
end
|
||||
|
||||
field!(parser, dict) = begin
|
||||
token = ","
|
||||
while token == ","
|
||||
token = next_token!(parser, "a new entry or }")
|
||||
if token != "}"
|
||||
key = lowercase(token)
|
||||
if haskey(dict, key)
|
||||
error("Duplicated field $key $(location(parser))")
|
||||
else
|
||||
expect!(parser, "=")
|
||||
token, dict[key] = value!(parser)
|
||||
end
|
||||
end
|
||||
end
|
||||
expect(parser, token, "}")
|
||||
end
|
||||
|
||||
"""
|
||||
parse_bibtex(text)
|
||||
|
||||
This is a simple input parser for BibTex. I had trouble finding a standard
|
||||
specification, but I've included several features of real BibTex. Returns
|
||||
a preamble (or an empty string) and a dict of dicts.
|
||||
|
||||
```jldoctest
|
||||
julia> using BibTeX: parse_bibtex
|
||||
|
||||
julia> preamble, result = parse_bibtex(""\"
|
||||
@preamble{some instructions}
|
||||
@comment blah blah
|
||||
@string{short = long}
|
||||
@a{b,
|
||||
c = {{c} c},
|
||||
d = "d {"} d",
|
||||
e = f # short
|
||||
}
|
||||
""\");
|
||||
|
||||
julia> preamble
|
||||
"some instructions"
|
||||
|
||||
julia> result["b"]["__type__"]
|
||||
"a"
|
||||
|
||||
julia> result["b"]["c"]
|
||||
"{c} c"
|
||||
|
||||
julia> result["b"]["d"]
|
||||
"d {\\"} d"
|
||||
|
||||
julia> result["b"]["e"]
|
||||
"f short"
|
||||
|
||||
julia> parse_bibtex("@book")
|
||||
ERROR: Expected { on line 1
|
||||
[...]
|
||||
|
||||
julia> parse_bibtex("@book@")
|
||||
ERROR: Expected { on line 1
|
||||
[...]
|
||||
```
|
||||
|
||||
Repeated fields and keys are not allowed:
|
||||
|
||||
```jldoctest
|
||||
julia> using BibTeX: parse_bibtex
|
||||
|
||||
julia> parse_bibtex(""\"
|
||||
@book{abook,
|
||||
title = A}
|
||||
@book{abook,
|
||||
title = B}
|
||||
""\")
|
||||
ERROR: Duplicated id abook on line 3
|
||||
[...]
|
||||
|
||||
julia> parse_bibtex(""\"
|
||||
@book{abook,
|
||||
title = A,
|
||||
title = B}
|
||||
""\")
|
||||
ERROR: Duplicated field title on line 3
|
||||
[...]
|
||||
```
|
||||
"""
|
||||
parse_bibtex(text) = begin
|
||||
parser = parse_text(text)
|
||||
token = next_token_default!(parser)
|
||||
preamble = ""
|
||||
while token != ""
|
||||
if token == "@"
|
||||
record_type = lowercase(next_token!(parser))
|
||||
if record_type == "preamble"
|
||||
trash, preamble = value!(parser)
|
||||
elseif record_type != "comment"
|
||||
expect!(parser, "{")
|
||||
if record_type == "string"
|
||||
field!(parser, parser.substitutions)
|
||||
else
|
||||
id = next_token!(parser)
|
||||
records = parser.records
|
||||
if haskey(records, id)
|
||||
error("Duplicated id $id $(location(parser))")
|
||||
else
|
||||
dict = Dict("__type__" => record_type)
|
||||
expect!(parser, ",")
|
||||
field!(parser, dict)
|
||||
records[id] = dict
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
token = next_token_default!(parser)
|
||||
end
|
||||
preamble, parser.records
|
||||
end
|
|
@ -1 +0,0 @@
|
|||
Documenter
|
|
@ -1,6 +0,0 @@
|
|||
const file = joinpath((@__FILE__) |> dirname |> dirname, "example", "examples.bib") |> readstring
|
||||
|
||||
using BenchmarkTools
|
||||
using BibTeX
|
||||
|
||||
@benchmark BibTeX.parse_bibtex(file)
|
|
@ -1,58 +0,0 @@
|
|||
using BibTeX, Base.Test
|
||||
|
||||
base_file = dirname(dirname(@__FILE__))
|
||||
|
||||
import Documenter
|
||||
Documenter.makedocs(
|
||||
modules = [BibTeX],
|
||||
format = :html,
|
||||
sitename = "BibTeX.jl",
|
||||
root = joinpath(base_file, "docs"),
|
||||
pages = Any["Home" => "index.md"],
|
||||
strict = true,
|
||||
linkcheck = true,
|
||||
checkdocs = :exports,
|
||||
authors = "Brandon Taylor"
|
||||
)
|
||||
|
||||
@testset "examples.bib" begin
|
||||
# note: ".." does not work on windows
|
||||
b = open(Bibliography, joinpath(base_file, "example", "examples.bib"), "r")
|
||||
@test length(b) == 92
|
||||
@test (b["angenendt"]::Citation{:article})["date"] == "2002"
|
||||
end
|
||||
|
||||
@testset "small bib" begin
|
||||
b = Bibliography("""
|
||||
@article{foo, bar=baz}
|
||||
@book{bar, foobar=1}
|
||||
""")
|
||||
@test get(b, "foobar", nothing) === nothing
|
||||
@test get(b["foo"], "blah", nothing) === nothing
|
||||
|
||||
@test string(b["foo"]) == "Citation{:article}(1 entries)"
|
||||
|
||||
Base.rehash!(b)
|
||||
b2 = copy(b)
|
||||
@test length(b2) == length(b)
|
||||
@test isempty(sizehint!(empty!(b2),10))
|
||||
@test isempty(similar(b))
|
||||
b2["x"] = Citation{:foo}()
|
||||
b2["x"]["bar"] = "blah"
|
||||
@test length(b2) == length(b2["x"]) == 1
|
||||
@test b2["x"]["bar"] == "blah"
|
||||
@test get(b2["x"], "foo", nothing) === nothing
|
||||
@test collect(b2)[1][2] == b2["x"]
|
||||
@test collect(b2["x"])[1] == ("bar"=>"blah")
|
||||
Base.rehash!(b2["x"])
|
||||
x2 = copy(b2["x"])::Citation{:foo}
|
||||
@test length(x2) == 1
|
||||
@test isempty(similar(x2))
|
||||
@test isempty(sizehint!(empty!(x2),10))
|
||||
end
|
||||
|
||||
import BibTeX: simplify_latex, markdown_directives
|
||||
@testset "latex" begin
|
||||
@test simplify_latex(raw"foo \$$x_1x_2^\mathrm{3}$ \dot{\alpha} {quote} \% \{unquote\} \emph{bar \textbf{bold}} {\bf baz 2.0} {\^{u}}", markdown_directives) ==
|
||||
"foo \$x₁x₂³ α̇ quote % {unquote} _bar **bold**_ **baz 2.0** û"
|
||||
end
|
|
@ -0,0 +1,3 @@
|
|||
var DOC_VERSIONS = [
|
||||
"latest",
|
||||
];
|
Loading…
Reference in New Issue