Better PDF generation script

This commit is contained in:
Yorik van Havre 2015-03-21 17:45:08 -03:00
parent f87fbe7e2a
commit d67d9603c2
4 changed files with 389 additions and 52 deletions

3
.gitignore vendored
View File

@ -27,3 +27,6 @@ install_manifest.txt
/Mod/
/ZERO_CHECK.dir/
/build/
/src/Tools/offlinedoc/localwiki/
/src/Tools/offlinedoc/todolist.txt
/src/Tools/offlinedoc/wikifiles.txt

View File

@ -41,6 +41,7 @@ VERBOSE = True # set true to get output messages
INCLUDECOMMANDS = True # if true, the command pages of each workbench are included after each WB page
OVERWRITE = False # if true, pdf files are recreated even if already existing
FIREFOXPDFFOLDER = os.path.expanduser("~")+os.sep+"PDF" # if firefox is used, set this to where it places its pdf files by default
COVER = "http://www.freecadweb.org/wiki/images/7/79/Freecad-pdf-cover.svg"
# END CONFIGURATION ##############################################
@ -50,7 +51,7 @@ FOLDER = "./localwiki"
fcount = dcount = 0
def crawl():
"downloads an entire wiki site"
"creates a pdf file from the localwiki folder"
# tests ###############################################
@ -65,9 +66,9 @@ def crawl():
print "Error: Htmldoc not found, exiting."
return 1
try:
from pyPdf import PdfFileReader,PdfFileWriter
from PyPDF2 import PdfFileReader,PdfFileWriter
except:
print "Error: Python-pypdf not installed, exiting."
print "Error: Python-pypdf2 not installed, exiting."
# run ########################################################
@ -77,6 +78,7 @@ def crawl():
if VERBOSE: print "All done!"
return 0
def buildpdffiles():
"scans a folder for html files and converts them all to pdf"
templist = os.listdir(FOLDER)
@ -101,6 +103,7 @@ def buildpdffiles():
createpdf_htmldoc(f[:-5])
i += 1
def fetch_resources(uri, rel):
"""
Callback to allow pisa/reportlab to retrieve Images,Stylesheets, etc.
@ -116,8 +119,8 @@ def createpdf_pisa(pagename):
"creates a pdf file from a saved page using pisa (python module)"
import ho.pisa as pisa
if (not exists(pagename+".pdf",image=True)) or OVERWRTIE:
infile = file(FOLDER + os.sep + pagename+'.html','ro')
outfile = file(FOLDER + os.sep + pagename+'.pdf','wb')
infile = open(FOLDER + os.sep + pagename+'.html','ro')
outfile = open(FOLDER + os.sep + pagename+'.pdf','wb')
if VERBOSE: print "Converting " + pagename + " to pdf..."
pdf = pisa.CreatePDF(infile,outfile,FOLDER,link_callback=fetch_resources)
outfile.close()
@ -125,6 +128,7 @@ def createpdf_pisa(pagename):
return pdf.err
return 0
def createpdf_firefox(pagename):
"creates a pdf file from a saved page using firefox (needs command line printing extension)"
# the default printer will be used, so make sure it is set to pdf
@ -139,6 +143,7 @@ def createpdf_firefox(pagename):
else:
print "-----------------------------------------> Couldn't find print output!"
def createpdf_htmldoc(pagename):
"creates a pdf file from a saved page using htmldoc (external app, but supports images)"
if (not exists(pagename+".pdf",image=True)) or OVERWRITE:
@ -146,6 +151,7 @@ def createpdf_htmldoc(pagename):
outfile = FOLDER + os.sep + pagename+'.pdf'
return os.system('htmldoc --webpage --textfont sans --browserwidth 840 -f '+outfile+' '+infile)
def createpdf_wkhtmltopdf(pagename):
"creates a pdf file from a saved page using htmldoc (external app, but supports images)"
if (not exists(pagename+".pdf",image=True)) or OVERWRITE:
@ -155,55 +161,59 @@ def createpdf_wkhtmltopdf(pagename):
else:
print "skipping"
def joinpdf():
"creates one pdf file from several others, following order from startpage"
from pyPdf import PdfFileReader,PdfFileWriter
"creates one pdf file from several others, following order from the cover"
from PyPDF2 import PdfFileReader,PdfFileWriter
if VERBOSE: print "Building table of contents..."
f = open(FOLDER+os.sep+INDEX+'.html')
html = ''
for line in f: html += line
f.close()
html = html.replace("\n"," ")
html = html.replace("> <","><")
html = re.findall("<ul.*/ul>",html)[0]
pages = re.findall('href="(.*?)"',html)
pages.insert(1,INDEX+".html")
result = PdfFileWriter()
for p in pages:
if exists(p[:-5]):
if VERBOSE: print 'Appending',p[:-5]+'.pdf'
try:
inputfile = PdfFileReader(file(FOLDER+os.sep+p[:-5]+'.pdf','rb'))
except:
print 'Unable to append',p
else:
for i in range(inputfile.getNumPages()):
createCover()
inputfile = PdfFileReader(open(FOLDER+os.sep+'Cover.pdf','rb'))
result.addPage(inputfile.getPage(0))
count = 1
tocfile = open("toc.txt")
parent = False
for page in tocfile:
page = page.strip()
if page:
if page[0] == "#":
continue
if page == "begin":
parent = True
continue
if page == "end":
parent = False
continue
if VERBOSE: print 'Appending',page, "at position",count
title = page.replace("_"," ")
pdffile = page + ".pdf"
if exists(pdffile,True):
inputfile = PdfFileReader(open(FOLDER + os.sep + pdffile,'rb'))
numpages = inputfile.getNumPages()
for i in range(numpages):
result.addPage(inputfile.getPage(i))
if INCLUDECOMMANDS:
if ("_Workbench.html" in p) or ("_Module.html" in p):
mod = [p.split("_")[0]]
if mod[0] == "PartDesign":
mod.append("Constraint")
for m in mod:
for f in fileslist:
if f[:len(m)+1] == m+"_":
if (not("Module" in f)) and (not("Workbench" in f)) and (not("Scripting" in f)) and (not("API" in f)):
if VERBOSE: print ' Appending',f[:-5]+'.pdf'
try:
inputfile = PdfFileReader(file(FOLDER+os.sep+f[:-5]+'.pdf','rb'))
except:
print 'Unable to append',f
else:
for i in range(inputfile.getNumPages()):
result.addPage(inputfile.getPage(i))
if parent == True:
parent = result.addBookmark(title,count)
elif parent == False:
result.addBookmark(title,count)
else:
result.addBookmark(title,count,parent)
count += numpages
else:
print "page",pdffile,"not found, aborting."
sys.exit()
if VERBOSE: print "Writing..."
outputfile = file(FOLDER+os.sep+"freecad.pdf",'wb')
outputfile = open(FOLDER+os.sep+"freecad.pdf",'wb')
result.write(outputfile)
outputfile.close()
if VERBOSE:
print ' '
print 'Successfully created '+FOLDER+os.sep+'freecad.pdf'
def local(page,image=False):
"returns a local path for a given page/image"
if image:
@ -211,22 +221,41 @@ def local(page,image=False):
else:
return FOLDER + os.sep + page + '.html'
def exists(page,image=False):
"checks if given page/image already exists"
path = local(page,image)
if os.path.exists(path): return True
return False
def makeStyleSheet():
"Creates a stylesheet for wkhtmltopdf"
outputfile = file(FOLDER+os.sep+"wkhtmltopdf.css",'wb')
outputfile = open(FOLDER+os.sep+"wkhtmltopdf.css",'wb')
outputfile.write("""
html {
margin: 50px 0;
margin: 50px 0 0 50px !important;
}
a:link, a:visited {
color: #000 !important;
}
.printfooter {
display:none !important;
}
""")
outputfile.close()
def createCover():
"downloads and creates a cover page"
if VERBOSE: print "fetching " + COVER
data = (urlopen(COVER).read())
path = FOLDER + os.sep + "Cover.svg"
fil = open(path,'wb')
fil.write(data)
fil.close()
os.system('inkscape --export-pdf='+FOLDER+os.sep+'Cover.pdf'+' '+FOLDER+os.sep+'Cover.svg')
if __name__ == "__main__":
crawl()
crawl()

View File

@ -53,8 +53,6 @@ def crawl(pagename):
todolist = []
processed = []
count = 1
if pagename:
INDEX = pagename[0]
if os.path.exists("wikifiles.txt"):
f = open("wikifiles.txt","r")
if VERBOSE: print "Reading existing list..."
@ -71,8 +69,11 @@ def crawl(pagename):
todolist.append(l.strip())
f.close()
else:
indexpages,imgs = get(INDEX)
todolist.extend(indexpages)
if pagename:
todolist = pagename
else:
indexpages,imgs = get(INDEX)
todolist.extend(indexpages)
while todolist:
targetpage = todolist.pop()
if not targetpage in NORETRIEVE:

View File

@ -0,0 +1,304 @@
# order of pages for the PDF version.
# pagenames preceded with # are incomplete and not included.
# each line indicates a pagename, or the word "begin" if the given
# page is the main page of a section, or "end" if the next pages don't
# below to any section.
Online_Help_Startpage
About_FreeCAD
Getting_started
Workbenches
begin
Part_Workbench
Part_Box
Part_Cone
Part_Cylinder
Part_Sphere
Part_Torus
Part_CreatePrimitives
Part_Plane
Part_Prism
Part_Wedge
Part_Helix
Part_Spiral
Part_Circle
Part_Ellipse
Part_Line
Part_Point
Part_RegularPolygon
Part_Booleans
# Part_Common
# Part_Cut
Part_Fuse
# Part_Shapebuilder
Part_Extrude
Part_Fillet
Part_Revolve
Part_SectionCross
Part_Chamfer
Part_Mirror
Part_RuledSurface
Part_Sweep
Part_Loft
Part_Offset
Part_Thickness
Part_RefineShape
Part_CheckGeometry
begin
PartDesign_Workbench
PartDesign_Pad
PartDesign_Pocket
PartDesign_Revolution
PartDesign_Groove
Sketcher_Point
Sketcher_Line
Sketcher_Arc
Sketcher_Circle
Sketcher_Ellipse
Sketcher_Arc_of_Ellipse
Sketcher_Polyline
Sketcher_Rectangle
Sketcher_Triangle
Sketcher_Square
Sketcher_Pentagon
Sketcher_Hexagon
Sketcher_Heptagon
Sketcher_Octagon
Sketcher_Slot
Sketcher_Fillet
Sketcher_Trimming
# Sketcher_Arch3Point
# Sketcher_Circle3Point
# Sketcher_ConicSections
# Sketcher_Ellipse_by_3_Points
Constraint_PointOnPoint
Constraint_Vertical
Constraint_Horizontal
Constraint_Parallel
Constraint_Perpendicular
Constraint_Tangent
Constraint_EqualLength
Constraint_Symmetric
Constraint_Lock
Constraint_HorizontalDistance
Constraint_VerticalDistance
Constraint_Length
Constraint_Radius
Constraint_InternalAngle
Constraint_SnellsLaw
Constraint_Internal_Alignment
# Constraint_PointOnObject
Sketcher_MapSketch
Sketcher_Reorient
Sketcher_Validate
Sketcher_Show_Hide_Internal_Geometry
# Sketcher_MergeSketch
# Sketcher_CloseShape
# Sketcher_ConnectLines
# Sketcher_SelectConstraints
# Sketcher_SelectOrigin
# Sketcher_SelectVerticalAxis
# Sketcher_SelectHorizontalAxis
# Sketcher_SelectRedundantConstraints
# Sketcher_SelectConflictingConstraints
# Sketcher_SelectElementsAssociatedWithConstraints
PartDesign_Fillet
PartDesign_Chamfer
PartDesign_Draft
PartDesign_Mirrored
PartDesign_LinearPattern
PartDesign_PolarPattern
PartDesign_Scaled
PartDesign_MultiTransform
PartDesign_WizardShaft
PartDesign_InvoluteGear
Sketcher_Tutorial
begin
Draft_Workbench
Draft_Line
Draft_Wire
Draft_Circle
Draft_Arc
Draft_Ellipse
Draft_Polygon
Draft_Rectangle
Draft_Text
Draft_Dimension
Draft_BSpline
Draft_Point
Draft_ShapeString
Draft_Facebinder
Draft_BezCurve
Draft_Move
Draft_Rotate
Draft_Offset
Draft_Trimex
Draft_Upgrade
Draft_Downgrade
Draft_Scale
Draft_Edit
Draft_WireToBSpline
Draft_AddPoint
Draft_DelPoint
Draft_Shape2DView
Draft_Draft2Sketch
Draft_Array
Draft_Clone
Draft_SelectPlane
Draft_VisGroup
begin
Arch_Workbench
Arch_Wall
Arch_Structure
Arch_Rebar
Arch_Floor
Arch_Building
Arch_Site
Arch_Window
Arch_SectionPlane
Arch_Axis
Arch_Roof
Arch_Space
Arch_Stairs
Arch_Panel
Arch_Frame
Arch_Equipment
Arch_CutPlane
Arch_Add
Arch_Remove
Arch_Survey
Arch_tutorial
begin
Drawing_Workbench
Drawing_Landscape_A3
Drawing_View
Drawing_Annotation
Drawing_Clip
Drawing_Openbrowser
Drawing_Symbol
Drawing_DraftView
Drawing_Save
Drawing_ProjectShape
# Drawing_Othoviews
begin
Raytracing_Workbench
# Raytracing_New
# Raytracing_Lux
# Raytracing_Part
# Raytracing_ResetCamera
# Raytracing_Export
# Raytracing_Render
begin
Robot_Workbench
# Robot_createRobot
# Robot_Simulate
# Robot_Export
# Robot_SetHomePos
# Robot_RestoreHomePos
# Robot_CreateTrajectory
# Robot_SetDefaultOrientation
# Robot_InsertWaypoint
# Robot_InsertWaypointPre
# Robot_Edge2Trac
# Robot_TrajectoryDressUp
# Robot_TrajectoryCompound
begin
OpenSCAD_Workbench
OpenSCAD_AddOpenSCADElement
# OpenSCAD_ColorCodeShape
# OpenSCAD_ReplaceObject
# OpenSCAD_RemoveSubtree
# OpenSCAD_RefineShapeFeature
# OpenSCAD_IncreaseTolerance
# OpenSCAD_Edgestofaces
# OpenSCAD_ExpandPlacements
# OpenSCAD_ExplodeGroup
# OpenSCAD_MeshBoolean
# OpenSCAD_Hull
# OpenSCAD_Minkowski
begin
Fem_Workbench
FEM_Analysis
# FEM_Create
# FEM_Material
# FEM_Calculation
# FEM_DefineNodes
# FEM_FixedConstraint
# FEM_ForceConstraint
# FEM_BearingConstraint
# FEM_GearConstraint
# FEM_PulleyConstraint
# FEM_ShowResult
begin
Plot_Module
Plot_Save
Plot_Basic_tutorial
Plot_MultiAxes_tutorial
# Plot_Axes
# Plot_Series
# Plot_Grid
# Plot_Legend
# Plot_Labels
# Plot_Positions
begin
Mesh_Workbench
end
Macros
Introduction_to_Python
Python_scripting_tutorial
Topological_data_scripting
Mesh_Scripting
Mesh_to_Part
Scenegraph
Pivy
begin
PySide
PySide_Beginner_Examples
PySide_Medium_Examples
PySide_Advanced_Examples
end
Scripted_objects
Embedding_FreeCAD
Embedding_FreeCADGui
Code_snippets