doc

package
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 7, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package doc holds the parsed document model. It turns the Docs API's index-addressed JSON into a tree of tabs, segments, blocks and runs that carries the original UTF-16 indices, assigns handles the model can name, and derives sections from headings. Nothing here talks to the network.

Index

Constants

This section is empty.

Variables

View Source
var NamedStyleOrder = []string{"NORMAL_TEXT", "TITLE", "SUBTITLE",
	"HEADING_1", "HEADING_2", "HEADING_3", "HEADING_4", "HEADING_5", "HEADING_6"}

NamedStyleOrder lists the named styles in the order a read reports them: the document's body style first, then its headings top down.

Functions

func Clip

func Clip(s string, n int) string

Clip trims s and cuts it to n characters with an ellipsis.

func CodePointToUTF16

func CodePointToUTF16(s string, cp int) int64

CodePointToUTF16 converts an offset in code points to UTF-16 units. Offsets past the end clamp to the total length.

func DocumentURL

func DocumentURL(id string) string

DocumentURL is the canonical edit URL for an id.

func Normalize

func Normalize(s string) string

Normalize makes prose comparable: NormalizeRune applied to every character, whitespace runs collapsed to one space, trimmed.

func NormalizeRune

func NormalizeRune(r rune) (rune, bool)

NormalizeRune maps one character to its comparison form: curly quotes to straight, dashes to hyphens, any space to a plain space, zero-width characters dropped (keep=false). Text matching and Normalize share it so needles and haystacks always agree.

func OneLine added in v0.3.0

func OneLine(s string) string

OneLine collapses whitespace runs, newlines included, to single spaces.

func ParseID

func ParseID(s string) (string, error)

ParseID accepts a document id or any docs.google.com URL and returns the id.

func UTF16Len

func UTF16Len(s string) int64

UTF16Len returns the length of s in UTF-16 code units, the unit the Docs API counts indices in. Characters outside the BMP (most emoji) count as two.

func UTF16ToByte

func UTF16ToByte(s string, u int64) int

UTF16ToByte converts a UTF-16 offset into a byte offset in s.

func UTF16ToCodePoint

func UTF16ToCodePoint(s string, u int64) int

UTF16ToCodePoint converts a UTF-16 offset to code points. An offset that lands inside a surrogate pair rounds up to the next character.

func WordCount

func WordCount(s string) int

WordCount counts whitespace-separated words.

Types

type Block

type Block struct {
	Kind    BlockKind
	Handle  string
	Start   int64
	End     int64
	Segment *Segment
	Cell    *Cell // enclosing table cell, nil at top level

	Paragraph    *Paragraph
	Table        *Table
	TOC          *TOC
	SectionBreak *SectionBreakInfo

	Inserted []string // suggestion ids that insert this block
	Deleted  []string // suggestion ids that delete this block

	// Wire is the structural element the block was parsed from, for the
	// raw read format.
	Wire *gdocs.StructuralElement
}

Block is one structural element with its UTF-16 range.

func Flatten

func Flatten(blocks []*Block) []*Block

Flatten lists blocks in document order, descending into table cells and tables of contents.

func (*Block) IsBlankParagraph added in v0.3.0

func (b *Block) IsBlankParagraph() bool

IsBlankParagraph reports whether the block is a paragraph holding nothing but whitespace: empty, or holding only spaces, as a footnote Google has just created does. Content written there fills it, which removes that whitespace, so a paragraph holding an image, a footnote reference, a chip, an equation or a break is never blank however little text it shows.

func (*Block) IsHeading

func (b *Block) IsHeading() bool

IsHeading reports whether the block is a heading paragraph.

func (*Block) Text

func (b *Block) Text(v View) string

Text returns a block's plain text: paragraphs directly, tables as rows of tab-separated cells, other kinds empty.

func (*Block) Words added in v0.3.0

func (b *Block) Words(v View) int

Words counts the block's words in the view: a paragraph's own, a table's or table of contents' nested paragraphs summed.

type BlockKind

type BlockKind string

BlockKind is the structural element type.

const (
	KindParagraph    BlockKind = "paragraph"
	KindTable        BlockKind = "table"
	KindSectionBreak BlockKind = "section_break"
	KindTOC          BlockKind = "toc"
)

Block kinds.

type Border added in v0.6.0

type Border struct {
	Color     string // #rrggbb, "" when unset
	WidthPt   float64
	PaddingPt float64
	DashStyle string // SOLID, DOT, DASH or ""
}

Border is one edge of a paragraph or table cell. Paragraph borders carry padding; cell borders do not.

type BulletInfo

type BulletInfo struct {
	ListID  string
	Nesting int
	Ordered bool
	Glyph   string
	// Number is the item's 1-based position among the preceding siblings
	// of the same list and level, restarting after any interruption.
	Number int
}

BulletInfo is list membership.

type Cell

type Cell struct {
	Table      *Table
	Row        int // 1-based
	Col        int // 1-based
	Handle     string
	Start      int64
	End        int64
	RowSpan    int
	ColSpan    int
	Blocks     []*Block
	MergedInto *Cell
	// Style is what the cell carries itself: background, content
	// alignment, per-side padding and borders.
	Style CellStyle
}

Cell is one table cell with its nested blocks. A cell covered by another cell's span stays in the grid (the API keeps it, empty) and points at the head cell through MergedInto.

func (*Cell) ContentEnd

func (c *Cell) ContentEnd() int64

ContentEnd is the index before the cell's final newline, the last position text can occupy.

func (*Cell) Covered added in v0.2.0

func (c *Cell) Covered() bool

Covered reports whether another cell's span hides this one.

func (*Cell) Text

func (c *Cell) Text(v View) string

Text joins the cell's blocks with newlines.

type CellStyle added in v0.6.0

type CellStyle struct {
	Background                                       string // #rrggbb, "" when unset
	ContentAlignment                                 string // TOP, MIDDLE, BOTTOM or ""
	PaddingTopPt                                     float64
	PaddingBottomPt                                  float64
	PaddingLeftPt                                    float64
	PaddingRightPt                                   float64
	BorderTop, BorderBottom, BorderLeft, BorderRight *Border
}

CellStyle is a table cell's own formatting.

type Document

type Document struct {
	ID                  string
	Title               string
	RevisionID          string
	SuggestionsViewMode string
	// Tabs in document order, parents before children.
	Tabs []*Tab
	// contains filtered or unexported fields
}

Document is a parsed documents.get response.

func Parse

func Parse(d *gdocs.Document) (*Document, error)

Parse converts a documents.get response into the model.

func (*Document) AllBlocks

func (d *Document) AllBlocks() []*Block

AllBlocks lists every block of every tab and segment in document order.

func (*Document) FindCell

func (d *Document) FindCell(handle string) (*Cell, bool)

FindCell looks a cell handle (tbl1:r2c3) up across the document.

func (*Document) FindHandle

func (d *Document) FindHandle(handle string) (*Block, bool)

FindHandle looks a handle up across every tab and segment.

func (*Document) HeadingByID

func (d *Document) HeadingByID(id string) (*Tab, Section, bool)

HeadingByID searches every tab's body for a heading id.

func (*Document) Stats

func (d *Document) Stats() Stats

Stats counts the document's content in the committed view.

func (*Document) Tab

func (d *Document) Tab(ref string) (*Tab, bool)

Tab finds a tab by id, then by title (case-insensitive), then by "tabN" or a bare number. The empty reference is the first tab.

type InlineObjectInfo

type InlineObjectInfo struct {
	ID          string
	Kind        string // image, drawing, chart, object
	Title       string
	Description string
	SourceURI   string
	ContentURI  string
	WidthPt     float64
	HeightPt    float64
}

InlineObjectInfo describes an inline image, drawing or chart.

type ListInfo

type ListInfo struct {
	ID     string
	Levels []ListLevel
}

ListInfo describes a list's nesting levels.

type ListLevel

type ListLevel struct {
	Ordered   bool
	Glyph     string
	GlyphType string
}

ListLevel is one nesting level of a list.

type NamedRange added in v0.4.0

type NamedRange struct {
	ID      string
	Name    string
	Segment string
	Start   int64
	End     int64
}

NamedRange is a span the document remembers by name. Unlike a handle it survives edits, because Google moves it with the text it covers.

type NamedStyleDef added in v0.5.0

type NamedStyleDef struct {
	Type string // NORMAL_TEXT, TITLE, SUBTITLE, HEADING_1..6
	Text TextStyle
	ParagraphStyle
}

NamedStyleDef is what one named style means in a tab: the formatting every paragraph carrying it inherits, and so the formatting a paragraph shows unless it overrides it.

type PageSetup added in v0.4.0

type PageSetup struct {
	WidthPt         float64
	HeightPt        float64
	MarginTopPt     float64
	MarginBottomPt  float64
	MarginLeftPt    float64
	MarginRightPt   float64
	MarginHeaderPt  float64
	MarginFooterPt  float64
	PageNumberStart int64
	Landscape       bool
	FirstPageHF     bool
	EvenPageHF      bool
	Background      string
}

PageSetup is a tab's page size, margins and header/footer choices.

type Paragraph

type Paragraph struct {
	NamedStyle string
	HeadingID  string
	Level      int // 1..6 for HEADING_n, 0 otherwise
	IsTitle    bool
	IsSubtitle bool
	// ParagraphStyle is what this paragraph carries itself; where it
	// says nothing, the tab's definition of NamedStyle applies.
	ParagraphStyle
	Bullet              *BulletInfo
	Runs                []*Run
	PositionedObjectIDs []string
}

Paragraph is a paragraph's style, bullet and runs.

func (*Paragraph) Count added in v0.3.0

func (p *Paragraph) Count(v View) (words, chars int)

Count returns the words and characters of the paragraph's text in the view, as WordCount and a rune count of Text would, without building the string.

func (*Paragraph) Text

func (p *Paragraph) Text(v View) string

Text returns the paragraph's plain text in the view, without the trailing newline. Chips contribute their display text; objects and breaks contribute nothing.

type ParagraphStyle added in v0.5.0

type ParagraphStyle struct {
	Alignment           string
	Direction           string // LEFT_TO_RIGHT, RIGHT_TO_LEFT or ""
	SpacingMode         string // NEVER_COLLAPSE, COLLAPSE_LISTS or ""
	LineSpacing         float64
	SpaceAbovePt        float64
	SpaceBelowPt        float64
	IndentStartPt       float64
	IndentEndPt         float64
	IndentFirstLinePt   float64
	KeepWithNext        bool
	KeepLinesTogether   bool
	AvoidWidowAndOrphan bool
	PageBreakBefore     bool
	// Shading is the paragraph's background as #rrggbb, "" when unset.
	Shading string
	// Borders are the paragraph's edges, nil when unset. Between is the
	// border drawn between consecutive paragraphs sharing it.
	BorderTop, BorderBottom, BorderLeft, BorderRight, BorderBetween *Border
	// TabStops are read-only: the API reports them and refuses to set
	// them, so nothing here writes them back.
	TabStops []TabStop
}

ParagraphStyle is block-level formatting, in the units the API uses: line spacing is a percentage of single (100 = single) and lengths are points. A named style defines one, and a paragraph shows it unless an edit overrode it on the paragraph itself, so both carry this type.

type Run

type Run struct {
	Kind  RunKind
	Start int64
	End   int64
	Text  string // text content; display text for chips
	Style TextStyle

	ObjectID       string
	FootnoteID     string
	FootnoteNumber string
	PersonName     string
	PersonEmail    string
	LinkTitle      string
	LinkURI        string
	AutoTextType   string

	Inserted []string
	Deleted  []string
}

Run is one paragraph element.

func (*Run) ContributesText added in v0.3.0

func (r *Run) ContributesText() bool

ContributesText reports whether the run puts characters in the paragraph's plain text: text and the chips that show their label.

func (*Run) IsSuggestedDeletion

func (r *Run) IsSuggestedDeletion() bool

IsSuggestedDeletion reports whether a suggestion removes the run.

func (*Run) IsSuggestedInsertion

func (r *Run) IsSuggestedInsertion() bool

IsSuggestedInsertion reports whether the run exists only as a suggestion.

func (*Run) Visible

func (r *Run) Visible(v View) bool

Visible reports whether the run shows in the view.

type RunKind

type RunKind string

RunKind is the paragraph element type.

const (
	RunText           RunKind = "text"
	RunInlineObject   RunKind = "inline_object"
	RunFootnoteRef    RunKind = "footnote_ref"
	RunPageBreak      RunKind = "page_break"
	RunColumnBreak    RunKind = "column_break"
	RunHorizontalRule RunKind = "horizontal_rule"
	RunPerson         RunKind = "person"
	RunRichLink       RunKind = "rich_link"
	RunDate           RunKind = "date"
	RunEquation       RunKind = "equation"
	RunAutoText       RunKind = "auto_text"
)

Run kinds.

type Section

type Section struct {
	Heading *Block
	Level   int
	From    int
	To      int
}

Section is a heading and the blocks it owns: everything up to the next heading of the same or a higher level. Indices are into Segment.Blocks; From is the heading itself, To is exclusive. A Section with a nil Heading is the preamble before the first heading.

type SectionBreakInfo

type SectionBreakInfo struct {
	Type            string
	DefaultHeaderID string
	DefaultFooterID string
}

SectionBreakInfo is the part of a section break we surface.

type Segment

type Segment struct {
	Kind           SegmentKind
	ID             string // segmentId for the API; "" for the body
	Number         int    // 1-based within its kind and tab
	FootnoteNumber string // visible number for footnotes, when known
	Prefix         string // handle prefix, e.g. "tab2/header1/"
	Tab            *Tab
	Blocks         []*Block
	// contains filtered or unexported fields
}

Segment is one index space: the body, a header, a footer or a footnote.

func (*Segment) AllBlocks

func (s *Segment) AllBlocks() []*Block

AllBlocks lists the segment's blocks in document order, descending into table cells and tables of contents. Parsed segments share one slice across calls; callers must not modify it.

func (*Segment) BlockAt added in v0.3.0

func (s *Segment) BlockAt(index int64) *Block

BlockAt finds the innermost paragraph covering an index of the segment, the enclosing top-level block when no paragraph does, or nil when the index lies outside the segment.

func (*Segment) ContentBlocks

func (s *Segment) ContentBlocks() []*Block

ContentBlocks lists the top-level blocks that carry content (no section breaks).

func (*Segment) ContentStart

func (s *Segment) ContentStart() int64

ContentStart is the first index content occupies: after the leading section break of a body, 0 elsewhere.

func (*Segment) End

func (s *Segment) End() int64

End is one past the segment's final newline.

func (*Segment) Label

func (s *Segment) Label() string

Label names the segment for people: body, header1, footnote3.

func (*Segment) Preamble

func (s *Segment) Preamble() Section

Preamble is the block range before the first heading.

func (*Segment) SectionByHeadingID

func (s *Segment) SectionByHeadingID(id string) (Section, bool)

SectionByHeadingID finds a section by Google's stable heading id.

func (*Segment) Sections

func (s *Segment) Sections() []Section

Sections derives the heading tree of a segment. Only top-level paragraphs count; headings inside tables and tables of contents do not.

func (*Segment) SectionsByHeading

func (s *Segment) SectionsByHeading(text string, level int) []Section

SectionsByHeading finds sections whose heading text matches after normalisation, optionally restricted to a level (0 = any).

type SegmentKind

type SegmentKind string

SegmentKind distinguishes index spaces.

const (
	SegmentBody     SegmentKind = "body"
	SegmentHeader   SegmentKind = "header"
	SegmentFooter   SegmentKind = "footer"
	SegmentFootnote SegmentKind = "footnote"
)

Segment kinds.

type Stats

type Stats struct {
	Tabs          int `json:"tabs"`
	Paragraphs    int `json:"paragraphs"`
	Headings      int `json:"headings"`
	Tables        int `json:"tables"`
	InlineObjects int `json:"inline_objects"`
	// FloatingObjects are images that sit on the page rather than in the
	// text, so no range covers them.
	FloatingObjects int `json:"floating_objects"`
	NamedRanges     int `json:"named_ranges"`
	Footnotes       int `json:"footnotes"`
	Words           int `json:"words"`
	Chars           int `json:"chars"`
	Suggestions     int `json:"pending_suggestions"`
}

Stats are document-wide counts, computed over every tab's body.

type TOC

type TOC struct {
	Blocks []*Block
}

TOC is a table of contents; read-only in the API.

type Tab

type Tab struct {
	ID       string
	Title    string
	Number   int // 1-based position in Document.Tabs
	Index    int64
	ParentID string
	Nesting  int

	Body      *Segment
	Headers   []*Segment
	Footers   []*Segment
	Footnotes []*Segment

	Lists         map[string]*ListInfo
	InlineObjects map[string]*InlineObjectInfo
	// PositionedObjects are floating images, keyed by object id. They sit
	// on a paragraph rather than in its text, so no range covers them and
	// only delete_object removes one.
	PositionedObjects map[string]*InlineObjectInfo
	// NamedRanges are the tab's named ranges by name, in name order. A
	// name can cover several ranges.
	NamedRanges []*NamedRange
	// Page is the tab's page setup.
	Page *PageSetup
	// NamedStyles are the tab's named style definitions, in
	// NamedStyleOrder. Every paragraph inherits from the one its
	// NamedStyle names, and layout_document named_style redefines them.
	NamedStyles []*NamedStyleDef
}

Tab is one document tab. Documents without tabs get a single synthetic tab so callers have one code path.

func (*Tab) NamedStyleUse added in v0.5.0

func (t *Tab) NamedStyleUse() map[string]int

NamedStyleUse counts the tab's paragraphs by the named style they carry, so a read can report the definitions actually in use rather than all nine. Every segment counts, not just the body: redefining a style changes the whole tab, headers and footnotes with it. A paragraph that names no style carries NORMAL_TEXT, which is what leaving the field out means.

func (*Tab) Prefix

func (t *Tab) Prefix() string

Prefix is the handle prefix for this tab ("" for the first tab).

func (*Tab) Segments

func (t *Tab) Segments() []*Segment

Segments returns body, headers, footers and footnotes in that order.

type TabStop added in v0.6.0

type TabStop struct {
	OffsetPt  float64
	Alignment string // START, CENTER, END
}

TabStop is one read-only tab stop.

type Table

type Table struct {
	Handle string
	Rows   int
	Cols   int
	Cells  [][]*Cell
}

Table is a grid of cells.

type TextStyle

type TextStyle struct {
	Bold          bool
	Italic        bool
	Underline     bool
	Strikethrough bool
	SmallCaps     bool
	Baseline      string // SUPERSCRIPT, SUBSCRIPT or ""
	FontFamily    string
	FontSizePt    float64
	Foreground    string // #rrggbb or ""
	Background    string
	LinkURL       string
	LinkHeadingID string
	LinkBookmark  string
	LinkTabID     string
}

TextStyle is the subset of character formatting we render and compare. All fields are comparable so styles can be tested with ==.

func (s TextStyle) HasLink() bool

HasLink reports whether the style carries any link.

func (TextStyle) Monospace

func (s TextStyle) Monospace() bool

Monospace reports whether the font is a code font.

type View

type View int

View selects how suggestions are folded into text.

const (
	// ViewInline keeps every run, matching the API's index space.
	ViewInline View = iota
	// ViewCurrent hides suggested insertions: the document as committed.
	ViewCurrent
	// ViewAccepted hides suggested deletions: the document if all
	// suggestions were accepted.
	ViewAccepted
)

Views.

Directories

Path Synopsis
Package doctest loads the synthetic document fixture for tests in several packages.
Package doctest loads the synthetic document fixture for tests in several packages.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL