├── .gitignore
├── .travis.yml
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── linkify-citations.js
├── linkify.min.js
├── package.json
├── src
└── linkify-citations.js
└── tests
├── test.html
├── testLinked.html
├── testLinkify.js
└── test_files
└── usc.css
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "4.1"
4 | deploy:
5 | provider: s3
6 | access_key_id:
7 | secure: "rbsQUWGyBeywbd95HX+Q/a7Wtlp++Qj4JyTph64ve0xnk34o1f+mxE6yrh1CZu0E8eClgHKDefohHpY6svUJ9CVTuj3+oXEbVKnomcz4g6WUlACi/Qp8ADDPWMopU5yFykOtaLp+fnbEROaOOojUzIfttME8w/yNuAJ+ogYRAdNqnkhiMWf/EZ3Pso/UFtLeKsW9kfNWxekKYF32RihaBz3qCdr96tiYAMqTfhoQr4VGGwpB2Upjrf4/CA4Ea+r6VFKTEh+S6gcGAMBzeY4KWSLLy/Ud12LpgkmShaBLXWLDMwUiC5hZc5X2BkC+dWbevSbTmSQORAlD7q6EJIOjLhG1aoOqY+CrAXAzBhb86QhicrxmdOQAfQ2LFf4u+lX7TLuSpr3BaH+uLEh/2oh+6a7UuAhIri8PskZnA4ZxcyiVH3Nrklkx44kv/C8vDt3EVdkCREAMzdFmUfA9MJ0hziO4+MPP5xBdOrpqRbcBM6oCQv23HoxRM4dJXKonwDKRY7K+2QQfhcYtF2SlJ96Nf+y1j0BASf8ZLXuJao4lwHFU5rKSN3tMi2LvqLGXbPuTdx/LDB6+bw4ROmBqgbnaVyspEdOh2LoNuPI5V8UK1Imy17iQj2qt3kapi0I5apn2rqFytQI2Cz6jFav+gpDXplV3ERaSgxg5O4qo2bREVaw="
8 | secret_access_key:
9 | secure: "OzAmsYKq4hfE6QxRHzubPBiAyEI0bLNd61AVjkUNHhZHyHfALNdO0cD7lyzwO/WWjmI3pZILw7peqLS/Gr3xrbqEN9aw6n6SsjGUutGv3aITnbmR0Qjkg1Isiv7TQOrLTofbDaXcKLxRkBVnmwXxLDC3spbVFzGc9dF9kwZUGBfISJIpxmsBEqarGWGuskU50QLcbxqr2BPEf4ane0z2Wl0A2j08ssVHoahZtKHlNrflpHGlQBQbWsBbF/Sz/OTEmf/3QS7QsXYsWNNf1RerX9efufaH9BpC2Er53ld2yFIOGHnjS+6uvE+5fumuqbumNsA9b1LROGg7ndaKpDKpkWy0f7p//pRA5xzqdbvsKhTHNuDDsJe0/hnrtJOWq1Al6Scbf6Mo1gGFli0CpnYnGSYNMjUodlv2V9X7VHsPd8U4tDc2pfbnVjJS1Q0hUBHI6poMt9zCv0Fc6qPS51BTpk62ZY7TCeO+WSjiMzzP68doh4oLSNzC7OSsPQ2Y4lNpuckUfhVd3E99Ck6olrwl6+bcXEJHbijxNBiR4LR48eApANG3J3JEk3BMCy1x1ftyJdgwKGFngARyMK3phJDpUZ2rI77+EGgjcO9HHPMbF6BVvF0nI0yeClQqQSloMdGha1XmON2SlxDGLB42uRsbTC0CO14q9mD4Tj9cVhDHOQg="
10 | bucket: "linkify-citations"
11 | skip_cleanup: true
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Welcome!
2 |
3 | We're so glad you're thinking about contributing to an 18F open source project! If you're unsure about anything, just ask -- or submit the issue or pull request anyway. The worst that can happen is you'll be politely asked to change something. We love all friendly contributions.
4 |
5 | We want to ensure a welcoming environment for all of our projects. Our staff follow the [18F Code of Conduct](https://github.com/18F/code-of-conduct/blob/master/code-of-conduct.md) and all contributors should do the same.
6 |
7 | We encourage you to read this project's CONTRIBUTING policy (you are here), its [LICENSE](LICENSE.md), and its [README](README.md).
8 |
9 | If you have any questions or want to read more, check out the [18F Open Source Policy GitHub repository]( https://github.com/18f/open-source-policy), or just [shoot us an email](mailto:18f@gsa.gov).
10 |
11 | ## Public domain
12 |
13 | This project is in the public domain within the United States, and
14 | copyright and related rights in the work worldwide are waived through
15 | the [CC0 1.0 Universal public domain dedication](https://creativecommons.org/publicdomain/zero/1.0/).
16 |
17 | All contributions to this project will be released under the CC0
18 | dedication. By submitting a pull request, you are agreeing to comply
19 | with this waiver of copyright interest.
20 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | As a work of the United States Government, this project is in the
2 | public domain within the United States.
3 |
4 | Additionally, we waive copyright and related rights in the work
5 | worldwide through the CC0 1.0 Universal public domain dedication.
6 |
7 | ## CC0 1.0 Universal Summary
8 |
9 | This is a human-readable summary of the [Legal Code (read the full text)](https://creativecommons.org/publicdomain/zero/1.0/legalcode).
10 |
11 | ### No Copyright
12 |
13 | The person who associated a work with this deed has dedicated the work to
14 | the public domain by waiving all of his or her rights to the work worldwide
15 | under copyright law, including all related and neighboring rights, to the
16 | extent allowed by law.
17 |
18 | You can copy, modify, distribute and perform the work, even for commercial
19 | purposes, all without asking permission.
20 |
21 | ### Other Information
22 |
23 | In no way are the patent or trademark rights of any person affected by CC0,
24 | nor are the rights that other persons may have in the work or in how the
25 | work is used, such as publicity or privacy rights.
26 |
27 | Unless expressly stated otherwise, the person who associated a work with
28 | this deed makes no warranties about the work, and disclaims liability for
29 | all uses of the work, to the fullest extent permitted by applicable law.
30 | When using or citing the work, you should not imply endorsement by the
31 | author or the affirmer.
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # linkify citations
2 |
3 | Scans the DOM for legal citations, finds them, and turns them into HTML links.
4 |
5 | ## Usage
6 |
7 | ```html
8 |
9 | ```
10 |
11 | ## Development/deployment
12 |
13 | Pull requests merged into `master` will automatically be deployed to the S3 bucket. To test things out, you might want to try [rawgit](https://rawgit.com).
14 |
15 | ### Dependencies
16 |
17 | None! Everything is self-contained. Under the hood, a lot of the heavy lifting is done by [citation.js](https://github.com/unitedstates/citation) ([demo](https://theunitedstates.io/citation/)).
18 |
--------------------------------------------------------------------------------
/linkify-citations.js:
--------------------------------------------------------------------------------
1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) {
131 |
132 | // merge all regexes into one, so that each pattern will begin at a predictable place
133 | var regex = new RegExp("(" + regexes.join(")|(") + ")", "ig");
134 |
135 | var replaced = text.replace(regex, function() {
136 | var match = arguments[0];
137 |
138 | // offset is second-to-last argument
139 | var index = arguments[arguments.length - 2];
140 |
141 | // pull out just the regex-captured matches
142 | var captures = Array.prototype.slice.call(arguments, 1, -2);
143 |
144 | // find the first matched index in the captures
145 | var matchIndex;
146 | for (matchIndex=0; matchIndex 0) {
173 | var proposedLeft = index - excerpt;
174 | var left = proposedLeft > 0 ? proposedLeft : 0;
175 |
176 | var proposedRight = index + matchInfo.match.length + excerpt;
177 | var right = (proposedRight <= text.length) ? proposedRight : text.length;
178 |
179 | matchInfo.excerpt = text.substring(left, right);
180 | }
181 |
182 |
183 | // if we want parent cites too, make those now
184 | if (parents && Citation.types[type].parents_by) {
185 | cites = Citation._.flatten(cites.map(function(cite) {
186 | return Citation.citeParents(cite, type);
187 | }));
188 | }
189 |
190 | cites = cites.map(function(cite) {
191 | var result = {};
192 |
193 | // match-level info
194 | Citation._.extend(result, matchInfo);
195 |
196 | // handle _submatch, which lets the user-level citator override the
197 | // match and index with a sub-part of the whole matched regex
198 | if (cite._submatch) {
199 | result.match = cite._submatch.text;
200 | result.index += cite._submatch.offset;
201 | delete cite._submatch;
202 | }
203 |
204 | // cite-level info, plus ID standardization
205 | result[type] = cite;
206 | result[type].id = Citation.types[type].id(cite);
207 |
208 | results.push(result);
209 |
210 | return result;
211 | });
212 |
213 | // If a replace function is given, replace each matched citation by the
214 | // result of calling the replace function with the citation passed as its
215 | // only argument.
216 | //
217 | // Most citators return only a single citation match per regex match, but
218 | // some return multiple citations for strings like "§§ 32-701 through 32-703".
219 |
220 | // Collect the final match string here.
221 | var finalstring = matchInfo.match;
222 |
223 | // Get the replace function. If options.replace is a function use that,
224 | // or if it is an object mapping the citator type to a function use that.
225 | var replace_func = null;
226 | if (typeof(replace) === "function")
227 | replace_func = replace;
228 | else if ((typeof(replace) === "object") && (typeof(replace[type]) === "function"))
229 | replace_func = replace[type];
230 | else
231 | replace_func = null;
232 |
233 | // If there's a replacement function...
234 | if (replace_func) {
235 | // Process the citations in the order they are returned. Assume they are
236 | // ordered from left to right.
237 | var last_index = 0;
238 | var dx = 0;
239 | for (var i = 0; i < cites.length; i++) {
240 | // Skip citations that overlap with the previous citation (e.g. there
241 | // may be two citations for the same text range.)
242 | if (cites[i].index >= last_index) {
243 | // Execute the replacement function. If the return is truth-y, perform
244 | // a replacement.
245 | var replacement = replace_func(cites[i]);
246 | if (replacement) {
247 | // Replace the substring.
248 | finalstring = finalstring.substring(0, cites[i].index-index+dx) + replacement + finalstring.substring(cites[i].index-index+cites[i].match.length+dx);
249 |
250 | // The replacement text may have a different length than the text
251 | // being replaced. Keep track of the total change in string length
252 | // as we go because we have to adjust future citation replacements's
253 | // indexes so that we make the edit to finalstring in the right place.
254 | dx += replacement.length - cites[i].match.length;
255 |
256 | // And track the end of last citation so we can skip any future citations
257 | // that overlap with this text range.
258 | last_index = cites[i].index + cites[i].match.length;
259 | }
260 | }
261 |
262 | // Per the citation API, delete the index field when doing a replacement.
263 | // After replacements, the index will no longer be useful to the caller
264 | // because the string has been edited.
265 | delete cites[i].index;
266 | }
267 | }
268 | return finalstring;
269 | });
270 | }
271 |
272 | // TODO: do for any external cite types, not just "judicial"
273 | if (types.indexOf("judicial") != -1)
274 | results = results.concat(Citation.types.judicial.extract(text));
275 |
276 | var response = {citations: results};
277 | if (options.replace) response.text = replaced;
278 |
279 | return response;
280 | },
281 |
282 |
283 | // for a given set of cite-specific details,
284 | // return itself and its parent citations
285 | citeParents: function(citation, type) {
286 | var field = Citation.types[type].parents_by;
287 | var results = [];
288 |
289 | for (var i=citation[field].length; i >= 0; i--) {
290 | var parent = Citation._.extend({}, citation);
291 | parent[field] = parent[field].slice(0, i);
292 | results.push(parent);
293 | }
294 | return results;
295 | },
296 |
297 | // given an array of captures *beginning* with values the pattern
298 | // knows how to process, turn it into an object with those keys.
299 | matchFor: function(captures, pattern) {
300 | var match = {};
301 | for (var i=0; i 0)
311 | types = options.types;
312 | } else
313 | types = [options.types];
314 | }
315 |
316 | // only allow valid types
317 | if (types) {
318 | types = types.filter(function(type) {
319 | return Object.keys(Citation.types).indexOf(type) != -1;
320 | });
321 | } else
322 | types = Object.keys(Citation.types);
323 |
324 | return types;
325 | },
326 |
327 | // small replacement for several functions previously served by
328 | // the `underscore` library.
329 | _: {
330 | extend: function(obj) {
331 | Array.prototype.slice.call(arguments, 1).forEach(function(source) {
332 | if (source) {
333 | for (var prop in source)
334 | obj[prop] = source[prop];
335 | }
336 | });
337 | return obj;
338 | },
339 |
340 | flatten: function(array) {
341 | var impl = function(input, output) {
342 | input.forEach(function(value) {
343 | if (Array.isArray(value))
344 | impl(value, output);
345 | else
346 | output.push(value);
347 | });
348 | return output;
349 | }
350 |
351 | return impl(array, []);
352 | }
353 | }
354 |
355 | };
356 |
357 |
358 | // TODO: load only the citation types asked for
359 | if (typeof(require) !== "undefined") {
360 | Citation.types.usc = require("./citations/usc");
361 | Citation.types.law = require("./citations/law");
362 | Citation.types.cfr = require("./citations/cfr");
363 | Citation.types.va_code = require("./citations/va_code");
364 | Citation.types.dc_code = require("./citations/dc_code");
365 | Citation.types.dc_register = require("./citations/dc_register");
366 | Citation.types.dc_law = require("./citations/dc_law");
367 | Citation.types.dc_stat = require("./citations/dc_stat");
368 | Citation.types.stat = require("./citations/stat");
369 | Citation.types.reporter = require("./citations/reporter");
370 |
371 |
372 | Citation.filters.lines = require("./filters/lines");
373 | }
374 |
375 | // auto-load in-browser
376 | if (typeof(window) !== "undefined")
377 | window.Citation = Citation;
378 |
379 | return Citation;
380 |
381 | })();
382 |
383 | },{"./citations/cfr":2,"./citations/dc_code":3,"./citations/dc_law":4,"./citations/dc_register":5,"./citations/dc_stat":6,"./citations/law":7,"./citations/reporter":8,"./citations/stat":9,"./citations/usc":10,"./citations/va_code":11,"./filters/lines":12}],2:[function(require,module,exports){
384 | module.exports = {
385 | type: "regex",
386 |
387 | id: function(data) {
388 | return ["cfr", data.title, (data.section || data.part)]
389 | .concat(data.subsections || [])
390 | .join("/")
391 | },
392 |
393 | patterns: [
394 | // done:
395 | // 14 CFR part 25
396 | // 38 CFR Part 74.2
397 | // 48 CFR § 9903.201
398 | // 24 CFR 85.25(h)
399 | // 5 CFR §531.610(f)
400 | // 45 C.F.R. 3009.4
401 | // 47 CFR 54.506 (c)
402 | // but not: 47 CFR 54.506 (whatever)
403 | // 5CFR, part 575
404 |
405 | // maybe:
406 | // 13 CFR Parts 125 and 134
407 | // 5CFR, part 575, subpart C
408 | // 23 CFR 650, Subpart A
409 | {
410 | regex:
411 | "(\\d+)\\s?" +
412 | "C\\.?\\s?F\\.?\\s?R\\.?" +
413 | "(?:[\\s,]+(?:§+|parts?))?" +
414 | "\\s*((?:\\d+\\.?\\d*(?:\\s*\\((?:[a-zA-Z\\d]{1,2}|[ixvIXV]+)\\))*)+)",
415 |
416 | fields: ['title', 'sections'],
417 |
418 | processor: function(captures) {
419 | var title = captures.title;
420 | var part, section, subsections;
421 |
422 | // separate subsections for each section being considered
423 | var split = captures.sections.split(/[\(\)]+/).filter(function(x) {return x;});
424 | section = split[0].trim();
425 | subsections = split.splice(1);
426 |
427 | if (section.indexOf(".") > 0)
428 | part = section.split(".")[0];
429 | else {
430 | part = section;
431 | section = null;
432 | subsections = null; // don't include empty array
433 | }
434 |
435 | return {
436 | title: title,
437 | part: part,
438 | section: section,
439 | subsections: subsections
440 | };
441 | }
442 | }
443 |
444 | // todo:
445 | // parts 121 and 135 of Title 14 of the Code of Federal Regulations
446 | // {
447 | // regex:
448 | // "section (\\d+[\\w\\d\-]*)((?:\\([^\\)]+\\))*)" +
449 | // "(?:\\s+of|\\,) title (\\d+)",
450 | // fields: ['section', 'subsections', 'title'],
451 | // processor: function(captures) {
452 | // return {
453 | // title: captures.title,
454 | // section: captures.section,
455 | // subsections: captures.subsections.split(/[\(\)]+/).filter(function(x) {return x;})
456 | // };
457 | // }
458 | // }
459 | ]
460 | };
461 |
462 | },{}],3:[function(require,module,exports){
463 | var base_regex =
464 | "(\\d+A?)" + // title
465 | "\\s?\\-\\s?" + // dash
466 | "([\\w\\d]+(?:\\.?[\\w\\d]+)?)" + // section identifier (letters/numbers/dots)
467 | "((?:\\([^\\)]+\\))*)"; // subsection (any number of adjacent parenthesized subsections)
468 |
469 | module.exports = {
470 | type: "regex",
471 |
472 | // normalize all cites to an ID, with and without subsections
473 | id: function(cite) {
474 | return ["dc-code", cite.title, cite.section]
475 | .concat(cite.subsections)
476 | .join("/");
477 | },
478 |
479 | // field to calculate parents from
480 | parents_by: "subsections",
481 |
482 | patterns: function(context) {
483 | // D.C. Official Code 3-1202.04
484 | // D.C. Official Code § 3-1201.01
485 | // D.C. Official Code §§ 38-2602(b)(11)
486 | // D.C. Official Code § 3- 1201.01
487 | // D.C. Official Code § 3 -1201.01
488 | //
489 | // § 32-701
490 | // § 32-701(4)
491 | // § 3-101.01
492 | // § 1-603.01(13)
493 | // § 1- 1163.33
494 | // § 1 -1163.33
495 | // section 16-2326.01
496 |
497 | var prefix_regex = "";
498 | var section_regex = "(?:sections?|§+)\\s+";
499 | var sections_regex = "(?:sections|§§)\\s+";
500 | if (context.source != "dc_code") {
501 | // Require "DC Official Code" but then make the section symbol optional.
502 | prefix_regex = "D\\.?C\\.? (?:Official )?Code\\s+";
503 | section_regex = "(?:" + section_regex + ")?";
504 | sections_regex = "(?:" + sections_regex + ")?";
505 | }
506 |
507 | return [
508 | // multiple citations
509 | // has precedence over a single citation
510 | // Unlike the single citation, the matched parts are just the title/section/subsection
511 | // and omits "DC Code" and the section symbols (if present) from the matched text.
512 | {
513 | regex: "(" + prefix_regex + sections_regex + ")(" + base_regex + "(?:(?:,|, and|\\s+and|\\s+through|\\s+to)\\s+" + base_regex + ")+)",
514 |
515 | fields: ["prefix", "multicite", "title1", "section1", "subsections1", "title2", "section2", "subsections2"],
516 |
517 | processor: function(captures) {
518 | var rx = new RegExp(base_regex, "g");
519 | var matches = new Array();
520 | var match;
521 | while((match = rx.exec(captures.multicite)) !== null) {
522 | matches.push({
523 | _submatch: {
524 | text: match[0],
525 | offset: captures.prefix.length + match.index,
526 | },
527 | title: match[1],
528 | section: match[2],
529 | subsections: split_subsections(match[3])
530 | });
531 | }
532 | return matches;
533 | }
534 | },
535 |
536 | // a single citation
537 | {
538 | regex: prefix_regex + section_regex + base_regex,
539 |
540 | fields: ["title", "section", "subsections"],
541 |
542 | processor: function(captures) {
543 | var title = captures.title;
544 | var section = captures.section;
545 | var subsections = split_subsections(captures.subsections);
546 |
547 | return {
548 | title: title,
549 | section: section,
550 | subsections: subsections
551 | };
552 | }
553 | }
554 | ];
555 | }
556 | };
557 |
558 | function split_subsections(match) {
559 | if (match)
560 | return match.split(/[\(\)]+/).filter(function(x) {return x});
561 | else
562 | return [];
563 | }
564 | },{}],4:[function(require,module,exports){
565 | module.exports = {
566 | type: "regex",
567 |
568 | id: function(cite) {
569 | return ["dc-law", cite.period, cite.number].join("/");
570 | },
571 |
572 | patterns: function(context) {
573 | // If the context for this citation is the DC Code, then Law XX-YYY can be assumed
574 | // to be a DC law. In other context, require the "DC Law" prefix. In the DC Code
575 | // context also slurp in the "DC" prefix.
576 | var context_regex = "D\\.?\\s*C\\.?\\s+";
577 | if (context.source == "dc_code")
578 | context_regex = "(?:" + context_regex + ")?"
579 |
580 | return [
581 | // "D.C. Law 111-89"
582 | // "DC Law 111-89"
583 | // "DC Law 18-135A"
584 | {
585 | regex:
586 | context_regex + "Law\\s+(\\d+)\\s?[-–]+\\s?(\\d+\\w?)",
587 | fields: ["period", "number"],
588 | processor: function(captures) {
589 | return {
590 | period: captures.period,
591 | number: captures.number
592 | };
593 | }
594 | }
595 | ];
596 | }
597 | };
598 |
599 | },{}],5:[function(require,module,exports){
600 | module.exports = {
601 | type: "regex",
602 |
603 | id: function(cite) {
604 | return ["dc-register", cite.volume, cite.page].join("/");
605 | },
606 |
607 | patterns: [
608 | // 54 DCR 8014
609 | {
610 | regex:
611 | "(\\d+)\\s+" +
612 | "DCR" +
613 | "\\s+(\\d+)",
614 | fields: ['volume', 'page'],
615 | processor: function(match) {
616 | return {
617 | volume: match.volume,
618 | page: match.page,
619 | };
620 | }
621 | }
622 | ]
623 | };
624 |
625 | },{}],6:[function(require,module,exports){
626 | module.exports = {
627 | type: "regex",
628 |
629 | // normalize all cites to an ID
630 | id: function(cite) {
631 | return ["dcstat", cite.volume, cite.page].join("/")
632 | },
633 |
634 | patterns: [
635 | // "20 DCSTAT 1952"
636 | {
637 | regex:
638 | "(\\d+)\\s+" +
639 | "DCSTAT" +
640 | "\\s+(\\d+)",
641 | fields: ['volume', 'page'],
642 | processor: function(match) {
643 | return {
644 | volume: match.volume,
645 | page: match.page,
646 | };
647 | }
648 | }
649 | ]
650 | };
651 |
652 | },{}],7:[function(require,module,exports){
653 | module.exports = {
654 | type: "regex",
655 |
656 | id: function(cite) {
657 | return ["us-law", cite.type, cite.congress, cite.number]
658 | .concat(cite.sections || [])
659 | .join("/");
660 | },
661 |
662 | // field to calculate parents from
663 | parents_by: "sections",
664 |
665 | patterns: [
666 | // "Public Law 111-89"
667 | // "Pub. L. 112-56"
668 | // "Pub. L. No. 110-2"
669 | // "Pub.L. 105-33"
670 | // "Private Law 111-72"
671 | // "Priv. L. No. 98-23"
672 | // "section 552 of Public Law 111-89"
673 | // "section 4402(e)(1) of Public Law 110-2"
674 | {
675 | regex:
676 | "(?:section (\\d+[\\w\\d\-]*)((?:\\([^\\)]+\\))*) of )?" +
677 | "(pub(?:lic)?|priv(?:ate)?)\\.?\\s*l(?:aw)?\\.?(?:\\s*No\\.?)?" +
678 | " +(\\d+)[-–]+(\\d+)",
679 | fields: ['section', 'subsections', 'type', 'congress', 'number'],
680 | processor: function(captures) {
681 | var sections = [];
682 | if (captures.section) sections.push(captures.section);
683 | if (captures.subsections) sections = sections.concat(captures.subsections.split(/[\(\)]+/).filter(function(x) {return x}));
684 |
685 | return {
686 | type: captures.type.match(/^priv/i) ? "private" : "public",
687 | congress: captures.congress,
688 | number: captures.number,
689 | sections: sections
690 | };
691 | }
692 | },
693 |
694 | // "PL 19-4"
695 | // "P.L. 45-78"
696 | // "section 552 of PL 19-4"
697 | // "section 4402(e)(1) of PL 19-4"
698 | {
699 | regex:
700 | "(?:section (\\d+[\\w\\d\-]*)((?:\\([^\\)]+\\))*) of )?" +
701 | "P\\.?L\\.? +(\\d+)[-–](\\d+)",
702 | fields: ['section', 'subsections', 'congress', 'number'],
703 | processor: function(captures) {
704 | sections = [];
705 | if (captures.section) sections.push(captures.section);
706 | if (captures.subsections) sections = sections.concat(captures.subsections.split(/[\(\)]+/).filter(function(x) {return x}));
707 |
708 | return {
709 | type: "public",
710 | congress: captures.congress,
711 | number: captures.number,
712 | sections: sections
713 | };
714 | }
715 | }
716 | ]
717 | };
718 |
719 | },{}],8:[function(require,module,exports){
720 | module.exports = {
721 | type: "regex",
722 |
723 | // normalize all cites to an ID
724 | id: function(cite) {
725 | return ["reporter", cite.volume, cite.reporter, cite.page].join("/")
726 | },
727 |
728 | patterns: [
729 | {
730 | regex:
731 | "(\\d{1,3})\\s" +
732 | "(\\w+(?:\\.\\w+(?:\\.)?)?(?:\\.\\dd)?|U\\.?\\s?S\\.?|F\\. Supp\\.(?:\\s\\dd)?)\\s" +
733 | "(\\d{1,4})",
734 | fields: ['volume', 'reporter', 'page'],
735 | processor: function(match) {
736 | return {
737 | volume: match.volume,
738 | reporter: match.reporter,
739 | page: match.page,
740 | };
741 | }
742 | }
743 | ]
744 | };
745 |
746 | },{}],9:[function(require,module,exports){
747 | module.exports = {
748 | type: "regex",
749 |
750 | // normalize all cites to an ID
751 | id: function(cite) {
752 | return ["stat", cite.volume, cite.page].join("/")
753 | },
754 |
755 | patterns: [
756 | // "117 Stat. 1952"
757 | // "77 STAT. 77"
758 | {
759 | regex:
760 | "(\\d+[\\w]*)\\s+" +
761 | "Stat\\.?" +
762 | "\\s+(\\d+)",
763 | fields: ['volume', 'page'],
764 | processor: function(match) {
765 | return {
766 | volume: match.volume,
767 | page: match.page,
768 | };
769 | }
770 | }
771 | ]
772 | };
773 |
774 | },{}],10:[function(require,module,exports){
775 | module.exports = {
776 | type: "regex",
777 |
778 | id: function(cite) {
779 | return ["usc", cite.title, cite.section]
780 | .concat(cite.subsections || [])
781 | .join("/");
782 | },
783 |
784 |
785 | // field to calculate parents from
786 | parents_by: "subsections",
787 |
788 | patterns: [
789 | // "5 USC 552"
790 | // "5 U.S.C. § 552(a)(1)(E)"
791 | // "7 U.S.C. 612c note"
792 | // "29 U.S.C. 1081 et seq"
793 | // "50 U.S.C. App. 595"
794 | // "45 U.S.C. 10a-10c"
795 | // "50 U.S.C. 404o-1(a)" - single section
796 | // "45 U.S.C. 10a(1)-10c(2)" - range
797 | // "50 U.S.C. App. §§ 451--473" - range
798 | {
799 | regex:
800 | "(\\d+)\\s+" + // title
801 | "U\\.?\\s?S\\.?\\s?C\\.?" +
802 | "(?:\\s+(App)\.?)?" + // appendix
803 | "(?:\\s+(§+))?" + // symbol
804 | "\\s+((?:\\-*\\d+[\\w\\d\\-]*(?:\\([^\\)]+\\))*)+)" + // sections
805 | "(?:\\s+(note|et\\s+seq))?", // note
806 |
807 | fields: [
808 | 'title', 'appendix',
809 | 'symbol', 'sections', 'note'
810 | ],
811 |
812 | processor: function(match) {
813 | // a few titles have distinct appendixes
814 | var title = match.title;
815 | if (match.appendix) title += "-app";
816 |
817 | var sections = match.sections.split(/-+/);
818 |
819 | var range = false;
820 |
821 | // two section symbols is unambiguous
822 | if (match.symbol == "§§") // 2 section symbols
823 | range = true;
824 |
825 | // paren before dash is unambiguous
826 | else {
827 | var dash = match.sections.indexOf("-");
828 | var paren = match.sections.indexOf("(");
829 | if (dash > 0 && paren > 0 && paren < dash)
830 | range = true;
831 | }
832 |
833 | // if there's a hyphen and the range is ambiguous,
834 | // also return the original section string as one
835 | if ((sections.length > 1) && !range)
836 | sections.unshift(match.sections);
837 |
838 | return sections.map(function(section) {
839 | // separate subsections for each section being considered
840 | var split = section.split(/[\(\)]+/).filter(function(x) {return x});
841 | section = split[0];
842 | subsections = split.splice(1);
843 | if (match.note)
844 | subsections.push(match.note.replace(" ", "-")); // "note" or "et seq"
845 |
846 | return {
847 | title: title,
848 | section: section,
849 | subsections: subsections
850 | };
851 | });
852 | }
853 | },
854 |
855 | // "section 552 of title 5"
856 | // "section 552, title 5"
857 | // "section 552(a)(1)(E) of title 5"
858 | // "section 404o-1(a) of title 50"
859 | {
860 | regex:
861 | "section (\\d+[\\w\\d\-]*)((?:\\([^\\)]+\\))*)" +
862 | "(?:\\s+of|\\,) title (\\d+)",
863 |
864 | fields: ['section', 'subsections', 'title'],
865 |
866 | processor: function(match) {
867 | return {
868 | title: match.title,
869 | section: match.section,
870 | subsections: match.subsections.split(/[\(\)]+/).filter(function(x) {return x})
871 | };
872 | }
873 | }
874 | ]
875 | };
876 |
877 | },{}],11:[function(require,module,exports){
878 | module.exports = {
879 | type: "regex",
880 |
881 | id: function(cite) {
882 | return ["va-code", data.title, data.section].join("/");
883 | },
884 |
885 | patterns: [
886 |
887 | // Va. Code Ann. § 19.2-56.2 (2010)
888 | // Va. Code Ann. § 19.2-56.2 (West 2010)
889 | // Va. Code Ann. § 57-1
890 | // Va. Code Ann. § 57-2.02
891 | // Va. Code Ann. § 63.2-300
892 | // Va. Code Ann. § 66-25.1:1
893 | // Va. Code § 66-25.1:1
894 | // VA Code § 66-25.1:1
895 | {
896 | regex:
897 | "Va\\.? Code\\.?" +
898 | "(?:\\s+Ann\\.?)?" +
899 | "(?:\\s+§+)?" +
900 | "\\s+([\\d\\.]+)\\-([\\d\\.:]+)" +
901 | "(?:\\s+\\((?:West )?([12]\\d{3})\\))?",
902 | fields: ['title', 'section', 'year'],
903 | processor: function (captures) {
904 | return {
905 | title: captures.title,
906 | section: captures.section,
907 | year: captures.year
908 | };
909 | }
910 | }
911 | ]
912 | };
913 |
914 | },{}],12:[function(require,module,exports){
915 | module.exports = {
916 |
917 | /*
918 | Filters receive:
919 | * text: the entire input text
920 | * options: any filter-specific options, e.g. delimiter
921 | * extract: execute this function once with every substring the filter
922 | breaks the input text into, e.g. each line,
923 | along with any associated metadata, e.g. the line number.
924 |
925 | */
926 |
927 | // A line-by-line filter.
928 | //
929 | // Breaks the text up by line, and feeds each line into the extractor.
930 | // Attaches the line number (1-indexed) as metadata to each cite,
931 | // so that any character offsets will be relative to that line.
932 | //
933 | // Accepts options:
934 | // delimiter: override the default delimiter
935 |
936 | from: function(text, options, extract) {
937 | // by default, break lines on any combination of \n\r
938 | var delimiter = (options && options.delimiter) || /[\n\r]+/;
939 |
940 | // split the text into an array of lines
941 | var lines = text.split(new RegExp(delimiter));
942 |
943 | // for each line, submit it to the extractor along with its line number
944 | lines.forEach(function(line, i) {
945 | extract(line, {line: (i+1)});
946 | });
947 | }
948 |
949 | };
950 |
951 | },{}],13:[function(require,module,exports){
952 | // Load minified citation.js
953 | var Citation = require('citation');
954 |
955 | var citationToURL = function(citation) {
956 | var url = getURLfromCitation(citation)
957 | if (url) return "" + citation.match + "";
958 | else return citation.match;
959 | };
960 |
961 | var replaceDOM = function (document) {
962 | var thePage = document.documentElement.cloneNode(true);
963 | // find the citations
964 | var citations = Citation.find(thePage.innerHTML).citations;
965 |
966 | // loop through each citation
967 | for (i = 0; i < citations.length; i++) {
968 | // generate a link
969 | var link = citationToURL(citations[i]);
970 | // stick the link onto the DOM
971 | thePage.innerHTML = thePage.innerHTML.replace(citations[i].match, link);
972 | }
973 | return thePage.innerHTML;
974 | }
975 |
976 | var getURLfromCitation = function (citation) {
977 | var url = "http://api.fdsys.gov/link?collection="
978 |
979 | switch (citation.type) {
980 | case "usc":
981 | return url + "uscode&title=" + citation.usc.title + "&year=mostrecent§ion=" + citation.usc.section + "&type=usc"
982 | case "law":
983 | return url + "plaw&congress=" + citation.law.congress + "&lawtype=public&lawnum=" + citation.law.number
984 | case "cfr":
985 | return "http://api.fdsys.gov/link?collection=cfr&titlenum=" +
986 | citation.cfr.title + "&partnum=" + citation.cfr.part + "§ionnum="
987 | citation.cfr.section + "&year=mostrecent"
988 | case "stat":
989 | return url + "statute&volume=" + citation.stat.volume + "&page=" + citation.stat.page
990 | case "fedreg":
991 | return url + "fr&volume=" + citation.fedreg.volume + "&page=" + citation.fedreg.page
992 | default:
993 | return false;
994 | }
995 | }
996 |
997 | if (typeof window === 'undefined') {
998 | module.exports = {
999 | getURLfromCitation: getURLfromCitation,
1000 | replaceDOM: replaceDOM,
1001 | citationToURL: citationToURL
1002 | }
1003 | }
1004 | else {
1005 | window.document.addEventListener("DOMContentLoaded", function() {
1006 | window.document.documentElement.innerHTML = replaceDOM(window.document)
1007 | })
1008 | }
1009 | },{"citation":1}]},{},[13]);
1010 |
--------------------------------------------------------------------------------
/linkify.min.js:
--------------------------------------------------------------------------------
1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o0){var regex=new RegExp("("+regexes.join(")|(")+")","ig");var replaced=text.replace(regex,function(){var match=arguments[0];var index=arguments[arguments.length-2];var captures=Array.prototype.slice.call(arguments,1,-2);var matchIndex;for(matchIndex=0;matchIndex0){var proposedLeft=index-excerpt;var left=proposedLeft>0?proposedLeft:0;var proposedRight=index+matchInfo.match.length+excerpt;var right=proposedRight<=text.length?proposedRight:text.length;matchInfo.excerpt=text.substring(left,right)}if(parents&&Citation.types[type].parents_by){cites=Citation._.flatten(cites.map(function(cite){return Citation.citeParents(cite,type)}))}cites=cites.map(function(cite){var result={};Citation._.extend(result,matchInfo);if(cite._submatch){result.match=cite._submatch.text;result.index+=cite._submatch.offset;delete cite._submatch}result[type]=cite;result[type].id=Citation.types[type].id(cite);results.push(result);return result});var finalstring=matchInfo.match;var replace_func=null;if(typeof replace==="function")replace_func=replace;else if(typeof replace==="object"&&typeof replace[type]==="function")replace_func=replace[type];else replace_func=null;if(replace_func){var last_index=0;var dx=0;for(var i=0;i=last_index){var replacement=replace_func(cites[i]);if(replacement){finalstring=finalstring.substring(0,cites[i].index-index+dx)+replacement+finalstring.substring(cites[i].index-index+cites[i].match.length+dx);dx+=replacement.length-cites[i].match.length;last_index=cites[i].index+cites[i].match.length}}delete cites[i].index}}return finalstring})}if(types.indexOf("judicial")!=-1)results=results.concat(Citation.types.judicial.extract(text));var response={citations:results};if(options.replace)response.text=replaced;return response},citeParents:function(citation,type){var field=Citation.types[type].parents_by;var results=[];for(var i=citation[field].length;i>=0;i--){var parent=Citation._.extend({},citation);parent[field]=parent[field].slice(0,i);results.push(parent)}return results},matchFor:function(captures,pattern){var match={};for(var i=0;i0)types=options.types}else types=[options.types]}if(types){types=types.filter(function(type){return Object.keys(Citation.types).indexOf(type)!=-1})}else types=Object.keys(Citation.types);return types},_:{extend:function(obj){Array.prototype.slice.call(arguments,1).forEach(function(source){if(source){for(var prop in source)obj[prop]=source[prop]}});return obj},flatten:function(array){var impl=function(input,output){input.forEach(function(value){if(Array.isArray(value))impl(value,output);else output.push(value)});return output};return impl(array,[])}}};if(typeof require!=="undefined"){Citation.types.usc=require("./citations/usc");Citation.types.law=require("./citations/law");Citation.types.cfr=require("./citations/cfr");Citation.types.va_code=require("./citations/va_code");Citation.types.dc_code=require("./citations/dc_code");Citation.types.dc_register=require("./citations/dc_register");Citation.types.dc_law=require("./citations/dc_law");Citation.types.dc_stat=require("./citations/dc_stat");Citation.types.stat=require("./citations/stat");Citation.types.reporter=require("./citations/reporter");Citation.filters.lines=require("./filters/lines")}if(typeof window!=="undefined")window.Citation=Citation;return Citation}()},{"./citations/cfr":2,"./citations/dc_code":3,"./citations/dc_law":4,"./citations/dc_register":5,"./citations/dc_stat":6,"./citations/law":7,"./citations/reporter":8,"./citations/stat":9,"./citations/usc":10,"./citations/va_code":11,"./filters/lines":12}],2:[function(require,module,exports){module.exports={type:"regex",id:function(data){return["cfr",data.title,data.section||data.part].concat(data.subsections||[]).join("/")},patterns:[{regex:"(\\d+)\\s?"+"C\\.?\\s?F\\.?\\s?R\\.?"+"(?:[\\s,]+(?:§+|parts?))?"+"\\s*((?:\\d+\\.?\\d*(?:\\s*\\((?:[a-zA-Z\\d]{1,2}|[ixvIXV]+)\\))*)+)",fields:["title","sections"],processor:function(captures){var title=captures.title;var part,section,subsections;var split=captures.sections.split(/[\(\)]+/).filter(function(x){return x});section=split[0].trim();subsections=split.splice(1);if(section.indexOf(".")>0)part=section.split(".")[0];else{part=section;section=null;subsections=null}return{title:title,part:part,section:section,subsections:subsections}}}]}},{}],3:[function(require,module,exports){var base_regex="(\\d+A?)"+"\\s?\\-\\s?"+"([\\w\\d]+(?:\\.?[\\w\\d]+)?)"+"((?:\\([^\\)]+\\))*)";module.exports={type:"regex",id:function(cite){return["dc-code",cite.title,cite.section].concat(cite.subsections).join("/")},parents_by:"subsections",patterns:function(context){var prefix_regex="";var section_regex="(?:sections?|§+)\\s+";var sections_regex="(?:sections|§§)\\s+";if(context.source!="dc_code"){prefix_regex="D\\.?C\\.? (?:Official )?Code\\s+";section_regex="(?:"+section_regex+")?";sections_regex="(?:"+sections_regex+")?"}return[{regex:"("+prefix_regex+sections_regex+")("+base_regex+"(?:(?:,|, and|\\s+and|\\s+through|\\s+to)\\s+"+base_regex+")+)",fields:["prefix","multicite","title1","section1","subsections1","title2","section2","subsections2"],processor:function(captures){var rx=new RegExp(base_regex,"g");var matches=new Array;var match;while((match=rx.exec(captures.multicite))!==null){matches.push({_submatch:{text:match[0],offset:captures.prefix.length+match.index},title:match[1],section:match[2],subsections:split_subsections(match[3])})}return matches}},{regex:prefix_regex+section_regex+base_regex,fields:["title","section","subsections"],processor:function(captures){var title=captures.title;var section=captures.section;var subsections=split_subsections(captures.subsections);return{title:title,section:section,subsections:subsections}}}]}};function split_subsections(match){if(match)return match.split(/[\(\)]+/).filter(function(x){return x});else return[]}},{}],4:[function(require,module,exports){module.exports={type:"regex",id:function(cite){return["dc-law",cite.period,cite.number].join("/")},patterns:function(context){var context_regex="D\\.?\\s*C\\.?\\s+";if(context.source=="dc_code")context_regex="(?:"+context_regex+")?";return[{regex:context_regex+"Law\\s+(\\d+)\\s?[-–]+\\s?(\\d+\\w?)",fields:["period","number"],processor:function(captures){return{period:captures.period,number:captures.number}}}]}}},{}],5:[function(require,module,exports){module.exports={type:"regex",id:function(cite){return["dc-register",cite.volume,cite.page].join("/")},patterns:[{regex:"(\\d+)\\s+"+"DCR"+"\\s+(\\d+)",fields:["volume","page"],processor:function(match){return{volume:match.volume,page:match.page}}}]}},{}],6:[function(require,module,exports){module.exports={type:"regex",id:function(cite){return["dcstat",cite.volume,cite.page].join("/")},patterns:[{regex:"(\\d+)\\s+"+"DCSTAT"+"\\s+(\\d+)",fields:["volume","page"],processor:function(match){return{volume:match.volume,page:match.page}}}]}},{}],7:[function(require,module,exports){module.exports={type:"regex",id:function(cite){return["us-law",cite.type,cite.congress,cite.number].concat(cite.sections||[]).join("/")},parents_by:"sections",patterns:[{regex:"(?:section (\\d+[\\w\\d-]*)((?:\\([^\\)]+\\))*) of )?"+"(pub(?:lic)?|priv(?:ate)?)\\.?\\s*l(?:aw)?\\.?(?:\\s*No\\.?)?"+" +(\\d+)[-–]+(\\d+)",fields:["section","subsections","type","congress","number"],processor:function(captures){var sections=[];if(captures.section)sections.push(captures.section);if(captures.subsections)sections=sections.concat(captures.subsections.split(/[\(\)]+/).filter(function(x){return x}));return{type:captures.type.match(/^priv/i)?"private":"public",congress:captures.congress,number:captures.number,sections:sections}}},{regex:"(?:section (\\d+[\\w\\d-]*)((?:\\([^\\)]+\\))*) of )?"+"P\\.?L\\.? +(\\d+)[-–](\\d+)",fields:["section","subsections","congress","number"],processor:function(captures){sections=[];if(captures.section)sections.push(captures.section);if(captures.subsections)sections=sections.concat(captures.subsections.split(/[\(\)]+/).filter(function(x){return x}));return{type:"public",congress:captures.congress,number:captures.number,sections:sections}}}]}},{}],8:[function(require,module,exports){module.exports={type:"regex",id:function(cite){return["reporter",cite.volume,cite.reporter,cite.page].join("/")},patterns:[{regex:"(\\d{1,3})\\s"+"(\\w+(?:\\.\\w+(?:\\.)?)?(?:\\.\\dd)?|U\\.?\\s?S\\.?|F\\. Supp\\.(?:\\s\\dd)?)\\s"+"(\\d{1,4})",fields:["volume","reporter","page"],processor:function(match){return{volume:match.volume,reporter:match.reporter,page:match.page}}}]}},{}],9:[function(require,module,exports){module.exports={type:"regex",id:function(cite){return["stat",cite.volume,cite.page].join("/")},patterns:[{regex:"(\\d+[\\w]*)\\s+"+"Stat\\.?"+"\\s+(\\d+)",fields:["volume","page"],processor:function(match){return{volume:match.volume,page:match.page}}}]}},{}],10:[function(require,module,exports){module.exports={type:"regex",id:function(cite){return["usc",cite.title,cite.section].concat(cite.subsections||[]).join("/")},parents_by:"subsections",patterns:[{regex:"(\\d+)\\s+"+"U\\.?\\s?S\\.?\\s?C\\.?"+"(?:\\s+(App).?)?"+"(?:\\s+(§+))?"+"\\s+((?:\\-*\\d+[\\w\\d\\-]*(?:\\([^\\)]+\\))*)+)"+"(?:\\s+(note|et\\s+seq))?",fields:["title","appendix","symbol","sections","note"],processor:function(match){var title=match.title;if(match.appendix)title+="-app";var sections=match.sections.split(/-+/);var range=false;if(match.symbol=="§§")range=true;else{var dash=match.sections.indexOf("-");var paren=match.sections.indexOf("(");if(dash>0&&paren>0&&paren1&&!range)sections.unshift(match.sections);return sections.map(function(section){var split=section.split(/[\(\)]+/).filter(function(x){return x});section=split[0];subsections=split.splice(1);if(match.note)subsections.push(match.note.replace(" ","-"));return{title:title,section:section,subsections:subsections}})}},{regex:"section (\\d+[\\w\\d-]*)((?:\\([^\\)]+\\))*)"+"(?:\\s+of|\\,) title (\\d+)",fields:["section","subsections","title"],processor:function(match){return{title:match.title,section:match.section,subsections:match.subsections.split(/[\(\)]+/).filter(function(x){return x})}}}]}},{}],11:[function(require,module,exports){module.exports={type:"regex",id:function(cite){return["va-code",data.title,data.section].join("/")},patterns:[{regex:"Va\\.? Code\\.?"+"(?:\\s+Ann\\.?)?"+"(?:\\s+§+)?"+"\\s+([\\d\\.]+)\\-([\\d\\.:]+)"+"(?:\\s+\\((?:West )?([12]\\d{3})\\))?",fields:["title","section","year"],processor:function(captures){return{title:captures.title,section:captures.section,year:captures.year}}}]}},{}],12:[function(require,module,exports){module.exports={from:function(text,options,extract){var delimiter=options&&options.delimiter||/[\n\r]+/;var lines=text.split(new RegExp(delimiter));lines.forEach(function(line,i){extract(line,{line:i+1})})}}},{}],13:[function(require,module,exports){var Citation=require("citation");var citationToURL=function(citation){var url=getURLfromCitation(citation);if(url)return""+citation.match+"";else return citation.match};var replaceDOM=function(document){var thePage=document.documentElement.cloneNode(true);var citations=Citation.find(thePage.innerHTML).citations;for(i=0;i linkify-citations.js",
8 | "build:minify": "./node_modules/uglify-js/bin/uglifyjs linkify-citations.js -o linkify.min.js",
9 | "build": "npm run build:browserify && npm run build:minify",
10 | "test": "./node_modules/.bin/tape tests/**.js"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git+https://github.com/18F/linkify-citations.git"
15 | },
16 | "author": "",
17 | "license": "CC0",
18 | "bugs": {
19 | "url": "https://github.com/18F/linkify-citations/issues"
20 | },
21 | "homepage": "https://github.com/18F/linkify-citations#readme",
22 | "devDependencies": {
23 | "browserify": "^11.2.0",
24 | "domify": "^1.4.0",
25 | "jsdom": "^6.5.1",
26 | "tape": "^4.2.0",
27 | "uglify-js": "^2.4.24"
28 | },
29 | "dependencies": {
30 | "citation": "^0.8.1"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/linkify-citations.js:
--------------------------------------------------------------------------------
1 | // Load minified citation.js
2 | var Citation = require('citation');
3 |
4 | var citationToURL = function(citation) {
5 | var url = getURLfromCitation(citation)
6 | if (url) return "" + citation.match + "";
7 | else return citation.match;
8 | };
9 |
10 | var replaceDOM = function (document) {
11 | var thePage = document.documentElement.cloneNode(true);
12 | // find the citations
13 | var citations = Citation.find(thePage.innerHTML).citations;
14 |
15 | // loop through each citation
16 | for (i = 0; i < citations.length; i++) {
17 | // generate a link
18 | var link = citationToURL(citations[i]);
19 | // stick the link onto the DOM
20 | thePage.innerHTML = thePage.innerHTML.replace(citations[i].match, link);
21 | }
22 | return thePage.innerHTML;
23 | }
24 |
25 | var getURLfromCitation = function (citation) {
26 | var url = "http://api.fdsys.gov/link?collection="
27 |
28 | switch (citation.type) {
29 | case "usc":
30 | return url + "uscode&title=" + citation.usc.title + "&year=mostrecent§ion=" + citation.usc.section + "&type=usc"
31 | case "law":
32 | return url + "plaw&congress=" + citation.law.congress + "&lawtype=public&lawnum=" + citation.law.number
33 | case "cfr":
34 | return "http://api.fdsys.gov/link?collection=cfr&titlenum=" +
35 | citation.cfr.title + "&partnum=" + citation.cfr.part + "§ionnum="
36 | citation.cfr.section + "&year=mostrecent"
37 | case "stat":
38 | return url + "statute&volume=" + citation.stat.volume + "&page=" + citation.stat.page
39 | case "fedreg":
40 | return url + "fr&volume=" + citation.fedreg.volume + "&page=" + citation.fedreg.page
41 | default:
42 | return false;
43 | }
44 | }
45 |
46 | if (typeof window === 'undefined') {
47 | module.exports = {
48 | getURLfromCitation: getURLfromCitation,
49 | replaceDOM: replaceDOM,
50 | citationToURL: citationToURL
51 | }
52 | }
53 | else {
54 | window.document.addEventListener("DOMContentLoaded", function() {
55 | window.document.documentElement.innerHTML = replaceDOM(window.document)
56 | })
57 | }
--------------------------------------------------------------------------------
/tests/test.html:
--------------------------------------------------------------------------------
1 |
2 | U.S.C. Title 40 - PUBLIC BUILDINGS, PROPERTY, AND WORKS
3 | 40 U.S.C.
4 | United States Code, 2011 Edition
5 | Title 40 - PUBLIC BUILDINGS, PROPERTY, AND WORKS
6 | SUBTITLE I - FEDERAL PROPERTY AND ADMINISTRATIVE SERVICES
7 | CHAPTER 3 - 1-ORGANIZATION OF GENERAL SERVICES ADMINISTRATION
8 | SUBCHAPTER III - FUNDS
9 | Sec. 321 - Acquisition Services Fund
10 | From the U.S. Government Printing Office, www.gpo.gov
11 |
12 |
13 |
14 |
15 |
16 |
§321. Acquisition Services Fund
17 |
18 |
19 |
(a) Existence.—The Acquisition Services Fund is a special fund in the Treasury.
20 |
(b) Composition.—
21 |
(1) In general.—The Fund is composed of amounts authorized to be transferred to the Fund or otherwise made available to the Fund.
22 |
(2) Other credits.—The Fund shall be credited with all reimbursements, advances, and refunds or recoveries relating to personal property or services procured through the Fund, including—
23 |
(A) the net proceeds of disposal of surplus personal property; and
24 |
(B) receipts from carriers and others for loss of, or damage to, personal property; and
25 |
(C) receipts from agencies charged fees pursuant to rates established by the Administrator.
26 |
27 |
(3) Cost and capital requirements.—The Administrator shall determine the cost and capital requirements of the Fund for each fiscal year and shall develop a plan concerning such requirements in consultation with the Chief Financial Officer of the General Services Administration. Any change to the cost and capital requirements of the Fund for a fiscal year shall be approved by the Administrator. The Administrator shall establish rates to be charged agencies provided, or to be provided, supply of personal property and non-personal services through the Fund, in accordance with the plan.
28 |
(4) Deposit of fees.—Fees collected by the Administrator under section 313 of this title may be deposited in the Fund to be used for the purposes of the Fund.
29 |
30 |
(c) Uses.—
31 |
(1) In general.—The Fund is available for use by or under the direction and control of the Administrator for—
32 |
(A) procuring, for the use of federal agencies in the proper discharge of their responsibilities—
33 |
(i) personal property (including the purchase from or through the Public Printer, for warehouse issue, of standard forms, blankbook work, standard specifications, and other printed material in common use by federal agencies and not available through the Superintendent of Documents);
34 |
(ii) nonpersonal services; and
35 |
(iii) personal services related to the provision of information technology (as defined in section 11101(6) of this title);
36 |
37 |
(B) paying the purchase price, cost of transportation of personal property and services, and cost of personal services employed directly in the repair, rehabilitation, and conversion of personal property; and
38 |
(C) paying other direct costs of, and indirect costs that are reasonably related to, contracting, procurement, inspection, storage, management, distribution, and accountability of property and nonpersonal services provided by the General Services Administration or by special order through the Administration.
39 |
40 |
(2) Other uses.—The Fund may be used for the procurement of personal property and nonpersonal services authorized to be acquired by—
41 |
(A) mixed-ownership Government corporations;
42 |
(B) the municipal government of the District of Columbia; or
43 |
(C) a requisitioning non-federal agency when the function of a federal agency authorized to procure for it is transferred to the Administration.
44 |
45 |
(d) Payment for Property and Services.—
46 |
(1) In general.—For property or services procured through the Fund for requisitioning agencies, the agencies shall pay prices the Administrator fixes under this subsection.
47 |
(2) Prices fixed by administrator.—The Administrator shall fix prices at levels sufficient to recover—
48 |
(A) so far as practicable—
49 |
(i) the purchase price;
50 |
(ii) the transportation cost;
51 |
(iii) inventory losses;
52 |
(iv) the cost of personal services employed directly in the repair, rehabilitation, and conversion of personal property;
53 |
(v) the cost of personal services employed directly in providing information technology (as defined in section 11101(6) of this title); and
54 |
(vi) the cost of amortization and repair of equipment used for lease or rent to executive agencies; and
55 |
56 |
(B) properly allocable costs payable by the Fund under subsection (c)(1)(C).
57 |
58 |
(3) Timing of payments.—
59 |
(A) Payment in advance.—A requisitioning agency shall pay in advance when the Administrator determines that there is insufficient capital otherwise available in the Fund. Payment in advance may also be made under an agreement between a requisitioning agency and the Administrator.
60 |
(B) Prompt reimbursement.—If payment is not made in advance, the Administration shall be reimbursed promptly out of amounts of the requisitioning agency in accordance with accounting procedures approved by the Comptroller General.
61 |
(C) Failure to make prompt reimbursement.—The Administrator may obtain reimbursement by the issuance of transfer and counterwarrants, or other lawful transfer documents, supported by itemized invoices, if payment is not made by a requisitioning agency within 45 days after the later of—
62 |
(i) the date of billing by the Administrator; or
63 |
(ii) the date on which actual liability for personal property or services is incurred by the Administrator.
64 |
65 |
(e) Reimbursement for Equipment Purchased for Congress.—The Administrator may accept periodic reimbursement from the Senate and from the House of Representatives for the cost of any equipment purchased for the Senate or the House of Representatives with money from the Fund. The amount of each periodic reimbursement shall be computed by amortizing the total cost of each item of equipment over the useful life of the equipment, as determined by the Administrator, in consultation with the Sergeant at Arms and Doorkeeper of the Senate or the Chief Administrative Officer of the House of Representatives, as appropriate.
66 |
(f) Transfer of Uncommitted Balances.—Following the close of each fiscal year, after making provision for a sufficient level of inventory of personal property to meet the needs of Federal agencies, the replacement cost of motor vehicles, and other anticipated operating needs reflected in the cost and capital plan developed under subsection (b), the uncommitted balance of any funds remaining in the Fund shall be transferred to the general fund of the Treasury as miscellaneous receipts.
67 |
(g) Audits.—The Comptroller General shall audit the Fund in accordance with the provisions of chapter 35 of title 31 and report the results of the audits.
68 |
69 |
70 |
(Pub. L. 107–217, Aug. 21, 2002, 116 Stat. 1074; Pub. L. 109–313, §3(d)–(g), (h)(2), Oct. 6, 2006, 120 Stat. 1735, 1736.)
71 |
72 |
73 |
74 |
Historical and Revision Notes
75 |
Revised
Section
Source (U.S. Code)
Source (Statutes at Large)
76 |
77 |
321(a)
78 |
40:756(a) (1st sentence).
79 |
June 30, 1949, ch. 288, title I, §109(a)–(c), (e), (f), 63 Stat. 382; Sept. 5, 1950, ch. 849, §§1, 2(a), (b), 3(a), 64 Stat. 578, 579; July 12, 1952, ch. 703, §1(c)–(e), 66 Stat. 593; Pub. L. 87–372, Oct. 4, 1961, 75 Stat. 802; Pub. L. 87–600, §1(a), (b), (d), Aug. 24, 1962, 76 Stat. 401; Pub. L. 93–604, title VII, §701, Jan. 2, 1975, 88 Stat. 1963; Pub. L. 94–273, §2(19), Apr. 21, 1976, 90 Stat. 375; Pub. L. 100–202, §101(m) [title VI, §619(a), (b)], Dec. 22, 1987, 101 Stat. 1329–427.
80 |
81 |
82 |
321(b)(1)
83 |
40:756(a) (2d sentence).
84 |
85 |
86 |
87 |
321(b)(2)
88 |
40:756(c).
89 |
90 |
91 |
92 |
321(b)(3)
93 |
40:756(g) (last sentence).
94 |
June 30, 1949, ch. 288, title I, §109(g) (last sentence), as added Sept. 5, 1950, ch. 849, §3(b), 64 Stat. 579; Pub. L. 86–591, July 5, 1960, 74 Stat. 330.
95 |
96 |
97 |
321(c)(1)
98 |
40:756(a) (last sentence).
99 |
100 |
101 |
102 |
321(c)(2)
103 |
40:756(f).
104 |
105 |
106 |
107 |
321(d)
108 |
40:756(b).
109 |
110 |
111 |
112 |
321(e)
113 |
40:756b.
114 |
Pub. L. 99–500, §151, Oct. 18, 1986, 100 Stat. 1783–352; Pub. L. 99–591, §151, Oct. 30, 1986, 100 Stat. 3341–355; Pub. L. 100–202, §101(i) [title I, §4], Dec. 22, 1987, 101 Stat. 1329–294; Pub. L. 104–186, title II, §221(15), Aug. 20, 1996, 110 Stat. 1750.
115 |
116 |
117 |
321(f)(1)
118 |
40:756(e)(1).
119 |
120 |
121 |
122 |
321(f)(2)
123 |
40:756a.
124 |
Pub. L. 97–12, title I, (proviso in par. under heading “General Supply Fund”), June 5, 1981, 95 Stat. 75.
125 |
126 |
127 |
321(g)
128 |
40:756(e)(2).
129 |
130 |
131 |
132 |
133 |
In subsection (b)(1), the words “the assets of the general supply fund (including any surplus therein) created by section 3 of the Act of February 27, 1929 (45 Stat. 1342; 41 U.S.C. 7c), and transferred to the Administrator by section 752 of this title” and “the fund shall assume all of the liabilities, obligations, and commitments of the general supply fund created by such Act of February 27, 1929” are omitted as executed and obsolete.
134 |
In subsection (b)(2)(B), the words “Amounts credited under this paragraph” are substituted for “and the same” for clarity.
135 |
In subsection (c)(2), the words “Subject to the requirements of subsections (a) to (e) of this section” are omitted as unnecessary.
136 |
In subsection (d)(1), the words “For property or services procured through the Fund for requisitioning agencies” are added for clarity.
137 |
In subsection (d)(2)(B), the words “with respect to the supplies or services concerned” are omitted as included in “properly allocable costs”.
138 |
In subsection (e), the text of 40:756b(b) and the words “Notwithstanding any other provision of law” are omitted as unnecessary.
139 |
In subsection (f)(2), the words “on and after June 5, 1981” are omitted as obsolete.
140 |
141 |
142 |
Amendments
143 |
2006—Pub. L. 109–313, §3(h)(2), substituted “Acquisition Services Fund” for “General Supply Fund” in section catchline.
144 |
Subsecs. (a), (b). Pub. L. 109–313, §3(d), amended subsecs. (a) and (b) generally. Prior to amendment, subsecs. (a) and (b) related to the existence and composition, respectively, of the General Supply Fund.
145 |
Subsec. (c)(1)(A)(iii). Pub. L. 109–313, §3(e), added cl. (iii).
146 |
Subsec. (d)(2)(A)(v), (vi). Pub. L. 109–313, §3(f), added cl. (v) and redesignated former cl. (v) as (vi).
147 |
Subsec. (f). Pub. L. 109–313, §3(g), amended heading and text of subsec. (f) generally. Prior to amendment, text read as follows:
148 |
“(1) Surplus deposited in treasury.—As of September 30 of each year, any surplus in the Fund above the amounts transferred or appropriated to establish and maintain the Fund (all assets, liabilities, and prior losses considered) shall be deposited in the Treasury as miscellaneous receipts.
149 |
“(2) Surplus retained.—From any surplus generated by operation of the Fund, the Administrator may retain amounts necessary to maintain a sufficient level of inventory of personal property to meet the needs of the federal agencies.”
150 |
151 |
152 |
Effective Date of 2006 Amendment
153 |
Amendment by Pub. L. 109–313 effective 60 days after Oct. 6, 2006, see section 6 of Pub. L. 109–313, set out as a note under section 5316 of Title 5, Government Organization and Employees.
“(a) Abolishment of General Supply Fund and Information Technology Fund.—The General Supply Fund and the Information Technology Fund in the Treasury are hereby abolished.
159 |
“(b) Transfers.—Capital assets and balances remaining in the General Supply Fund and the Information Technology Fund as in existence immediately before this section takes effect [see Effective Date of 2006 Amendment note above] shall be transferred to the Acquisition Services Fund and shall be merged with and be available for the purposes of the Acquisition Services Fund under section 321 of title 40, United States Code (as amended by this Act).
160 |
“(c) Assumption of Obligations.—Any liabilities, commitments, and obligations of the General Supply Fund and the Information Technology Fund as in existence immediately before this section takes effect shall be assumed by the Acquisition Services Fund.”
161 |
162 |
163 |
164 |
165 |
--------------------------------------------------------------------------------
/tests/testLinked.html:
--------------------------------------------------------------------------------
1 | U.S.C. Title 40 - PUBLIC BUILDINGS, PROPERTY, AND WORKS
2 | 40 U.S.C.
3 | United States Code, 2011 Edition
4 | Title 40 - PUBLIC BUILDINGS, PROPERTY, AND WORKS
5 | SUBTITLE I - FEDERAL PROPERTY AND ADMINISTRATIVE SERVICES
6 | CHAPTER 3 - 1-ORGANIZATION OF GENERAL SERVICES ADMINISTRATION
7 | SUBCHAPTER III - FUNDS
8 | Sec. 321 - Acquisition Services Fund
9 | From the U.S. Government Printing Office, www.gpo.gov
10 |
11 |
12 |
13 |
14 |
15 |
§321. Acquisition Services Fund
16 |
17 |
18 |
(a) Existence.—The Acquisition Services Fund is a special fund in the Treasury.
19 |
(b) Composition.—
20 |
(1) In general.—The Fund is composed of amounts authorized to be transferred to the Fund or otherwise made available to the Fund.
21 |
(2) Other credits.—The Fund shall be credited with all reimbursements, advances, and refunds or recoveries relating to personal property or services procured through the Fund, including—
22 |
(A) the net proceeds of disposal of surplus personal property; and
23 |
(B) receipts from carriers and others for loss of, or damage to, personal property; and
24 |
(C) receipts from agencies charged fees pursuant to rates established by the Administrator.
25 |
26 |
(3) Cost and capital requirements.—The Administrator shall determine the cost and capital requirements of the Fund for each fiscal year and shall develop a plan concerning such requirements in consultation with the Chief Financial Officer of the General Services Administration. Any change to the cost and capital requirements of the Fund for a fiscal year shall be approved by the Administrator. The Administrator shall establish rates to be charged agencies provided, or to be provided, supply of personal property and non-personal services through the Fund, in accordance with the plan.
27 |
(4) Deposit of fees.—Fees collected by the Administrator under section 313 of this title may be deposited in the Fund to be used for the purposes of the Fund.
28 |
29 |
(c) Uses.—
30 |
(1) In general.—The Fund is available for use by or under the direction and control of the Administrator for—
31 |
(A) procuring, for the use of federal agencies in the proper discharge of their responsibilities—
32 |
(i) personal property (including the purchase from or through the Public Printer, for warehouse issue, of standard forms, blankbook work, standard specifications, and other printed material in common use by federal agencies and not available through the Superintendent of Documents);
33 |
(ii) nonpersonal services; and
34 |
(iii) personal services related to the provision of information technology (as defined in section 11101(6) of this title);
35 |
36 |
(B) paying the purchase price, cost of transportation of personal property and services, and cost of personal services employed directly in the repair, rehabilitation, and conversion of personal property; and
37 |
(C) paying other direct costs of, and indirect costs that are reasonably related to, contracting, procurement, inspection, storage, management, distribution, and accountability of property and nonpersonal services provided by the General Services Administration or by special order through the Administration.
38 |
39 |
(2) Other uses.—The Fund may be used for the procurement of personal property and nonpersonal services authorized to be acquired by—
40 |
(A) mixed-ownership Government corporations;
41 |
(B) the municipal government of the District of Columbia; or
42 |
(C) a requisitioning non-federal agency when the function of a federal agency authorized to procure for it is transferred to the Administration.
43 |
44 |
(d) Payment for Property and Services.—
45 |
(1) In general.—For property or services procured through the Fund for requisitioning agencies, the agencies shall pay prices the Administrator fixes under this subsection.
46 |
(2) Prices fixed by administrator.—The Administrator shall fix prices at levels sufficient to recover—
47 |
(A) so far as practicable—
48 |
(i) the purchase price;
49 |
(ii) the transportation cost;
50 |
(iii) inventory losses;
51 |
(iv) the cost of personal services employed directly in the repair, rehabilitation, and conversion of personal property;
52 |
(v) the cost of personal services employed directly in providing information technology (as defined in section 11101(6) of this title); and
53 |
(vi) the cost of amortization and repair of equipment used for lease or rent to executive agencies; and
54 |
55 |
(B) properly allocable costs payable by the Fund under subsection (c)(1)(C).
56 |
57 |
(3) Timing of payments.—
58 |
(A) Payment in advance.—A requisitioning agency shall pay in advance when the Administrator determines that there is insufficient capital otherwise available in the Fund. Payment in advance may also be made under an agreement between a requisitioning agency and the Administrator.
59 |
(B) Prompt reimbursement.—If payment is not made in advance, the Administration shall be reimbursed promptly out of amounts of the requisitioning agency in accordance with accounting procedures approved by the Comptroller General.
60 |
(C) Failure to make prompt reimbursement.—The Administrator may obtain reimbursement by the issuance of transfer and counterwarrants, or other lawful transfer documents, supported by itemized invoices, if payment is not made by a requisitioning agency within 45 days after the later of—
61 |
(i) the date of billing by the Administrator; or
62 |
(ii) the date on which actual liability for personal property or services is incurred by the Administrator.
63 |
64 |
(e) Reimbursement for Equipment Purchased for Congress.—The Administrator may accept periodic reimbursement from the Senate and from the House of Representatives for the cost of any equipment purchased for the Senate or the House of Representatives with money from the Fund. The amount of each periodic reimbursement shall be computed by amortizing the total cost of each item of equipment over the useful life of the equipment, as determined by the Administrator, in consultation with the Sergeant at Arms and Doorkeeper of the Senate or the Chief Administrative Officer of the House of Representatives, as appropriate.
65 |
(f) Transfer of Uncommitted Balances.—Following the close of each fiscal year, after making provision for a sufficient level of inventory of personal property to meet the needs of Federal agencies, the replacement cost of motor vehicles, and other anticipated operating needs reflected in the cost and capital plan developed under subsection (b), the uncommitted balance of any funds remaining in the Fund shall be transferred to the general fund of the Treasury as miscellaneous receipts.
66 |
(g) Audits.—The Comptroller General shall audit the Fund in accordance with the provisions of chapter 35 of title 31 and report the results of the audits.
June 30, 1949, ch. 288, title I, §109(g) (last sentence), as added Sept. 5, 1950, ch. 849, §3(b), 64 Stat. 579; Pub. L. 86–591, July 5, 1960, 74 Stat. 330.
Pub. L. 97–12, title I, (proviso in par. under heading “General Supply Fund”), June 5, 1981, 95 Stat. 75.
124 |
125 |
126 |
321(g)
127 |
40:756(e)(2).
128 |
129 |
130 |
131 |
132 |
In subsection (b)(1), the words “the assets of the general supply fund (including any surplus therein) created by section 3 of the Act of February 27, 1929 (45 Stat. 1342; 41 U.S.C. 7c), and transferred to the Administrator by section 752 of this title” and “the fund shall assume all of the liabilities, obligations, and commitments of the general supply fund created by such Act of February 27, 1929” are omitted as executed and obsolete.
133 |
In subsection (b)(2)(B), the words “Amounts credited under this paragraph” are substituted for “and the same” for clarity.
134 |
In subsection (c)(2), the words “Subject to the requirements of subsections (a) to (e) of this section” are omitted as unnecessary.
135 |
In subsection (d)(1), the words “For property or services procured through the Fund for requisitioning agencies” are added for clarity.
136 |
In subsection (d)(2)(B), the words “with respect to the supplies or services concerned” are omitted as included in “properly allocable costs”.
137 |
In subsection (e), the text of 40:756b(b) and the words “Notwithstanding any other provision of law” are omitted as unnecessary.
138 |
In subsection (f)(2), the words “on and after June 5, 1981” are omitted as obsolete.
139 |
140 |
141 |
Amendments
142 |
2006—Pub. L. 109–313, §3(h)(2), substituted “Acquisition Services Fund” for “General Supply Fund” in section catchline.
143 |
Subsecs. (a), (b). Pub. L. 109–313, §3(d), amended subsecs. (a) and (b) generally. Prior to amendment, subsecs. (a) and (b) related to the existence and composition, respectively, of the General Supply Fund.
144 |
Subsec. (c)(1)(A)(iii). Pub. L. 109–313, §3(e), added cl. (iii).
145 |
Subsec. (d)(2)(A)(v), (vi). Pub. L. 109–313, §3(f), added cl. (v) and redesignated former cl. (v) as (vi).
146 |
Subsec. (f). Pub. L. 109–313, §3(g), amended heading and text of subsec. (f) generally. Prior to amendment, text read as follows:
147 |
“(1) Surplus deposited in treasury.—As of September 30 of each year, any surplus in the Fund above the amounts transferred or appropriated to establish and maintain the Fund (all assets, liabilities, and prior losses considered) shall be deposited in the Treasury as miscellaneous receipts.
148 |
“(2) Surplus retained.—From any surplus generated by operation of the Fund, the Administrator may retain amounts necessary to maintain a sufficient level of inventory of personal property to meet the needs of the federal agencies.”
“(a) Abolishment of General Supply Fund and Information Technology Fund.—The General Supply Fund and the Information Technology Fund in the Treasury are hereby abolished.
158 |
“(b) Transfers.—Capital assets and balances remaining in the General Supply Fund and the Information Technology Fund as in existence immediately before this section takes effect [see Effective Date of 2006 Amendment note above] shall be transferred to the Acquisition Services Fund and shall be merged with and be available for the purposes of the Acquisition Services Fund under section 321 of title 40, United States Code (as amended by this Act).
159 |
“(c) Assumption of Obligations.—Any liabilities, commitments, and obligations of the General Supply Fund and the Information Technology Fund as in existence immediately before this section takes effect shall be assumed by the Acquisition Services Fund.”