36 |
Zotero Style Repository
38 |
Here you can find Citation Style Language 1.0.2 citation styles for use with Zotero and other CSL 1.0.2–compatible software. For more information on using CSL styles with Zotero, see the Zotero wiki .
39 |
40 |
41 |
42 |
43 |
Style Search
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
Format: Loading…
53 |
Fields: Loading…
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/include/data/previews.json:
--------------------------------------------------------------------------------
1 | {
2 | "items": [{
3 | "id": 3886,
4 | "type": "article-journal",
5 | "title": "An adaptable metric shapes perceptual space",
6 | "container-title": "Current Biology",
7 | "page": "1911-1915",
8 | "volume": "26",
9 | "issue": "14",
10 | "source": "www.cell.com",
11 | "URL": "http://www.cell.com/current-biology/abstract/S0960-9822(16)30544-9",
12 | "DOI": "10.1016/j.cub.2016.05.047",
13 | "ISSN": "0960-9822",
14 | "journalAbbreviation": "Curr. Biol.",
15 | "language": "en",
16 | "author": [{
17 | "family": "Hisakata",
18 | "given": "Rumi"
19 | }, {
20 | "family": "Nishida",
21 | "given": "Shin'ya"
22 | }, {
23 | "family": "Johnston",
24 | "given": "Alan"
25 | }],
26 | "issued": {
27 | "date-parts": [
28 | [
29 | "2016",
30 | 7,
31 | 25
32 | ]
33 | ]
34 | },
35 | "accessed": {
36 | "date-parts": [
37 | [
38 | "2016",
39 | 10,
40 | 3
41 | ]
42 | ]
43 | }
44 | }, {
45 | "id": 3884,
46 | "type": "post-weblog",
47 | "container-title": "Hyperbole and a Half",
48 | "title": "The Alot is Better Than You at Everything",
49 | "URL": "https://hyperboleandahalf.blogspot.com/2010/04/alot-is-better-than-you-at-everything.html",
50 | "author": [
51 | {
52 | "family": "Brosh",
53 | "given": "Allie"
54 | }
55 | ],
56 | "accessed": {
57 | "date-parts": [
58 | [
59 | "2018",
60 | 2,
61 | 6
62 | ]
63 | ]
64 | },
65 | "issued": {
66 | "date-parts": [
67 | [
68 | "2010",
69 | 4,
70 | 13
71 | ]
72 | ]
73 | }
74 | }, {
75 | "id": 3881,
76 | "type": "chapter",
77 | "title": "Structure databases",
78 | "container-title": "Bioinformatics",
79 | "collection-title": "Life Sciences Series",
80 | "publisher": "Wiley-Interscience",
81 | "publisher-place": "New York, NY",
82 | "page": "83-109",
83 | "edition": "2",
84 | "event-place": "New York, NY",
85 | "ISBN": "0471383910",
86 | "language": "en-US",
87 | "author": [{
88 | "family": "Hogue",
89 | "given": "Christopher W. V."
90 | }],
91 | "editor": [{
92 | "family": "Baxevanis",
93 | "given": "Andreas D."
94 | }, {
95 | "family": "Ouellette",
96 | "given": "B. F. Francis"
97 | }],
98 | "issued": {
99 | "date-parts": [
100 | [
101 | "2001"
102 | ]
103 | ]
104 | }
105 | }, {
106 | "id": 3877,
107 | "type": "book",
108 | "title": "Molecular cloning: a laboratory manual",
109 | "publisher": "CSHL Press",
110 | "publisher-place": "Cold Spring Harbor, NY",
111 | "number-of-pages": "999",
112 | "edition": "3",
113 | "event-place": "Cold Spring Harbor, NY",
114 | "ISBN": "0879695773",
115 | "shortTitle": "Molecular cloning",
116 | "language": "en-US",
117 | "author": [{
118 | "family": "Sambrook",
119 | "given": "Joe"
120 | }, {
121 | "family": "Russell",
122 | "given": "David William"
123 | }],
124 | "issued": {
125 | "date-parts": [
126 | [
127 | "2001",
128 | 1,
129 | 15
130 | ]
131 | ]
132 | }
133 | }],
134 | "citationClusters": [{
135 | "citationItems": [{
136 | "id": 3886
137 | }, {
138 | "id": 3884
139 | }, {
140 | "id": 3881
141 | }, {
142 | "id": 3877
143 | }],
144 | "properties": {
145 | "noteIndex": 1
146 | }
147 | }]
148 | }
149 |
--------------------------------------------------------------------------------
/htdocs/styles.php:
--------------------------------------------------------------------------------
1 | .
23 |
24 | ***** END LICENSE BLOCK *****
25 | */
26 |
27 | require('../include/config.inc.php');
28 | require('../include/static.inc.php');
29 | require('../include/Styles_Repo.inc.php');
30 |
31 | $uri = $_SERVER['REQUEST_URI'];
32 | // Strip query string
33 | $mainURI = preg_replace('/\?.*/', '', $uri);
34 |
35 | if (strpos($uri, '/styles/?s=Harvard/') !== false) {
36 | header("HTTP/1.1 400 Bad Request");
37 | echo "400 Bad Request";
38 | exit;
39 | }
40 |
41 | // Set $PATH_INFO
42 | if (isset($_SERVER['PATH_INFO'])) {
43 | $PATH_INFO = explode('/', substr($_SERVER['PATH_INFO'], 1));
44 | }
45 | if (!isset($PATH_INFO) || $PATH_INFO[0] == '') {
46 | $PATH_INFO = array();
47 | }
48 |
49 | // Single style
50 | if (isset($PATH_INFO[0])) {
51 | header('Access-Control-Allow-Origin: *');
52 | header('Access-Control-Allow-Headers: If-Modified-Since');
53 | header('Cache-Control: max-age=900');
54 |
55 | if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
56 | header("HTTP/1.1 200 OK");
57 | exit;
58 | }
59 |
60 | $name = $PATH_INFO[0];
61 | $dependent = !empty($_GET['dep']);
62 | $source = !empty($_GET['source']);
63 |
64 | if (!Styles_Repo::isValidName($name) || isset($PATH_INFO[1])) {
65 | header("HTTP/1.1 404 Not Found");
66 | exit;
67 | }
68 |
69 | $newName = Styles_Repo::getRenamedStyle($name);
70 | if ($newName && $name != $newName) {
71 | header("Location: $newName");
72 | exit;
73 | }
74 |
75 | $csl = Styles_Repo::getCode($name, $dependent);
76 | // Dependent flag is optional
77 | if ($csl) {
78 | $lastModified = Styles_Repo::getLastModified($name, false);
79 | }
80 | else {
81 | $csl = Styles_Repo::getCode($name, true);
82 | $lastModified = Styles_Repo::getLastModified($name, true);
83 | }
84 | if ((isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
85 | && $_SERVER['HTTP_IF_MODIFIED_SINCE'] == $lastModified)) {
86 | header("HTTP/1.1 304 Not Modified");
87 | exit;
88 | }
89 |
90 | // Single style
91 | if (!empty($csl)) {
92 | header("Last-Modified: " . $lastModified);
93 | if (!empty($source)) {
94 | header('Content-Type: text/xml');
95 | header("Content-Disposition: inline; filename=$name.csl");
96 | }
97 | else {
98 | header('Content-Type: application/vnd.citationstyles.style+xml');
99 | header("Content-Disposition: attachment; filename=$name.csl");
100 | }
101 | echo $csl;
102 | }
103 | // Style not found
104 | else {
105 | header("HTTP/1.0 404 Not Found");
106 | echo "Style not found";
107 | }
108 | exit;
109 | }
110 |
111 | // Styles list
112 | $searchString = isset($_GET['q']) ? $_GET['q'] : '';
113 | $client = !empty($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], "Zotero/") !== false;
114 | require("../views/index.phtml");
115 |
--------------------------------------------------------------------------------
/frontend/scss/style.scss:
--------------------------------------------------------------------------------
1 | $color: #000;
2 |
3 | $accent-color: #999;
4 | $accent-background-color: #f0f0f0;
5 |
6 | $popover-color: #000;
7 | $popover-background-color: #fff;
8 | $popover-box-shadow-color: rgba(0, 0, 0, .15);
9 |
10 | $view-source-button-color: #000;
11 |
12 | $search-pane-button-color: $color;
13 | $search-pane-button-border-color: $accent-color;
14 | $search-pane-button-background-color: $accent-background-color;
15 | $search-pane-button-hover-color: $color;
16 | $search-pane-button-hover-border-color: #6d95e0;
17 | $search-pane-button-hover-background-color: #bbcef1;
18 | $search-pane-button-active-color: #fff;
19 | $search-pane-button-active-border-color: rgb(89, 139, 236);
20 | $search-pane-button-active-background-color: rgb(89, 139, 236);
21 | $search-pane-button-active-hover-color: #fff;
22 | $search-pane-button-active-hover-border-color: rgb(109, 149, 224);
23 | $search-pane-button-active-hover-background-color: rgb(187, 206, 241);
24 |
25 | $search-pane-loading-indicator-color: #fff;
26 | $search-pane-loading-indicator-background-color: #b50000;
27 |
28 | body {
29 | color: $color;
30 | font-family: Georgia, "Times New Roman", Times, serif;
31 | margin: 0;
32 | padding: 0;
33 | }
34 |
35 | h1 {
36 | font-size: 1.7em;
37 | }
38 |
39 |
40 | h2 {
41 | font-size: 1.3em;
42 | margin: 0;
43 | top: 18px;
44 | }
45 |
46 | .page-wrapper {
47 | padding: 0 1em;
48 | }
49 |
50 |
51 | .search-pane {
52 | background: $accent-background-color;
53 | border: 1px $accent-color solid;
54 | display: flex;
55 | flex-direction: row;
56 | margin: 1em 0;
57 | max-width: 1010px;
58 | min-height: 140px;
59 | min-width: 720px;
60 | padding: 0 1em;
61 | position: relative;
62 |
63 | .fields-list,
64 | .formats-list {
65 | display: block;
66 | height: auto;
67 | list-style: none;
68 | overflow: hidden;
69 | width: 90%;
70 |
71 | li {
72 | background-color: $search-pane-button-background-color;
73 | border: 1px $search-pane-button-border-color solid;
74 | border-radius: 8px;
75 | color: $search-pane-button-color;
76 | cursor: default;
77 | display: inline-block;
78 | margin: 4px 7px 4px 0;
79 | padding: 3px 6px;
80 |
81 | &:hover {
82 | background-color: $search-pane-button-hover-background-color;
83 | border: 1px solid $search-pane-button-hover-border-color;
84 | color: $search-pane-button-hover-color;
85 | }
86 |
87 | &.field-active,
88 | &.format-active {
89 | background: $search-pane-button-active-background-color;
90 | border: 1px solid $search-pane-button-active-border-color;
91 | color: $search-pane-button-active-color;
92 |
93 | &:hover {
94 | background: $search-pane-button-active-hover-background-color;
95 | border: 1px solid $search-pane-button-active-hover-border-color;
96 | color: $search-pane-button-active-hover-color;
97 | }
98 | }
99 | }
100 | }
101 | }
102 |
103 | .search-pane-loading-indicator {
104 | background: $search-pane-loading-indicator-background-color;
105 | color: $search-pane-loading-indicator-color;
106 | display: none;
107 | margin: 0;
108 | padding: .1em .2em .2em .6em;
109 | position: absolute;
110 | right: 0;
111 | top: 0;
112 |
113 | .styles-processing & {
114 | display: block;
115 | }
116 | }
117 |
118 |
119 | .search-field {
120 | font-size: 16px;
121 | margin-top: 1em;
122 | max-width: 255px;
123 | width: 255px;
124 | }
125 |
126 | .style-list {
127 | li {
128 | display: inline-list-item;
129 | line-height: 1.2em;
130 | margin-bottom: .6em;
131 | }
132 |
133 | .metadata {
134 | font-size: .85em;
135 | margin-left: 1.5em;
136 | }
137 | }
138 |
139 | .search-pane-col-1 {
140 | flex: 0 0 260px;
141 | padding-top: 1.5em;
142 | }
143 |
144 | .search-pane-col-2 {
145 | max-width: calc(100% - 260px);
146 |
147 | p {
148 | display: flex;
149 | flex-direction: row;
150 |
151 | strong,
152 | span {
153 | min-width: 100px;
154 | padding-top: .5em;
155 | text-align: right;
156 | }
157 |
158 | ul {
159 | margin: 0;
160 | padding: 0 0 0 .5em;
161 | }
162 | }
163 | }
164 |
165 | .styles-loading {
166 | min-height: 50px;
167 | text-align: center;
168 |
169 | @at-root {
170 | @keyframes loading {
171 | to {
172 | transform: rotate(360deg);
173 | }
174 | }
175 | }
176 |
177 | &:after {
178 | animation: loading .75s steps(8, end) infinite;
179 | background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHZlcnNpb249IjEuMSIgeT0iMHB4IiB4PSIwcHgiIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgdmlld0JveD0iMCAwIDUwIDUwIj48cGF0aCBkPSJtMzUuODMgMy43NTljNC4zNzcgMi4yMjUgOC4wODYgNS44NiAxMC4yOSAxMC41M2wtMTAuMjEgNC42NDljLTAuODkwMi0yLjEyNy0yLjg0NC0zLjk1Ni01LjE2OC01LjExOWw1LjA5LTEwLjA2eiIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utd2lkdGg9Ii4zNTYxIiBjbGFzcz0ic3QxIi8+PGcgc3Ryb2tlPSIjZTdlN2U3IiBzdHJva2Utd2lkdGg9Ii4zNTYxIiBmaWxsPSIjZTdlN2U3Ij48cGF0aCBkPSJtNDcuNjcgMTcuNjNjMS41MzMgNC42NzMgMS41ODMgOS44NDEtMC4xNzMxIDE0LjcxbC0xMC41MS0zLjkwN2MwLjg2NTUtMi4xMjcgMC43NjY1LTQuNzk3LTAuMDQ5NDUtNy4yN2wxMC43My0zLjUzNnoiIGNsYXNzPSJzdDAiLz48cGF0aCBkPSJtNDYuMjQgMzUuODNjLTIuMjI1IDQuMzc3LTUuODYgOC4wODYtMTAuNTMgMTAuMjlsLTQuNjQ5LTEwLjE5YzIuMTI3LTAuODkwMiAzLjk1Ni0yLjg0NCA1LjExOS01LjE2OGwxMC4wNiA1LjA2OXoiIGNsYXNzPSJzdDAiLz48cGF0aCBkPSJtMzIuMzcgNDcuNjdjLTQuNjczIDEuNTMzLTkuODQxIDEuNTgzLTE0LjcxLTAuMTczMWwzLjkwNy0xMC41MWMyLjEyNyAwLjg2NTQgNC43OTcgMC43NjY1IDcuMjctMC4wNDk1bDMuNTM2IDEwLjczeiIgY2xhc3M9InN0MCIvPjxwYXRoIGQ9Im0xNC4xNyA0Ni4yNGMtNC4zNzctMi4yMi04LjA4Ni01Ljg2LTEwLjI5LTEwLjUzbDEwLjE5LTQuNjQ5YzAuODkwMiAyLjEyNyAyLjg0NCAzLjk1NiA1LjE2OCA1LjExOWwtNS4wNjkgMTAuMDZ6IiBjbGFzcz0ic3QwIi8+PHBhdGggZD0ibTIuMzI1IDMyLjM3Yy0xLjUzMy00LjY3My0xLjU4My05Ljg0MSAwLjE3MzEtMTQuNzFsMTAuNTEgMy45MDdjLTAuODY1NSAyLjEyNy0wLjc2NjUgNC43OTcgMC4wNDk0NSA3LjI3bC0xMC43MyAzLjUzNnoiIGNsYXNzPSJzdDAiLz48cGF0aCBkPSJtMy43NTkgMTQuMTdjMi4yMjYtNC4zNzcgNS44NjEtOC4wODYgMTAuNTMtMTAuMjlsNC42NDkgMTAuMTljLTIuMTI3IDAuODkwMi0zLjk1NiAyLjg0NC01LjExOSA1LjE2OGwtMTAuMDYtNS4wN3oiIGNsYXNzPSJzdDAiLz48cGF0aCBkPSJtMTcuNjMgMi4zMjVjNC42NzMtMS41MzMgOS44NDEtMS41ODMgMTQuNzEgMC4xNzMxbC0zLjkgMTAuNTFjLTIuMTI3LTAuODY1NC00Ljc5Ny0wLjc2NjUtNy4yNyAwLjA0OTVsLTMuNTQtMTAuNzR6IiBjbGFzcz0ic3QwIi8+PC9nPjwvc3ZnPgo=') 0 0 no-repeat;
180 | content: '';
181 | display: inline-block;
182 | height: 25px;
183 | left: -62px;
184 | position: relative;
185 | top: .5em;
186 | vertical-align: top;
187 | width: 25px;
188 | }
189 | }
190 |
191 | .drop.style-tooltip {
192 | background: $popover-background-color;
193 | border: 2px $popover-color solid;
194 | box-shadow: 1px 2px 4px 1px $popover-box-shadow-color;
195 | color: $popover-color;
196 | display: none;
197 | margin-left: 40px;
198 | max-width: 700px;
199 | min-width: 50px;
200 | overflow: hidden;
201 | padding: 5px 9px;
202 | position: absolute;
203 | text-align: left;
204 | word-wrap: break-word;
205 | z-index: 15000;
206 |
207 | &.drop-open {
208 | display: block;
209 | }
210 | }
211 |
212 | .drop-content {
213 | overflow: hidden;
214 | word-wrap: break-word;
215 | }
216 |
217 | .csl-bib-body {
218 | margin-bottom: .6em;
219 | position: relative;
220 | word-wrap: normal;
221 | }
222 |
223 |
224 |
225 | .style-view-source,
226 | .style-individual-link {
227 | color: $view-source-button-color;
228 | display: none;
229 | font-size: 11px;
230 | line-height: .9em;
231 | margin-left: 2px;
232 | padding: 2px 6px 3px;
233 | text-align: center;
234 | vertical-align: middle;
235 | cursor: pointer;
236 | text-decoration: underline;
237 |
238 | li:hover & {
239 | display: inline;
240 | }
241 | }
242 |
243 | .style-individual-link {
244 | margin-left: 10px;
245 | }
246 |
247 | .preview-content {
248 | h3:first-child {
249 | margin-top: .25em;
250 | }
251 |
252 | h3 {
253 | font-size: 18px;
254 | }
255 | }
256 |
257 | /*
258 | .inline-citation ul,
259 | .inline-citation li {
260 | margin: 0;
261 | padding: 0;
262 | }
263 |
264 | .inline-citation ul {
265 | list-style: none;
266 | }
267 | */
268 |
--------------------------------------------------------------------------------
/include/Styles_Preview.inc.php:
--------------------------------------------------------------------------------
1 | .
23 |
24 | ***** END LICENSE BLOCK *****
25 | */
26 |
27 | require_once("Styles.inc.php");
28 |
29 | class CSLPreview {
30 | public static function getCitations($code, $data) {
31 | $server = CITEPROC_NODE_URL;
32 |
33 | $url = "$server?responseformat=json&citations=1&bibliography=0";
34 |
35 | $data->styleXML = $code;
36 | $json = json_encode($data);
37 |
38 | $response = self::callProcessor($url, $json);
39 |
40 | if (!$response) {
41 | throw new Exception("No response generating citations");
42 | }
43 |
44 | $response = json_decode($response);
45 | $citations = $response->citations;
46 |
47 | $toReturn = array();
48 | foreach ($citations as $citation) {
49 | $toReturn[] = $citation[1];
50 | }
51 | return $toReturn;
52 | }
53 |
54 |
55 | /**
56 | * Generate JSON for items and send to citeproc-js web service
57 | *
58 | * From getBibliographyFromCiteServer() in Zotero_Cite data server class
59 | */
60 | public static function getBibliography($code, $data) {
61 | $server = CITEPROC_NODE_URL;
62 |
63 | $url = "$server?responseformat=json";
64 |
65 | $data->styleXML = $code;
66 | $json = json_encode($data);
67 |
68 | $response = self::callProcessor($url, $json);
69 |
70 | if (!$response) {
71 | throw new Exception("No response generating bibliography");
72 | }
73 |
74 | //
75 | // Ported from Zotero.Cite.makeFormattedBibliography() in Zotero client
76 | //
77 |
78 | $bib = json_decode($response);
79 | $bib = $bib->bibliography;
80 |
81 | if (!$bib) {
82 | $url .= "&citations=1";
83 | $response = self::callProcessor($url, $json);
84 | if (!$response) {
85 | throw new Exception("No response generating citations");
86 | }
87 | $result = json_decode($response);
88 | $citations = array();
89 | foreach ($result->citations as $citation) {
90 | $citations[] = $citation[1];
91 | }
92 | $styleXML = new SimpleXMLElement($code);
93 | if ($styleXML['class'] == 'note') {
94 | return "'
129 | + '
Citations '
130 | + '
' + preview.citation.join(' ') + '
'
131 | + '
Bibliography '
132 | + preview.bibliography
133 | + '
';
134 | this.tooltips[index].position();
135 | });
136 | }
137 | });
138 | this.tooltips[index].open();
139 | }
140 | }
141 | });
142 |
143 | mountToDom(this.container, ac, () => {
144 | if(process.env.NODE_ENV === 'development') {
145 | let t1 = performance.now();
146 | console.log('Mounting vidom took ' + (t1 - t0) + ' ms.');
147 | }
148 | });
149 | };
150 |
151 | /**
152 | * Filter styles for given query and update the App State with the results
153 | * @param {Object} query - object defining search criteria. Can contain the following keys:
154 | */
155 | ZSR.prototype.search = function(query) {
156 | if(process.env.NODE_ENV === 'development') {
157 | var t0 = performance.now();
158 | }
159 | var filtered;
160 | var filteredCounter = this.styles && this.styles.length || 0;
161 | var formats;
162 | var fields;
163 |
164 |
165 | if(!this.styles || !this.styles.length) {
166 | this.state.setState({
167 | query: query
168 | });
169 | return;
170 | }
171 |
172 | if(query) {
173 | let queryKeys = Object.keys(query),
174 | queryFormat,
175 | queryId,
176 | queryDependent,
177 | queryFields,
178 | querySearch;
179 |
180 | fields = new Set();
181 | formats = new Set();
182 |
183 | if(queryKeys.indexOf('id') > -1 && query.id !== null) {
184 | queryId = query.id;
185 | }
186 |
187 | if(queryKeys.indexOf('format') > -1 && query.format !== null) {
188 | queryFormat = query.format;
189 | }
190 |
191 | if(queryKeys.indexOf('dependent') > -1 && query.dependent !== null) {
192 | queryDependent = query.dependent;
193 | }
194 |
195 | if(queryKeys.indexOf('fields') > -1 && query.fields.length) {
196 | queryFields = query.fields;
197 | }
198 |
199 | if(queryKeys.indexOf('search') > -1 && query.search !== null && query.search.length) {
200 | querySearch = query.search;
201 | let matches = querySearch.match(/id\:\s*([\w\-]*)/i);
202 | if(matches) {
203 | queryId = matches[1].trim();
204 | querySearch = querySearch.slice(0, matches.index) + querySearch.slice(matches.index + matches[0].length);
205 | querySearch = querySearch.trim();
206 | }
207 | }
208 |
209 | filtered = this.styles.map(item => {
210 | item.visible = true;
211 |
212 | if(typeof queryId !== 'undefined') {
213 | item.visible = item.visible && item.name === queryId;
214 | }
215 |
216 | if(typeof queryFormat !== 'undefined') {
217 | item.visible = item.visible && item.categories.format === queryFormat;
218 | }
219 | if(typeof queryDependent !== 'undefined') {
220 | item.visible = item.visible && !!item.dependent === !!queryDependent;
221 | }
222 | if(typeof queryFields !== 'undefined') {
223 | item.visible = item.visible && intersection(queryFields, item.categories.fields).length === queryFields.length;
224 | }
225 | if(typeof querySearch !== 'undefined') {
226 | let queryLow = querySearch.toLowerCase();
227 | let queryLowParts = queryLow.split(/\s+/);
228 | item.visible = item.visible
229 | && queryLowParts.every((part) => {
230 | return item.name.toLowerCase().includes(part)
231 | || item.title.toLowerCase().includes(part)
232 | || (item.titleShort && item.titleShort.toLowerCase().includes(part));
233 | });
234 | }
235 |
236 | if(item.visible) {
237 | item.categories.fields.forEach(field => {
238 | fields.add(field);
239 | });
240 |
241 | formats.add(item.categories.format);
242 | } else {
243 | filteredCounter--;
244 | }
245 |
246 | return item;
247 |
248 | });
249 | } else {
250 | fields = this.fields;
251 | formats = this.formats;
252 | }
253 |
254 | if(process.env.NODE_ENV === 'development') {
255 | let t1 = performance.now();
256 | console.log('Filtering took ' + (t1 - t0) + ' ms.');
257 | }
258 |
259 | this.state.setState({
260 | styles: filtered,
261 | count: filteredCounter,
262 | fields: Array.from(fields),
263 | formats: Array.from(formats),
264 | query: query
265 | });
266 | };
267 |
268 | export default ZSR;
--------------------------------------------------------------------------------
/scripts/generate-index:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 | .
24 |
25 | ***** END LICENSE BLOCK *****
26 | */
27 |
28 | error_reporting(E_ALL);
29 | ini_set("display_errors", true);
30 |
31 | ini_set('include_path', '.:' . dirname(dirname(__FILE__)) . '/include');
32 | require('config.inc.php');
33 | require('Styles.inc.php');
34 | require("Styles_Repo.inc.php");
35 |
36 | class CSL_Index_Generator {
37 | private static $initialized = false;
38 | private static $originalStylesPath;
39 | private static $localStylesPath;
40 | private static $dataPath;
41 |
42 | private static function init() {
43 | self::$initialized = true;
44 |
45 | self::$originalStylesPath = ROOT_PATH . "styles/original/";
46 | self::$localStylesPath = ROOT_PATH . "styles/local/";
47 | self::$dataPath = ROOT_PATH . "styles/data/";
48 |
49 | if (!file_exists(self::$originalStylesPath)) {
50 | throw new Exception("Original styles directory not found");
51 | }
52 | if (!file_exists(self::$originalStylesPath . ".git")) {
53 | chdir(self::$originalStylesPath);
54 | if (file_exists(".gitignore")) {
55 | unlink(".gitignore");
56 | }
57 | exec("git clone https://github.com/citation-style-language/styles.git .");
58 | }
59 | if (!file_exists(self::$localStylesPath . "dependent")) {
60 | mkdir(self::$localStylesPath . "dependent");
61 | }
62 | if (!file_exists(self::$dataPath . "dependent")) {
63 | mkdir(self::$dataPath . "dependent");
64 | }
65 | }
66 |
67 | public static function run() {
68 | if (!self::$initialized) {
69 | self::init();
70 | }
71 |
72 | // Update original styles
73 | chdir(self::$originalStylesPath);
74 | exec("/usr/bin/git pull");
75 |
76 | $keep = array(
77 | 'independent' => array(),
78 | 'dependent' => array()
79 | );
80 |
81 | $path = self::$originalStylesPath;
82 | $dir = opendir($path);
83 | while (false !== ($filename = readdir($dir))) {
84 | if (fnmatch("*.csl", $filename)) {
85 | $name = self::processOriginalStyle($path . $filename);
86 | if ($name) {
87 | $keep['independent'][] = $name;
88 | }
89 | }
90 | }
91 | closedir($dir);
92 |
93 | $path = self::$originalStylesPath . "dependent/";
94 | $dir = opendir($path);
95 | while (false !== ($filename = readdir($dir))) {
96 | if (fnmatch("*.csl", $filename)) {
97 | $name = self::processOriginalStyle($path . $filename, true);
98 | if ($name) {
99 | $keep['dependent'][] = $name;
100 | }
101 | }
102 | }
103 | closedir($dir);
104 |
105 | //
106 | // Delete styles that weren't updated
107 | //
108 | $path = self::$localStylesPath;
109 | $dir = opendir($path);
110 | while (false !== ($filename = readdir($dir))) {
111 | if (strpos($filename, ".") !== false || $filename == 'dependent') {
112 | continue;
113 | }
114 | if (!in_array($filename, $keep['independent'])) {
115 | Styles::log("Deleting $filename");
116 | unlink($path . $filename);
117 | }
118 | }
119 | closedir($dir);
120 |
121 | $path = self::$localStylesPath . "dependent/";
122 | $dir = opendir($path);
123 | while (false !== ($filename = readdir($dir))) {
124 | if (strpos($filename, ".") !== false) {
125 | continue;
126 | }
127 | if (!in_array($filename, $keep['dependent'])) {
128 | Styles::log("Deleting dependent/$filename");
129 | unlink($path . $filename);
130 | }
131 | }
132 | closedir($dir);
133 |
134 |
135 | //
136 | // Delete data files that weren't updated
137 | //
138 | $path = self::$dataPath;
139 | $dir = opendir($path);
140 | while (false !== ($filename = readdir($dir))) {
141 | if (strpos($filename, ".") !== false
142 | || $filename == 'dependent'
143 | || $filename == 'cache') {
144 | continue;
145 | }
146 | if (!in_array($filename, $keep['independent'])) {
147 | Styles::log("Deleting $filename");
148 | unlink($path . $filename);
149 | }
150 | }
151 | closedir($dir);
152 |
153 | $path = self::$dataPath . "dependent/";
154 | $dir = opendir($path);
155 | while (false !== ($filename = readdir($dir))) {
156 | if (strpos($filename, ".") !== false) {
157 | continue;
158 | }
159 | if (!in_array($filename, $keep['dependent'])) {
160 | Styles::log("Deleting dependent/$filename");
161 | unlink($path . $filename);
162 | }
163 | }
164 | closedir($dir);
165 |
166 | // Save 'lastModified' and 'etag' values for caching
167 | try {
168 | $styleList = Styles_Repo::getAllStyles();
169 | Styles_Repo::setCacheValues($styleList);
170 | }
171 | catch (Exception $e) {
172 | error_log($e);
173 | }
174 | }
175 |
176 |
177 | /**
178 | * Update cached file from original
179 | *
180 | * If style doesn't already exist or has changed, set a new timestamp
181 | *
182 | * Returns the parsed style name, or FALSE on error
183 | */
184 | private static function processOriginalStyle($originalStyle, $dependent=false) {
185 | Styles::log("=========================================\n");
186 | $filename = substr(strrchr($originalStyle, '/'), 1);
187 | Styles::log("$filename\n");
188 |
189 | $valid = null;
190 |
191 | $xmlstr = file_get_contents($originalStyle);
192 |
193 | try {
194 | $xml = new SimpleXMLElement($xmlstr);
195 | }
196 | catch (Exception $e) {
197 | Styles::log("$filename is invalid XML");
198 | return false;
199 | }
200 |
201 | $name = substr(strrchr($xml->info->id, '/'), 1);
202 |
203 | if (strpos($name, ".") !== false) {
204 | Styles::log("Invalid style name '" . $name . "'");
205 | return false;
206 | }
207 |
208 | // Compare CSL to existing version and skip if identical
209 | $localStyle = self::$localStylesPath . ($dependent ? "dependent/" : "") . $name;
210 | $dataFile = self::$dataPath . ($dependent ? "dependent/" : "") . $name;
211 | if (file_exists($localStyle) && file_exists($dataFile)) {
212 | $code = file_get_contents($localStyle);
213 | if (preg_replace("'