Skip to content

Instantly share code, notes, and snippets.

@aufflick
Created November 28, 2014 03:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save aufflick/cdef43bd835831558937 to your computer and use it in GitHub Desktop.
Save aufflick/cdef43bd835831558937 to your computer and use it in GitHub Desktop.
Make a Dash compatible docset from ChilKat's ObjC library html documentation
#!/usr/bin/perl -w
=head1 NAME
make_chilkat_objc_docset - Make a Dash compatible docset from ChilKat's ObjC library html documentation
=head1 SYNOPSIS
./make_chilkat_objc_docset.pl
Then go to the Docsets tab of Dash preferences, and use the [+] button at bottom of list to add the created ChilKatObjC.docset.
=head1 DESCRIPTION
Make a Dash compatible docset from ChilKat's ObjC library html documentation.
ChilKat make a very comprehensive set of cross platform cryptography (and other) libraries. See L<http://www.chilkat.com>.
The docset is a bit basic at the moment, and we have to parse the html...
=cut
use strict;
use warnings;
use LWP::UserAgent;
use HTML::LinkExtor;
use Data::Dumper;
use DBI;
use HTML::TreeBuilder;
my $docset_path = 'ChilKatObjC.docset/';
my $docset_contents_path = $docset_path . 'Contents/';
my $docset_resources_path = $docset_contents_path . 'Resources/';
my $docset_docs_path = $docset_resources_path . 'Documents/';
system("mkdir -p $docset_docs_path") == 0
or die "Unable to create docset dir";
my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new(GET => 'http://www.chilkatsoft.com/refdoc/objc.asp');
my $res = $ua->request($req);
if (!$res->is_success) {
die "Unable to get index page";
}
# will be filled by the found_link callback
my @doc_urls = ('http://www.chilkatsoft.com/css/refdoc.css');
my $p = HTML::LinkExtor->new(\&found_link, $res->base);
$p->parse($res->as_string);
my $dbfile = $docset_resources_path . "docSet.dsidx";
unlink $dbfile;
my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile","","")
or die "Unable to make database";
$dbh->do('CREATE TABLE searchIndex(id INTEGER PRIMARY KEY, name TEXT, type TEXT, path TEXT)');
$dbh->do('CREATE UNIQUE INDEX anchor ON searchIndex (name, type, path)');
my $sth = $dbh->prepare('INSERT OR IGNORE INTO searchIndex(name, type, path) VALUES (?, ?, ?)');
for my $doc_url (@doc_urls) {
$req = HTTP::Request->new(GET => $doc_url);
$res = $ua->request($req);
if ($res->is_success) {
my $text = $res->decoded_content;
$text =~ s!/css/!!g;
my $filename = $res->filename;
open my $fh, '>', $docset_docs_path . $filename
or die $!;
print $fh $text;
print "Wrote " . $filename . "\n";
if ($filename !~ /css$/) {
parse_doc($filename, $text);
}
}
}
write_info_plist();
exit(0);
sub parse_doc {
my ($filename, $content) = @_;
my $tree = HTML::TreeBuilder->new_from_content($content);
my $root = $tree->guts;
$tree = undef;
# find class name
my @h2 = $root->find_by_tag_name('h2');
if (@h2 != 1) {
warn "ChilKat seem to have changed their doc html format for " . $filename . "...";
} else {
$sth->execute($h2[0]->as_text, 'Class', $filename);
}
# find methods & properties
my @entities = $root->look_down( _tag => 'p', id => 'cEnt' );
for my $ent (@entities) {
my $name_el = ($ent->find_by_tag_name('a'))[0];
my $name = $name_el->attr('name');
parse_prop($filename, $ent, $name)
if $name =~ /^prop/;
parse_method($filename, $ent, $name)
if $name =~ /^method/;
}
}
sub parse_prop {
my ($filename, $ent, $name, $class) = @_;
my $sig_el = ($ent->look_down( _tag => 'span', id => 'sig' ))[0];
my $sig = $sig_el->as_text;
if ($sig) {
$sth->execute($sig, 'Property', "$filename#$name");
}
}
sub parse_method {
my ($filename, $ent, $name, $class) = @_;
my $sig_el = ($ent->look_down( _tag => 'span', id => 'sig' ))[0];
my $sig = $sig_el->as_text;
if ($sig) {
$sth->execute($sig, 'Method', "$filename#$name");
}
}
sub found_link {
my ($tag, %links) = @_;
if ($tag eq 'a') {
my $uri = $links{href};
my $page_url = $uri->as_string;
if ($page_url =~ s/Ref.html/Doc.html/) {
push @doc_urls, $page_url;
}
}
}
sub write_info_plist {
my $plist = <<END;
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.chilkat.refdoc.objc</string>
<key>CFBundleName</key>
<string>ChilKat ObjC</string>
<key>DocSetPlatformFamily</key>
<string>ChilKat</string>
<key>isDashDocset</key>
<true/>
</dict>
</plist>
END
open my $fh, '>', $docset_contents_path . 'Info.plist'
or die $!;
print $fh $plist;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment