Commit | Line | Data |
---|---|---|
c1c9c817 MG |
1 | package Zeal::Docset; |
2 | ||
3 | use 5.014000; | |
4 | use strict; | |
5 | use warnings; | |
6 | ||
7 | our $VERSION = '0.000_001'; | |
8 | ||
9 | use parent qw/Class::Accessor::Fast/; | |
10 | __PACKAGE__->mk_ro_accessors(qw/path plist dbh name id family/); | |
11 | ||
12 | use Carp qw/carp/; | |
13 | use Cwd qw/realpath/; | |
14 | use File::Spec::Functions qw/catfile catdir rel2abs/; | |
15 | use HTTP::Tiny; | |
16 | ||
17 | use DBI; | |
18 | use File::Slurp qw/read_file/; | |
19 | use Mac::PropertyList::SAX qw/parse_plist_file/; | |
20 | ||
21 | use Zeal::Document; | |
22 | ||
23 | sub new { | |
24 | my ($class, $path) = @_; | |
25 | $path = realpath $path; | |
26 | my $plpath = catfile $path, 'Contents', 'Info.plist'; | |
27 | my $dbpath = catfile $path, 'Contents', 'Resources', 'docSet.dsidx'; | |
28 | my $plist = parse_plist_file($plpath)->as_perl; | |
29 | carp 'This is not a Dash docset' unless $plist->{isDashDocset}; | |
30 | ||
31 | bless { | |
32 | path => $path, | |
33 | plist => $plist, | |
34 | dbh => DBI->connect("dbi:SQLite:dbname=$dbpath", '', ''), | |
35 | name => $plist->{CFBundleName}, | |
36 | id => $plist->{CFBundleIdentifier}, | |
37 | family => $plist->{DocSetPlatformFamily}, | |
38 | }, $class | |
39 | } | |
40 | ||
41 | sub _blessdocs { | |
42 | my ($self, $docsref) = @_; | |
43 | map { Zeal::Document->new(+{%$_, docset => $self}) } @$docsref; | |
44 | } | |
45 | ||
46 | sub fetch { | |
47 | my ($self, $path) = @_; | |
9f3addb5 | 48 | return HTTP::Tiny->new->get($path)->{content} if $path =~ /^http:/s; |
c1c9c817 MG |
49 | my $docroot = catdir $self->path, 'Contents', 'Resources', 'Documents'; |
50 | $path = rel2abs $path, $docroot; | |
51 | scalar read_file $path | |
52 | } | |
53 | ||
54 | sub query { | |
55 | my ($self, $cond) = @_; | |
56 | my $query = 'SELECT * FROM searchIndex WHERE name LIKE ?'; | |
57 | my $res = $self->dbh->selectall_arrayref($query, {Slice => {}}, $cond); | |
58 | my @results = $self->_blessdocs($res); | |
59 | wantarray ? @results : $results[0] | |
60 | } | |
61 | ||
62 | sub get { | |
63 | my ($self, $cond) = @_; | |
64 | $self->query($cond)->fetch | |
65 | } | |
66 | ||
67 | sub list { | |
68 | my ($self) = @_; | |
69 | my $query = 'SELECT * FROM searchIndex'; | |
70 | my $res = $self->dbh->selectall_arrayref($query, {Slice => {}}); | |
71 | $self->_blessdocs($res) | |
72 | } | |
73 | ||
74 | 1; | |
75 | __END__ | |
76 | ||
77 | =encoding utf-8 | |
78 | ||
79 | =head1 NAME | |
80 | ||
81 | Zeal::Docset - Class representing a Dash/Zeal docset | |
82 | ||
83 | =head1 SYNOPSIS | |
84 | ||
85 | use Zeal::Docset; | |
86 | ||
87 | =head1 DESCRIPTION | |
88 | ||
89 | Dash is an offline API documentation browser. Zeal::Docset is a class | |
90 | representing a Dash/Zeal docset. | |
91 | ||
92 | Available methods: | |
93 | ||
94 | =over | |
95 | ||
96 | =item Zeal::Docset->B<new>(I<$path>) | |
97 | ||
98 | Create a Zeal::Docset object from a given docset. I<$path> should be | |
99 | the path to a F<something.docset> directory. | |
100 | ||
101 | =item $ds->B<path> | |
102 | ||
103 | The path to the docset folder. | |
104 | ||
105 | =item $ds->B<plist> | |
106 | ||
107 | A hashref with the contents of Info.plist. | |
108 | ||
109 | =item $ds->B<dbh> | |
110 | ||
111 | A DBI database handle to the docSet.dsidx index. | |
112 | ||
113 | =item $ds->B<name> | |
114 | ||
115 | The name of this docset. Equivalent to | |
116 | C<< $ds->plist->{CFBundleName} >> | |
117 | ||
118 | =item $ds->B<id> | |
119 | ||
120 | The identifier of this docset. Equivalent to | |
121 | C<< $ds->plist->{CFBundleIdentifier} >> | |
122 | ||
123 | =item $ds->B<family> | |
124 | ||
125 | The family this docset belongs to. Dash uses this as the keyword for | |
126 | restricting searches to a particular family of docsets. Equivalent to | |
127 | C<< $ds->plist->{DocSetPlatformFamily} >> | |
128 | ||
129 | =item $ds->B<fetch>(I<$path>) | |
130 | ||
131 | Internal method for fetching the HTML content of a document. I<$path> | |
132 | is either the path to the document relative to C<< $ds->B<path> >> or | |
133 | a HTTP URL. | |
134 | ||
135 | =item $ds->B<query>(I<$cond>) | |
136 | ||
137 | In list context, return all documents (L<Zeal::Document> instances) | |
138 | matching I<$cond>. In scalar context, return one such document. | |
139 | I<$cond> is a SQL LIKE condition. | |
140 | ||
141 | =item $ds->B<get>(I<$cond>) | |
142 | ||
143 | The HTML content of one document that matches I<$cond>. | |
144 | I<$cond> is a SQL LIKE condition. | |
145 | ||
146 | This method is shorthand for C<< $ds->query(I<$cond>)->fetch >>. | |
147 | ||
148 | =item $ds->B<list> | |
149 | ||
150 | The list of all documents (L<Zeal::Document> instances) in this | |
151 | docset. | |
152 | ||
153 | =back | |
154 | ||
155 | =head1 SEE ALSO | |
156 | ||
157 | L<Zeal>, L<http://kapeli.com/dash>, L<http://zealdocs.org> | |
158 | ||
159 | =head1 AUTHOR | |
160 | ||
161 | Marius Gavrilescu, E<lt>marius@ieval.roE<gt> | |
162 | ||
163 | =head1 COPYRIGHT AND LICENSE | |
164 | ||
165 | Copyright (C) 2014 by Marius Gavrilescu | |
166 | ||
167 | This library is free software; you can redistribute it and/or modify | |
168 | it under the same terms as Perl itself, either Perl version 5.20.1 or, | |
169 | at your option, any later version of Perl 5 you may have available. | |
170 | ||
171 | ||
172 | =cut |