Document extractor service (#15665)
* Document extractor service * Fixing vendor modules * Addressing PR Review comments * Some small simplifications * Fixing a linter complain * simplifying a bit the code using package variables Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
04ef5c682e
Коммит
8d5be2d657
3
vendor/code.sajari.com/docconv/.gitignore
сгенерированный
поставляемый
Обычный файл
3
vendor/code.sajari.com/docconv/.gitignore
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,3 @@
|
||||
|
||||
sajari-convert
|
||||
*tests/
|
||||
10
vendor/code.sajari.com/docconv/.travis.yml
сгенерированный
поставляемый
Обычный файл
10
vendor/code.sajari.com/docconv/.travis.yml
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,10 @@
|
||||
sudo: false
|
||||
language: go
|
||||
go:
|
||||
- "1.13"
|
||||
- "1.14"
|
||||
- tip
|
||||
go_import_path: code.sajari.com/docconv
|
||||
notifications:
|
||||
email:
|
||||
- infra@sajari.com
|
||||
21
vendor/code.sajari.com/docconv/LICENSE
сгенерированный
поставляемый
Обычный файл
21
vendor/code.sajari.com/docconv/LICENSE
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Sajari Pty Ltd
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
139
vendor/code.sajari.com/docconv/README.md
сгенерированный
поставляемый
Обычный файл
139
vendor/code.sajari.com/docconv/README.md
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,139 @@
|
||||
# docconv
|
||||
|
||||
[](https://godoc.org/code.sajari.com/docconv)
|
||||
[](https://travis-ci.org/sajari/docconv)
|
||||
|
||||
A Go wrapper library to convert PDF, DOC, DOCX, XML, HTML, RTF, ODT, Pages documents and images (see optional dependencies below) to plain text.
|
||||
|
||||
> **Note for returning users:** the Go import path for this package been moved to `code.sajari.com/docconv`.
|
||||
|
||||
## Installation
|
||||
|
||||
If you haven't setup Go before, you first need to [install Go](https://golang.org/doc/install).
|
||||
|
||||
To fetch and build the code:
|
||||
|
||||
$ go get code.sajari.com/docconv/...
|
||||
|
||||
This will also build the command line tool `docd` into `$GOPATH/bin`. Make sure that `$GOPATH/bin` is in your `PATH` environment variable.
|
||||
|
||||
## Dependencies
|
||||
|
||||
tidy, wv, popplerutils, unrtf, https://github.com/JalfResi/justext
|
||||
|
||||
Example install of dependencies (not all systems):
|
||||
|
||||
$ sudo apt-get install poppler-utils wv unrtf tidy
|
||||
$ go get github.com/JalfResi/justext
|
||||
|
||||
### Optional dependencies
|
||||
|
||||
To add image support to the `docconv` library you first need to [install and build gosseract](https://github.com/otiai10/gosseract/tree/v2.2.4).
|
||||
|
||||
Now you can add `-tags ocr` to any `go` command when building/fetching/testing `docconv` to include support for processing images:
|
||||
|
||||
$ go get -tags ocr code.sajari.com/docconv/...
|
||||
|
||||
This may complain on macOS, which you can fix by installing [tesseract](https://tesseract-ocr.github.io) via brew:
|
||||
|
||||
$ brew install tesseract
|
||||
|
||||
## docd tool
|
||||
|
||||
The `docd` tool runs as either:
|
||||
|
||||
1. a service on port 8888 (by default)
|
||||
|
||||
Documents can be sent as a multipart POST request and the plain text (body) and meta information are then returned as a JSON object.
|
||||
|
||||
2. a service exposed from within a Docker container
|
||||
|
||||
This also runs as a service, but from within a Docker container. There are three build scripts:
|
||||
|
||||
- [./docd/debian.sh](./docd/debian.sh)
|
||||
- [./docd/alpine.sh](./docd/alpine.sh)
|
||||
- [./docd/appengine.sh](./docd/appengine.sh)
|
||||
|
||||
The `debian` version uses the Debian package repository which can vary with builds. The `alpine` version uses a very cut down Linux distribution to produce a container ~40MB. It also locks the dependency versions for consistency, but may miss out on future updates. The `appengine` version is a flex based custom runtime for Google Cloud.
|
||||
|
||||
3. via the command line.
|
||||
|
||||
Documents can be sent as an argument, e.g.
|
||||
|
||||
$ docd -input document.pdf
|
||||
|
||||
### Optional flags
|
||||
|
||||
- `addr` - the bind address for the HTTP server, default is ":8888"
|
||||
- `log-level`
|
||||
- 0: errors & critical info
|
||||
- 1: inclues 0 and logs each request as well
|
||||
- 2: include 1 and logs the response payloads
|
||||
- `readability-length-low` - sets the readability length low if the ?readability=1 parameter is set
|
||||
- `readability-length-high` - sets the readability length high if the ?readability=1 parameter is set
|
||||
- `readability-stopwords-low` - sets the readability stopwords low if the ?readability=1 parameter is set
|
||||
- `readability-stopwords-high` - sets the readability stopwords high if the ?readability=1 parameter is set
|
||||
- `readability-max-link-density` - sets the readability max link density if the ?readability=1 parameter is set
|
||||
- `readability-max-heading-distance` - sets the readability max heading distance if the ?readability=1 parameter is set
|
||||
- `readability-use-classes` - comma separated list of readability classes to use if the ?readability=1 parameter is set
|
||||
|
||||
### How to start the service
|
||||
|
||||
$ # This will only log errors and critical info
|
||||
$ docd -log-level 0
|
||||
|
||||
$ # This will run on port 8000 and log each request
|
||||
$ docd -addr :8000 -log-level 1
|
||||
|
||||
## Example usage (code)
|
||||
|
||||
Some basic code is shown below, but normally you would accept the file by HTTP or open it from the file system.
|
||||
|
||||
This should be enough to get you started though.
|
||||
|
||||
### Use case 1: run locally
|
||||
|
||||
> Note: this assumes you have the [dependencies](#dependencies) installed.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"code.sajari.com/docconv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res, err := docconv.ConvertPath("your-file.pdf")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(res)
|
||||
}
|
||||
```
|
||||
|
||||
### Use case 2: request over the network
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"code.sajari.com/docconv/client"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Create a new client, using the default endpoint (localhost:8888)
|
||||
c := client.New()
|
||||
|
||||
res, err := client.ConvertPath(c, "your-file.pdf")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(res)
|
||||
}
|
||||
```
|
||||
94
vendor/code.sajari.com/docconv/doc.go
сгенерированный
поставляемый
Обычный файл
94
vendor/code.sajari.com/docconv/doc.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,94 @@
|
||||
package docconv
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ConvertDoc converts an MS Word .doc to text.
|
||||
func ConvertDoc(r io.Reader) (string, map[string]string, error) {
|
||||
f, err := NewLocalFile(r)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("error creating local file: %v", err)
|
||||
}
|
||||
defer f.Done()
|
||||
|
||||
// Meta data
|
||||
mc := make(chan map[string]string, 1)
|
||||
go func() {
|
||||
meta := make(map[string]string)
|
||||
metaStr, err := exec.Command("wvSummary", f.Name()).Output()
|
||||
if err != nil {
|
||||
// TODO: Remove this.
|
||||
log.Println("wvSummary:", err)
|
||||
}
|
||||
|
||||
// Parse meta output
|
||||
for _, line := range strings.Split(string(metaStr), "\n") {
|
||||
if parts := strings.SplitN(line, "=", 2); len(parts) > 1 {
|
||||
meta[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
|
||||
}
|
||||
}
|
||||
|
||||
// Convert parsed meta
|
||||
if tmp, ok := meta["Last Modified"]; ok {
|
||||
if t, err := time.Parse(time.RFC3339, tmp); err == nil {
|
||||
meta["ModifiedDate"] = fmt.Sprintf("%d", t.Unix())
|
||||
}
|
||||
}
|
||||
if tmp, ok := meta["Created"]; ok {
|
||||
if t, err := time.Parse(time.RFC3339, tmp); err == nil {
|
||||
meta["CreatedDate"] = fmt.Sprintf("%d", t.Unix())
|
||||
}
|
||||
}
|
||||
|
||||
mc <- meta
|
||||
}()
|
||||
|
||||
// Document body
|
||||
bc := make(chan string, 1)
|
||||
go func() {
|
||||
|
||||
// Save output to a file
|
||||
outputFile, err := ioutil.TempFile("/tmp", "sajari-convert-")
|
||||
if err != nil {
|
||||
// TODO: Remove this.
|
||||
log.Println("TempFile Out:", err)
|
||||
return
|
||||
}
|
||||
defer os.Remove(outputFile.Name())
|
||||
|
||||
err = exec.Command("wvText", f.Name(), outputFile.Name()).Run()
|
||||
if err != nil {
|
||||
// TODO: Remove this.
|
||||
log.Println("wvText:", err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
_, err = buf.ReadFrom(outputFile)
|
||||
if err != nil {
|
||||
// TODO: Remove this.
|
||||
log.Println("wvText:", err)
|
||||
}
|
||||
|
||||
bc <- buf.String()
|
||||
}()
|
||||
|
||||
// TODO: Should errors in either of the above Goroutines stop things from progressing?
|
||||
body := <-bc
|
||||
meta := <-mc
|
||||
|
||||
// TODO: Check for errors instead of len(body) == 0?
|
||||
if len(body) == 0 {
|
||||
f.Seek(0, 0)
|
||||
return ConvertDocx(f)
|
||||
}
|
||||
return body, meta, nil
|
||||
}
|
||||
145
vendor/code.sajari.com/docconv/docconv.go
сгенерированный
поставляемый
Обычный файл
145
vendor/code.sajari.com/docconv/docconv.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,145 @@
|
||||
package docconv // import "code.sajari.com/docconv"
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Response payload sent back to the requestor
|
||||
type Response struct {
|
||||
Body string `json:"body"`
|
||||
Meta map[string]string `json:"meta"`
|
||||
MSecs uint32 `json:"msecs"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// MimeTypeByExtension returns a mimetype for the given extension, or
|
||||
// application/octet-stream if none can be determined.
|
||||
func MimeTypeByExtension(filename string) string {
|
||||
switch strings.ToLower(path.Ext(filename)) {
|
||||
case ".doc":
|
||||
return "application/msword"
|
||||
case ".docx":
|
||||
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
||||
case ".odt":
|
||||
return "application/vnd.oasis.opendocument.text"
|
||||
case ".pages":
|
||||
return "application/vnd.apple.pages"
|
||||
case ".pdf":
|
||||
return "application/pdf"
|
||||
case ".pptx":
|
||||
return "application/vnd.openxmlformats-officedocument.presentationml.presentation"
|
||||
case ".rtf":
|
||||
return "application/rtf"
|
||||
case ".xml":
|
||||
return "text/xml"
|
||||
case ".xhtml", ".html", ".htm":
|
||||
return "text/html"
|
||||
case ".jpg", ".jpeg", ".jpe", ".jfif", ".jfif-tbnl":
|
||||
return "image/jpeg"
|
||||
case ".png":
|
||||
return "image/png"
|
||||
case ".tif":
|
||||
return "image/tif"
|
||||
case ".tiff":
|
||||
return "image/tiff"
|
||||
case ".txt":
|
||||
return "text/plain"
|
||||
}
|
||||
return "application/octet-stream"
|
||||
}
|
||||
|
||||
// Convert a file to plain text.
|
||||
func Convert(r io.Reader, mimeType string, readability bool) (*Response, error) {
|
||||
start := time.Now()
|
||||
|
||||
var body string
|
||||
var meta map[string]string
|
||||
var err error
|
||||
switch mimeType {
|
||||
case "application/msword", "application/vnd.ms-word":
|
||||
body, meta, err = ConvertDoc(r)
|
||||
|
||||
case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
|
||||
body, meta, err = ConvertDocx(r)
|
||||
|
||||
case "application/vnd.openxmlformats-officedocument.presentationml.presentation":
|
||||
body, meta, err = ConvertPptx(r)
|
||||
|
||||
case "application/vnd.oasis.opendocument.text":
|
||||
body, meta, err = ConvertODT(r)
|
||||
|
||||
case "application/vnd.apple.pages", "application/x-iwork-pages-sffpages":
|
||||
body, meta, err = ConvertPages(r)
|
||||
|
||||
case "application/pdf":
|
||||
body, meta, err = ConvertPDF(r)
|
||||
|
||||
case "application/rtf", "application/x-rtf", "text/rtf", "text/richtext":
|
||||
body, meta, err = ConvertRTF(r)
|
||||
|
||||
case "text/html":
|
||||
body, meta, err = ConvertHTML(r, readability)
|
||||
|
||||
case "text/url":
|
||||
body, meta, err = ConvertURL(r, readability)
|
||||
|
||||
case "text/xml", "application/xml":
|
||||
body, meta, err = ConvertXML(r)
|
||||
|
||||
case "image/jpeg", "image/png", "image/tif", "image/tiff":
|
||||
body, meta, err = ConvertImage(r)
|
||||
|
||||
case "text/plain":
|
||||
var b []byte
|
||||
b, err = ioutil.ReadAll(r)
|
||||
body = string(b)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error converting data: %v", err)
|
||||
}
|
||||
|
||||
return &Response{
|
||||
Body: strings.TrimSpace(body),
|
||||
Meta: meta,
|
||||
MSecs: uint32(time.Since(start) / time.Millisecond),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ConvertPath converts a local path to text.
|
||||
func ConvertPath(path string) (*Response, error) {
|
||||
mimeType := MimeTypeByExtension(path)
|
||||
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return Convert(f, mimeType, true)
|
||||
}
|
||||
|
||||
// ConvertPathReadability converts a local path to text, with the given readability
|
||||
// option.
|
||||
func ConvertPathReadability(path string, readability bool) ([]byte, error) {
|
||||
mimeType := MimeTypeByExtension(path)
|
||||
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
data, err := Convert(f, mimeType, readability)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(data)
|
||||
}
|
||||
155
vendor/code.sajari.com/docconv/docx.go
сгенерированный
поставляемый
Обычный файл
155
vendor/code.sajari.com/docconv/docx.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,155 @@
|
||||
package docconv
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
type typeOverride struct {
|
||||
XMLName xml.Name `xml:"Override"`
|
||||
ContentType string `xml:"ContentType,attr"`
|
||||
PartName string `xml:"PartName,attr"`
|
||||
}
|
||||
|
||||
type contentTypeDefinition struct {
|
||||
XMLName xml.Name `xml:"Types"`
|
||||
Overrides []typeOverride `xml:"Override"`
|
||||
}
|
||||
|
||||
// ConvertDocx converts an MS Word docx file to text.
|
||||
func ConvertDocx(r io.Reader) (string, map[string]string, error) {
|
||||
var size int64
|
||||
|
||||
// Common case: if the reader is a file (or trivial wrapper), avoid
|
||||
// loading it all into memory.
|
||||
var ra io.ReaderAt
|
||||
if f, ok := r.(interface {
|
||||
io.ReaderAt
|
||||
Stat() (os.FileInfo, error)
|
||||
}); ok {
|
||||
si, err := f.Stat()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
size = si.Size()
|
||||
ra = f
|
||||
} else {
|
||||
b, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return "", nil, nil
|
||||
}
|
||||
size = int64(len(b))
|
||||
ra = bytes.NewReader(b)
|
||||
}
|
||||
|
||||
zr, err := zip.NewReader(ra, size)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("error unzipping data: %v", err)
|
||||
}
|
||||
|
||||
zipFiles := mapZipFiles(zr.File)
|
||||
|
||||
contentTypeDefinition, err := getContentTypeDefinition(zipFiles["[Content_Types].xml"])
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
meta := make(map[string]string)
|
||||
var textHeader, textBody, textFooter string
|
||||
for _, override := range contentTypeDefinition.Overrides {
|
||||
f := zipFiles[override.PartName]
|
||||
|
||||
switch {
|
||||
case override.ContentType == "application/vnd.openxmlformats-package.core-properties+xml":
|
||||
rc, err := f.Open()
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("error opening '%v' from archive: %v", f.Name, err)
|
||||
}
|
||||
defer rc.Close()
|
||||
|
||||
meta, err = XMLToMap(rc)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("error parsing '%v': %v", f.Name, err)
|
||||
}
|
||||
|
||||
if tmp, ok := meta["modified"]; ok {
|
||||
if t, err := time.Parse(time.RFC3339, tmp); err == nil {
|
||||
meta["ModifiedDate"] = fmt.Sprintf("%d", t.Unix())
|
||||
}
|
||||
}
|
||||
if tmp, ok := meta["created"]; ok {
|
||||
if t, err := time.Parse(time.RFC3339, tmp); err == nil {
|
||||
meta["CreatedDate"] = fmt.Sprintf("%d", t.Unix())
|
||||
}
|
||||
}
|
||||
case override.ContentType == "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml":
|
||||
body, err := parseDocxText(f)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
textBody += body + "\n"
|
||||
case override.ContentType == "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml":
|
||||
footer, err := parseDocxText(f)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
textFooter += footer + "\n"
|
||||
case override.ContentType == "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml":
|
||||
header, err := parseDocxText(f)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
textHeader += header + "\n"
|
||||
}
|
||||
|
||||
}
|
||||
return textHeader + "\n" + textBody + "\n" + textFooter, meta, nil
|
||||
}
|
||||
|
||||
func getContentTypeDefinition(zf *zip.File) (*contentTypeDefinition, error) {
|
||||
f, err := zf.Open()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
x := &contentTypeDefinition{}
|
||||
if err := xml.NewDecoder(f).Decode(x); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
func mapZipFiles(files []*zip.File) map[string]*zip.File {
|
||||
filesMap := make(map[string]*zip.File, 2*len(files))
|
||||
for _, f := range files {
|
||||
filesMap[f.Name] = f
|
||||
filesMap["/"+f.Name] = f
|
||||
}
|
||||
return filesMap
|
||||
}
|
||||
|
||||
func parseDocxText(f *zip.File) (string, error) {
|
||||
r, err := f.Open()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error opening '%v' from archive: %v", f.Name, err)
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
text, err := DocxXMLToText(r)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error parsing '%v': %v", f.Name, err)
|
||||
}
|
||||
return text, nil
|
||||
}
|
||||
|
||||
// DocxXMLToText converts Docx XML into plain text.
|
||||
func DocxXMLToText(r io.Reader) (string, error) {
|
||||
return XMLToText(r, []string{"br", "p", "tab"}, []string{"instrText", "script"}, true)
|
||||
}
|
||||
21
vendor/code.sajari.com/docconv/go.mod
сгенерированный
поставляемый
Обычный файл
21
vendor/code.sajari.com/docconv/go.mod
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,21 @@
|
||||
module code.sajari.com/docconv
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/JalfResi/justext v0.0.0-20170829062021-c0282dea7198
|
||||
github.com/PuerkitoBio/goquery v1.5.1 // indirect
|
||||
github.com/advancedlogic/GoOse v0.0.0-20191112112754-e742535969c1
|
||||
github.com/andybalholm/cascadia v1.2.0 // indirect
|
||||
github.com/araddon/dateparse v0.0.0-20200409225146-d820a6159ab1 // indirect
|
||||
github.com/go-resty/resty/v2 v2.3.0 // indirect
|
||||
github.com/golang/protobuf v1.4.2
|
||||
github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7 // indirect
|
||||
github.com/levigross/exp-html v0.0.0-20120902181939-8df60c69a8f5 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.4 // indirect
|
||||
github.com/otiai10/gosseract/v2 v2.2.4
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9
|
||||
golang.org/x/text v0.3.2 // indirect
|
||||
)
|
||||
99
vendor/code.sajari.com/docconv/go.sum
сгенерированный
поставляемый
Обычный файл
99
vendor/code.sajari.com/docconv/go.sum
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,99 @@
|
||||
github.com/JalfResi/justext v0.0.0-20170829062021-c0282dea7198 h1:8P+AjBhGByCuCX2zTkAf6UY+dj0JczX+t6cSdCSyvfw=
|
||||
github.com/JalfResi/justext v0.0.0-20170829062021-c0282dea7198/go.mod h1:0SURuH1rsE8aVWvutuMZghRNrNrYEUzibzJfhEYR8L0=
|
||||
github.com/PuerkitoBio/goquery v1.4.1 h1:smcIRGdYm/w7JSbcdeLHEMzxmsBQvl8lhf0dSw2nzMI=
|
||||
github.com/PuerkitoBio/goquery v1.4.1/go.mod h1:T9ezsOHcCrDCgA8aF1Cqr3sSYbO/xgdy8/R/XiIMAhA=
|
||||
github.com/PuerkitoBio/goquery v1.5.1 h1:PSPBGne8NIUWw+/7vFBV+kG2J/5MOjbzc7154OaKCSE=
|
||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||
github.com/advancedlogic/GoOse v0.0.0-20191112112754-e742535969c1 h1:d0Ct1dZwgwMO0Llf81Eu+Lyj6kwqXdqHP/WsSkEria0=
|
||||
github.com/advancedlogic/GoOse v0.0.0-20191112112754-e742535969c1/go.mod h1:f3HCSN1fBWjcpGtXyM119MJgeQl838v6so/PQOqvE1w=
|
||||
github.com/andybalholm/cascadia v1.0.0 h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRySc45o=
|
||||
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/andybalholm/cascadia v1.2.0 h1:vuRCkM5Ozh/BfmsaTm26kbjm0mIOM3yS5Ek/F5h18aE=
|
||||
github.com/andybalholm/cascadia v1.2.0/go.mod h1:YCyR8vOZT9aZ1CHEd8ap0gMVm2aFgxBp0T0eFw1RUQY=
|
||||
github.com/araddon/dateparse v0.0.0-20180729174819-cfd92a431d0e h1:s05JG2GwtJMHaPcXDpo4V35TFgyYZzNsmBlSkHPEbeg=
|
||||
github.com/araddon/dateparse v0.0.0-20180729174819-cfd92a431d0e/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI=
|
||||
github.com/araddon/dateparse v0.0.0-20200409225146-d820a6159ab1 h1:TEBmxO80TM04L8IuMWk77SGL1HomBmKTdzdJLLWznxI=
|
||||
github.com/araddon/dateparse v0.0.0-20200409225146-d820a6159ab1/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA=
|
||||
github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI=
|
||||
github.com/gigawattio/window v0.0.0-20180317192513-0f5467e35573 h1:u8AQ9bPa9oC+8/A/jlWouakhIvkFfuxgIIRjiy8av7I=
|
||||
github.com/gigawattio/window v0.0.0-20180317192513-0f5467e35573/go.mod h1:eBvb3i++NHDH4Ugo9qCvMw8t0mTSctaEa5blJbWcNxs=
|
||||
github.com/go-resty/resty/v2 v2.0.0 h1:9Nq/U+V4xsoDnDa/iTrABDWUCuk3Ne92XFHPe6dKWUc=
|
||||
github.com/go-resty/resty/v2 v2.0.0/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8=
|
||||
github.com/go-resty/resty/v2 v2.3.0 h1:JOOeAvjSlapTT92p8xiS19Zxev1neGikoHsXJeOq8So=
|
||||
github.com/go-resty/resty/v2 v2.3.0/go.mod h1:UpN9CgLZNsv4e9XG50UU8xdI0F43UQ4HmxLBDwaroHU=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0 h1:xqgexXAGQgY3HAjNPSaCqn5Aahbo5TKsmhp8VRfr1iQ=
|
||||
github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
|
||||
github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7 h1:g0fAGBisHaEQ0TRq1iBvemFRf+8AEWEmBESSiWB3Vsc=
|
||||
github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
|
||||
github.com/levigross/exp-html v0.0.0-20120902181939-8df60c69a8f5 h1:W7p+m/AECTL3s/YR5RpQ4hz5SjNeKzZBl1q36ws12s0=
|
||||
github.com/levigross/exp-html v0.0.0-20120902181939-8df60c69a8f5/go.mod h1:QMe2wuKJ0o7zIVE8AqiT8rd8epmm6WDIZ2wyuBqYPzM=
|
||||
github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4=
|
||||
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84 h1:fiKJgB4JDUd43CApkmCeTSQlWjtTtABrU2qsgbuP0BI=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
|
||||
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
|
||||
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95 h1:+OLn68pqasWca0z5ryit9KGfp3sUsW4Lqg32iRMJyzs=
|
||||
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
|
||||
github.com/otiai10/gosseract/v2 v2.2.4 h1:h/PV+oJqke8q2Ccw9bjpMBWfd7N2vtGDCUcihZj3nRo=
|
||||
github.com/otiai10/gosseract/v2 v2.2.4/go.mod h1:ahOp/kHojnOMGv1RaUnR0jwY5JVa6BYKhYAS8nbMLSo=
|
||||
github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc=
|
||||
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/simplereach/timeutils v1.2.0/go.mod h1:VVbQDfN/FHRZa1LSqcwo4kNZ62OOyqLLGQKYB3pB0Q8=
|
||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo=
|
||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM=
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
191
vendor/code.sajari.com/docconv/html.go
сгенерированный
поставляемый
Обычный файл
191
vendor/code.sajari.com/docconv/html.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,191 @@
|
||||
// +build !appengine
|
||||
|
||||
package docconv
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/net/html"
|
||||
|
||||
"github.com/JalfResi/justext"
|
||||
)
|
||||
|
||||
// ConvertHTML converts HTML into text.
|
||||
func ConvertHTML(r io.Reader, readability bool) (string, map[string]string, error) {
|
||||
meta := make(map[string]string)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
_, err := buf.ReadFrom(r)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
cleanXML, err := Tidy(buf, false)
|
||||
if err != nil {
|
||||
log.Println("Tidy:", err)
|
||||
// Tidy failed, so we now manually tokenize instead
|
||||
clean := cleanHTML(buf, true)
|
||||
cleanXML = []byte(clean)
|
||||
// TODO: remove this log
|
||||
log.Println("Cleaned HTML using Golang tokenizer")
|
||||
}
|
||||
|
||||
if readability {
|
||||
cleanXML = HTMLReadability(bytes.NewReader(cleanXML))
|
||||
}
|
||||
return HTMLToText(bytes.NewReader(cleanXML)), meta, nil
|
||||
}
|
||||
|
||||
var acceptedHTMLTags = [...]string{
|
||||
"div", "p", "br", "span", "body", "head", "html", "ul", "ol", "li", "dl", "dt", "dd", "a", "form", "article",
|
||||
"section", "table", "tr", "td", "tbody", "thead", "th", "tfoot", "col", "colgroup", "caption", "form", "input",
|
||||
"title", "h1", "h2", "h3", "h4", "h5", "h6", "meta", "strong", "cite", "em", "address", "abbr", "acronym",
|
||||
"blockquote", "q", "pre", "samp", "select", "fieldset", "legend", "button", "option", "textarea", "label",
|
||||
}
|
||||
|
||||
// Tests for known friendly HTML parameters that tidy is unlikely to choke on
|
||||
func acceptedHTMLTag(tagName string) bool {
|
||||
for _, tag := range acceptedHTMLTags {
|
||||
if tag == tagName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Removes scripts, comments, styles and parameters from HTML.
|
||||
// Also removes made up tags, e.g. <fb:like>
|
||||
// Can keep head elements or not. Typically not much in there.
|
||||
func cleanHTML(r io.Reader, all bool) string {
|
||||
output := ""
|
||||
if !all {
|
||||
output = "<html><head></head>"
|
||||
}
|
||||
mainSection := false
|
||||
junkSection := false
|
||||
|
||||
d := html.NewTokenizer(r)
|
||||
for {
|
||||
// token type
|
||||
tokenType := d.Next()
|
||||
if tokenType == html.ErrorToken {
|
||||
return output
|
||||
}
|
||||
token := d.Token()
|
||||
|
||||
switch tokenType {
|
||||
case html.StartTagToken: // <tag>
|
||||
if token.Data == "body" || (token.Data == "html" && all) {
|
||||
mainSection = true
|
||||
}
|
||||
if !acceptedHTMLTag(token.Data) {
|
||||
junkSection = true
|
||||
}
|
||||
|
||||
if !junkSection && mainSection {
|
||||
output += "<" + token.Data + ">"
|
||||
}
|
||||
|
||||
case html.TextToken: // text between start and end tag
|
||||
if !junkSection && mainSection {
|
||||
output += token.Data
|
||||
}
|
||||
|
||||
case html.EndTagToken: // </tag>
|
||||
if !junkSection && mainSection {
|
||||
output += "</" + token.Data + ">"
|
||||
}
|
||||
if !acceptedHTMLTag(token.Data) {
|
||||
junkSection = false
|
||||
}
|
||||
|
||||
case html.SelfClosingTagToken: // <tag/>
|
||||
if !junkSection && mainSection {
|
||||
output += "<" + token.Data + " />" // TODO: Can probably keep attributes from the meta tags
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HTMLReadabilityOptions is a type which defines parameters that are passed to the justext package.
|
||||
// TODO: Improve this!
|
||||
type HTMLReadabilityOptions struct {
|
||||
LengthLow int
|
||||
LengthHigh int
|
||||
StopwordsLow float64
|
||||
StopwordsHigh float64
|
||||
MaxLinkDensity float64
|
||||
MaxHeadingDistance int
|
||||
ReadabilityUseClasses string
|
||||
}
|
||||
|
||||
// HTMLReadabilityOptionsValues are the global settings used for HTMLReadability.
|
||||
// TODO: Remove this from global state.
|
||||
var HTMLReadabilityOptionsValues HTMLReadabilityOptions
|
||||
|
||||
// HTMLReadability extracts the readable text in an HTML document
|
||||
func HTMLReadability(r io.Reader) []byte {
|
||||
jr := justext.NewReader(r)
|
||||
|
||||
// TODO: Improve this!
|
||||
jr.Stoplist = readabilityStopList
|
||||
jr.LengthLow = HTMLReadabilityOptionsValues.LengthLow
|
||||
jr.LengthHigh = HTMLReadabilityOptionsValues.LengthHigh
|
||||
jr.StopwordsLow = HTMLReadabilityOptionsValues.StopwordsLow
|
||||
jr.StopwordsHigh = HTMLReadabilityOptionsValues.StopwordsHigh
|
||||
jr.MaxLinkDensity = HTMLReadabilityOptionsValues.MaxLinkDensity
|
||||
jr.MaxHeadingDistance = HTMLReadabilityOptionsValues.MaxHeadingDistance
|
||||
|
||||
paragraphSet, err := jr.ReadAll()
|
||||
if err != nil {
|
||||
log.Println("Justext:", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
useClasses := strings.SplitN(HTMLReadabilityOptionsValues.ReadabilityUseClasses, ",", 10)
|
||||
|
||||
output := ""
|
||||
for _, paragraph := range paragraphSet {
|
||||
for _, class := range useClasses {
|
||||
if paragraph.CfClass == class {
|
||||
output += paragraph.Text + "\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return []byte(output)
|
||||
}
|
||||
|
||||
// HTMLToText converts HTML to plain text.
|
||||
func HTMLToText(input io.Reader) string {
|
||||
text, _ := XMLToText(input, []string{"br", "p", "h1", "h2", "h3", "h4"}, []string{}, false)
|
||||
return text
|
||||
}
|
||||
|
||||
var readabilityStopList = map[string]bool{"and": true, "the": true, "a": true, "about": true, "above": true, "across": true, "after": true, "afterwards": true, "again": true, "against": true, "all": true, "almost": true, "alone": true,
|
||||
"along": true, "already": true, "also": true, "although": true, "always": true, "am": true, "among": true, "amongst": true, "amoungst": true, "amount": true, "an": true, "another": true, "any": true,
|
||||
"anyhow": true, "anyone": true, "anything": true, "anyway": true, "anywhere": true, "are": true, "around": true, "as": true, "at": true, "back": true, "be": true, "became": true, "because": true,
|
||||
"become": true, "becomes": true, "becoming": true, "been": true, "before": true, "beforehand": true, "behind": true, "being": true, "below": true, "beside": true, "besides": true, "between": true,
|
||||
"beyond": true, "both": true, "bottom": true, "but": true, "by": true, "can": true, "cannot": true, "cant": true, "co": true, "con": true, "could": true, "couldnt": true, "cry": true,
|
||||
"de": true, "describe": true, "detail": true, "do": true, "done": true, "down": true, "due": true, "during": true, "each": true, "eg": true, "eight": true, "either": true, "eleven": true, "else": true,
|
||||
"elsewhere": true, "empty": true, "enough": true, "etc": true, "even": true, "ever": true, "every": true, "everyone": true, "everything": true, "everywhere": true, "except": true, "few": true,
|
||||
"fifteen": true, "fify": true, "fill": true, "find": true, "fire": true, "first": true, "five": true, "for": true, "former": true, "formerly": true, "forty": true, "found": true, "four": true, "from": true,
|
||||
"front": true, "full": true, "further": true, "get": true, "give": true, "go": true, "had": true, "has": true, "hasnt": true, "have": true, "he": true, "hence": true, "her": true, "here": true, "hereafter": true,
|
||||
"hereby": true, "herein": true, "hereupon": true, "hers": true, "herself": true, "him": true, "himself": true, "his": true, "how": true, "however": true, "hundred": true, "ie": true, "if": true, "in": true,
|
||||
"inc": true, "indeed": true, "interest": true, "into": true, "is": true, "it": true, "its": true, "itself": true, "keep": true, "last": true, "latter": true, "latterly": true, "least": true, "less": true,
|
||||
"ltd": true, "made": true, "many": true, "may": true, "me": true, "meanwhile": true, "might": true, "mill": true, "mine": true, "more": true, "moreover": true, "most": true, "mostly": true, "move": true,
|
||||
"much": true, "must": true, "my": true, "myself": true, "name": true, "namely": true, "neither": true, "never": true, "nevertheless": true, "next": true, "nine": true, "no": true, "nobody": true,
|
||||
"none": true, "noone": true, "nor": true, "not": true, "nothing": true, "now": true, "nowhere": true, "of": true, "off": true, "often": true, "on": true, "once": true, "one": true, "only": true, "onto": true,
|
||||
"or": true, "other": true, "others": true, "otherwise": true, "our": true, "ours": true, "ourselves": true, "out": true, "over": true, "own": true, "part": true, "per": true, "perhaps": true,
|
||||
"please": true, "put": true, "rather": true, "re": true, "same": true, "see": true, "seem": true, "seemed": true, "seeming": true, "seems": true, "serious": true, "several": true, "she": true,
|
||||
"should": true, "show": true, "side": true, "since": true, "sincere": true, "six": true, "sixty": true, "so": true, "some": true, "somehow": true, "someone": true, "something": true, "sometime": true,
|
||||
"sometimes": true, "somewhere": true, "still": true, "such": true, "take": true, "ten": true, "than": true, "that": true, "their": true, "them": true, "themselves": true,
|
||||
"then": true, "thence": true, "there": true, "thereafter": true, "thereby": true, "therefore": true, "therein": true, "thereupon": true, "these": true, "they": true, "thickv": true, "thin": true,
|
||||
"third": true, "this": true, "those": true, "though": true, "three": true, "through": true, "throughout": true, "thru": true, "thus": true, "to": true, "together": true, "too": true, "top": true,
|
||||
"toward": true, "towards": true, "twelve": true, "twenty": true, "two": true, "un": true, "under": true, "until": true, "up": true, "upon": true, "us": true, "very": true, "via": true, "was": true, "we": true,
|
||||
"well": true, "were": true, "what": true, "whatever": true, "when": true, "whence": true, "whenever": true, "where": true, "whereafter": true, "whereas": true, "whereby": true, "wherein": true,
|
||||
"whereupon": true, "wherever": true, "whether": true, "which": true, "while": true, "whither": true, "who": true, "whoever": true, "whole": true, "whom": true, "whose": true, "why": true, "will": true,
|
||||
"with": true, "within": true, "without": true, "would": true, "yet": true, "you": true, "your": true, "youre": true, "yours": true, "yourself": true, "yourselves": true, "www": true, "com": true, "http": true}
|
||||
18
vendor/code.sajari.com/docconv/html_appengine.go
сгенерированный
поставляемый
Обычный файл
18
vendor/code.sajari.com/docconv/html_appengine.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,18 @@
|
||||
// +build appengine
|
||||
|
||||
package docconv
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
)
|
||||
|
||||
func HTMLReadability(r io.Reader) []byte {
|
||||
b, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
log.Printf("HTMLReadability: %v", err)
|
||||
return nil
|
||||
}
|
||||
return b
|
||||
}
|
||||
587
vendor/code.sajari.com/docconv/iWork/TSPArchiveMessages.pb.go
сгенерированный
поставляемый
Обычный файл
587
vendor/code.sajari.com/docconv/iWork/TSPArchiveMessages.pb.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,587 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: TSPArchiveMessages.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package TSP is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
TSPArchiveMessages.proto
|
||||
TSPDatabaseMessages.proto
|
||||
TSPMessages.proto
|
||||
|
||||
It has these top-level messages:
|
||||
ArchiveInfo
|
||||
MessageInfo
|
||||
FieldInfo
|
||||
FieldPath
|
||||
ComponentInfo
|
||||
ComponentExternalReference
|
||||
ComponentDataReference
|
||||
PackageMetadata
|
||||
PasteboardMetadata
|
||||
DataInfo
|
||||
ViewStateMetadata
|
||||
*/
|
||||
package TSP
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = math.Inf
|
||||
|
||||
type FieldInfo_Type int32
|
||||
|
||||
const (
|
||||
FieldInfo_Value FieldInfo_Type = 0
|
||||
FieldInfo_ObjectReference FieldInfo_Type = 1
|
||||
FieldInfo_DataReference FieldInfo_Type = 2
|
||||
FieldInfo_Message FieldInfo_Type = 3
|
||||
)
|
||||
|
||||
var FieldInfo_Type_name = map[int32]string{
|
||||
0: "Value",
|
||||
1: "ObjectReference",
|
||||
2: "DataReference",
|
||||
3: "Message",
|
||||
}
|
||||
var FieldInfo_Type_value = map[string]int32{
|
||||
"Value": 0,
|
||||
"ObjectReference": 1,
|
||||
"DataReference": 2,
|
||||
"Message": 3,
|
||||
}
|
||||
|
||||
func (x FieldInfo_Type) Enum() *FieldInfo_Type {
|
||||
p := new(FieldInfo_Type)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
func (x FieldInfo_Type) String() string {
|
||||
return proto.EnumName(FieldInfo_Type_name, int32(x))
|
||||
}
|
||||
func (x *FieldInfo_Type) UnmarshalJSON(data []byte) error {
|
||||
value, err := proto.UnmarshalJSONEnum(FieldInfo_Type_value, data, "FieldInfo_Type")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*x = FieldInfo_Type(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
type FieldInfo_Rule int32
|
||||
|
||||
const (
|
||||
FieldInfo_IgnoreAndDrop FieldInfo_Rule = 0
|
||||
FieldInfo_IgnoreAndPreserve FieldInfo_Rule = 1
|
||||
FieldInfo_MustUnderstand FieldInfo_Rule = 2
|
||||
FieldInfo_NotSupported FieldInfo_Rule = -1
|
||||
)
|
||||
|
||||
var FieldInfo_Rule_name = map[int32]string{
|
||||
0: "IgnoreAndDrop",
|
||||
1: "IgnoreAndPreserve",
|
||||
2: "MustUnderstand",
|
||||
-1: "NotSupported",
|
||||
}
|
||||
var FieldInfo_Rule_value = map[string]int32{
|
||||
"IgnoreAndDrop": 0,
|
||||
"IgnoreAndPreserve": 1,
|
||||
"MustUnderstand": 2,
|
||||
"NotSupported": -1,
|
||||
}
|
||||
|
||||
func (x FieldInfo_Rule) Enum() *FieldInfo_Rule {
|
||||
p := new(FieldInfo_Rule)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
func (x FieldInfo_Rule) String() string {
|
||||
return proto.EnumName(FieldInfo_Rule_name, int32(x))
|
||||
}
|
||||
func (x *FieldInfo_Rule) UnmarshalJSON(data []byte) error {
|
||||
value, err := proto.UnmarshalJSONEnum(FieldInfo_Rule_value, data, "FieldInfo_Rule")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*x = FieldInfo_Rule(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
type ArchiveInfo struct {
|
||||
Identifier *uint64 `protobuf:"varint,1,opt,name=identifier" json:"identifier,omitempty"`
|
||||
MessageInfos []*MessageInfo `protobuf:"bytes,2,rep,name=message_infos" json:"message_infos,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ArchiveInfo) Reset() { *m = ArchiveInfo{} }
|
||||
func (m *ArchiveInfo) String() string { return proto.CompactTextString(m) }
|
||||
func (*ArchiveInfo) ProtoMessage() {}
|
||||
|
||||
func (m *ArchiveInfo) GetIdentifier() uint64 {
|
||||
if m != nil && m.Identifier != nil {
|
||||
return *m.Identifier
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *ArchiveInfo) GetMessageInfos() []*MessageInfo {
|
||||
if m != nil {
|
||||
return m.MessageInfos
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type MessageInfo struct {
|
||||
Type *uint32 `protobuf:"varint,1,req,name=type" json:"type,omitempty"`
|
||||
Version []uint32 `protobuf:"varint,2,rep,packed,name=version" json:"version,omitempty"`
|
||||
Length *uint32 `protobuf:"varint,3,req,name=length" json:"length,omitempty"`
|
||||
FieldInfos []*FieldInfo `protobuf:"bytes,4,rep,name=field_infos" json:"field_infos,omitempty"`
|
||||
ObjectReferences []uint64 `protobuf:"varint,5,rep,packed,name=object_references" json:"object_references,omitempty"`
|
||||
DataReferences []uint64 `protobuf:"varint,6,rep,packed,name=data_references" json:"data_references,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *MessageInfo) Reset() { *m = MessageInfo{} }
|
||||
func (m *MessageInfo) String() string { return proto.CompactTextString(m) }
|
||||
func (*MessageInfo) ProtoMessage() {}
|
||||
|
||||
func (m *MessageInfo) GetType() uint32 {
|
||||
if m != nil && m.Type != nil {
|
||||
return *m.Type
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *MessageInfo) GetVersion() []uint32 {
|
||||
if m != nil {
|
||||
return m.Version
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MessageInfo) GetLength() uint32 {
|
||||
if m != nil && m.Length != nil {
|
||||
return *m.Length
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *MessageInfo) GetFieldInfos() []*FieldInfo {
|
||||
if m != nil {
|
||||
return m.FieldInfos
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MessageInfo) GetObjectReferences() []uint64 {
|
||||
if m != nil {
|
||||
return m.ObjectReferences
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MessageInfo) GetDataReferences() []uint64 {
|
||||
if m != nil {
|
||||
return m.DataReferences
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type FieldInfo struct {
|
||||
Path *FieldPath `protobuf:"bytes,1,req,name=path" json:"path,omitempty"`
|
||||
Type *FieldInfo_Type `protobuf:"varint,2,opt,name=type,enum=TSP.FieldInfo_Type,def=0" json:"type,omitempty"`
|
||||
Rule *FieldInfo_Rule `protobuf:"varint,3,opt,name=rule,enum=TSP.FieldInfo_Rule,def=0" json:"rule,omitempty"`
|
||||
ObjectReferences []uint64 `protobuf:"varint,4,rep,packed,name=object_references" json:"object_references,omitempty"`
|
||||
DataReferences []uint64 `protobuf:"varint,5,rep,packed,name=data_references" json:"data_references,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *FieldInfo) Reset() { *m = FieldInfo{} }
|
||||
func (m *FieldInfo) String() string { return proto.CompactTextString(m) }
|
||||
func (*FieldInfo) ProtoMessage() {}
|
||||
|
||||
const Default_FieldInfo_Type FieldInfo_Type = FieldInfo_Value
|
||||
const Default_FieldInfo_Rule FieldInfo_Rule = FieldInfo_IgnoreAndDrop
|
||||
|
||||
func (m *FieldInfo) GetPath() *FieldPath {
|
||||
if m != nil {
|
||||
return m.Path
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *FieldInfo) GetType() FieldInfo_Type {
|
||||
if m != nil && m.Type != nil {
|
||||
return *m.Type
|
||||
}
|
||||
return Default_FieldInfo_Type
|
||||
}
|
||||
|
||||
func (m *FieldInfo) GetRule() FieldInfo_Rule {
|
||||
if m != nil && m.Rule != nil {
|
||||
return *m.Rule
|
||||
}
|
||||
return Default_FieldInfo_Rule
|
||||
}
|
||||
|
||||
func (m *FieldInfo) GetObjectReferences() []uint64 {
|
||||
if m != nil {
|
||||
return m.ObjectReferences
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *FieldInfo) GetDataReferences() []uint64 {
|
||||
if m != nil {
|
||||
return m.DataReferences
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type FieldPath struct {
|
||||
Path []uint32 `protobuf:"varint,1,rep,packed,name=path" json:"path,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *FieldPath) Reset() { *m = FieldPath{} }
|
||||
func (m *FieldPath) String() string { return proto.CompactTextString(m) }
|
||||
func (*FieldPath) ProtoMessage() {}
|
||||
|
||||
func (m *FieldPath) GetPath() []uint32 {
|
||||
if m != nil {
|
||||
return m.Path
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ComponentInfo struct {
|
||||
Identifier *uint64 `protobuf:"varint,1,req,name=identifier" json:"identifier,omitempty"`
|
||||
PreferredLocator *string `protobuf:"bytes,2,req,name=preferred_locator" json:"preferred_locator,omitempty"`
|
||||
Locator *string `protobuf:"bytes,3,opt,name=locator" json:"locator,omitempty"`
|
||||
ReadVersion []uint32 `protobuf:"varint,4,rep,packed,name=read_version" json:"read_version,omitempty"`
|
||||
WriteVersion []uint32 `protobuf:"varint,5,rep,packed,name=write_version" json:"write_version,omitempty"`
|
||||
ExternalReferences []*ComponentExternalReference `protobuf:"bytes,6,rep,name=external_references" json:"external_references,omitempty"`
|
||||
DataReferences []*ComponentDataReference `protobuf:"bytes,7,rep,name=data_references" json:"data_references,omitempty"`
|
||||
AllowsDuplicatesOutsideOfDocumentPackage *bool `protobuf:"varint,8,opt,name=allows_duplicates_outside_of_document_package,def=0" json:"allows_duplicates_outside_of_document_package,omitempty"`
|
||||
DirtiesDocumentPackage *bool `protobuf:"varint,9,opt,name=dirties_document_package,def=1" json:"dirties_document_package,omitempty"`
|
||||
IsStoredOutsideObjectArchive *bool `protobuf:"varint,10,opt,name=is_stored_outside_object_archive,def=0" json:"is_stored_outside_object_archive,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ComponentInfo) Reset() { *m = ComponentInfo{} }
|
||||
func (m *ComponentInfo) String() string { return proto.CompactTextString(m) }
|
||||
func (*ComponentInfo) ProtoMessage() {}
|
||||
|
||||
const Default_ComponentInfo_AllowsDuplicatesOutsideOfDocumentPackage bool = false
|
||||
const Default_ComponentInfo_DirtiesDocumentPackage bool = true
|
||||
const Default_ComponentInfo_IsStoredOutsideObjectArchive bool = false
|
||||
|
||||
func (m *ComponentInfo) GetIdentifier() uint64 {
|
||||
if m != nil && m.Identifier != nil {
|
||||
return *m.Identifier
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *ComponentInfo) GetPreferredLocator() string {
|
||||
if m != nil && m.PreferredLocator != nil {
|
||||
return *m.PreferredLocator
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *ComponentInfo) GetLocator() string {
|
||||
if m != nil && m.Locator != nil {
|
||||
return *m.Locator
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *ComponentInfo) GetReadVersion() []uint32 {
|
||||
if m != nil {
|
||||
return m.ReadVersion
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ComponentInfo) GetWriteVersion() []uint32 {
|
||||
if m != nil {
|
||||
return m.WriteVersion
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ComponentInfo) GetExternalReferences() []*ComponentExternalReference {
|
||||
if m != nil {
|
||||
return m.ExternalReferences
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ComponentInfo) GetDataReferences() []*ComponentDataReference {
|
||||
if m != nil {
|
||||
return m.DataReferences
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ComponentInfo) GetAllowsDuplicatesOutsideOfDocumentPackage() bool {
|
||||
if m != nil && m.AllowsDuplicatesOutsideOfDocumentPackage != nil {
|
||||
return *m.AllowsDuplicatesOutsideOfDocumentPackage
|
||||
}
|
||||
return Default_ComponentInfo_AllowsDuplicatesOutsideOfDocumentPackage
|
||||
}
|
||||
|
||||
func (m *ComponentInfo) GetDirtiesDocumentPackage() bool {
|
||||
if m != nil && m.DirtiesDocumentPackage != nil {
|
||||
return *m.DirtiesDocumentPackage
|
||||
}
|
||||
return Default_ComponentInfo_DirtiesDocumentPackage
|
||||
}
|
||||
|
||||
func (m *ComponentInfo) GetIsStoredOutsideObjectArchive() bool {
|
||||
if m != nil && m.IsStoredOutsideObjectArchive != nil {
|
||||
return *m.IsStoredOutsideObjectArchive
|
||||
}
|
||||
return Default_ComponentInfo_IsStoredOutsideObjectArchive
|
||||
}
|
||||
|
||||
type ComponentExternalReference struct {
|
||||
ComponentIdentifier *uint64 `protobuf:"varint,1,req,name=component_identifier" json:"component_identifier,omitempty"`
|
||||
ObjectIdentifier *uint64 `protobuf:"varint,2,opt,name=object_identifier" json:"object_identifier,omitempty"`
|
||||
IsWeak *bool `protobuf:"varint,3,opt,name=is_weak" json:"is_weak,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ComponentExternalReference) Reset() { *m = ComponentExternalReference{} }
|
||||
func (m *ComponentExternalReference) String() string { return proto.CompactTextString(m) }
|
||||
func (*ComponentExternalReference) ProtoMessage() {}
|
||||
|
||||
func (m *ComponentExternalReference) GetComponentIdentifier() uint64 {
|
||||
if m != nil && m.ComponentIdentifier != nil {
|
||||
return *m.ComponentIdentifier
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *ComponentExternalReference) GetObjectIdentifier() uint64 {
|
||||
if m != nil && m.ObjectIdentifier != nil {
|
||||
return *m.ObjectIdentifier
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *ComponentExternalReference) GetIsWeak() bool {
|
||||
if m != nil && m.IsWeak != nil {
|
||||
return *m.IsWeak
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ComponentDataReference struct {
|
||||
DataIdentifier *uint64 `protobuf:"varint,1,req,name=data_identifier" json:"data_identifier,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ComponentDataReference) Reset() { *m = ComponentDataReference{} }
|
||||
func (m *ComponentDataReference) String() string { return proto.CompactTextString(m) }
|
||||
func (*ComponentDataReference) ProtoMessage() {}
|
||||
|
||||
func (m *ComponentDataReference) GetDataIdentifier() uint64 {
|
||||
if m != nil && m.DataIdentifier != nil {
|
||||
return *m.DataIdentifier
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type PackageMetadata struct {
|
||||
LastObjectIdentifier *uint64 `protobuf:"varint,1,req,name=last_object_identifier" json:"last_object_identifier,omitempty"`
|
||||
Components []*ComponentInfo `protobuf:"bytes,3,rep,name=components" json:"components,omitempty"`
|
||||
Datas []*DataInfo `protobuf:"bytes,4,rep,name=datas" json:"datas,omitempty"`
|
||||
ReadVersion []uint32 `protobuf:"varint,5,rep,packed,name=read_version" json:"read_version,omitempty"`
|
||||
WriteVersion []uint32 `protobuf:"varint,6,rep,packed,name=write_version" json:"write_version,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *PackageMetadata) Reset() { *m = PackageMetadata{} }
|
||||
func (m *PackageMetadata) String() string { return proto.CompactTextString(m) }
|
||||
func (*PackageMetadata) ProtoMessage() {}
|
||||
|
||||
func (m *PackageMetadata) GetLastObjectIdentifier() uint64 {
|
||||
if m != nil && m.LastObjectIdentifier != nil {
|
||||
return *m.LastObjectIdentifier
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *PackageMetadata) GetComponents() []*ComponentInfo {
|
||||
if m != nil {
|
||||
return m.Components
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PackageMetadata) GetDatas() []*DataInfo {
|
||||
if m != nil {
|
||||
return m.Datas
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PackageMetadata) GetReadVersion() []uint32 {
|
||||
if m != nil {
|
||||
return m.ReadVersion
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PackageMetadata) GetWriteVersion() []uint32 {
|
||||
if m != nil {
|
||||
return m.WriteVersion
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PasteboardMetadata struct {
|
||||
Version []uint32 `protobuf:"varint,1,rep,packed,name=version" json:"version,omitempty"`
|
||||
AppName *string `protobuf:"bytes,2,req,name=app_name" json:"app_name,omitempty"`
|
||||
Datas []*DataInfo `protobuf:"bytes,3,rep,name=datas" json:"datas,omitempty"`
|
||||
SourceDocumentUuid *string `protobuf:"bytes,4,opt,name=source_document_uuid" json:"source_document_uuid,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *PasteboardMetadata) Reset() { *m = PasteboardMetadata{} }
|
||||
func (m *PasteboardMetadata) String() string { return proto.CompactTextString(m) }
|
||||
func (*PasteboardMetadata) ProtoMessage() {}
|
||||
|
||||
func (m *PasteboardMetadata) GetVersion() []uint32 {
|
||||
if m != nil {
|
||||
return m.Version
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PasteboardMetadata) GetAppName() string {
|
||||
if m != nil && m.AppName != nil {
|
||||
return *m.AppName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *PasteboardMetadata) GetDatas() []*DataInfo {
|
||||
if m != nil {
|
||||
return m.Datas
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PasteboardMetadata) GetSourceDocumentUuid() string {
|
||||
if m != nil && m.SourceDocumentUuid != nil {
|
||||
return *m.SourceDocumentUuid
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type DataInfo struct {
|
||||
Identifier *uint64 `protobuf:"varint,1,req,name=identifier" json:"identifier,omitempty"`
|
||||
Digest []byte `protobuf:"bytes,2,req,name=digest" json:"digest,omitempty"`
|
||||
PreferredFileName *string `protobuf:"bytes,3,req,name=preferred_file_name" json:"preferred_file_name,omitempty"`
|
||||
FileName *string `protobuf:"bytes,4,opt,name=file_name" json:"file_name,omitempty"`
|
||||
DocumentResourceLocator *string `protobuf:"bytes,5,opt,name=document_resource_locator" json:"document_resource_locator,omitempty"`
|
||||
SourceBookmarkData []byte `protobuf:"bytes,6,opt,name=source_bookmark_data" json:"source_bookmark_data,omitempty"`
|
||||
PasteboardExternalFilePath *string `protobuf:"bytes,99,opt,name=pasteboard_external_file_path" json:"pasteboard_external_file_path,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *DataInfo) Reset() { *m = DataInfo{} }
|
||||
func (m *DataInfo) String() string { return proto.CompactTextString(m) }
|
||||
func (*DataInfo) ProtoMessage() {}
|
||||
|
||||
func (m *DataInfo) GetIdentifier() uint64 {
|
||||
if m != nil && m.Identifier != nil {
|
||||
return *m.Identifier
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *DataInfo) GetDigest() []byte {
|
||||
if m != nil {
|
||||
return m.Digest
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *DataInfo) GetPreferredFileName() string {
|
||||
if m != nil && m.PreferredFileName != nil {
|
||||
return *m.PreferredFileName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *DataInfo) GetFileName() string {
|
||||
if m != nil && m.FileName != nil {
|
||||
return *m.FileName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *DataInfo) GetDocumentResourceLocator() string {
|
||||
if m != nil && m.DocumentResourceLocator != nil {
|
||||
return *m.DocumentResourceLocator
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *DataInfo) GetSourceBookmarkData() []byte {
|
||||
if m != nil {
|
||||
return m.SourceBookmarkData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *DataInfo) GetPasteboardExternalFilePath() string {
|
||||
if m != nil && m.PasteboardExternalFilePath != nil {
|
||||
return *m.PasteboardExternalFilePath
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ViewStateMetadata struct {
|
||||
Version []uint32 `protobuf:"varint,1,rep,packed,name=version" json:"version,omitempty"`
|
||||
DocumentVersionUuid *string `protobuf:"bytes,2,req,name=document_version_uuid" json:"document_version_uuid,omitempty"`
|
||||
Component *ComponentInfo `protobuf:"bytes,3,req,name=component" json:"component,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ViewStateMetadata) Reset() { *m = ViewStateMetadata{} }
|
||||
func (m *ViewStateMetadata) String() string { return proto.CompactTextString(m) }
|
||||
func (*ViewStateMetadata) ProtoMessage() {}
|
||||
|
||||
func (m *ViewStateMetadata) GetVersion() []uint32 {
|
||||
if m != nil {
|
||||
return m.Version
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ViewStateMetadata) GetDocumentVersionUuid() string {
|
||||
if m != nil && m.DocumentVersionUuid != nil {
|
||||
return *m.DocumentVersionUuid
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *ViewStateMetadata) GetComponent() *ComponentInfo {
|
||||
if m != nil {
|
||||
return m.Component
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("TSP.FieldInfo_Type", FieldInfo_Type_name, FieldInfo_Type_value)
|
||||
proto.RegisterEnum("TSP.FieldInfo_Rule", FieldInfo_Rule_name, FieldInfo_Rule_value)
|
||||
}
|
||||
150
vendor/code.sajari.com/docconv/iWork/TSPDatabaseMessages.pb.go
сгенерированный
поставляемый
Обычный файл
150
vendor/code.sajari.com/docconv/iWork/TSPDatabaseMessages.pb.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,150 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: TSPDatabaseMessages.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
package TSP
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = math.Inf
|
||||
|
||||
type DatabaseImageDataArchive_ImageType int32
|
||||
|
||||
const (
|
||||
DatabaseImageDataArchive_unknown DatabaseImageDataArchive_ImageType = 0
|
||||
DatabaseImageDataArchive_bitmap DatabaseImageDataArchive_ImageType = 1
|
||||
DatabaseImageDataArchive_pdf DatabaseImageDataArchive_ImageType = 2
|
||||
)
|
||||
|
||||
var DatabaseImageDataArchive_ImageType_name = map[int32]string{
|
||||
0: "unknown",
|
||||
1: "bitmap",
|
||||
2: "pdf",
|
||||
}
|
||||
var DatabaseImageDataArchive_ImageType_value = map[string]int32{
|
||||
"unknown": 0,
|
||||
"bitmap": 1,
|
||||
"pdf": 2,
|
||||
}
|
||||
|
||||
func (x DatabaseImageDataArchive_ImageType) Enum() *DatabaseImageDataArchive_ImageType {
|
||||
p := new(DatabaseImageDataArchive_ImageType)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
func (x DatabaseImageDataArchive_ImageType) String() string {
|
||||
return proto.EnumName(DatabaseImageDataArchive_ImageType_name, int32(x))
|
||||
}
|
||||
func (x *DatabaseImageDataArchive_ImageType) UnmarshalJSON(data []byte) error {
|
||||
value, err := proto.UnmarshalJSONEnum(DatabaseImageDataArchive_ImageType_value, data, "DatabaseImageDataArchive_ImageType")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*x = DatabaseImageDataArchive_ImageType(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
type DatabaseData struct {
|
||||
Data *DataReference `protobuf:"bytes,1,req,name=data" json:"data,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *DatabaseData) Reset() { *m = DatabaseData{} }
|
||||
func (m *DatabaseData) String() string { return proto.CompactTextString(m) }
|
||||
func (*DatabaseData) ProtoMessage() {}
|
||||
|
||||
func (m *DatabaseData) GetData() *DataReference {
|
||||
if m != nil {
|
||||
return m.Data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DatabaseDataArchive struct {
|
||||
Data *Reference `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"`
|
||||
AppRelativePath *string `protobuf:"bytes,2,opt,name=app_relative_path" json:"app_relative_path,omitempty"`
|
||||
DisplayName *string `protobuf:"bytes,3,req,name=display_name" json:"display_name,omitempty"`
|
||||
Length *uint64 `protobuf:"varint,4,opt,name=length" json:"length,omitempty"`
|
||||
Hash *uint32 `protobuf:"varint,5,opt,name=hash" json:"hash,omitempty"`
|
||||
Sharable *bool `protobuf:"varint,6,req,name=sharable,def=1" json:"sharable,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *DatabaseDataArchive) Reset() { *m = DatabaseDataArchive{} }
|
||||
func (m *DatabaseDataArchive) String() string { return proto.CompactTextString(m) }
|
||||
func (*DatabaseDataArchive) ProtoMessage() {}
|
||||
|
||||
const Default_DatabaseDataArchive_Sharable bool = true
|
||||
|
||||
func (m *DatabaseDataArchive) GetData() *Reference {
|
||||
if m != nil {
|
||||
return m.Data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *DatabaseDataArchive) GetAppRelativePath() string {
|
||||
if m != nil && m.AppRelativePath != nil {
|
||||
return *m.AppRelativePath
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *DatabaseDataArchive) GetDisplayName() string {
|
||||
if m != nil && m.DisplayName != nil {
|
||||
return *m.DisplayName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *DatabaseDataArchive) GetLength() uint64 {
|
||||
if m != nil && m.Length != nil {
|
||||
return *m.Length
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *DatabaseDataArchive) GetHash() uint32 {
|
||||
if m != nil && m.Hash != nil {
|
||||
return *m.Hash
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *DatabaseDataArchive) GetSharable() bool {
|
||||
if m != nil && m.Sharable != nil {
|
||||
return *m.Sharable
|
||||
}
|
||||
return Default_DatabaseDataArchive_Sharable
|
||||
}
|
||||
|
||||
type DatabaseImageDataArchive struct {
|
||||
Super *DatabaseDataArchive `protobuf:"bytes,1,req,name=super" json:"super,omitempty"`
|
||||
Type *DatabaseImageDataArchive_ImageType `protobuf:"varint,2,req,name=type,enum=TSP.DatabaseImageDataArchive_ImageType" json:"type,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *DatabaseImageDataArchive) Reset() { *m = DatabaseImageDataArchive{} }
|
||||
func (m *DatabaseImageDataArchive) String() string { return proto.CompactTextString(m) }
|
||||
func (*DatabaseImageDataArchive) ProtoMessage() {}
|
||||
|
||||
func (m *DatabaseImageDataArchive) GetSuper() *DatabaseDataArchive {
|
||||
if m != nil {
|
||||
return m.Super
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *DatabaseImageDataArchive) GetType() DatabaseImageDataArchive_ImageType {
|
||||
if m != nil && m.Type != nil {
|
||||
return *m.Type
|
||||
}
|
||||
return DatabaseImageDataArchive_unknown
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("TSP.DatabaseImageDataArchive_ImageType", DatabaseImageDataArchive_ImageType_name, DatabaseImageDataArchive_ImageType_value)
|
||||
}
|
||||
524
vendor/code.sajari.com/docconv/iWork/TSPMessages.pb.go
сгенерированный
поставляемый
Обычный файл
524
vendor/code.sajari.com/docconv/iWork/TSPMessages.pb.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,524 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: TSPMessages.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
package TSP
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = math.Inf
|
||||
|
||||
type Color_ColorModel int32
|
||||
|
||||
const (
|
||||
Color_rgb Color_ColorModel = 1
|
||||
Color_cmyk Color_ColorModel = 2
|
||||
Color_white Color_ColorModel = 3
|
||||
)
|
||||
|
||||
var Color_ColorModel_name = map[int32]string{
|
||||
1: "rgb",
|
||||
2: "cmyk",
|
||||
3: "white",
|
||||
}
|
||||
var Color_ColorModel_value = map[string]int32{
|
||||
"rgb": 1,
|
||||
"cmyk": 2,
|
||||
"white": 3,
|
||||
}
|
||||
|
||||
func (x Color_ColorModel) Enum() *Color_ColorModel {
|
||||
p := new(Color_ColorModel)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
func (x Color_ColorModel) String() string {
|
||||
return proto.EnumName(Color_ColorModel_name, int32(x))
|
||||
}
|
||||
func (x *Color_ColorModel) UnmarshalJSON(data []byte) error {
|
||||
value, err := proto.UnmarshalJSONEnum(Color_ColorModel_value, data, "Color_ColorModel")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*x = Color_ColorModel(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
type Path_ElementType int32
|
||||
|
||||
const (
|
||||
Path_moveTo Path_ElementType = 1
|
||||
Path_lineTo Path_ElementType = 2
|
||||
Path_quadCurveTo Path_ElementType = 3
|
||||
Path_curveTo Path_ElementType = 4
|
||||
Path_closeSubpath Path_ElementType = 5
|
||||
)
|
||||
|
||||
var Path_ElementType_name = map[int32]string{
|
||||
1: "moveTo",
|
||||
2: "lineTo",
|
||||
3: "quadCurveTo",
|
||||
4: "curveTo",
|
||||
5: "closeSubpath",
|
||||
}
|
||||
var Path_ElementType_value = map[string]int32{
|
||||
"moveTo": 1,
|
||||
"lineTo": 2,
|
||||
"quadCurveTo": 3,
|
||||
"curveTo": 4,
|
||||
"closeSubpath": 5,
|
||||
}
|
||||
|
||||
func (x Path_ElementType) Enum() *Path_ElementType {
|
||||
p := new(Path_ElementType)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
func (x Path_ElementType) String() string {
|
||||
return proto.EnumName(Path_ElementType_name, int32(x))
|
||||
}
|
||||
func (x *Path_ElementType) UnmarshalJSON(data []byte) error {
|
||||
value, err := proto.UnmarshalJSONEnum(Path_ElementType_value, data, "Path_ElementType")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*x = Path_ElementType(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
type Reference struct {
|
||||
Identifier *uint64 `protobuf:"varint,1,req,name=identifier" json:"identifier,omitempty"`
|
||||
DeprecatedType *int32 `protobuf:"varint,2,opt,name=deprecated_type" json:"deprecated_type,omitempty"`
|
||||
DeprecatedIsExternal *bool `protobuf:"varint,3,opt,name=deprecated_is_external" json:"deprecated_is_external,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Reference) Reset() { *m = Reference{} }
|
||||
func (m *Reference) String() string { return proto.CompactTextString(m) }
|
||||
func (*Reference) ProtoMessage() {}
|
||||
|
||||
func (m *Reference) GetIdentifier() uint64 {
|
||||
if m != nil && m.Identifier != nil {
|
||||
return *m.Identifier
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Reference) GetDeprecatedType() int32 {
|
||||
if m != nil && m.DeprecatedType != nil {
|
||||
return *m.DeprecatedType
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Reference) GetDeprecatedIsExternal() bool {
|
||||
if m != nil && m.DeprecatedIsExternal != nil {
|
||||
return *m.DeprecatedIsExternal
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type DataReference struct {
|
||||
Identifier *uint64 `protobuf:"varint,1,req,name=identifier" json:"identifier,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *DataReference) Reset() { *m = DataReference{} }
|
||||
func (m *DataReference) String() string { return proto.CompactTextString(m) }
|
||||
func (*DataReference) ProtoMessage() {}
|
||||
|
||||
func (m *DataReference) GetIdentifier() uint64 {
|
||||
if m != nil && m.Identifier != nil {
|
||||
return *m.Identifier
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Point struct {
|
||||
X *float32 `protobuf:"fixed32,1,req,name=x" json:"x,omitempty"`
|
||||
Y *float32 `protobuf:"fixed32,2,req,name=y" json:"y,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Point) Reset() { *m = Point{} }
|
||||
func (m *Point) String() string { return proto.CompactTextString(m) }
|
||||
func (*Point) ProtoMessage() {}
|
||||
|
||||
func (m *Point) GetX() float32 {
|
||||
if m != nil && m.X != nil {
|
||||
return *m.X
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Point) GetY() float32 {
|
||||
if m != nil && m.Y != nil {
|
||||
return *m.Y
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Size struct {
|
||||
Width *float32 `protobuf:"fixed32,1,req,name=width" json:"width,omitempty"`
|
||||
Height *float32 `protobuf:"fixed32,2,req,name=height" json:"height,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Size) Reset() { *m = Size{} }
|
||||
func (m *Size) String() string { return proto.CompactTextString(m) }
|
||||
func (*Size) ProtoMessage() {}
|
||||
|
||||
func (m *Size) GetWidth() float32 {
|
||||
if m != nil && m.Width != nil {
|
||||
return *m.Width
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Size) GetHeight() float32 {
|
||||
if m != nil && m.Height != nil {
|
||||
return *m.Height
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Range struct {
|
||||
Location *uint32 `protobuf:"varint,1,req,name=location" json:"location,omitempty"`
|
||||
Length *uint32 `protobuf:"varint,2,req,name=length" json:"length,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Range) Reset() { *m = Range{} }
|
||||
func (m *Range) String() string { return proto.CompactTextString(m) }
|
||||
func (*Range) ProtoMessage() {}
|
||||
|
||||
func (m *Range) GetLocation() uint32 {
|
||||
if m != nil && m.Location != nil {
|
||||
return *m.Location
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Range) GetLength() uint32 {
|
||||
if m != nil && m.Length != nil {
|
||||
return *m.Length
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Date struct {
|
||||
Seconds *float64 `protobuf:"fixed64,1,req,name=seconds" json:"seconds,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Date) Reset() { *m = Date{} }
|
||||
func (m *Date) String() string { return proto.CompactTextString(m) }
|
||||
func (*Date) ProtoMessage() {}
|
||||
|
||||
func (m *Date) GetSeconds() float64 {
|
||||
if m != nil && m.Seconds != nil {
|
||||
return *m.Seconds
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type IndexSet struct {
|
||||
Ranges []*Range `protobuf:"bytes,1,rep,name=ranges" json:"ranges,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *IndexSet) Reset() { *m = IndexSet{} }
|
||||
func (m *IndexSet) String() string { return proto.CompactTextString(m) }
|
||||
func (*IndexSet) ProtoMessage() {}
|
||||
|
||||
func (m *IndexSet) GetRanges() []*Range {
|
||||
if m != nil {
|
||||
return m.Ranges
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Color struct {
|
||||
Model *Color_ColorModel `protobuf:"varint,1,req,name=model,enum=TSP.Color_ColorModel" json:"model,omitempty"`
|
||||
R *float32 `protobuf:"fixed32,3,opt,name=r" json:"r,omitempty"`
|
||||
G *float32 `protobuf:"fixed32,4,opt,name=g" json:"g,omitempty"`
|
||||
B *float32 `protobuf:"fixed32,5,opt,name=b" json:"b,omitempty"`
|
||||
A *float32 `protobuf:"fixed32,6,opt,name=a,def=1" json:"a,omitempty"`
|
||||
C *float32 `protobuf:"fixed32,7,opt,name=c" json:"c,omitempty"`
|
||||
M *float32 `protobuf:"fixed32,8,opt,name=m" json:"m,omitempty"`
|
||||
Y *float32 `protobuf:"fixed32,9,opt,name=y" json:"y,omitempty"`
|
||||
K *float32 `protobuf:"fixed32,10,opt,name=k" json:"k,omitempty"`
|
||||
W *float32 `protobuf:"fixed32,11,opt,name=w" json:"w,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Color) Reset() { *m = Color{} }
|
||||
func (m *Color) String() string { return proto.CompactTextString(m) }
|
||||
func (*Color) ProtoMessage() {}
|
||||
|
||||
const Default_Color_A float32 = 1
|
||||
|
||||
func (m *Color) GetModel() Color_ColorModel {
|
||||
if m != nil && m.Model != nil {
|
||||
return *m.Model
|
||||
}
|
||||
return Color_rgb
|
||||
}
|
||||
|
||||
func (m *Color) GetR() float32 {
|
||||
if m != nil && m.R != nil {
|
||||
return *m.R
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Color) GetG() float32 {
|
||||
if m != nil && m.G != nil {
|
||||
return *m.G
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Color) GetB() float32 {
|
||||
if m != nil && m.B != nil {
|
||||
return *m.B
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Color) GetA() float32 {
|
||||
if m != nil && m.A != nil {
|
||||
return *m.A
|
||||
}
|
||||
return Default_Color_A
|
||||
}
|
||||
|
||||
func (m *Color) GetC() float32 {
|
||||
if m != nil && m.C != nil {
|
||||
return *m.C
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Color) GetM() float32 {
|
||||
if m != nil && m.M != nil {
|
||||
return *m.M
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Color) GetY() float32 {
|
||||
if m != nil && m.Y != nil {
|
||||
return *m.Y
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Color) GetK() float32 {
|
||||
if m != nil && m.K != nil {
|
||||
return *m.K
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Color) GetW() float32 {
|
||||
if m != nil && m.W != nil {
|
||||
return *m.W
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Path struct {
|
||||
Elements []*Path_Element `protobuf:"bytes,1,rep,name=elements" json:"elements,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Path) Reset() { *m = Path{} }
|
||||
func (m *Path) String() string { return proto.CompactTextString(m) }
|
||||
func (*Path) ProtoMessage() {}
|
||||
|
||||
func (m *Path) GetElements() []*Path_Element {
|
||||
if m != nil {
|
||||
return m.Elements
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Path_Element struct {
|
||||
Type *Path_ElementType `protobuf:"varint,1,req,name=type,enum=TSP.Path_ElementType" json:"type,omitempty"`
|
||||
Points []*Point `protobuf:"bytes,2,rep,name=points" json:"points,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Path_Element) Reset() { *m = Path_Element{} }
|
||||
func (m *Path_Element) String() string { return proto.CompactTextString(m) }
|
||||
func (*Path_Element) ProtoMessage() {}
|
||||
|
||||
func (m *Path_Element) GetType() Path_ElementType {
|
||||
if m != nil && m.Type != nil {
|
||||
return *m.Type
|
||||
}
|
||||
return Path_moveTo
|
||||
}
|
||||
|
||||
func (m *Path_Element) GetPoints() []*Point {
|
||||
if m != nil {
|
||||
return m.Points
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ReferenceDictionary struct {
|
||||
Entries []*ReferenceDictionary_Entry `protobuf:"bytes,1,rep,name=entries" json:"entries,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ReferenceDictionary) Reset() { *m = ReferenceDictionary{} }
|
||||
func (m *ReferenceDictionary) String() string { return proto.CompactTextString(m) }
|
||||
func (*ReferenceDictionary) ProtoMessage() {}
|
||||
|
||||
func (m *ReferenceDictionary) GetEntries() []*ReferenceDictionary_Entry {
|
||||
if m != nil {
|
||||
return m.Entries
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ReferenceDictionary_Entry struct {
|
||||
Key *Reference `protobuf:"bytes,1,req,name=key" json:"key,omitempty"`
|
||||
Value *Reference `protobuf:"bytes,2,req,name=value" json:"value,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ReferenceDictionary_Entry) Reset() { *m = ReferenceDictionary_Entry{} }
|
||||
func (m *ReferenceDictionary_Entry) String() string { return proto.CompactTextString(m) }
|
||||
func (*ReferenceDictionary_Entry) ProtoMessage() {}
|
||||
|
||||
func (m *ReferenceDictionary_Entry) GetKey() *Reference {
|
||||
if m != nil {
|
||||
return m.Key
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ReferenceDictionary_Entry) GetValue() *Reference {
|
||||
if m != nil {
|
||||
return m.Value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PasteboardObject struct {
|
||||
Stylesheet *Reference `protobuf:"bytes,1,opt,name=stylesheet" json:"stylesheet,omitempty"`
|
||||
Drawables []*Reference `protobuf:"bytes,2,rep,name=drawables" json:"drawables,omitempty"`
|
||||
Styles []*Reference `protobuf:"bytes,3,rep,name=styles" json:"styles,omitempty"`
|
||||
Theme *Reference `protobuf:"bytes,4,opt,name=theme" json:"theme,omitempty"`
|
||||
WpStorage *Reference `protobuf:"bytes,5,opt,name=wp_storage" json:"wp_storage,omitempty"`
|
||||
GuideStorage *Reference `protobuf:"bytes,9,opt,name=guide_storage" json:"guide_storage,omitempty"`
|
||||
AppNativeObject *Reference `protobuf:"bytes,6,opt,name=app_native_object" json:"app_native_object,omitempty"`
|
||||
IsTextPrimary *bool `protobuf:"varint,7,opt,name=is_text_primary,def=0" json:"is_text_primary,omitempty"`
|
||||
IsSmart *bool `protobuf:"varint,8,opt,name=is_smart,def=0" json:"is_smart,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *PasteboardObject) Reset() { *m = PasteboardObject{} }
|
||||
func (m *PasteboardObject) String() string { return proto.CompactTextString(m) }
|
||||
func (*PasteboardObject) ProtoMessage() {}
|
||||
|
||||
const Default_PasteboardObject_IsTextPrimary bool = false
|
||||
const Default_PasteboardObject_IsSmart bool = false
|
||||
|
||||
func (m *PasteboardObject) GetStylesheet() *Reference {
|
||||
if m != nil {
|
||||
return m.Stylesheet
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PasteboardObject) GetDrawables() []*Reference {
|
||||
if m != nil {
|
||||
return m.Drawables
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PasteboardObject) GetStyles() []*Reference {
|
||||
if m != nil {
|
||||
return m.Styles
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PasteboardObject) GetTheme() *Reference {
|
||||
if m != nil {
|
||||
return m.Theme
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PasteboardObject) GetWpStorage() *Reference {
|
||||
if m != nil {
|
||||
return m.WpStorage
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PasteboardObject) GetGuideStorage() *Reference {
|
||||
if m != nil {
|
||||
return m.GuideStorage
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PasteboardObject) GetAppNativeObject() *Reference {
|
||||
if m != nil {
|
||||
return m.AppNativeObject
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PasteboardObject) GetIsTextPrimary() bool {
|
||||
if m != nil && m.IsTextPrimary != nil {
|
||||
return *m.IsTextPrimary
|
||||
}
|
||||
return Default_PasteboardObject_IsTextPrimary
|
||||
}
|
||||
|
||||
func (m *PasteboardObject) GetIsSmart() bool {
|
||||
if m != nil && m.IsSmart != nil {
|
||||
return *m.IsSmart
|
||||
}
|
||||
return Default_PasteboardObject_IsSmart
|
||||
}
|
||||
|
||||
type ObjectContainer struct {
|
||||
Identifier *uint32 `protobuf:"varint,1,opt,name=identifier" json:"identifier,omitempty"`
|
||||
Objects []*Reference `protobuf:"bytes,2,rep,name=objects" json:"objects,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ObjectContainer) Reset() { *m = ObjectContainer{} }
|
||||
func (m *ObjectContainer) String() string { return proto.CompactTextString(m) }
|
||||
func (*ObjectContainer) ProtoMessage() {}
|
||||
|
||||
func (m *ObjectContainer) GetIdentifier() uint32 {
|
||||
if m != nil && m.Identifier != nil {
|
||||
return *m.Identifier
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *ObjectContainer) GetObjects() []*Reference {
|
||||
if m != nil {
|
||||
return m.Objects
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("TSP.Color_ColorModel", Color_ColorModel_name, Color_ColorModel_value)
|
||||
proto.RegisterEnum("TSP.Path_ElementType", Path_ElementType_name, Path_ElementType_value)
|
||||
}
|
||||
17
vendor/code.sajari.com/docconv/image.go
сгенерированный
поставляемый
Обычный файл
17
vendor/code.sajari.com/docconv/image.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,17 @@
|
||||
// +build !ocr
|
||||
|
||||
package docconv
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// ConvertImage converts images to text.
|
||||
// Requires gosseract (ocr build tag).
|
||||
func ConvertImage(r io.Reader) (string, map[string]string, error) {
|
||||
return "", nil, fmt.Errorf("docconv not built with `ocr` build tag")
|
||||
}
|
||||
|
||||
// SetImageLanguages sets the languages parameter passed to gosseract.
|
||||
func SetImageLanguages(...string) {}
|
||||
51
vendor/code.sajari.com/docconv/image_ocr.go
сгенерированный
поставляемый
Обычный файл
51
vendor/code.sajari.com/docconv/image_ocr.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,51 @@
|
||||
// +build ocr
|
||||
|
||||
package docconv
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/otiai10/gosseract/v2"
|
||||
)
|
||||
|
||||
var config = struct {
|
||||
langs []string
|
||||
sync.Mutex
|
||||
}{
|
||||
langs: []string{"eng"},
|
||||
}
|
||||
|
||||
func SetImageLanguages(l ...string) {
|
||||
config.Lock()
|
||||
config.langs = l
|
||||
config.Unlock()
|
||||
}
|
||||
|
||||
// ConvertImage converts images to text.
|
||||
// Requires gosseract.
|
||||
func ConvertImage(r io.Reader) (string, map[string]string, error) {
|
||||
f, err := NewLocalFile(r)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("error creating local file: %v", err)
|
||||
}
|
||||
defer f.Done()
|
||||
|
||||
meta := make(map[string]string)
|
||||
|
||||
client := gosseract.NewClient()
|
||||
defer client.Close()
|
||||
|
||||
config.Lock()
|
||||
defer config.Unlock()
|
||||
|
||||
client.SetLanguage(config.langs...)
|
||||
client.SetImage(f.Name())
|
||||
text, err := client.Text()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
return text, meta, nil
|
||||
}
|
||||
51
vendor/code.sajari.com/docconv/local.go
сгенерированный
поставляемый
Обычный файл
51
vendor/code.sajari.com/docconv/local.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,51 @@
|
||||
package docconv
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
// LocalFile is a type which wraps an *os.File. See NewLocalFile for more details.
|
||||
type LocalFile struct {
|
||||
*os.File
|
||||
|
||||
unlink bool
|
||||
}
|
||||
|
||||
// NewLocalFile ensures that there is a file which contains the data provided by r. If r is
|
||||
// actually an instance of *os.File then this file is used, otherwise a temporary file is
|
||||
// created and the data from r copied into it. Callers must call Done() when
|
||||
// the LocalFile is no longer needed to ensure all resources are cleaned up.
|
||||
func NewLocalFile(r io.Reader) (*LocalFile, error) {
|
||||
if f, ok := r.(*os.File); ok {
|
||||
return &LocalFile{
|
||||
File: f,
|
||||
}, nil
|
||||
}
|
||||
|
||||
f, err := ioutil.TempFile(os.TempDir(), "/docconv")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating temporary file: %v", err)
|
||||
}
|
||||
_, err = io.Copy(f, r)
|
||||
if err != nil {
|
||||
f.Close()
|
||||
os.Remove(f.Name())
|
||||
return nil, fmt.Errorf("error copying data into temporary file: %v", err)
|
||||
}
|
||||
|
||||
return &LocalFile{
|
||||
File: f,
|
||||
unlink: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Done cleans up all resources.
|
||||
func (l *LocalFile) Done() {
|
||||
l.Close()
|
||||
if l.unlink {
|
||||
os.Remove(l.Name())
|
||||
}
|
||||
}
|
||||
69
vendor/code.sajari.com/docconv/odt.go
сгенерированный
поставляемый
Обычный файл
69
vendor/code.sajari.com/docconv/odt.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,69 @@
|
||||
package docconv
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ConvertODT converts a ODT file to text
|
||||
func ConvertODT(r io.Reader) (string, map[string]string, error) {
|
||||
meta := make(map[string]string)
|
||||
var textBody string
|
||||
|
||||
b, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
zr, err := zip.NewReader(bytes.NewReader(b), int64(len(b)))
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("error unzipping data: %v", err)
|
||||
}
|
||||
|
||||
for _, f := range zr.File {
|
||||
switch f.Name {
|
||||
case "meta.xml":
|
||||
rc, err := f.Open()
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("error extracting '%v' from archive: %v", f.Name, err)
|
||||
}
|
||||
defer rc.Close()
|
||||
|
||||
info, err := XMLToMap(rc)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("error parsing '%v': %v", f.Name, err)
|
||||
}
|
||||
|
||||
if tmp, ok := info["creator"]; ok {
|
||||
meta["Author"] = tmp
|
||||
}
|
||||
if tmp, ok := info["date"]; ok {
|
||||
if t, err := time.Parse("2006-01-02T15:04:05", tmp); err == nil {
|
||||
meta["ModifiedDate"] = fmt.Sprintf("%d", t.Unix())
|
||||
}
|
||||
}
|
||||
if tmp, ok := info["creation-date"]; ok {
|
||||
if t, err := time.Parse("2006-01-02T15:04:05", tmp); err == nil {
|
||||
meta["CreatedDate"] = fmt.Sprintf("%d", t.Unix())
|
||||
}
|
||||
}
|
||||
|
||||
case "content.xml":
|
||||
rc, err := f.Open()
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("error extracting '%v' from archive: %v", f.Name, err)
|
||||
}
|
||||
defer rc.Close()
|
||||
|
||||
textBody, err = XMLToText(rc, []string{"br", "p", "tab"}, []string{}, true)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("error parsing '%v': %v", f.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return textBody, meta, nil
|
||||
}
|
||||
60
vendor/code.sajari.com/docconv/pages.go
сгенерированный
поставляемый
Обычный файл
60
vendor/code.sajari.com/docconv/pages.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,60 @@
|
||||
package docconv
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
"code.sajari.com/docconv/iWork"
|
||||
"code.sajari.com/docconv/snappy"
|
||||
)
|
||||
|
||||
// ConvertPages converts a Pages file to text.
|
||||
func ConvertPages(r io.Reader) (string, map[string]string, error) {
|
||||
meta := make(map[string]string)
|
||||
var textBody string
|
||||
|
||||
b, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("error reading data: %v", err)
|
||||
}
|
||||
|
||||
zr, err := zip.NewReader(bytes.NewReader(b), int64(len(b)))
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("error unzipping data: %v", err)
|
||||
}
|
||||
|
||||
for _, f := range zr.File {
|
||||
if strings.HasSuffix(f.Name, "Preview.pdf") {
|
||||
// There is a preview PDF version we can use
|
||||
if rc, err := f.Open(); err == nil {
|
||||
return ConvertPDF(rc)
|
||||
}
|
||||
}
|
||||
if f.Name == "index.xml" {
|
||||
// There's an XML version we can use
|
||||
if rc, err := f.Open(); err == nil {
|
||||
return ConvertXML(rc)
|
||||
}
|
||||
}
|
||||
if f.Name == "Index/Document.iwa" {
|
||||
rc, _ := f.Open()
|
||||
defer rc.Close()
|
||||
bReader := bufio.NewReader(snappy.NewReader(io.MultiReader(strings.NewReader("\xff\x06\x00\x00sNaPpY"), rc)))
|
||||
archiveLength, err := binary.ReadVarint(bReader)
|
||||
archiveInfoData, err := ioutil.ReadAll(io.LimitReader(bReader, archiveLength))
|
||||
archiveInfo := &TSP.ArchiveInfo{}
|
||||
err = proto.Unmarshal(archiveInfoData, archiveInfo)
|
||||
fmt.Println("archiveInfo:", archiveInfo, err)
|
||||
}
|
||||
}
|
||||
|
||||
return textBody, meta, nil
|
||||
}
|
||||
30
vendor/code.sajari.com/docconv/pdf.go
сгенерированный
поставляемый
Обычный файл
30
vendor/code.sajari.com/docconv/pdf.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,30 @@
|
||||
// +build !ocr
|
||||
|
||||
package docconv
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
func ConvertPDF(r io.Reader) (string, map[string]string, error) {
|
||||
|
||||
f, err := NewLocalFile(r)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("error creating local file: %v", err)
|
||||
}
|
||||
defer f.Done()
|
||||
|
||||
bodyResult, metaResult, convertErr := ConvertPDFText(f.Name())
|
||||
if convertErr != nil {
|
||||
return "", nil, convertErr
|
||||
}
|
||||
if bodyResult.err != nil {
|
||||
return "", nil, bodyResult.err
|
||||
}
|
||||
if metaResult.err != nil {
|
||||
return "", nil, metaResult.err
|
||||
}
|
||||
return bodyResult.body, metaResult.meta, nil
|
||||
|
||||
}
|
||||
161
vendor/code.sajari.com/docconv/pdf_ocr.go
сгенерированный
поставляемый
Обычный файл
161
vendor/code.sajari.com/docconv/pdf_ocr.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,161 @@
|
||||
// +build ocr
|
||||
|
||||
package docconv
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
exts = []string{".jpg", ".tif", ".tiff", ".png", ".pbm"}
|
||||
)
|
||||
|
||||
func compareExt(ext string, exts []string) bool {
|
||||
for _, e := range exts {
|
||||
if ext == e {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func cleanupTemp(tmpDir string) {
|
||||
err := os.RemoveAll(tmpDir)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func ConvertPDFImages(path string) (BodyResult, error) {
|
||||
bodyResult := BodyResult{}
|
||||
|
||||
tmp, err := ioutil.TempDir(os.TempDir(), "tmp-imgs-")
|
||||
if err != nil {
|
||||
bodyResult.err = err
|
||||
return bodyResult, err
|
||||
}
|
||||
tmpDir := fmt.Sprintf("%s/", tmp)
|
||||
|
||||
defer cleanupTemp(tmpDir)
|
||||
|
||||
_, err = exec.Command("pdfimages", "-j", path, tmpDir).Output()
|
||||
if err != nil {
|
||||
return bodyResult, err
|
||||
}
|
||||
|
||||
filePaths := []string{}
|
||||
|
||||
walkFunc := func(path string, info os.FileInfo, err error) error {
|
||||
path, err = filepath.Abs(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if compareExt(filepath.Ext(path), exts) {
|
||||
filePaths = append(filePaths, path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
filepath.Walk(tmpDir, walkFunc)
|
||||
|
||||
fileLength := len(filePaths)
|
||||
|
||||
if fileLength < 1 {
|
||||
return bodyResult, nil
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
data := make(chan string, fileLength)
|
||||
|
||||
wg.Add(fileLength)
|
||||
|
||||
for _, p := range filePaths {
|
||||
go func(pathFile string) {
|
||||
defer wg.Done()
|
||||
f, err := os.Open(pathFile)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
out, _, err := ConvertImage(f)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
data <- out
|
||||
|
||||
}(p)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
close(data)
|
||||
|
||||
for str := range data {
|
||||
bodyResult.body += str + " "
|
||||
}
|
||||
|
||||
return bodyResult, nil
|
||||
}
|
||||
|
||||
// PdfHasImage verify if `path` (PDF) has images
|
||||
func PDFHasImage(path string) bool {
|
||||
cmd := "pdffonts -l 5 %s | tail -n +3 | cut -d' ' -f1 | sort | uniq"
|
||||
out, err := exec.Command("bash", "-c", fmt.Sprintf(cmd, path)).Output()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return false
|
||||
}
|
||||
if string(out) == "" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func ConvertPDF(r io.Reader) (string, map[string]string, error) {
|
||||
f, err := NewLocalFile(r)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("error creating local file: %v", err)
|
||||
}
|
||||
defer f.Done()
|
||||
|
||||
bodyResult, metaResult, textConvertErr := ConvertPDFText(f.Name())
|
||||
if textConvertErr != nil {
|
||||
return "", nil, textConvertErr
|
||||
}
|
||||
if bodyResult.err != nil {
|
||||
return "", nil, bodyResult.err
|
||||
}
|
||||
if metaResult.err != nil {
|
||||
return "", nil, metaResult.err
|
||||
}
|
||||
|
||||
if !PDFHasImage(f.Name()) {
|
||||
return bodyResult.body, metaResult.meta, nil
|
||||
}
|
||||
|
||||
imageConvertResult, imageConvertErr := ConvertPDFImages(f.Name())
|
||||
if imageConvertErr != nil {
|
||||
log.Println(imageConvertErr)
|
||||
return bodyResult.body, metaResult.meta, nil
|
||||
}
|
||||
if imageConvertResult.err != nil {
|
||||
log.Println(imageConvertResult.err)
|
||||
return bodyResult.body, metaResult.meta, nil
|
||||
}
|
||||
|
||||
fullBody := strings.Join([]string{bodyResult.body, imageConvertResult.body}, " ")
|
||||
|
||||
return fullBody, metaResult.meta, nil
|
||||
|
||||
}
|
||||
84
vendor/code.sajari.com/docconv/pdf_text.go
сгенерированный
поставляемый
Обычный файл
84
vendor/code.sajari.com/docconv/pdf_text.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,84 @@
|
||||
package docconv
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Meta data
|
||||
type MetaResult struct {
|
||||
meta map[string]string
|
||||
err error
|
||||
}
|
||||
|
||||
type BodyResult struct {
|
||||
body string
|
||||
err error
|
||||
}
|
||||
|
||||
// Convert PDF
|
||||
|
||||
func ConvertPDFText(path string) (BodyResult, MetaResult, error) {
|
||||
metaResult := MetaResult{meta: make(map[string]string)}
|
||||
bodyResult := BodyResult{}
|
||||
mr := make(chan MetaResult, 1)
|
||||
go func() {
|
||||
metaStr, err := exec.Command("pdfinfo", path).Output()
|
||||
if err != nil {
|
||||
metaResult.err = err
|
||||
mr <- metaResult
|
||||
return
|
||||
}
|
||||
|
||||
// Parse meta output
|
||||
for _, line := range strings.Split(string(metaStr), "\n") {
|
||||
if parts := strings.SplitN(line, ":", 2); len(parts) > 1 {
|
||||
metaResult.meta[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
|
||||
}
|
||||
}
|
||||
|
||||
// Convert parsed meta
|
||||
if x, ok := metaResult.meta["ModDate"]; ok {
|
||||
if t, ok := pdfTimeLayouts.Parse(x); ok {
|
||||
metaResult.meta["ModifiedDate"] = fmt.Sprintf("%d", t.Unix())
|
||||
}
|
||||
}
|
||||
if x, ok := metaResult.meta["CreationDate"]; ok {
|
||||
if t, ok := pdfTimeLayouts.Parse(x); ok {
|
||||
metaResult.meta["CreatedDate"] = fmt.Sprintf("%d", t.Unix())
|
||||
}
|
||||
}
|
||||
|
||||
mr <- metaResult
|
||||
}()
|
||||
|
||||
br := make(chan BodyResult, 1)
|
||||
go func() {
|
||||
body, err := exec.Command("pdftotext", "-q", "-nopgbrk", "-enc", "UTF-8", "-eol", "unix", path, "-").Output()
|
||||
if err != nil {
|
||||
bodyResult.err = err
|
||||
}
|
||||
|
||||
bodyResult.body = string(body)
|
||||
|
||||
br <- bodyResult
|
||||
}()
|
||||
|
||||
return <-br, <-mr, nil
|
||||
}
|
||||
|
||||
var pdfTimeLayouts = timeLayouts{time.ANSIC, "Mon Jan _2 15:04:05 2006 MST"}
|
||||
|
||||
type timeLayouts []string
|
||||
|
||||
func (tl timeLayouts) Parse(x string) (time.Time, bool) {
|
||||
for _, layout := range tl {
|
||||
t, err := time.Parse(layout, x)
|
||||
if err == nil {
|
||||
return t, true
|
||||
}
|
||||
}
|
||||
return time.Time{}, false
|
||||
}
|
||||
67
vendor/code.sajari.com/docconv/pptx.go
сгенерированный
поставляемый
Обычный файл
67
vendor/code.sajari.com/docconv/pptx.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,67 @@
|
||||
package docconv
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ConvertPptx converts an MS PowerPoint pptx file to text.
|
||||
func ConvertPptx(r io.Reader) (string, map[string]string, error) {
|
||||
var size int64
|
||||
|
||||
// Common case: if the reader is a file (or trivial wrapper), avoid
|
||||
// loading it all into memory.
|
||||
var ra io.ReaderAt
|
||||
if f, ok := r.(interface {
|
||||
io.ReaderAt
|
||||
Stat() (os.FileInfo, error)
|
||||
}); ok {
|
||||
si, err := f.Stat()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
size = si.Size()
|
||||
ra = f
|
||||
} else {
|
||||
b, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return "", nil, nil
|
||||
}
|
||||
size = int64(len(b))
|
||||
ra = bytes.NewReader(b)
|
||||
}
|
||||
|
||||
zr, err := zip.NewReader(ra, size)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("could not unzip: %v", err)
|
||||
}
|
||||
|
||||
zipFiles := mapZipFiles(zr.File)
|
||||
|
||||
contentTypeDefinition, err := getContentTypeDefinition(zipFiles["[Content_Types].xml"])
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
meta := make(map[string]string)
|
||||
var textBody string
|
||||
for _, override := range contentTypeDefinition.Overrides {
|
||||
f := zipFiles[override.PartName]
|
||||
|
||||
switch override.ContentType {
|
||||
case "application/vnd.openxmlformats-officedocument.presentationml.slide+xml",
|
||||
"application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml":
|
||||
body, err := parseDocxText(f)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("could not parse pptx: %v", err)
|
||||
}
|
||||
textBody += body + "\n"
|
||||
}
|
||||
}
|
||||
return strings.TrimSuffix(textBody, "\n"), meta, nil
|
||||
}
|
||||
52
vendor/code.sajari.com/docconv/rtf.go
сгенерированный
поставляемый
Обычный файл
52
vendor/code.sajari.com/docconv/rtf.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,52 @@
|
||||
package docconv
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ConvertRTF converts RTF files to text.
|
||||
func ConvertRTF(r io.Reader) (string, map[string]string, error) {
|
||||
f, err := NewLocalFile(r)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("error creating local file: %v", err)
|
||||
}
|
||||
defer f.Done()
|
||||
|
||||
var output string
|
||||
tmpOutput, err := exec.Command("unrtf", "--nopict", "--text", f.Name()).Output()
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("unrtf error: %v", err)
|
||||
}
|
||||
|
||||
// Step through content looking for meta data and stripping out comments
|
||||
meta := make(map[string]string)
|
||||
for _, line := range strings.Split(string(tmpOutput), "\n") {
|
||||
if parts := strings.SplitN(line, ":", 2); len(parts) > 1 {
|
||||
meta[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
|
||||
}
|
||||
if len(line) > 4 && line[:4] != "### " {
|
||||
output += line + "\n"
|
||||
}
|
||||
}
|
||||
|
||||
// Identify meta data
|
||||
if tmp, ok := meta["AUTHOR"]; ok {
|
||||
meta["Author"] = tmp
|
||||
}
|
||||
if tmp, ok := meta["### creation date"]; ok {
|
||||
if t, err := time.Parse("02 January 2006 15:04", tmp); err == nil {
|
||||
meta["CreatedDate"] = fmt.Sprintf("%d", t.Unix())
|
||||
}
|
||||
}
|
||||
if tmp, ok := meta["### revision date"]; ok {
|
||||
if t, err := time.Parse("02 January 2006 15:04", tmp); err == nil {
|
||||
meta["ModifiedDate"] = fmt.Sprintf("%d", t.Unix())
|
||||
}
|
||||
}
|
||||
|
||||
return output, meta, nil
|
||||
}
|
||||
27
vendor/code.sajari.com/docconv/snappy/LICENSE
сгенерированный
поставляемый
Обычный файл
27
vendor/code.sajari.com/docconv/snappy/LICENSE
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2011 The Snappy-Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
13
vendor/code.sajari.com/docconv/snappy/README
сгенерированный
поставляемый
Обычный файл
13
vendor/code.sajari.com/docconv/snappy/README
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,13 @@
|
||||
This is a Snappy library for the Go programming language that has been modified to work with Apple files, which fail to set CRC checks and stream identifiers. This version is a total hack, so if you want to use snappy for other projects **DO NOT USE THIS VERSION**. Use the proper version as per below:
|
||||
|
||||
To download and install from source:
|
||||
$ go get code.google.com/p/snappy-go/snappy
|
||||
|
||||
|
||||
|
||||
Unless otherwise noted, the Snappy-Go source files are distributed
|
||||
under the BSD-style license found in the LICENSE file.
|
||||
|
||||
Contributions should follow the same procedure as for the Go project:
|
||||
http://golang.org/doc/contribute.html
|
||||
|
||||
297
vendor/code.sajari.com/docconv/snappy/decode.go
сгенерированный
поставляемый
Обычный файл
297
vendor/code.sajari.com/docconv/snappy/decode.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,297 @@
|
||||
// Copyright 2011 The Snappy-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package snappy
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrCorrupt reports that the input is invalid.
|
||||
ErrCorrupt = errors.New("snappy: corrupt input")
|
||||
// ErrUnsupported reports that the input isn't supported.
|
||||
ErrUnsupported = errors.New("snappy: unsupported input")
|
||||
)
|
||||
|
||||
// DecodedLen returns the length of the decoded block.
|
||||
func DecodedLen(src []byte) (int, error) {
|
||||
v, _, err := decodedLen(src)
|
||||
return v, err
|
||||
}
|
||||
|
||||
// decodedLen returns the length of the decoded block and the number of bytes
|
||||
// that the length header occupied.
|
||||
func decodedLen(src []byte) (blockLen, headerLen int, err error) {
|
||||
v, n := binary.Uvarint(src)
|
||||
if n == 0 {
|
||||
return 0, 0, ErrCorrupt
|
||||
}
|
||||
if uint64(int(v)) != v {
|
||||
return 0, 0, errors.New("snappy: decoded block is too large")
|
||||
}
|
||||
return int(v), n, nil
|
||||
}
|
||||
|
||||
// Decode returns the decoded form of src. The returned slice may be a sub-
|
||||
// slice of dst if dst was large enough to hold the entire decoded block.
|
||||
// Otherwise, a newly allocated slice will be returned.
|
||||
// It is valid to pass a nil dst.
|
||||
func Decode(dst, src []byte) ([]byte, error) {
|
||||
dLen, s, err := decodedLen(src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) < dLen {
|
||||
dst = make([]byte, dLen)
|
||||
}
|
||||
|
||||
var d, offset, length int
|
||||
for s < len(src) {
|
||||
switch src[s] & 0x03 {
|
||||
case tagLiteral:
|
||||
x := uint(src[s] >> 2)
|
||||
switch {
|
||||
case x < 60:
|
||||
s += 1
|
||||
case x == 60:
|
||||
s += 2
|
||||
if s > len(src) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
x = uint(src[s-1])
|
||||
case x == 61:
|
||||
s += 3
|
||||
if s > len(src) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
x = uint(src[s-2]) | uint(src[s-1])<<8
|
||||
case x == 62:
|
||||
s += 4
|
||||
if s > len(src) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
x = uint(src[s-3]) | uint(src[s-2])<<8 | uint(src[s-1])<<16
|
||||
case x == 63:
|
||||
s += 5
|
||||
if s > len(src) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
x = uint(src[s-4]) | uint(src[s-3])<<8 | uint(src[s-2])<<16 | uint(src[s-1])<<24
|
||||
}
|
||||
length = int(x + 1)
|
||||
if length <= 0 {
|
||||
return nil, errors.New("snappy: unsupported literal length")
|
||||
}
|
||||
if length > len(dst)-d || length > len(src)-s {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
copy(dst[d:], src[s:s+length])
|
||||
d += length
|
||||
s += length
|
||||
continue
|
||||
|
||||
case tagCopy1:
|
||||
s += 2
|
||||
if s > len(src) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
length = 4 + int(src[s-2])>>2&0x7
|
||||
offset = int(src[s-2])&0xe0<<3 | int(src[s-1])
|
||||
|
||||
case tagCopy2:
|
||||
s += 3
|
||||
if s > len(src) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
length = 1 + int(src[s-3])>>2
|
||||
offset = int(src[s-2]) | int(src[s-1])<<8
|
||||
|
||||
case tagCopy4:
|
||||
return nil, errors.New("snappy: unsupported COPY_4 tag")
|
||||
}
|
||||
|
||||
end := d + length
|
||||
if offset > d || end > len(dst) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
for ; d < end; d++ {
|
||||
dst[d] = dst[d-offset]
|
||||
}
|
||||
}
|
||||
if d != dLen {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
return dst[:d], nil
|
||||
}
|
||||
|
||||
// NewReader returns a new Reader that decompresses from r, using the framing
|
||||
// format described at
|
||||
// https://code.google.com/p/snappy/source/browse/trunk/framing_format.txt
|
||||
func NewReader(r io.Reader) *Reader {
|
||||
return &Reader{
|
||||
r: r,
|
||||
decoded: make([]byte, maxUncompressedChunkLen),
|
||||
buf: make([]byte, MaxEncodedLen(maxUncompressedChunkLen)+checksumSize),
|
||||
}
|
||||
}
|
||||
|
||||
// Reader is an io.Reader than can read Snappy-compressed bytes.
|
||||
type Reader struct {
|
||||
r io.Reader
|
||||
err error
|
||||
decoded []byte
|
||||
buf []byte
|
||||
// decoded[i:j] contains decoded bytes that have not yet been passed on.
|
||||
i, j int
|
||||
readHeader bool
|
||||
}
|
||||
|
||||
// Reset discards any buffered data, resets all state, and switches the Snappy
|
||||
// reader to read from r. This permits reusing a Reader rather than allocating
|
||||
// a new one.
|
||||
func (r *Reader) Reset(reader io.Reader) {
|
||||
r.r = reader
|
||||
r.err = nil
|
||||
r.i = 0
|
||||
r.j = 0
|
||||
r.readHeader = false
|
||||
}
|
||||
|
||||
func (r *Reader) readFull(p []byte) (ok bool) {
|
||||
if _, r.err = io.ReadFull(r.r, p); r.err != nil {
|
||||
if r.err == io.ErrUnexpectedEOF {
|
||||
r.err = ErrCorrupt
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Read satisfies the io.Reader interface.
|
||||
func (r *Reader) Read(p []byte) (int, error) {
|
||||
if r.err != nil {
|
||||
return 0, r.err
|
||||
}
|
||||
for {
|
||||
if r.i < r.j {
|
||||
n := copy(p, r.decoded[r.i:r.j])
|
||||
r.i += n
|
||||
return n, nil
|
||||
}
|
||||
if !r.readFull(r.buf[:4]) {
|
||||
return 0, r.err
|
||||
}
|
||||
chunkType := r.buf[0]
|
||||
if !r.readHeader {
|
||||
if chunkType != chunkTypeStreamIdentifier {
|
||||
r.err = ErrCorrupt
|
||||
return 0, r.err
|
||||
}
|
||||
r.readHeader = true
|
||||
}
|
||||
chunkLen := int(r.buf[1]) | int(r.buf[2])<<8 | int(r.buf[3])<<16
|
||||
if chunkLen > len(r.buf) {
|
||||
r.err = ErrUnsupported
|
||||
return 0, r.err
|
||||
}
|
||||
|
||||
// The chunk types are specified at
|
||||
// https://code.google.com/p/snappy/source/browse/trunk/framing_format.txt
|
||||
switch chunkType {
|
||||
case chunkTypeCompressedData:
|
||||
// Section 4.2. Compressed data (chunk type 0x00).
|
||||
/*
|
||||
if chunkLen < checksumSize {
|
||||
r.err = ErrCorrupt
|
||||
return 0, r.err
|
||||
}
|
||||
*/
|
||||
buf := r.buf[:chunkLen]
|
||||
if !r.readFull(buf) {
|
||||
return 0, r.err
|
||||
}
|
||||
/*
|
||||
checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24
|
||||
buf = buf[checksumSize:]
|
||||
*/
|
||||
n, err := DecodedLen(buf)
|
||||
if err != nil {
|
||||
r.err = err
|
||||
return 0, r.err
|
||||
}
|
||||
if n > len(r.decoded) {
|
||||
r.err = ErrCorrupt
|
||||
return 0, r.err
|
||||
}
|
||||
if _, err := Decode(r.decoded, buf); err != nil {
|
||||
r.err = err
|
||||
return 0, r.err
|
||||
}
|
||||
/*
|
||||
if crc(r.decoded[:n]) != checksum {
|
||||
r.err = ErrCorrupt
|
||||
return 0, r.err
|
||||
}
|
||||
*/
|
||||
r.i, r.j = 0, n
|
||||
continue
|
||||
|
||||
case chunkTypeUncompressedData:
|
||||
// Section 4.3. Uncompressed data (chunk type 0x01).
|
||||
if chunkLen < checksumSize {
|
||||
r.err = ErrCorrupt
|
||||
return 0, r.err
|
||||
}
|
||||
buf := r.buf[:checksumSize]
|
||||
if !r.readFull(buf) {
|
||||
return 0, r.err
|
||||
}
|
||||
checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24
|
||||
// Read directly into r.decoded instead of via r.buf.
|
||||
n := chunkLen - checksumSize
|
||||
if !r.readFull(r.decoded[:n]) {
|
||||
return 0, r.err
|
||||
}
|
||||
if crc(r.decoded[:n]) != checksum {
|
||||
r.err = ErrCorrupt
|
||||
return 0, r.err
|
||||
}
|
||||
r.i, r.j = 0, n
|
||||
continue
|
||||
|
||||
case chunkTypeStreamIdentifier:
|
||||
// Section 4.1. Stream identifier (chunk type 0xff).
|
||||
if chunkLen != len(magicBody) {
|
||||
r.err = ErrCorrupt
|
||||
return 0, r.err
|
||||
}
|
||||
if !r.readFull(r.buf[:len(magicBody)]) {
|
||||
return 0, r.err
|
||||
}
|
||||
for i := 0; i < len(magicBody); i++ {
|
||||
if r.buf[i] != magicBody[i] {
|
||||
r.err = ErrCorrupt
|
||||
return 0, r.err
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if chunkType <= 0x7f {
|
||||
// Section 4.5. Reserved unskippable chunks (chunk types 0x02-0x7f).
|
||||
r.err = ErrUnsupported
|
||||
return 0, r.err
|
||||
|
||||
} else {
|
||||
// Section 4.4 Padding (chunk type 0xfe).
|
||||
// Section 4.6. Reserved skippable chunks (chunk types 0x80-0xfd).
|
||||
if !r.readFull(r.buf[:chunkLen]) {
|
||||
return 0, r.err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
258
vendor/code.sajari.com/docconv/snappy/encode.go
сгенерированный
поставляемый
Обычный файл
258
vendor/code.sajari.com/docconv/snappy/encode.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,258 @@
|
||||
// Copyright 2011 The Snappy-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package snappy
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
)
|
||||
|
||||
// We limit how far copy back-references can go, the same as the C++ code.
|
||||
const maxOffset = 1 << 15
|
||||
|
||||
// emitLiteral writes a literal chunk and returns the number of bytes written.
|
||||
func emitLiteral(dst, lit []byte) int {
|
||||
i, n := 0, uint(len(lit)-1)
|
||||
switch {
|
||||
case n < 60:
|
||||
dst[0] = uint8(n)<<2 | tagLiteral
|
||||
i = 1
|
||||
case n < 1<<8:
|
||||
dst[0] = 60<<2 | tagLiteral
|
||||
dst[1] = uint8(n)
|
||||
i = 2
|
||||
case n < 1<<16:
|
||||
dst[0] = 61<<2 | tagLiteral
|
||||
dst[1] = uint8(n)
|
||||
dst[2] = uint8(n >> 8)
|
||||
i = 3
|
||||
case n < 1<<24:
|
||||
dst[0] = 62<<2 | tagLiteral
|
||||
dst[1] = uint8(n)
|
||||
dst[2] = uint8(n >> 8)
|
||||
dst[3] = uint8(n >> 16)
|
||||
i = 4
|
||||
case int64(n) < 1<<32:
|
||||
dst[0] = 63<<2 | tagLiteral
|
||||
dst[1] = uint8(n)
|
||||
dst[2] = uint8(n >> 8)
|
||||
dst[3] = uint8(n >> 16)
|
||||
dst[4] = uint8(n >> 24)
|
||||
i = 5
|
||||
default:
|
||||
panic("snappy: source buffer is too long")
|
||||
}
|
||||
if copy(dst[i:], lit) != len(lit) {
|
||||
panic("snappy: destination buffer is too short")
|
||||
}
|
||||
return i + len(lit)
|
||||
}
|
||||
|
||||
// emitCopy writes a copy chunk and returns the number of bytes written.
|
||||
func emitCopy(dst []byte, offset, length int) int {
|
||||
i := 0
|
||||
for length > 0 {
|
||||
x := length - 4
|
||||
if 0 <= x && x < 1<<3 && offset < 1<<11 {
|
||||
dst[i+0] = uint8(offset>>8)&0x07<<5 | uint8(x)<<2 | tagCopy1
|
||||
dst[i+1] = uint8(offset)
|
||||
i += 2
|
||||
break
|
||||
}
|
||||
|
||||
x = length
|
||||
if x > 1<<6 {
|
||||
x = 1 << 6
|
||||
}
|
||||
dst[i+0] = uint8(x-1)<<2 | tagCopy2
|
||||
dst[i+1] = uint8(offset)
|
||||
dst[i+2] = uint8(offset >> 8)
|
||||
i += 3
|
||||
length -= x
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
// Encode returns the encoded form of src. The returned slice may be a sub-
|
||||
// slice of dst if dst was large enough to hold the entire encoded block.
|
||||
// Otherwise, a newly allocated slice will be returned.
|
||||
// It is valid to pass a nil dst.
|
||||
func Encode(dst, src []byte) ([]byte, error) {
|
||||
if n := MaxEncodedLen(len(src)); len(dst) < n {
|
||||
dst = make([]byte, n)
|
||||
}
|
||||
|
||||
// The block starts with the varint-encoded length of the decompressed bytes.
|
||||
d := binary.PutUvarint(dst, uint64(len(src)))
|
||||
|
||||
// Return early if src is short.
|
||||
if len(src) <= 4 {
|
||||
if len(src) != 0 {
|
||||
d += emitLiteral(dst[d:], src)
|
||||
}
|
||||
return dst[:d], nil
|
||||
}
|
||||
|
||||
// Initialize the hash table. Its size ranges from 1<<8 to 1<<14 inclusive.
|
||||
const maxTableSize = 1 << 14
|
||||
shift, tableSize := uint(32-8), 1<<8
|
||||
for tableSize < maxTableSize && tableSize < len(src) {
|
||||
shift--
|
||||
tableSize *= 2
|
||||
}
|
||||
var table [maxTableSize]int
|
||||
|
||||
// Iterate over the source bytes.
|
||||
var (
|
||||
s int // The iterator position.
|
||||
t int // The last position with the same hash as s.
|
||||
lit int // The start position of any pending literal bytes.
|
||||
)
|
||||
for s+3 < len(src) {
|
||||
// Update the hash table.
|
||||
b0, b1, b2, b3 := src[s], src[s+1], src[s+2], src[s+3]
|
||||
h := uint32(b0) | uint32(b1)<<8 | uint32(b2)<<16 | uint32(b3)<<24
|
||||
p := &table[(h*0x1e35a7bd)>>shift]
|
||||
// We need to to store values in [-1, inf) in table. To save
|
||||
// some initialization time, (re)use the table's zero value
|
||||
// and shift the values against this zero: add 1 on writes,
|
||||
// subtract 1 on reads.
|
||||
t, *p = *p-1, s+1
|
||||
// If t is invalid or src[s:s+4] differs from src[t:t+4], accumulate a literal byte.
|
||||
if t < 0 || s-t >= maxOffset || b0 != src[t] || b1 != src[t+1] || b2 != src[t+2] || b3 != src[t+3] {
|
||||
s++
|
||||
continue
|
||||
}
|
||||
// Otherwise, we have a match. First, emit any pending literal bytes.
|
||||
if lit != s {
|
||||
d += emitLiteral(dst[d:], src[lit:s])
|
||||
}
|
||||
// Extend the match to be as long as possible.
|
||||
s0 := s
|
||||
s, t = s+4, t+4
|
||||
for s < len(src) && src[s] == src[t] {
|
||||
s++
|
||||
t++
|
||||
}
|
||||
// Emit the copied bytes.
|
||||
d += emitCopy(dst[d:], s-t, s-s0)
|
||||
lit = s
|
||||
}
|
||||
|
||||
// Emit any final pending literal bytes and return.
|
||||
if lit != len(src) {
|
||||
d += emitLiteral(dst[d:], src[lit:])
|
||||
}
|
||||
return dst[:d], nil
|
||||
}
|
||||
|
||||
// MaxEncodedLen returns the maximum length of a snappy block, given its
|
||||
// uncompressed length.
|
||||
func MaxEncodedLen(srcLen int) int {
|
||||
// Compressed data can be defined as:
|
||||
// compressed := item* literal*
|
||||
// item := literal* copy
|
||||
//
|
||||
// The trailing literal sequence has a space blowup of at most 62/60
|
||||
// since a literal of length 60 needs one tag byte + one extra byte
|
||||
// for length information.
|
||||
//
|
||||
// Item blowup is trickier to measure. Suppose the "copy" op copies
|
||||
// 4 bytes of data. Because of a special check in the encoding code,
|
||||
// we produce a 4-byte copy only if the offset is < 65536. Therefore
|
||||
// the copy op takes 3 bytes to encode, and this type of item leads
|
||||
// to at most the 62/60 blowup for representing literals.
|
||||
//
|
||||
// Suppose the "copy" op copies 5 bytes of data. If the offset is big
|
||||
// enough, it will take 5 bytes to encode the copy op. Therefore the
|
||||
// worst case here is a one-byte literal followed by a five-byte copy.
|
||||
// That is, 6 bytes of input turn into 7 bytes of "compressed" data.
|
||||
//
|
||||
// This last factor dominates the blowup, so the final estimate is:
|
||||
return 32 + srcLen + srcLen/6
|
||||
}
|
||||
|
||||
// NewWriter returns a new Writer that compresses to w, using the framing
|
||||
// format described at
|
||||
// https://code.google.com/p/snappy/source/browse/trunk/framing_format.txt
|
||||
func NewWriter(w io.Writer) *Writer {
|
||||
return &Writer{
|
||||
w: w,
|
||||
enc: make([]byte, MaxEncodedLen(maxUncompressedChunkLen)),
|
||||
}
|
||||
}
|
||||
|
||||
// Writer is an io.Writer than can write Snappy-compressed bytes.
|
||||
type Writer struct {
|
||||
w io.Writer
|
||||
err error
|
||||
enc []byte
|
||||
buf [checksumSize + chunkHeaderSize]byte
|
||||
wroteHeader bool
|
||||
}
|
||||
|
||||
// Reset discards the writer's state and switches the Snappy writer to write to
|
||||
// w. This permits reusing a Writer rather than allocating a new one.
|
||||
func (w *Writer) Reset(writer io.Writer) {
|
||||
w.w = writer
|
||||
w.err = nil
|
||||
w.wroteHeader = false
|
||||
}
|
||||
|
||||
// Write satisfies the io.Writer interface.
|
||||
func (w *Writer) Write(p []byte) (n int, errRet error) {
|
||||
if w.err != nil {
|
||||
return 0, w.err
|
||||
}
|
||||
if !w.wroteHeader {
|
||||
copy(w.enc, magicChunk)
|
||||
if _, err := w.w.Write(w.enc[:len(magicChunk)]); err != nil {
|
||||
w.err = err
|
||||
return n, err
|
||||
}
|
||||
w.wroteHeader = true
|
||||
}
|
||||
for len(p) > 0 {
|
||||
var uncompressed []byte
|
||||
if len(p) > maxUncompressedChunkLen {
|
||||
uncompressed, p = p[:maxUncompressedChunkLen], p[maxUncompressedChunkLen:]
|
||||
} else {
|
||||
uncompressed, p = p, nil
|
||||
}
|
||||
checksum := crc(uncompressed)
|
||||
|
||||
// Compress the buffer, discarding the result if the improvement
|
||||
// isn't at least 12.5%.
|
||||
chunkType := uint8(chunkTypeCompressedData)
|
||||
chunkBody, err := Encode(w.enc, uncompressed)
|
||||
if err != nil {
|
||||
w.err = err
|
||||
return n, err
|
||||
}
|
||||
if len(chunkBody) >= len(uncompressed)-len(uncompressed)/8 {
|
||||
chunkType, chunkBody = chunkTypeUncompressedData, uncompressed
|
||||
}
|
||||
|
||||
chunkLen := 4 + len(chunkBody)
|
||||
w.buf[0] = chunkType
|
||||
w.buf[1] = uint8(chunkLen >> 0)
|
||||
w.buf[2] = uint8(chunkLen >> 8)
|
||||
w.buf[3] = uint8(chunkLen >> 16)
|
||||
w.buf[4] = uint8(checksum >> 0)
|
||||
w.buf[5] = uint8(checksum >> 8)
|
||||
w.buf[6] = uint8(checksum >> 16)
|
||||
w.buf[7] = uint8(checksum >> 24)
|
||||
if _, err = w.w.Write(w.buf[:]); err != nil {
|
||||
w.err = err
|
||||
return n, err
|
||||
}
|
||||
if _, err = w.w.Write(chunkBody); err != nil {
|
||||
w.err = err
|
||||
return n, err
|
||||
}
|
||||
n += len(uncompressed)
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
68
vendor/code.sajari.com/docconv/snappy/snappy.go
сгенерированный
поставляемый
Обычный файл
68
vendor/code.sajari.com/docconv/snappy/snappy.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,68 @@
|
||||
// Copyright 2011 The Snappy-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package snappy implements the snappy block-based compression format.
|
||||
// It aims for very high speeds and reasonable compression.
|
||||
//
|
||||
// The C++ snappy implementation is at http://code.google.com/p/snappy/
|
||||
package snappy
|
||||
|
||||
import (
|
||||
"hash/crc32"
|
||||
)
|
||||
|
||||
/*
|
||||
Each encoded block begins with the varint-encoded length of the decoded data,
|
||||
followed by a sequence of chunks. Chunks begin and end on byte boundaries. The
|
||||
first byte of each chunk is broken into its 2 least and 6 most significant bits
|
||||
called l and m: l ranges in [0, 4) and m ranges in [0, 64). l is the chunk tag.
|
||||
Zero means a literal tag. All other values mean a copy tag.
|
||||
|
||||
For literal tags:
|
||||
- If m < 60, the next 1 + m bytes are literal bytes.
|
||||
- Otherwise, let n be the little-endian unsigned integer denoted by the next
|
||||
m - 59 bytes. The next 1 + n bytes after that are literal bytes.
|
||||
|
||||
For copy tags, length bytes are copied from offset bytes ago, in the style of
|
||||
Lempel-Ziv compression algorithms. In particular:
|
||||
- For l == 1, the offset ranges in [0, 1<<11) and the length in [4, 12).
|
||||
The length is 4 + the low 3 bits of m. The high 3 bits of m form bits 8-10
|
||||
of the offset. The next byte is bits 0-7 of the offset.
|
||||
- For l == 2, the offset ranges in [0, 1<<16) and the length in [1, 65).
|
||||
The length is 1 + m. The offset is the little-endian unsigned integer
|
||||
denoted by the next 2 bytes.
|
||||
- For l == 3, this tag is a legacy format that is no longer supported.
|
||||
*/
|
||||
const (
|
||||
tagLiteral = 0x00
|
||||
tagCopy1 = 0x01
|
||||
tagCopy2 = 0x02
|
||||
tagCopy4 = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
checksumSize = 4
|
||||
chunkHeaderSize = 4
|
||||
magicChunk = "\xff\x06\x00\x00" + magicBody
|
||||
magicBody = "sNaPpY"
|
||||
// https://code.google.com/p/snappy/source/browse/trunk/framing_format.txt says
|
||||
// that "the uncompressed data in a chunk must be no longer than 65536 bytes".
|
||||
maxUncompressedChunkLen = 65536
|
||||
)
|
||||
|
||||
const (
|
||||
chunkTypeCompressedData = 0x00
|
||||
chunkTypeUncompressedData = 0x01
|
||||
chunkTypePadding = 0xfe
|
||||
chunkTypeStreamIdentifier = 0xff
|
||||
)
|
||||
|
||||
var crcTable = crc32.MakeTable(crc32.Castagnoli)
|
||||
|
||||
// crc implements the checksum specified in section 3 of
|
||||
// https://code.google.com/p/snappy/source/browse/trunk/framing_format.txt
|
||||
func crc(b []byte) uint32 {
|
||||
c := crc32.Update(0, crcTable, b)
|
||||
return uint32(c>>15|c<<17) + 0xa282ead8
|
||||
}
|
||||
32
vendor/code.sajari.com/docconv/tidy.go
сгенерированный
поставляемый
Обычный файл
32
vendor/code.sajari.com/docconv/tidy.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,32 @@
|
||||
package docconv
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
// Tidy attempts to tidy up XML.
|
||||
// Errors & warnings are deliberately suppressed as underlying tools
|
||||
// throw warnings very easily.
|
||||
func Tidy(r io.Reader, xmlIn bool) ([]byte, error) {
|
||||
f, err := ioutil.TempFile(os.TempDir(), "/docconv")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer os.Remove(f.Name())
|
||||
io.Copy(f, r)
|
||||
|
||||
var output []byte
|
||||
if xmlIn {
|
||||
output, err = exec.Command("tidy", "-xml", "-numeric", "-asxml", "-quiet", "-utf8", f.Name()).Output()
|
||||
} else {
|
||||
output, err = exec.Command("tidy", "-numeric", "-asxml", "-quiet", "-utf8", f.Name()).Output()
|
||||
}
|
||||
|
||||
if err != nil && err.Error() != "exit status 1" {
|
||||
return nil, err
|
||||
}
|
||||
return output, nil
|
||||
}
|
||||
31
vendor/code.sajari.com/docconv/url.go
сгенерированный
поставляемый
Обычный файл
31
vendor/code.sajari.com/docconv/url.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,31 @@
|
||||
package docconv
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/advancedlogic/GoOse"
|
||||
)
|
||||
|
||||
// ConvertURL fetches the HTML page at the URL given in the io.Reader.
|
||||
func ConvertURL(input io.Reader, readability bool) (string, map[string]string, error) {
|
||||
meta := make(map[string]string)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
_, err := buf.ReadFrom(input)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
g := goose.New()
|
||||
article, err := g.ExtractFromURL(buf.String())
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
meta["title"] = article.Title
|
||||
meta["description"] = article.MetaDescription
|
||||
meta["image"] = article.TopImage
|
||||
|
||||
return article.CleanedText, meta, nil
|
||||
}
|
||||
98
vendor/code.sajari.com/docconv/xml.go
сгенерированный
поставляемый
Обычный файл
98
vendor/code.sajari.com/docconv/xml.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,98 @@
|
||||
package docconv
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// ConvertXML converts an XML file to text.
|
||||
func ConvertXML(r io.Reader) (string, map[string]string, error) {
|
||||
meta := make(map[string]string)
|
||||
cleanXML, err := Tidy(r, true)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("tidy error: %v", err)
|
||||
}
|
||||
result, err := XMLToText(bytes.NewReader(cleanXML), []string{}, []string{}, true)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("error from XMLToText: %v", err)
|
||||
}
|
||||
return result, meta, nil
|
||||
}
|
||||
|
||||
// XMLToText converts XML to plain text given how to treat elements.
|
||||
func XMLToText(r io.Reader, breaks []string, skip []string, strict bool) (string, error) {
|
||||
var result string
|
||||
|
||||
dec := xml.NewDecoder(r)
|
||||
dec.Strict = strict
|
||||
for {
|
||||
t, err := dec.Token()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
switch v := t.(type) {
|
||||
case xml.CharData:
|
||||
result += string(v)
|
||||
case xml.StartElement:
|
||||
for _, breakElement := range breaks {
|
||||
if v.Name.Local == breakElement {
|
||||
result += "\n"
|
||||
}
|
||||
}
|
||||
for _, skipElement := range skip {
|
||||
if v.Name.Local == skipElement {
|
||||
depth := 1
|
||||
for {
|
||||
t, err := dec.Token()
|
||||
if err != nil {
|
||||
// An io.EOF here is actually an error.
|
||||
return "", err
|
||||
}
|
||||
|
||||
switch t.(type) {
|
||||
case xml.StartElement:
|
||||
depth++
|
||||
case xml.EndElement:
|
||||
depth--
|
||||
}
|
||||
|
||||
if depth == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// XMLToMap converts XML to a nested string map.
|
||||
func XMLToMap(r io.Reader) (map[string]string, error) {
|
||||
m := make(map[string]string)
|
||||
dec := xml.NewDecoder(r)
|
||||
var tagName string
|
||||
for {
|
||||
t, err := dec.Token()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch v := t.(type) {
|
||||
case xml.StartElement:
|
||||
tagName = string(v.Name.Local)
|
||||
case xml.CharData:
|
||||
m[tagName] = string(v)
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
Ссылка в новой задаче
Block a user