2017-09-03 12:01:55 -05:00
|
|
|
// Copyright 2017 Baliance. All rights reserved.
|
|
|
|
//
|
|
|
|
// Use of this source code is governed by the terms of the Affero GNU General
|
|
|
|
// Public License version 3.0 as published by the Free Software Foundation and
|
|
|
|
// appearing in the file LICENSE included in the packaging of this file. A
|
|
|
|
// commercial license can be purchased by contacting sales@baliance.com.
|
|
|
|
|
|
|
|
package gooxml
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2017-09-28 17:05:38 -05:00
|
|
|
"strings"
|
|
|
|
|
|
|
|
"baliance.com/gooxml/algo"
|
2017-09-03 12:01:55 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
// Common filenames used in zip packages.
|
|
|
|
const (
|
|
|
|
ContentTypesFilename = "[Content_Types].xml"
|
|
|
|
BaseRelsFilename = "_rels/.rels"
|
|
|
|
)
|
|
|
|
|
2017-09-08 17:06:52 -05:00
|
|
|
// DocType represents one of the three document types supported (docx/xlsx/pptx)
|
2017-09-03 12:01:55 -05:00
|
|
|
type DocType byte
|
|
|
|
|
2017-09-08 17:06:52 -05:00
|
|
|
// Document Type constants
|
2017-09-03 12:01:55 -05:00
|
|
|
const (
|
|
|
|
Unknown DocType = iota
|
|
|
|
DocTypeSpreadsheet
|
|
|
|
DocTypeDocument
|
|
|
|
DocTypePresentation
|
|
|
|
)
|
|
|
|
|
2017-09-28 17:05:38 -05:00
|
|
|
// RelativeFilename returns a filename relative to the source file referenced
|
|
|
|
// from a relationships file. Index is used in some cases for files which there
|
|
|
|
// may be more than one of (e.g. worksheets/drawings/charts)
|
|
|
|
func RelativeFilename(dt DocType, relToTyp, typ string, index int) string {
|
|
|
|
orig := AbsoluteFilename(dt, typ, index)
|
|
|
|
if relToTyp == "" {
|
|
|
|
return orig
|
|
|
|
}
|
2017-09-03 12:01:55 -05:00
|
|
|
|
2017-09-28 17:05:38 -05:00
|
|
|
relTo := AbsoluteFilename(dt, relToTyp, index)
|
|
|
|
relToSp := strings.Split(relTo, "/")
|
|
|
|
origSp := strings.Split(orig, "/")
|
2017-09-17 12:58:51 -05:00
|
|
|
|
2017-09-28 17:05:38 -05:00
|
|
|
// determine how many segments match
|
|
|
|
matching := 0
|
|
|
|
for i := 0; i < len(relToSp); i++ {
|
|
|
|
if relToSp[i] == origSp[i] {
|
|
|
|
matching++
|
2017-09-03 12:01:55 -05:00
|
|
|
}
|
2017-09-28 17:05:38 -05:00
|
|
|
if i+1 == len(origSp) {
|
|
|
|
break
|
2017-09-28 16:48:11 -05:00
|
|
|
}
|
2017-09-03 12:01:55 -05:00
|
|
|
}
|
2017-09-28 17:05:38 -05:00
|
|
|
relToSp = relToSp[matching:]
|
|
|
|
origSp = origSp[matching:]
|
|
|
|
nm := len(relToSp) - 1
|
|
|
|
if nm > 0 {
|
|
|
|
return algo.RepeatString("../", nm) + strings.Join(origSp, "/")
|
|
|
|
}
|
|
|
|
return strings.Join(origSp, "/")
|
2017-09-03 12:01:55 -05:00
|
|
|
}
|
|
|
|
|
2017-09-08 17:06:52 -05:00
|
|
|
// AbsoluteFilename returns the full path to a file from the root of the zip
|
|
|
|
// container. Index is used in some cases for files which there may be more than
|
|
|
|
// one of (e.g. worksheets/drawings/charts)
|
2017-09-03 12:01:55 -05:00
|
|
|
func AbsoluteFilename(dt DocType, typ string, index int) string {
|
|
|
|
switch typ {
|
|
|
|
case CorePropertiesType:
|
|
|
|
return "docProps/core.xml"
|
|
|
|
case ExtendedPropertiesType:
|
|
|
|
return "docProps/app.xml"
|
|
|
|
case ThumbnailType:
|
|
|
|
return "docProps/thumbnail.jpeg"
|
|
|
|
|
|
|
|
case OfficeDocumentType:
|
|
|
|
switch dt {
|
|
|
|
case DocTypeSpreadsheet:
|
|
|
|
return "xl/workbook.xml"
|
2017-09-08 17:06:52 -05:00
|
|
|
case DocTypeDocument:
|
|
|
|
return "word/document.xml"
|
2017-10-03 09:55:27 -05:00
|
|
|
case DocTypePresentation:
|
|
|
|
return "ppt/presentation.xml"
|
2017-09-03 12:01:55 -05:00
|
|
|
default:
|
2017-09-29 20:52:19 -05:00
|
|
|
Log("unsupported type %s pair and %v", typ, dt)
|
2017-09-03 12:01:55 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
case ThemeType, ThemeContentType:
|
|
|
|
switch dt {
|
|
|
|
case DocTypeSpreadsheet:
|
|
|
|
return fmt.Sprintf("xl/theme/theme%d.xml", index)
|
2017-09-08 17:06:52 -05:00
|
|
|
case DocTypeDocument:
|
|
|
|
return fmt.Sprintf("word/theme/theme%d.xml", index)
|
2017-10-03 09:55:27 -05:00
|
|
|
case DocTypePresentation:
|
|
|
|
return fmt.Sprintf("ppt/theme/theme%d.xml", index)
|
2017-09-03 12:01:55 -05:00
|
|
|
default:
|
2017-09-29 20:52:19 -05:00
|
|
|
Log("unsupported type %s pair and %v", typ, dt)
|
2017-09-03 12:01:55 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
case StylesType:
|
|
|
|
switch dt {
|
|
|
|
case DocTypeSpreadsheet:
|
|
|
|
return "xl/styles.xml"
|
2017-09-08 17:06:52 -05:00
|
|
|
case DocTypeDocument:
|
|
|
|
return "word/styles.xml"
|
2017-10-03 09:55:27 -05:00
|
|
|
case DocTypePresentation:
|
|
|
|
return "ppt/styles.xml"
|
2017-09-08 21:25:01 -05:00
|
|
|
default:
|
2017-09-29 20:52:19 -05:00
|
|
|
Log("unsupported type %s pair and %v", typ, dt)
|
2017-09-03 12:01:55 -05:00
|
|
|
}
|
|
|
|
|
2017-09-03 18:39:35 -05:00
|
|
|
case ChartType, ChartContentType:
|
2017-09-03 12:01:55 -05:00
|
|
|
switch dt {
|
|
|
|
case DocTypeSpreadsheet:
|
|
|
|
return fmt.Sprintf("xl/charts/chart%d.xml", index)
|
|
|
|
default:
|
2017-09-29 20:52:19 -05:00
|
|
|
Log("unsupported type %s pair and %v", typ, dt)
|
2017-09-03 12:01:55 -05:00
|
|
|
}
|
2017-09-17 12:58:51 -05:00
|
|
|
case TableType, TableContentType:
|
|
|
|
return fmt.Sprintf("xl/tables/table%d.xml", index)
|
2017-09-03 12:01:55 -05:00
|
|
|
|
2017-09-03 18:39:35 -05:00
|
|
|
case DrawingType, DrawingContentType:
|
2017-09-03 12:01:55 -05:00
|
|
|
switch dt {
|
|
|
|
case DocTypeSpreadsheet:
|
|
|
|
return fmt.Sprintf("xl/drawings/drawing%d.xml", index)
|
|
|
|
default:
|
2017-09-29 20:52:19 -05:00
|
|
|
Log("unsupported type %s pair and %v", typ, dt)
|
2017-09-03 12:01:55 -05:00
|
|
|
}
|
2017-09-08 21:25:01 -05:00
|
|
|
|
|
|
|
case CommentsType, CommentsContentType:
|
|
|
|
switch dt {
|
|
|
|
case DocTypeSpreadsheet:
|
|
|
|
return fmt.Sprintf("xl/comments%d.xml", index)
|
|
|
|
default:
|
2017-09-29 20:52:19 -05:00
|
|
|
Log("unsupported type %s pair and %v", typ, dt)
|
2017-09-08 21:25:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
case VMLDrawingType, VMLDrawingContentType:
|
|
|
|
switch dt {
|
|
|
|
case DocTypeSpreadsheet:
|
|
|
|
return fmt.Sprintf("xl/drawings/vmlDrawing%d.vml", index)
|
|
|
|
default:
|
2017-09-29 20:52:19 -05:00
|
|
|
Log("unsupported type %s pair and %v", typ, dt)
|
2017-09-08 21:25:01 -05:00
|
|
|
}
|
|
|
|
|
2017-09-28 17:05:38 -05:00
|
|
|
case ImageType:
|
|
|
|
switch dt {
|
|
|
|
case DocTypeDocument:
|
|
|
|
return fmt.Sprintf("word/media/image%d.png", index)
|
|
|
|
case DocTypeSpreadsheet:
|
|
|
|
return fmt.Sprintf("xl/media/image%d.png", index)
|
2017-10-03 09:55:27 -05:00
|
|
|
case DocTypePresentation:
|
|
|
|
return fmt.Sprintf("ppt/media/image%d.png", index)
|
2017-09-28 17:05:38 -05:00
|
|
|
default:
|
2017-09-29 20:52:19 -05:00
|
|
|
Log("unsupported type %s pair and %v", typ, dt)
|
2017-09-28 17:05:38 -05:00
|
|
|
}
|
2017-09-03 12:01:55 -05:00
|
|
|
// SML
|
|
|
|
case WorksheetType, WorksheetContentType:
|
|
|
|
return fmt.Sprintf("xl/worksheets/sheet%d.xml", index)
|
|
|
|
case SharedStingsType, SharedStringsContentType:
|
|
|
|
return "xl/sharedStrings.xml"
|
|
|
|
|
2017-10-03 09:55:27 -05:00
|
|
|
// WML
|
2017-09-08 17:06:52 -05:00
|
|
|
case FontTableType:
|
|
|
|
return "word/fontTable.xml"
|
|
|
|
case EndNotesType:
|
|
|
|
return "word/endnotes.xml"
|
|
|
|
case FootNotesType:
|
|
|
|
return "word/footnotes.xml"
|
|
|
|
case NumberingType:
|
|
|
|
return "word/numbering.xml"
|
|
|
|
case WebSettingsType:
|
|
|
|
return "word/webSettings.xml"
|
|
|
|
case SettingsType:
|
|
|
|
return "word/settings.xml"
|
|
|
|
case HeaderType:
|
|
|
|
return fmt.Sprintf("word/header%d.xml", index)
|
|
|
|
case FooterType:
|
|
|
|
return fmt.Sprintf("word/footer%d.xml", index)
|
|
|
|
|
2017-10-03 09:55:27 -05:00
|
|
|
// PML
|
|
|
|
case SlideType:
|
|
|
|
return fmt.Sprintf("ppt/slides/slide%d.xml", index)
|
|
|
|
case SlideLayoutType:
|
|
|
|
return fmt.Sprintf("ppt/slideLayouts/slideLayout%d.xml", index)
|
|
|
|
case SlideMasterType:
|
|
|
|
return fmt.Sprintf("ppt/slideMasters/slideMaster%d.xml", index)
|
|
|
|
|
2017-09-03 12:01:55 -05:00
|
|
|
default:
|
2017-09-29 20:52:19 -05:00
|
|
|
Log("unsupported type %s", typ)
|
2017-09-03 12:01:55 -05:00
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|