├── CNAME ├── README.md ├── _config.yml ├── _layouts └── default.html ├── api.html ├── cli.md ├── coding-standards.html ├── config.md ├── images ├── bg_hr.png ├── blacktocat.png ├── icon_download.png └── sprite_download.png ├── index.html ├── installation.md ├── introduction.md ├── javascripts ├── main.js └── scale.fix.js ├── params.json ├── parser.md ├── release-process.md ├── search.md ├── stylesheets ├── pygment_trac.css ├── styles.css └── stylesheet.css ├── templates.md └── xml-format.html /CNAME: -------------------------------------------------------------------------------- 1 | docs.statedecoded.com 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Documentation 2 | ============= 3 | 4 | Guides to using The State Decoded, whether deploying a site or using the data from one. 5 | 6 | All files can be found [in the gh-pages branch](https://github.com/statedecoded/documentation/tree/gh-pages). 7 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | markdown: kramdown -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{ page.title }} 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 |
18 | 19 |
20 |

The State Decoded Documentation

21 |

{{ page.title }}

22 |
23 | 24 |
25 | {{ content }} 26 |
27 | 28 |

Edit this on GitHub

29 | 30 | 34 |
35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /api.html: -------------------------------------------------------------------------------- 1 | --- 2 | title: API 3 | layout: default 4 | --- 5 | 6 |

Contents

7 | 8 | 21 | 22 |

How to...

23 | 24 |

...get an API key.

25 | 26 |

Register for a key on the site in question (e.g., Virginia).

27 | 28 |

...browse the Code starting at the root.

29 | 30 |

http://vacode.org/api/structure/?key=[api_key]

31 | 32 |

...get information about a given law.

33 | 34 |

http://vacode.org/api/law/[section_number]?key=[api_key]

35 | 36 |

...get a information about a given title/chapter/part/etc.

37 | 38 |

http://vacode.org/api/structure/[identifier]?key=[api_key]

39 | 40 |

...get all definitions for a word or phrase.

41 | 42 |

http://vacode.org/api/dictionary/[term]?key=[api_key]

43 | 44 |

...get the definition for a word or phrase as it's used in a specific law.

45 | 46 |

http://vacode.org/api/dictionary/[term]?section=[section_number]&key=[api_key]

47 | 48 |

...restrict the fields that are returned.

49 | 50 |

Append &fields=field1,field2,field3 to the query, substituting the desired field names for "field1," etc.

51 | 52 |

Methods

53 | 54 |

Dictionary

55 | 56 |

When provided with a term, returns all definitions for that term found within the code. Optionally, when provided with a section identifier and no term, returns all terms that apply within the scope of that section.

57 | 58 |

Query format

59 | 60 |

61 | http://vacode.org/api/dictionary/[word_or_phrase]?key=[api_key] 62 |

63 | 64 |

Optional parameters

65 | 66 |

Section number

67 | 68 |

Pass the parameter section and a section number, and get only the definition of the term that is relevant to that law. (Most terms have a defined scope of a given structural unit or law.) N.B.: Because only one definition is returned, rather than providing an array of definitions, just a single definition’s fields are returned. They are not stored as the lone element in an array, but are at the top level of the JSON.

69 | 70 |

71 | http://vacode.org/api/dictionary/person?section=12.1-14&key=[api_key] 72 | http://vacode.org/api/dictionary/?section=12.1-14&key=[api_key] 73 |

74 | 75 |

Callback

76 | 77 |

Pass the parameter callback and a callback string to have results returned as JSONP.

78 | 79 |

80 | http://vacode.org/api/dictionary/[word_or_phrase]?key=[api_key]&callback=d9f3lIb013 81 |

82 | 83 |

Specified fields

84 | 85 |

Pass the parameter fields and a comma-separated listing of fields to limit the response to those fields.

86 | 87 |

88 | http://vacode.org/api/dictionary/word_or_phrase]?key=[api_key]&fields=definition 89 |

90 | 91 |

Fields

92 | 93 |

When looking up a definition

94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 |
NameTypeDescriptionNotes
termstringThe term that is being defined.
definitionstringThe text of the definition.
scopestringHow broadly that this definition applies.This is based on the structural unit labels, which vary between implementations. Possible values might be title, chapter, part, or others. A definition that applies to just one law would have a value of section, while a definition that applies to the whole code would have a value of global.
section_numberstringThe unique identifier for the section in which the definition appears.
urlstringThe URL of the section in which the definition appears.
formattedstringThe definition, with display-ready formatting and a citation.This is the same as the content of definition, with typographic niceties and a parenthetical citation.
genericbooleanDetermines if the query should include terms from the generic dictionary.Overrides the USE_GENERIC_TERMS setting.
api_versionintegerThe version of the API that is returning this result.
164 | 165 |

Term list

166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 |
NameTypeDescriptionNotes
termstringThe term that is being defined.
187 | 188 |

Sample queries and responses

189 | 190 |

191 | http://vacode.org/api/dictionary/person?section=12.1-14&key=[api_key] 192 |

193 | 194 |

 195 | {
 196 |     "term": "person",
 197 |     "definition": "“Person” includes any individual, corporation, partnership, association, cooperative, limited liability company, trust, joint venture, government, political subdivision, or any other legal or commercial entity and any successor, representative, agent, agency, or instrumentality thereof.",
 198 |     "section_number": "1-230",
 199 |     "scope": "global",
 200 |     "url": "http://vacode.org/1-230/",
 201 |     "formatted": "“Person” includes any individual, corporation, partnership, association, cooperative, limited liability company, trust, joint venture, government, political subdivision, or any other legal or commercial entity and any successor, representative, agent, agency, or instrumentality thereof. (<a href=\"http://vacode.org/1-230/\">§&nbsp;1-230<\/a>)",
 202 |     "api_version": "1.0"
 203 | }
 204 | 
205 | 206 | Edited for brevity. 207 | 208 |

209 | http://vacode.org/api/dictionary/?section=12.1-14&key=[api_key] 210 |

211 | 212 |

 213 | {
 214 | 	0: "adult",
 215 | 	1: "bond with surety",
 216 | 	2: "state agency",
 217 | 	3: "city",
 218 | 	4: "collegial body",
 219 | 	5: "courts of record",
 220 | 	6: "ex officio",
 221 | 	7: "includes",
 222 | 	8: "real estate",
 223 | 	9: "blighted property",
 224 | 	api_version: "1.0"
 225 | }
 226 | 
227 | 228 |

Law

229 | 230 |

When provided with a section number identifying an individual law, returns everything that The State Decoded knows about that law.

231 | 232 |

Query format

233 | 234 |

235 | http://vacode.org/api/law/[section_number]?key=[api_key] 236 |

237 | 238 |

Optional parameters

239 | 240 |

Callback

241 | 242 |

Pass the parameter callback and a callback string to have results returned as JSONP.

243 | 244 |

245 | http://vacode.org/api/law/[section_number]?key=[api_key]&callback=d9f3lIb013 246 |

247 | 248 |

Specified fields

249 | 250 |

Pass the parameter fields and a comma-separated listing of fields to limit the response to those fields.

251 | 252 |

253 | http://vacode.org/api/law/[section_number]?key=[api_key]&fields=catch_line,url_official_url,citation 254 |

255 | 256 |

Fields

257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 |
NameTypeDescriptionNotes
section_numberstringThe unique identifier for this section.
section_idintegerInternal unique identifier for this law.
structure_idintegerInternal unique identifier for the law's containing structural unit.
catch_linestring or nullThe title of this section.Not all legal codes have catch lines. California's laws, for instance, lack them.
historystring or nullThe acts of the legislature that created this law.Only some legal codes include histories.
full_textstringThe complete text of the law as a single string of text.This duplicates the collective contents of `text`, but concatenates all subsections into a single string.
repealedtrue/falseIndicates whether this law is still in force.Only some legal codes continue to publish laws that have been repealed.
textarrayContains the subsections of text that comprise this law.There is one child element for each subsection. Some codes may be broken up not by labelled subsection, but by paragraphs that lack any labels or unique identifiers.
327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 |
textstringThe text of the subsection.
typestringWhat type of subsection this is—`section` (the default), `table`, `illustration`, or possibly others, as dictated by the needs of each legal code.
prefixesarrayA list of of the complete prefix path that uniquely identifies this subsection.
prefixstring or nullThis subsection's identifying prefix.
entire_prefixstring or nullThe complete, uniquely identifying prefix for this subsection.The same data that's in `prefixes`, only collapsed into a single string.
prefix_anchorstring or nullThe complete, uniquely identifying prefix for this subsection, ready to be used in a URL.This is `entire_prefix`, URL encoded.
levelintegerHow deeply nested that this level is, in the hierarchy of subsections. 1 is the top level.
372 | 373 |

ancestryarrayContains a subsection for each hierarchically nested structural unit that contains this law.

385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 |
idintegerInternal unique identifier for this structural unit.
namestringThe title of this structural unit.
identifierstringThe identifer for this structural unit.This will often—but not always—be a number.
labelstringThe name of this level of structural unit.
urlstringThe public (non-API) URL for this structural unit.
420 | 421 |

structure_contentsarrayContains a subsection for each law that is part of the immediate structural unit (siblings of the requested section).

433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 |
idintegerInternal unique identifier for this law.
structure_idintegerInternal unique identifier for the containing structural unit.
section_numberstringThe unique identifier for this section.
catch_linestring or nullThe title of this section.Not all legal codes have catch lines. California's laws, for instance, lack them.
urlstringThe public (non-API) URL for this law.
api_urlstringThe API URL for this law.
479 | 480 |

previous_sectionarrayThe prior law within the containing structural unit, as ordered.

492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 |
idintegerInternal unique identifier for this law.
structure_idintegerInternal unique identifier for the containing structural unit.
section_numberstringThe unique identifier for this section.
catch_linestring or nullThe title of this section.Not all legal codes have catch lines. California's laws, for instance, lack them.
urlstringThe public (non-API) URL for this law.
api_urlstringThe API URL for this law.
538 | 539 |

next_sectionarrayThe following law within the containing structural unit, as ordered.

551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 |
idintegerInternal unique identifier for this law.
structure_idintegerInternal unique identifier for the containing structural unit.
section_numberstringThe unique identifier for this section.
catch_linestring or nullThe title of this section.Not all legal codes have catch lines. California's laws, for instance, lack them.
urlstringThe public (non-API) URL for this law.
api_urlstringThe API URL for this law.
597 | 598 |

metadataarray, or nullContains all metadata about this law that is stored separately in the metadata table.By default, this contains nothing, but any State Decoded implementation that wants to store additional metadata about laws—data beyond the structure otherwise described here—would emit that metadata here.
court_decisionsarray, or nullEvery court decision that cites this law.Only available within State Decoded implementations that have chosen to ingest court rulings.
official_urlstring, or nullThe URL for this law on the official website for this legal code.
history_textstring, or nullA narrative version of the history field.
referencesarrayA listing of all other laws that refer to this one.

638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 |
idintegerInternal unique identifier for this law.
section_numberstringThe unique identifier for this section.
catch_linestring or nullThe title of this section.Not all legal codes have catch lines. California's laws, for instance, lack them.
urlstringThe public (non-API) URL for this law.
670 | 671 |

relatedarrayA list of all other laws that are have been determined through lexical analysis to be similar to this one.This list is generated by Solr's MoreLikeThis handler.

683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 |
idintegerInternal unique identifier for this law.
catch_linestring or nullThe title of this section.Not all legal codes have catch lines. California's laws, for instance, lack them.
section_numberstringThe unique identifier for this section.
urlstringThe public (non-API) URL for this law.
715 | 716 |

amendment_yearsarrayA list of every year in which this law was amended.
urlstringThe public (non-API) URL for this law.
citationarrayA list of formal citation methods for this law.

742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 |
officialstringA formal citation for this law, in The Bluebook format.
universalstringA formal citation for this law, in the AALL Universal Citation Guide format.
759 | 760 |

api_versionintegerThe version of the API that is returning this result.
772 | 773 |

Sample query and response

774 | 775 |

Edited for brevity.

776 | 777 |

 778 | http://vacode.org/api/law/15.2-627?key=[api_key]
 779 | 
780 | 781 |

 782 | {
 783 |     "section_number": "15.2-627",
 784 |     "section_id": "7508",
 785 |     "structure_id": "1980",
 786 |     "catch_line": "Department of education.",
 787 |     "history": "Code 1950, § 15-324; 1956, c. 153; 1962, c. 623, § 15.1-644; 1980, c. 559; 1981, c. 246; 1982, cc. 32, 75; 1995, c. 8; 1996, c. 873; 1997, c. 587.",
 788 |     "full_text": "<p>The department of education shall consist of the county school board, the division superintendent of schools and the officers and employees thereof. Except as herein otherwise provided, the county school board and the division superintendent of schools shall exercise all the powers conferred and perform all the duties imposed upon them by general law. Except for the initial elected board which shall consist of five members, the county school board shall be composed of not less than three nor more than nine members; however, there shall be at least one school board member elected from each of the county’s magisterial or election districts. The members shall be elected by popular vote from election districts coterminous with the election districts for the board of county supervisors. The exact number of members shall be determined by the board of county supervisors. Elections of school board members shall be held to coincide with the elections of members of the board of county supervisors at the regular general election in November. The terms of office for the county school board members shall be the same as the terms of the members of the board of county supervisors and shall commence on January 1 following their election.<\/p><p>A vacancy in the office of school board member shall be filled pursuant to §§ 24.2-226 and 24.2-228.<\/p><p>In order to have their names placed on the ballot, all candidates shall be nominated only by petition as provided by general law pursuant to § 24.2-506.<\/p><p>The county school board may also appoint a resident of the county to cast the deciding vote in case of a tie vote of the school board as provided in § 22.1-75. The tie breaker, if any, shall be appointed for a four-year term whether appointed to fill a vacancy caused by expiration of term or otherwise.<\/p><p>The chairman of the county school board, for the purpose of appearing before the board of county supervisors, shall be considered head of this department, unless some other person in the department shall be designated by the school board for such purpose.<\/p>",
 789 |     "repealed": "n",
 790 |     "text": {
 791 |         "0": {
 792 |             "text": "The department of education shall consist of the county school board, the division superintendent of schools and the officers and employees thereof. Except as herein otherwise provided, the county school board and the division superintendent of schools shall exercise all the powers conferred and perform all the duties imposed upon them by general law. Except for the initial elected board which shall consist of five members, the county school board shall be composed of not less than three nor more than nine members; however, there shall be at least one school board member elected from each of the county’s magisterial or election districts. The members shall be elected by popular vote from election districts coterminous with the election districts for the board of county supervisors. The exact number of members shall be determined by the board of county supervisors. Elections of school board members shall be held to coincide with the elections of members of the board of county supervisors at the regular general election in November. The terms of office for the county school board members shall be the same as the terms of the members of the board of county supervisors and shall commence on January 1 following their election.",
 793 |             "type": "section",
 794 |             "prefixes": [
 795 |                 ""
 796 |             ],
 797 |             "prefix": "",
 798 |             "entire_prefix": "",
 799 |             "prefix_anchor": "",
 800 |             "level": 1
 801 |         },
 802 |         "1": {
 803 |             "text": "A vacancy in the office of school board member shall be filled pursuant to §§ 24.2-226 and 24.2-228.",
 804 |             "type": "section",
 805 |             "prefixes": [
 806 |                 ""
 807 |             ],
 808 |             "prefix": "",
 809 |             "entire_prefix": "",
 810 |             "prefix_anchor": "",
 811 |             "level": 1
 812 |         },
 813 |         "2": {
 814 |             "text": "In order to have their names placed on the ballot, all candidates shall be nominated only by petition as provided by general law pursuant to § 24.2-506.",
 815 |             "type": "section",
 816 |             "prefixes": [
 817 |                 ""
 818 |             ],
 819 |             "prefix": "",
 820 |             "entire_prefix": "",
 821 |             "prefix_anchor": "",
 822 |             "level": 1
 823 |         },
 824 |         "3": {
 825 |             "text": "The county school board may also appoint a resident of the county to cast the deciding vote in case of a tie vote of the school board as provided in § 22.1-75. The tie breaker, if any, shall be appointed for a four-year term whether appointed to fill a vacancy caused by expiration of term or otherwise.",
 826 |             "type": "section",
 827 |             "prefixes": [
 828 |                 ""
 829 |             ],
 830 |             "prefix": "",
 831 |             "entire_prefix": "",
 832 |             "prefix_anchor": "",
 833 |             "level": 1
 834 |         },
 835 |         "4": {
 836 |             "text": "The chairman of the county school board, for the purpose of appearing before the board of county supervisors, shall be considered head of this department, unless some other person in the department shall be designated by the school board for such purpose.",
 837 |             "type": "section",
 838 |             "prefixes": [
 839 |                 ""
 840 |             ],
 841 |             "prefix": "",
 842 |             "entire_prefix": "",
 843 |             "prefix_anchor": "",
 844 |             "level": 1
 845 |         }
 846 |     },
 847 |     "ancestry": {
 848 |         "1": {
 849 |             "id": "1980",
 850 |             "name": "County Manager Form of Government",
 851 |             "identifier": "6",
 852 |             "label": "chapter",
 853 |             "url": "/15.2/6/"
 854 |         },
 855 |         "2": {
 856 |             "id": "27",
 857 |             "name": "Counties, Cities and Towns",
 858 |             "identifier": "15.2",
 859 |             "label": "title",
 860 |             "url": "/15.2/"
 861 |         }
 862 |     },
 863 |     "structure_contents": {
 864 |         "0": {
 865 |             "id": "7481",
 866 |             "structure_id": "1980",
 867 |             "section_number": "15.2-600",
 868 |             "catch_line": "Designation of form; applicability of chapter.",
 869 |             "url": "http://vacode.org/15.2-600/",
 870 |             "api_url": "http://vacode.org/api/law/15.2-600/"
 871 |         },
 872 |         "1": {
 873 |             "id": "7482",
 874 |             "structure_id": "1980",
 875 |             "section_number": "15.2-601",
 876 |             "catch_line": "Adoption of county manager form.",
 877 |             "url": "http://vacode.org/15.2-601/",
 878 |             "api_url": "http://vacode.org/api/law/15.2-601/"
 879 |         },
 880 |         "2": {
 881 |             "id": "7483",
 882 |             "structure_id": "1980",
 883 |             "section_number": "15.2-602",
 884 |             "catch_line": "Powers vested in board of supervisors; election and terms of members; vacancies.",
 885 |             "url": "http://vacode.org/15.2-602/",
 886 |             "api_url": "http://vacode.org/api/law/15.2-602/"
 887 |         },
 888 |         "3": {
 889 |             "id": "7484",
 890 |             "structure_id": "1980",
 891 |             "section_number": "15.2-603",
 892 |             "catch_line": "Referendum on election of supervisors by districts or at large.",
 893 |             "url": "http://vacode.org/15.2-603/",
 894 |             "api_url": "http://vacode.org/api/law/15.2-603/"
 895 |         },
 896 |         "4": {
 897 |             "id": "7485",
 898 |             "structure_id": "1980",
 899 |             "section_number": "15.2-604",
 900 |             "catch_line": "General powers of board.",
 901 |             "url": "http://vacode.org/15.2-604/",
 902 |             "api_url": "http://vacode.org/api/law/15.2-604/"
 903 |         },
 904 |         "5": {
 905 |             "id": "7486",
 906 |             "structure_id": "1980",
 907 |             "section_number": "15.2-605",
 908 |             "catch_line": "Prohibiting misdemeanors and providing penalties.",
 909 |             "url": "http://vacode.org/15.2-605/",
 910 |             "api_url": "http://vacode.org/api/law/15.2-605/"
 911 |         },
 912 |         "6": {
 913 |             "id": "7487",
 914 |             "structure_id": "1980",
 915 |             "section_number": "15.2-606",
 916 |             "catch_line": "Investigation of county officers.",
 917 |             "url": "http://vacode.org/15.2-606/",
 918 |             "api_url": "http://vacode.org/api/law/15.2-606/"
 919 |         },
 920 |         "7": {
 921 |             "id": "7488",
 922 |             "structure_id": "1980",
 923 |             "section_number": "15.2-607",
 924 |             "catch_line": "Organization of departments.",
 925 |             "url": "http://vacode.org/15.2-607/",
 926 |             "api_url": "http://vacode.org/api/law/15.2-607/"
 927 |         },
 928 |         "8": {
 929 |             "id": "7489",
 930 |             "structure_id": "1980",
 931 |             "section_number": "15.2-608",
 932 |             "catch_line": "Designation of officers to perform certain duties.",
 933 |             "url": "http://vacode.org/15.2-608/",
 934 |             "api_url": "http://vacode.org/api/law/15.2-608/"
 935 |         },
 936 |         "9": {
 937 |             "id": "7490",
 938 |             "structure_id": "1980",
 939 |             "section_number": "15.2-609",
 940 |             "catch_line": "Appointment of county manager.",
 941 |             "url": "http://vacode.org/15.2-609/",
 942 |             "api_url": "http://vacode.org/api/law/15.2-609/"
 943 |         },
 944 |         "10": {
 945 |             "id": "7491",
 946 |             "structure_id": "1980",
 947 |             "section_number": "15.2-610",
 948 |             "catch_line": "Tenure of office; removal.",
 949 |             "url": "http://vacode.org/15.2-610/",
 950 |             "api_url": "http://vacode.org/api/law/15.2-610/"
 951 |         },
 952 |         "11": {
 953 |             "id": "7492",
 954 |             "structure_id": "1980",
 955 |             "section_number": "15.2-611",
 956 |             "catch_line": "Disability of county manager.",
 957 |             "url": "http://vacode.org/15.2-611/",
 958 |             "api_url": "http://vacode.org/api/law/15.2-611/"
 959 |         },
 960 |         "12": {
 961 |             "id": "7493",
 962 |             "structure_id": "1980",
 963 |             "section_number": "15.2-612",
 964 |             "catch_line": "Manager responsible for administration of affairs of county; appointment of officers and employees.",
 965 |             "url": "http://vacode.org/15.2-612/",
 966 |             "api_url": "http://vacode.org/api/law/15.2-612/"
 967 |         }
 968 |     },
 969 |     "previous_section": {
 970 |         "id": "7507",
 971 |         "structure_id": "1980",
 972 |         "section_number": "15.2-626",
 973 |         "catch_line": "Department and board of social services.",
 974 |         "url": "http://vacode.org/15.2-626/",
 975 |         "api_url": "http://vacode.org/api/law/15.2-626/"
 976 |     },
 977 |     "next_section": {
 978 |         "id": "7509",
 979 |         "structure_id": "1980",
 980 |         "section_number": "15.2-628",
 981 |         "catch_line": "Terms of school boards.",
 982 |         "url": "http://vacode.org/15.2-628/",
 983 |         "api_url": "http://vacode.org/api/law/15.2-628/"
 984 |     },
 985 |     "metadata": {
 986 |         "history": {
 987 |             "1": {
 988 |                 "year": "1956",
 989 |                 "chapter": "153"
 990 |             },
 991 |             "2": {
 992 |                 "year": "1962",
 993 |                 "chapter": "623",
 994 |                 "section": "1962, c. 623, § 15.1-644"
 995 |             },
 996 |             "3": {
 997 |                 "year": "1980",
 998 |                 "chapter": "559"
 999 |             },
1000 |             "4": {
1001 |                 "year": "1981",
1002 |                 "chapter": "246"
1003 |             },
1004 |             "5": {
1005 |                 "year": "1982",
1006 |                 "chapter": [
1007 |                     "32",
1008 |                     "75"
1009 |                 ]
1010 |             },
1011 |             "6": {
1012 |                 "year": "1995",
1013 |                 "chapter": "8"
1014 |             },
1015 |             "7": {
1016 |                 "year": "1996",
1017 |                 "chapter": "873"
1018 |             },
1019 |             "8": {
1020 |                 "year": "1997",
1021 |                 "chapter": "587"
1022 |             }
1023 |         }
1024 |     },
1025 |     "court_decisions": false,
1026 |     "official_url": "http://lis.virginia.gov/cgi-bin/legp604.exe?000+cod+15.2-627",
1027 |     "history_text": "This law has been modified 7 times since it was first created in 1956. Those modifications are cataloged by “The Acts of Assembly,” a state publication, by year and chapter. Those modifications that can be read on the General Assembly’s website will be linked accordingly. Those modifications are as follows: in 1962, chapter 623; in 1980, chapter 559; in 1981, chapter 246; in 1982, chapters 32, 75; in 1995 chapter <a href=\"http://leg1.state.va.us/cgi-bin/legp504.exe?951+ful+CHAP0008\">8<\/a>; in 1996 chapter <a href=\"http://leg1.state.va.us/cgi-bin/legp504.exe?961+ful+CHAP0873\">873<\/a>; in 1997 chapter <a href=\"http://leg1.state.va.us/cgi-bin/legp504.exe?971+ful+CHAP0587\">587<\/a>.",
1028 |     "references": [
1029 |         {
1030 |             "id": "12528",
1031 |             "section_number": "22.1-29.1",
1032 |             "catch_line": "Public hearing before appointment of school board members.",
1033 |             "url": "http://vacode.org/22.1-29.1/"
1034 |         },
1035 |         {
1036 |             "id": "12533",
1037 |             "section_number": "22.1-34",
1038 |             "catch_line": "Application of article.",
1039 |             "url": "http://vacode.org/22.1-34/"
1040 |         },
1041 |         {
1042 |             "id": "12542",
1043 |             "section_number": "22.1-41",
1044 |             "catch_line": "Application of article.",
1045 |             "url": "http://vacode.org/22.1-41/"
1046 |         },
1047 |         {
1048 |             "id": "12596",
1049 |             "section_number": "22.1-75",
1050 |             "catch_line": "Procedure in case of tie vote.",
1051 |             "url": "http://vacode.org/22.1-75/"
1052 |         }
1053 |     ],
1054 |     "related": {
1055 |         "0": {
1056 |             "id": "7469",
1057 |             "catch_line": "Department of education.",
1058 |             "section_number": "15.2-531",
1059 |             "url": "/15.2-531/"
1060 |         },
1061 |         "1": {
1062 |             "id": "7618",
1063 |             "catch_line": "Department of education.",
1064 |             "section_number": "15.2-837",
1065 |             "url": "/15.2-837/"
1066 |         },
1067 |         "2": {
1068 |             "id": "12566",
1069 |             "catch_line": "Election of school board members; appointment of tie breaker.",
1070 |             "section_number": "22.1-57.3",
1071 |             "url": "/22.1-57.3/"
1072 |         },
1073 |         "3": {
1074 |             "id": "7428",
1075 |             "catch_line": "County school board and division superintendent of schools.",
1076 |             "section_number": "15.2-410",
1077 |             "url": "/15.2-410/"
1078 |         },
1079 |         "4": {
1080 |             "id": "7583",
1081 |             "catch_line": "Powers of county vested in board of supervisors; membership, election, terms, etc., of board; vacancies; powers of chairman.",
1082 |             "section_number": "15.2-802",
1083 |             "url": "/15.2-802/"
1084 |         }
1085 |     },
1086 |     "amendment_years": {
1087 |         "0": "1950",
1088 |         "1": "1956",
1089 |         "2": "1962",
1090 |         "3": "1980",
1091 |         "4": "1981",
1092 |         "5": "1982",
1093 |         "6": "1995",
1094 |         "7": "1996",
1095 |         "8": "1997"
1096 |     },
1097 |     "url": "http://vacode.org/15.2-627/",
1098 |     "citation": {
1099 |         "official": "Va. Code §&nbsp;15.2-627",
1100 |         "universal": "VA Code §&nbsp;15.2-627"
1101 |     },
1102 |     "api_version": "1.0"
1103 | }
1104 | 
1105 | 1106 |

Structure

1107 | 1108 |

When provided with a structural identifier identifying an individual structural unit (e.g., a title, a chapter, a part, etc.), returns everything that The State Decoded knows about that structural unit.

1109 | 1110 |

Query format

1111 | 1112 |

http://vacode.org/api/structure/[identifier]?key=[api_key]

1113 | 1114 |

Leave [identifier] blank to get a top-level listing of structural units—that is, the major structural units that make up the basic divisions of the code (e.g., titles).

1115 | 1116 |

Optional parameters

1117 | 1118 |

Callback

1119 | 1120 |

Pass the parameter callback and a callback string to have results returned as JSONP.

1121 | 1122 |

1123 | http://vacode.org/api/structure/[identifier]?key=[api_key]&callback=d9f3lIb013 1124 |

1125 | 1126 |

Specified fields

1127 | 1128 |

Pass the parameter fields and a comma-separated listing of fields to limit the response to those fields.

1129 | 1130 |

1131 | http://vacode.org/api/structure/[identifier]?key=[api_key]&fields=catch_line,url_official_url,citation 1132 |

1133 | 1134 |

Fields

1135 | 1136 | 1137 | 1138 | 1139 | 1140 | 1141 | 1142 | 1143 | 1144 | 1145 | 1146 | 1147 | 1148 | 1149 | 1150 | 1151 | 1152 | 1153 | 1154 | 1155 | 1204 | 1205 | 1206 | 1207 | 1208 | 1209 | 1210 | 1211 | 1212 | 1213 | 1214 | 1259 | 1260 | 1261 | 1262 | 1263 | 1264 | 1265 | 1266 | 1267 | 1268 | 1269 | 1318 |

1319 | 1320 | 1321 | 1322 | 1323 | 1324 | 1325 | 1326 | 1327 | 1328 |
NameTypeDescriptionNotes
ancestryarrayInformation about every structural unit included in the path specified in the request.
1156 | 1157 | 1158 | 1159 | 1160 | 1161 | 1162 | 1163 | 1164 | 1165 | 1166 | 1167 | 1168 | 1169 | 1170 | 1171 | 1172 | 1173 | 1174 | 1175 | 1176 | 1177 | 1178 | 1179 | 1180 | 1181 | 1182 | 1183 | 1184 | 1185 | 1186 | 1187 | 1188 | 1189 | 1190 | 1191 | 1192 | 1193 | 1194 | 1195 | 1196 | 1197 | 1198 | 1199 | 1200 | 1201 |
idintegerInternal unique identifier for this structural unit.
identifierstringThe identifer for this structural unit.This will often—but not always—be a number.
namestringThe title of this structural unit.
labelstringThe name of this level of structural unit.
parent_idintegerInternal unique identifier for this structural unit’s parent.
levelintegerHow deeply nested that this level is, in the hierarchy of subsections. 1 is the top level.
urlstringThe public (non-API) URL for this structural unit.
1202 | 1203 |

childrenarrayA list of every structural unit that is a child of the requested one.

1215 | 1216 | 1217 | 1218 | 1219 | 1220 | 1221 | 1222 | 1223 | 1224 | 1225 | 1226 | 1227 | 1228 | 1229 | 1230 | 1231 | 1232 | 1233 | 1234 | 1235 | 1236 | 1237 | 1238 | 1239 | 1240 | 1241 | 1242 | 1243 | 1244 | 1245 | 1246 | 1247 | 1248 | 1249 | 1250 | 1251 | 1252 | 1253 | 1254 | 1255 | 1256 |
idintegerInternal unique identifier for this structural unit.
labelstringThe name of this level of structural unit.
namestringThe title of this structural unit.
identifierstringThe identifer for this structural unit.This will often—but not always—be a number.
urlstringThe public (non-API) URL for this structural unit.
api_urlstringThe API URL for this structural unit.
1257 | 1258 |

lawsarrayA list of every law that is a child of the requested structural unit.

1270 | 1271 | 1272 | 1273 | 1274 | 1275 | 1276 | 1277 | 1278 | 1279 | 1280 | 1281 | 1282 | 1283 | 1284 | 1285 | 1286 | 1287 | 1288 | 1289 | 1290 | 1291 | 1292 | 1293 | 1294 | 1295 | 1296 | 1297 | 1298 | 1299 | 1300 | 1301 | 1302 | 1303 | 1304 | 1305 | 1306 | 1307 | 1308 | 1309 | 1310 | 1311 | 1312 | 1313 | 1314 | 1315 |
idintegerInternal unique identifier for this law.
structure_idintegerInternal unique identifier for the containing structural unit.
section_numberstringThe unique identifier for this section.
catch_linestring or nullThe title of this section.Not all legal codes have catch lines. California's laws, for instance, lack them.
urlstringThe public (non-API) URL for this law.
api_urlstringThe API URL for this law.
1316 | 1317 |

api_versionintegerThe version of the API that is returning this result.
1329 | 1330 |

Sample query and response

1331 | 1332 |

1333 | http://vacode.org/api/structure/18.2?key=[api_key] 1334 |

1335 | 1336 |

1337 | {
1338 |     "ancestry": {
1339 |         "0": {
1340 |             "id": "30",
1341 |             "identifier": "18.2",
1342 |             "name": "Crimes and Offenses Generally",
1343 |             "label": "title",
1344 |             "parent_id": "",
1345 |             "level": 1,
1346 |             "url": "http://vacode.org/18.2/"
1347 |         }
1348 |     },
1349 |     "children": {
1350 |         "0": {
1351 |             "id": "2082",
1352 |             "label": "chapter",
1353 |             "name": "In General",
1354 |             "identifier": "1",
1355 |             "url": "http://vacode.org/18.2/1/",
1356 |             "api_url": "http://vacode.org/api/structure/18.2/1/"
1357 |         },
1358 |         "1": {
1359 |             "id": "2083",
1360 |             "label": "chapter",
1361 |             "name": "Principals and Accessories",
1362 |             "identifier": "2",
1363 |             "url": "http://vacode.org/18.2/2/",
1364 |             "api_url": "http://vacode.org/api/structure/18.2/2/"
1365 |         },
1366 |         "2": {
1367 |             "id": "2084",
1368 |             "label": "chapter",
1369 |             "name": "Inchoate Offenses",
1370 |             "identifier": "3",
1371 |             "url": "http://vacode.org/18.2/3/",
1372 |             "api_url": "http://vacode.org/api/structure/18.2/3/"
1373 |         },
1374 |         "3": {
1375 |             "id": "2085",
1376 |             "label": "chapter",
1377 |             "name": "Crimes Against the Person",
1378 |             "identifier": "4",
1379 |             "url": "http://vacode.org/18.2/4/",
1380 |             "api_url": "http://vacode.org/api/structure/18.2/4/"
1381 |         },
1382 |         "4": {
1383 |             "id": "2086",
1384 |             "label": "chapter",
1385 |             "name": "Crimes Against Property",
1386 |             "identifier": "5",
1387 |             "url": "http://vacode.org/18.2/5/",
1388 |             "api_url": "http://vacode.org/api/structure/18.2/5/"
1389 |         },
1390 |         "5": {
1391 |             "id": "2087",
1392 |             "label": "chapter",
1393 |             "name": "Crimes Involving Fraud",
1394 |             "identifier": "6",
1395 |             "url": "http://vacode.org/18.2/6/",
1396 |             "api_url": "http://vacode.org/api/structure/18.2/6/"
1397 |         },
1398 |         "6": {
1399 |             "id": "2088",
1400 |             "label": "chapter",
1401 |             "name": "Crimes Involving Health and Safety",
1402 |             "identifier": "7",
1403 |             "url": "http://vacode.org/18.2/7/",
1404 |             "api_url": "http://vacode.org/api/structure/18.2/7/"
1405 |         },
1406 |         "7": {
1407 |             "id": "2089",
1408 |             "label": "chapter",
1409 |             "name": "Crimes Involving Morals and Decency",
1410 |             "identifier": "8",
1411 |             "url": "http://vacode.org/18.2/8/",
1412 |             "api_url": "http://vacode.org/api/structure/18.2/8/"
1413 |         },
1414 |         "8": {
1415 |             "id": "2090",
1416 |             "label": "chapter",
1417 |             "name": "Crimes Against Peace and Order",
1418 |             "identifier": "9",
1419 |             "url": "http://vacode.org/18.2/9/",
1420 |             "api_url": "http://vacode.org/api/structure/18.2/9/"
1421 |         },
1422 |         "9": {
1423 |             "id": "2091",
1424 |             "label": "chapter",
1425 |             "name": "Crimes Against the Administration of Justice",
1426 |             "identifier": "10",
1427 |             "url": "http://vacode.org/18.2/10/",
1428 |             "api_url": "http://vacode.org/api/structure/18.2/10/"
1429 |         },
1430 |         "10": {
1431 |             "id": "2092",
1432 |             "label": "chapter",
1433 |             "name": "Offenses Against the Sovereignty of the Commonwealth",
1434 |             "identifier": "11",
1435 |             "url": "http://vacode.org/18.2/11/",
1436 |             "api_url": "http://vacode.org/api/structure/18.2/11/"
1437 |         },
1438 |         "11": {
1439 |             "id": "2093",
1440 |             "label": "chapter",
1441 |             "name": "Miscellaneous",
1442 |             "identifier": "12",
1443 |             "url": "http://vacode.org/18.2/12/",
1444 |             "api_url": "http://vacode.org/api/structure/18.2/12/"
1445 |         },
1446 |         "12": {
1447 |             "id": "2094",
1448 |             "label": "chapter",
1449 |             "name": "Virginia Racketeer Influenced and Corrupt Organization Act",
1450 |             "identifier": "13",
1451 |             "url": "http://vacode.org/18.2/13/",
1452 |             "api_url": "http://vacode.org/api/structure/18.2/13/"
1453 |         }
1454 |     },
1455 |     "laws": false,
1456 |     "api_version": "1.0"
1457 | }
1458 | 
1459 | 1460 |

Search

1461 | 1462 |

When provided with a term, returns all uses of that term within the code, sorted by relevance, limited to the top 100 results.

1463 | 1464 |

Query format

1465 | 1466 |

1467 | http://vacode.org/api/search/[word_or_phrase]?key=[api_key] 1468 |

1469 | 1470 |

Optional parameters

1471 | 1472 |

Detail Level

1473 | 1474 |

Pass the parameter detailed and either true or false to indicate whether you want brief results or detailed results. Detailed results are exactly the same as if you'd used the Law method for each result. The standard fields returned by the Search method are all replaced with the standard fields returned by the Law method, with the exception of the score field, which remains. 1475 | 1476 |

Callback

1477 | 1478 |

Pass the parameter callback and a callback string to have results returned as JSONP.

1479 | 1480 |

1481 | http://vacode.org/api/search/[word_or_phrase]?key=[api_key]&callback=d9f3lIb013 1482 |

1483 | 1484 |

Specified fields

1485 | 1486 |

Pass the parameter fields and a comma-separated list of fields to limit the response to those fields.

1487 | 1488 |

1489 | http://vacode.org/api/search/word_or_phrase]?key=[api_key]&fields=results 1490 |

1491 | 1492 |

Fields

1493 | 1494 | 1495 | 1496 | 1497 | 1498 | 1499 | 1500 | 1501 | 1502 | 1503 | 1504 | 1505 | 1506 | 1507 | 1508 | 1509 | 1510 | 1511 | 1512 | 1513 | 1566 | 1567 | 1568 | 1569 | 1570 | 1571 | 1572 | 1573 | 1574 | 1575 | 1576 | 1577 | 1578 | 1579 | 1580 | 1581 | 1582 |
NameTypeDescriptionNotes
resultsobjectA list of the results of this search.Limited to the first 100 results.
1514 | 1515 | 1516 | 1517 | 1518 | 1519 | 1520 | 1521 | 1522 | 1523 | 1524 | 1525 | 1526 | 1527 | 1528 | 1529 | 1530 | 1531 | 1532 | 1533 | 1534 | 1535 | 1536 | 1537 | 1538 | 1539 | 1540 | 1541 | 1542 | 1543 | 1544 | 1545 | 1546 | 1547 | 1548 | 1549 | 1550 | 1551 | 1552 | 1553 | 1554 | 1555 | 1556 | 1557 | 1558 | 1559 | 1560 | 1561 | 1562 | 1563 | 1564 | 1565 |
section_numberstringThe unique identifier for this section.
catch_linestringThe title of this section.Not all legal codes have catch lines. California's laws, for instance, lack them.
excerptstringAn excerpt of the text of the section.Includes the portions of the text where the search term is used.
textstringThe entire text of the section.
urlstringThe URL of the section in which the definition appears.
scoreintegerThe score measuring the relevance of this document.As provided by Solr (Lucene).
ancestryarrayLists each hierarchically nested structural unit that contains this law.
total_recordsintegerThe number of records that match this search term.This number may exceed the number of records returned, since this method is limited to the top 100 results.
api_versionintegerThe version of the API that is returning this result.
1583 | 1584 |

Sample query and response

1585 | 1586 |

Edited for brevity.

1587 | 1588 |

1589 | http://vacode.org/api/search/person?key=[api_key] 1590 |

1591 | 1592 |

1593 | {
1594 | 	"results": {
1595 | 		"section_number": "1-230",
1596 | 		"catch_line": "Person.",
1597 | 		"excerpt": "“Person” includes any individual, corporation, partnership, association, cooperative, limited liability company.....",
1598 | 		"text": "“Person” includes any individual, corporation, partnership, association, cooperative, limited liability company, trust, joint venture, government, political subdivision, or any other legal or commercial entity and any successor, representative, agent, agency, or instrumentality thereof.",
1599 | 		"url": "http://vacode.org/1-230/",
1600 | 		"score": "5.6"
1601 | 	},
1602 | 	"total_records": "2,263",
1603 |     "api_version": "1.0",
1604 | 	"ancestry": {
1605 | 		"title": "General Provisions",
1606 | 		"chapter": "Common Law and Rules of Construction"
1607 | 	}
1608 | }
1609 | 
1610 | 1611 | 1612 |

Suggest

1613 | 1614 |

When provided with a term, or a portion thereof, returns a list of suggestions for how to complete that term, sorted by likelihood of usefulness, limited to 5 results. Intended to be used internally, within the site, as real-time suggestions while typing in search parameters.

1615 | 1616 |

Query format

1617 | 1618 |

1619 | http://vacode.org/api/suggest/[word_or_phrase]?key=[api_key] 1620 |

1621 | 1622 |

Optional parameters

1623 | 1624 |

Callback

1625 | 1626 |

Pass the parameter callback and a callback string to have results returned as JSONP.

1627 | 1628 |

1629 | http://vacode.org/api/suggest/[word_or_phrase]?key=[api_key]&callback=d9f3lIb013 1630 |

1631 | 1632 |

Fields

1633 | 1634 | 1635 | 1636 | 1637 | 1638 | 1639 | 1640 | 1641 | 1642 | 1643 | 1644 | 1645 | 1646 | 1647 | 1648 | 1649 | 1650 | 1651 | 1652 | 1653 | 1654 | 1655 | 1656 | 1657 | 1658 | 1659 |
NameTypeDescriptionNotes
termsobjectA list of the suggested terms.Limited to the first 4 results.
api_versionintegerThe version of the API that is returning this result.
1660 | 1661 |

Sample query and response

1662 | 1663 |

Edited for brevity.

1664 | 1665 |

1666 | http://vacode.org/api/suggest/lawsu?key=[api_key] 1667 |

1668 | 1669 |

1670 | {
1671 | 	"terms": [
1672 | 		{
1673 | 			id: 0,
1674 | 			term: "laws"
1675 | 		},
1676 | 		{
1677 | 			id: 1,
1678 | 			term: "lawful"
1679 | 		},
1680 | 		{
1681 | 			id: 2,
1682 | 			term: "lapse"
1683 | 		},
1684 | 		{
1685 | 			id: 3,
1686 | 			term: "lawsuit"
1687 | 		},
1688 | 		{
1689 | 			id: 4,
1690 | 			term: "lawns"
1691 | 		}
1692 | 	],
1693 |     "api_version": "1.0",
1694 | }
1695 | 
1696 | 1697 |

Errors

1698 | 1699 |

When a request cannot be completed, the API will return a JSON-formatted error. For example, if an invalid key is provided in a request, the response would be as follows:

1700 | 1701 |

1702 | "error"
1703 | {
1704 |     "message": "An Error Occurred",
1705 |     "details": "Invalid key."
1706 | }
1707 | 
1708 | -------------------------------------------------------------------------------- /cli.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Command Line Tool 3 | layout: default 4 | --- 5 | 6 | 16 | 17 | 39 | 40 |

Overview

41 | 42 |

State Decoded comes with a command line tool, statedecoded. This 43 | tool provides a non-web method to perform common actions, such as importing data 44 | and managing editions.

45 | 46 |

Note: to use this tool, the PHP CLI will need to be 47 | installed. (This is installed by default on most systems that have PHP.) On 48 | linux/unix systems, the tool should be set to be executable to be able to run it 49 | directly, but it may also be run as a normal PHP script (php statedecoded 50 | arguments); the examples below assume it is being run as a 51 | standalone executable. Due to path resolution, you'll probably need to run it 52 | with the path prefix as well – if you're in the root of the statedecoded 53 | directory, it will be ./statedecoded.

54 | 55 |

All commands are run with the statedecoded command. You can run 56 | statedecoded help to see all available commands, and you can use 57 | statedecoded help command to see an explanation of a 58 | specific command along with all available options for it.

59 | 60 |

Many commands use the -v=# option to change the output 61 | verbosity. Messages are weighted by importance, so a verbosity of 1 will show 62 | all message, up to a maximum of 10 for only important messages. Any number above 63 | 10 should silence most, if not all messages.

64 | 65 |

Import

66 | 67 |

Instead of having to use the admin area of The State Decoded to parse data 68 | files to import legal codes, the command line tool can be run. This is helpful 69 | if the data is provided on a regular basis, allowing the script to be run as 70 | part of a cron job, scheduled task, or similar.

71 | 72 |

The default import command (statedecoded import) will import 73 | data from the files in the directory specified in the config file as 74 | IMPORT_DATA_DIR. You may override this to use a different directory 75 | with the -d=directory option.

76 | 77 |

By default, the data is imported into the current edition. You may specify a 78 | different edition to update with the --edition=slug option 79 | by specifying the edition slug. Note that you cannot create a new edition using 80 | the import command, you must use the 81 | Create Edition command first.

82 | 83 |

You may make the selected edition current by using the --current 84 | option.

85 | 86 |

Clear Metadata

87 | 88 |

You may clear the metadata associated with laws via the 89 | statedecoded clear-metadata command. By default this removes all 90 | metadata associated with laws for all editions. You may specify a specific 91 | edition to clear with the --edition=slug option, and/or 92 | a particular field to clear out with the --field=field 93 | option. For instance, to clear out all court decisions (which is a good thing 94 | to do every few months to remove stale data), you may run the command 95 | statedecoded --field=court_decisions

96 | 97 |

Environment Test

98 | 99 |

You can test whether your environment is setup properly to run The State 100 | Decoded by running the statedecoded test-env command. This test 101 | is also run automatically before attempting to import data. If the environment 102 | is not sufficient, errors will be listed, and the command will return with an 103 | error code of 1.

104 | 105 |

Migrations

106 | 107 |

When writing new code for The State Decoded, you may need to modify the 108 | database - to create tables, modify existing ones, or manipulate data. To do 109 | this in a way that is repeatable without modifying our base database 110 | definitions, we use database migrations.

These are scripts that 111 | describe the changes to the database in a way that can easily be reproduced. 112 | 113 |

Migrate the Database

114 | 115 |

To run all migrations that have not been run yet, use the statedecoded 116 | migrate command. To "roll back" (undo) all of the migrations, use the 117 | statedecoded migrate --down option. 118 | 119 |

Writing Migrations

120 | 121 |

To generate a new database migration file, run the statedecoded 122 | generate-migration command. This command will print out the name of the 123 | newly-generated migration file.

124 | 125 |

Inside of this file, you will find a class with two methods: an 126 | up method for making changes to the database, and a 127 | down method for undoing those changes when rolling back. You 128 | should fill out both methods when creating a migration, if all changes are able 129 | to be undone. In general, MySQL will not let you modify a database table such 130 | that data is truncated, such as when chaning the size of a field or index – so 131 | for those operations you should not provide a down 132 | method.

133 | 134 |

Migrations use standard SQL queries, wrapped by our database wrapper into a 135 | single database transaction. The $this->queue() method is used 136 | to queue up queries, and these must be run by the $this->execute() 137 | method. Please have a look at the existing migration files in the 138 | includes/migrations/ directory for examples.

139 | 140 |

Note:Migrations are run in the order of their file names. 141 | These files are timestamped to avoid collisions. Unlike some other migration 142 | tools, we keep track of which migrations have been run and execute all 143 | migrations that have not been run, so you shouldn't need to worry out-of-order 144 | migrations being lost from merging branches.

145 | 146 | 147 |

Editions

148 | 149 |

You can manipulate editions with several builtin commands.

150 | 151 |

Note: As of now, you cannot make an edition 152 | current with these commands, you must do that at the time you are importing 153 | data. This is due to the complex changes to permalinks that must occur when an 154 | edition is made current.

155 | 156 |

List Editions

157 | 158 |

To get the name of the current edition, you can use the statedecoded 159 | edition command. To get a list of all editions, use the 160 | statedecoded edition list command. For both of these commands, you 161 | may add the -v (verbose) flag to receive all of the data about the 162 | editions as a JSON-formatted string.

163 | 164 |

Create Editions

165 | 166 |

To create a new edition, use the statedecoded edition create 167 | --name=name command. You may optionally specify a slug for the 168 | edition with the --slug=slug flag, otherwise the slug will 169 | be generated based on the name provided. Note that if your name has spaces in 170 | it, you must provide the name in quotes, e.g. statedecoded 171 | edition create --name="My New Edition". 172 | 173 |

Delete Editions

174 | 175 |

You may delete an edition by its slug with the statedecoded edition 176 | delete --slug=slug command.

177 | -------------------------------------------------------------------------------- /coding-standards.html: -------------------------------------------------------------------------------- 1 | --- 2 | title: Coding Standards 3 | layout: default 4 | --- 5 | 6 | 46 | -------------------------------------------------------------------------------- /config.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Config file 3 | layout: default 4 | --- 5 | # Configuration Options 6 | 7 | ## SITE_TITLE 8 | What is the title of the website? 9 | 10 | ## PLACE_NAME 11 | What is the name of the place that these laws govern? 12 | 13 | ## LAWS_NAME 14 | What does this place call its laws? e.g., `The Kansas Statutes`, `The Code of Virginia`, etc. 15 | 16 | ## SECTION_SYMBOL 17 | What is the prefix that indicates a section? In many states, this is `§`, but in others it might be `s `. This would be formatted as `§ 1.23-45` or `s. 123`. 18 | 19 | ## WEB_ROOT 20 | The path to the contents of the website, e.g. the location of `index.php`. 21 | 22 | ## IMPORT_DATA_DIR 23 | The directory in which the importer can find the laws to be imported. 24 | 25 | ## CUSTOM_FUNCTIONS 26 | The file in the `/includes/` directory that contains functions custom to this installation. By convention, this is named for the place that these laws govern, e.g. `class.Kansas.inc.php`. 27 | 28 | ## THEMES_DIR 29 | The directory in which themes (site design templates) are found. 30 | 31 | ## THEME_NAME 32 | The name of the theme that's in use. 33 | 34 | ## THEME_DIR 35 | The filesystem path to the directory that contains the theme. This defaults to `TEMPATE_DIR/THEME_NAME` (e.g., `/var/www/example.com/themes/StateDecoded2013/`.) 36 | 37 | ## THEME_WEB_PATH 38 | The public URL of the directory that contains the theme (e.g., `http://example.com/themes/StateDecoded2013/`.) 39 | 40 | ## CURRENT_API_VERSION 41 | Define the default version of the API to send requests to, if a version isn't othewise specified. 42 | 43 | ## EDITION_ID 44 | Establish which version of the code that's in effect sitewide. This is the database ID in the `editions` table. (On a new installation, this will always be `1`.) 45 | 46 | ## EDITION_YEAR 47 | Establish which version of the code that's in effect sitewide. This is the label for the present revision. Although the word "year" appears in the title, if setting up a site for a code that is updated more frequently than annually, another terse label will suffice here (e.g., `2015-02-01` or `2014-Q1`). This label will appear in URLs. 48 | 49 | ## INCLUDES_REPEALED 50 | Does this state's code include laws that have been repealed formally, and that are marked as such? This will suppress their display, so that visits don't have to wade through empty, repealed laws. If your legal code isn't full of vast wastelands of long-abandoned chapters, then you can leave this set to `FALSE`. 51 | 52 | ## LONG_LAW_URLS 53 | Should we use short URLs or long URLs for laws? Short URLs are the default (e.g., `http://example.com/12.3-45:67/`), but if laws have non-unique identifiers, then you'll need to use long URLs (e.g. `http://example.com/56/21/12.3-45:67/`), which are URLs that incorporate the hierarchical structures (e.g., laws, titles, parts, etc.) that contain each law. 54 | 55 | ## PDO_DSN 56 | [PHP Data Object's Data Source Name](http://php.net/manual/en/ref.pdo-mysql.connection.php)—tells PHP how to connect to the MySQL database. (Only MySQL will work.) This looks like this: 57 | 58 | ~~~ 59 | mysql:dbname=statedecoded;host=localhost;charset=utf8 60 | ~~~ 61 | 62 | `dbname` is the name of the database that you created for The State Decoded. `host` is the name of the database server. This will most often be `localhost`—check with your host for details, if that doesn't work. And `charset` must always be `utf8`. 63 | 64 | ## PDO_USERNAME 65 | The database username. 66 | 67 | ## PDO_PASSWORD 68 | The database password. 69 | 70 | ## GLOBAL_DEFINITIONS 71 | Specify the structural identifier ancestry for the unit of the code that contains definitions of terms that are used throughout the code, and thus should have a global scope. Separate each identifier with a comma. If all global definitions are found in Title 15A, Part BD, Chapter 16.2, that would be identified as `15A,BD,16.2`. If all global definitions are found in Article 36, Section 105, that would be identified as `36,105`. This must be the *complete path* to the container for global definitions, and not a standard citation. 72 | 73 | Not all legal codes need this. This only needs to be specified for those legal codes that list globally applicable definitions but that don't specify within the list of definitions that they are globally applicable. For instance, a legal code might set aside a chapter to list all global definitions, and use the first law in the chapter to say "all following laws apply globally," and then have 100 more laws, each containing a single definition. This is a legal code for which this configuration option is necessary. 74 | 75 | ## STRUCTURE 76 | Create a list of the hiearchy of the code, from the top container to the name of an individual law. A legal code's top structural unit might be "titles," and each title might be divided into "chapters," each chapter might be divided into "parts," and each part might be divided into "sections." That would be rendered here as `title,chapter,part,section`. 77 | 78 | ## SECTION_REGEX 79 | Define the regular expression that identifies section references. It is best to do so without using the legal code's symbol (e.g., `§`), since section references are frequently made without its presence. [A growing collection of per-state regular expressions is available](https://github.com/statedecoded/law-identifier)—even if the regular expression that you need isn't found there, you should be able to find something to repurpose. 80 | 81 | ## ERROR_PAGE_DB 82 | The path, relative to the webroot, to an error page to be displayed if the database connection is not available. (Like the fail whale.) Do not begin this path with a slash. If this is undefined, a bare database connection error will be displayed. 83 | 84 | ## EMAIL_ADDRESS 85 | When there is cause for the website to send an e-mail (e.g., API registration), what "From" address should be used? 86 | 87 | ## EMAIL_NAME 88 | When sending e-mail, what name should appear in the "From" field? 89 | 90 | ## RECORD_VIEWS 91 | Record each view of each law in the laws_views table? Doing so provides a corpus of data that can be useful for analysis, data that will be drawn on in future releases of The State Decoded, but that at present is not used for anything. This is done via MySQL's `INSERT DELAYED`, so it will not slow down page rendering time, but it does require a certain amount of system resources and storage. 92 | 93 | ## USE_GENERIC_TERMS 94 | When embedding definitions for legal terms, should the terms in The State Decoded's built-in legal dictionary be included? If this is set to `FALSE`, only the terms defined within this legal code will appear as defined terms. The built-in legal dictionary includes definitions for nearly 500 legal terms that are not generally defined within legal codes. If any of the terms are defined within this legal code, the generic definition will not be displayed, in favor of the legal code’s custom definition. 95 | 96 | ## SEARCH_CONFIG 97 | This indicates whether the data is indexed with Solr or MySQL and, if Solr, specifies how to interact with Solr. Unusually for these configuration options, the value of this is a JSON-encoded array (JSON-encoded because constants cannot contain arrays). Only the `engine` element is necessary if using MySQL, otherwise all additional listed array elements must be completed as specified within the config file. 98 | 99 | ## API_KEY 100 | The site uses its own API extensively, such as to display inline definitions and inline cross-references. That API is stored here, although you don't have to do it—this is populated automatically at the time that the parser is run. 101 | 102 | ## DISQUS_SHORTNAME 103 | If you want to enable [Disqus](http://www.disqus.com/) commenting for every law, register for Disqus, create a new site, and enter the assigned Disqus shortname here. 104 | 105 | ## VARNISH_HOST 106 | If you're running a Varnish server, and you want The State Decoded to automatically purge expired content, provide the URL (including the port number) here. 107 | 108 | ## GOOGLE_ANALYTICS_ID 109 | If you want to track traffic stats with Google Analytics, provide your site's web property ID here. 110 | 111 | ## TYPEKIT_ID 112 | The State Decoded can optionally render the site using several very nice, commercial fonts, calling them from Adobe's [Typekit](https://typekit.com/) service. This requires [paid registration at the "Portfolio" level](https://typekit.com/plans), which costs $4/month. The provided Typekit site ID goes here. See [the "Typekit typefaces" section of the installation guide](http://statedecoded.github.io/documentation/installation.html#typekit-typefaces) for details about where to find that ID. 113 | 114 | ## COURTLISTENER_USERNAME / COURTLISTENER_PASSWORD 115 | * If you want to display court decisions that affect each law using [CourtListener's REST API](https://www.courtlistener.com/api/rest-info/), you must register for an account and enter your username and password here. See the `get_court_decisions()` method in `class.State-sample.inc.php` to actually enable the display of these decisions. 116 | 117 | # Caching 118 | If you are running APC on your web server, note that all of these configuration constants are cached aggressively. You will need to clear APC's cache after making any changes to them, or else those changes will not take effect for hours or days. This can be done in your site’s admin section. (Note that the option is only displayed if you are running APC.) 119 | -------------------------------------------------------------------------------- /images/bg_hr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/statedecoded/documentation/b654b85128f000b9c983843cfb0a9fce1ddfe71b/images/bg_hr.png -------------------------------------------------------------------------------- /images/blacktocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/statedecoded/documentation/b654b85128f000b9c983843cfb0a9fce1ddfe71b/images/blacktocat.png -------------------------------------------------------------------------------- /images/icon_download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/statedecoded/documentation/b654b85128f000b9c983843cfb0a9fce1ddfe71b/images/icon_download.png -------------------------------------------------------------------------------- /images/sprite_download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/statedecoded/documentation/b654b85128f000b9c983843cfb0a9fce1ddfe71b/images/sprite_download.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Documentation by statedecoded 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 |
17 |
18 |

Documentation

19 |

Guides to using The State Decoded, whether deploying a site or using the data from one.

20 | 21 |

View the Project on GitHub statedecoded/documentation

22 | 23 | 24 | 29 |
30 |
31 | 32 |

Introduction

33 |

An introduction to The State Decoded—what it does, why you might want to use it, what you need to get started.

34 | 35 |

Installation

36 |

How to get a State Decoded site up and running.

37 | 38 |

Configuration

39 |

Detailed descriptions of each setting in the configuration file, config.inc.php.

40 | 41 |

XML Format

42 |

Description of the The State Decoded's XML format, which the platform uses as a simple, common format to import legal codes. Also, how to convert other XML formats into The State Decoded's format using provided XSLT.

43 | 44 |

Search Engine

45 |

Instructions about how to configure and tune Solr, the search system that powers aspects of The State Decoded, and suggestions about how to use software other than Solr, such as a hosted search system.

46 | 47 |

How the Parser Works

48 |

A narrative description of how the parser works, for those who want to modify it to import legal information in a format other than The State Decoded's XML format.

49 | 50 |

Customizing The Site

51 |

How to customize the appearance of a State Decoded website.

52 | 53 |

API

54 |

How to interact with the API, including getting a key, a list of methods, information on all fields in responds to each method, and handling errors.

55 | 56 |

Command Line Tool

57 |

How to use The State Decoded command line tool to import data, manipulate the database, and perform other common tasks.

58 | 59 |

Coding Standards

60 |

The basic practices and norms employed with The State Decoded's codebase, for those who want to contribute.

61 | 62 |

Release Process Checklist

63 |

A checklist of steps to be taken before releasing a new version of The State Decoded.

64 | 65 |
66 | 70 |
71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /installation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Installation 3 | layout: default 4 | --- 5 | 6 | # Contents 7 | {:.no_toc} 8 | 9 | * Will be replaced with the ToC, excluding the "Contents" header 10 | {:toc} 11 | 12 | # Requirements 13 | 14 | The following programs and modules are required to run The State Decoded, in addition to a basic LAMP/WAMP stack (MySQL 5+, PHP 5.4+, Apache 2+). *Nearly all of these are almost certainly already installed and configured properly on any standard server.* The exception is on Amazon’s EC2 and other stripped-down cloud servers. The State Decoded’s installer will automatically check to see whether these are installed and running, and alert you to any problems. 15 | 16 | * Make sure that that [`.htaccess` files can use `RewriteRule`](https://help.ubuntu.com/community/EnablingUseOfApacheHtaccessFiles) 17 | * Make sure that [`MultiViews` isn’t enabled](http://httpd.apache.org/docs/2.2/mod/mod_negotiation.html#multiviews) for your site’s virtual host. 18 | * Make sure that [`php.ini` has `allow_url_fopen` enabled](http://www.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen). 19 | * [Make sure that Apache has `mod_rewrite` enabled](http://stackoverflow.com/questions/9021425/how-to-check-if-mod-rewrite-is-enabled-in-php): 20 | * Red Hat/Fedora/CentOS: uncomment [`mod_rewrite.so` from `httpd.conf`](http://www.ewhathow.com/2013/09/how-to-enable-mod_rewrite-on-apache/) 21 | * SuSE: [add `rewrite` to the `APACHE_MODULES` portion of `/etc/sysconfig/apache2`](http://enarion.net/web/htaccess/mod_rewrite-on-suse/) 22 | * Debian/Ubuntu: `sudo a2enmod rewrite` 23 | * Windows: uncomment [`mod_rewrite.so` from `httpd.conf`](http://www.webdevdoor.com/php/mod_rewrite-windows-apache-url-rewriting/) 24 | * Make sure that Apache has `mod_env` enabled: 25 | * Red Hat/Fedora/CentOS/Windows: [instructions](http://serverfault.com/questions/56394/how-do-i-enable-apache-modules-from-the-command-line-in-redhat/56435#56435) 26 | * SuSE: [instructions](http://johannesluderschmidt.de/lang/en-us/django-invalid-command-setenv-in-opensuse/291/) 27 | * Debian/Ubuntu: `sudo a2enmod env` 28 | * Make sure that [PHP's PDO extension](http://php.net/manual/en/book.pdo.php) has MySQL support included, and install `php-curl`, `php-tidy` (or `tidy`), `zip`, and `xmllint`: 29 | * Red Hat/Fedora/CentOS: `sudo yum install php-mysql php-curl php-tidy zip libxml2` 30 | * SuSE: `yast2 --install php5-mysql php5-curl php5-tidy zip libxml2-tools` 31 | * Debian/Ubuntu: `sudo apt-get install php5-mysql php5-curl php5-tidy zip libxml2-utils` 32 | * Windows: `add to php.ini: extension=php_pdo_mysql.dll` 33 | 34 | * (Optional) Solr Search Engine 35 | 36 | Instead of the built-in text search engine, you may use the more advanced Solr search engine. This provides many enhancements over the default engine, but can be difficult to setup and configure. 37 | 38 | * You must use Apache Solr 4.3 or newer. 39 | * In most cases this rules out any system package installations (via `yum`, `yast2`, `apt-get`, etc.), which are all older versions. 40 | * Simply [download Solr](http://lucene.apache.org/solr/downloads.html) to your server, and in the `example/` directory, run `java -jar start.jar -Dsolr.solr.home=/var/www/example.com/solr_home/`, replacing `/var/www/example.com/solr_home/` with the actual path to the `solr_home` directory, which is provided as part of the State Decoded download. 41 | * Note the port number on which Solr is running. This is `8080` by default, but some Linux distributions (e.g., Ubuntu) will set it to `8983` instead. If it isn't `8080`, then you'll need to modify `SOLR_URL` in `config.inc.php` to reflect that different port number. 42 | * When deploying a production site, you'll need to follow [Apache's guide to enabling Solr as a standard system service that will start at boot time](http://wiki.apache.org/solr/SolrJetty#Init_script_to_run_the_Solr_example). 43 | * You'll also need to edit The State Decoded's `config.inc.php` file to use the SolrSearchEngine; an example configuration is provided. 44 | 45 | # Basic configuration 46 | 47 | Here is the process of configuring the beta version of The State Decoded. 48 | 49 | 1. Upload the `htdocs`, `includes`, and `solr_home` directories to your web server (e.g., all within `/var/www/example.com/`), with `htdocs` serving as the web server's document root (e.g. `/var/www/example.com/htdocs/`). 50 | 1. Create a new MySQL database (e.g., `mysqladmin create statedecoded`) and make sure that the web server has access to it. 51 | 1. Rename `config-sample.inc.php` to `config.inc.php` 52 | 1. Rename `class.State-sample.inc.php` to `class.[Placename].inc.php` (e.g., `class.Kansas.inc.php`). 53 | 1. Go through `config.inc.php` and configure each setting. Additional details about each setting can be found within [the configuration file documentation](config.html). 54 | 1. Prepare the parser, selecting from these two methods: 55 | * Straightforward method: With all laws in [the State Decoded XML format](xml-format.html), copy all XML files to `htdocs/admin/import-data/`. 56 | * Custom method: Modify `class.[Statename].inc.php`—specifically `Parser::iterate`, `Parser::parse`, and `Parser::store`—to support the legal code that you will be importing. See “[How the Parser Works](parser.html)” for details. 57 | 1. Load `http://example.com/admin/` in your browser and follow the prompts in the "Import Data" section. Wait while the parser runs, which could require anywhere from 5-60 minutes to run, depending on the power of your server and the length of your legal code. This is iterating through the XML, loading it into the database, and creating the website. When the is parser finished, you have a complete site for your legal code at `http://example.com/`. 58 | 59 | # Advanced configuration 60 | 61 | ## Typekit typefaces 62 | 63 | The State Decoded has been designed to look best with three specific fonts: [FF Meta Serif Web Pro](https://typekit.com/fonts/ff-meta-serif-web-pro), [Adobe Jenson Pro](https://typekit.com/fonts/adobe-jenson-pro), and [Proxima Nova](https://typekit.com/fonts/proxima-nova). In order to use these fonts on the site, it's necessary to [pay for an account on Typekit](https://typekit.com/plans), Adobe's website font service. These three fonts require their "Portfolio" plan, which costs $4/month. 64 | 65 | If you do not sign up for Typekit, the site will work perfectly well. It simply won't look as nice as it otherwise would. 66 | 67 | ## Custom functions 68 | 69 | Within the `State` class, in `class.[Statename].inc.php`, there exist several methods, commented out, that can be written for your specific implementation, to provide additional functionality on your site. To implement these, it is only necessary to write the methods—all of the glue is already in place to include their output within the law object, return the data via the API, and display it on the law pages. 70 | 71 | This class can also be used to house additional functionality not envisioned within The State Decoded. 72 | 73 | ### Official URL 74 | 75 | Method `official_url()`. Turns a law's section number into the URL for the law on its official government website. For example, `10-2.301.4` might become `http://example.gov/laws/10-2.301.4/`. This URL will be provided on the sidebar of every law page and within the API's law method. 76 | 77 | ### Translate history 78 | 79 | Method `translate_history()`. Turns a law's history text into a plain-English version of the same text. For example, `Code 1950, c. 118; 1972, c. 825` might become: 80 | 81 | > This law was first codified in 1950, as recorded in chapter 118 of the Acts of Assembly, and was amended in 1972, by chapter 825. 82 | 83 | The translated history will be displayed after each law on the law page, and will be provided within the API's law method. 84 | 85 | ### Citations 86 | 87 | Method `citations()`. Turns a law's section number and history into one or more citation methods. For example, it might turn a law's section number (10-2.301.4) and the most recent year in which that law was amended (1997) into `Ne. Code § 10-2.301.4 (1997)`. All created citation methods will be displayed in the sidebar of the law page and within the API's law method. 88 | 89 | ## Definition parsing 90 | 91 | Within `class.[Statename].inc.php`, the `extract_definitions()` method does its best to determine the *scope* of definitions. “Scope” is how broadly that a term is to be defined. Some terms are defined only for the purpose of a single law: 92 | 93 | > As used in this section, unless the context requires a different meaning: 94 | > 95 | > “Costs” means the reasonable and customary charges for goods and services incurred or to be incurred in major information technology projects. 96 | 97 | Others might be defined for an entire structural unit—a chapter, title, part, or other named structural unit. And still others might be global, defined for the entire legal code. Every legal code has its own terminology, and many are inconsistent in how a definition's scope is described. "As used in this chapter," "for the purpose of this chapter," and "for purposes of this chapter" are all viable phrases indicating scope. These candidate phrases are stored in the `$scope_indicators` array. The scope of a list of definitions is gathered from the first paragraph in that list. 98 | 99 | Then there are the phrases that indicate an actual definition: 100 | 101 | * "mean" 102 | * "means" 103 | * "shall include" 104 | * "includes" 105 | * "has the same meaning as" 106 | * "shall be construed" 107 | * "shall also be construed to mean" 108 | 109 | These are all terms that can connect a defined term to its definition. These are stored in the `$linking_phrases` array. If your legal code uses different terminology, you need only add its linking phrases to the list. 110 | 111 | Finally, the terms themselves are located based on the presence of quotation marks. (Either straight quotation marks—`U+0022` in Unicode—or angled double quotation marks—`U+201C` and `U+201D` in Unicode.) If the terms within your legal code are not stored within double quotation marks, then `extract_definitions()` will need to be modified to be able to isolate those terms, such as locating them within `` tags. For those rare legal codes that do not offset defined terms in any way (italics, quotation marks, or otherwise; e.g., Nebraska), modifications to the code will be necessary in order to isolate the term being defined. 112 | 113 | The State Decoded does its best to allow for the many terms and phrases employed by different legal codes, but this may need to be tuned to accommodate the legal code that you are parsing. Survey how it indicates the scope of definitions, and how it connects a term to its definition, and modify `extract_definitions()` to suit those circumstances. 114 | 115 | ## Varnish caching 116 | 117 | If you are running a Varnish server, and you want The State Decoded to automatically purge expired content, provide the URL for the Varnish server as the value of `VARNISH_HOST` within `config.inc.php`. Make sure that your [Varnish VCL](https://www.varnish-cache.org/docs/2.1/tutorial/vcl.html) [supports a `BAN`](https://www.varnish-cache.org/docs/3.0/tutorial/purging.html#bans). 118 | 119 | ## Autolinking cross-references 120 | 121 | Many legal codes use coherent, compact, unique citation methods, assigning every law an identifier that is never used elsewhere. With the regular expression in the config file (`SECTION_PCRE`), The State Decoded can identify all cross-references and turn these into links. But for those legal codes that do not use these identifiers, some custom autolinking code will need to be written. 122 | 123 | The first step to doing this is to copy the `replace_sections()` method found within `includes/class.Autolinker.inc.php` and paste it into your `class.[Statename].inc.php` file, within a `State_Autolinker` class, like such: 124 | 125 | ~~~ 126 | class State_Autolinker extends Autolinker 127 | { 128 | function replace_sections() 129 | { 130 | [paste method contents here] 131 | } 132 | } 133 | ~~~ 134 | 135 | The function of the existing `replace_sections()` method is to process a single match from `SECTION_REGEX`. Normally this is as simple as `return ''.$match.'';`, because the section number is the same as the URL slug. But for something like, say, [the Maryland Code's citations](https://github.com/statedecoded/law-identifier/blob/master/Maryland.md), it's necessary to be able to generate a URL for "§ 9-301 of the State Government Article" (say, `sg-9-301`). That might mean maintaining a lookup table within `replace_sections()` to turn every article name ("State government Article") into a URL prefix ("sg-"). Methods will vary between legal codes. 136 | -------------------------------------------------------------------------------- /introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: An Introduction to The State Decoded 3 | layout: default 4 | --- 5 | 6 | # Contents 7 | {:.no_toc} 8 | 9 | * Will be replaced with the ToC, excluding the "Contents" header 10 | {:toc} 11 | 12 | # What It Does 13 | 14 | The State Decoded is a program that takes structured legal data and generates a website, an API, and bulk downloads based on that legal data. It was designed for U.S. state and municipal legal codes, but it works just as nicely for regulations, contracts, even EULAs. It interfaces with court decisions, legislation, and arbitrary types of connected legal data. 15 | 16 | # Who It’s For 17 | 18 | Governments, open-government groups, lone data hackers, law libraries, or anybody else who wants to put legal data online. 19 | 20 | # How It Works 21 | You provide it with bulk legal data in a simple XML format (or any other format that you might like, if you're comfortable writing PHP), with each XML file storing a single law. After some simple site configuration (editing a config file, maybe making a few tweaks to PHP if you want to customize advanced functionality), you run a parser, which chews through those XML files and uses the data in them to populate a MySQL database. For each law, it stores the text of the law and its relationship to other laws—the chapters etc. into which the laws are divided, and also cross-references between the laws. Then it indexes all of the laws for searching, and exports them in a few different formats for people to download. When the parser is finished, you're left with a complete, wholly functional website for that legal code. 22 | 23 | # Understand the Legal Code 24 | 25 | You'll need to have some level of understanding of how your legal code is structured to be able to import that data into The State Decoded. Most legal codes have a similar organizational system - that is, there are `laws` (usually referred to as `sections`) contained within a hierarchy of `structures` with different labels and names. However, from there, every legal code is different. [This blog post](http://krues8dr.com/blog/2016/08/01/what-i-wish-i-had-known-about-decoding-the-law/) summarizes many of the issues that you may discover in your legal code that will complicate your importing process. 26 | 27 | # Getting a Copy of the Legal Code 28 | 29 | Getting the laws or regulations in question can be a non-trivial challenge. It will almost certainly be more work than actually setting up The State Decoded. 30 | 31 | The best-case scenario is that machine-readable, bulk data is available. This might be XML, JSON, or SGML of the legal code, provided directly by the government in question, or by a vendor on their behalf. This is enormously rare. The worst-case scenario is that the code is available only as printed materials, which would need to be scanned in and OCRed every time that the legal code is updated. The reality is that 95% of the time, the data is available as a middle ground, such as in RTF or Word files, or as HTML. 32 | 33 | It’s quite likely that you’re going to be converting unstructured (or poorly structured) data into structured data. Maybe Word files, maybe screen-scraping HTML. In whatever your language of choice is—any programming language can handle it—you’ll be isolating, extracting, and storing some basic information about each law or regulation: its section number, some sort of structural parent number, an optional catch line or title, and the text of the law. ([See the XML format specification](xml-format.html) for detailed information about these fields.) If possible, develop this on a collaborative platform like GitHub and broadcast to others what you’re doing, because that will allow other people to assist you. 34 | 35 | *Before you screen-scrape any HTML, make sure that you read the website’s terms of service!* If you are prohibited from duplicating the contents of that site, then proceed no further without consulting an attorney. 36 | 37 | The best way to start obtaining bulk legal data is almost always to contact the government in question, after identifying which agency or department is the keeper of the code. It is nearly always best to approach with an open mind, planning to build a relationship with the employees at that education, educate them about what you’re doing and why it’s important, and expect to learn a great deal from them about how the legal code works. (If you aren’t an attorney with deep experience with the legal code in question, you almost certainly do not actually understand how it’s structured, how it’s maintained, or its quirks.) *Do not approach them by citing FOIA or otherwise demanding data with an official-sounding request.* This is often perceived as aggressive, and will not earn you any friends in that government. Be friendly! Talk to them about how you can promote their hard work on the code by making it more widely available, and explore how you can make their job easier. For instance, maybe they’ve been wanting an XML version of their legal code, and the parser you’re building for their Word files could be really helpful to them. These folks are underpaid, their work is underfunded, nobody ever tells them “I’m a big fan of your work.” In all likelihood, *you* are a fan of their work. Say so. 38 | 39 | The worst-case scenario is that you’d need to issue a FOIA request to get the data that you need, and re-issue that request to get an updated copy as often as it’s updated. This is a last resort. 40 | 41 | # You Must Provide Updates 42 | 43 | If you are using The State Decoded for a legal code or for regulations, you must have an ongoing source of updates to those laws to keep your website current. This is an essential element without which you would be foolish to proceed. *It’s not enough to get a copy of the legal code once. You must have a method of obtaining regular updates as the code is updated.* This isn't a technical requirement for the software, but it’s a crucial practical prerequisite. 44 | 45 | # A Stern Warning About Data Quality 46 | 47 | By putting a legal code online, you are providing information that, inevitably, people will rely on. You’re implicitly making an agreement to the public that you will present accurate information and keep that information on your site up-to-date. You mustn’t start a site like this on a lark. You’re making an indefinite commitment to the public interest. 48 | -------------------------------------------------------------------------------- /javascripts/main.js: -------------------------------------------------------------------------------- 1 | console.log('This would be the main JS file.'); 2 | -------------------------------------------------------------------------------- /javascripts/scale.fix.js: -------------------------------------------------------------------------------- 1 | var metas = document.getElementsByTagName('meta'); 2 | var i; 3 | if (navigator.userAgent.match(/iPhone/i)) { 4 | for (i=0; iiterate()) 20 | { 21 | $parser->section = $section; 22 | $parser->parse(); 23 | $parser->store(); 24 | } 25 | ~~~ 26 | 27 | `iterate()` retrieves each law, one by one, from the source material, and hands each one of them off to `parse()`. The job of `parse()` is to turn that raw material into a normalized PHP object, which is then passed to `store()`, which puts that data into the database. 28 | 29 | # By Method 30 | 31 | ## iterate() 32 | 33 | The first method to be called, its job is to step through the source of the entirety of the state's laws and extract each law, one at a time. It might be retrieving raw HTML off a web server, stepping through a single XML file on disk, or collecting JSON via an API. Its sole job is to encapsulate the raw material for *just one law* to pass along to `parse()`. This loops over and over again, returning one law with each loop, until finally the entire legal code has been iterated over. 34 | 35 | ## parse() 36 | 37 | The second method to be called, this is where the heavy lifting is done. Its job is to distill each component of a law from the raw material provided by iterate and load it into an object. This might be easy (such as if the data source is well-structured XML or JSON), or might be tricky (such as if the source is HTML or poorly structured XML or JSON). At a minimum this is: 38 | 39 | * name: the "catch line"—the title of the law (e.g. "Proceeds exempt from local taxation") 40 | * text: the complete text of the law 41 | * section_number: the alphanumeric identifier for the law (e.g. "15.2-912.2") 42 | * structure->identifier: the alphanumeric identifier for the law's container—such as chapter or title number (e.g. "16") 43 | * structure->name: the title of the structural container (e.g. "Industrial Development Corporations") 44 | 45 | Optionally, this can be included: 46 | 47 | * history: the legislative history of the law's creation and amendments (e.g. "1995, c. 837, § 18.2-340.32; 1997, cc. 777, 838") 48 | 49 | ## store() 50 | 51 | This method should require minimal customization. The data should have been well massaged within parse(). The one clear exception is the stanza that identifies whether the current law is a list of definitions, generally based on its catch line (e.g., "Definitions," or "Meaning of certain terms"). This list will need to include all catch lines that can indicates that the instant law is a glossary. (See extract_definitions() for more.) 52 | 53 | ## extract_definitions() 54 | 55 | When fed a section that contains a list of definitions, this atomizes them into a list of definitions, and then extracts the term being defined from each definition. Because every state stores these definitions differently (and each state can store them in different ways within the same legal code), this is likely to require some very simple customization. 56 | 57 | The two customizations to be made are to "scope indicators" and to "linking phrases." 58 | 59 | #### Scope indicators 60 | 61 | The first set of phrases to be customized are the scope indicators, stored as `$scope_indicators`. These are the phrases that indicate that a list of definitions is about to follow, and tell the reader what the scope of those definitions is. That is, do these terms apply only within this law? Or they apply to the whole chapter, part, title, article, etc? In context, these phrases might look like this: 62 | 63 | > The following terms are to be defined as such when used in this chapter: 64 | 65 | Or this: 66 | 67 | > In this section, these terms shall be defined as follows: 68 | 69 | “Scope indicators” are the phrases that appear immediately prior to the name of the structural unit (e.g., "title," "chapter," etc.) to which the definitions apply. By default, scope indicators look like this: 70 | 71 | ~~~ 72 | $scope_indicators = array( ' are used in this ', 73 | ' when used in this ', 74 | ' for purposes of this ', 75 | ' for the purpose of this ', 76 | ' in this ', 77 | ); 78 | ~~~ 79 | 80 | Your legal code is unlikely to use this exact set of scope indicators. You'll need to read through a bunch of laws to get a handle on the candidate phrases, and list those here. Again, you must use the phrase that appears *immediately* prior to the name of the structural unit. If this does not fit how your legal code describes scope, then you'll need to make some modifications to `extract_definitions()`. Specifically this bit: 81 | 82 | ~~~ 83 | /* 84 | * Now figure out the specified scope by examining the text that appears 85 | * immediately after the scope indicator. Pull out as many characters as the 86 | * length of the longest structural label. 87 | */ 88 | $phrase = substr( $paragraph, ($pos + strlen($scope_indicator)), $longest_label ); 89 | ~~~ 90 | 91 | You'll just need to grab a different chunk of text surrounding `$scope_indicator`. 92 | 93 | If you get this wrong, it's not disasterous. If you include a scope indicator erroneously, almost certainly the only effect will be that the parser does a bit more work that it has to. If you fail to include a scope indicator, the definitions will still be detected, extracted, and stored, but their scope will be limited to the law in which they appear, as that is the most cautious default. 94 | 95 | 96 | #### Linking phrases 97 | 98 | The second and final set of phrases to be customized are the linking phrases, which is the word, words, or characters that connect a term to its definitions. For example: 99 | 100 | > “Person” shall include individuals, a trust, an estate, a partnership, an association, an order, a corporation, or any other legal or commercial entity. 101 | 102 | Or: 103 | 104 | > “Decree”: Shall be used interchangeably with “judgment,” and shall include orders or awards. 105 | 106 | In the former example, "shall include" is the linking phrase. In the latter, ": " is the linking phrase. (Admittedly, ": " is not a phrase, but it's also not a common construct within legal codes.) 107 | 108 | We use these linking phrases to separate a term from its definition. They're stored in an array, named `$linking_phrases`, which looks like this by default: 109 | 110 | ~~~ 111 | $linking_phrases = array( ' mean ', 112 | ' means ', 113 | ' shall include ', 114 | ' includes ', 115 | ' has the same meaning as ', 116 | ' shall be construed ', 117 | ' shall also be construed to mean ', 118 | ); 119 | ~~~ 120 | 121 | As with scope indicators, it is necessary to survey your legal code, to see how it links terms to their definitions, in order to populate your list. Odds aren't bad that it'll look rather like the default list. 122 | 123 | If your linking phrases list is overly broad, the only effect will be to imperceptably slow down The State Decoded's parser. If it's overly narrow, the effect will be to omit affected terms and definitions from your dictionary—The State Decoded will simply have no idea that it's looking at a definition. 124 | 125 | ### Quotation marks 126 | 127 | There is a third attribute of which to be aware, although it's not a trivial customization like scope indicators and linking phrases. The State Decoded assumes that defined terms are contained within quotes, like this: 128 | 129 | > “Decree”: Shall include orders or awards. 130 | 131 | Those can be straight quotes or angled quotes (aka "smart quotes"), but the terms must be within quotes. We use quotation marks for two reasons. The first is to determine whether to examine a paragraph to see if it contains a definition. No quotes, no definition. The second is to determine which words are the term being defined. 132 | 133 | If your legal code does not insert defined terms within quotes, don't panic. While there is no friendly configuration option to address this, it's not a tough customization. 134 | 135 | The first change you'd need to make is to the conditional that checks whether a quotation mark is present within a paragraph: 136 | 137 | ~~~ 138 | /* 139 | * All defined terms are surrounded by quotation marks, so let's use that as a criteria 140 | * to round down our candidate paragraphs. 141 | */ 142 | if (strpos($paragraph, $quote_sample) !== FALSE) 143 | { 144 | ~~~ 145 | 146 | Best-case, there will be some other wrapper around each definition (e.g., `Decree: Shall include orders or awards.`), in which case you might turn the conditional into this: 147 | 148 | ~~~ 149 | if (strpos($paragraph, '') !== FALSE) 150 | ~~~ 151 | 152 | Worst-case, you'd have this examine every single paragraph (e.g., `if (1 == 1)`, or just remove the `if(…){…}` wrapper entirely.) 153 | 154 | Then, throughout the contents of `if (strpos($paragraph, $quote_sample) !== FALSE) { … }`, you'd need to replace references to quotation marks to the applicable characters, including in the regular expression that extracts the defined term: 155 | 156 | ~~~ 157 | preg_match_all('/("|“)([A-Za-z]{1})([A-Za-z,\'\s-]*)([A-Za-z]{1})("|”)/', $paragraph, $terms); 158 | ~~~ 159 | 160 | Specifically, it's the two instances of `("|”)` that would need to be replaced with the new character or characters used to enclose the defined term. 161 | 162 | If there are no characters used to enclose the defined term, this is still very fixable, although a bit outside of the scope of this guide. 163 | 164 | 165 | ## extract_references() 166 | 167 | This method should not require any customization. Its job is to scan each section for mentions of other sections to create a cross reference list. 168 | 169 | ## extract_history() 170 | 171 | Turns the often-cryptic history sections within nearly every law into standardized data. For instance: 172 | 173 | ~~~ 174 | 1995, c. 837, § 18.2-340.32; 1997, cc. 777, 838 175 | ~~~ 176 | 177 | This tell us that in the 1995 Acts of Assembly, the instant law was modified (or perhaps created), as recorded in chapter 837, and the law was then known as § 18.2-340.32, though it as since been renumbered. And then in the 1997 Acts of Assembly, it was modified twice, in chapters 777 and 838. The job of `extract_history()` is to turn this data into an object, rather than storing it as a single string of text. Inevitably, it will require extensive modification to work with each state's unique method of storing history data, although this is both technically and logistically straightforward. 178 | 179 | ## create_structure 180 | 181 | The only customization that may be helpful here is to populate the `order_by` field in the `structure` table. Many legal codes are ordered in such a way that no standard SQL-based ordering can display them properly (e.g., 4.8, 4.9, 4.10, 4.11, rather than the mathematically proper 4.10, 4.11, 4.8, 4.9, or 4.8, 4.8:A, 4.8:B, 4.8:C). For such codes it may be helpful to populate `order_by` within the SQL query in this method, by whatever ordering mechanisms are available. 182 | 183 | # Working with Metadata 184 | 185 | You may have additional properties, data, and fields in your legal code that The State Decoded does not know about out-of-the-box. To include these, you'll need to store them in the law's `metadata`. For example, for the Virginia code, we include court cases via The Court Listener which reference a given law. 186 | 187 | This data is stored in the `laws_meta` database table. However, instead of directly adding records to this table, you can use an existing instance of the Law class, add your metadata to the object, and call `store_metadata()` to save it. Here's an example, from the `class.State-sample.inc.php` code: 188 | 189 | ``` 190 | // Store these decisions in the metadata table. 191 | $law = new Law(); 192 | $law->section_id = $this->section_id; 193 | 194 | $law->metadata->{0} = new stdClass(); 195 | $law->metadata->{0}->key = 'court_decisions'; 196 | $law->metadata->{0}->value = json_encode($this->decisions); 197 | 198 | $law->store_metadata(); 199 | ``` 200 | 201 | You can create metadata at any point after the law has been created in the parser (the call to the `Parser->store()`), but in most cases you'll want to store it before the laws are exported (`ParserController->export()`), so that the metadata can appear in the exported data files. 202 | 203 | To show this data on a law's page, you'lll need to edit the `htdocs\law.php` file to format the data appropriately. Again, refer to the `court_decisions` example in that file for reference – in most cases, your data will be available on the law as `$law->metadata->your_field`. 204 | 205 | You may also store metadata on a structure, but you will need to manage this manually. The metadata for structures is stored in the `structure.metadata` field as an object that has been run through the `serialize()` function. Be careful to load the structure's previous metadata when adding your new metadata, so as not to overwrite previously-created data. 206 | -------------------------------------------------------------------------------- /release-process.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Release Process 3 | layout: default 4 | --- 5 | 6 | * review all code to make sure no alpha-testing code has slipped in 7 | * run a from-scratch test deployment 8 | * run site with E_NOTICE errors enabled 9 | * validate site template 10 | * validate CSS 11 | * update the docblock at the head of each document 12 | * update CHANGELOG.md based on both the closed issues and the actual changes 13 | * review LICENSE to make sure that any newly incorporated packages are credited 14 | * review README.md 15 | * tag the release on GitHub 16 | * create a new Vagrant image 17 | * upload it and publish the URL 18 | * write a blog entry announcing it 19 | * tweet about it 20 | * inform every known State Decoded user 21 | -------------------------------------------------------------------------------- /search.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Search 3 | layout: default 4 | --- 5 | 6 | *Note: This page is actively under development. At present, it's more of a collection of thoughts than actual documentation.* 7 | 8 | ##solr_home directory 9 | 10 | The `/solr_home/` directory can be kept anywhere. There's no functional need for it to be available within the scope of the website. By default, it lives in parallel to `/htdocs/` and `/includes/`. Its location is only relevant when starting Solr, which is when the path is provided, e.g. `-Dsolr.solr.home=/var/www/example.com/solr_home/`. 11 | 12 | ## Tag weighting 13 | 14 | In `/solr_home/statedecoded/conf/solrconfig.xml`, the request handler for standard searches (``) is configured to give tags the same weight as all other indexed fields. Depending on the source of your tags, you may be well served by adjusting this number. 15 | 16 | For instance, if your tags are well written, accurate, and not over-broad, then you could increase its weight from the (implied) default of 1.0, and take it up to 2.0, 5.0, even 10.0, for Solr to value tags, in determining the relevance of a given law, that multiple of times above all other fields. 17 | 18 | On the other hand, if your tags are good-not-great, then you'd want to decrease the weight of tags, down to .5 or .2 or even .1, to have Solr value other fields beyond tags, but still include tags in its index. 19 | 20 | This is done by appending `^5` (to weight tags at 500% that of other fields) or `^.1` (to weight tags at just 10% of other fields) after `tags` within the `` tag, e.g.: 21 | 22 | ~~~ 23 | 24 | catch_line 25 | tags^5 26 | text 27 | structure 28 | section_ancestor^10 29 | section_descendent^10 30 | refers_to_descendent 31 | refers_to_ancestor 32 | referred_to_by_descendent 33 | referred_to_by_ancestor 34 | term 35 | definition 36 | 37 | ~~~ 38 | 39 | ## Section number tokenizer 40 | Within `/solr_home/statedecoded/conf/schema.xml` there is a tokenizer that indexes cross-references mentions of other laws within a law. The job of this tokenizer is to identify the pattern of a cross-reference, treat it as a single unit of data (instead of inadvertently breaking it up), and index it. 41 | 42 | Here's what the tokenizer looks like: 43 | 44 | 45 | ~~~ 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | ~~~ 62 | 63 | As of this writing, this tokenizer is decoupled from the configuration performed in `/includes/config-sample.inc.php`, which is to say that it may require manual configuration. As provided, it should work for most legal codes. 64 | -------------------------------------------------------------------------------- /stylesheets/pygment_trac.css: -------------------------------------------------------------------------------- 1 | .highlight { background: #ffffff; } 2 | .highlight .c { color: #999988; font-style: italic } /* Comment */ 3 | .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ 4 | .highlight .k { font-weight: bold } /* Keyword */ 5 | .highlight .o { font-weight: bold } /* Operator */ 6 | .highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */ 7 | .highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */ 8 | .highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */ 9 | .highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */ 10 | .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ 11 | .highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */ 12 | .highlight .ge { font-style: italic } /* Generic.Emph */ 13 | .highlight .gr { color: #aa0000 } /* Generic.Error */ 14 | .highlight .gh { color: #999999 } /* Generic.Heading */ 15 | .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ 16 | .highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */ 17 | .highlight .go { color: #888888 } /* Generic.Output */ 18 | .highlight .gp { color: #555555 } /* Generic.Prompt */ 19 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 20 | .highlight .gu { color: #800080; font-weight: bold; } /* Generic.Subheading */ 21 | .highlight .gt { color: #aa0000 } /* Generic.Traceback */ 22 | .highlight .kc { font-weight: bold } /* Keyword.Constant */ 23 | .highlight .kd { font-weight: bold } /* Keyword.Declaration */ 24 | .highlight .kn { font-weight: bold } /* Keyword.Namespace */ 25 | .highlight .kp { font-weight: bold } /* Keyword.Pseudo */ 26 | .highlight .kr { font-weight: bold } /* Keyword.Reserved */ 27 | .highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */ 28 | .highlight .m { color: #009999 } /* Literal.Number */ 29 | .highlight .s { color: #d14 } /* Literal.String */ 30 | .highlight .na { color: #008080 } /* Name.Attribute */ 31 | .highlight .nb { color: #0086B3 } /* Name.Builtin */ 32 | .highlight .nc { color: #445588; font-weight: bold } /* Name.Class */ 33 | .highlight .no { color: #008080 } /* Name.Constant */ 34 | .highlight .ni { color: #800080 } /* Name.Entity */ 35 | .highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */ 36 | .highlight .nf { color: #990000; font-weight: bold } /* Name.Function */ 37 | .highlight .nn { color: #555555 } /* Name.Namespace */ 38 | .highlight .nt { color: #000080 } /* Name.Tag */ 39 | .highlight .nv { color: #008080 } /* Name.Variable */ 40 | .highlight .ow { font-weight: bold } /* Operator.Word */ 41 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 42 | .highlight .mf { color: #009999 } /* Literal.Number.Float */ 43 | .highlight .mh { color: #009999 } /* Literal.Number.Hex */ 44 | .highlight .mi { color: #009999 } /* Literal.Number.Integer */ 45 | .highlight .mo { color: #009999 } /* Literal.Number.Oct */ 46 | .highlight .sb { color: #d14 } /* Literal.String.Backtick */ 47 | .highlight .sc { color: #d14 } /* Literal.String.Char */ 48 | .highlight .sd { color: #d14 } /* Literal.String.Doc */ 49 | .highlight .s2 { color: #d14 } /* Literal.String.Double */ 50 | .highlight .se { color: #d14 } /* Literal.String.Escape */ 51 | .highlight .sh { color: #d14 } /* Literal.String.Heredoc */ 52 | .highlight .si { color: #d14 } /* Literal.String.Interpol */ 53 | .highlight .sx { color: #d14 } /* Literal.String.Other */ 54 | .highlight .sr { color: #009926 } /* Literal.String.Regex */ 55 | .highlight .s1 { color: #d14 } /* Literal.String.Single */ 56 | .highlight .ss { color: #990073 } /* Literal.String.Symbol */ 57 | .highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */ 58 | .highlight .vc { color: #008080 } /* Name.Variable.Class */ 59 | .highlight .vg { color: #008080 } /* Name.Variable.Global */ 60 | .highlight .vi { color: #008080 } /* Name.Variable.Instance */ 61 | .highlight .il { color: #009999 } /* Literal.Number.Integer.Long */ 62 | 63 | .type-csharp .highlight .k { color: #0000FF } 64 | .type-csharp .highlight .kt { color: #0000FF } 65 | .type-csharp .highlight .nf { color: #000000; font-weight: normal } 66 | .type-csharp .highlight .nc { color: #2B91AF } 67 | .type-csharp .highlight .nn { color: #000000 } 68 | .type-csharp .highlight .s { color: #A31515 } 69 | .type-csharp .highlight .sc { color: #A31515 } 70 | -------------------------------------------------------------------------------- /stylesheets/styles.css: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css?family=Lato:300italic,700italic,300,700); 2 | 3 | body { 4 | padding:50px; 5 | font:14px/1.5 Lato, "Helvetica Neue", Helvetica, Arial, sans-serif; 6 | color:#777; 7 | font-weight:300; 8 | } 9 | 10 | h1, h2, h3, h4, h5, h6 { 11 | color:#222; 12 | margin:0 0 20px; 13 | } 14 | 15 | p, ul, ol, table, pre, dl { 16 | margin:0 0 20px; 17 | } 18 | 19 | h1, h2, h3 { 20 | line-height:1.1; 21 | } 22 | 23 | h1 { 24 | font-size:28px; 25 | } 26 | 27 | h2 { 28 | color:#393939; 29 | } 30 | 31 | h3, h4, h5, h6 { 32 | color:#494949; 33 | } 34 | 35 | a { 36 | color:#39c; 37 | font-weight:400; 38 | text-decoration:none; 39 | } 40 | 41 | a small { 42 | font-size:11px; 43 | color:#777; 44 | margin-top:-0.6em; 45 | display:block; 46 | } 47 | 48 | .wrapper { 49 | width:860px; 50 | margin:0 auto; 51 | } 52 | 53 | blockquote { 54 | border-left:1px solid #e5e5e5; 55 | margin:0; 56 | padding:0 0 0 20px; 57 | font-style:italic; 58 | } 59 | 60 | code, pre { 61 | font-family:Monaco, Bitstream Vera Sans Mono, Lucida Console, Terminal; 62 | color:#333; 63 | font-size:12px; 64 | } 65 | 66 | pre { 67 | padding:8px 15px; 68 | background: #f8f8f8; 69 | border-radius:5px; 70 | border:1px solid #e5e5e5; 71 | overflow-x: auto; 72 | } 73 | 74 | table { 75 | width:100%; 76 | border-collapse:collapse; 77 | } 78 | 79 | th, td { 80 | text-align:left; 81 | padding:5px 10px; 82 | border-bottom:1px solid #e5e5e5; 83 | } 84 | 85 | dt { 86 | color:#444; 87 | font-weight:700; 88 | } 89 | 90 | th { 91 | color:#444; 92 | } 93 | 94 | img { 95 | max-width:100%; 96 | } 97 | 98 | header { 99 | width:270px; 100 | float:left; 101 | position:fixed; 102 | } 103 | 104 | header ul { 105 | list-style:none; 106 | height:40px; 107 | 108 | padding:0; 109 | 110 | background: #eee; 111 | background: -moz-linear-gradient(top, #f8f8f8 0%, #dddddd 100%); 112 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f8f8f8), color-stop(100%,#dddddd)); 113 | background: -webkit-linear-gradient(top, #f8f8f8 0%,#dddddd 100%); 114 | background: -o-linear-gradient(top, #f8f8f8 0%,#dddddd 100%); 115 | background: -ms-linear-gradient(top, #f8f8f8 0%,#dddddd 100%); 116 | background: linear-gradient(top, #f8f8f8 0%,#dddddd 100%); 117 | 118 | border-radius:5px; 119 | border:1px solid #d2d2d2; 120 | box-shadow:inset #fff 0 1px 0, inset rgba(0,0,0,0.03) 0 -1px 0; 121 | width:270px; 122 | } 123 | 124 | header li { 125 | width:89px; 126 | float:left; 127 | border-right:1px solid #d2d2d2; 128 | height:40px; 129 | } 130 | 131 | header ul a { 132 | line-height:1; 133 | font-size:11px; 134 | color:#999; 135 | display:block; 136 | text-align:center; 137 | padding-top:6px; 138 | height:40px; 139 | } 140 | 141 | strong { 142 | color:#222; 143 | font-weight:700; 144 | } 145 | 146 | header ul li + li { 147 | width:88px; 148 | border-left:1px solid #fff; 149 | } 150 | 151 | header ul li + li + li { 152 | border-right:none; 153 | width:89px; 154 | } 155 | 156 | header ul a strong { 157 | font-size:14px; 158 | display:block; 159 | color:#222; 160 | } 161 | 162 | section { 163 | width:500px; 164 | float:right; 165 | padding-bottom:50px; 166 | } 167 | 168 | small { 169 | font-size:11px; 170 | } 171 | 172 | hr { 173 | border:0; 174 | background:#e5e5e5; 175 | height:1px; 176 | margin:0 0 20px; 177 | } 178 | 179 | footer { 180 | width:270px; 181 | float:left; 182 | position:fixed; 183 | bottom:50px; 184 | } 185 | 186 | @media print, screen and (max-width: 960px) { 187 | 188 | div.wrapper { 189 | width:auto; 190 | margin:0; 191 | } 192 | 193 | header, section, footer { 194 | float:none; 195 | position:static; 196 | width:auto; 197 | } 198 | 199 | header { 200 | padding-right:320px; 201 | } 202 | 203 | section { 204 | border:1px solid #e5e5e5; 205 | border-width:1px 0; 206 | padding:20px 0; 207 | margin:0 0 20px; 208 | } 209 | 210 | header a small { 211 | display:inline; 212 | } 213 | 214 | header ul { 215 | position:absolute; 216 | right:50px; 217 | top:52px; 218 | } 219 | } 220 | 221 | @media print, screen and (max-width: 720px) { 222 | body { 223 | word-wrap:break-word; 224 | } 225 | 226 | header { 227 | padding:0; 228 | } 229 | 230 | header ul, header p.view { 231 | position:static; 232 | } 233 | 234 | pre, code { 235 | word-wrap:normal; 236 | } 237 | } 238 | 239 | @media print, screen and (max-width: 480px) { 240 | body { 241 | padding:15px; 242 | } 243 | 244 | header ul { 245 | display:none; 246 | } 247 | } 248 | 249 | @media print { 250 | body { 251 | padding:0.4in; 252 | font-size:12pt; 253 | color:#444; 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /stylesheets/stylesheet.css: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Slate Theme for GitHub Pages 3 | by Jason Costello, @jsncostello 4 | *******************************************************************************/ 5 | 6 | @import url(pygment_trac.css); 7 | 8 | /******************************************************************************* 9 | MeyerWeb Reset 10 | *******************************************************************************/ 11 | 12 | html, body, div, span, applet, object, iframe, 13 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 14 | a, abbr, acronym, address, big, cite, code, 15 | del, dfn, em, img, ins, kbd, q, s, samp, 16 | small, strike, strong, sub, sup, tt, var, 17 | b, u, i, center, 18 | dl, dt, dd, ol, ul, li, 19 | fieldset, form, label, legend, 20 | table, caption, tbody, tfoot, thead, tr, th, td, 21 | article, aside, canvas, details, embed, 22 | figure, figcaption, footer, header, hgroup, 23 | menu, nav, output, ruby, section, summary, 24 | time, mark, audio, video { 25 | margin: 0; 26 | padding: 0; 27 | border: 0; 28 | font: inherit; 29 | vertical-align: baseline; 30 | } 31 | 32 | /* HTML5 display-role reset for older browsers */ 33 | article, aside, details, figcaption, figure, 34 | footer, header, hgroup, menu, nav, section { 35 | display: block; 36 | } 37 | 38 | ol, ul { 39 | list-style: none; 40 | } 41 | 42 | blockquote, q { 43 | } 44 | 45 | table { 46 | border-collapse: collapse; 47 | border-spacing: 0; 48 | } 49 | 50 | /******************************************************************************* 51 | Theme Styles 52 | *******************************************************************************/ 53 | 54 | body { 55 | box-sizing: border-box; 56 | color:#373737; 57 | background: #212121; 58 | font-size: 16px; 59 | font-family: 'Myriad Pro', Calibri, Helvetica, Arial, sans-serif; 60 | line-height: 1.5; 61 | -webkit-font-smoothing: antialiased; 62 | } 63 | 64 | h1, h2, h3, h4, h5, h6 { 65 | margin: 10px 0; 66 | font-weight: 700; 67 | color:#222222; 68 | font-family: 'Lucida Grande', 'Calibri', Helvetica, Arial, sans-serif; 69 | letter-spacing: -1px; 70 | } 71 | 72 | h1 { 73 | font-size: 36px; 74 | font-weight: 700; 75 | } 76 | 77 | h2 { 78 | padding-bottom: 10px; 79 | font-size: 32px; 80 | background: url('../images/bg_hr.png') repeat-x bottom; 81 | } 82 | 83 | h3 { 84 | font-size: 24px; 85 | } 86 | 87 | h4 { 88 | font-size: 21px; 89 | } 90 | 91 | h5 { 92 | font-size: 18px; 93 | } 94 | 95 | h6 { 96 | font-size: 16px; 97 | } 98 | 99 | p { 100 | margin: 10px 0 15px 0; 101 | } 102 | 103 | footer p { 104 | color: #f2f2f2; 105 | } 106 | 107 | a { 108 | text-decoration: none; 109 | color: #007edf; 110 | text-shadow: none; 111 | 112 | transition: color 0.5s ease; 113 | transition: text-shadow 0.5s ease; 114 | -webkit-transition: color 0.5s ease; 115 | -webkit-transition: text-shadow 0.5s ease; 116 | -moz-transition: color 0.5s ease; 117 | -moz-transition: text-shadow 0.5s ease; 118 | -o-transition: color 0.5s ease; 119 | -o-transition: text-shadow 0.5s ease; 120 | -ms-transition: color 0.5s ease; 121 | -ms-transition: text-shadow 0.5s ease; 122 | } 123 | 124 | #main_content a:hover { 125 | color: #0069ba; 126 | text-shadow: #0090ff 0px 0px 2px; 127 | } 128 | 129 | footer a:hover { 130 | color: #43adff; 131 | text-shadow: #0090ff 0px 0px 2px; 132 | } 133 | 134 | em { 135 | font-style: italic; 136 | } 137 | 138 | strong { 139 | font-weight: bold; 140 | } 141 | 142 | img { 143 | position: relative; 144 | margin: 0 auto; 145 | max-width: 739px; 146 | padding: 5px; 147 | margin: 10px 0 10px 0; 148 | border: 1px solid #ebebeb; 149 | 150 | box-shadow: 0 0 5px #ebebeb; 151 | -webkit-box-shadow: 0 0 5px #ebebeb; 152 | -moz-box-shadow: 0 0 5px #ebebeb; 153 | -o-box-shadow: 0 0 5px #ebebeb; 154 | -ms-box-shadow: 0 0 5px #ebebeb; 155 | } 156 | 157 | pre, code { 158 | width: 100%; 159 | color: #222; 160 | background-color: #fff; 161 | 162 | font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace; 163 | font-size: 14px; 164 | 165 | border-radius: 2px; 166 | -moz-border-radius: 2px; 167 | -webkit-border-radius: 2px; 168 | 169 | 170 | 171 | } 172 | 173 | pre { 174 | width: 100%; 175 | padding: 10px; 176 | box-shadow: 0 0 10px rgba(0,0,0,.1); 177 | overflow: auto; 178 | } 179 | 180 | code { 181 | padding: 3px; 182 | margin: 0 3px; 183 | box-shadow: 0 0 10px rgba(0,0,0,.1); 184 | } 185 | 186 | pre code { 187 | display: block; 188 | box-shadow: none; 189 | } 190 | 191 | blockquote { 192 | color: #666; 193 | margin-bottom: 20px; 194 | padding: 0 0 0 20px; 195 | border-left: 3px solid #bbb; 196 | } 197 | 198 | ul, ol, dl { 199 | margin-bottom: 15px 200 | } 201 | 202 | ul li { 203 | list-style: inside; 204 | padding-left: 20px; 205 | } 206 | 207 | ol li { 208 | list-style: decimal inside; 209 | padding-left: 20px; 210 | } 211 | 212 | dl dt { 213 | font-weight: bold; 214 | } 215 | 216 | dl dd { 217 | padding-left: 20px; 218 | font-style: italic; 219 | } 220 | 221 | dl p { 222 | padding-left: 20px; 223 | font-style: italic; 224 | } 225 | 226 | hr { 227 | height: 1px; 228 | margin-bottom: 5px; 229 | border: none; 230 | background: url('../images/bg_hr.png') repeat-x center; 231 | } 232 | 233 | table { 234 | border: 1px solid #373737; 235 | margin-bottom: 20px; 236 | text-align: left; 237 | } 238 | 239 | th { 240 | font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif; 241 | padding: 10px; 242 | background: #373737; 243 | color: #fff; 244 | } 245 | 246 | td { 247 | padding: 10px; 248 | border: 1px solid #373737; 249 | } 250 | 251 | form { 252 | background: #f2f2f2; 253 | padding: 20px; 254 | } 255 | 256 | img { 257 | width: 100%; 258 | max-width: 100%; 259 | } 260 | 261 | /******************************************************************************* 262 | Full-Width Styles 263 | *******************************************************************************/ 264 | 265 | .outer { 266 | width: 100%; 267 | } 268 | 269 | .inner { 270 | position: relative; 271 | max-width: 640px; 272 | padding: 20px 10px; 273 | margin: 0 auto; 274 | } 275 | 276 | #forkme_banner { 277 | display: block; 278 | position: absolute; 279 | top:0; 280 | right: 10px; 281 | z-index: 10; 282 | padding: 10px 50px 10px 10px; 283 | color: #fff; 284 | background: url('../images/blacktocat.png') #0090ff no-repeat 95% 50%; 285 | font-weight: 700; 286 | box-shadow: 0 0 10px rgba(0,0,0,.5); 287 | border-bottom-left-radius: 2px; 288 | border-bottom-right-radius: 2px; 289 | } 290 | 291 | #header_wrap { 292 | background: #212121; 293 | background: -moz-linear-gradient(top, #373737, #212121); 294 | background: -webkit-linear-gradient(top, #373737, #212121); 295 | background: -ms-linear-gradient(top, #373737, #212121); 296 | background: -o-linear-gradient(top, #373737, #212121); 297 | background: linear-gradient(top, #373737, #212121); 298 | } 299 | 300 | #header_wrap .inner { 301 | padding: 50px 10px 30px 10px; 302 | } 303 | 304 | #project_title { 305 | margin: 0; 306 | color: #fff; 307 | font-size: 42px; 308 | font-weight: 700; 309 | text-shadow: #111 0px 0px 10px; 310 | } 311 | 312 | #project_tagline { 313 | color: #fff; 314 | font-size: 24px; 315 | font-weight: 300; 316 | background: none; 317 | text-shadow: #111 0px 0px 10px; 318 | } 319 | 320 | #downloads { 321 | position: absolute; 322 | width: 210px; 323 | z-index: 10; 324 | bottom: -40px; 325 | right: 0; 326 | height: 70px; 327 | background: url('../images/icon_download.png') no-repeat 0% 90%; 328 | } 329 | 330 | .zip_download_link { 331 | display: block; 332 | float: right; 333 | width: 90px; 334 | height:70px; 335 | text-indent: -5000px; 336 | overflow: hidden; 337 | background: url(../images/sprite_download.png) no-repeat bottom left; 338 | } 339 | 340 | .tar_download_link { 341 | display: block; 342 | float: right; 343 | width: 90px; 344 | height:70px; 345 | text-indent: -5000px; 346 | overflow: hidden; 347 | background: url(../images/sprite_download.png) no-repeat bottom right; 348 | margin-left: 10px; 349 | } 350 | 351 | .zip_download_link:hover { 352 | background: url(../images/sprite_download.png) no-repeat top left; 353 | } 354 | 355 | .tar_download_link:hover { 356 | background: url(../images/sprite_download.png) no-repeat top right; 357 | } 358 | 359 | #main_content_wrap { 360 | background: #f2f2f2; 361 | border-top: 1px solid #111; 362 | border-bottom: 1px solid #111; 363 | } 364 | 365 | #main_content { 366 | padding-top: 40px; 367 | } 368 | 369 | #footer_wrap { 370 | background: #212121; 371 | } 372 | 373 | 374 | 375 | /******************************************************************************* 376 | Small Device Styles 377 | *******************************************************************************/ 378 | 379 | @media screen and (max-width: 480px) { 380 | body { 381 | font-size:14px; 382 | } 383 | 384 | #downloads { 385 | display: none; 386 | } 387 | 388 | .inner { 389 | min-width: 320px; 390 | max-width: 480px; 391 | } 392 | 393 | #project_title { 394 | font-size: 32px; 395 | } 396 | 397 | h1 { 398 | font-size: 28px; 399 | } 400 | 401 | h2 { 402 | font-size: 24px; 403 | } 404 | 405 | h3 { 406 | font-size: 21px; 407 | } 408 | 409 | h4 { 410 | font-size: 18px; 411 | } 412 | 413 | h5 { 414 | font-size: 14px; 415 | } 416 | 417 | h6 { 418 | font-size: 12px; 419 | } 420 | 421 | code, pre { 422 | min-width: 320px; 423 | max-width: 480px; 424 | font-size: 11px; 425 | } 426 | 427 | } 428 | -------------------------------------------------------------------------------- /templates.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Templates 3 | layout: default 4 | --- 5 | 6 | # Contents 7 | {:.no_toc} 8 | 9 | * Will be replaced with the ToC, excluding the "Contents" header 10 | {:toc} 11 | 12 | # Master template file 13 | Duplicate `htdocs/themes/StateDecoded2013/` (to, say, `htdocs/themes/Kansas/`), then edit `THEME_NAME` in `includes/config.inc.php` to read `Kansas` instead of `StateDecoded2013`. The contents of the new `Kansas` directory are now your site template. 14 | 15 | # Images 16 | There is a [State Decoded Assets repository](https://github.com/statedecoded/statedecoded-assets/) that contains PSD files of page mockups and a favicon. These may be modified to customize the site's images as you see fit. 17 | 18 | # CSS 19 | If you choose to duplicate the default “State Decoded 2013“ theme, then you will be happiest if you do not edit the existing CSS files directly. Instead, create a new CSS file (e.g., `htdocs/themes/Kansas/static/css/kansas.css`) and start it with the following line: 20 | 21 | ~~~ 22 | @import url("application.css"); 23 | ~~~ 24 | 25 | Then add your CSS declarations on top of that. This way, as subsequent releases of The State Decoded add modify the bundled CSS to add new functionality, you will gain that functionality in your own design by simply copying over the new `application.css`. Then, in your template (e.g., `htdocs/themes/Kansas/default.inc.php`), have it load `kansas.css` instead of `application.css`. 26 | 27 | Better still, if you're comfortable with SCSS, do the same, but by creating a new SCSS file (e.g., `htdocs/themes/Kansas/static/scss/kansas.scss`) that leads off by importing `application.scss`, and then use that to generate `htdocs/themes/Kansas/static/css/application.css`. 28 | 29 | # Caching 30 | If you're running Varnish or mod_pagespeed on your server, you'll need to clear out your cache after making design changes. That's important for Varnish, which caches whole pages. mod_pagespeed should automatically expire its cached assets (Javascript, CSS, and images) when you change them, but if it doesn't, you'll need [flush its cache manually](https://developers.google.com/speed/pagespeed/module/system#flush_cache). 31 | 32 | # Home Page Layout 33 | The home page is found at `home.php`, not `index.php`. (`index.php` is the file through which all page requests on the site are piped.) 34 | 35 | If you have an introductory video that you want to display on the home page, uncomment the `
[…]
` stanza from `htdocs/home.php` and modify appropriately to link to your video. 36 | 37 | # Favicons, Apple Touch Icons 38 | 39 | Each of these icons should somehow correlate to the political entity's legal code. With Virginia, we used the seal icon that was created for the site. The larger touch icons have bitmapped 0 and 1s fading across, representing digital bits being "decoded" as it were. Feel free to edit the master images in [the State Decoded Assets repository](https://github.com/statedecoded/statedecoded-assets) to suit your needs. We recommend running any images through [ImageOptim](http://imageoptim.com) to squeeze out excess file size. 40 | 41 | # Sass, Compass, etc. 42 | 43 | This site was built with future flexibility and reuse in mind. To that end, the site basically is a style guide as well as a design. We use Sass/SCSS to allow the power of variables in CSS. This makes it easy to rapidly change colors and fonts without having to do massive find-and-replace or worry about color math variations in Photoshop. 44 | 45 | This does create a layer of complexity, but a worthwhile one. You, as an end user, can write regular CSS in an SCSS file and it will compile normally. 46 | 47 | To compile the SCSS into CSS, you need to run CodeKit, Scout, CompassApp, or do a manual setup with Ruby on your system. This is documented on [the Compass site](http://compass-style.org/install/). 48 | 49 | # Media Queries 50 | 51 | The site is defined with three breakpoints: 52 | 53 | * Handheld/iPhone 54 | * Tablet/iPad (Portrait) 55 | * Everything else 56 | 57 | # Creating New Pages 58 | 59 | You may add new pages to the site by simply including `HTML` or `PHP` files inside of the `htdocs` directory of the site. You can then reference those files by name. Similarly, any images or other assets in that directory can be used on the site. 60 | 61 | If you would like to use the template engine of The State Decoded instead of having to include an entire page, simply create a new PHP file with at least the following contents, replacing `$body` with your content. 62 | 63 | ``` 64 | /* 65 | * Create a container for our content. 66 | */ 67 | $content = new Content(); 68 | 69 | $body = 'Hello World'; 70 | 71 | /* 72 | * Put the shorthand $body variable into its proper place. 73 | */ 74 | $content->set('body', $body); 75 | 76 | /* 77 | * Parse the template, which is a shortcut for a few steps that culminate in sending the content 78 | * to the browser. 79 | */ 80 | $template = Template::create(); 81 | $template->parse($content); 82 | ``` 83 | 84 | There are other fields available on a page, including the page title and heading. Please have a look at the other pages on the site and the theme's `default.inc.php` template file for specific fields that are available to change via the `$content->set` method. 85 | 86 | To have the page appear without the file extension, as the About page and others do, you'll need to add it to the routing system. The routing system uses simple [regular expressions](http://www.regular-expressions.info/) to match routes. Simply add a line to the `Specific Routes` section of the `includes/routes.inc.php` file with your page's name, route structure, and filename like this: 87 | 88 | ``` 89 | $router->addRoute('contact', '^/contact/$', 'contact.php'); 90 | ``` 91 | 92 | 93 | # Editing Help Content 94 | 95 | To customize the help content of any section, you'll need to edit the `htdocs/content/help.json` file. There, you'll need to give the help content a title, a brief description, and the full content that should appear in the modal popup. 96 | -------------------------------------------------------------------------------- /xml-format.html: -------------------------------------------------------------------------------- 1 | --- 2 | title: XML Format 3 | layout: default 4 | --- 5 | 6 |

The State Decoded parser can either be modified to use bespoke PHP to parse a legal code in its native format, or it can parse a prescribed XML format. This is a totally invented XML format. There is no legal code that is provided in this format. It is provided as an option because, via XSLT, it can be substantially easier to convert an existing XML to this format than to write a parser for it in PHP.

7 | 8 |

The State Decoded includes a sample XSLT file on which you can base your own XSLT. It is well commented and verbose, so even if you’re not familiar with XSLT, you’ve got a fighting chance of transforming your XML to The State Decoded’s format. If the legal code that you are ingesting is in Lexis-Nexis' XML format (which sometimes travels under the name of “legislativedoc v1”), then use lexis-nexis.xsl, which is included with The State Decoded.

9 | 10 |

Note that this is not an effort to create a standard interchange or storage format for legal codes. This exists solely as a convenience for importing data into The State Decoded.

11 | 12 |

Terminology

13 | 14 | Legal codes throughout the U.S. all use different terminology (e.g., "statutes" vs "code" vs "laws"). We need to adopt some terminology here, and while it can't be the right terminology everywhere, we hope to avoid any disputes about what exactly is the right terminology. The terminology we've adopted was the simplest that also reflected the reality of the data. A lot of people implementing The State Decoded are programmers, not attorneys, and the terminology that the project uses needs to reflect the reality of that user base. 15 | 16 | Below, the word "law" refers to what some jurisdictions would call a section, and it's usually prefixed with the § symbol. It corresponds to a single page on a State Decoded website. 17 | 18 | Within a "law", we use "section" elements to represent the hierarchical structure of the paragraphs within it. In some jurisdictions this would be called a subsection. A "section" corresponds to a paragraph plus any logically nested (typically indented) content within it. 19 | 20 |

Descriptive Specifications

21 | 22 |
    23 |
  • There must be one file per law.
  • 24 |
  • All files must be in the same directory.
  • 25 |
  • The names of the files are irrelevant.
  • 26 |
  • Every file contains both structural data about its container—which chapter/title/part/article/etc. that it's within—and data about the law itself.
  • 27 |
  • Text must be broken up by subsection, rather than provided as a single block of text, unless the text of the law does not have subsections.
  • 28 |
  • Subsections may be nested.
  • 29 |
30 | 31 |

This being open source software, some relatively simple tweaks to Parser::iterate and Parser::parse make all of these specifications malleable.

32 | 33 |

Fields

34 | 35 |
    36 |
  • law: the container for all other fields—required 37 |
    • structure: the container for structural units (chapters, titles, articles, parts, etc.)—required
    • 38 |
    • unit: a single structural unit that contains this law—required 39 |
      • label: the type of structural unit that this is (chapter, title, article, part, etc.)—required
      • 40 |
      • identifier: the unique identifier for this structural unit (but not necessarily globally unique!), almost always a number (e.g., 18.2, 6)—required
      • 41 |
      • orderby: when listing all structural units of this label, in what ordinal position this structural unit should appear—optional
      • 42 |
      • level: a whole number, starting at one, indicating the depth of this structural unit—required
    • 43 |
    • sectionnumber: the unique identifier for this law—required
    • 44 |
    • catchline: the title of this law—required
    • 45 |
    • orderby: when listing all laws within this structural unit, in what ordinal position this law should appear—optional
    • 46 |
    • text: the container for the text of the law itself—required
    • 47 |
    • section: a single labelled section of a law—optional 48 |
      • prefix: the identifying label for this section (e.g., A, 6, vi)—required
      • 49 |
      • type: the type of material within this section; default is text, other options are "table" and "image"—optional
    • 50 |
    • history: the textual description of the history of amendments to this law—optional
    • 51 |
    • metadata: a container for any additional fields, which will be stored as key:value in the laws_meta table—optional; values of true and false will be stored in the database as y and n, respectively, but converted back to true and false within the internal and external APIs
  • 52 |
53 | 54 |

Sample XML

55 | 56 |

Structure

57 | 58 |

With All Fields

59 | 60 |
 61 | <?xml version="1.0" encoding="utf-8"?>
 62 | <law>
 63 |     <structure>
 64 |         <unit label="" identifier="" order_by="" level=""></unit>
 65 |     </structure>
 66 |     <section_number></section_number>
 67 |     <catch_line></catch_line>
 68 |     <order_by></order_by>
 69 |     <text>
 70 |         <section prefix=""></section>
 71 |     </text>
 72 |     <history></history>
 73 |     <metadata></metadata>
 74 |     <tags>
 75 |         <tag></tag>
 76 |     </tags>
 77 | </law>
 78 | 
79 | 80 |

Bare Minimum

81 | 82 |
 83 | <?xml version="1.0" encoding="utf-8"?>
 84 | <law>
 85 |     <structure>
 86 |         <unit label="" identifier="" level=""></unit>
 87 |     </structure>
 88 |     <section_number></section_number>
 89 |     <catch_line></catch_line>
 90 |     <text></text>
 91 | </law>
 92 | 
93 | 94 |

Populated

95 | 96 |

Here is a complete, populated sample XML file that includes every available parameter.

97 | 98 |
 99 | <?xml version="1.0" encoding="utf-8"?>
100 | <law>
101 |     <structure>
102 |         <unit label="title" identifier="18.2" order_by="18.2" level="1">Crimes and Offenses Generally</unit>
103 |         <unit label="chapter" identifier="6" order_by="6" level="2">Crimes Involving Fraud</unit>
104 |     </structure>
105 |     <section_number>18.2-186</section_number>
106 |     <catch_line>False statements to obtain property or credit.</catch_line>
107 |     <order_by>00000000009104318.2</order_by>
108 |     <text>
109 |         <section prefix="1">
110 |             Notwithstanding § 18.2-186:
111 | 
112 | 			<section prefix="A">A person shall be guilty of a Class 1 misdemeanor if he makes,
113 | 			causes to be made or conspires to make directly, indirectly or through an agency, any
114 | 			materially false statement in writing, knowing it to be false and intending that it be
115 | 			relied upon, concerning the financial condition or means or ability to pay of himself,
116 | 			or of any other person for whom he is acting, or any firm or corporation in which he is
117 | 			interested or for which he is acting, for the purpose of procuring, for his own benefit
118 | 			or for the benefit of such person, firm or corporation, the delivery of personal
119 | 			property, the payment of cash, the making of a loan or credit, the extension of a
120 | 			credit, the discount of an account receivable, or the making, acceptance, discount, sale
121 | 			or endorsement of a bill of exchange or promissory note.</section>
122 | 
123 | 			<section prefix="B">Any person who knows that a false statement has been made in writing
124 | 			concerning the financial condition or ability to pay of himself or of any person for
125 | 			whom he is acting, or any firm or corporation in which he is interested or for which he
126 | 			is acting and who, with intent to defraud, procures, upon the faith thereof.
127 | 	
128 | 				<section prefix="i" type="table">
129 | 				+------------------+--------------------+
130 | 				| PERSON           | STATEMENT          |
131 | 				+------------------+--------------------+
132 | 				| any              | false              |
133 | 				| no               | true               |
134 | 				+------------------+--------------------+
135 | 				</section>
136 | 	
137 | 			For his own benefit, or for the benefit of the person, firm or corporation in which he
138 | 			is interested or for which he is acting, any such delivery, payment, loan, credit,
139 | 			extension, discount making, acceptance, sale or endorsement, shall, if the value of the
140 | 			thing or the amount of the loan, credit or benefit obtained is $200 or more, be guilty
141 | 			of grand larceny or, if the value is less than $200, be guilty of petit
142 | 			larceny.</section>
143 | 	
144 | 			<section prefix="C">Venue for the trial of any person charged with an offense under this
145 | 			section may be in the county or city in which (i) any act was performed in furtherance
146 | 			of the offense, or (ii) the person charged with the offense resided at the time of the
147 | 			offense.</section>
148 | 	
149 | 			<section prefix="D">As used in this section, "in writing" shall include information
150 | 			transmitted by computer, facsimile, e-mail, Internet, or any other electronic medium,
151 | 			and shall not include information transmitted by any such medium by voice
152 | 			transmission.</section>
153 | 		</section>
154 | 		<section prefix="2">
155 | 			This law shall expire on July 1, 2014.
156 | 		</section>
157 | 	</text>
158 | 	<history>Code 1950, § 18.1-125; 1960, c. 358; 1975, cc. 14, 15.</history>
159 | 	<metadata>
160 | 		<repealed>y</repealed>
161 | 		<expiration>2014-07-01</expiration>
162 | 	</metadata>
163 | 	<tags>
164 | 		<tag>lying</tag>
165 | 		<tag>fraud</tag>
166 | 		<tag>theft</tag>
167 | 	</tags>
168 | </law>
169 | 
170 | --------------------------------------------------------------------------------