Design models in the model.py.
28 | Edit dev.cfg to use a different backend, or start with a pre-configured SQLite database.
29 | Use script tg-admin sql create to create the database tables.
Edit controllers.py and build your
39 | website structure with the simplicity of Python objects.
40 | TurboGears will automatically reload itself when you modify your project.
41 |
42 |
43 |
If you create something cool, please let people know, and consider contributing something back to the community.
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/demo/wsgi/pisawsgidemo.py:
--------------------------------------------------------------------------------
1 | #!/bin/python2.5
2 | # -*- coding: UTF-8 -*-
3 |
4 | # Copyright 2010 Dirk Holtwick, holtwick.it
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | # Copyright 2010 Dirk Holtwick, holtwick.it
18 | #
19 | # Licensed under the Apache License, Version 2.0 (the "License");
20 | # you may not use this file except in compliance with the License.
21 | # You may obtain a copy of the License at
22 | #
23 | # http://www.apache.org/licenses/LICENSE-2.0
24 | #
25 | # Unless required by applicable law or agreed to in writing, software
26 | # distributed under the License is distributed on an "AS IS" BASIS,
27 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28 | # See the License for the specific language governing permissions and
29 | # limitations under the License.
30 |
31 |
32 | __version__ = "$Revision: 103 $"
33 | __author__ = "$Author: holtwick $"
34 | __date__ = "$Date: 2007-10-31 17:08:54 +0100 (Mi, 31 Okt 2007) $"
35 | __svnid__ = "$Id: pisa.py 103 2007-10-31 16:08:54Z holtwick $"
36 |
37 | from wsgiref.simple_server import make_server
38 | import logging
39 |
40 | import sx.pisa3.pisa_wsgi as pisa_wsgi
41 |
42 | def SimpleApp(environ, start_response):
43 |
44 | # That's the magic!
45 | #
46 | # Set the environment variable "pisa.topdf" to the filename
47 | # you would like to have for the resulting PDF
48 | environ["pisa.topdf"] = "index.pdf"
49 |
50 | # Simple Hello World example
51 | start_response(
52 | '200 OK', [
53 | ('content-type', "text/html"),
54 | ])
55 | return ["Hello World"]
56 |
57 | if __name__ == '__main__':
58 |
59 | HOST = ''
60 | PORT = 8080
61 | logging.basicConfig(level=logging.DEBUG)
62 |
63 | app = SimpleApp
64 |
65 | # Add PISA WSGI Middleware
66 | app = pisa_wsgi.PisaMiddleware(app)
67 |
68 | httpd = make_server(HOST, PORT, app)
69 | print "Serving HTTP on port %d..." % PORT
70 | httpd.serve_forever()
71 |
--------------------------------------------------------------------------------
/doc/pisa-en.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/holtwick/xhtml2pdf/881850e49b67d8c9111ac53d09fb90138c1a3320/doc/pisa-en.pdf
--------------------------------------------------------------------------------
/doc/pisa.css:
--------------------------------------------------------------------------------
1 | @media print {
2 |
3 | @font-face {
4 | font-family: "DejaVu Sans Mono", dejamono;
5 | src: url(DejaVuSansMono.ttf);
6 | }
7 |
8 | @font-face {
9 | font-family: "DejaVu Sans Mono", dejamono;
10 | font-weight: bold;
11 | src: url(DejaVuSansMono-Bold.ttf);
12 | }
13 |
14 | @font-face {
15 | font-family: Calibri;
16 | src: url("CALIBRI.TTF");
17 | }
18 |
19 | @font-face {
20 | font-family: Calibri;
21 | src: url("CALIBRIB.TTF");
22 | font-weight: bold;
23 | }
24 |
25 | @font-face {
26 | font-family: Calibri;
27 | src: url("CALIBRII.TTF");
28 | font-style: italic;
29 | }
30 |
31 | @font-face {
32 | font-family: Calibri;
33 | src: url("CALIBRIZ.TTF");
34 | font-weight: bold;
35 | font-style: italic;
36 | }
37 |
38 | @page {
39 |
40 | -pdf-page-orientation: portrait;
41 | -pdf-page-size: a4;
42 |
43 | /* background-image: url(background.pdf); */
44 |
45 | margin-top: 2cm;
46 | margin-left: 4cm;
47 | margin-right: 2cm;
48 | margin-bottom: 3cm;
49 |
50 | }
51 |
52 | @page regular {
53 |
54 | -pdf-page-orientation: portrait;
55 | -pdf-page-size: a4;
56 |
57 | /* background-image: url(background.pdf); */
58 |
59 | margin-top: 2cm;
60 | margin-left: 4cm;
61 | margin-right: 2cm;
62 | margin-bottom: 3cm;
63 |
64 | @frame footer {
65 | -pdf-frame-content: footer;
66 | bottom: 2cm;
67 | left: 4cm;
68 | right: 2cm;
69 | height: 1cm;
70 | }
71 |
72 | }
73 |
74 | }
75 |
76 | html {
77 | font-family: Calibri, Arial, Helvetica, sans-serif;
78 | font-size: 10pt;
79 | }
80 |
81 | h1 {
82 | page-break-before: always;
83 | border-bottom: 2px solid #ccc;
84 | }
85 |
86 | pre, code {
87 | background: #eee;
88 | font-family: dejamono, "DejaVu Sans Mono", "Courier New", Courier, monospace;
89 | font-size: 8pt;
90 | }
91 |
92 | code {
93 | font-weight: bold;
94 | color: #333;
95 | /* text-decoration: underline; */
96 | font-size: 8pt;
97 | }
98 |
99 | .del {
100 | text-decoration: line-through;
101 | }
102 |
103 | p, pre {
104 | margin-top: 1em;
105 | margin-bottom: 1em;
106 | }
107 |
108 | .license {
109 | font-size: 8px;
110 | line-height: 110%;
111 | }
112 |
113 |
114 | .title {
115 | font-size: 300%;
116 | font-weight: bold;
117 | margin-top: 20pt;
118 | margin-bottom: 20pt;
119 | }
120 |
121 | .subtitle {
122 | font-size: 150%;
123 | font-weight: bold;
124 | margin-top: 20pt;
125 | margin-bottom: 20pt;
126 | }
127 |
128 | #footer {
129 | text-align: right;
130 | }
131 |
132 | i, em {
133 | font-style: normal;
134 | color: #990000;
135 | font-weight: bold;
136 | }
137 |
138 | a {
139 | color: #000066;
140 | }
141 |
142 | pdftoc {
143 | }
144 |
145 | pdftoc.pdftoclevel0 {
146 | font-weight: bold;
147 | margin-top: 0.5em;
148 | }
149 |
150 | pdftoc.pdftoclevel1 {
151 | margin-left: 1em;
152 | }
153 |
154 | pdftoc.pdftoclevel2 {
155 | margin-left: 1em;
156 | font-weight: normal;
157 | }
158 |
159 | h2 {
160 | margin-top: 1.5em;
161 | margin-bottom: 0.5em;
162 | font-size: 125%;
163 | color: #666;
164 | }
165 |
166 | h3 {
167 | font-size: 100%;
168 | color: #000000;
169 | margin-bottom: 0.5em;
170 | }
171 |
--------------------------------------------------------------------------------
/doc/screen.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 2em;
3 | counter-reset: Ebene01;
4 | }
5 | h1:before {
6 | content: counter(Ebene01) " ";
7 | counter-increment: Ebene01;
8 | }
9 | h1 {
10 | counter-reset: Ebene02;
11 | background: #CCCC99;
12 | }
13 | h2:before {
14 | content: counter(Ebene01) "." counter(Ebene02) " ";
15 | counter-increment: Ebene02;
16 | }
17 | h2 {
18 | border-bottom: 2px solid #CCCC99;
19 | }
20 | pre {
21 | padding: 0.5em;
22 | }
23 | a, code {
24 | background: #CCCC99;
25 | color: #333333;
26 | }
27 |
28 | code {
29 | font-weight: bold;
30 | }
31 |
32 | @media screen {
33 | .pdf {
34 | display: none;
35 | }
36 | }
--------------------------------------------------------------------------------
/ho/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: ISO-8859-1 -*-
2 |
3 | # Copyright 2010 Dirk Holtwick, holtwick.it
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | __version__ = "$Revision: 128 $"
18 | __author__ = "$Author: holtwick $"
19 | __date__ = "$Date: 2008-01-10 21:26:42 +0100 (Do, 10 Jan 2008) $"
20 | __svnid__ = "$Id: __init__.py 128 2008-01-10 20:26:42Z holtwick $"
21 |
22 | # Also look in other packages with the same name
23 |
24 | from pkgutil import extend_path
25 | __path__ = extend_path(__path__, __name__)
26 |
--------------------------------------------------------------------------------
/ho/pisa/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: ISO-8859-1 -*-
2 |
3 | # Copyright 2010 Dirk Holtwick, holtwick.it
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | """
18 | In the near future pisa will be moved into the namespace "ho"
19 | This is a helper for migration
20 | """
21 |
22 | __reversion__ = "$Revision: 160 $"
23 | __author__ = "$Author: holtwick $"
24 | __date__ = "$Date: 2008-03-12 16:40:03 +0100 (Mi, 12 Mrz 2008) $"
25 |
26 | from sx.pisa3.pisa import *
27 |
28 | __version__ = VERSION
29 |
--------------------------------------------------------------------------------
/pisa.py:
--------------------------------------------------------------------------------
1 | #!/usr/local/bin/python
2 | # -*- coding: ISO-8859-1 -*-
3 |
4 | # Copyright 2010 Dirk Holtwick, holtwick.it
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 |
18 | __version__ = "$Revision: 221 $"
19 | __author__ = "$Author: holtwick $"
20 | __date__ = "$Date: 2008-05-31 18:56:27 +0200 (Sa, 31 Mai 2008) $"
21 | __svnid__ = "$Id: pisa.py 221 2008-05-31 16:56:27Z holtwick $"
22 |
23 | import ho.pisa as pisa
24 | pisa.command()
25 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [install]
2 |
3 | compile = 1
4 | optimize = 1
5 |
6 | [sdist]
7 |
8 | formats = gztar, zip
9 |
10 | [bdist]
11 |
12 | formats = wininst
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: ISO-8859-1 -*-
3 |
4 | # Copyright 2010 Dirk Holtwick, holtwick.it
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 |
18 | __version__ = "$Revision: 247 $"
19 | __author__ = "$Author: holtwick $"
20 | __date__ = "$Date: 2008-08-15 13:37:57 +0200 (Fr, 15 Aug 2008) $"
21 | __svnid__ = "$Id: setup.py 247 2008-08-15 11:37:57Z holtwick $"
22 |
23 | try:
24 | from setuptools import setup, find_packages
25 | except ImportError:
26 | from ez_setup import use_setuptools
27 | use_setuptools()
28 | from setuptools import setup, find_packages
29 |
30 | setup(
31 | name = "pisa",
32 | version = "VERSION{3.0.33}VERSION"[8:-8],
33 | description = "PDF generator using HTML and CSS",
34 | license = "Apache License 2.0",
35 | author = "Dirk Holtwick",
36 | author_email = "dirk.holtwick@gmail.com",
37 | url = "http://www.xhtml2pdf.com",
38 | download_url = "http://pypi.python.org/pypi/pisa/",
39 | keywords = "PDF, HTML, XHTML, XML, CSS",
40 |
41 | requires = ["html5lib", "pypdf", "pil"], #, "reportlab"],
42 |
43 | include_package_data = False,
44 |
45 | packages = [
46 | 'ho',
47 | 'ho.pisa',
48 | 'sx',
49 | 'sx.pisa3',
50 | 'sx.w3c',
51 | ],
52 |
53 | test_suite = "tests",
54 |
55 | entry_points = {
56 | 'console_scripts': [
57 | 'pisa = sx.pisa3:command',
58 | 'xhtml2pdf = sx.pisa3:command',
59 | ]
60 | },
61 |
62 | long_description = """
63 | pisa is a html2pdf converter using the ReportLab Toolkit,
64 | the HTML5lib and pyPdf. It supports HTML 5 and CSS 2.1 (and some of CSS 3).
65 | It is completely written in pure Python so it is platform independent.
66 | The main benefit of this tool that a user with Web skills like HTML and CSS
67 | is able to generate PDF templates very quickly without learning new
68 | technologies. Easy integration into Python frameworks like CherryPy,
69 | KID Templating, TurboGears, Django, Zope, Plone, Google AppEngine (GAE) etc.
70 | (see 'demo' folder for examples)
71 | """.strip(),
72 |
73 | classifiers = [x.strip() for x in """
74 | License :: Freeware
75 | License :: OSI Approved
76 | License :: OSI Approved :: Apache Software License
77 | Development Status :: 5 - Production/Stable
78 | Development Status :: 6 - Mature
79 | Environment :: Console
80 | Environment :: MacOS X
81 | Environment :: Other Environment
82 | Environment :: Web Environment
83 | Environment :: Win32 (MS Windows)
84 | Framework :: Django
85 | Framework :: Plone
86 | Framework :: Pylons
87 | Framework :: TurboGears
88 | Framework :: Zope2
89 | Framework :: Zope3
90 | Intended Audience :: Customer Service
91 | Intended Audience :: Developers
92 | Intended Audience :: Education
93 | Intended Audience :: Financial and Insurance Industry
94 | Intended Audience :: Healthcare Industry
95 | Intended Audience :: Information Technology
96 | Intended Audience :: Legal Industry
97 | Intended Audience :: Manufacturing
98 | Intended Audience :: Science/Research
99 | Intended Audience :: System Administrators
100 | Intended Audience :: Telecommunications Industry
101 | Natural Language :: English
102 | Natural Language :: German
103 | Operating System :: MacOS
104 | Operating System :: MacOS :: MacOS X
105 | Operating System :: Microsoft
106 | Operating System :: Microsoft :: MS-DOS
107 | Operating System :: Microsoft :: Windows
108 | Operating System :: Other OS
109 | Operating System :: POSIX
110 | Operating System :: POSIX :: Linux
111 | Operating System :: Unix
112 | Topic :: Documentation
113 | Topic :: Internet
114 | Topic :: Multimedia
115 | Topic :: Office/Business
116 | Topic :: Office/Business :: Financial
117 | Topic :: Office/Business :: Financial :: Accounting
118 | Topic :: Printing
119 | Topic :: Text Processing
120 | Topic :: Text Processing :: Filters
121 | Topic :: Text Processing :: Fonts
122 | Topic :: Text Processing :: General
123 | Topic :: Text Processing :: Indexing
124 | Topic :: Text Processing :: Linguistic
125 | Topic :: Text Processing :: Markup
126 | Topic :: Text Processing :: Markup :: HTML
127 | Topic :: Text Processing :: Markup :: XML
128 | Topic :: Utilities
129 | """.strip().splitlines()],
130 |
131 | )
132 |
--------------------------------------------------------------------------------
/setup_exe.py:
--------------------------------------------------------------------------------
1 | # -*- coding: ISO-8859-1 -*-
2 |
3 | # Copyright 2010 Dirk Holtwick, holtwick.it
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | __version__ = "$Revision: 247 $"
18 | __author__ = "$Author: holtwick $"
19 | __date__ = "$Date: 2008-08-15 13:37:57 +0200 (Fr, 15 Aug 2008) $"
20 | __svnid__ = "$Id: setup_exe.py 247 2008-08-15 11:37:57Z holtwick $"
21 |
22 | """
23 | Optimiert für den Einsatz mit py2exe Version 0.5.4
24 | """
25 |
26 | import zipfile
27 | from distutils.core import setup
28 | import py2exe
29 |
30 | VERSION = "VERSION{3.0.33}VERSION"[8:-8]
31 |
32 | class Target:
33 | def __init__(self, **kw):
34 | self.__dict__.update(kw)
35 | self.version = VERSION
36 | self.company_name = "Dirk Holtwick"
37 | self.copyright = "(c) Dirk Holtwick, 2002-2010"
38 | self.name = "xhtml2pdf"
39 | self.description = "xhtml2pdf"
40 |
41 | setup(
42 |
43 | console = [{
44 | 'script': "pisa.py",
45 | }],
46 |
47 | options = {
48 | "py2exe": {
49 | # "optimize" : 2,
50 | "excludes" : ["Tkinter","Tix"],
51 | "includes": [
52 | "encodings",
53 | "encodings.*",
54 | 'ho',
55 | 'ho.pisa',
56 | "sx",
57 | "sx.pisa3",
58 | "sx.w3c",
59 | "html5lib",
60 | "html5lib.treebuilders.*",
61 | "html5lib.treewalkers.*",
62 | "reportlab",
63 | ],
64 | "dist_dir" : "exe",
65 | "bundle_files": 1,
66 | }
67 | },
68 |
69 | name = "pisa",
70 | version = "VERSION{3.0.33}VERSION"[8:-8],
71 | description = "PDF generator using HTML and CSS",
72 | license = "GNU General Public License (GPL)",
73 | author = "Dirk Holtwick",
74 | author_email = "dirk.holtwick@gmail.com",
75 | url = "http://www.xhtml2pdf.com",
76 | download_url = "http://pypi.python.org/pypi/pisa/",
77 | keywords = "HTML, CSS, PDF",
78 |
79 | requires = ["html5lib"], #, "reportlab"],
80 |
81 | packages = [
82 | 'ho',
83 | 'ho.pisa',
84 | 'sx',
85 | 'sx.pisa3',
86 | 'sx.w3c',
87 | ],
88 |
89 | long_description = """
90 | pisa is a html2pdf converter using the ReportLab Toolkit,
91 | the HTML5lib and pyPdf. It supports HTML 5 and CSS 2.1 (and some of CSS 3).
92 | It is completely written in pure Python so it is platform independent.
93 | The main benefit of this tool that a user with Web skills like HTML and CSS
94 | is able to generate PDF templates very quickly without learning new
95 | technologies. Easy integration into Python frameworks like CherryPy,
96 | KID Templating, TurboGears, Django, Zope, Plone, Google AppEngine (GAE) etc.
97 | (see 'demo' folder for examples)
98 | """.strip(),
99 |
100 | classifiers = [x.strip() for x in """
101 | Development Status :: 5 - Production/Stable
102 | Development Status :: 6 - Mature
103 | Environment :: Console
104 | Environment :: MacOS X
105 | Environment :: Other Environment
106 | Environment :: Web Environment
107 | Environment :: Win32 (MS Windows)
108 | Framework :: Django
109 | Framework :: Plone
110 | Framework :: Pylons
111 | Framework :: TurboGears
112 | Framework :: Zope2
113 | Framework :: Zope3
114 | Intended Audience :: Customer Service
115 | Intended Audience :: Developers
116 | Intended Audience :: Education
117 | Intended Audience :: Financial and Insurance Industry
118 | Intended Audience :: Healthcare Industry
119 | Intended Audience :: Information Technology
120 | Intended Audience :: Legal Industry
121 | Intended Audience :: Manufacturing
122 | Intended Audience :: Science/Research
123 | Intended Audience :: System Administrators
124 | Intended Audience :: Telecommunications Industry
125 | License :: Free for non-commercial use
126 | License :: OSI Approved :: GNU General Public License (GPL)
127 | Natural Language :: English
128 | Natural Language :: German
129 | Operating System :: MacOS
130 | Operating System :: MacOS :: MacOS X
131 | Operating System :: Microsoft
132 | Operating System :: Microsoft :: MS-DOS
133 | Operating System :: Microsoft :: Windows
134 | Operating System :: Other OS
135 | Operating System :: POSIX
136 | Operating System :: POSIX :: Linux
137 | Operating System :: Unix
138 | Topic :: Documentation
139 | Topic :: Internet
140 | Topic :: Multimedia
141 | Topic :: Office/Business
142 | Topic :: Office/Business :: Financial
143 | Topic :: Office/Business :: Financial :: Accounting
144 | Topic :: Printing
145 | Topic :: Text Processing
146 | Topic :: Text Processing :: Filters
147 | Topic :: Text Processing :: Fonts
148 | Topic :: Text Processing :: General
149 | Topic :: Text Processing :: Indexing
150 | Topic :: Text Processing :: Linguistic
151 | Topic :: Text Processing :: Markup
152 | Topic :: Text Processing :: Markup :: HTML
153 | Topic :: Text Processing :: Markup :: XML
154 | Topic :: Utilities
155 | """.strip().splitlines()],
156 |
157 | )
158 |
159 |
160 | import os, os.path, shutil
161 |
162 | SDIST = "pisa-" + VERSION + "\\"
163 | DIR = "pisa-" + VERSION + "-windows"
164 | # os.makedirs(DIR)
165 | os.rename("exe", DIR)
166 | shutil.copy(r"LICENSE.txt", DIR)
167 | shutil.copy(r"LICENSE.pdf", DIR)
168 | shutil.copy(r"README-WINDOWS.TXT", DIR + "\\README.txt")
169 | shutil.copytree(SDIST + "doc", DIR + "\\doc")
170 | shutil.copytree(SDIST + "test", DIR + "\\test")
171 | os.system(r"zip -r dist\xhtml2pdf-windows.zip pisa-" + VERSION + "-windows")
172 |
--------------------------------------------------------------------------------
/setup_version.py:
--------------------------------------------------------------------------------
1 | # -*- coding: ISO-8859-1 -*-
2 |
3 | # Copyright 2010 Dirk Holtwick, holtwick.it
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | """
18 | Updates the version infos
19 | """
20 |
21 | import time
22 | import re
23 | import cgi
24 |
25 | VERSION = open("VERSION.txt", "r").read().strip()
26 | BUILD = time.strftime("%Y-%m-%d")
27 | FILES = [
28 | "setup.py",
29 | "setup_exe.py",
30 | # "setup_egg.py",
31 | "sx/pisa3/pisa_version.py",
32 | "doc/pisa-en.html",
33 | ]
34 | try:
35 | HELP = cgi.escape(open("HELP.txt", "r").read(), 1)
36 | except:
37 | HELP = ""
38 | HELP = "
" + HELP + "
"
39 |
40 | rxversion = re.compile("VERSION{.*?}VERSION", re.MULTILINE|re.IGNORECASE|re.DOTALL)
41 | rxbuild = re.compile("BUILD{.*?}BUILD", re.MULTILINE|re.IGNORECASE|re.DOTALL)
42 | rxversionhtml = re.compile("\<\!--VERSION--\>.*?\<\!--VERSION--\>", re.MULTILINE|re.IGNORECASE|re.DOTALL)
43 | rxhelphtml = re.compile("\<\!--HELP--\>.*?\<\!--HELP--\>", re.MULTILINE|re.IGNORECASE|re.DOTALL)
44 |
45 | for fname in FILES:
46 | print "Update", fname, "..."
47 | data = open(fname, "rb").read()
48 | data = rxversion.sub("VERSION{" + VERSION + "}VERSION", data)
49 | data = rxversionhtml.sub("" + VERSION + "", data)
50 | data = rxbuild.sub("BUILD{" + BUILD + "}BUILD", data)
51 | data = rxhelphtml.sub(HELP, data)
52 | open(fname, "wb").write(data)
53 |
54 |
--------------------------------------------------------------------------------
/sx/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: ISO-8859-1 -*-
2 |
3 | # Copyright 2010 Dirk Holtwick, holtwick.it
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | __version__ = "$Revision: 128 $"
18 | __author__ = "$Author: holtwick $"
19 | __date__ = "$Date: 2008-01-10 21:26:42 +0100 (Do, 10 Jan 2008) $"
20 | __svnid__ = "$Id: __init__.py 128 2008-01-10 20:26:42Z holtwick $"
21 |
22 | # Also look in other packages with the same name
23 |
24 | from pkgutil import extend_path
25 | __path__ = extend_path(__path__, __name__)
26 |
--------------------------------------------------------------------------------
/sx/pisa3/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: ISO-8859-1 -*-
2 |
3 | # Copyright 2010 Dirk Holtwick, holtwick.it
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | __reversion__ = "$Revision: 238 $"
18 | __author__ = "$Author: holtwick $"
19 | __date__ = "$Date: 2008-06-26 20:06:02 +0200 (Do, 26 Jun 2008) $"
20 |
21 | REQUIRED_INFO = """
22 | ****************************************************
23 | IMPORT ERROR!
24 | %s
25 | ****************************************************
26 |
27 | The following Python packages are required for PISA:
28 | - Reportlab Toolkit >= 2.2
29 | - HTML5lib >= 0.11.1
30 |
31 | Optional packages:
32 | - pyPDF
33 | - PIL
34 |
35 | """.lstrip()
36 |
37 | import logging
38 | log = logging.getLogger(__name__)
39 |
40 | try:
41 | from pisa import *
42 | if not REPORTLAB22:
43 | raise ImportError, "Reportlab Toolkit Version 2.2 or higher needed"
44 | except ImportError, e:
45 | import sys
46 | sys.stderr.write(REQUIRED_INFO % e)
47 | log.error(REQUIRED_INFO % e)
48 | raise
49 |
50 | __version__ = VERSION
51 |
--------------------------------------------------------------------------------
/sx/pisa3/pisa.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/holtwick/xhtml2pdf/881850e49b67d8c9111ac53d09fb90138c1a3320/sx/pisa3/pisa.py
--------------------------------------------------------------------------------
/sx/pisa3/pisa_document.py:
--------------------------------------------------------------------------------
1 | # -*- coding: ISO-8859-1 -*-
2 |
3 | # Copyright 2010 Dirk Holtwick, holtwick.it
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 |
18 | __reversion__ = "$Revision: 20 $"
19 | __author__ = "$Author: holtwick $"
20 | __date__ = "$Date: 2007-10-09 12:58:24 +0200 (Di, 09 Okt 2007) $"
21 |
22 | from pisa_context import pisaContext
23 | from pisa_parser import pisaParser
24 | from pisa_util import *
25 | from pisa_reportlab import *
26 | from pisa_default import DEFAULT_CSS
27 |
28 | from reportlab.platypus.flowables import Spacer
29 |
30 | #import os
31 | #import types
32 | #import cgi
33 | #import logging
34 |
35 | log = logging.getLogger("ho.pisa")
36 |
37 | def pisaErrorDocument(dest, c):
38 | out = pisaTempFile(capacity=c.capacity)
39 | out.write("
%d error(s) occured:
" % c.err)
40 | for mode, line, msg, code in c.log:
41 | if mode=="error":
42 | out.write("
" % c.warn)
45 | for mode, line, msg, code in c.log:
46 | if mode=="warning":
47 | out.write("
%s in line %d: %s
" % (mode, line, cgi.escape(msg)))
48 |
49 | return pisaDocument(out.getvalue(), dest, raise_exception=False)
50 |
51 | def pisaStory(
52 | src,
53 | path = None,
54 | link_callback = None,
55 | debug = 0,
56 | default_css = None,
57 | xhtml = False,
58 | encoding = None,
59 | c = None,
60 | xml_output = None,
61 | **kw):
62 |
63 | # Prepare Context
64 | if not c:
65 | c = pisaContext(path, debug=debug)
66 | c.pathCallback = link_callback
67 |
68 | # Use a default set of CSS definitions to get an expected output
69 | if default_css is None:
70 | default_css = DEFAULT_CSS
71 |
72 | # Parse and fill the story
73 | pisaParser(src, c, default_css, xhtml, encoding, xml_output)
74 |
75 | #if 0:
76 | # import reportlab.pdfbase.pdfmetrics as pm
77 | # pm.dumpFontData()
78 |
79 | # Avoid empty documents
80 | if not c.story:
81 | c.story = [Spacer(1,1)]
82 | # c.addPara(force=True)
83 |
84 | # Remove anchors if they do not exist (because of a bug in Reportlab)
85 | for frag, anchor in c.anchorFrag:
86 | if anchor not in c.anchorName:
87 | frag.link = None
88 |
89 | return c
90 |
91 | def pisaDocument(
92 | src,
93 | dest = None,
94 | path = None,
95 | link_callback = None,
96 | debug = 0,
97 | show_error_as_pdf = False,
98 | default_css = None,
99 | xhtml = False,
100 | encoding = None,
101 | xml_output = None,
102 | raise_exception = True,
103 | capacity = 100 * 1024, # -1,
104 | **kw):
105 |
106 | c = None
107 | if show_error_as_pdf:
108 | raise_exception = False
109 |
110 | try:
111 |
112 | log.debug("pisaDocument options:\n src = %r\n dest = %r\n path = %r\n link_callback = %r\n xhtml = %r",
113 | src,
114 | dest,
115 | path,
116 | link_callback,
117 | xhtml)
118 |
119 | # Prepare simple context
120 | c = pisaContext(path, debug=debug, capacity=capacity)
121 | c.pathCallback = link_callback
122 |
123 | if dest is None:
124 | dest = pisaTempFile(capacity=c.capacity)
125 | c.dest = dest
126 |
127 | # Build story
128 | c = pisaStory(src, path, link_callback, debug, default_css, xhtml, encoding, c=c, xml_output=xml_output)
129 |
130 | # Buffer PDF into memory
131 | out = pisaTempFile(capacity=c.capacity)
132 |
133 | doc = PmlBaseDoc(
134 | out,
135 | pagesize = c.pageSize,
136 | author = c.meta["author"].strip(),
137 | subject = c.meta["subject"].strip(),
138 | keywords = [x.strip() for x in c.meta["keywords"].strip().split(",") if x],
139 | title = c.meta["title"].strip(),
140 | showBoundary = 0,
141 | allowSplitting = 1)
142 |
143 | # XXX It is not possible to access PDF info, because it is private in canvas
144 | # doc.info.producer = "pisa "
145 |
146 | # Prepare templates and their frames
147 | if c.templateList.has_key("body"):
148 | body = c.templateList["body"]
149 | del c.templateList["body"]
150 | else:
151 | x, y, w, h = getBox("1cm 1cm -1cm -1cm", c.pageSize)
152 | body = PmlPageTemplate(
153 | id="body",
154 | frames=[
155 | Frame(x, y, w, h,
156 | id = "body",
157 | leftPadding = 0,
158 | rightPadding = 0,
159 | bottomPadding = 0,
160 | topPadding = 0)],
161 | pagesize = c.pageSize)
162 |
163 | # print body.frames
164 |
165 | # print [body] + c.templateList.values()
166 | doc.addPageTemplates([body] + c.templateList.values())
167 |
168 | # Use multibuild e.g. if a TOC has to be created
169 | if c.multiBuild:
170 | doc.multiBuild(c.story)
171 | else:
172 | doc.build(c.story)
173 |
174 | # Add watermarks
175 | if pyPdf:
176 | for bgouter in c.pisaBackgroundList:
177 |
178 | # If we have at least one background, then lets do it
179 | if bgouter:
180 |
181 | istream = out
182 | try:
183 | output = pyPdf.PdfFileWriter()
184 | input1 = pyPdf.PdfFileReader(istream)
185 | ctr = 0
186 | for bg in c.pisaBackgroundList:
187 | page = input1.getPage(ctr)
188 | if bg and not bg.notFound() and (bg.mimetype=="application/pdf"):
189 | bginput = pyPdf.PdfFileReader(bg.getFile())
190 | pagebg = bginput.getPage(0)
191 | pagebg.mergePage(page)
192 | page = pagebg
193 | else:
194 | log.warn(c.warning("Background PDF %s doesn't exist.", bg))
195 | output.addPage(page)
196 | ctr += 1
197 | out = pisaTempFile(capacity=c.capacity)
198 | output.write(out)
199 | # data = sout.getvalue()
200 | except Exception:
201 | log.exception(c.error("pyPDF error"))
202 | if raise_exception:
203 | raise
204 |
205 |
206 | # Found a background? So leave loop after first occurence
207 | break
208 | else:
209 | log.warn(c.warning("pyPDF not installed!"))
210 |
211 | # In web frameworks for debugging purposes maybe an output of
212 | # errors in a PDF is preferred
213 | if show_error_as_pdf and c and c.err:
214 | return pisaErrorDocument(c.dest, c)
215 |
216 | # Get the resulting PDF and write it to the file object
217 | # passed from the caller
218 | data = out.getvalue()
219 | c.dest.write(data)
220 |
221 | except:
222 | # log.exception(c.error("Document error"))
223 | log.exception("Document error")
224 | c.err += 1
225 | if raise_exception:
226 | raise
227 |
228 | if raise_exception and c.err:
229 | raise Exception("Errors occured, please see log files for more informations")
230 |
231 | return c
232 |
--------------------------------------------------------------------------------
/sx/pisa3/pisa_pdf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: ISO-8859-1 -*-
2 |
3 | # Copyright 2010 Dirk Holtwick, holtwick.it
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 |
18 | __reversion__ = "$Revision: 20 $"
19 | __author__ = "$Author: holtwick $"
20 | __date__ = "$Date: 2007-10-09 12:58:24 +0200 (Di, 09 Okt 2007) $"
21 |
22 | from pisa_util import pisaTempFile, getFile
23 |
24 | import logging
25 | log = logging.getLogger("ho.pisa")
26 |
27 | class pisaPDF:
28 |
29 | def __init__(self, capacity=-1):
30 | self.capacity = capacity
31 | self.files = []
32 |
33 | def addFromURI(self, url, basepath=None):
34 | obj = getFile(url, basepath)
35 | if obj and (not obj.notFound()):
36 | self.files.append(obj.getFile())
37 |
38 | addFromFileName = addFromURI
39 |
40 | def addFromFile(self, f):
41 | if hasattr(f, "read"):
42 | self.files.append(f)
43 | self.addFromURI(f)
44 |
45 | def addFromString(self, data):
46 | self.files.append(pisaTempFile(data, capacity=self.capacity))
47 |
48 | def addDocument(self, doc):
49 | if hasattr(doc.dest, "read"):
50 | self.files.append(doc.dest)
51 |
52 | def join(self, file=None):
53 | import pyPdf
54 | if pyPdf:
55 | output = pyPdf.PdfFileWriter()
56 | for pdffile in self.files:
57 | input = pyPdf.PdfFileReader(pdffile)
58 | for pageNumber in range(0, input.getNumPages()):
59 | output.addPage(input.getPage(pageNumber))
60 | if file is not None:
61 | output.write(file)
62 | return file
63 | out = pisaTempFile(capacity=self.capacity)
64 | output.write(out)
65 | return out.getvalue()
66 |
67 | getvalue = join
68 | __str__ = join
69 |
--------------------------------------------------------------------------------
/sx/pisa3/pisa_turbogears.py:
--------------------------------------------------------------------------------
1 | # -*- coding: ISO-8859-1 -*-
2 |
3 | # Copyright 2010 Dirk Holtwick, holtwick.it
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | __reversion__ = "$Revision: 20 $"
18 | __author__ = "$Author: holtwick $"
19 | __date__ = "$Date: 2007-10-09 12:58:24 +0200 (Di, 09 Okt 2007) $"
20 |
21 | from turbogears.decorator import weak_signature_decorator
22 | import sx.pisa3 as pisa
23 | import StringIO
24 | import cherrypy
25 |
26 | def to_pdf(filename=None, content_type="application/pdf"):
27 | def entangle(func):
28 | def decorated(func, *args, **kw):
29 | output = func(*args, **kw)
30 | dst = StringIO.StringIO()
31 | result = pisa.CreatePDF(
32 | StringIO.StringIO(output),
33 | dst
34 | )
35 | if not result.err:
36 | cherrypy.response.headers["Content-Type"] = content_type
37 | if filename:
38 | cherrypy.response.headers["Content-Disposition"] = "attachment; filename=" + filename
39 | output = dst.getvalue()
40 | return output
41 | return decorated
42 | return weak_signature_decorator(entangle)
43 |
44 | topdf = to_pdf
45 |
--------------------------------------------------------------------------------
/sx/pisa3/pisa_version.py:
--------------------------------------------------------------------------------
1 | # -*- coding: ISO-8859-1 -*-
2 |
3 | # Copyright 2010 Dirk Holtwick, holtwick.it
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | __reversion__ = "$Revision: 247 $"
18 | __author__ = "$Author: holtwick $"
19 | __date__ = "$Date: 2008-08-15 13:37:57 +0200 (Fr, 15 Aug 2008) $"
20 | __version__ = VERSION = "VERSION{3.0.33}VERSION"[8:-8]
21 | __build__ = BUILD = "BUILD{2010-06-16}BUILD"[6:-6]
22 |
23 | VERSION_STR = """XHTML2PDF/pisa %s (Build %s)
24 | http://www.xhtml2pdf.com
25 |
26 | Copyright 2010 Dirk Holtwick, holtwick.it
27 |
28 | Licensed under the Apache License, Version 2.0 (the "License");
29 | you may not use this file except in compliance with the License.
30 | You may obtain a copy of the License at
31 |
32 | http://www.apache.org/licenses/LICENSE-2.0
33 |
34 | Unless required by applicable law or agreed to in writing, software
35 | distributed under the License is distributed on an "AS IS" BASIS,
36 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
37 | See the License for the specific language governing permissions and
38 | limitations under the License.""" % (
39 | VERSION,
40 | BUILD,
41 | )
42 |
--------------------------------------------------------------------------------
/sx/pisa3/pisa_wsgi.py:
--------------------------------------------------------------------------------
1 | # -*- coding: UTF-8 -*-
2 |
3 | # Copyright 2010 Dirk Holtwick, holtwick.it
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | __version__ = "$Revision: 103 $"
18 | __author__ = "$Author: holtwick $"
19 | __date__ = "$Date: 2007-10-31 17:08:54 +0100 (Mi, 31 Okt 2007) $"
20 | __svnid__ = "$Id: pisa.py 103 2007-10-31 16:08:54Z holtwick $"
21 |
22 | import ho.pisa as pisa
23 | import StringIO
24 |
25 | import logging
26 | log = logging.getLogger("ho.pisa.wsgi")
27 |
28 | class Filter(object):
29 |
30 | def __init__(self, app):
31 | self.app = app
32 |
33 | def __call__(self, environ, start_response):
34 | script_name = environ.get('SCRIPT_NAME', '')
35 | path_info = environ.get('PATH_INFO', '')
36 | sent = []
37 | written_response = StringIO.StringIO()
38 | def replacement_start_response(status, headers, exc_info=None):
39 | if not self.should_filter(status, headers):
40 | return start_response(status, headers, exc_info)
41 | else:
42 | sent[:] = [status, headers, exc_info]
43 | return written_response.write
44 | app_iter = self.app(environ, replacement_start_response)
45 | if not sent:
46 | return app_iter
47 | status, headers, exc_info = sent
48 | try:
49 | for chunk in app_iter:
50 | written_response.write(chunk)
51 | finally:
52 | if hasattr(app_iter, 'close'):
53 | app_iter.close()
54 | body = written_response.getvalue()
55 | status, headers, body = self.filter(
56 | script_name, path_info, environ, status, headers, body)
57 | start_response(status, headers, exc_info)
58 | return [body]
59 |
60 | def should_filter(self, status, headers):
61 | print headers
62 |
63 | def filter(self, status, headers, body):
64 | raise NotImplementedError
65 |
66 |
67 | class HTMLFilter(Filter):
68 |
69 | def should_filter(self, status, headers):
70 | if not status.startswith('200'):
71 | return False
72 | for name, value in headers:
73 | if name.lower() == 'content-type':
74 | return value.startswith('text/html')
75 | return False
76 |
77 | class PisaMiddleware(HTMLFilter):
78 |
79 | def filter(self,
80 | script_name,
81 | path_info,
82 | environ,
83 | status,
84 | headers,
85 | body):
86 | topdf = environ.get("pisa.topdf", "")
87 | if topdf:
88 | dst = StringIO.StringIO()
89 | result = pisa.CreatePDF(
90 | body,
91 | dst,
92 | show_error_as_pdf=True,
93 | )
94 | headers = [
95 | ("content-type", "application/pdf"),
96 | ("content-disposition", "attachment; filename=" + topdf)
97 | ]
98 | body = dst.getvalue()
99 | return status, headers, body
100 |
--------------------------------------------------------------------------------
/sx/w3c/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 | ##~ Copyright (C) 2002-2004 TechGame Networks, LLC.
4 | ##~
5 | ##~ This library is free software; you can redistribute it and/or
6 | ##~ modify it under the terms of the BSD style License as found in the
7 | ##~ LICENSE file included with this distribution.
8 | ##
9 | ## Modified by Dirk Holtwick , 2007
10 | ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 |
12 |
13 |
--------------------------------------------------------------------------------
/sx/w3c/cssDOMElementInterface.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 | ##~ Copyright (C) 2002-2004 TechGame Networks, LLC.
4 | ##~
5 | ##~ This library is free software; you can redistribute it and/or
6 | ##~ modify it under the terms of the BSD style License as found in the
7 | ##~ LICENSE file included with this distribution.
8 | ##
9 | ## Modified by Dirk Holtwick , 2007-2008
10 | ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 |
12 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13 | #~ Imports
14 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
15 |
16 | import css
17 |
18 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 | #~ Definitions
20 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21 |
22 | class CSSDOMElementInterface(css.CSSElementInterfaceAbstract):
23 | """An implementation of css.CSSElementInterfaceAbstract for xml.dom Element Nodes"""
24 |
25 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26 | #~ Constants / Variables / Etc.
27 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28 |
29 | style = None
30 |
31 | _pseudoStateHandlerLookup = {
32 | 'first-child':
33 | lambda self: not bool(self.getPreviousSibling()),
34 | 'not-first-child':
35 | lambda self: bool(self.getPreviousSibling()),
36 |
37 | 'last-child':
38 | lambda self: not bool(self.getNextSibling()),
39 | 'not-last-child':
40 | lambda self: bool(self.getNextSibling()),
41 |
42 | 'middle-child':
43 | lambda self: not bool(self.getPreviousSibling()) and not bool(self.getNextSibling()),
44 | 'not-middle-child':
45 | lambda self: bool(self.getPreviousSibling()) or bool(self.getNextSibling()),
46 |
47 | # XXX 'first-line':
48 |
49 | }
50 |
51 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
52 | #~ Definitions
53 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
54 |
55 | def __init__(self, domElement, cssParser=None):
56 | self.domElement = domElement
57 | # print self.domElement.attributes
58 | if cssParser is not None:
59 | self.onCSSParserVisit(cssParser)
60 |
61 | def onCSSParserVisit(self, cssParser):
62 | styleSrc = self.getStyleAttr()
63 | if styleSrc:
64 | style = cssParser.parseInline(styleSrc)
65 | self.setInlineStyle(style)
66 |
67 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
68 |
69 | def matchesNode(self, (namespace, tagName)):
70 | if tagName not in ('*', self.domElement.tagName):
71 | return False
72 | if namespace in (None, '', '*'):
73 | # matches any namespace
74 | return True
75 | else: # full compare
76 | return namespace == self.domElement.namespaceURI
77 |
78 | def getAttr(self, name, default=NotImplemented):
79 | attrValue = self.domElement.attributes.get(name)
80 | if attrValue is not None:
81 | return attrValue.value
82 | else:
83 | return default
84 |
85 | def getIdAttr(self):
86 | return self.getAttr('id', '')
87 | def getClassAttr(self):
88 | return self.getAttr('class', '')
89 | def getStyleAttr(self):
90 | return self.getAttr('style', None)
91 |
92 | def inPseudoState(self, name, params=()):
93 | handler = self._pseudoStateHandlerLookup.get(name, lambda self: False)
94 | return handler(self)
95 |
96 | def iterXMLParents(self, includeSelf=False):
97 | klass = self.__class__
98 | current = self.domElement
99 | if not includeSelf:
100 | current = current.parentNode
101 | while (current is not None) and (current.nodeType == current.ELEMENT_NODE):
102 | yield klass(current)
103 | current = current.parentNode
104 |
105 | def getPreviousSibling(self):
106 | sibling = self.domElement.previousSibling
107 | while sibling:
108 | if sibling.nodeType == sibling.ELEMENT_NODE:
109 | return sibling
110 | else:
111 | sibling = sibling.previousSibling
112 | return None
113 | def getNextSibling(self):
114 | sibling = self.domElement.nextSibling
115 | while sibling:
116 | if sibling.nodeType == sibling.ELEMENT_NODE:
117 | return sibling
118 | else:
119 | sibling = sibling.nextSibling
120 | return None
121 |
122 | def getInlineStyle(self):
123 | return self.style
124 | def setInlineStyle(self, style):
125 | self.style = style
126 |
127 |
--------------------------------------------------------------------------------
/test/cookbook.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | HTML to PDF conversion example
4 |
9 |
10 |
11 |
Hello Wörld
12 |
13 |
14 |
15 |
Amount
16 |
Description
17 |
Total
18 |
19 |
20 |
1
21 |
Good weather
22 |
0 EUR
23 |
24 |
25 |
Sum
26 |
0 EUR
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/test/cookbook.py:
--------------------------------------------------------------------------------
1 | # -*- coding: ISO-8859-1 -*-
2 |
3 | # Copyright 2010 Dirk Holtwick, holtwick.it
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | __version__ = "$Revision: 176 $"
18 | __author__ = "$Author: holtwick $"
19 | __date__ = "$Date: 2008-03-15 00:11:47 +0100 (Sa, 15 Mrz 2008) $"
20 |
21 | """
22 | HTML/CSS to PDF converter
23 |
24 | Most people know how to write a page with HTML and CSS. Why not using these skills to dynamically generate PDF documents using it? The "pisa" project http://www.htmltopdf.org enables you to to this quite simple.
25 | """
26 |
27 | import cStringIO
28 | import ho.pisa as pisa
29 | import os
30 |
31 | # Shortcut for dumping all logs to the screen
32 | pisa.showLogging()
33 |
34 | def HTML2PDF(data, filename, open=False):
35 |
36 | """
37 | Simple test showing how to create a PDF file from
38 | PML Source String. Also shows errors and tries to start
39 | the resulting PDF
40 | """
41 |
42 | pdf = pisa.CreatePDF(
43 | cStringIO.StringIO(data),
44 | file(filename, "wb"))
45 |
46 | if open and (not pdf.err):
47 | pisa.startViewer(filename)
48 |
49 | return not pdf.err
50 |
51 | if __name__=="__main__":
52 | HTMLTEST = """
53 |
54 |
Das ist ein einfaches Beispiel. Etwas Text zum üben
41 | und fertig. Das ist ein einfaches Beispiel. Etwas Text zum üben und fertig.
42 | Das ist ein einfaches Beispiel. Etwas Text zum üben und fertig.
43 | Das ist ein einfaches Beispiel. Etwas Text zum üben und fertig.
44 |
Das ist ein einfaches Beispiel. Etwas Text zum üben und fertig.Das ist
45 | ein
46 | einfaches Beispiel. Etwas Text zum üben und fertig. Das ist ein einfaches
47 | Beispiel. Etwas Text zum üben und fertig. Das ist ein einfaches Beispiel.
48 | Etwas Text zum üben und fertig.
49 |
Das ist ein einfaches Beispiel. Etwas Text zum üben und fertig.Das ist
50 | ein
51 | einfaches Beispiel. Etwas Text zum üben und fertig. Das ist ein einfaches
52 | Beispiel. Etwas Text zum üben und fertig. Das ist ein einfaches Beispiel.
53 | Etwas Text zum üben und fertig. g. Das ist ein einfaches Beispiel.
54 | Etwas Text zum üben und fertig. g. Das ist ein einfaches Beispiel.
55 | Etwas Text zum üben und fertig. g. Das ist ein einfaches Beispiel.
56 | Etwas Text zum üben und fertig. g. Das ist ein einfaches Beispiel.
57 | Etwas Text zum üben und fertig.
58 |
Das ist ein einfaches Beispiel. Etwas Text zum üben und fertig.Das ist
59 | ein
60 | einfaches Beispiel. Etwas Text zum üben und fertig. Das ist ein einfaches
61 | Beispiel. Etwas Text zum üben und fertig. Das ist ein einfaches Beispiel.
62 | Etwas Text zum üben und fertig.
63 |
Das ist ein einfaches Beispiel.
64 | Etwas Text zum üben und fertig.Das ist
65 | ein
66 | einfaches Beispiel. Etwas Text zum üben und fertig. Das ist ein einfaches
67 | Beispiel. Etwas Text zum üben und fertig. Das ist ein einfaches Beispiel.
68 | Etwas Text zum üben und fertig.
69 |
Das ist ein einfaches Beispiel. Etwas Text zum üben und fertig.Das ist
70 | ein
71 | einfaches Beispiel. Etwas Text zum üben und fertig. Das ist ein einfaches
72 | Beispiel. Etwas Text zum üben und fertig. Das ist ein einfaches Beispiel.
73 | Etwas Text zum üben und fertig.
74 |
Das ist ein einfaches Beispiel. Etwas Text zum üben und fertig.Das ist
75 | ein
76 | einfaches Beispiel. Etwas Text zum üben und fertig. Das ist ein einfaches
77 | Beispiel. Etwas Text zum üben und fertig. Das ist ein einfaches Beispiel.
78 | Etwas Text zum üben und fertig.
79 |
80 |
81 |
--------------------------------------------------------------------------------
/test/simple.py:
--------------------------------------------------------------------------------
1 | # -*- coding: ISO-8859-1 -*-
2 |
3 | # Copyright 2010 Dirk Holtwick, holtwick.it
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | __version__ = "$Revision: 194 $"
18 | __author__ = "$Author: holtwick $"
19 | __date__ = "$Date: 2008-04-18 18:59:53 +0200 (Fr, 18 Apr 2008) $"
20 |
21 | import os
22 | import sys
23 | import cgi
24 | import cStringIO
25 | import logging
26 |
27 | import ho.pisa as pisa
28 |
29 | # Shortcut for dumping all logs to the screen
30 | pisa.showLogging()
31 |
32 | def dumpErrors(pdf, showLog=True):
33 | #if showLog and pdf.log:
34 | # for mode, line, msg, code in pdf.log:
35 | # print "%s in line %d: %s" % (mode, line, msg)
36 | #if pdf.warn:
37 | # print "*** %d WARNINGS OCCURED" % pdf.warn
38 | if pdf.err:
39 | print "*** %d ERRORS OCCURED" % pdf.err
40 |
41 | def testSimple(
42 | data="""Hello World """,
43 | dest="test.pdf"):
44 |
45 | """
46 | Simple test showing how to create a PDF file from
47 | PML Source String. Also shows errors and tries to start
48 | the resulting PDF
49 | """
50 |
51 | pdf = pisa.CreatePDF(
52 | cStringIO.StringIO(data),
53 | file(dest, "wb")
54 | )
55 |
56 | if pdf.err:
57 | dumpErrors(pdf)
58 | else:
59 | pisa.startViewer(dest)
60 |
61 | def testCGI(data="Hello World"):
62 |
63 | """
64 | This one shows, how to get the resulting PDF as a
65 | file object and then send it to STDOUT
66 | """
67 |
68 | result = cStringIO.StringIO()
69 |
70 | pdf = pisa.CreatePDF(
71 | cStringIO.StringIO(data),
72 | result
73 | )
74 |
75 | if pdf.err:
76 | print "Content-Type: text/plain"
77 | print
78 | dumpErrors(pdf)
79 | else:
80 | print "Content-Type: application/octet-stream"
81 | print
82 | sys.stdout.write(result.getvalue())
83 |
84 | def testBackgroundAndImage(
85 | src="test-background.html",
86 | dest="test-background.pdf"):
87 |
88 | """
89 | Simple test showing how to create a PDF file from
90 | PML Source String. Also shows errors and tries to start
91 | the resulting PDF
92 | """
93 |
94 | pdf = pisa.CreatePDF(
95 | file(src, "r"),
96 | file(dest, "wb"),
97 | log_warn = 1,
98 | log_err = 1,
99 | path = os.path.join(os.getcwd(), src)
100 | )
101 |
102 | dumpErrors(pdf)
103 | if not pdf.err:
104 | pisa.startViewer(dest)
105 |
106 | def testURL(
107 | url="http://www.htmltopdf.org",
108 | dest="test-website.pdf"):
109 |
110 | """
111 | Loading from an URL. We open a file like object for the URL by
112 | using 'urllib'. If there have to be loaded more data from the web,
113 | the pisaLinkLoader helper is passed as 'link_callback'. The
114 | pisaLinkLoader creates temporary files for everything it loads, because
115 | the Reportlab Toolkit needs real filenames for images and stuff. Then
116 | we also pass the url as 'path' for relative path calculations.
117 | """
118 | import urllib
119 |
120 | pdf = pisa.CreatePDF(
121 | urllib.urlopen(url),
122 | file(dest, "wb"),
123 | log_warn = 1,
124 | log_err = 1,
125 | path = url,
126 | link_callback = pisa.pisaLinkLoader(url).getFileName
127 | )
128 |
129 | dumpErrors(pdf)
130 | if not pdf.err:
131 | pisa.startViewer(dest)
132 |
133 | if __name__=="__main__":
134 |
135 | testSimple()
136 | # testCGI()
137 | #testBackgroundAndImage()
138 | #testURL()
139 |
--------------------------------------------------------------------------------
/test/story2canvas.py:
--------------------------------------------------------------------------------
1 | # -*- coding: ISO-8859-1 -*-
2 |
3 | # Copyright 2010 Dirk Holtwick, holtwick.it
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | __version__ = "$Revision: 194 $"
18 | __author__ = "$Author: holtwick $"
19 | __date__ = "$Date: 2008-04-18 18:59:53 +0200 (Fr, 18 Apr 2008) $"
20 |
21 | from reportlab.pdfgen.canvas import Canvas
22 | from reportlab.lib.units import inch
23 | from reportlab.platypus import Frame
24 |
25 | import ho.pisa as pisa
26 |
27 | def test(filename):
28 |
29 | # Convert HTML to "Reportlab Story" structure
30 | story = pisa.pisaStory("""
31 |
LEFT Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec euismod ante sed mi. Mauris tortor purus, fermentum sit amet, interdum et, rutrum nec, risus. Suspendisse erat nisi, vestibulum a, mattis at, dignissim quis, ante. Ut in dui. Etiam sed elit nec tellus vulputate tincidunt. Nunc tortor risus, dignissim in, tempor a, sodales vel, erat. Aenean metus ipsum, vulputate vel, eleifend sed, tristique sed, nibh. Aliquam erat volutpat. Sed lobortis fringilla mauris. Nullam convallis ullamcorper urna. Integer id justo sed pede suscipit convallis. Cras non purus sed nisi faucibus scelerisque. Donec ullamcorper massa id risus. Vivamus tristique hendrerit neque. Maecenas pulvinar ipsum dictum ante. Cras eleifend lacus. Suspendisse et massa. Vestibulum sit amet lacus. In sed libero. Duis quis enim sit amet lorem ultrices rhoncus.
18 |
JUSTIFY Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec euismod ante sed mi. Mauris tortor purus, fermentum sit amet, interdum et, rutrum nec, risus. Suspendisse erat nisi, vestibulum a, mattis at, dignissim quis, ante. Ut in dui. Etiam sed elit nec tellus vulputate tincidunt. Nunc tortor risus, dignissim in, tempor a, sodales vel, erat. Aenean metus ipsum, vulputate vel, eleifend sed, tristique sed, nibh. Aliquam erat volutpat. Sed lobortis fringilla mauris. Nullam convallis ullamcorper urna. Integer id justo sed pede suscipit convallis. Cras non purus sed nisi faucibus scelerisque. Donec ullamcorper massa id risus. Vivamus tristique hendrerit neque. Maecenas pulvinar ipsum dictum ante. Cras eleifend lacus. Suspendisse et massa. Vestibulum sit amet lacus. In sed libero. Duis quis enim sit amet lorem ultrices rhoncus.
19 |
CENTER CLASS Lorem ipsum...
20 |
CENTER STYLE Lorem ipsum...
21 |
CENTER ID Lorem ipsum...
22 |
CENTER STYLE ATTR Lorem ipsum...
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/test/test-all.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Test all features of pisa
6 |
14 |
15 |
16 |
This document will try to test all features of pisa in an easy way. On the left side
17 | you see the rendered snippet an on the right an Image showing how it should look like
18 |
19 |
20 |
#
21 |
Rendered
22 |
Sample
23 |
24 |
25 |
01
26 |
27 | Normal
28 | Bold
29 | Italic
30 | Underlined
31 | Red
32 | Bigger
33 | Times
34 | Normal
35 |
x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x
33 |
34 |
35 |
36 | x x
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x
45 |
90 |
91 | This is normal
92 |
93 | becomes bold
94 |
95 | then also italic
96 |
97 |
98 |
99 | and then just italic
100 |
101 |
102 |
103 |
TTF (DejaVu Mono)
104 |
105 |
106 |
107 | This is normal
108 |
109 | becomes bold
110 |
111 | then also italic
112 |
113 |
114 |
115 | and then just italic
116 |
117 |
118 |
119 |
120 | Some text in "Farsi":
121 | به گفته وزیرخارجه روسیه، قطعنامه ای که اعضای دائم شورای امنیت سازمان ملل متحد و آلمان دیروز بر سر تصویب آن علیه ایران به توافق
122 | رسیدند، تحریمهای تازه و سختی بر این کشور اعمال نخواهد کرد
123 |
124 |
125 |
126 | Some text in "Korean":
127 | 박응용
128 |
129 |
130 |
Postscript (XXX)
131 |
132 |
133 |
134 | This is normal
135 |
136 | becomes bold
137 |
138 | then also italic
139 |
140 |
141 |
142 | and then just italic
143 |
144 |
32 | Denkt der Denker
33 |
34 | an die Mitte?
35 |
36 |
37 |
38 |
39 |
40 | Denkt der Denker
41 |
42 | an das Unten?
43 |
44 |
45 |
46 |
47 |
48 |
Woran der Denker denkt
49 |
50 |
51 | Denkt der Denker
52 |
53 | an das Oben?
54 |
55 |
56 |
57 |
58 |
59 | Denkt der Denker
60 |
61 | an die Mitte?
62 |
63 |
64 |
65 |
66 |
67 | Denkt der Denker
68 |
69 | an das Unten?
70 |
71 |
72 |
73 |
74 |
75 | Oder denkt er an ...?
77 |
78 |
79 |
80 | Manche Texte erschließen sich nur aus der nötigen Distanz.
81 | Aber das hier, das ist richtiger Text. Und er fließt sogar,
82 | nämlich um die Grafik.
83 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
21 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
22 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
23 |
24 |
25 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
26 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
27 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Blender is a software that is used for creating 3D content.
27 | Primarily this means you can make three dimensional images. However,
28 | you can also add sound, and make it time-based and interactive. This
29 | makes Blender ideal for a wide range of uses including creating 3D
30 | models, rendering, post -production, story boarding, creating
31 | animations, making movies, creating 3D 'programs', and making
32 | interactive environments and games.
33 |
34 |
2. Blender & it's Unique Interface
35 |
It's no secret that the Blender interface breaks a lot of rules.
36 | Luckily Blender has good reasons for it and after time these reasons
37 | become clear. Blender's interface is built around providing you with
38 | the shortest routes to the most results. It's also particularly focused
39 | on reducing the kind of stress on wrists and hands that's often felt
40 | when using mouse-intensive graphical applications every day.
41 |
42 |
43 |
3. < Installing Blender on OSX
44 |
45 |
Software Name: Blender
46 | Homepage:http://www.blender.org
47 | Software version used for this installation: Blender 2.43
48 | Operating System used for thisinstalltion: OSX (10.4.8)
49 | Reccomended Hardware: Powerbook G4, Powermac G5, Mac Pro, MacBookPro, iMac (core Duo)
50 |
Blender is a software that is used for creating 3D content.
27 | Primarily this means you can make three dimensional images. However,
28 | you can also add sound, and make it time-based and interactive. This
29 | makes Blender ideal for a wide range of uses including creating 3D
30 | models, rendering, post -production, story boarding, creating
31 | animations, making movies, creating 3D 'programs', and making
32 | interactive environments and games.
33 |
34 |
2. Blender's Unique Interface
35 |
It's no secret that the Blender interface breaks a lot of rules.
36 | Luckily Blender has good reasons for it and after time these reasons
37 | become clear. Blender's interface is built around providing you with
38 | the shortest routes to the most results. It's also particularly focused
39 | on reducing the kind of stress on wrists and hands that's often felt
40 | when using mouse-intensive graphical applications every day.
41 |
42 |
43 |
3. Installing Blender on OSX
44 |
45 |
Software Name: Blender
46 | Homepage:http://www.blender.org
47 | Software version used for this installation: Blender 2.43
48 | Operating System used for thisinstalltion: OSX (10.4.8)
49 | Reccomended Hardware: Powerbook G4, Powermac G5, Mac Pro, MacBookPro, iMac (core Duo)
50 |
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec euismod ante sed mi. Mauris tortor purus, fermentum sit amet, interdum et, rutrum nec, risus. Suspendisse erat nisi, vestibulum a, mattis at, dignissim quis, ante. Ut in dui. Etiam sed elit nec tellus vulputate tincidunt.
53 | LOREM
54 |
55 |
56 |
In blandit justo sed lorem. Proin malesuada. Pellentesque dignissim sem tempus augue ultrices sagittis. Nulla ac justo quis quam bibendum adipiscing. Curabitur pharetra, ipsum at iaculis faucibus, quam massa egestas mi, et mollis tellus tellus ac sapien. Etiam odio. Vivamus posuere dapibus velit. Etiam eros dui, vulputate non, congue eu, elementum ac, tellus. Vestibulum ac sapien sit amet diam blandit sollicitudin. Aenean in augue. Suspendisse potenti. Proin a leo. Etiam consequat, neque sed vulputate hendrerit, nibh nibh vehicula justo, sed dapibus augue justo bibendum erat. Suspendisse iaculis. Curabitur tempus. Aenean ultricies nonummy pede. Nulla facilisi. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Cras sem. Cras dolor risus, consequat ut, viverra eget, viverra a, orci.
57 |
LOREM
58 |
In blandit justo sed lorem. Proin malesuada. Pellentesque dignissim sem tempus augue ultrices sagittis. Nulla ac justo quis quam bibendum adipiscing. Curabitur pharetra, ipsum at iaculis faucibus, quam massa egestas mi, et mollis tellus tellus ac sapien. Etiam odio. Vivamus posuere dapibus velit. Etiam eros dui, vulputate non, congue eu, elementum ac, tellus. Vestibulum ac sapien sit amet diam blandit sollicitudin. Aenean in augue. Suspendisse potenti. Proin a leo. Etiam consequat, neque sed vulputate hendrerit, nibh nibh vehicula justo, sed dapibus augue justo bibendum erat. Suspendisse iaculis. Curabitur tempus. Aenean ultricies nonummy pede. Nulla facilisi. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Cras sem. Cras dolor risus, consequat ut, viverra eget, viverra a, orci.
59 |
60 |
61 |
LOREM
62 |
In blandit justo sed lorem. Proin malesuada. Pellentesque dignissim sem tempus augue ultrices sagittis. Nulla ac justo quis quam bibendum adipiscing. Curabitur pharetra, ipsum at iaculis faucibus, quam massa egestas mi, et mollis tellus tellus ac sapien. Etiam odio. Vivamu
77 |
78 | Many thanks to Birger Langker
79 |
80 | for providing the following link to The New
81 | Testament in Modern Greek. http://www.gospel.gr
82 |
83 | My home page
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/test/test-unicode-thaana.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Thaana Unicode Support Test and Resource Links
6 |
9 |
10 |
11 |
29 | Translation:
30 |
31 | Cuando vas a pescar ¿qué es lo peor que nos pasa ? Cuando vamos a pescar lo peor es cuando los
32 | cebos son escasos y no tenemos cebos. ¿Cómo haces para coger cebos ?
33 |
34 |
35 | The sample Thaana text on this page is from The World's Writing Systems by Daniels and Bright.
36 | The Spanish translation is borrowed from a web site which used the same sample text but failed to
37 | cite its source.
38 |
39 | Thaana is a right-to-left script.
40 |
41 | In order to make the spaces between the words a bit larger, I used two spaces between each word.
42 |
13 |
14 |
--------------------------------------------------------------------------------
/test/unicode.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "code2000";
3 | src: url("font/code2000.ttf")
4 | }
5 |
6 | html {
7 | font-family: code2000;
8 | }
9 |
--------------------------------------------------------------------------------
/test/visualdiff.py:
--------------------------------------------------------------------------------
1 | # Copyright 2010 Dirk Holtwick, holtwick.it
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | import sys
16 | import glob
17 | import subprocess
18 | import tempfile
19 | import os
20 | import os.path
21 |
22 | CONVERT = r"C:\Programme\ImageMagick-6.3.8-Q16\convert.exe"
23 | DIFF = "tortoiseidiff.exe"
24 |
25 | __version__ = "0.1"
26 |
27 | class VisualObject:
28 |
29 | def __init__(self):
30 | self.files = []
31 | self.files4del = []
32 | self.folder4del = None
33 |
34 | def __del__(self):
35 | for file in self.files4del:
36 | os.remove(file)
37 | self.files4del = []
38 | if self.folder4del:
39 | os.rmdir(self.folder4del)
40 | self.folder4del = None
41 |
42 | def execute(self, *a):
43 | print "EXECUTE", " ".join(a)
44 | return subprocess.Popen(a, stdout=subprocess.PIPE).communicate()[0]
45 |
46 | def getFiles(self, folder, pattern="*.*"):
47 | pattern = os.path.join(folder, pattern)
48 | self.files = [x for x in glob.glob(pattern) if not x.startswith(".")]
49 | self.files.sort()
50 | print "FILES", self.files
51 | return self.files
52 |
53 | def loadFile(self, file, folder=None, delete=True):
54 | if folder is None:
55 | folder = self.folder4del = tempfile.mkdtemp(prefix="visualdiff-tmp-")
56 | delete = True
57 | print "FOLDER", folder, "DELETE", delete
58 | source = os.path.abspath(file)
59 | destination = os.path.join(folder, "image.png")
60 | self.execute(CONVERT, source, destination)
61 | self.files4del = self.getFiles(folder, "*.png")
62 | return folder
63 |
64 | def compare(self, other, chunk=16 * 1024):
65 | if len(self.files) <> len(other.files):
66 | return False
67 | for i in range(len(self.files)):
68 | a = open(self.files[i], "rb")
69 | b = open(other.files[i], "rb")
70 | if a.read() <> b.read():
71 | return False
72 | return True
73 |
74 | def getoptions():
75 | from optparse import OptionParser
76 | usage = "usage: %prog [options] arg"
77 | description = """
78 | Visual Differences
79 | """.strip()
80 | version = __version__
81 | parser = OptionParser(
82 | usage,
83 | description=description,
84 | version=version,
85 | )
86 | #parser.add_option(
87 | # "-c", "--css",
88 | # help="Path to default CSS file",
89 | # dest="css",
90 | # )
91 | parser.add_option("-q", "--quiet",
92 | action="store_false", dest="verbose", default=True,
93 | help="don't print status messages to stdout")
94 | parser.set_defaults(
95 | # css=None,
96 | )
97 | (options, args) = parser.parse_args()
98 |
99 | #if not (0 < len(args) <= 2):
100 | # parser.error("incorrect number of arguments")
101 |
102 | return options, args
103 |
104 | def main():
105 |
106 | options, args = getoptions()
107 |
108 | print args
109 |
110 | a = VisualObject()
111 | b = VisualObject()
112 |
113 | a.loadFile("expected/test-loremipsum.pdf")
114 | b.files = a.files
115 |
116 | print a.compare(b)
117 |
118 | if __name__=="__main__":
119 | main()
120 |
--------------------------------------------------------------------------------
/test/witherror.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/holtwick/xhtml2pdf/881850e49b67d8c9111ac53d09fb90138c1a3320/test/witherror.py
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
1 | from runtests import buildTestSuite
2 |
--------------------------------------------------------------------------------
/tests/runtests.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import os
3 | import glob
4 | import unittest
5 |
6 | #Allow us to import the parent module
7 | os.chdir(os.path.split(os.path.abspath(__file__))[0])
8 | sys.path.insert(0, os.path.abspath(os.curdir))
9 | sys.path.insert(0, os.path.abspath(os.pardir))
10 | # sys.path.insert(0, os.path.join(os.path.abspath(os.pardir), "src"))
11 |
12 | def buildTestSuite():
13 | suite = unittest.TestSuite()
14 | for testcase in glob.glob('test_*.py'):
15 | module = os.path.splitext(testcase)[0]
16 | suite.addTest(__import__(module).buildTestSuite())
17 | return suite
18 |
19 | def main():
20 | results = unittest.TextTestRunner().run(buildTestSuite())
21 | return results
22 |
23 | if __name__ == "__main__":
24 | results = main()
25 | if not results.wasSuccessful():
26 | sys.exit(1)
27 |
--------------------------------------------------------------------------------
/tests/samples/borders.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
48 |
49 |
50 |
Hello World: class=c1
51 |
Goodbye: class=c2
52 |
Goodbye: class=c2 padding: 16px;
53 |
Goodbye: class=c2 padding: 16px;
54 |
Goodbye: class=c2 Next line
55 |
Mixed colors: class=c3
56 |
Hello World: class=c1
57 |
Goodbye: class=c2
58 |
Mixed colors: class=c3
59 |
This is line A with line-spacing: 100%, there should not be any space between the lines
60 | This is line B
61 |
This is line A with line-spacing: 150%, there should be a gap
62 | This is line B
63 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
64 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
65 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea consectetur commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
66 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
67 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
68 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
69 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
70 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Here we are testing if the floating of images work and the inline feature.
11 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
12 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
13 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.