Commit 833f753e authored by ChangZhuo Chen's avatar ChangZhuo Chen

Imported Upstream version 0.1.1

parent 5838a268
image: jkozera/qt5-mingw32 # Dockerfile available at https://github.com/jkozera/docker-qt5-mingw32
script:
- wine regedit /root/qttemp.reg # doesn't work for some reason in Dockerfile's setup.sh
- cd zeal
- date +%Y%m%d > VERSION
# a bit ugly version updating:
- grep -v ZEAL_VERSION zeal.pro > zeal.pro.noversion
- mv zeal.pro.noversion zeal.pro
- echo 'DEFINES += ZEAL_VERSION=\\\"'`cat VERSION`'\\\"' >> zeal.pro
- wine qmake
- wine mingw32-make
- mkdir zeal-$(cat VERSION)
- cp release/zeal.exe zeal-$(cat VERSION)
- cp -r icons zeal-$(cat VERSION)
- wget https://bitbucket.org/jerzykozera/zeal-win32-binary-downloads/downloads/bsdtar.exe -O zeal-$(cat VERSION)/bsdtar.exe
- wget https://bitbucket.org/jerzykozera/zeal-win32-binary-downloads/downloads/bzip2.dll -O zeal-$(cat VERSION)/bzip2.dll
- wget https://bitbucket.org/jerzykozera/zeal-win32-binary-downloads/downloads/zlib1.dll -O zeal-$(cat VERSION)/zlib1.dll
- mkdir zeal-$(cat VERSION)/imageformats
- mkdir zeal-$(cat VERSION)/platforms
- mkdir zeal-$(cat VERSION)/sqldrivers
- cp /root/Tools/mingw482_32/opt/bin/ssleay32.dll zeal-$(cat VERSION)
- cp /root/Tools/mingw482_32/opt/bin/libeay32.dll zeal-$(cat VERSION)
- cp /root/5.3/mingw482_32/plugins/imageformats/qico.dll zeal-$(cat VERSION)/imageformats
- cp /root/5.3/mingw482_32/plugins/platforms/qwindows.dll zeal-$(cat VERSION)/platforms
- cp /root/5.3/mingw482_32/plugins/sqldrivers/qsqlite.dll zeal-$(cat VERSION)/sqldrivers
- cp /root/5.3/mingw482_32/bin/libstdc++-6.dll zeal-$(cat VERSION)
- cp /root/5.3/mingw482_32/bin/libgcc_s_dw2-1.dll zeal-$(cat VERSION)
- cp /root/5.3/mingw482_32/bin/libwinpthread-1.dll zeal-$(cat VERSION)
- cp /root/5.3/mingw482_32/bin/icu*.dll zeal-$(cat VERSION)
- for l in Core Gui Multimedia MultimediaWidgets Network OpenGL Qml Quick Sql WebKit WebKitWidgets Widgets Xml Positioning PrintSupport Sensors; do cp /root/5.3/mingw482_32/bin/Qt5$l.dll zeal-$(cat VERSION); done
- zip -r zeal-$(cat VERSION).zip zeal-$(cat VERSION)
- mkdir win32_release
- mv zeal-$(cat VERSION).zip win32_release
publish:
github:
branch: master
artifacts:
- win32_release/
tag: $(cat VERSION)
token: $$github_token
user: jkozera
repo: zeal
zeal-build-Desktop-Debug/
zeal/zeal.pro.user
# C++ objects and libs
*.slo
*.lo
*.o
zeal/zeal
zeal/moc_*.cpp
zeal/ui_*.h
zeal/Makefile
build-zeal-Desktop*
*.swp
zeal/qrc_zeal.cpp
*.a
*.la
*.lai
*.so
*.dll
*.dylib
# Qt-es
/.qmake.cache
/.qmake.stash
*.pro.user
*.pro.user.*
*.moc
moc_*.cpp
qrc_*.cpp
ui_*.h
Makefile*
*-build-*
# QtCreator
*.autosave
#QtCtreator Qml
*.qmlproject.user
*.qmlproject.user.*
SRC_ROOT=$$PWD
BUILD_ROOT=$$shadowed($$PWD)
build_image: shippableimages/ubuntu1404_base
cache: true
before_install:
- dpkg --add-architecture i386
- shippable_retry sudo apt-get -y -q update
- export QT_DIR=$HOME/qt/5.4/mingw491_32
install:
- shippable_retry sudo apt-get -y -q install --no-install-recommends wine p7zip-full ca-certificates curl
# Install Qt
- bash -c '[ -d $HOME/qt/Tools ] || mkdir -p $HOME/qt/OUT'
- bash -c '[ -d $HOME/qt/Tools ] || curl -Lso $HOME/qt/qt.exe http://download.qt.io/official_releases/qt/5.4/5.4.0/qt-opensource-windows-x86-mingw491_opengl-5.4.0.exe'
- bash -c '[ -d $HOME/qt/Tools ] || wine $HOME/qt/qt.exe --dump-binary-data -o $HOME/qt/OUT'
- bash -c '[ -d $HOME/qt/Tools ] || 7z x $HOME/qt/OUT/qt.54.win32_mingw491/5.4.0-1i686-4.9.1-release-posix-dwarf-rt_v3-rev2-runtime.7z -o$HOME/qt'
- bash -c '[ -d $HOME/qt/Tools ] || 7z x $HOME/qt/OUT/qt.54.win32_mingw491/5.4.0-1icu_53_1_mingw_builds_4_9_1_posix_dwarf_32.7z -o$HOME/qt'
- bash -c '[ -d $HOME/qt/Tools ] || 7z x $HOME/qt/OUT/qt.54.win32_mingw491/5.4.0-1qt5_addons.7z -o$HOME/qt'
- bash -c '[ -d $HOME/qt/Tools ] || 7z x $HOME/qt/OUT/qt.54.win32_mingw491/5.4.0-1qt5_essentials.7z -o$HOME/qt'
- bash -c '[ -d $HOME/qt/Tools ] || 7z x $HOME/qt/OUT/qt.tools.win32_mingw491/4.9.1-2i686-4.9.1-release-posix-dwarf-rt_v3-rev2.7z -o$HOME/qt'
- rm -rf $HOME/qt/OUT
- rm -f $HOME/qt/qt.exe
# Install libarchive headers and library
- bash -c '[ -f $HOME/qt/Tools/mingw491_32/i686-w64-mingw32/include/archive.h ] || curl -LOs https://bitbucket.org/zealdocs/zeal-win32-binary-downloads/downloads/libarchive-3.1.2-win32-mingw491.7z'
- bash -c '[ -f $HOME/qt/Tools/mingw491_32/i686-w64-mingw32/include/archive.h ] || 7z x libarchive-3.1.2-win32-mingw491.7z -o$HOME/qt/Tools/mingw491_32/i686-w64-mingw32'
- rm -f libarchive-3.1.2-win32-mingw491.7z
# Setup environment
- echo '[Paths]' > $QT_DIR/bin/qt.conf
- echo 'Prefix=..' >> $QT_DIR/bin/qt.conf
- echo '[HKEY_CURRENT_USER\Environment]' > $HOME/qt/temp.reg
- echo '"QMAKESPEC"="BASEDIR\\5.4\\mingw491_32\\mkspecs\\win32-g++"' >> $HOME/qt/temp.reg
- echo '"QTDIR"="BASEDIR\\5.4\\mingw491_32"' >> $HOME/qt/temp.reg
- echo '"PATH"="BASEDIR\\Tools\\mingw491_32\\libexec\\gcc\\i686-w64-mingw32;BASEDIR\\Tools\\mingw491_32\\bin;BASEDIR\\5.4\\mingw491_32\\bin"' >> $HOME/qt/temp.reg
- sed -i "s.BASEDIR.Z:$HOME/qt.g" $HOME/qt/temp.reg
- sed -i 's./.\\\\.g' $HOME/qt/temp.reg
- wine regedit $HOME/qt/temp.reg
before_script:
- export ZEAL_VERSION=`date +%Y%m%d`
- export ZEAL_DIR=zeal-$ZEAL_VERSION
script:
- wine qmake
- wine mingw32-make
after_success:
# Prepare ZIP package
- mkdir $ZEAL_DIR
- cp bin/zeal.exe $ZEAL_DIR
- for dir in imageformats platforms sqldrivers; do mkdir $ZEAL_DIR/$dir; done
- cp $HOME/qt/Tools/mingw491_32/opt/bin/ssleay32.dll $ZEAL_DIR
- cp $HOME/qt/Tools/mingw491_32/opt/bin/libeay32.dll $ZEAL_DIR
- for l in gif ico jpeg tiff; do cp $QT_DIR/plugins/imageformats/q$l.dll $ZEAL_DIR/imageformats; done
- cp $QT_DIR/plugins/platforms/qwindows.dll $ZEAL_DIR/platforms
- cp $QT_DIR/plugins/sqldrivers/qsqlite.dll $ZEAL_DIR/sqldrivers
- cp $QT_DIR/bin/libstdc++-6.dll $ZEAL_DIR
- cp $QT_DIR/bin/libgcc_s_dw2-1.dll $ZEAL_DIR
- cp $QT_DIR/bin/libwinpthread-1.dll $ZEAL_DIR
- cp $QT_DIR/bin/icu*.dll $ZEAL_DIR
- for l in Core Gui Multimedia MultimediaWidgets Network OpenGL Qml Quick Sql WebKit WebKitWidgets WebChannel Widgets Positioning PrintSupport Sensors; do cp $QT_DIR/bin/Qt5$l.dll $ZEAL_DIR; done
# Pack everything into ZIP
- 7z a -mx=9 $ZEAL_DIR.zip $ZEAL_DIR
# Upload to BitBucket
- bash -c 'curl -H "Content-Type:application/octet-stream" -H "Auth-Token:$AUTH_TOKEN" --data-binary @$ZEAL_DIR.zip ci2bb.herokuapp.com || true'
# Cleanup
- rm -rf $ZEAL_DIR*
env:
global:
- secure: LRSLJQbkpc6kkWDVbmvCARm20edC+1RCCgSdEzK0GfG66V+dyGYi6ubFBv1M+kV9YEVY1FkkZctiKlneJLpi/YS3pSJF7bEhYggtxNxRD+9bAVk4GZwVxT7TUw1ZPtLUkWc7L7PqgIO+OOiI8THwsONBNcn5q4fLsByhlt2XOyGPOrQYmfmqjWpgErgI0K4aYoJfoJGTgV2v5sZ+owSkMniyJY5WU9iZkRLO63ddmk72d9eq8ECwgQqxDyhR9/WtHkMPCrwVh06RFd9jG4DfCNDDZRdQLdGxCPXTNwP7QHqG9mKFRQeM91gs/tKlhFFlfPHMckWiBK4hAo+WLC+Ekg==
# Zeal
**zeal**
*noun*
[![Build Status](https://api.shippable.com/projects/54ac2ce4d46935d5fbc19b84/badge?branchName=master)](https://app.shippable.com/projects/54ac2ce4d46935d5fbc19b84/builds/latest)
[![AppVeyor](https://img.shields.io/appveyor/ci/trollixx/zeal.svg?style=flat-square)](https://ci.appveyor.com/project/trollixx/zeal)
[![Coverity Scan](https://img.shields.io/coverity/scan/4271.svg?style=flat-square)](https://scan.coverity.com/projects/4271)
[![IRC](https://img.shields.io/badge/irc-%23zealdocs-blue.svg?style=flat-square)](https://kiwiirc.com/client/irc.freenode.net/#zealdocs)
1. a feeling of strong eagerness (usually in favor of a person or cause)
2. excessive fervor to do something or accomplish some end
3. prompt willingness
> **zeal** *noun*
>
> 1. a feeling of strong eagerness (usually in favor of a person or cause)
> 2. excessive fervor to do something or accomplish some end
> 3. prompt willingness
>
> (from WordNet 3.0)
(from WordNet 3.0)
Zeal is a simple documentation browser inspired by [Dash](http://kapeli.com/dash/).
Zeal is a simple offline documentation browser inspired by [Dash](http://kapeli.com/dash/).
![Screenshot](http://i.imgur.com/SiLvpz8.png)
[More screenshots (imgur)](http://imgur.com/a/eVi97)
[More screenshots](http://imgur.com/a/eVi97)
## Download
For details about binary packages (currently available for Windows and Ubuntu) see [downloads page](http://zealdocs.org/download.html).
For details about binary packages (currently available for Windows and Ubuntu) see [downloads page](http://zealdocs.org/download.html). Also, the latest unstable builds are available [here]( https://bitbucket.org/zealdocs/zeal-win32-binary-downloads/downloads).
## How to use
After installing/compiling it you need to download docsets. It can be done automatically by clicking 'Edit', 'Options', 'Docsets', 'Download...'.
After installing Zeal, you need to download docsets. Go to *File->Options->Docsets*, select the ones you want, and click the *Download* button.
## How to compile
If you prefer to compile Zeal manually.
### Requirements
* Qt 5.0
* X C Binding – keysyms (Ubuntu `libxcb-keysyms1-dev`)
* `bsdtar` is required for the built-in docset extracting to work
* `libappindicator` and `libappindicator-devel` for notifications
* you may need to install `libqt5webkit5-dev` and `qtbase5-private-dev`
* [Qt](https://www.qt.io/) (version 5.2.0 or above is required)
* [libarchive](http://libarchive.org/)
* Optionally [libappindicator](https://launchpad.net/libappindicator) for Unity users
To compile it, run `qmake` and `make` in the `zeal` directory. On Linux, a final `make install` is required to install icons.
To compile it, run `qmake` and `make`.
## Query & Filter docsets
......@@ -48,28 +50,10 @@ You can also search multiple docsets separating them with a comma:
## Command line
If you prefer, you can start with Zeal queries from command line, for this, use the option `--query`:
`zeal --query python:bomb`
If you prefer, you can start Zeal with a query from command line:
## TODO
* [Issues](https://github.com/jkozera/zeal/issues)
* Search enhancements - some ideas:
* Allow selecting subset of docsets to search in (enable/disable docsets, docset groups)
* Grouping of similar results (like overloaded functions)
* Code cleanup
* Refactoring to reuse common code between `ZealDocsetsRegistry` and `ZealListModel`
* ...
`zeal python:bomb`
## Creating your own docsets
You can use [Dash's instructions for generating docsets](http://kapeli.com/docsets).
## Contributions / Project Status
Any feedback, feature requests, or pull requests are welcome. However the project is not under active development at the moment, so unless someone is interested in contributing code, no new features are expected.
I'm going to continue updating docsets that are part of Dash/Zeal exchange programme, and try to fix critical stability/compatibility issues if any arise, to keep the project somewhat alive, but will not implement new features in foreseeable future. Anyway, I should be able to review pull requests.
Please keep in mind I'm not an experienced C++ programmer, so the code quality might be not great.
AppceleratorTitanium https://drive.google.com/uc?export=download&confirm=no_antivirus&id=0B8S9pdOpH0GPUVAyU3N1dUxEQWc 201309192030
Django https://drive.google.com/uc?export=download&confirm=no_antivirus&id=0B8S9pdOpH0GPZGlkazZOdFJ0UDg 201303282044
ExtJS-4.2.1 https://drive.google.com/uc?export=download&confirm=no_antivirus&id=0B8S9pdOpH0GPVGg2NVhrWEx0ck0 201305242113
jQuery https://drive.google.com/uc?export=download&confirm=no_antivirus&id=0B8S9pdOpH0GPVS1rVEc3XzFka0E 201305312107
python-2.7.3-docs-html https://drive.google.com/uc?export=download&confirm=no_antivirus&id=0B8S9pdOpH0GPVkVtM0lrNVdCNXM 201303062116
Qt5 https://drive.google.com/uc?export=download&confirm=no_antivirus&id=0B8S9pdOpH0GPMjlHa1k5WTVldDg 201303062116
Ruby https://drive.google.com/uc?export=download&confirm=no_antivirus&id=0B8S9pdOpH0GPS3JZc2dZdUVTYms 201303170016
Ruby2 https://drive.google.com/uc?export=download&confirm=no_antivirus&id=0B8S9pdOpH0GPM1A5WkJKYkd2SEU 201303170016
SenchaTouch-2.2.1 https://drive.google.com/uc?export=download&confirm=no_antivirus&id=0B8S9pdOpH0GPZjM5MWpwOGp3Q00 201305242113
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
#!/usr/bin/env python
"""ExtJS docsets parser - needs to be run in the ExtJS reference documentation
directory as a working directory. It can be downloaded from http://docs.sencha.com/"""
from cStringIO import StringIO
import errno
import os
import re
from json import loads
from lxml.html import parse, tostring, fromstring
from shutil import copytree, rmtree, copy
import sqlite3
INPUT_DIR = '.'
OUTPUT_DIR = os.path.join(INPUT_DIR, 'output')
icon = 'icon.png'
indexpath = 'html/Ext.html'
if os.path.exists(os.path.join(INPUT_DIR, 'extjs-build')):
builddir = 'extjs-build'
OUT_DIR = 'ExtJS-4.2.2.docset'
docsetname = 'ExtJS'
docsetshortname = 'extjs'
elif os.path.exists(os.path.join(INPUT_DIR, 'touch-build')):
builddir = 'touch-build'
OUT_DIR = 'SenchaTouch-2.3.0.docset'
docsetname = 'Sencha Touch'
docsetshortname = 'sencha'
else:
# assuming Appcelerator Titanium
builddir = None
OUT_DIR = 'AppceleratorTitanium.docset'
docsetname = 'Appcelerator Titanium'
docsetshortname = 'titanium'
icon = 'appcelerator.png'
indexpath = 'html/Titanium.html'
DOCUMENTS_DIR = os.path.join(OUT_DIR, 'Contents', 'Resources', 'Documents')
HTML_DIR = os.path.join(DOCUMENTS_DIR, 'html')
rmtree(OUT_DIR, ignore_errors=True)
copytree(INPUT_DIR, DOCUMENTS_DIR)
# index.html doesn't work with Dash
rmtree(os.path.join(DOCUMENTS_DIR, 'output'))
if builddir:
rmtree(os.path.join(DOCUMENTS_DIR, builddir))
rmtree(os.path.join(DOCUMENTS_DIR, 'guides'), ignore_errors=True)
if docsetname == 'Appcelerator Titanium':
# CSS fix for fluid width
for dirpath, dirnames, filenames in os.walk(DOCUMENTS_DIR):
for fname in filenames:
if not fname.endswith('.css'): continue
with open(os.path.join(dirpath, fname), 'a') as f:
f.write("""
body {min-width:0px !important}
.class-overview p.private {border:0px; background-color:inherit; padding:0px; text-align:left;}""")
print os.path.join(dirpath, fname), 'CSS fixed'
os.unlink(os.path.join(DOCUMENTS_DIR, 'index.html'))
copy(os.path.join(os.path.dirname(__file__), icon), os.path.join(OUT_DIR, 'icon.png'))
os.mkdir(HTML_DIR)
with open(os.path.join(OUT_DIR, 'Contents', 'Info.plist'), 'w') as plist:
plist.write("""<?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>%s</string>
<key>CFBundleName</key>
<string>%s</string>
<key>DocSetPlatformFamily</key>
<string>%s</string>
<key>isDashDocset</key>
<true/>
<key>dashIndexFilePath</key>
<string>%s</string>
</dict>
</plist>""" % (docsetshortname, docsetname, docsetshortname, indexpath))
conn = sqlite3.connect(os.path.join(OUT_DIR, 'Contents', 'Resources', 'docSet.dsidx'))
c = conn.cursor()
c.execute('CREATE TABLE searchIndex (id integer primary key, name text, type text, path text)')
c.execute('CREATE UNIQUE INDEX anchor ON searchIndex (name, type, path);')
ids = {}
trees = {}
h3_bug_re = re.compile(r"<h4 class='members-subtitle'>([^<>]+)</h3>")
for fname in os.listdir(OUTPUT_DIR):
data = loads(open(os.path.join(OUTPUT_DIR, fname), 'r').read().split('(', 1)[1].rsplit(')', 1)[0])
html = h3_bug_re.sub(r'<h4 class="members-subtitle">\1</h4>', data['html'].encode('utf-8'))
name = fname.rsplit('.', 1)[0]+'.html'
if not fname.rsplit('.', 1)[0].strip():
# ignore invalid files with empty names
continue
trees[name] = tree = parse(StringIO(html))
for div in tree.findall('//div'):
if 'id' in div.attrib:
ids[name[:-len('.html')]+'-'+div.attrib['id']] = (name, div.attrib['id'])
untypes = set()
for fname, tree in trees.iteritems():
with open(os.path.join(HTML_DIR, fname), 'w') as htmlfile:
htmlfile.write("""<!doctype html>
<html>
<head>
<link rel="stylesheet" href="../resources/css/app-4689d2a5522dcd3c9e9923ca59c33f27.css" type="text/css" />
<!-- titanium hack -->
<link rel="stylesheet" href="../resources/css/my.css" type="text/css" />
<link rel="stylesheet" href="../resources/css/viewport.css" type="text/css" />
<link rel="stylesheet" href="../resources/css/docs-ext.css" type="text/css" />
<style>
body {
margin: 2em;
}
.members .member .short {
display: none;
}
.members .member .long {
display: block;
}
</style>
</head>
<body>
<span style="font-size:2em; font-weight:bold">%s</span>
<!-- center-container is for titanium -->
<div id="center-container" class="class-overview"><div class="x-panel-body">"""%fname[:-len('.html')])
for a in tree.findall('//a'):
if 'href' not in a.attrib: continue
if a.attrib['href'].startswith('source/'):
a.attrib['href'] = '../' + a.attrib['href']
else:
if not a.attrib['href'].startswith('#'): continue
ignore = ['/guide/', '/example/', '/guides/', '/video/']
if any(i in a.attrib['href'] for i in ignore): continue
fragment = a.attrib['href'].replace('#!/api/', '')
def cfg():
return fragment.replace('property-', 'cfg-')
if fragment in ids:
a.attrib['href'] = ids[fragment][0] + '#' + ids[fragment][1]
elif cfg() in ids:
a.attrib['href'] = ids[cfg()][0] + '#' + ids[cfg()][1]
elif fragment == '#':
# remove JS elements
a.getparent().remove(a)
else:
if os.path.isfile(os.path.join(OUTPUT_DIR, fragment+'.js')):
a.attrib['href'] = fragment+'.html'
else:
print fragment, 'missing.'
for pre in tree.findall('//pre'):
if not pre.attrib.get('class'):
# enables CSS
pre.attrib['class'] = 'notpretty'
for section in tree.getroot().find_class('members-section'):
stype = section.find('h3').text
try:
idxtype = {'Methods': 'clm',
'Properties': 'Property',
'Config options': 'Option',
'Events': 'event',
'CSS Mixins': 'Mixin',
'CSS Variables': 'var'}[stype]
except KeyError:
untypes.add(stype)
idxtype = 'unknown'
for member in section.find_class('member'):
membername = member.xpath('div[@class="title"]/a/text()')
if not len(membername): continue
membername = membername[0]
member.insert(0, fromstring("<a name='//apple_ref/cpp/%s/%s' class='dashAnchor' />" % (idxtype, membername)))
if member.find_class('defined-in')[0].text and \
member.find_class('defined-in')[0].text != fname[:-len('.html')]:
assert member.find_class('defined-in')[0].text + '.html' in trees, member.find_class('defined-in')[0].text
continue
c.execute('INSERT INTO searchIndex(type, name, path) values(?, ?, ?)',
(idxtype, fname[:-len('html')]+membername,
os.path.join('html', fname)+'#'+member.attrib['id']))
c.execute('INSERT INTO searchIndex(type, name, path) values("cl", ?, ?)',
(fname[:-len('.html')], os.path.join('html', fname)))
htmlfile.write(tostring(tree))
htmlfile.write("""</body>
</div></div></html>""")
conn.commit()
conn.close()
if untypes:
print 'Unknown types:', untypes
import sqlite3
import os
from lxml.html import parse
os.unlink('index.sqlite')
conn = sqlite3.connect('index.sqlite')
c = conn.cursor()
c.execute('CREATE TABLE things (id integer primary key, type text, name text, path text, parent integer)')
tree = parse('py-modindex.html')
modules = {}
classes = {}
for tbl in tree.xpath('//table[@class="indextable modindextable"]'):
for tr in tbl.findall('tr'):
a = tr.findall('td')[1].find('a')
if a is None: continue
modname = a.find('tt').text
c.execute('INSERT INTO things(type, name, path) values("module", ?, ?)', (modname, a.attrib['href']))
modules[modname] = (c.lastrowid, a.attrib['href'].split('#')[0])
parsed_files = set()
for modname, (modid, fname) in modules.items():
if '.' in modname: modname = modname.split('.')[0] # modules aren't well-structured