slaw 1.0.0.alpha.6 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +13 -147
- data/bin/slaw +2 -1
- data/lib/slaw.rb +0 -6
- data/lib/slaw/generator.rb +2 -8
- data/lib/slaw/grammars/pl/act.treetop +10 -14
- data/lib/slaw/grammars/pl/act_text.xsl +271 -0
- data/lib/slaw/version.rb +1 -1
- data/slaw.gemspec +3 -3
- metadata +6 -17
- data/lib/slaw/act.rb +0 -452
- data/lib/slaw/bylaw.rb +0 -62
- data/lib/slaw/collection.rb +0 -60
- data/lib/slaw/lifecycle_event.rb +0 -23
- data/lib/slaw/render/html.rb +0 -70
- data/lib/slaw/render/xsl/act.xsl +0 -15
- data/lib/slaw/render/xsl/elements.xsl +0 -120
- data/lib/slaw/render/xsl/fragment.xsl +0 -16
- data/spec/act_spec.rb +0 -56
- data/spec/bylaw_spec.rb +0 -49
data/lib/slaw/bylaw.rb
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
require 'slaw/act'
|
2
|
-
|
3
|
-
module Slaw
|
4
|
-
# An extension of {Slaw::Act} which wraps an AkomaNtoso XML document describing an By-Law.
|
5
|
-
#
|
6
|
-
# There are minor differences between Acts and By-laws, the most notable being that a by-law
|
7
|
-
# is not identified by a year and a number, and therefore has a different FRBR uri structure.
|
8
|
-
class ByLaw < Act
|
9
|
-
|
10
|
-
# [String] The code of the region this by-law applies to
|
11
|
-
attr_reader :region
|
12
|
-
|
13
|
-
# [String] A short file-like name of this by-law, unique within its year and region
|
14
|
-
attr_reader :name
|
15
|
-
|
16
|
-
# ByLaws don't have numbers, use their short-name instead
|
17
|
-
def num
|
18
|
-
name
|
19
|
-
end
|
20
|
-
|
21
|
-
def title
|
22
|
-
node = @meta.at_xpath('./a:identification/a:FRBRWork/a:FRBRalias', a: NS)
|
23
|
-
title = node ? node['value'] : "(Unknown)"
|
24
|
-
|
25
|
-
if amended? and not title.end_with?("as amended")
|
26
|
-
title = title + " as amended"
|
27
|
-
end
|
28
|
-
|
29
|
-
title
|
30
|
-
end
|
31
|
-
|
32
|
-
# Set the short (file-like) name for this bylaw. This changes the {#id_uri}.
|
33
|
-
def name=(value)
|
34
|
-
@name = value
|
35
|
-
rebuild_id_uri
|
36
|
-
end
|
37
|
-
|
38
|
-
# Set the region code for this bylaw. This changes the {#id_uri}.
|
39
|
-
def region=(value)
|
40
|
-
@region = value
|
41
|
-
rebuild_id_uri
|
42
|
-
end
|
43
|
-
|
44
|
-
protected
|
45
|
-
|
46
|
-
def extract_id_uri
|
47
|
-
# /za/by-law/cape-town/2010/public-parks
|
48
|
-
|
49
|
-
@id_uri = @meta.at_xpath('./a:identification/a:FRBRWork/a:FRBRuri', a: NS)['value']
|
50
|
-
empty, @country, @nature, @region, date, @name = @id_uri.split('/')
|
51
|
-
|
52
|
-
# yyyy[-mm-dd]
|
53
|
-
@year = date.split('-', 2)[0]
|
54
|
-
end
|
55
|
-
|
56
|
-
def build_id_uri
|
57
|
-
# /za/by-law/cape-town/2010/public-parks
|
58
|
-
"/#{@country}/#{@nature}/#{@region}/#{@year}/#{@name}"
|
59
|
-
end
|
60
|
-
|
61
|
-
end
|
62
|
-
end
|
data/lib/slaw/collection.rb
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
require 'forwardable'
|
2
|
-
|
3
|
-
module Slaw
|
4
|
-
# A collection of Act instances.
|
5
|
-
#
|
6
|
-
# This is useful for looking up acts by their FRBR uri and for
|
7
|
-
# loading a collection of XML act documents.
|
8
|
-
#
|
9
|
-
# This collection is enumerable and can be iterated over. Use {#items} to
|
10
|
-
# access the underlying array of objects.
|
11
|
-
#
|
12
|
-
# @example Load a collection of acts and then iterate over them.
|
13
|
-
#
|
14
|
-
# acts = Slaw::DocumentCollection.new
|
15
|
-
# acts.discover('/path/to/acts/')
|
16
|
-
#
|
17
|
-
# for act in acts
|
18
|
-
# puts act.short_name
|
19
|
-
# end
|
20
|
-
#
|
21
|
-
class DocumentCollection
|
22
|
-
|
23
|
-
include Enumerable
|
24
|
-
extend Forwardable
|
25
|
-
|
26
|
-
# [Array<Act>] The underlying array of acts
|
27
|
-
attr_accessor :items
|
28
|
-
|
29
|
-
def_delegators :items, :each, :<<, :length
|
30
|
-
|
31
|
-
def initialize(items=nil)
|
32
|
-
@items = items || []
|
33
|
-
end
|
34
|
-
|
35
|
-
# Find all XML files in `path` and add them into this
|
36
|
-
# collection.
|
37
|
-
#
|
38
|
-
# @param path [String] the path to glob for xml files
|
39
|
-
# @param cls [Class] the class to instantiate for each file
|
40
|
-
#
|
41
|
-
# @return [DocumentCollection] this collection
|
42
|
-
def discover(path, cls=Slaw::Act)
|
43
|
-
for fname in Dir.glob("#{path}/**/*.xml")
|
44
|
-
@items << cls.new(fname)
|
45
|
-
end
|
46
|
-
|
47
|
-
self
|
48
|
-
end
|
49
|
-
|
50
|
-
# Try to find an act who's FRBRuri matches this one,
|
51
|
-
# returning nil on failure
|
52
|
-
#
|
53
|
-
# @param uri [String] the uri to look for
|
54
|
-
#
|
55
|
-
# @return [Act, nil] the act, or nil
|
56
|
-
def for_uri(uri)
|
57
|
-
return @items.find { |doc| doc.id_uri == uri }
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
data/lib/slaw/lifecycle_event.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
module Slaw
|
2
|
-
# An event in the lifecycle of an act
|
3
|
-
class LifecycleEvent
|
4
|
-
include Slaw::Namespace
|
5
|
-
|
6
|
-
# Date of the event
|
7
|
-
attr_accessor :date
|
8
|
-
|
9
|
-
# type of the event
|
10
|
-
attr_accessor :type
|
11
|
-
|
12
|
-
# the source of the event, an XML reference element
|
13
|
-
attr_accessor :source
|
14
|
-
|
15
|
-
def initialize(element)
|
16
|
-
@date = element['date']
|
17
|
-
@type = element['type']
|
18
|
-
|
19
|
-
source_id = element['source'][1..-1]
|
20
|
-
@source = element.document.at_xpath("//a:references/*[@id=\"#{source_id}\"]", a: NS)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
data/lib/slaw/render/html.rb
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
module Slaw
|
2
|
-
module Render
|
3
|
-
|
4
|
-
# Support for transforming XML AN documents into HTML.
|
5
|
-
#
|
6
|
-
# This rendering is done using XSLT stylesheets. Both an entire
|
7
|
-
# document and fragments can be rendered.
|
8
|
-
class HTMLRenderer
|
9
|
-
|
10
|
-
# [Hash] A Hash of Nokogiri::XSLT objects
|
11
|
-
attr_accessor :xslt
|
12
|
-
|
13
|
-
def initialize
|
14
|
-
here = File.dirname(__FILE__)
|
15
|
-
|
16
|
-
@xslt = {
|
17
|
-
act: Nokogiri::XSLT(File.open(File.join([here, 'xsl/act.xsl']))),
|
18
|
-
fragment: Nokogiri::XSLT(File.open(File.join([here, 'xsl/fragment.xsl']))),
|
19
|
-
}
|
20
|
-
end
|
21
|
-
|
22
|
-
# Transform an entire XML document (a Nokogiri::XML::Document object) into HTML.
|
23
|
-
# Specify `base_url` to manage the base for relative URLs generated by
|
24
|
-
# the transform.
|
25
|
-
#
|
26
|
-
# @param doc [Nokogiri::XML::Document] document to render
|
27
|
-
# @param base_url [String] root URL for relative URLs (cannot be empty)
|
28
|
-
#
|
29
|
-
# @return [String]
|
30
|
-
def render(doc, base_url='')
|
31
|
-
params = _transform_params({'base_url' => base_url})
|
32
|
-
_run_xslt(:act, doc, params)
|
33
|
-
end
|
34
|
-
|
35
|
-
# Transform just a single node and its children into HTML.
|
36
|
-
#
|
37
|
-
# If +elem+ has an id, we use xpath to tell the XSLT which
|
38
|
-
# element to transform. Otherwise we copy the node into a new
|
39
|
-
# tree and apply the XSLT to that.
|
40
|
-
#
|
41
|
-
# @param node [Nokogiri::XML::Node] node to render
|
42
|
-
# @param base_url [String] root URL for relative URLs (cannot be empty)
|
43
|
-
#
|
44
|
-
# @return [String]
|
45
|
-
def render_node(node, base_url='')
|
46
|
-
params = _transform_params({'base_url' => base_url})
|
47
|
-
|
48
|
-
if node.id
|
49
|
-
params += ['root_elem', "//*[@id='#{node.id}']"]
|
50
|
-
doc = node.document
|
51
|
-
else
|
52
|
-
# create a new document with just this element at the root
|
53
|
-
doc = Nokogiri::XML::Document.new
|
54
|
-
doc.root = node
|
55
|
-
params += ['root_elem', '*']
|
56
|
-
end
|
57
|
-
|
58
|
-
_run_xslt(:fragment, doc, params)
|
59
|
-
end
|
60
|
-
|
61
|
-
def _run_xslt(xslt, doc, params)
|
62
|
-
@xslt[xslt].transform(doc, params).to_s
|
63
|
-
end
|
64
|
-
|
65
|
-
def _transform_params(params)
|
66
|
-
Nokogiri::XSLT.quote_params(params)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
data/lib/slaw/render/xsl/act.xsl
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
<?xml version="1.0"?>
|
2
|
-
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
|
3
|
-
xmlns:a="http://www.akomantoso.org/2.0"
|
4
|
-
exclude-result-prefixes="a">
|
5
|
-
|
6
|
-
<xsl:import href="elements.xsl" />
|
7
|
-
|
8
|
-
<xsl:output method="html" />
|
9
|
-
|
10
|
-
<xsl:template match="/">
|
11
|
-
<xsl:apply-templates select="a:akomaNtoso/a:act" />
|
12
|
-
</xsl:template>
|
13
|
-
|
14
|
-
</xsl:stylesheet>
|
15
|
-
|
@@ -1,120 +0,0 @@
|
|
1
|
-
<?xml version="1.0"?>
|
2
|
-
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
|
3
|
-
xmlns:a="http://www.akomantoso.org/2.0"
|
4
|
-
exclude-result-prefixes="a">
|
5
|
-
|
6
|
-
<xsl:template match="a:act">
|
7
|
-
<xsl:element name="span" namespace="">
|
8
|
-
<xsl:attribute name="class">an-act</xsl:attribute>
|
9
|
-
<xsl:apply-templates select="a:preamble" />
|
10
|
-
<xsl:apply-templates select="a:body/a:part | a:body/a:chapter | a:body/a:section" />
|
11
|
-
</xsl:element>
|
12
|
-
</xsl:template>
|
13
|
-
|
14
|
-
<!-- for parts and chapters, include an easily stylable heading -->
|
15
|
-
<xsl:template match="a:part">
|
16
|
-
<div class="an-part" id="{@id}">
|
17
|
-
<h1>
|
18
|
-
<xsl:text>Part </xsl:text>
|
19
|
-
<xsl:value-of select="./a:num" />
|
20
|
-
<xsl:text> - </xsl:text>
|
21
|
-
<xsl:value-of select="./a:heading" />
|
22
|
-
</h1>
|
23
|
-
|
24
|
-
<xsl:apply-templates select="./*[not(self::a:num) and not(self::a:heading)]" />
|
25
|
-
</div>
|
26
|
-
</xsl:template>
|
27
|
-
|
28
|
-
<xsl:template match="a:chapter">
|
29
|
-
<div class="an-chapter" id="{@id}">
|
30
|
-
<h1>
|
31
|
-
<xsl:text>Chapter </xsl:text>
|
32
|
-
<xsl:value-of select="./a:num" />
|
33
|
-
<br/>
|
34
|
-
<xsl:value-of select="./a:heading" />
|
35
|
-
</h1>
|
36
|
-
|
37
|
-
<xsl:apply-templates select="./*[not(self::a:num) and not(self::a:heading)]" />
|
38
|
-
</div>
|
39
|
-
</xsl:template>
|
40
|
-
|
41
|
-
<!-- the schedules "chapter" isn't actually a chapter -->
|
42
|
-
<xsl:template match="a:chapter[starts-with(@id, 'schedule')]">
|
43
|
-
<div class="an-chapter" id="{@id}">
|
44
|
-
<h1>
|
45
|
-
<xsl:text>Schedule </xsl:text>
|
46
|
-
<xsl:value-of select="./a:num" />
|
47
|
-
<br/>
|
48
|
-
<xsl:value-of select="./a:heading" />
|
49
|
-
</h1>
|
50
|
-
|
51
|
-
<xsl:apply-templates select="./*[not(self::a:num) and not(self::a:heading)]" />
|
52
|
-
</div>
|
53
|
-
</xsl:template>
|
54
|
-
|
55
|
-
<xsl:template match="a:section">
|
56
|
-
<div class="an-{local-name()}" id="{@id}">
|
57
|
-
<h3>
|
58
|
-
<xsl:value-of select="./a:num" />
|
59
|
-
<xsl:text> </xsl:text>
|
60
|
-
<xsl:value-of select="./a:heading" />
|
61
|
-
</h3>
|
62
|
-
|
63
|
-
<xsl:apply-templates select="./*[not(self::a:num) and not(self::a:heading)]" />
|
64
|
-
</div>
|
65
|
-
</xsl:template>
|
66
|
-
|
67
|
-
<xsl:template match="a:subsection">
|
68
|
-
<span class="an-{local-name()}" id="{@id}">
|
69
|
-
<xsl:apply-templates select="./*[not(self::a:heading)]" />
|
70
|
-
</span>
|
71
|
-
</xsl:template>
|
72
|
-
|
73
|
-
<!-- for term nodes, ensure we keep the refersTo element -->
|
74
|
-
<xsl:template match="a:term">
|
75
|
-
<a class="an-{local-name()}">
|
76
|
-
<xsl:attribute name="data-refers-to">
|
77
|
-
<xsl:value-of select="@refersTo" />
|
78
|
-
</xsl:attribute>
|
79
|
-
|
80
|
-
<xsl:attribute name="href"><xsl:value-of select="$base_url" />/definitions/#def-<xsl:value-of select="translate(@refersTo, '#', '')" /></xsl:attribute>
|
81
|
-
|
82
|
-
<xsl:apply-templates />
|
83
|
-
</a>
|
84
|
-
</xsl:template>
|
85
|
-
|
86
|
-
<!-- for all nodes, generate a SPAN element with a class matching
|
87
|
-
the AN name of the node and copy over the ID if it exists -->
|
88
|
-
<xsl:template match="*">
|
89
|
-
<span class="an-{local-name()}">
|
90
|
-
<xsl:if test="@id">
|
91
|
-
<xsl:attribute name="id">
|
92
|
-
<xsl:value-of select="@id" />
|
93
|
-
</xsl:attribute>
|
94
|
-
</xsl:if>
|
95
|
-
<xsl:apply-templates />
|
96
|
-
</span>
|
97
|
-
</xsl:template>
|
98
|
-
|
99
|
-
<!-- For HTML table elements, copy them over then apply normal AN
|
100
|
-
processing to their contents -->
|
101
|
-
<xsl:template match="a:table | a:tr | a:th | a:td">
|
102
|
-
<xsl:element name="{local-name()}">
|
103
|
-
<xsl:copy-of select="@*" />
|
104
|
-
<xsl:apply-templates />
|
105
|
-
</xsl:element>
|
106
|
-
</xsl:template>
|
107
|
-
|
108
|
-
<!-- special HTML elements -->
|
109
|
-
<xsl:template match="a:a | a:abbr | a:b | a:i | a:span | a:sub | a:sup | a:u">
|
110
|
-
<xsl:element name="{local-name()}">
|
111
|
-
<xsl:copy-of select="@*" />
|
112
|
-
<xsl:apply-templates />
|
113
|
-
</xsl:element>
|
114
|
-
</xsl:template>
|
115
|
-
|
116
|
-
<xsl:template match="a:eol">
|
117
|
-
<xsl:element name="br" />
|
118
|
-
</xsl:template>
|
119
|
-
|
120
|
-
</xsl:stylesheet>
|
@@ -1,16 +0,0 @@
|
|
1
|
-
<?xml version="1.0"?>
|
2
|
-
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
|
3
|
-
xmlns:a="http://www.akomantoso.org/2.0"
|
4
|
-
exclude-result-prefixes="a">
|
5
|
-
|
6
|
-
<xsl:import href="elements.xsl" />
|
7
|
-
|
8
|
-
<xsl:output method="html" />
|
9
|
-
|
10
|
-
<xsl:template match="/">
|
11
|
-
<!-- root_elem is passed in as an xpath parameter -->
|
12
|
-
<xsl:apply-templates select="$root_elem" />
|
13
|
-
</xsl:template>
|
14
|
-
|
15
|
-
</xsl:stylesheet>
|
16
|
-
|
data/spec/act_spec.rb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
require 'slaw'
|
5
|
-
|
6
|
-
describe Slaw::Act do
|
7
|
-
let(:filename) { File.dirname(__FILE__) + "/fixtures/community-fire-safety.xml" }
|
8
|
-
subject { Slaw::Act.new(filename) }
|
9
|
-
|
10
|
-
it 'should have correct basic properties' do
|
11
|
-
subject.title.should == 'Community Fire Safety By-law'
|
12
|
-
subject.amended?.should be_true
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'should set the title correctly' do
|
16
|
-
subject.title = 'foo'
|
17
|
-
subject.meta.at_xpath('./a:identification/a:FRBRWork/a:FRBRalias', a: Slaw::NS)['value'].should == 'foo'
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'should set the title if it doesnt exist' do
|
21
|
-
subject.meta.at_xpath('./a:identification/a:FRBRWork/a:FRBRalias', a: Slaw::NS).remove
|
22
|
-
subject.title = 'bar'
|
23
|
-
subject.title.should == 'bar'
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'should set the publication details' do
|
27
|
-
subject.meta.at_xpath('./a:publication', a: Slaw::NS).remove
|
28
|
-
|
29
|
-
subject.published!(name: 'foo', number: '1234', date: '2014-01-01')
|
30
|
-
subject.publication['name'].should == 'foo'
|
31
|
-
subject.publication['showAs'].should == 'foo'
|
32
|
-
subject.publication['number'].should == '1234'
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'should get/set the work date' do
|
36
|
-
subject.date.should == '2002-02-28'
|
37
|
-
|
38
|
-
subject.date = '2014-01-01'
|
39
|
-
subject.date.should == '2014-01-01'
|
40
|
-
subject.meta.at_xpath('./a:identification/a:FRBRWork/a:FRBRdate[@name="Generation"]', a: Slaw::NS)['date'].should == '2014-01-01'
|
41
|
-
subject.meta.at_xpath('./a:identification/a:FRBRExpression/a:FRBRdate[@name="Generation"]', a: Slaw::NS)['date'].should == '2014-01-01'
|
42
|
-
|
43
|
-
subject.id_uri.should == '/za/by-law/2014/2002'
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'should update the uri when the year changes' do
|
47
|
-
subject.id_uri.should == '/za/by-law/cape-town/2002/community-fire-safety'
|
48
|
-
subject.year = '1980'
|
49
|
-
subject.id_uri.should == '/za/by-law/1980/2002'
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'should validate' do
|
53
|
-
subject.validate.should == []
|
54
|
-
subject.validates?.should be_true
|
55
|
-
end
|
56
|
-
end
|
data/spec/bylaw_spec.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
require 'slaw'
|
5
|
-
|
6
|
-
describe Slaw::ByLaw do
|
7
|
-
let(:filename) { File.dirname(__FILE__) + "/fixtures/community-fire-safety.xml" }
|
8
|
-
subject { Slaw::ByLaw.new(filename) }
|
9
|
-
|
10
|
-
it 'should have correct basic properties' do
|
11
|
-
subject.title.should == 'Community Fire Safety By-law as amended'
|
12
|
-
subject.amended?.should be_true
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'should update the uri when the region changes' do
|
16
|
-
subject.id_uri.should == '/za/by-law/cape-town/2002/community-fire-safety'
|
17
|
-
subject.region = 'foo-bar'
|
18
|
-
subject.id_uri.should == '/za/by-law/foo-bar/2002/community-fire-safety'
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'should update the uri when the name changes' do
|
22
|
-
subject.id_uri.should == '/za/by-law/cape-town/2002/community-fire-safety'
|
23
|
-
subject.name = 'foo-bar'
|
24
|
-
subject.id_uri.should == '/za/by-law/cape-town/2002/foo-bar'
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'should set the title if it doesnt exist' do
|
28
|
-
subject.meta.at_xpath('./a:identification/a:FRBRWork/a:FRBRalias', a: Slaw::NS).remove
|
29
|
-
subject.title = 'bar'
|
30
|
-
subject.title.should == 'bar as amended'
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'should get/set the work date' do
|
34
|
-
subject.date.should == '2002-02-28'
|
35
|
-
|
36
|
-
subject.date = '2014-01-01'
|
37
|
-
subject.date.should == '2014-01-01'
|
38
|
-
subject.meta.at_xpath('./a:identification/a:FRBRWork/a:FRBRdate[@name="Generation"]', a: Slaw::NS)['date'].should == '2014-01-01'
|
39
|
-
subject.meta.at_xpath('./a:identification/a:FRBRExpression/a:FRBRdate[@name="Generation"]', a: Slaw::NS)['date'].should == '2014-01-01'
|
40
|
-
|
41
|
-
subject.id_uri.should == '/za/by-law/cape-town/2014/community-fire-safety'
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'should update the uri when the year changes' do
|
45
|
-
subject.id_uri.should == '/za/by-law/cape-town/2002/community-fire-safety'
|
46
|
-
subject.year = '1980'
|
47
|
-
subject.id_uri.should == '/za/by-law/cape-town/1980/community-fire-safety'
|
48
|
-
end
|
49
|
-
end
|