diff --git a/example.md b/example.md index 3b36983..6c4ae75 100644 --- a/example.md +++ b/example.md @@ -22,7 +22,7 @@ This is the *blah blah*. hijkl - Continued + Cross reference to `rule 1`_ (2) DEF diff --git a/example.pdf b/example.pdf index 50fdf72..96b89b8 100644 Binary files a/example.pdf and b/example.pdf differ diff --git a/example.rtf b/example.rtf index 157b11c..14ceecb 100644 --- a/example.rtf +++ b/example.rtf @@ -1 +1 @@ -{\rtf1\deff0{\fonttbl{\f0 TeX Gyre Heros{\*\falt FreeSans}{\*\falt Liberation Sans}{\*\falt Arial};}}\paperw11905\paperh16837\margl1133\margr1133\margt1133\margb1133{\header\f0\fs16\tqr\tx9637 Example Legal Document\tab }{\footer\f0\fs16\tqr\tx9637 \tab\chpgn}\sa198\fs1\~\fs24 {\fs20\li566{\b Note:} This is a note.\par}{\sb566\keepn\b\fs26\qc\caps Part 1\u8212?Preliminary\par}{\keepn\b\fi-566\li566 1\tab Short title\par}{\li566 This is the {\i blah blah}.\par}{\keepn\b\fi-566\li566 2\tab Another heading\par}{\fi-566\li1133 (1)\tab ABC\par}{\li1133 Continued\par}{\fi-566\li1700 (a)\tab asdf\par}{\fi-566\li1700 (b)\tab abcdefg\par}{\li1700 hijkl\par}{\li1133 Continued\par}{\fi-566\li1133 (2)\tab DEF\par}{\keepn\b\fi-566\li566 3\tab Table example\par}{\sa0\trowd\trgaph120\trleft566\clbrdrt\brdrs\clbrdrb\brdrs\cellx2380\clbrdrt\brdrs\clbrdrb\brdrs\cellx9636 {\b Column 1\intbl\cell}{\b Column 2\intbl\cell}\row{\b This is a long column header that will overflow onto multiple lines\intbl\cell}{\b Second column\intbl\cell}\row {1. First row\intbl\cell}{Foo bar\intbl\cell}\row {2. Second row\intbl\cell}{Baz qux\intbl\cell}\row }} +{\rtf1\deff0{\fonttbl{\f0 TeX Gyre Heros{\*\falt FreeSans}{\*\falt Liberation Sans}{\*\falt Arial};}}\paperw11905\paperh16837\margl1133\margr1133\margt1133\margb1133{\header\f0\fs16\tqr\tx9637 Example Legal Document\tab }{\footer\f0\fs16\tqr\tx9637 \tab\chpgn}\sa198\fs1\~\fs24 {\fs20\li566{\b Note:} This is a note.\par}{\sb566\keepn\b\fs26\qc\caps Part 1\u8212?Preliminary\par}{\keepn\b\fi-566\li566 1\tab Short title\par}{\li566 This is the {\i blah blah}.\par}{\keepn\b\fi-566\li566 2\tab Another heading\par}{\fi-566\li1133 (1)\tab ABC\par}{\li1133 Continued\par}{\fi-566\li1700 (a)\tab asdf\par}{\fi-566\li1700 (b)\tab abcdefg\par}{\li1700 hijkl\par}{\li1133 Cross reference to rule\u160?1\par}{\fi-566\li1133 (2)\tab DEF\par}{\keepn\b\fi-566\li566 3\tab Table example\par}{\sa0\trowd\trgaph120\trleft566\clbrdrt\brdrs\clbrdrb\brdrs\cellx2380\clbrdrt\brdrs\clbrdrb\brdrs\cellx9636 {\b Column 1\intbl\cell}{\b Column 2\intbl\cell}\row{\b This is a long column header that will overflow onto multiple lines\intbl\cell}{\b Second column\intbl\cell}\row {1. First row\intbl\cell}{Foo bar\intbl\cell}\row {2. Second row\intbl\cell}{Baz qux\intbl\cell}\row }} diff --git a/legalmd/__main__.py b/legalmd/__main__.py index da86322..11c3f11 100644 --- a/legalmd/__main__.py +++ b/legalmd/__main__.py @@ -40,4 +40,22 @@ with renderer_cls() as renderer: doc.author = rawdoc.get('author', '') doc.footer = rawdoc.get('footer', '') + doc.full_label_map = {} + + # Preprocess custom tokens + def walk_elem(elem, parent=None): + elem.doc = doc + elem.parent = parent + + if isinstance(elem, legal_token.NumberedHeading) or isinstance(elem, legal_token.SubrulesItem): + full_label = elem.full_label() + if full_label: + doc.full_label_map[full_label] = elem + + if hasattr(elem, 'children'): + for child in elem.children: + walk_elem(child, elem) + + walk_elem(doc) + print(renderer.render(doc)) diff --git a/legalmd/latex_renderer.py b/legalmd/latex_renderer.py index d78f5ff..19345a4 100644 --- a/legalmd/latex_renderer.py +++ b/legalmd/latex_renderer.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import hashlib + import mistletoe import mistletoe.latex_renderer @@ -35,6 +37,8 @@ class LaTeXRenderer(mistletoe.latex_renderer.LaTeXRenderer): def __init__(self, *extras): super().__init__(*extras) + self.render_map['CrossReference'] = self.render_cross_reference + self.render_map['NumberedHeading'] = self.render_numbered_heading self.render_map['Subrules'] = self.render_subrules self.render_map['SubrulesItem'] = self.render_subrules_item @@ -48,6 +52,20 @@ class LaTeXRenderer(mistletoe.latex_renderer.LaTeXRenderer): result = result.replace('★★★', r'\texorpdfstring{\freeserif ★★★}{★★★}') return result + def render_cross_reference(self, token): + reference = token.get_reference() + if not reference: + raise Exception('Unable to resolve reference "{}"'.format(token.reference_num)) + + sha = hashlib.sha256() + sha.update(reference.full_label().encode('utf-8')) + + return format(r'\hyperlink{}{}', + linkname=sha.hexdigest(), + reference_type=(token.reference_type + '~') if token.reference_type else '', + reference_num=token.reference_num + ) + def render_heading(self, token): if token.level == 1: heading_last, self.heading_last = self.heading_last, True @@ -69,10 +87,17 @@ class LaTeXRenderer(mistletoe.latex_renderer.LaTeXRenderer): ) def render_numbered_heading(self, token): + sha = hashlib.sha256() + sha.update(token.full_label().encode('utf-8')) + hyperlink = format(r'\hypertarget{}{}', + linkname=sha.hexdigest() + ) + if token.level == 1: # Part heading_last, self.heading_last = self.heading_last, True - return format(r'{\par\vspace{1cm plus 0.3cm minus 0.3cm}\bfseries\fontsize{13pt}{15pt}\selectfont\centering\uppercase{Part