Commit 8626af91 by Edgar HIPP

Remove coffee

parent ebea6f31
DOMParser = require('xmldom').DOMParser
XMLSerializer= require('xmldom').XMLSerializer
DocUtils = {}
DocUtils.xml2Str = (xmlNode) ->
a= new XMLSerializer()
a.serializeToString(xmlNode)
DocUtils.Str2xml= (str,errorHandler) ->
parser=new DOMParser({errorHandler})
xmlDoc=parser.parseFromString(str,"text/xml")
DocUtils.maxArray = (a) -> Math.max.apply(null, a)
DocUtils.decodeUtf8= (s) ->
try
if s==undefined then return undefined
return decodeURIComponent(escape(DocUtils.convertSpaces(s))) #replace Ascii 160 space by the normal space, Ascii 32
catch e
console.error s
console.error 'could not decode'
throw new Error('end')
DocUtils.encodeUtf8 = (s)->
unescape(encodeURIComponent(s))
DocUtils.convertSpaces= (s) ->
s.replace(new RegExp(String.fromCharCode(160),"g")," ")
DocUtils.pregMatchAll= (regex, content) ->
###regex is a string, content is the content. It returns an array of all matches with their offset, for example:
regex=la
content=lolalolilala
returns: [{0:'la',offset:2},{0:'la',offset:8},{0:'la',offset:10}]
###
if (typeof regex!='object')
regex= (new RegExp(regex,'g'))
matchArray= []
replacer = (pn...)->
string = pn.pop()
offset = pn.pop()
#add match so that pn[0] = whole match, pn[1]= first parenthesis,...
pn.offset= offset
matchArray.push pn
content.replace regex,replacer
matchArray
module.exports=DocUtils
XmlTemplater=require('docxtemplater').XmlTemplater
vm=require('vm')
JSZip=require('jszip')
QrCode=require('qrcode-reader')
module.exports= class DocxQrCode
constructor:(imageData, @xmlTemplater,@imgName="",@num,@getDataFromString)->
@callbacked=false
@data=imageData
if @data==undefined then throw new Error("data of qrcode can't be undefined")
@ready=false
@result=null
decode:(@callback) ->
_this= this
@qr= new QrCode()
@qr.callback= () ->
_this.ready= true
_this.result= @result
testdoc= new XmlTemplater @result,
fileTypeConfig:_this.xmlTemplater.fileTypeConfig
tags:_this.xmlTemplater.tags
Tags:_this.xmlTemplater.Tags
parser:_this.xmlTemplater.parser
testdoc.render()
_this.result=testdoc.content
_this.searchImage()
@qr.decode({width:@data.width,height:@data.height},@data.decoded)
searchImage:() ->
cb=(err,@data=@data.data)=>
if err then console.error err
@callback(this,@imgName,@num)
if !@result? then return cb()
@getDataFromString(@result,cb)
DocUtils=require('./docUtils')
imageExtensions=['gif','jpeg','jpg','emf','png']
module.exports = class ImgManager
constructor:(@zip,@fileName)->
@endFileName=@fileName.replace(/^.*?([a-z0-9]+)\.xml$/,"$1")
getImageList: () ->
regex= ///
[^.]+
\.
([^.]+)
///
imageList= []
for index of @zip.files
extension= index.replace(regex,'$1')
if extension in imageExtensions #Defined in constructor
imageList.push {"path":index,files:@zip.files[index]}
imageList
setImage:(fileName,data,options={})->
@zip.remove(fileName)
@zip.file(fileName,data,options)
hasImage:(fileName)->
@zip.files[fileName]?
loadImageRels: () ->
file=@zip.files["word/_rels/#{@endFileName}.xml.rels"] || @zip.files["word/_rels/document.xml.rels"]
if file==undefined then return
content= DocUtils.decodeUtf8 file.asText()
@xmlDoc= DocUtils.Str2xml content
# Get all Rids
RidArray = []
for tag in @xmlDoc.getElementsByTagName('Relationship')
RidArray.push(parseInt tag.getAttribute("Id").substr(3))
@maxRid=DocUtils.maxArray(RidArray)
@imageRels=[]
this
addExtensionRels: (contentType,extension) -> #Add an extension type in the [Content_Types.xml], is used if for example you want word to be able to read png files (for every extension you add you need a contentType)
content = @zip.files["[Content_Types].xml"].asText()
xmlDoc= DocUtils.Str2xml content
addTag= true
defaultTags=xmlDoc.getElementsByTagName('Default')
for tag in defaultTags
if tag.getAttribute('Extension')==extension then addTag= false
if addTag
types=xmlDoc.getElementsByTagName("Types")[0]
newTag=xmlDoc.createElement 'Default'
newTag.namespaceURI= null
newTag.setAttribute('ContentType',contentType)
newTag.setAttribute('Extension',extension)
types.appendChild newTag
@setImage "[Content_Types].xml",DocUtils.encodeUtf8 DocUtils.xml2Str xmlDoc
addImageRels: (imageName,imageData,i=0) -> #Adding an image and returns it's Rid
realImageName=if i==0 then imageName else imageName+"(#{i})"
if @zip.files["word/media/#{realImageName}"]?
return @addImageRels(imageName,imageData,i+1)
@maxRid++
file=
'name':"word/media/#{realImageName}"
'data':imageData
'options':
base64: false
binary: true
compression: null
date: new Date()
dir: false
@zip.file file.name,file.data,file.options
extension= realImageName.replace(/[^.]+\.([^.]+)/,'$1')
@addExtensionRels("image/#{extension}",extension)
relationships= @xmlDoc.getElementsByTagName("Relationships")[0]
newTag= @xmlDoc.createElement 'Relationship' #,relationships.namespaceURI
newTag.namespaceURI= null
newTag.setAttribute('Id',"rId#{@maxRid}")
newTag.setAttribute('Type','http://schemas.openxmlformats.org/officeDocument/2006/relationships/image')
newTag.setAttribute('Target',"media/#{realImageName}")
relationships.appendChild newTag
@setImage("word/_rels/#{@endFileName}.xml.rels",DocUtils.encodeUtf8 DocUtils.xml2Str @xmlDoc)
@maxRid
getImageName:(id=0)->
nameCandidate="Copie_"+id+".png"
fullPath=@getFullPath(nameCandidate)
if @hasImage(fullPath)
return @getImageName(id+1)
nameCandidate
getFullPath:(imgName)->"word/media/#{imgName}"
getImageByRid:(rId)-> #This is to get an image by it's rId (returns null if no img was found)
relationships= @xmlDoc.getElementsByTagName('Relationship')
for relationship in relationships
cRId= relationship.getAttribute('Id')
if rId==cRId
path=relationship.getAttribute('Target')
if path.substr(0,6)=='media/'
return @zip.files["word/#{path}"]
else
throw new Error("Rid is not an image")
throw new Error("No Media with this Rid found")
DocUtils=require('./docUtils')
DocxQrCode=require('./docxQrCode')
PNG=require('png-js')
JSZip=require('jszip')
module.exports= class ImgReplacer
constructor: (@xmlTemplater,@imgManager)->
@imgMatches=[]
@xmlTemplater.numQrCode=0
this
findImages:() ->
@imgMatches= DocUtils.pregMatchAll /<w:drawing[^>]*>.*?<a:blip.r:embed.*?<\/w:drawing>/g, @xmlTemplater.content
this
replaceImages: ()->
@qr=[]
@xmlTemplater.numQrCode+=@imgMatches.length
@replaceImage(match,u) for match,u in @imgMatches
this
imageSetter:(docxqrCode) =>
if docxqrCode.callbacked==true then return
docxqrCode.callbacked=true
docxqrCode.xmlTemplater.numQrCode--
@imgManager.setImage("word/media/#{docxqrCode.imgName}",docxqrCode.data,{binary:true})
@popQrQueue(@imgManager.fileName+'-'+docxqrCode.num,false)
replaceImage:(match,u)->
num=parseInt(Math.random()*10000)
try
baseDocument = """<?xml version="1.0" ?>
<w:document
mc:Ignorable="w14 wp14"
xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:w10="urn:schemas-microsoft-com:office:word"
xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml"
xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing"
xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas"
xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup"
xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk"
xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape">#{match[0]}</w:document>
"""
f=(_i,type)->
if _i=='fatalError'
throw "fatalError"
xmlImg= DocUtils.Str2xml baseDocument,f
catch e
return
tagrId= xmlImg.getElementsByTagName("a:blip")[0]
if tagrId==undefined then throw new Error('tagRiD undefined !')
rId = tagrId.getAttribute('r:embed')
oldFile= @imgManager.getImageByRid(rId)
tag= xmlImg.getElementsByTagName("wp:docPr")[0]
if tag==undefined then throw new Error('tag undefined')
if tag.getAttribute("name").substr(0,6)=="Copie_" then return #if image is already a replacement then do nothing
imgName= @imgManager.getImageName()
@pushQrQueue(@imgManager.fileName+'-'+num,true)
newId= @imgManager.addImageRels(imgName,"")
@xmlTemplater.imageId++
@imgManager.setImage(@imgManager.getFullPath(imgName),oldFile.data,{binary:true})
tag.setAttribute('name',"#{imgName}")
tagrId.setAttribute('r:embed',"rId#{newId}")
imageTag=xmlImg.getElementsByTagName('w:drawing')[0]
if imageTag==undefined then throw new Error('imageTag undefined')
replacement= DocUtils.xml2Str imageTag
@xmlTemplater.content= @xmlTemplater.content.replace(match[0], replacement)
mockedQrCode={xmlTemplater:@xmlTemplater,imgName:imgName,data:oldFile.asBinary(),num:num}
if /\.png$/.test(oldFile.name)
do (imgName) =>
base64= JSZip.base64.encode oldFile.asBinary()
binaryData = new Buffer(base64, 'base64')
png= new PNG(binaryData)
finished= (a) =>
png.decoded= a
try
@qr[u]= new DocxQrCode(png,@xmlTemplater,imgName,num,@getDataFromString)
@qr[u].decode(@imageSetter)
catch e
console.error e
console.error e.stack
@imageSetter(mockedQrCode)
dat= png.decode(finished)
else
@imageSetter(mockedQrCode)
SubContent=require('docxtemplater').SubContent
ImgManager=require('./imgManager')
ImgReplacer=require('./imgReplacer')
fs=require('fs')
class ImageModule
constructor:(@options={})->
if !@options.centered? then @options.centered=false
if !@options.getImage? then throw new Error("You should pass getImage")
if !@options.getSize? then throw new Error("You should pass getSize")
@qrQueue=[]
@imageNumber=1
handleEvent:(event,eventData)->
if event=='rendering-file'
@renderingFileName=eventData
gen=@manager.getInstance('gen')
@imgManager=new ImgManager(gen.zip,@renderingFileName)
@imgManager.loadImageRels()
if event=='rendered'
if @qrQueue.length==0 then @finished()
get:(data)->
if data=='loopType'
templaterState=@manager.getInstance('templaterState')
if templaterState.textInsideTag[0]=='%'
return 'image'
null
getNextImageName:()->
name="image_generated_#{@imageNumber}.png"
@imageNumber++
name
replaceBy:(text,outsideElement)->
xmlTemplater=@manager.getInstance('xmlTemplater')
templaterState=@manager.getInstance('templaterState')
subContent=new SubContent(xmlTemplater.content)
subContent=subContent.getInnerTag(templaterState)
subContent=subContent.getOuterXml(outsideElement)
xmlTemplater.replaceXml(subContent,text)
convertPixelsToEmus:(pixel)->
Math.round(pixel * 9525)
replaceTag:->
scopeManager=@manager.getInstance('scopeManager')
templaterState=@manager.getInstance('templaterState')
tag = templaterState.textInsideTag.substr(1)
tagValue = scopeManager.getValue(tag)
xmlTemplater = @manager.getInstance('xmlTemplater')
tagXml=xmlTemplater.fileTypeConfig.tagsXmlArray[0]
tagXmlParagraph = tagXml.substr(0,1)+':p'
if @options.centered==false
outsideElement=tagXml
if @options.centered==true
outsideElement=tagXmlParagraph
startEnd= "<#{tagXml}></#{tagXml}>"
if !tagValue? then return @replaceBy(startEnd,tagXml)
try
imgBuffer=@options.getImage(tagValue, tag)
catch e
return @replaceBy(startEnd,tagXml)
imageRels=@imgManager.loadImageRels()
if imageRels
rId=imageRels.addImageRels(@getNextImageName(),imgBuffer)
sizePixel=@options.getSize(imgBuffer, tagValue, tag)
size=[@convertPixelsToEmus(sizePixel[0]),@convertPixelsToEmus(sizePixel[1])]
if @options.centered==false
newText=@getImageXml(rId,size)
if @options.centered==true
newText=@getImageXmlCentered(rId,size)
@replaceBy(newText,outsideElement)
replaceQr:->
xmlTemplater=@manager.getInstance('xmlTemplater')
imR=new ImgReplacer(xmlTemplater,@imgManager)
imR.getDataFromString=(result,cb)=>
if @options.getImageAsync?
@options.getImageAsync(result,cb)
else
cb(null,@options.getImage(result))
imR.pushQrQueue=(num)=>
@qrQueue.push(num)
imR.popQrQueue=(num)=>
found = @qrQueue.indexOf(num)
if found!=-1
@qrQueue.splice(found,1)
else @on('error',new Error("qrqueue #{num} is not in qrqueue"))
if @qrQueue.length==0 then @finished()
num=parseInt(Math.random()*10000)
imR.pushQrQueue("rendered-" + num)
try
imR.findImages().replaceImages()
catch e
@on('error',e)
f=()=>imR.popQrQueue("rendered-" + num)
setTimeout f, 1
finished:->
on:(event,data)->
if event=='error'
throw data
handle:(type,data)->
if type=='replaceTag' and data=='image'
@replaceTag()
if type=='xmlRendered' and @options.qrCode
@replaceQr()
null
getImageXml:(rId,size)->
return """
<w:drawing>
<wp:inline distT="0" distB="0" distL="0" distR="0">
<wp:extent cx="#{size[0]}" cy="#{size[1]}"/>
<wp:effectExtent l="0" t="0" r="0" b="0"/>
<wp:docPr id="2" name="Image 2" descr="image"/>
<wp:cNvGraphicFramePr>
<a:graphicFrameLocks xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" noChangeAspect="1"/>
</wp:cNvGraphicFramePr>
<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:nvPicPr>
<pic:cNvPr id="0" name="Picture 1" descr="image"/>
<pic:cNvPicPr>
<a:picLocks noChangeAspect="1" noChangeArrowheads="1"/>
</pic:cNvPicPr>
</pic:nvPicPr>
<pic:blipFill>
<a:blip r:embed="rId#{rId}">
<a:extLst>
<a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}">
<a14:useLocalDpi xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main" val="0"/>
</a:ext>
</a:extLst>
</a:blip>
<a:srcRect/>
<a:stretch>
<a:fillRect/>
</a:stretch>
</pic:blipFill>
<pic:spPr bwMode="auto">
<a:xfrm>
<a:off x="0" y="0"/>
<a:ext cx="#{size[0]}" cy="#{size[1]}"/>
</a:xfrm>
<a:prstGeom prst="rect">
<a:avLst/>
</a:prstGeom>
<a:noFill/>
<a:ln>
<a:noFill/>
</a:ln>
</pic:spPr>
</pic:pic>
</a:graphicData>
</a:graphic>
</wp:inline>
</w:drawing>
"""
getImageXmlCentered:(rId,size)->
"""
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr/>
<w:drawing>
<wp:inline distT="0" distB="0" distL="0" distR="0">
<wp:extent cx="#{size[0]}" cy="#{size[1]}"/>
<wp:docPr id="0" name="Picture" descr=""/>
<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:nvPicPr>
<pic:cNvPr id="0" name="Picture" descr=""/>
<pic:cNvPicPr>
<a:picLocks noChangeAspect="1" noChangeArrowheads="1"/>
</pic:cNvPicPr>
</pic:nvPicPr>
<pic:blipFill>
<a:blip r:embed="rId#{rId}"/>
<a:stretch>
<a:fillRect/>
</a:stretch>
</pic:blipFill>
<pic:spPr bwMode="auto">
<a:xfrm>
<a:off x="0" y="0"/>
<a:ext cx="#{size[0]}" cy="#{size[1]}"/>
</a:xfrm>
<a:prstGeom prst="rect">
<a:avLst/>
</a:prstGeom>
<a:noFill/>
<a:ln w="9525">
<a:noFill/>
<a:miter lim="800000"/>
<a:headEnd/>
<a:tailEnd/>
</a:ln>
</pic:spPr>
</pic:pic>
</a:graphicData>
</a:graphic>
</wp:inline>
</w:drawing>
</w:r>
</w:p>
"""
module.exports=ImageModule
...@@ -4,10 +4,9 @@ ...@@ -4,10 +4,9 @@
"description": "Image Module for docxtemplater v1.0", "description": "Image Module for docxtemplater v1.0",
"main": "js/index.js", "main": "js/index.js",
"scripts": { "scripts": {
"convertto:es6": "rm es6 -rf; mkdir -p es6; for i in coffee/*.coffee; do echo \"$i\"; decaffeinate \"$i\"; mv \"${i%.coffee}.js\" \"${i%.coffee}.es6\"; done; for i in coffee/*.es6; do mv \"$i\" \"es6${i#coffee}\"; done ", "compile": "rm js -rf ; mkdir -p test/spec; mkdir -p js; babel es6 --out-dir js; mv js/test.js test/test.js",
"convertto:es5": "rm js -rf ; mkdir -p test/spec; mkdir -p js; babel es6 --out-dir js; mv js/test.js test/test.js",
"test:compiled": "mocha", "test:compiled": "mocha",
"test": "npm run convertto:es6 && npm run convertto:es5 && npm run test:compiled" "test": "npm run compile && npm run test:compiled"
}, },
"devDependencies": { "devDependencies": {
"babel-preset-es2015": "^6.3.13", "babel-preset-es2015": "^6.3.13",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment