From 917c2debe7aeeb6017208520c474309d6d30cfa1 Mon Sep 17 00:00:00 2001 From: Andrew Morozko Date: Fri, 6 Sep 2024 12:54:16 +0400 Subject: [PATCH] AST encoder, decoder and builder --- go.mod | 3 +- go.sum | 6 +- plugin/ast/builder.go | 306 ++ plugin/ast/parser.go | 61 + plugin/ast/v1/ast.pb.go | 3140 +++++++++++++++++ plugin/ast/v1/ast_decoder.go | 274 ++ plugin/ast/v1/ast_encoder.go | 361 ++ plugin/ast/v1/ast_test.go | 98 + plugin/ast/v1/enum_codec.go | 116 + plugin/ast/v1/interfaces.go | 306 ++ .../fuzz/FuzzEncoder/2a2178732c0ce29f | 2 + .../fuzz/FuzzEncoder/6b5e47038908d6af | 2 + .../fuzz/FuzzEncoder/ad3dae11905f3e82 | 2 + plugin/ast/v1/util.go | 11 + proto/ast/v1/ast.proto | 242 ++ 15 files changed, 4927 insertions(+), 3 deletions(-) create mode 100644 plugin/ast/builder.go create mode 100644 plugin/ast/parser.go create mode 100644 plugin/ast/v1/ast.pb.go create mode 100644 plugin/ast/v1/ast_decoder.go create mode 100644 plugin/ast/v1/ast_encoder.go create mode 100644 plugin/ast/v1/ast_test.go create mode 100644 plugin/ast/v1/enum_codec.go create mode 100644 plugin/ast/v1/interfaces.go create mode 100644 plugin/ast/v1/testdata/fuzz/FuzzEncoder/2a2178732c0ce29f create mode 100644 plugin/ast/v1/testdata/fuzz/FuzzEncoder/6b5e47038908d6af create mode 100644 plugin/ast/v1/testdata/fuzz/FuzzEncoder/ad3dae11905f3e82 create mode 100644 plugin/ast/v1/util.go create mode 100644 proto/ast/v1/ast.proto diff --git a/go.mod b/go.mod index b7c5a563..238a8d6d 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Masterminds/sprig/v3 v3.2.3 github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 + github.com/blackstork-io/goldmark-markdown v0.1.1 github.com/elastic/go-elasticsearch/v8 v8.14.0 github.com/evanphx/go-hclog-slog v0.0.0-20240717231540-be48fc4c4df5 github.com/gobwas/glob v0.2.3 @@ -33,7 +34,7 @@ require ( github.com/testcontainers/testcontainers-go/modules/elasticsearch v0.32.0 github.com/testcontainers/testcontainers-go/modules/postgres v0.32.0 github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.46 - github.com/yuin/goldmark v1.7.1 + github.com/yuin/goldmark v1.7.4 github.com/zclconf/go-cty v1.14.4 go.opentelemetry.io/contrib/bridges/otelslog v0.1.0 go.opentelemetry.io/contrib/instrumentation/host v0.51.0 diff --git a/go.sum b/go.sum index 7100142d..b94f19ae 100644 --- a/go.sum +++ b/go.sum @@ -41,6 +41,8 @@ github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x0 github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= +github.com/blackstork-io/goldmark-markdown v0.1.1 h1:58uV/NB6jhKG8sPIVHRNgrzeMZvty9Qzk3q9UJ/17+8= +github.com/blackstork-io/goldmark-markdown v0.1.1/go.mod h1:0r4jctdZOy9oirGo/NikVBdPL4h+3TSs3e2hYRkGEs8= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= @@ -304,8 +306,8 @@ github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.46/go.mod h1:YCJyt5TSr4luj4 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U= -github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg= +github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8= diff --git a/plugin/ast/builder.go b/plugin/ast/builder.go new file mode 100644 index 00000000..4297767c --- /dev/null +++ b/plugin/ast/builder.go @@ -0,0 +1,306 @@ +package ast + +import ( + "bytes" + "regexp" + + astv1 "github.com/blackstork-io/fabric/plugin/ast/v1" +) + +// inlines + +func CodeSpan(code []byte) *astv1.Node_CodeSpan { + return &astv1.Node_CodeSpan{ + CodeSpan: &astv1.CodeSpan{ + Base: &astv1.BaseNode{ + Children: []*astv1.Node{{ + Kind: &astv1.Node_Text{ + Text: &astv1.Text{ + Base: &astv1.BaseNode{}, + Segment: code, + Raw: true, + }, + }, + }}, + }, + }, + } +} + +func emphasis(level int64, children []astv1.InlineContent) *astv1.Node_Emphasis { + return &astv1.Node_Emphasis{ + Emphasis: &astv1.Emphasis{ + Base: &astv1.BaseNode{ + Children: astv1.Inlines.ExtendNodes(children, nil), + }, + Level: level, + }, + } +} + +func Emphasis(children ...astv1.InlineContent) *astv1.Node_Emphasis { + return emphasis(1, children) +} + +var Italic = Emphasis + +func StrongEmphasis(children ...astv1.InlineContent) *astv1.Node_Emphasis { + return emphasis(2, children) +} + +var Bold = StrongEmphasis + +func Strikethrough(children ...astv1.InlineContent) *astv1.Node_Strikethrough { + return &astv1.Node_Strikethrough{ + Strikethrough: &astv1.Strikethrough{ + Base: &astv1.BaseNode{ + Children: astv1.Inlines.ExtendNodes(children, nil), + }, + }, + } +} + +func Link(text ...astv1.InlineContent) *astv1.LinkOrImage { + return &astv1.LinkOrImage{ + Base: &astv1.BaseNode{ + Children: astv1.Inlines.ExtendNodes(text, nil), + }, + IsImage: false, + } +} + +func Image(alt ...astv1.InlineContent) *astv1.LinkOrImage { + return &astv1.LinkOrImage{ + Base: &astv1.BaseNode{ + Children: astv1.Inlines.ExtendNodes(alt, nil), + }, + IsImage: true, + } +} + +func AutoLink(url string) *astv1.Node_AutoLink { + before, after, found := bytes.Cut([]byte(url), []byte("://")) + if found { + return &astv1.Node_AutoLink{ + AutoLink: &astv1.AutoLink{ + Base: &astv1.BaseNode{}, + Type: astv1.AutoLinkType_AUTO_LINK_TYPE_URL, + Protocol: before, + Value: after, + }, + } + } else { + return &astv1.Node_AutoLink{ + AutoLink: &astv1.AutoLink{ + Base: &astv1.BaseNode{}, + Type: astv1.AutoLinkType_AUTO_LINK_TYPE_EMAIL, + Value: before, + }, + } + } +} + +func AutoLinkEmail(email string) *astv1.Node_AutoLink { + return &astv1.Node_AutoLink{ + AutoLink: &astv1.AutoLink{ + Base: &astv1.BaseNode{}, + Type: astv1.AutoLinkType_AUTO_LINK_TYPE_EMAIL, + Value: []byte(email), + }, + } +} + +func InlineHTML(html string) *astv1.Node_RawHtml { + return &astv1.Node_RawHtml{ + RawHtml: &astv1.RawHTML{ + Base: &astv1.BaseNode{}, + Segments: [][]byte{[]byte(html)}, + }, + } +} + +func LineBreak() *astv1.Node_Text { + return &astv1.Node_Text{ + Text: &astv1.Text{ + Base: &astv1.BaseNode{}, + Segment: nil, + HardLineBreak: true, + }, + } +} + +var textHardBreakRegexp = regexp.MustCompile(`( {2,}\n *|\\\n *)`) + +func splitBytes(re *regexp.Regexp, s []byte, n int) [][]byte { + if n == 0 { + return nil + } + + if len(s) == 0 { + return [][]byte{nil} + } + + matches := re.FindAllIndex(s, n) + subBytes := make([][]byte, 0, len(matches)) + + beg := 0 + end := 0 + for _, match := range matches { + if n > 0 && len(subBytes) >= n-1 { + break + } + + end = match[0] + if match[1] != 0 { + subBytes = append(subBytes, s[beg:end]) + } + beg = match[1] + } + + if end != len(s) { + subBytes = append(subBytes, s[beg:]) + } + + return subBytes +} + +func convertSoftBreaks(txt []byte) (res []*astv1.Text) { + split := bytes.Split(txt, []byte("\n")) + res = make([]*astv1.Text, 0, len(split)) + res = append(res, &astv1.Text{ + Segment: split[0], + }) + for i, s := range split[1:] { + res[i].SoftLineBreak = true + res = append(res, &astv1.Text{ + Segment: s, + }) + } + return +} + +func convertHardBreaks(txt []byte) (res []*astv1.Text) { + split := splitBytes(textHardBreakRegexp, txt, -1) + res = make([]*astv1.Text, 0, len(split)) + res = append(res, convertSoftBreaks(split[0])...) + for i, s := range split[1:] { + res[i].HardLineBreak = true + res = append(res, convertSoftBreaks(s)...) + } + return +} + +func Text(text string) (res astv1.Inlines) { + txt := convertHardBreaks([]byte(text)) + res = make(astv1.Inlines, len(txt)) + for i, t := range txt { + res[i] = &astv1.Node_Text{ + Text: t, + } + } + return +} + +// container blocks +func Blockquote(children ...astv1.BlockContent) *astv1.Node_Blockquote { + return &astv1.Node_Blockquote{ + Blockquote: &astv1.Blockquote{ + Base: &astv1.BaseNode{ + Children: astv1.Blocks.ExtendNodes(children, nil), + }, + }, + } +} + +type listMarker uint32 + +const ( + Period listMarker = '.' + Paren listMarker = ')' + Star listMarker = '*' + Plus listMarker = '+' + Hyphen listMarker = '-' +) + +func List(marker listMarker) *astv1.Node_List { + return &astv1.Node_List{ + List: &astv1.List{ + Base: &astv1.BaseNode{}, + Marker: uint32(marker), + }, + } +} + +func ThematicBreak() *astv1.Node_ThematicBreak { + return &astv1.Node_ThematicBreak{ + ThematicBreak: &astv1.ThematicBreak{ + Base: &astv1.BaseNode{}, + }, + } +} + +func Header(level uint32, children ...astv1.InlineContent) *astv1.Node_Heading { + return &astv1.Node_Heading{ + Heading: &astv1.Heading{ + Base: &astv1.BaseNode{ + Children: astv1.Inlines.ExtendNodes(children, nil), + }, + Level: max(1, min(level, 6)), + }, + } +} + +func IndentedCodeBlock(code []byte) *astv1.Node_CodeBlock { + return &astv1.Node_CodeBlock{ + CodeBlock: &astv1.CodeBlock{ + Base: &astv1.BaseNode{}, + Lines: bytes.Split(code, []byte("\n")), + }, + } +} + +func FencedCodeBlock(code []byte) *astv1.Node_FencedCodeBlock { + return &astv1.Node_FencedCodeBlock{ + FencedCodeBlock: &astv1.FencedCodeBlock{ + Base: &astv1.BaseNode{}, + Info: nil, + Lines: bytes.Split(code, []byte("\n")), + }, + } +} + +func HTMLBlock(html []byte) *astv1.Node_HtmlBlock { + return &astv1.Node_HtmlBlock{ + HtmlBlock: &astv1.HTMLBlock{ + Base: &astv1.BaseNode{}, + // setting the value to most general type, hopefully renderers don't care + Type: astv1.HTMLBlockType_HTML_BLOCK_TYPE_7, + Lines: bytes.Split(html, []byte("\n")), + }, + } +} + +func Paragraph(children ...astv1.InlineContent) *astv1.Node_Paragraph { + return &astv1.Node_Paragraph{ + Paragraph: &astv1.Paragraph{ + Base: &astv1.BaseNode{ + Children: astv1.Inlines.ExtendNodes(children, nil), + }, + }, + } +} + +var ( + AlignLeft = astv1.CellAlignment_CELL_ALIGNMENT_LEFT + AlignRight = astv1.CellAlignment_CELL_ALIGNMENT_RIGHT + AlignCenter = astv1.CellAlignment_CELL_ALIGNMENT_CENTER + AlignNone = astv1.CellAlignment_CELL_ALIGNMENT_NONE +) + +func Table() *astv1.Node_Table { + return &astv1.Node_Table{ + Table: &astv1.Table{ + Base: &astv1.BaseNode{}, + }, + } +} diff --git a/plugin/ast/parser.go b/plugin/ast/parser.go new file mode 100644 index 00000000..60a268ea --- /dev/null +++ b/plugin/ast/parser.go @@ -0,0 +1,61 @@ +package ast + +import ( + "bytes" + "fmt" + + markdown "github.com/blackstork-io/goldmark-markdown" + "github.com/yuin/goldmark" + "github.com/yuin/goldmark/extension" + "github.com/yuin/goldmark/text" + + astv1 "github.com/blackstork-io/fabric/plugin/ast/v1" +) + +// Converts markdown source to ast nodes +func FromMarkdown(source []byte) (nodes []*astv1.Node, err error) { + md := goldmark.New( + goldmark.WithExtensions( + extension.Table, + extension.Strikethrough, + extension.TaskList, + ), + ) + + tree := md.Parser().Parse(text.NewReader(source)) + + encodedTree, err := astv1.Encode(tree, source) + if err != nil { + err = fmt.Errorf("failed to encode the ast: %w", err) + return + } + + nodes = encodedTree.GetDocument().GetBase().GetChildren() + return +} + +// Converts ast node to markdown source +func ToMarkdown(node *astv1.Node) (source []byte, err error) { + astNode, src, err := astv1.Decode(node) + if err != nil { + return nil, fmt.Errorf("failed to decode AST: %w", err) + } + + md := goldmark.New( + goldmark.WithExtensions( + extension.Table, + extension.Strikethrough, + extension.TaskList, + ), + ) + + renderer := markdown.NewRenderer() + renderer.AddOptions(markdown.WithParser(md.Parser())) + var buf bytes.Buffer + err = renderer.Render(&buf, src, astNode) + if err != nil { + return nil, fmt.Errorf("failed to render AST to markdown: %w", err) + } + source = buf.Bytes() + return +} diff --git a/plugin/ast/v1/ast.pb.go b/plugin/ast/v1/ast.pb.go new file mode 100644 index 00000000..68bdc63d --- /dev/null +++ b/plugin/ast/v1/ast.pb.go @@ -0,0 +1,3140 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.2 +// protoc (unknown) +// source: ast/v1/ast.proto + +package astv1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + anypb "google.golang.org/protobuf/types/known/anypb" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type HTMLBlockType int32 + +const ( + HTMLBlockType_HTML_BLOCK_TYPE_UNSPECIFIED HTMLBlockType = 0 + HTMLBlockType_HTML_BLOCK_TYPE_1 HTMLBlockType = 1 + HTMLBlockType_HTML_BLOCK_TYPE_2 HTMLBlockType = 2 + HTMLBlockType_HTML_BLOCK_TYPE_3 HTMLBlockType = 3 + HTMLBlockType_HTML_BLOCK_TYPE_4 HTMLBlockType = 4 + HTMLBlockType_HTML_BLOCK_TYPE_5 HTMLBlockType = 5 + HTMLBlockType_HTML_BLOCK_TYPE_6 HTMLBlockType = 6 + HTMLBlockType_HTML_BLOCK_TYPE_7 HTMLBlockType = 7 +) + +// Enum value maps for HTMLBlockType. +var ( + HTMLBlockType_name = map[int32]string{ + 0: "HTML_BLOCK_TYPE_UNSPECIFIED", + 1: "HTML_BLOCK_TYPE_1", + 2: "HTML_BLOCK_TYPE_2", + 3: "HTML_BLOCK_TYPE_3", + 4: "HTML_BLOCK_TYPE_4", + 5: "HTML_BLOCK_TYPE_5", + 6: "HTML_BLOCK_TYPE_6", + 7: "HTML_BLOCK_TYPE_7", + } + HTMLBlockType_value = map[string]int32{ + "HTML_BLOCK_TYPE_UNSPECIFIED": 0, + "HTML_BLOCK_TYPE_1": 1, + "HTML_BLOCK_TYPE_2": 2, + "HTML_BLOCK_TYPE_3": 3, + "HTML_BLOCK_TYPE_4": 4, + "HTML_BLOCK_TYPE_5": 5, + "HTML_BLOCK_TYPE_6": 6, + "HTML_BLOCK_TYPE_7": 7, + } +) + +func (x HTMLBlockType) Enum() *HTMLBlockType { + p := new(HTMLBlockType) + *p = x + return p +} + +func (x HTMLBlockType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (HTMLBlockType) Descriptor() protoreflect.EnumDescriptor { + return file_ast_v1_ast_proto_enumTypes[0].Descriptor() +} + +func (HTMLBlockType) Type() protoreflect.EnumType { + return &file_ast_v1_ast_proto_enumTypes[0] +} + +func (x HTMLBlockType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use HTMLBlockType.Descriptor instead. +func (HTMLBlockType) EnumDescriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{0} +} + +type AutoLinkType int32 + +const ( + AutoLinkType_AUTO_LINK_TYPE_UNSPECIFIED AutoLinkType = 0 + AutoLinkType_AUTO_LINK_TYPE_EMAIL AutoLinkType = 1 + AutoLinkType_AUTO_LINK_TYPE_URL AutoLinkType = 2 +) + +// Enum value maps for AutoLinkType. +var ( + AutoLinkType_name = map[int32]string{ + 0: "AUTO_LINK_TYPE_UNSPECIFIED", + 1: "AUTO_LINK_TYPE_EMAIL", + 2: "AUTO_LINK_TYPE_URL", + } + AutoLinkType_value = map[string]int32{ + "AUTO_LINK_TYPE_UNSPECIFIED": 0, + "AUTO_LINK_TYPE_EMAIL": 1, + "AUTO_LINK_TYPE_URL": 2, + } +) + +func (x AutoLinkType) Enum() *AutoLinkType { + p := new(AutoLinkType) + *p = x + return p +} + +func (x AutoLinkType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (AutoLinkType) Descriptor() protoreflect.EnumDescriptor { + return file_ast_v1_ast_proto_enumTypes[1].Descriptor() +} + +func (AutoLinkType) Type() protoreflect.EnumType { + return &file_ast_v1_ast_proto_enumTypes[1] +} + +func (x AutoLinkType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use AutoLinkType.Descriptor instead. +func (AutoLinkType) EnumDescriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{1} +} + +type CellAlignment int32 + +const ( + CellAlignment_CELL_ALIGNMENT_UNSPECIFIED CellAlignment = 0 + CellAlignment_CELL_ALIGNMENT_LEFT CellAlignment = 1 + CellAlignment_CELL_ALIGNMENT_RIGHT CellAlignment = 2 + CellAlignment_CELL_ALIGNMENT_CENTER CellAlignment = 3 + CellAlignment_CELL_ALIGNMENT_NONE CellAlignment = 4 +) + +// Enum value maps for CellAlignment. +var ( + CellAlignment_name = map[int32]string{ + 0: "CELL_ALIGNMENT_UNSPECIFIED", + 1: "CELL_ALIGNMENT_LEFT", + 2: "CELL_ALIGNMENT_RIGHT", + 3: "CELL_ALIGNMENT_CENTER", + 4: "CELL_ALIGNMENT_NONE", + } + CellAlignment_value = map[string]int32{ + "CELL_ALIGNMENT_UNSPECIFIED": 0, + "CELL_ALIGNMENT_LEFT": 1, + "CELL_ALIGNMENT_RIGHT": 2, + "CELL_ALIGNMENT_CENTER": 3, + "CELL_ALIGNMENT_NONE": 4, + } +) + +func (x CellAlignment) Enum() *CellAlignment { + p := new(CellAlignment) + *p = x + return p +} + +func (x CellAlignment) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (CellAlignment) Descriptor() protoreflect.EnumDescriptor { + return file_ast_v1_ast_proto_enumTypes[2].Descriptor() +} + +func (CellAlignment) Type() protoreflect.EnumType { + return &file_ast_v1_ast_proto_enumTypes[2] +} + +func (x CellAlignment) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use CellAlignment.Descriptor instead. +func (CellAlignment) EnumDescriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{2} +} + +type Attribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name []byte `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Types that are assignable to Value: + // + // *Attribute_Bytes + // *Attribute_Str + Value isAttribute_Value `protobuf_oneof:"value"` +} + +func (x *Attribute) Reset() { + *x = Attribute{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Attribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Attribute) ProtoMessage() {} + +func (x *Attribute) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Attribute.ProtoReflect.Descriptor instead. +func (*Attribute) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{0} +} + +func (x *Attribute) GetName() []byte { + if x != nil { + return x.Name + } + return nil +} + +func (m *Attribute) GetValue() isAttribute_Value { + if m != nil { + return m.Value + } + return nil +} + +func (x *Attribute) GetBytes() []byte { + if x, ok := x.GetValue().(*Attribute_Bytes); ok { + return x.Bytes + } + return nil +} + +func (x *Attribute) GetStr() string { + if x, ok := x.GetValue().(*Attribute_Str); ok { + return x.Str + } + return "" +} + +type isAttribute_Value interface { + isAttribute_Value() +} + +type Attribute_Bytes struct { + Bytes []byte `protobuf:"bytes,2,opt,name=bytes,proto3,oneof"` +} + +type Attribute_Str struct { + Str string `protobuf:"bytes,3,opt,name=str,proto3,oneof"` +} + +func (*Attribute_Bytes) isAttribute_Value() {} + +func (*Attribute_Str) isAttribute_Value() {} + +type BaseNode struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Children []*Node `protobuf:"bytes,1,rep,name=children,proto3" json:"children,omitempty"` + Attributes []*Attribute `protobuf:"bytes,2,rep,name=attributes,proto3" json:"attributes,omitempty"` + // value meaningful only for blocks + BlankPreviousLines bool `protobuf:"varint,3,opt,name=blank_previous_lines,json=blankPreviousLines,proto3" json:"blank_previous_lines,omitempty"` +} + +func (x *BaseNode) Reset() { + *x = BaseNode{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BaseNode) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BaseNode) ProtoMessage() {} + +func (x *BaseNode) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BaseNode.ProtoReflect.Descriptor instead. +func (*BaseNode) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{1} +} + +func (x *BaseNode) GetChildren() []*Node { + if x != nil { + return x.Children + } + return nil +} + +func (x *BaseNode) GetAttributes() []*Attribute { + if x != nil { + return x.Attributes + } + return nil +} + +func (x *BaseNode) GetBlankPreviousLines() bool { + if x != nil { + return x.BlankPreviousLines + } + return false +} + +type Node struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Kind: + // + // *Node_Document + // *Node_TextBlock + // *Node_Paragraph + // *Node_Heading + // *Node_ThematicBreak + // *Node_CodeBlock + // *Node_FencedCodeBlock + // *Node_Blockquote + // *Node_List + // *Node_ListItem + // *Node_HtmlBlock + // *Node_Text + // *Node_String_ + // *Node_CodeSpan + // *Node_Emphasis + // *Node_LinkOrImage + // *Node_AutoLink + // *Node_RawHtml + // *Node_Table + // *Node_TableRow + // *Node_TableCell + // *Node_TaskCheckbox + // *Node_Strikethrough + // *Node_PluginMeta + // *Node_Other + Kind isNode_Kind `protobuf_oneof:"kind"` +} + +func (x *Node) Reset() { + *x = Node{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Node) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Node) ProtoMessage() {} + +func (x *Node) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Node.ProtoReflect.Descriptor instead. +func (*Node) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{2} +} + +func (m *Node) GetKind() isNode_Kind { + if m != nil { + return m.Kind + } + return nil +} + +func (x *Node) GetDocument() *Document { + if x, ok := x.GetKind().(*Node_Document); ok { + return x.Document + } + return nil +} + +func (x *Node) GetTextBlock() *TextBlock { + if x, ok := x.GetKind().(*Node_TextBlock); ok { + return x.TextBlock + } + return nil +} + +func (x *Node) GetParagraph() *Paragraph { + if x, ok := x.GetKind().(*Node_Paragraph); ok { + return x.Paragraph + } + return nil +} + +func (x *Node) GetHeading() *Heading { + if x, ok := x.GetKind().(*Node_Heading); ok { + return x.Heading + } + return nil +} + +func (x *Node) GetThematicBreak() *ThematicBreak { + if x, ok := x.GetKind().(*Node_ThematicBreak); ok { + return x.ThematicBreak + } + return nil +} + +func (x *Node) GetCodeBlock() *CodeBlock { + if x, ok := x.GetKind().(*Node_CodeBlock); ok { + return x.CodeBlock + } + return nil +} + +func (x *Node) GetFencedCodeBlock() *FencedCodeBlock { + if x, ok := x.GetKind().(*Node_FencedCodeBlock); ok { + return x.FencedCodeBlock + } + return nil +} + +func (x *Node) GetBlockquote() *Blockquote { + if x, ok := x.GetKind().(*Node_Blockquote); ok { + return x.Blockquote + } + return nil +} + +func (x *Node) GetList() *List { + if x, ok := x.GetKind().(*Node_List); ok { + return x.List + } + return nil +} + +func (x *Node) GetListItem() *ListItem { + if x, ok := x.GetKind().(*Node_ListItem); ok { + return x.ListItem + } + return nil +} + +func (x *Node) GetHtmlBlock() *HTMLBlock { + if x, ok := x.GetKind().(*Node_HtmlBlock); ok { + return x.HtmlBlock + } + return nil +} + +func (x *Node) GetText() *Text { + if x, ok := x.GetKind().(*Node_Text); ok { + return x.Text + } + return nil +} + +func (x *Node) GetString_() *String { + if x, ok := x.GetKind().(*Node_String_); ok { + return x.String_ + } + return nil +} + +func (x *Node) GetCodeSpan() *CodeSpan { + if x, ok := x.GetKind().(*Node_CodeSpan); ok { + return x.CodeSpan + } + return nil +} + +func (x *Node) GetEmphasis() *Emphasis { + if x, ok := x.GetKind().(*Node_Emphasis); ok { + return x.Emphasis + } + return nil +} + +func (x *Node) GetLinkOrImage() *LinkOrImage { + if x, ok := x.GetKind().(*Node_LinkOrImage); ok { + return x.LinkOrImage + } + return nil +} + +func (x *Node) GetAutoLink() *AutoLink { + if x, ok := x.GetKind().(*Node_AutoLink); ok { + return x.AutoLink + } + return nil +} + +func (x *Node) GetRawHtml() *RawHTML { + if x, ok := x.GetKind().(*Node_RawHtml); ok { + return x.RawHtml + } + return nil +} + +func (x *Node) GetTable() *Table { + if x, ok := x.GetKind().(*Node_Table); ok { + return x.Table + } + return nil +} + +func (x *Node) GetTableRow() *TableRow { + if x, ok := x.GetKind().(*Node_TableRow); ok { + return x.TableRow + } + return nil +} + +func (x *Node) GetTableCell() *TableCell { + if x, ok := x.GetKind().(*Node_TableCell); ok { + return x.TableCell + } + return nil +} + +func (x *Node) GetTaskCheckbox() *TaskCheckbox { + if x, ok := x.GetKind().(*Node_TaskCheckbox); ok { + return x.TaskCheckbox + } + return nil +} + +func (x *Node) GetStrikethrough() *Strikethrough { + if x, ok := x.GetKind().(*Node_Strikethrough); ok { + return x.Strikethrough + } + return nil +} + +func (x *Node) GetPluginMeta() *PluginMetadata { + if x, ok := x.GetKind().(*Node_PluginMeta); ok { + return x.PluginMeta + } + return nil +} + +func (x *Node) GetOther() *OtherKind { + if x, ok := x.GetKind().(*Node_Other); ok { + return x.Other + } + return nil +} + +type isNode_Kind interface { + isNode_Kind() +} + +type Node_Document struct { + // Blocks + Document *Document `protobuf:"bytes,1,opt,name=document,proto3,oneof"` +} + +type Node_TextBlock struct { + TextBlock *TextBlock `protobuf:"bytes,5,opt,name=text_block,json=textBlock,proto3,oneof"` +} + +type Node_Paragraph struct { + Paragraph *Paragraph `protobuf:"bytes,6,opt,name=paragraph,proto3,oneof"` +} + +type Node_Heading struct { + Heading *Heading `protobuf:"bytes,7,opt,name=heading,proto3,oneof"` +} + +type Node_ThematicBreak struct { + ThematicBreak *ThematicBreak `protobuf:"bytes,8,opt,name=thematic_break,json=thematicBreak,proto3,oneof"` +} + +type Node_CodeBlock struct { + CodeBlock *CodeBlock `protobuf:"bytes,9,opt,name=code_block,json=codeBlock,proto3,oneof"` +} + +type Node_FencedCodeBlock struct { + FencedCodeBlock *FencedCodeBlock `protobuf:"bytes,10,opt,name=fenced_code_block,json=fencedCodeBlock,proto3,oneof"` +} + +type Node_Blockquote struct { + Blockquote *Blockquote `protobuf:"bytes,11,opt,name=blockquote,proto3,oneof"` +} + +type Node_List struct { + List *List `protobuf:"bytes,12,opt,name=list,proto3,oneof"` +} + +type Node_ListItem struct { + ListItem *ListItem `protobuf:"bytes,13,opt,name=list_item,json=listItem,proto3,oneof"` +} + +type Node_HtmlBlock struct { + HtmlBlock *HTMLBlock `protobuf:"bytes,14,opt,name=html_block,json=htmlBlock,proto3,oneof"` +} + +type Node_Text struct { + // inlines + Text *Text `protobuf:"bytes,15,opt,name=text,proto3,oneof"` +} + +type Node_String_ struct { + String_ *String `protobuf:"bytes,16,opt,name=string,proto3,oneof"` +} + +type Node_CodeSpan struct { + CodeSpan *CodeSpan `protobuf:"bytes,17,opt,name=code_span,json=codeSpan,proto3,oneof"` +} + +type Node_Emphasis struct { + Emphasis *Emphasis `protobuf:"bytes,18,opt,name=emphasis,proto3,oneof"` +} + +type Node_LinkOrImage struct { + LinkOrImage *LinkOrImage `protobuf:"bytes,19,opt,name=link_or_image,json=linkOrImage,proto3,oneof"` +} + +type Node_AutoLink struct { + AutoLink *AutoLink `protobuf:"bytes,20,opt,name=auto_link,json=autoLink,proto3,oneof"` +} + +type Node_RawHtml struct { + RawHtml *RawHTML `protobuf:"bytes,21,opt,name=raw_html,json=rawHtml,proto3,oneof"` +} + +type Node_Table struct { + // Github Flavored Markdown + Table *Table `protobuf:"bytes,22,opt,name=table,proto3,oneof"` +} + +type Node_TableRow struct { + TableRow *TableRow `protobuf:"bytes,23,opt,name=table_row,json=tableRow,proto3,oneof"` +} + +type Node_TableCell struct { + TableCell *TableCell `protobuf:"bytes,24,opt,name=table_cell,json=tableCell,proto3,oneof"` +} + +type Node_TaskCheckbox struct { + // inline + TaskCheckbox *TaskCheckbox `protobuf:"bytes,25,opt,name=task_checkbox,json=taskCheckbox,proto3,oneof"` +} + +type Node_Strikethrough struct { + Strikethrough *Strikethrough `protobuf:"bytes,26,opt,name=strikethrough,proto3,oneof"` +} + +type Node_PluginMeta struct { + // Root of the plugin-rendered data + PluginMeta *PluginMetadata `protobuf:"bytes,254,opt,name=plugin_meta,json=pluginMeta,proto3,oneof"` +} + +type Node_Other struct { + // Custom node types can be serialized using this + Other *OtherKind `protobuf:"bytes,255,opt,name=other,proto3,oneof"` +} + +func (*Node_Document) isNode_Kind() {} + +func (*Node_TextBlock) isNode_Kind() {} + +func (*Node_Paragraph) isNode_Kind() {} + +func (*Node_Heading) isNode_Kind() {} + +func (*Node_ThematicBreak) isNode_Kind() {} + +func (*Node_CodeBlock) isNode_Kind() {} + +func (*Node_FencedCodeBlock) isNode_Kind() {} + +func (*Node_Blockquote) isNode_Kind() {} + +func (*Node_List) isNode_Kind() {} + +func (*Node_ListItem) isNode_Kind() {} + +func (*Node_HtmlBlock) isNode_Kind() {} + +func (*Node_Text) isNode_Kind() {} + +func (*Node_String_) isNode_Kind() {} + +func (*Node_CodeSpan) isNode_Kind() {} + +func (*Node_Emphasis) isNode_Kind() {} + +func (*Node_LinkOrImage) isNode_Kind() {} + +func (*Node_AutoLink) isNode_Kind() {} + +func (*Node_RawHtml) isNode_Kind() {} + +func (*Node_Table) isNode_Kind() {} + +func (*Node_TableRow) isNode_Kind() {} + +func (*Node_TableCell) isNode_Kind() {} + +func (*Node_TaskCheckbox) isNode_Kind() {} + +func (*Node_Strikethrough) isNode_Kind() {} + +func (*Node_PluginMeta) isNode_Kind() {} + +func (*Node_Other) isNode_Kind() {} + +type Document struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` +} + +func (x *Document) Reset() { + *x = Document{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Document) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Document) ProtoMessage() {} + +func (x *Document) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Document.ProtoReflect.Descriptor instead. +func (*Document) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{3} +} + +func (x *Document) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +type TextBlock struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` +} + +func (x *TextBlock) Reset() { + *x = TextBlock{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TextBlock) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TextBlock) ProtoMessage() {} + +func (x *TextBlock) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TextBlock.ProtoReflect.Descriptor instead. +func (*TextBlock) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{4} +} + +func (x *TextBlock) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +type Paragraph struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` +} + +func (x *Paragraph) Reset() { + *x = Paragraph{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Paragraph) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Paragraph) ProtoMessage() {} + +func (x *Paragraph) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Paragraph.ProtoReflect.Descriptor instead. +func (*Paragraph) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{5} +} + +func (x *Paragraph) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +type Heading struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` + Level uint32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` +} + +func (x *Heading) Reset() { + *x = Heading{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Heading) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Heading) ProtoMessage() {} + +func (x *Heading) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Heading.ProtoReflect.Descriptor instead. +func (*Heading) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{6} +} + +func (x *Heading) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +func (x *Heading) GetLevel() uint32 { + if x != nil { + return x.Level + } + return 0 +} + +type ThematicBreak struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` +} + +func (x *ThematicBreak) Reset() { + *x = ThematicBreak{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ThematicBreak) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ThematicBreak) ProtoMessage() {} + +func (x *ThematicBreak) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ThematicBreak.ProtoReflect.Descriptor instead. +func (*ThematicBreak) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{7} +} + +func (x *ThematicBreak) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +type CodeBlock struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` + Lines [][]byte `protobuf:"bytes,2,rep,name=lines,proto3" json:"lines,omitempty"` +} + +func (x *CodeBlock) Reset() { + *x = CodeBlock{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CodeBlock) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CodeBlock) ProtoMessage() {} + +func (x *CodeBlock) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CodeBlock.ProtoReflect.Descriptor instead. +func (*CodeBlock) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{8} +} + +func (x *CodeBlock) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +func (x *CodeBlock) GetLines() [][]byte { + if x != nil { + return x.Lines + } + return nil +} + +type FencedCodeBlock struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` + Info *Text `protobuf:"bytes,2,opt,name=info,proto3" json:"info,omitempty"` + Lines [][]byte `protobuf:"bytes,3,rep,name=lines,proto3" json:"lines,omitempty"` +} + +func (x *FencedCodeBlock) Reset() { + *x = FencedCodeBlock{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FencedCodeBlock) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FencedCodeBlock) ProtoMessage() {} + +func (x *FencedCodeBlock) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FencedCodeBlock.ProtoReflect.Descriptor instead. +func (*FencedCodeBlock) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{9} +} + +func (x *FencedCodeBlock) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +func (x *FencedCodeBlock) GetInfo() *Text { + if x != nil { + return x.Info + } + return nil +} + +func (x *FencedCodeBlock) GetLines() [][]byte { + if x != nil { + return x.Lines + } + return nil +} + +type Blockquote struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` +} + +func (x *Blockquote) Reset() { + *x = Blockquote{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Blockquote) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Blockquote) ProtoMessage() {} + +func (x *Blockquote) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Blockquote.ProtoReflect.Descriptor instead. +func (*Blockquote) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{10} +} + +func (x *Blockquote) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +type List struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` + Marker uint32 `protobuf:"varint,2,opt,name=marker,proto3" json:"marker,omitempty"` + IsTight bool `protobuf:"varint,3,opt,name=is_tight,json=isTight,proto3" json:"is_tight,omitempty"` + Start uint32 `protobuf:"varint,4,opt,name=start,proto3" json:"start,omitempty"` +} + +func (x *List) Reset() { + *x = List{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *List) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*List) ProtoMessage() {} + +func (x *List) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use List.ProtoReflect.Descriptor instead. +func (*List) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{11} +} + +func (x *List) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +func (x *List) GetMarker() uint32 { + if x != nil { + return x.Marker + } + return 0 +} + +func (x *List) GetIsTight() bool { + if x != nil { + return x.IsTight + } + return false +} + +func (x *List) GetStart() uint32 { + if x != nil { + return x.Start + } + return 0 +} + +type ListItem struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` + Offset int64 `protobuf:"varint,2,opt,name=offset,proto3" json:"offset,omitempty"` +} + +func (x *ListItem) Reset() { + *x = ListItem{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListItem) ProtoMessage() {} + +func (x *ListItem) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListItem.ProtoReflect.Descriptor instead. +func (*ListItem) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{12} +} + +func (x *ListItem) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +func (x *ListItem) GetOffset() int64 { + if x != nil { + return x.Offset + } + return 0 +} + +type HTMLBlock struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` + Type HTMLBlockType `protobuf:"varint,2,opt,name=type,proto3,enum=ast.v1.HTMLBlockType" json:"type,omitempty"` + Lines [][]byte `protobuf:"bytes,3,rep,name=lines,proto3" json:"lines,omitempty"` + ClosureLine []byte `protobuf:"bytes,4,opt,name=closure_line,json=closureLine,proto3" json:"closure_line,omitempty"` +} + +func (x *HTMLBlock) Reset() { + *x = HTMLBlock{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HTMLBlock) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HTMLBlock) ProtoMessage() {} + +func (x *HTMLBlock) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HTMLBlock.ProtoReflect.Descriptor instead. +func (*HTMLBlock) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{13} +} + +func (x *HTMLBlock) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +func (x *HTMLBlock) GetType() HTMLBlockType { + if x != nil { + return x.Type + } + return HTMLBlockType_HTML_BLOCK_TYPE_UNSPECIFIED +} + +func (x *HTMLBlock) GetLines() [][]byte { + if x != nil { + return x.Lines + } + return nil +} + +func (x *HTMLBlock) GetClosureLine() []byte { + if x != nil { + return x.ClosureLine + } + return nil +} + +type Text struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` + Segment []byte `protobuf:"bytes,2,opt,name=segment,proto3" json:"segment,omitempty"` + SoftLineBreak bool `protobuf:"varint,3,opt,name=soft_line_break,json=softLineBreak,proto3" json:"soft_line_break,omitempty"` + HardLineBreak bool `protobuf:"varint,4,opt,name=hard_line_break,json=hardLineBreak,proto3" json:"hard_line_break,omitempty"` + Raw bool `protobuf:"varint,5,opt,name=raw,proto3" json:"raw,omitempty"` +} + +func (x *Text) Reset() { + *x = Text{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Text) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Text) ProtoMessage() {} + +func (x *Text) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Text.ProtoReflect.Descriptor instead. +func (*Text) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{14} +} + +func (x *Text) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +func (x *Text) GetSegment() []byte { + if x != nil { + return x.Segment + } + return nil +} + +func (x *Text) GetSoftLineBreak() bool { + if x != nil { + return x.SoftLineBreak + } + return false +} + +func (x *Text) GetHardLineBreak() bool { + if x != nil { + return x.HardLineBreak + } + return false +} + +func (x *Text) GetRaw() bool { + if x != nil { + return x.Raw + } + return false +} + +type String struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + Raw bool `protobuf:"varint,3,opt,name=raw,proto3" json:"raw,omitempty"` + Code bool `protobuf:"varint,4,opt,name=code,proto3" json:"code,omitempty"` +} + +func (x *String) Reset() { + *x = String{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *String) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*String) ProtoMessage() {} + +func (x *String) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use String.ProtoReflect.Descriptor instead. +func (*String) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{15} +} + +func (x *String) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +func (x *String) GetValue() []byte { + if x != nil { + return x.Value + } + return nil +} + +func (x *String) GetRaw() bool { + if x != nil { + return x.Raw + } + return false +} + +func (x *String) GetCode() bool { + if x != nil { + return x.Code + } + return false +} + +type CodeSpan struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` +} + +func (x *CodeSpan) Reset() { + *x = CodeSpan{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CodeSpan) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CodeSpan) ProtoMessage() {} + +func (x *CodeSpan) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CodeSpan.ProtoReflect.Descriptor instead. +func (*CodeSpan) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{16} +} + +func (x *CodeSpan) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +type Emphasis struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` + Level int64 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` +} + +func (x *Emphasis) Reset() { + *x = Emphasis{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Emphasis) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Emphasis) ProtoMessage() {} + +func (x *Emphasis) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Emphasis.ProtoReflect.Descriptor instead. +func (*Emphasis) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{17} +} + +func (x *Emphasis) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +func (x *Emphasis) GetLevel() int64 { + if x != nil { + return x.Level + } + return 0 +} + +type LinkOrImage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` + Destination []byte `protobuf:"bytes,2,opt,name=destination,proto3" json:"destination,omitempty"` + Title []byte `protobuf:"bytes,3,opt,name=title,proto3" json:"title,omitempty"` + IsImage bool `protobuf:"varint,4,opt,name=is_image,json=isImage,proto3" json:"is_image,omitempty"` +} + +func (x *LinkOrImage) Reset() { + *x = LinkOrImage{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LinkOrImage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LinkOrImage) ProtoMessage() {} + +func (x *LinkOrImage) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LinkOrImage.ProtoReflect.Descriptor instead. +func (*LinkOrImage) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{18} +} + +func (x *LinkOrImage) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +func (x *LinkOrImage) GetDestination() []byte { + if x != nil { + return x.Destination + } + return nil +} + +func (x *LinkOrImage) GetTitle() []byte { + if x != nil { + return x.Title + } + return nil +} + +func (x *LinkOrImage) GetIsImage() bool { + if x != nil { + return x.IsImage + } + return false +} + +type AutoLink struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` + Type AutoLinkType `protobuf:"varint,2,opt,name=type,proto3,enum=ast.v1.AutoLinkType" json:"type,omitempty"` + Protocol []byte `protobuf:"bytes,3,opt,name=protocol,proto3" json:"protocol,omitempty"` + Value []byte `protobuf:"bytes,4,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *AutoLink) Reset() { + *x = AutoLink{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AutoLink) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AutoLink) ProtoMessage() {} + +func (x *AutoLink) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AutoLink.ProtoReflect.Descriptor instead. +func (*AutoLink) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{19} +} + +func (x *AutoLink) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +func (x *AutoLink) GetType() AutoLinkType { + if x != nil { + return x.Type + } + return AutoLinkType_AUTO_LINK_TYPE_UNSPECIFIED +} + +func (x *AutoLink) GetProtocol() []byte { + if x != nil { + return x.Protocol + } + return nil +} + +func (x *AutoLink) GetValue() []byte { + if x != nil { + return x.Value + } + return nil +} + +type RawHTML struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` + Segments [][]byte `protobuf:"bytes,2,rep,name=segments,proto3" json:"segments,omitempty"` +} + +func (x *RawHTML) Reset() { + *x = RawHTML{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RawHTML) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RawHTML) ProtoMessage() {} + +func (x *RawHTML) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[20] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RawHTML.ProtoReflect.Descriptor instead. +func (*RawHTML) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{20} +} + +func (x *RawHTML) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +func (x *RawHTML) GetSegments() [][]byte { + if x != nil { + return x.Segments + } + return nil +} + +type Table struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` + Alignments []CellAlignment `protobuf:"varint,2,rep,packed,name=alignments,proto3,enum=ast.v1.CellAlignment" json:"alignments,omitempty"` +} + +func (x *Table) Reset() { + *x = Table{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Table) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Table) ProtoMessage() {} + +func (x *Table) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[21] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Table.ProtoReflect.Descriptor instead. +func (*Table) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{21} +} + +func (x *Table) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +func (x *Table) GetAlignments() []CellAlignment { + if x != nil { + return x.Alignments + } + return nil +} + +type TableRow struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` + Alignments []CellAlignment `protobuf:"varint,2,rep,packed,name=alignments,proto3,enum=ast.v1.CellAlignment" json:"alignments,omitempty"` + IsHeader bool `protobuf:"varint,4,opt,name=is_header,json=isHeader,proto3" json:"is_header,omitempty"` +} + +func (x *TableRow) Reset() { + *x = TableRow{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TableRow) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TableRow) ProtoMessage() {} + +func (x *TableRow) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[22] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TableRow.ProtoReflect.Descriptor instead. +func (*TableRow) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{22} +} + +func (x *TableRow) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +func (x *TableRow) GetAlignments() []CellAlignment { + if x != nil { + return x.Alignments + } + return nil +} + +func (x *TableRow) GetIsHeader() bool { + if x != nil { + return x.IsHeader + } + return false +} + +type TableCell struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` + Alignment CellAlignment `protobuf:"varint,2,opt,name=alignment,proto3,enum=ast.v1.CellAlignment" json:"alignment,omitempty"` +} + +func (x *TableCell) Reset() { + *x = TableCell{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TableCell) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TableCell) ProtoMessage() {} + +func (x *TableCell) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[23] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TableCell.ProtoReflect.Descriptor instead. +func (*TableCell) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{23} +} + +func (x *TableCell) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +func (x *TableCell) GetAlignment() CellAlignment { + if x != nil { + return x.Alignment + } + return CellAlignment_CELL_ALIGNMENT_UNSPECIFIED +} + +type TaskCheckbox struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` + IsChecked bool `protobuf:"varint,2,opt,name=is_checked,json=isChecked,proto3" json:"is_checked,omitempty"` +} + +func (x *TaskCheckbox) Reset() { + *x = TaskCheckbox{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TaskCheckbox) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TaskCheckbox) ProtoMessage() {} + +func (x *TaskCheckbox) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[24] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TaskCheckbox.ProtoReflect.Descriptor instead. +func (*TaskCheckbox) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{24} +} + +func (x *TaskCheckbox) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +func (x *TaskCheckbox) GetIsChecked() bool { + if x != nil { + return x.IsChecked + } + return false +} + +type Strikethrough struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` +} + +func (x *Strikethrough) Reset() { + *x = Strikethrough{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Strikethrough) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Strikethrough) ProtoMessage() {} + +func (x *Strikethrough) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[25] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Strikethrough.ProtoReflect.Descriptor instead. +func (*Strikethrough) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{25} +} + +func (x *Strikethrough) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +// Fabric plugin metadata, transparent for the render +type PluginMetadata struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Fully qualified plugin name with version + GeneratedBy string `protobuf:"bytes,1,opt,name=generated_by,json=generatedBy,proto3" json:"generated_by,omitempty"` + // Types that are assignable to Content: + // + // *PluginMetadata_Static + // *PluginMetadata_CustomRenderer + Content isPluginMetadata_Content `protobuf_oneof:"content"` +} + +func (x *PluginMetadata) Reset() { + *x = PluginMetadata{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PluginMetadata) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PluginMetadata) ProtoMessage() {} + +func (x *PluginMetadata) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[26] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PluginMetadata.ProtoReflect.Descriptor instead. +func (*PluginMetadata) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{26} +} + +func (x *PluginMetadata) GetGeneratedBy() string { + if x != nil { + return x.GeneratedBy + } + return "" +} + +func (m *PluginMetadata) GetContent() isPluginMetadata_Content { + if m != nil { + return m.Content + } + return nil +} + +func (x *PluginMetadata) GetStatic() *BaseNode { + if x, ok := x.GetContent().(*PluginMetadata_Static); ok { + return x.Static + } + return nil +} + +func (x *PluginMetadata) GetCustomRenderer() *CustomRenderer { + if x, ok := x.GetContent().(*PluginMetadata_CustomRenderer); ok { + return x.CustomRenderer + } + return nil +} + +type isPluginMetadata_Content interface { + isPluginMetadata_Content() +} + +type PluginMetadata_Static struct { + // Static node content + Static *BaseNode `protobuf:"bytes,2,opt,name=static,proto3,oneof"` +} + +type PluginMetadata_CustomRenderer struct { + // Custom node renderer must be used + CustomRenderer *CustomRenderer `protobuf:"bytes,3,opt,name=custom_renderer,json=customRenderer,proto3,oneof"` +} + +func (*PluginMetadata_Static) isPluginMetadata_Content() {} + +func (*PluginMetadata_CustomRenderer) isPluginMetadata_Content() {} + +type CustomRenderer struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Input for the custom renderer + Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` + // Format => content map. + // Results of custom render of the `data` to `format` are stored in this cache + // Repeaded renders to the same format should use it, instead of calling the plugin. + // Changes to data (i.e. editing via web interface) should clear the cache + Cache map[string]*BaseNode `protobuf:"bytes,2,rep,name=cache,proto3" json:"cache,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *CustomRenderer) Reset() { + *x = CustomRenderer{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CustomRenderer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CustomRenderer) ProtoMessage() {} + +func (x *CustomRenderer) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[27] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CustomRenderer.ProtoReflect.Descriptor instead. +func (*CustomRenderer) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{27} +} + +func (x *CustomRenderer) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +func (x *CustomRenderer) GetCache() map[string]*BaseNode { + if x != nil { + return x.Cache + } + return nil +} + +type OtherKind struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *BaseNode `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` + IsBlock bool `protobuf:"varint,2,opt,name=is_block,json=isBlock,proto3" json:"is_block,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + Other *anypb.Any `protobuf:"bytes,4,opt,name=other,proto3" json:"other,omitempty"` +} + +func (x *OtherKind) Reset() { + *x = OtherKind{} + if protoimpl.UnsafeEnabled { + mi := &file_ast_v1_ast_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *OtherKind) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OtherKind) ProtoMessage() {} + +func (x *OtherKind) ProtoReflect() protoreflect.Message { + mi := &file_ast_v1_ast_proto_msgTypes[28] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OtherKind.ProtoReflect.Descriptor instead. +func (*OtherKind) Descriptor() ([]byte, []int) { + return file_ast_v1_ast_proto_rawDescGZIP(), []int{28} +} + +func (x *OtherKind) GetBase() *BaseNode { + if x != nil { + return x.Base + } + return nil +} + +func (x *OtherKind) GetIsBlock() bool { + if x != nil { + return x.IsBlock + } + return false +} + +func (x *OtherKind) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *OtherKind) GetOther() *anypb.Any { + if x != nil { + return x.Other + } + return nil +} + +var File_ast_v1_ast_proto protoreflect.FileDescriptor + +var file_ast_v1_ast_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x61, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x06, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x54, 0x0a, 0x09, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, 0x12, + 0x0a, 0x03, 0x73, 0x74, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x73, + 0x74, 0x72, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x99, 0x01, 0x0a, 0x08, + 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x28, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, + 0x64, 0x72, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x73, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, + 0x65, 0x6e, 0x12, 0x31, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x62, 0x6c, 0x61, 0x6e, 0x6b, 0x5f, 0x70, + 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x12, 0x62, 0x6c, 0x61, 0x6e, 0x6b, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, + 0x75, 0x73, 0x4c, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x85, 0x0a, 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, + 0x12, 0x2e, 0x0a, 0x08, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x6f, 0x63, 0x75, + 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x08, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x12, 0x32, 0x0a, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, + 0x78, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x09, 0x74, 0x65, 0x78, 0x74, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x31, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x61, 0x67, 0x72, 0x61, 0x70, + 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x61, 0x72, 0x61, 0x67, 0x72, 0x61, 0x70, 0x68, 0x48, 0x00, 0x52, 0x09, 0x70, 0x61, + 0x72, 0x61, 0x67, 0x72, 0x61, 0x70, 0x68, 0x12, 0x2b, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x69, + 0x6e, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x07, 0x68, 0x65, 0x61, + 0x64, 0x69, 0x6e, 0x67, 0x12, 0x3e, 0x0a, 0x0e, 0x74, 0x68, 0x65, 0x6d, 0x61, 0x74, 0x69, 0x63, + 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, + 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x65, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x42, 0x72, + 0x65, 0x61, 0x6b, 0x48, 0x00, 0x52, 0x0d, 0x74, 0x68, 0x65, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x42, + 0x72, 0x65, 0x61, 0x6b, 0x12, 0x32, 0x0a, 0x0a, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x09, 0x63, + 0x6f, 0x64, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x45, 0x0a, 0x11, 0x66, 0x65, 0x6e, 0x63, + 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x6e, + 0x63, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x0f, + 0x66, 0x65, 0x6e, 0x63, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, + 0x34, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x48, 0x00, 0x52, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x71, 0x75, 0x6f, 0x74, 0x65, 0x12, 0x22, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x48, 0x00, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x09, 0x6c, 0x69, 0x73, + 0x74, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, + 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x48, 0x00, + 0x52, 0x08, 0x6c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x32, 0x0a, 0x0a, 0x68, 0x74, + 0x6d, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, + 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x54, 0x4d, 0x4c, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x48, 0x00, 0x52, 0x09, 0x68, 0x74, 0x6d, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x22, + 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, + 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x48, 0x00, 0x52, 0x04, 0x74, 0x65, + 0x78, 0x74, 0x12, 0x28, 0x0a, 0x06, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x10, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x2f, 0x0a, 0x09, + 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x73, 0x70, 0x61, 0x6e, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x53, 0x70, 0x61, + 0x6e, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x64, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x12, 0x2e, 0x0a, + 0x08, 0x65, 0x6d, 0x70, 0x68, 0x61, 0x73, 0x69, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x68, 0x61, 0x73, 0x69, + 0x73, 0x48, 0x00, 0x52, 0x08, 0x65, 0x6d, 0x70, 0x68, 0x61, 0x73, 0x69, 0x73, 0x12, 0x39, 0x0a, + 0x0d, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x6f, 0x72, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x13, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x6e, 0x6b, 0x4f, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x6c, 0x69, 0x6e, + 0x6b, 0x4f, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x6f, + 0x5f, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x73, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x6f, 0x4c, 0x69, 0x6e, 0x6b, 0x48, 0x00, 0x52, + 0x08, 0x61, 0x75, 0x74, 0x6f, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x2c, 0x0a, 0x08, 0x72, 0x61, 0x77, + 0x5f, 0x68, 0x74, 0x6d, 0x6c, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x73, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x61, 0x77, 0x48, 0x54, 0x4d, 0x4c, 0x48, 0x00, 0x52, 0x07, + 0x72, 0x61, 0x77, 0x48, 0x74, 0x6d, 0x6c, 0x12, 0x25, 0x0a, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x54, 0x61, 0x62, 0x6c, 0x65, 0x48, 0x00, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x2f, + 0x0a, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x6f, 0x77, 0x18, 0x17, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, + 0x52, 0x6f, 0x77, 0x48, 0x00, 0x52, 0x08, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x6f, 0x77, 0x12, + 0x32, 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x18, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x62, + 0x6c, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x48, 0x00, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x43, + 0x65, 0x6c, 0x6c, 0x12, 0x3b, 0x0a, 0x0d, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x63, 0x68, 0x65, 0x63, + 0x6b, 0x62, 0x6f, 0x78, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x73, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, + 0x48, 0x00, 0x52, 0x0c, 0x74, 0x61, 0x73, 0x6b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, + 0x12, 0x3d, 0x0a, 0x0d, 0x73, 0x74, 0x72, 0x69, 0x6b, 0x65, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, + 0x68, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6b, 0x65, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x48, 0x00, + 0x52, 0x0d, 0x73, 0x74, 0x72, 0x69, 0x6b, 0x65, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x12, + 0x3a, 0x0a, 0x0b, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0xfe, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, + 0x0a, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x2a, 0x0a, 0x05, 0x6f, + 0x74, 0x68, 0x65, 0x72, 0x18, 0xff, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x73, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x4b, 0x69, 0x6e, 0x64, 0x48, 0x00, + 0x52, 0x05, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x42, 0x06, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x22, + 0x30, 0x0a, 0x08, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x62, + 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, + 0x65, 0x22, 0x31, 0x0a, 0x09, 0x54, 0x65, 0x78, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x24, + 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, + 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, + 0x62, 0x61, 0x73, 0x65, 0x22, 0x31, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x61, 0x67, 0x72, 0x61, 0x70, + 0x68, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x64, + 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, 0x45, 0x0a, 0x07, 0x48, 0x65, 0x61, 0x64, 0x69, + 0x6e, 0x67, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, + 0x64, 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, + 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x35, + 0x0a, 0x0d, 0x54, 0x68, 0x65, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x12, + 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, + 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, + 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, 0x47, 0x0a, 0x09, 0x43, 0x6f, 0x64, 0x65, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, + 0x64, 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x65, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x6f, + 0x0a, 0x0f, 0x46, 0x65, 0x6e, 0x63, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x64, + 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, + 0x65, 0x78, 0x74, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6e, + 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x22, + 0x32, 0x0a, 0x0a, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x12, 0x24, 0x0a, + 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x73, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, + 0x61, 0x73, 0x65, 0x22, 0x75, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x62, + 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, + 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x06, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, + 0x74, 0x69, 0x67, 0x68, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x54, + 0x69, 0x67, 0x68, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x22, 0x48, 0x0a, 0x08, 0x4c, 0x69, + 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, + 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, + 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6f, 0x66, + 0x66, 0x73, 0x65, 0x74, 0x22, 0x95, 0x01, 0x0a, 0x09, 0x48, 0x54, 0x4d, 0x4c, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, + 0x64, 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x48, 0x54, 0x4d, 0x4c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0c, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6c, 0x6f, + 0x73, 0x75, 0x72, 0x65, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0b, 0x63, 0x6c, 0x6f, 0x73, 0x75, 0x72, 0x65, 0x4c, 0x69, 0x6e, 0x65, 0x22, 0xa8, 0x01, 0x0a, + 0x04, 0x54, 0x65, 0x78, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, + 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, + 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x65, + 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x6f, 0x66, 0x74, 0x5f, 0x6c, 0x69, + 0x6e, 0x65, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, + 0x73, 0x6f, 0x66, 0x74, 0x4c, 0x69, 0x6e, 0x65, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x12, 0x26, 0x0a, + 0x0f, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x68, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x6e, 0x65, + 0x42, 0x72, 0x65, 0x61, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x61, 0x77, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x03, 0x72, 0x61, 0x77, 0x22, 0x6a, 0x0a, 0x06, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x64, + 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x10, 0x0a, + 0x03, 0x72, 0x61, 0x77, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x72, 0x61, 0x77, 0x12, + 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x63, + 0x6f, 0x64, 0x65, 0x22, 0x30, 0x0a, 0x08, 0x43, 0x6f, 0x64, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x12, + 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, + 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, + 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, 0x46, 0x0a, 0x08, 0x45, 0x6d, 0x70, 0x68, 0x61, 0x73, 0x69, + 0x73, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x64, + 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x86, 0x01, + 0x0a, 0x0b, 0x4c, 0x69, 0x6e, 0x6b, 0x4f, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, + 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x73, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, + 0x61, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x69, + 0x73, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, + 0x73, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x8c, 0x01, 0x0a, 0x08, 0x41, 0x75, 0x74, 0x6f, 0x4c, + 0x69, 0x6e, 0x6b, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, + 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x41, 0x75, 0x74, 0x6f, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x4b, 0x0a, 0x07, 0x52, 0x61, 0x77, 0x48, 0x54, 0x4d, 0x4c, + 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, + 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, + 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x22, 0x64, 0x0a, 0x05, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x24, 0x0a, 0x04, 0x62, + 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, + 0x65, 0x12, 0x35, 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x65, 0x6c, 0x6c, 0x41, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x61, 0x6c, + 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x84, 0x01, 0x0a, 0x08, 0x54, 0x61, 0x62, + 0x6c, 0x65, 0x52, 0x6f, 0x77, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, + 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x0a, 0x61, + 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32, + 0x15, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x65, 0x6c, 0x6c, 0x41, 0x6c, 0x69, + 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x73, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, + 0x66, 0x0a, 0x09, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x12, 0x24, 0x0a, 0x04, + 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x73, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, 0x61, + 0x73, 0x65, 0x12, 0x33, 0x0a, 0x09, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x65, 0x6c, 0x6c, 0x41, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x09, 0x61, 0x6c, + 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x53, 0x0a, 0x0c, 0x54, 0x61, 0x73, 0x6b, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, + 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x1d, 0x0a, + 0x0a, 0x69, 0x73, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x09, 0x69, 0x73, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x22, 0x35, 0x0a, 0x0d, + 0x53, 0x74, 0x72, 0x69, 0x6b, 0x65, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x12, 0x24, 0x0a, + 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x73, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, + 0x61, 0x73, 0x65, 0x22, 0xad, 0x01, 0x0a, 0x0e, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x67, 0x65, + 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x12, 0x2a, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x48, 0x00, 0x52, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x69, 0x63, 0x12, 0x41, 0x0a, 0x0f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, + 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, + 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, + 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x42, 0x09, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x22, 0xa9, 0x01, 0x0a, 0x0e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, + 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x37, 0x0a, 0x05, 0x63, 0x61, + 0x63, 0x68, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x61, 0x73, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, + 0x72, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x63, 0x61, + 0x63, 0x68, 0x65, 0x1a, 0x4a, 0x0a, 0x0a, 0x43, 0x61, 0x63, 0x68, 0x65, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, + 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, + 0x8c, 0x01, 0x0a, 0x09, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x24, 0x0a, + 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x73, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x62, + 0x61, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x05, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2a, 0xd1, + 0x01, 0x0a, 0x0d, 0x48, 0x54, 0x4d, 0x4c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x1f, 0x0a, 0x1b, 0x48, 0x54, 0x4d, 0x4c, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x15, 0x0a, 0x11, 0x48, 0x54, 0x4d, 0x4c, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x31, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x48, 0x54, 0x4d, 0x4c, + 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x32, 0x10, 0x02, 0x12, + 0x15, 0x0a, 0x11, 0x48, 0x54, 0x4d, 0x4c, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x33, 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x48, 0x54, 0x4d, 0x4c, 0x5f, 0x42, + 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x34, 0x10, 0x04, 0x12, 0x15, 0x0a, + 0x11, 0x48, 0x54, 0x4d, 0x4c, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x35, 0x10, 0x05, 0x12, 0x15, 0x0a, 0x11, 0x48, 0x54, 0x4d, 0x4c, 0x5f, 0x42, 0x4c, 0x4f, + 0x43, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x36, 0x10, 0x06, 0x12, 0x15, 0x0a, 0x11, 0x48, + 0x54, 0x4d, 0x4c, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x37, + 0x10, 0x07, 0x2a, 0x60, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x6f, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x1a, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4d, 0x41, 0x49, 0x4c, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, + 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, + 0x52, 0x4c, 0x10, 0x02, 0x2a, 0x96, 0x01, 0x0a, 0x0d, 0x43, 0x65, 0x6c, 0x6c, 0x41, 0x6c, 0x69, + 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1e, 0x0a, 0x1a, 0x43, 0x45, 0x4c, 0x4c, 0x5f, 0x41, + 0x4c, 0x49, 0x47, 0x4e, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x45, 0x4c, 0x4c, 0x5f, 0x41, + 0x4c, 0x49, 0x47, 0x4e, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x4c, 0x45, 0x46, 0x54, 0x10, 0x01, 0x12, + 0x18, 0x0a, 0x14, 0x43, 0x45, 0x4c, 0x4c, 0x5f, 0x41, 0x4c, 0x49, 0x47, 0x4e, 0x4d, 0x45, 0x4e, + 0x54, 0x5f, 0x52, 0x49, 0x47, 0x48, 0x54, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x43, 0x45, 0x4c, + 0x4c, 0x5f, 0x41, 0x4c, 0x49, 0x47, 0x4e, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x43, 0x45, 0x4e, 0x54, + 0x45, 0x52, 0x10, 0x03, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x45, 0x4c, 0x4c, 0x5f, 0x41, 0x4c, 0x49, + 0x47, 0x4e, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x04, 0x42, 0x84, 0x01, + 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x42, 0x08, 0x41, 0x73, + 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x6b, 0x2d, + 0x69, 0x6f, 0x2f, 0x66, 0x61, 0x62, 0x72, 0x69, 0x63, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, + 0x2f, 0x61, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x73, 0x74, 0x76, 0x31, 0xa2, 0x02, 0x03, + 0x41, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x41, 0x73, 0x74, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x06, 0x41, + 0x73, 0x74, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x12, 0x41, 0x73, 0x74, 0x5c, 0x56, 0x31, 0x5c, 0x47, + 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x41, 0x73, 0x74, + 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_ast_v1_ast_proto_rawDescOnce sync.Once + file_ast_v1_ast_proto_rawDescData = file_ast_v1_ast_proto_rawDesc +) + +func file_ast_v1_ast_proto_rawDescGZIP() []byte { + file_ast_v1_ast_proto_rawDescOnce.Do(func() { + file_ast_v1_ast_proto_rawDescData = protoimpl.X.CompressGZIP(file_ast_v1_ast_proto_rawDescData) + }) + return file_ast_v1_ast_proto_rawDescData +} + +var file_ast_v1_ast_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_ast_v1_ast_proto_msgTypes = make([]protoimpl.MessageInfo, 30) +var file_ast_v1_ast_proto_goTypes = []any{ + (HTMLBlockType)(0), // 0: ast.v1.HTMLBlockType + (AutoLinkType)(0), // 1: ast.v1.AutoLinkType + (CellAlignment)(0), // 2: ast.v1.CellAlignment + (*Attribute)(nil), // 3: ast.v1.Attribute + (*BaseNode)(nil), // 4: ast.v1.BaseNode + (*Node)(nil), // 5: ast.v1.Node + (*Document)(nil), // 6: ast.v1.Document + (*TextBlock)(nil), // 7: ast.v1.TextBlock + (*Paragraph)(nil), // 8: ast.v1.Paragraph + (*Heading)(nil), // 9: ast.v1.Heading + (*ThematicBreak)(nil), // 10: ast.v1.ThematicBreak + (*CodeBlock)(nil), // 11: ast.v1.CodeBlock + (*FencedCodeBlock)(nil), // 12: ast.v1.FencedCodeBlock + (*Blockquote)(nil), // 13: ast.v1.Blockquote + (*List)(nil), // 14: ast.v1.List + (*ListItem)(nil), // 15: ast.v1.ListItem + (*HTMLBlock)(nil), // 16: ast.v1.HTMLBlock + (*Text)(nil), // 17: ast.v1.Text + (*String)(nil), // 18: ast.v1.String + (*CodeSpan)(nil), // 19: ast.v1.CodeSpan + (*Emphasis)(nil), // 20: ast.v1.Emphasis + (*LinkOrImage)(nil), // 21: ast.v1.LinkOrImage + (*AutoLink)(nil), // 22: ast.v1.AutoLink + (*RawHTML)(nil), // 23: ast.v1.RawHTML + (*Table)(nil), // 24: ast.v1.Table + (*TableRow)(nil), // 25: ast.v1.TableRow + (*TableCell)(nil), // 26: ast.v1.TableCell + (*TaskCheckbox)(nil), // 27: ast.v1.TaskCheckbox + (*Strikethrough)(nil), // 28: ast.v1.Strikethrough + (*PluginMetadata)(nil), // 29: ast.v1.PluginMetadata + (*CustomRenderer)(nil), // 30: ast.v1.CustomRenderer + (*OtherKind)(nil), // 31: ast.v1.OtherKind + nil, // 32: ast.v1.CustomRenderer.CacheEntry + (*anypb.Any)(nil), // 33: google.protobuf.Any +} +var file_ast_v1_ast_proto_depIdxs = []int32{ + 5, // 0: ast.v1.BaseNode.children:type_name -> ast.v1.Node + 3, // 1: ast.v1.BaseNode.attributes:type_name -> ast.v1.Attribute + 6, // 2: ast.v1.Node.document:type_name -> ast.v1.Document + 7, // 3: ast.v1.Node.text_block:type_name -> ast.v1.TextBlock + 8, // 4: ast.v1.Node.paragraph:type_name -> ast.v1.Paragraph + 9, // 5: ast.v1.Node.heading:type_name -> ast.v1.Heading + 10, // 6: ast.v1.Node.thematic_break:type_name -> ast.v1.ThematicBreak + 11, // 7: ast.v1.Node.code_block:type_name -> ast.v1.CodeBlock + 12, // 8: ast.v1.Node.fenced_code_block:type_name -> ast.v1.FencedCodeBlock + 13, // 9: ast.v1.Node.blockquote:type_name -> ast.v1.Blockquote + 14, // 10: ast.v1.Node.list:type_name -> ast.v1.List + 15, // 11: ast.v1.Node.list_item:type_name -> ast.v1.ListItem + 16, // 12: ast.v1.Node.html_block:type_name -> ast.v1.HTMLBlock + 17, // 13: ast.v1.Node.text:type_name -> ast.v1.Text + 18, // 14: ast.v1.Node.string:type_name -> ast.v1.String + 19, // 15: ast.v1.Node.code_span:type_name -> ast.v1.CodeSpan + 20, // 16: ast.v1.Node.emphasis:type_name -> ast.v1.Emphasis + 21, // 17: ast.v1.Node.link_or_image:type_name -> ast.v1.LinkOrImage + 22, // 18: ast.v1.Node.auto_link:type_name -> ast.v1.AutoLink + 23, // 19: ast.v1.Node.raw_html:type_name -> ast.v1.RawHTML + 24, // 20: ast.v1.Node.table:type_name -> ast.v1.Table + 25, // 21: ast.v1.Node.table_row:type_name -> ast.v1.TableRow + 26, // 22: ast.v1.Node.table_cell:type_name -> ast.v1.TableCell + 27, // 23: ast.v1.Node.task_checkbox:type_name -> ast.v1.TaskCheckbox + 28, // 24: ast.v1.Node.strikethrough:type_name -> ast.v1.Strikethrough + 29, // 25: ast.v1.Node.plugin_meta:type_name -> ast.v1.PluginMetadata + 31, // 26: ast.v1.Node.other:type_name -> ast.v1.OtherKind + 4, // 27: ast.v1.Document.base:type_name -> ast.v1.BaseNode + 4, // 28: ast.v1.TextBlock.base:type_name -> ast.v1.BaseNode + 4, // 29: ast.v1.Paragraph.base:type_name -> ast.v1.BaseNode + 4, // 30: ast.v1.Heading.base:type_name -> ast.v1.BaseNode + 4, // 31: ast.v1.ThematicBreak.base:type_name -> ast.v1.BaseNode + 4, // 32: ast.v1.CodeBlock.base:type_name -> ast.v1.BaseNode + 4, // 33: ast.v1.FencedCodeBlock.base:type_name -> ast.v1.BaseNode + 17, // 34: ast.v1.FencedCodeBlock.info:type_name -> ast.v1.Text + 4, // 35: ast.v1.Blockquote.base:type_name -> ast.v1.BaseNode + 4, // 36: ast.v1.List.base:type_name -> ast.v1.BaseNode + 4, // 37: ast.v1.ListItem.base:type_name -> ast.v1.BaseNode + 4, // 38: ast.v1.HTMLBlock.base:type_name -> ast.v1.BaseNode + 0, // 39: ast.v1.HTMLBlock.type:type_name -> ast.v1.HTMLBlockType + 4, // 40: ast.v1.Text.base:type_name -> ast.v1.BaseNode + 4, // 41: ast.v1.String.base:type_name -> ast.v1.BaseNode + 4, // 42: ast.v1.CodeSpan.base:type_name -> ast.v1.BaseNode + 4, // 43: ast.v1.Emphasis.base:type_name -> ast.v1.BaseNode + 4, // 44: ast.v1.LinkOrImage.base:type_name -> ast.v1.BaseNode + 4, // 45: ast.v1.AutoLink.base:type_name -> ast.v1.BaseNode + 1, // 46: ast.v1.AutoLink.type:type_name -> ast.v1.AutoLinkType + 4, // 47: ast.v1.RawHTML.base:type_name -> ast.v1.BaseNode + 4, // 48: ast.v1.Table.base:type_name -> ast.v1.BaseNode + 2, // 49: ast.v1.Table.alignments:type_name -> ast.v1.CellAlignment + 4, // 50: ast.v1.TableRow.base:type_name -> ast.v1.BaseNode + 2, // 51: ast.v1.TableRow.alignments:type_name -> ast.v1.CellAlignment + 4, // 52: ast.v1.TableCell.base:type_name -> ast.v1.BaseNode + 2, // 53: ast.v1.TableCell.alignment:type_name -> ast.v1.CellAlignment + 4, // 54: ast.v1.TaskCheckbox.base:type_name -> ast.v1.BaseNode + 4, // 55: ast.v1.Strikethrough.base:type_name -> ast.v1.BaseNode + 4, // 56: ast.v1.PluginMetadata.static:type_name -> ast.v1.BaseNode + 30, // 57: ast.v1.PluginMetadata.custom_renderer:type_name -> ast.v1.CustomRenderer + 32, // 58: ast.v1.CustomRenderer.cache:type_name -> ast.v1.CustomRenderer.CacheEntry + 4, // 59: ast.v1.OtherKind.base:type_name -> ast.v1.BaseNode + 33, // 60: ast.v1.OtherKind.other:type_name -> google.protobuf.Any + 4, // 61: ast.v1.CustomRenderer.CacheEntry.value:type_name -> ast.v1.BaseNode + 62, // [62:62] is the sub-list for method output_type + 62, // [62:62] is the sub-list for method input_type + 62, // [62:62] is the sub-list for extension type_name + 62, // [62:62] is the sub-list for extension extendee + 0, // [0:62] is the sub-list for field type_name +} + +func init() { file_ast_v1_ast_proto_init() } +func file_ast_v1_ast_proto_init() { + if File_ast_v1_ast_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_ast_v1_ast_proto_msgTypes[0].Exporter = func(v any, i int) any { + switch v := v.(*Attribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[1].Exporter = func(v any, i int) any { + switch v := v.(*BaseNode); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[2].Exporter = func(v any, i int) any { + switch v := v.(*Node); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[3].Exporter = func(v any, i int) any { + switch v := v.(*Document); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[4].Exporter = func(v any, i int) any { + switch v := v.(*TextBlock); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[5].Exporter = func(v any, i int) any { + switch v := v.(*Paragraph); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[6].Exporter = func(v any, i int) any { + switch v := v.(*Heading); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[7].Exporter = func(v any, i int) any { + switch v := v.(*ThematicBreak); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[8].Exporter = func(v any, i int) any { + switch v := v.(*CodeBlock); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[9].Exporter = func(v any, i int) any { + switch v := v.(*FencedCodeBlock); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[10].Exporter = func(v any, i int) any { + switch v := v.(*Blockquote); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[11].Exporter = func(v any, i int) any { + switch v := v.(*List); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[12].Exporter = func(v any, i int) any { + switch v := v.(*ListItem); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[13].Exporter = func(v any, i int) any { + switch v := v.(*HTMLBlock); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[14].Exporter = func(v any, i int) any { + switch v := v.(*Text); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[15].Exporter = func(v any, i int) any { + switch v := v.(*String); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[16].Exporter = func(v any, i int) any { + switch v := v.(*CodeSpan); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[17].Exporter = func(v any, i int) any { + switch v := v.(*Emphasis); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[18].Exporter = func(v any, i int) any { + switch v := v.(*LinkOrImage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[19].Exporter = func(v any, i int) any { + switch v := v.(*AutoLink); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[20].Exporter = func(v any, i int) any { + switch v := v.(*RawHTML); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[21].Exporter = func(v any, i int) any { + switch v := v.(*Table); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[22].Exporter = func(v any, i int) any { + switch v := v.(*TableRow); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[23].Exporter = func(v any, i int) any { + switch v := v.(*TableCell); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[24].Exporter = func(v any, i int) any { + switch v := v.(*TaskCheckbox); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[25].Exporter = func(v any, i int) any { + switch v := v.(*Strikethrough); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[26].Exporter = func(v any, i int) any { + switch v := v.(*PluginMetadata); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[27].Exporter = func(v any, i int) any { + switch v := v.(*CustomRenderer); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ast_v1_ast_proto_msgTypes[28].Exporter = func(v any, i int) any { + switch v := v.(*OtherKind); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_ast_v1_ast_proto_msgTypes[0].OneofWrappers = []any{ + (*Attribute_Bytes)(nil), + (*Attribute_Str)(nil), + } + file_ast_v1_ast_proto_msgTypes[2].OneofWrappers = []any{ + (*Node_Document)(nil), + (*Node_TextBlock)(nil), + (*Node_Paragraph)(nil), + (*Node_Heading)(nil), + (*Node_ThematicBreak)(nil), + (*Node_CodeBlock)(nil), + (*Node_FencedCodeBlock)(nil), + (*Node_Blockquote)(nil), + (*Node_List)(nil), + (*Node_ListItem)(nil), + (*Node_HtmlBlock)(nil), + (*Node_Text)(nil), + (*Node_String_)(nil), + (*Node_CodeSpan)(nil), + (*Node_Emphasis)(nil), + (*Node_LinkOrImage)(nil), + (*Node_AutoLink)(nil), + (*Node_RawHtml)(nil), + (*Node_Table)(nil), + (*Node_TableRow)(nil), + (*Node_TableCell)(nil), + (*Node_TaskCheckbox)(nil), + (*Node_Strikethrough)(nil), + (*Node_PluginMeta)(nil), + (*Node_Other)(nil), + } + file_ast_v1_ast_proto_msgTypes[26].OneofWrappers = []any{ + (*PluginMetadata_Static)(nil), + (*PluginMetadata_CustomRenderer)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_ast_v1_ast_proto_rawDesc, + NumEnums: 3, + NumMessages: 30, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_ast_v1_ast_proto_goTypes, + DependencyIndexes: file_ast_v1_ast_proto_depIdxs, + EnumInfos: file_ast_v1_ast_proto_enumTypes, + MessageInfos: file_ast_v1_ast_proto_msgTypes, + }.Build() + File_ast_v1_ast_proto = out.File + file_ast_v1_ast_proto_rawDesc = nil + file_ast_v1_ast_proto_goTypes = nil + file_ast_v1_ast_proto_depIdxs = nil +} diff --git a/plugin/ast/v1/ast_decoder.go b/plugin/ast/v1/ast_decoder.go new file mode 100644 index 00000000..cf35edd0 --- /dev/null +++ b/plugin/ast/v1/ast_decoder.go @@ -0,0 +1,274 @@ +package astv1 + +import ( + "fmt" + "math" + + "github.com/yuin/goldmark/ast" + east "github.com/yuin/goldmark/extension/ast" + + "github.com/yuin/goldmark/text" +) + +type DecoderOption interface { + apply(*decoder) +} + +type ( + AttributeDecoder func(*Attribute) (ast.Attribute, error) + NodeDecoder func(*Node) (ast.Node, error) +) + +func (f AttributeDecoder) apply(dec *decoder) { + if f != nil { + dec.attributeDecoder = f + } +} + +func (f NodeDecoder) apply(dec *decoder) { + if f != nil { + dec.nodeDecoder = f + } +} + +func defaultNodeDecoder(node *Node) (ast.Node, error) { + return nil, fmt.Errorf("%w: %T", UnsupportedNodeType, node) +} + +func Decode(root *Node, opts ...DecoderOption) (node ast.Node, source []byte, err error) { + defer func() { + if r := recover(); r != nil { + if pErr, ok := r.(panickyErr); ok { + err = pErr.err + } else { + panic(r) + } + } + }() + dec := &decoder{ + attributeDecoder: DefaultAttributeDecoder, + nodeDecoder: defaultNodeDecoder, + } + for _, opt := range opts { + opt.apply(dec) + } + + node = dec.decodeNode(root) + source = dec.source.asBytes() + return +} + +type source []byte + +func (s *source) decodeSegment(segment []byte) text.Segment { + start := len(*s) + *s = append(*s, segment...) + stop := len(*s) + return text.NewSegment(start, stop) +} + +func (s source) asBytes() []byte { + return s +} + +func (s *source) decodeSegments(segments [][]byte) *text.Segments { + values := make([]text.Segment, len(segments)) + for i, segment := range segments { + values[i] = s.decodeSegment(segment) + } + res := text.NewSegments() + res.AppendAll(values) + return res +} + +type decoder struct { + source + attributeDecoder AttributeDecoder + nodeDecoder NodeDecoder +} + +func DefaultAttributeDecoder(attr *Attribute) (res ast.Attribute, err error) { + switch val := attr.GetValue().(type) { + case nil: + case *Attribute_Bytes: + res.Value = val.Bytes + case *Attribute_Str: + res.Value = val.Str + default: + err = fmt.Errorf("%w: %T", UnsupportedAttributeType, val) + return + } + res.Name = attr.GetName() + return +} + +func (d *decoder) decodeBaseNode(base *BaseNode, node ast.Node) { + for _, encAttr := range base.GetAttributes() { + attr, err := d.attributeDecoder(encAttr) + if err != nil { + panic(panickyErr{err: err}) + } + node.SetAttribute(attr.Name, attr.Value) + } + + for _, encChild := range base.GetChildren() { + node.AppendChild(node, d.decodeNode(encChild)) + } +} + +func (d *decoder) decodeText(txt *Text) *ast.Text { + if txt == nil { + return nil + } + res := ast.NewText() + res.Segment = d.decodeSegment(txt.GetSegment()) + res.SetSoftLineBreak(txt.GetSoftLineBreak()) + res.SetHardLineBreak(txt.GetHardLineBreak()) + res.SetRaw(txt.GetRaw()) + return res +} + +func (d *decoder) decodeNode(node *Node) (res ast.Node) { + var base *BaseNode + switch val := node.GetKind().(type) { + case *Node_Document: + base = val.Document.GetBase() + res = ast.NewDocument() + res.SetBlankPreviousLines(true) + case *Node_TextBlock: + base = val.TextBlock.GetBase() + res = ast.NewTextBlock() + case *Node_Paragraph: + base = val.Paragraph.GetBase() + res = ast.NewParagraph() + case *Node_Heading: + base = val.Heading.GetBase() + res = ast.NewHeading(int(val.Heading.GetLevel())) + case *Node_ThematicBreak: + base = val.ThematicBreak.GetBase() + res = ast.NewThematicBreak() + case *Node_CodeBlock: + base = val.CodeBlock.GetBase() + codeBlock := ast.NewCodeBlock() + codeBlock.SetLines(d.decodeSegments(val.CodeBlock.GetLines())) + res = codeBlock + case *Node_FencedCodeBlock: + base = val.FencedCodeBlock.GetBase() + fencedCodeBlock := ast.NewFencedCodeBlock(d.decodeText(val.FencedCodeBlock.GetInfo())) + fencedCodeBlock.SetLines(d.decodeSegments(val.FencedCodeBlock.GetLines())) + res = fencedCodeBlock + case *Node_Blockquote: + base = val.Blockquote.GetBase() + res = ast.NewBlockquote() + case *Node_List: + base = val.List.GetBase() + marker := val.List.GetMarker() + if marker == 0 || marker > math.MaxUint8 { + panic(pErrF("invalid marker character code: %d", marker)) + } + list := ast.NewList(byte(marker)) + list.IsTight = val.List.GetIsTight() + list.Start = int(val.List.GetStart()) + res = list + case *Node_ListItem: + base = val.ListItem.GetBase() + res = ast.NewListItem(int(val.ListItem.GetOffset())) + case *Node_HtmlBlock: + base = val.HtmlBlock.GetBase() + htmlBlock := ast.NewHTMLBlock(val.HtmlBlock.GetType().decode()) + if closure := val.HtmlBlock.GetClosureLine(); closure != nil { + htmlBlock.ClosureLine = d.decodeSegment(val.HtmlBlock.GetClosureLine()) + } else { + htmlBlock.ClosureLine = text.NewSegment(-1, -1) + } + htmlBlock.SetLines(d.decodeSegments(val.HtmlBlock.GetLines())) + res = htmlBlock + case *Node_Text: + base = val.Text.GetBase() + res = d.decodeText(val.Text) + case *Node_String_: + base = val.String_.GetBase() + str := ast.NewString(val.String_.GetValue()) + str.SetRaw(val.String_.GetRaw()) + str.SetCode(val.String_.GetCode()) + res = str + case *Node_CodeSpan: + base = val.CodeSpan.GetBase() + res = ast.NewCodeSpan() + case *Node_Emphasis: + base = val.Emphasis.GetBase() + res = ast.NewEmphasis(int(val.Emphasis.GetLevel())) + case *Node_LinkOrImage: + base = val.LinkOrImage.GetBase() + tRes := ast.NewLink() + tRes.Title = val.LinkOrImage.GetTitle() + tRes.Destination = val.LinkOrImage.GetDestination() + if val.LinkOrImage.GetIsImage() { + res = ast.NewImage(tRes) + } else { + res = tRes + } + case *Node_AutoLink: + base = val.AutoLink.GetBase() + tRes := ast.NewAutoLink(val.AutoLink.GetType().decode(), d.decodeText(&Text{ + Segment: val.AutoLink.GetValue(), + })) + tRes.Protocol = val.AutoLink.GetProtocol() + res = tRes + + case *Node_RawHtml: + base = val.RawHtml.GetBase() + tRes := ast.NewRawHTML() + tRes.Segments = d.decodeSegments(val.RawHtml.GetSegments()) + res = tRes + + case *Node_Table: + base = val.Table.GetBase() + tRes := east.NewTable() + tRes.Alignments = decodeCellAlignments(val.Table.Alignments) + res = tRes + + case *Node_TableRow: + base = val.TableRow.GetBase() + tRes := east.NewTableRow(decodeCellAlignments(val.TableRow.Alignments)) + if val.TableRow.IsHeader { + res = east.NewTableHeader(tRes) + } else { + res = tRes + } + case *Node_TableCell: + base = val.TableCell.GetBase() + tRes := east.NewTableCell() + tRes.Alignment = val.TableCell.Alignment.decode() + res = tRes + + case *Node_Strikethrough: + base = val.Strikethrough.GetBase() + res = east.NewStrikethrough() + + case *Node_TaskCheckbox: + base = val.TaskCheckbox.GetBase() + res = east.NewTaskCheckBox(val.TaskCheckbox.GetIsChecked()) + + case *Node_Other: + base = val.Other.GetBase() + var err error + res, err = d.nodeDecoder(node) + if err != nil { + panic(panickyErr{err: err}) + } + default: + panic(pErrF("Unsupported block kind: %T", node.Kind)) + } + + switch res.Type() { + case ast.TypeBlock: + res.SetBlankPreviousLines(base.GetBlankPreviousLines()) + fallthrough + case ast.TypeInline, ast.TypeDocument: + d.decodeBaseNode(base, res) + default: + panic(pErrF("Unsupported block type: %+v", res.Type())) + } + return +} diff --git a/plugin/ast/v1/ast_encoder.go b/plugin/ast/v1/ast_encoder.go new file mode 100644 index 00000000..4ffa91fb --- /dev/null +++ b/plugin/ast/v1/ast_encoder.go @@ -0,0 +1,361 @@ +package astv1 + +import ( + "errors" + "fmt" + + "github.com/yuin/goldmark/ast" + east "github.com/yuin/goldmark/extension/ast" + "github.com/yuin/goldmark/text" +) + +// Return this error from AttributeEncoder if the attribute should be skipped. +var SkipAttribute = errors.New("skip") + +var ( + UnsupportedNodeType = errors.New("unsupported node type") + UnsupportedAttributeType = errors.New("unsupported attribute type") + UnsupportedAlignment = errors.New("unsupported alignment") +) + +type ( + AttributeEncoder func(*ast.Attribute) (*Attribute, error) + NodeEncoder func(ast.Node) (isNode_Kind, error) +) + +func (f AttributeEncoder) apply(enc *encoder) { + if f != nil { + enc.attributeEncoder = f + } +} + +func (f NodeEncoder) apply(enc *encoder) { + if f != nil { + enc.nodeEncoder = f + } +} + +type EncoderOption interface { + apply(*encoder) +} + +type encoder struct { + attributeEncoder AttributeEncoder + nodeEncoder NodeEncoder + source []byte +} + +func defaultNodeEncoder(node ast.Node) (isNode_Kind, error) { + return nil, fmt.Errorf("%w: %s", UnsupportedNodeType, node.Kind()) +} + +func Encode(root ast.Node, source []byte, opts ...EncoderOption) (node *Node, err error) { + defer func() { + if r := recover(); r != nil { + if pErr, ok := r.(panickyErr); ok { + err = pErr.err + } else { + panic(r) + } + } + }() + enc := &encoder{ + attributeEncoder: DefaultAttributeEncoder, + source: source, + nodeEncoder: defaultNodeEncoder, + } + for _, opt := range opts { + opt.apply(enc) + } + node = enc.encodeNode(root) + return +} + +func (e *encoder) encodeSegment(seg text.Segment) []byte { + if seg.Start > seg.Stop || seg.Start < 0 || seg.Stop > len(e.source) { + // Invalid segment. + return nil + } + // Note: zero-length segments (seg.Start == seg.Stop) are valid, + // and even could be meaningful if padding is > 0. + // Render them using seg.Value. + return seg.Value(e.source) +} + +func (e *encoder) encodeBaseNode(node *ast.BaseNode) *BaseNode { + var res BaseNode + attrs := node.Attributes() + res.Attributes = make([]*Attribute, 0, len(attrs)) + for _, attr := range attrs { + encoded, err := e.attributeEncoder(&attr) + if err != nil { + panic(panickyErr{err: err}) + } + res.Attributes = append(res.Attributes, encoded) + } + res.Children = make([]*Node, 0, node.ChildCount()) + for child := node.FirstChild(); child != nil; child = child.NextSibling() { + res.Children = append(res.Children, e.encodeNode(child)) + } + return &res +} + +func (e *encoder) encodeBaseBlock(node *ast.BaseBlock) (res *BaseNode) { + res = e.encodeBaseNode(&node.BaseNode) + res.BlankPreviousLines = node.HasBlankPreviousLines() + return +} + +func (e *encoder) encodeNode(node ast.Node) *Node { + var kind isNode_Kind + + switch n := node.(type) { + case *ast.Document: + kind = &Node_Document{ + Document: &Document{ + Base: e.encodeBaseBlock(&n.BaseBlock), + }, + } + case *ast.TextBlock: + kind = &Node_TextBlock{ + TextBlock: &TextBlock{ + Base: e.encodeBaseBlock(&n.BaseBlock), + }, + } + case *ast.Paragraph: + kind = &Node_Paragraph{ + Paragraph: &Paragraph{ + Base: e.encodeBaseBlock(&n.BaseBlock), + }, + } + case *ast.Heading: + kind = &Node_Heading{ + Heading: &Heading{ + Base: e.encodeBaseBlock(&n.BaseBlock), + Level: uint32(n.Level), + }, + } + case *ast.ThematicBreak: + kind = &Node_ThematicBreak{ + ThematicBreak: &ThematicBreak{ + Base: e.encodeBaseBlock(&n.BaseBlock), + }, + } + case *ast.CodeBlock: + kind = &Node_CodeBlock{ + CodeBlock: &CodeBlock{ + Base: e.encodeBaseBlock(&n.BaseBlock), + Lines: e.encodeSegments(n.Lines()), + }, + } + case *ast.FencedCodeBlock: + var txt *Text + if n.Info != nil { + txt = &Text{ + Segment: e.encodeSegment(n.Info.Segment), + Raw: n.Info.IsRaw(), + } + } + kind = &Node_FencedCodeBlock{ + FencedCodeBlock: &FencedCodeBlock{ + Base: e.encodeBaseBlock(&n.BaseBlock), + Info: txt, + Lines: e.encodeSegments(n.Lines()), + }, + } + case *ast.Blockquote: + kind = &Node_Blockquote{ + Blockquote: &Blockquote{ + Base: e.encodeBaseBlock(&n.BaseBlock), + }, + } + case *ast.List: + kind = &Node_List{ + List: &List{ + Base: e.encodeBaseBlock(&n.BaseBlock), + Marker: uint32(n.Marker), + IsTight: n.IsTight, + Start: uint32(n.Start), + }, + } + case *ast.ListItem: + kind = &Node_ListItem{ + ListItem: &ListItem{ + Base: e.encodeBaseBlock(&n.BaseBlock), + Offset: int64(n.Offset), + }, + } + case *ast.HTMLBlock: + // Doing encoding manually to prevent a change in the internal representation + // of HTMLBlockType enum from breaking our encoding. + kind = &Node_HtmlBlock{ + HtmlBlock: &HTMLBlock{ + Base: e.encodeBaseBlock(&n.BaseBlock), + Type: encodeHTMLBlockType(n.HTMLBlockType), + Lines: e.encodeSegments(n.Lines()), + ClosureLine: e.encodeSegment(n.ClosureLine), + }, + } + case *ast.Text: + kind = &Node_Text{ + Text: &Text{ + Base: e.encodeBaseNode(&n.BaseNode), + Segment: e.encodeSegment(n.Segment), + SoftLineBreak: n.SoftLineBreak(), + HardLineBreak: n.HardLineBreak(), + Raw: n.IsRaw(), + }, + } + case *ast.String: + kind = &Node_String_{ + String_: &String{ + Base: e.encodeBaseNode(&n.BaseNode), + Value: n.Value, + Raw: n.IsRaw(), + Code: n.IsCode(), + }, + } + case *ast.CodeSpan: + kind = &Node_CodeSpan{ + CodeSpan: &CodeSpan{ + Base: e.encodeBaseNode(&n.BaseNode), + }, + } + case *ast.Emphasis: + kind = &Node_Emphasis{ + Emphasis: &Emphasis{ + Base: e.encodeBaseNode(&n.BaseNode), + Level: int64(n.Level), + }, + } + case *ast.Link: + kind = &Node_LinkOrImage{ + LinkOrImage: &LinkOrImage{ + Base: e.encodeBaseNode(&n.BaseNode), + Destination: n.Destination, + Title: n.Title, + IsImage: false, + }, + } + case *ast.Image: + kind = &Node_LinkOrImage{ + LinkOrImage: &LinkOrImage{ + Base: e.encodeBaseNode(&n.BaseNode), + Destination: n.Destination, + Title: n.Title, + IsImage: true, + }, + } + case *ast.AutoLink: + kind = &Node_AutoLink{ + AutoLink: &AutoLink{ + Base: e.encodeBaseNode(&n.BaseNode), + Type: encodeAutoLinkType(n.AutoLinkType), + Protocol: n.Protocol, + Value: n.Label(e.source), + }, + } + case *ast.RawHTML: + kind = &Node_RawHtml{ + RawHtml: &RawHTML{ + Base: e.encodeBaseNode(&n.BaseNode), + Segments: e.encodeSegments(n.Segments), + }, + } + // GitHub Flavored Markdown + case *east.Table: + kind = &Node_Table{ + Table: &Table{ + Base: e.encodeBaseBlock(&n.BaseBlock), + Alignments: encodeCellAlignments(n.Alignments), + }, + } + + case *east.TableRow: + kind = &Node_TableRow{ + TableRow: &TableRow{ + Base: e.encodeBaseBlock(&n.BaseBlock), + Alignments: encodeCellAlignments(n.Alignments), + IsHeader: false, + }, + } + case *east.TableHeader: + kind = &Node_TableRow{ + TableRow: &TableRow{ + Base: e.encodeBaseBlock(&n.BaseBlock), + Alignments: encodeCellAlignments(n.Alignments), + IsHeader: true, + }, + } + case *east.TableCell: + kind = &Node_TableCell{ + TableCell: &TableCell{ + Base: e.encodeBaseBlock(&n.BaseBlock), + Alignment: encodeCellAlignment(n.Alignment), + }, + } + case *east.Strikethrough: + kind = &Node_Strikethrough{ + Strikethrough: &Strikethrough{ + Base: e.encodeBaseNode(&n.BaseNode), + }, + } + case *east.TaskCheckBox: + kind = &Node_TaskCheckbox{ + TaskCheckbox: &TaskCheckbox{ + Base: e.encodeBaseNode(&n.BaseNode), + IsChecked: n.IsChecked, + }, + } + default: + var err error + kind, err = e.nodeEncoder(node) + if err != nil { + panic(panickyErr{err: err}) + } + } + + return &Node{ + Kind: kind, + } +} + +func (e *encoder) encodeSegments(seg *text.Segments) [][]byte { + res := make([][]byte, seg.Len()) + for i := range res { + res[i] = e.encodeSegment(seg.At(i)) + } + return res +} + +func DefaultAttributeEncoder(attr *ast.Attribute) (*Attribute, error) { + var res isAttribute_Value + switch val := attr.Value.(type) { + case []byte: + res = &Attribute_Bytes{ + Bytes: val, + } + case string: + res = &Attribute_Str{ + Str: val, + } + case uint, uint8, uint16, uint32, uintptr, uint64, int, int8, int16, int32, int64: + res = &Attribute_Str{ + Str: fmt.Sprintf("%d", val), + } + case bool: + res = &Attribute_Bytes{ + Bytes: attr.Name, + } + case float32, float64: + res = &Attribute_Str{ + Str: fmt.Sprintf("%f", val), + } + default: + return nil, fmt.Errorf("%w: %T", UnsupportedAttributeType, attr.Value) + } + return &Attribute{ + Name: attr.Name, + Value: res, + }, nil +} diff --git a/plugin/ast/v1/ast_test.go b/plugin/ast/v1/ast_test.go new file mode 100644 index 00000000..a2db7b67 --- /dev/null +++ b/plugin/ast/v1/ast_test.go @@ -0,0 +1,98 @@ +package astv1_test + +import ( + "bytes" + "testing" + + "github.com/blackstork-io/goldmark-markdown/pkg/mdexamples" + "github.com/yuin/goldmark" + "github.com/yuin/goldmark/extension" + "github.com/yuin/goldmark/text" + + astv1 "github.com/blackstork-io/fabric/plugin/ast/v1" +) + +func roundtrip(t *testing.T, source []byte) { + t.Helper() + md := goldmark.New( + goldmark.WithExtensions( + extension.Table, + extension.Strikethrough, + extension.TaskList, + ), + ) + + tree := md.Parser().Parse(text.NewReader(source)) + + // roundtrip + encTree, err := astv1.Encode(tree, source) + if err != nil { + t.Fatalf("encode: %v", err) + } + decTree, decSrc, err := astv1.Decode(encTree) + if err != nil { + t.Fatalf("decode: %v", err) + } + + // assume that trees are identical if their html render is identical + // can't use equality checks because the segments hold no reference to *which* + // source they are referring to + var bufOrig, bufRoundtrip bytes.Buffer + + err = md.Renderer().Render(&bufOrig, source, tree) + if err != nil { + t.Fatalf("render original: %v", err) + } + + err = md.Renderer().Render(&bufRoundtrip, decSrc, decTree) + if err != nil { + t.Fatalf("render decoded: %v", err) + } + + if !bytes.Equal(bufOrig.Bytes(), bufRoundtrip.Bytes()) { + t.Errorf("rendered html differs") + t.Logf("---------- original -----------\n%s\n\n", bufOrig.String()) + t.Logf("---------- roundtrip ----------\n%s\n\n", bufRoundtrip.String()) + } +} + +func TestSpecExamplesRoundtrip(t *testing.T) { + for _, exFile := range mdexamples.ReadAllSpecExamples() { + for _, ex := range exFile.Examples { + t.Run(exFile.Name+":"+ex.Link, func(t *testing.T) { + t.Parallel() + // Skipped tests are ok to use, we're only interested in the roundtrip + roundtrip(t, ex.Markdown) + }) + } + } +} + +func TestDocumentsRoundtrip(t *testing.T) { + for _, ex := range mdexamples.ReadAllDocumentExamples() { + t.Run(ex.Name, func(t *testing.T) { + t.Parallel() + roundtrip(t, ex.Data) + }) + } +} + +func TestFuzzCase(t *testing.T) { + roundtrip(t, []byte("* 0\n-|\n\t0")) +} + +// go test -fuzz '^FuzzEncoder$' "astcodec/ast/v1" + +func FuzzEncoder(f *testing.F) { + // for _, exFile := range test.ReadAllSpecExamples() { + // for _, ex := range exFile.Examples { + // f.Add(ex.Markdown) + // } + // } + for _, ex := range mdexamples.ReadAllDocumentExamples() { + f.Add(ex.Data) + } + f.Fuzz(func(t *testing.T, data []byte) { + roundtrip(t, data) + }) +} diff --git a/plugin/ast/v1/enum_codec.go b/plugin/ast/v1/enum_codec.go new file mode 100644 index 00000000..f8260577 --- /dev/null +++ b/plugin/ast/v1/enum_codec.go @@ -0,0 +1,116 @@ +package astv1 + +import ( + "github.com/yuin/goldmark/ast" + east "github.com/yuin/goldmark/extension/ast" +) + +func encodeHTMLBlockType(ty ast.HTMLBlockType) HTMLBlockType { + switch ty { + case ast.HTMLBlockType1: + return HTMLBlockType_HTML_BLOCK_TYPE_1 + case ast.HTMLBlockType2: + return HTMLBlockType_HTML_BLOCK_TYPE_2 + case ast.HTMLBlockType3: + return HTMLBlockType_HTML_BLOCK_TYPE_3 + case ast.HTMLBlockType4: + return HTMLBlockType_HTML_BLOCK_TYPE_4 + case ast.HTMLBlockType5: + return HTMLBlockType_HTML_BLOCK_TYPE_5 + case ast.HTMLBlockType6: + return HTMLBlockType_HTML_BLOCK_TYPE_6 + case ast.HTMLBlockType7: + return HTMLBlockType_HTML_BLOCK_TYPE_7 + default: + panic(pErrF("unsupported HTML block type: %v", ty)) + } +} + +func (bt HTMLBlockType) decode() ast.HTMLBlockType { + switch bt { + case HTMLBlockType_HTML_BLOCK_TYPE_1: + return ast.HTMLBlockType1 + case HTMLBlockType_HTML_BLOCK_TYPE_2: + return ast.HTMLBlockType2 + case HTMLBlockType_HTML_BLOCK_TYPE_3: + return ast.HTMLBlockType3 + case HTMLBlockType_HTML_BLOCK_TYPE_4: + return ast.HTMLBlockType4 + case HTMLBlockType_HTML_BLOCK_TYPE_5: + return ast.HTMLBlockType5 + case HTMLBlockType_HTML_BLOCK_TYPE_6: + return ast.HTMLBlockType6 + case HTMLBlockType_HTML_BLOCK_TYPE_7: + return ast.HTMLBlockType7 + default: + panic(pErrF("unsupported HTML block type: %v", bt)) + } +} + +func encodeAutoLinkType(ty ast.AutoLinkType) AutoLinkType { + switch ty { + case ast.AutoLinkURL: + return AutoLinkType_AUTO_LINK_TYPE_URL + case ast.AutoLinkEmail: + return AutoLinkType_AUTO_LINK_TYPE_EMAIL + default: + panic(pErrF("unsupported auto link type: %v", ty)) + } +} + +func (ty AutoLinkType) decode() ast.AutoLinkType { + switch ty { + case AutoLinkType_AUTO_LINK_TYPE_URL: + return ast.AutoLinkURL + case AutoLinkType_AUTO_LINK_TYPE_EMAIL: + return ast.AutoLinkEmail + default: + panic(pErrF("unsupported auto link type: %v", ty)) + } +} + +func encodeCellAlignment(alignment east.Alignment) CellAlignment { + switch alignment { + case east.AlignLeft: + return CellAlignment_CELL_ALIGNMENT_LEFT + case east.AlignRight: + return CellAlignment_CELL_ALIGNMENT_RIGHT + case east.AlignCenter: + return CellAlignment_CELL_ALIGNMENT_CENTER + case east.AlignNone: + return CellAlignment_CELL_ALIGNMENT_NONE + default: + panic(pErrF("unsupported cell alignment: %v", alignment)) + } +} + +func (ca CellAlignment) decode() east.Alignment { + switch ca { + case CellAlignment_CELL_ALIGNMENT_NONE: + return east.AlignNone + case CellAlignment_CELL_ALIGNMENT_LEFT: + return east.AlignLeft + case CellAlignment_CELL_ALIGNMENT_RIGHT: + return east.AlignRight + case CellAlignment_CELL_ALIGNMENT_CENTER: + return east.AlignCenter + default: + panic(pErrF("unsupported cell alignment: %v", ca)) + } +} + +func encodeCellAlignments(align []east.Alignment) []CellAlignment { + res := make([]CellAlignment, len(align)) + for i, a := range align { + res[i] = encodeCellAlignment(a) + } + return res +} + +func decodeCellAlignments(align []CellAlignment) []east.Alignment { + res := make([]east.Alignment, len(align)) + for i, a := range align { + res[i] = a.decode() + } + return res +} diff --git a/plugin/ast/v1/interfaces.go b/plugin/ast/v1/interfaces.go new file mode 100644 index 00000000..4bfb6142 --- /dev/null +++ b/plugin/ast/v1/interfaces.go @@ -0,0 +1,306 @@ +package astv1 + +import "slices" + +type Content interface { + ExtendNodes(nodes []*Node) []*Node +} + +type Contents []Content + +func (c Contents) ExtendNodes(nodes []*Node) []*Node { + for _, content := range c { + nodes = content.ExtendNodes(nodes) + } + return nodes +} + +// InlineContent represents any inline node or something convertable to inline nodes. +type InlineContent interface { + Content + isInline() +} + +// Inlines is a list of InlineContent. +type Inlines []InlineContent + +func (n Inlines) isInline() {} +func (n Inlines) ExtendNodes(nodes []*Node) []*Node { + for _, inlines := range n { + nodes = inlines.ExtendNodes(nodes) + } + return nodes +} + +func (n *Node_CodeSpan) isInline() {} +func (n *Node_CodeSpan) ExtendNodes(nodes []*Node) []*Node { + return append(nodes, &Node{Kind: n}) +} + +func (n *Node_Emphasis) isInline() {} +func (n *Node_Emphasis) ExtendNodes(nodes []*Node) []*Node { + return append(nodes, &Node{Kind: n}) +} + +func (n *Node_LinkOrImage) isInline() {} +func (n *Node_LinkOrImage) ExtendNodes(nodes []*Node) []*Node { + return append(nodes, &Node{Kind: n}) +} + +func (n *Node_LinkOrImage) SetDestination(url string) *Node_LinkOrImage { + n.LinkOrImage.Destination = []byte(url) + return n +} + +func (n *Node_LinkOrImage) SetTitle(title string) *Node_LinkOrImage { + n.LinkOrImage.Title = []byte(title) + return n +} + +func (n *Node_AutoLink) isInline() {} +func (n *Node_AutoLink) ExtendNodes(nodes []*Node) []*Node { + return append(nodes, &Node{Kind: n}) +} + +func (n *Node_RawHtml) isInline() {} +func (n *Node_RawHtml) ExtendNodes(nodes []*Node) []*Node { + return append(nodes, &Node{Kind: n}) +} + +func (n *Node_Text) isInline() {} +func (n *Node_Text) ExtendNodes(nodes []*Node) []*Node { + return append(nodes, &Node{Kind: n}) +} + +func (n *Node_String_) isInline() {} +func (n *Node_String_) ExtendNodes(nodes []*Node) []*Node { + return append(nodes, &Node{Kind: n}) +} + +func (n *Node_Strikethrough) isInline() {} +func (n *Node_Strikethrough) ExtendNodes(nodes []*Node) []*Node { + return append(nodes, &Node{Kind: n}) +} + +// checkbox is inline content, but it can be used only in a list item. + +// BlockContent represents any block node or something convertable to block nodes. +type BlockContent interface { + Content + isBlock() +} +type Blocks []BlockContent + +func (b Blocks) isBlock() {} +func (b Blocks) ExtendNodes(nodes []*Node) []*Node { + for _, inlines := range b { + nodes = inlines.ExtendNodes(nodes) + } + return nodes +} + +func (n *Node_Blockquote) isBlock() {} +func (n *Node_Blockquote) ExtendNodes(nodes []*Node) []*Node { + return append(nodes, &Node{Kind: n}) +} + +func (n *Node_List) isBlock() {} +func (n *Node_List) ExtendNodes(nodes []*Node) []*Node { + if n == nil || n.List == nil || n.List.Base == nil || len(n.List.Base.Children) == 0 { + return nodes + } + return append(nodes, &Node{ + Kind: n, + }) +} + +// SetStart sets the start number of the list (only works on ordered lists, "." and ")" markers). +func (n *Node_List) SetStart(start uint32) *Node_List { + switch n.List.Marker { + case '.', ')': + n.List.Start = start + } + return n +} + +func prependCheckbox(checked bool, content []BlockContent) (itemChildren []*Node) { + itemChildren = Blocks.ExtendNodes(content, nil) + + checkbox := &Node{ + Kind: &Node_TaskCheckbox{ + TaskCheckbox: &TaskCheckbox{ + IsChecked: checked, + }, + }, + } + + if len(itemChildren) > 0 { + if text, ok := itemChildren[0].Kind.(*Node_Paragraph); ok { + text.Paragraph.Base.Children = slices.Insert(text.Paragraph.Base.Children, 0, checkbox) + return + } + } + // Checkbox was not prepended to existing paragraph, create a new paragraph. + itemChildren = slices.Insert(itemChildren, 0, &Node{ + Kind: &Node_Paragraph{ + Paragraph: &Paragraph{ + Base: &BaseNode{ + Children: []*Node{checkbox}, + }, + }, + }, + }) + return +} + +func (n *Node_List) appendItem(children []*Node) { + n.List.Base.Children = append(n.List.Base.Children, &Node{ + Kind: &Node_ListItem{ + ListItem: &ListItem{ + Base: &BaseNode{ + Children: children, + }, + }, + }, + }) +} + +// AppendItem appends a list item to the list. +func (n *Node_List) AppendItem(content ...BlockContent) *Node_List { + n.appendItem(Blocks.ExtendNodes(content, nil)) + return n +} + +// AppendTaskItem appends a task list item to the list. +func (n *Node_List) AppendTaskItem(checked bool, content ...BlockContent) *Node_List { + n.appendItem(prependCheckbox(checked, content)) + return n +} + +// Thematic breaks +func (n *Node_ThematicBreak) isBlock() {} + +func (n *Node_ThematicBreak) ExtendNodes(nodes []*Node) []*Node { + return append(nodes, &Node{Kind: n}) +} + +func (n *Node_Heading) isBlock() {} + +func (n *Node_Heading) ExtendNodes(nodes []*Node) []*Node { + return append(nodes, &Node{Kind: n}) +} + +func (n *Node_CodeBlock) isBlock() {} + +func (n *Node_CodeBlock) ExtendNodes(nodes []*Node) []*Node { + return append(nodes, &Node{Kind: n}) +} + +func (n *Node_FencedCodeBlock) isBlock() {} + +func (n *Node_FencedCodeBlock) ExtendNodes(nodes []*Node) []*Node { + return append(nodes, &Node{Kind: n}) +} + +func (n *Node_FencedCodeBlock) SetLanguage(language string) *Node_FencedCodeBlock { + n.FencedCodeBlock.Info = &Text{ + Segment: []byte(language), + } + return n +} + +func (n *Node_HtmlBlock) isBlock() {} +func (n *Node_HtmlBlock) ExtendNodes(nodes []*Node) []*Node { + return append(nodes, &Node{Kind: n}) +} + +func (n *Node_Paragraph) isBlock() {} +func (n *Node_Paragraph) ExtendNodes(nodes []*Node) []*Node { + return append(nodes, &Node{Kind: n}) +} + +func (n *Node_Table) isBlock() {} +func (n *Node_Table) ExtendNodes(nodes []*Node) []*Node { + if n == nil { + return nodes + } + rows := n.Table.GetBase().GetChildren() + if len(rows) == 0 { + return nodes + } + headerCellCount := len(rows[0].GetTableRow().GetBase().GetChildren()) + if headerCellCount == 0 { + // must have at least one table cell + return nodes + } + unspecifiedAlignments := headerCellCount - len(n.Table.Alignments) + if unspecifiedAlignments <= 0 { + // Trim the alignments to the number of header cells + n.Table.Alignments = n.Table.Alignments[:len(n.Table.Alignments)+unspecifiedAlignments] + } else { + // Extend the alignments to the number of header cells, filling missing alignments with NONE + n.Table.Alignments = slices.Grow(n.Table.Alignments, unspecifiedAlignments) + for i := 0; i < unspecifiedAlignments; i++ { + n.Table.Alignments = append(n.Table.Alignments, CellAlignment_CELL_ALIGNMENT_NONE) + } + } + for rowIdx, row := range rows { + tr := row.GetTableRow() + if tr == nil { + return nodes + } + tr.IsHeader = rowIdx == 0 + cells := tr.GetBase().Children + tr.Alignments = n.Table.Alignments[:min(len(cells), len(n.Table.Alignments))] + for i, cell := range cells { + c := cell.GetTableCell() + if c == nil { + return nodes + } + if i < len(tr.Alignments) { + c.Alignment = tr.Alignments[i] + } else { + c.Alignment = CellAlignment_CELL_ALIGNMENT_NONE + } + } + } + return append(nodes, &Node{Kind: n}) +} + +func (n *Node_Table) SetColumnAlignments(alignments ...CellAlignment) *Node_Table { + n.Table.Alignments = alignments + return n +} + +func (n *Node_Table) AppendRow(cells ...[]InlineContent) *Node_Table { + if len(cells) == 0 { + return n + } + cellNodes := make([]*Node, len(cells)) + for i, cellContent := range cells { + if cellContent == nil { + continue + } + cellNodes[i] = &Node{ + Kind: &Node_TableCell{ + TableCell: &TableCell{ + Base: &BaseNode{ + Children: Inlines.ExtendNodes(cellContent, nil), + }, + }, + }, + } + } + + n.Table.Base.Children = append(n.Table.Base.Children, &Node{ + Kind: &Node_TableRow{ + TableRow: &TableRow{ + Base: &BaseNode{ + Children: cellNodes, + }, + IsHeader: false, + }, + }, + }) + return n +} diff --git a/plugin/ast/v1/testdata/fuzz/FuzzEncoder/2a2178732c0ce29f b/plugin/ast/v1/testdata/fuzz/FuzzEncoder/2a2178732c0ce29f new file mode 100644 index 00000000..cc5aa59b --- /dev/null +++ b/plugin/ast/v1/testdata/fuzz/FuzzEncoder/2a2178732c0ce29f @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("* 0\n-|\n\t0") diff --git a/plugin/ast/v1/testdata/fuzz/FuzzEncoder/6b5e47038908d6af b/plugin/ast/v1/testdata/fuzz/FuzzEncoder/6b5e47038908d6af new file mode 100644 index 00000000..918fda37 --- /dev/null +++ b/plugin/ast/v1/testdata/fuzz/FuzzEncoder/6b5e47038908d6af @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte(" ```\n\t") diff --git a/plugin/ast/v1/testdata/fuzz/FuzzEncoder/ad3dae11905f3e82 b/plugin/ast/v1/testdata/fuzz/FuzzEncoder/ad3dae11905f3e82 new file mode 100644 index 00000000..87184aad --- /dev/null +++ b/plugin/ast/v1/testdata/fuzz/FuzzEncoder/ad3dae11905f3e82 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("> ```\n>\t0") diff --git a/plugin/ast/v1/util.go b/plugin/ast/v1/util.go new file mode 100644 index 00000000..ffce9ccb --- /dev/null +++ b/plugin/ast/v1/util.go @@ -0,0 +1,11 @@ +package astv1 + +import "fmt" + +type panickyErr struct { + err error +} + +func pErrF(format string, a ...any) panickyErr { + return panickyErr{err: fmt.Errorf(format, a...)} +} diff --git a/proto/ast/v1/ast.proto b/proto/ast/v1/ast.proto new file mode 100644 index 00000000..78108e60 --- /dev/null +++ b/proto/ast/v1/ast.proto @@ -0,0 +1,242 @@ +syntax = "proto3"; + +package ast.v1; + +import "google/protobuf/any.proto"; + +message Attribute { + bytes name = 1; + oneof value { + bytes bytes = 2; + string str = 3; + } +} + +message BaseNode { + repeated Node children = 1; + repeated Attribute attributes = 2; + // value meaningful only for blocks + bool blank_previous_lines = 3; +} + +message Node { + oneof kind { + // Blocks + Document document = 1; + TextBlock text_block = 5; + Paragraph paragraph = 6; + Heading heading = 7; + ThematicBreak thematic_break = 8; + CodeBlock code_block = 9; + FencedCodeBlock fenced_code_block = 10; + Blockquote blockquote = 11; + List list = 12; + ListItem list_item = 13; + HTMLBlock html_block = 14; + + // inlines + Text text = 15; + String string = 16; + CodeSpan code_span = 17; + Emphasis emphasis = 18; + LinkOrImage link_or_image = 19; + AutoLink auto_link = 20; + RawHTML raw_html = 21; + + // Github Flavored Markdown + Table table = 22; + TableRow table_row = 23; + TableCell table_cell = 24; + // inline + TaskCheckbox task_checkbox = 25; + Strikethrough strikethrough = 26; + + + // Root of the plugin-rendered data + PluginMetadata plugin_meta = 254; + // Custom node types can be serialized using this + OtherKind other = 255; + } +} + +// Node kinds + +message Document { + BaseNode base = 1; +} + +message TextBlock { + BaseNode base = 1; +} + +message Paragraph { + BaseNode base = 1; +} + +message Heading { + BaseNode base = 1; + uint32 level = 2; +} + +message ThematicBreak { + BaseNode base = 1; +} + +message CodeBlock { + BaseNode base = 1; + repeated bytes lines = 2; +} + +message FencedCodeBlock { + BaseNode base = 1; + Text info = 2; + repeated bytes lines = 3; +} + +message Blockquote { + BaseNode base = 1; +} + +message List { + BaseNode base = 1; + uint32 marker = 2; + bool is_tight = 3; + uint32 start = 4; +} + +message ListItem { + BaseNode base = 1; + int64 offset = 2; +} + +enum HTMLBlockType { + HTML_BLOCK_TYPE_UNSPECIFIED = 0; + HTML_BLOCK_TYPE_1 = 1; + HTML_BLOCK_TYPE_2 = 2; + HTML_BLOCK_TYPE_3 = 3; + HTML_BLOCK_TYPE_4 = 4; + HTML_BLOCK_TYPE_5 = 5; + HTML_BLOCK_TYPE_6 = 6; + HTML_BLOCK_TYPE_7 = 7; +} + +message HTMLBlock { + BaseNode base = 1; + HTMLBlockType type = 2; + repeated bytes lines = 3; + bytes closure_line = 4; +} + +message Text { + BaseNode base = 1; + bytes segment = 2; + bool soft_line_break = 3; + bool hard_line_break = 4; + bool raw = 5; +} + +message String { + BaseNode base = 1; + bytes value = 2; + bool raw = 3; + bool code = 4; +} + +message CodeSpan { + BaseNode base = 1; +} + +message Emphasis { + BaseNode base = 1; + int64 level = 2; +} + +message LinkOrImage { + BaseNode base = 1; + bytes destination = 2; + bytes title = 3; + bool is_image = 4; +} + +enum AutoLinkType { + AUTO_LINK_TYPE_UNSPECIFIED = 0; + AUTO_LINK_TYPE_EMAIL = 1; + AUTO_LINK_TYPE_URL = 2; +} + +message AutoLink { + BaseNode base = 1; + AutoLinkType type = 2; + bytes protocol = 3; + bytes value = 4; +} + +message RawHTML { + BaseNode base = 1; + repeated bytes segments = 2; +} + +enum CellAlignment { + CELL_ALIGNMENT_UNSPECIFIED = 0; + CELL_ALIGNMENT_LEFT = 1; + CELL_ALIGNMENT_RIGHT = 2; + CELL_ALIGNMENT_CENTER = 3; + CELL_ALIGNMENT_NONE = 4; +} + +message Table { + BaseNode base = 1; + repeated CellAlignment alignments = 2; +} + +message TableRow { + BaseNode base = 1; + repeated CellAlignment alignments = 2; + bool is_header = 4; +} + +message TableCell { + BaseNode base = 1; + CellAlignment alignment = 2; +} + +message TaskCheckbox { + BaseNode base = 1; + bool is_checked = 2; +} + +message Strikethrough { + BaseNode base = 1; +} + + +// Fabric plugin metadata, transparent for the render +message PluginMetadata { + // Fully qualified plugin name with version + string generated_by = 1; + + oneof content { + // Static node content + BaseNode static = 2; + // Custom node renderer must be used + CustomRenderer custom_renderer = 3; + } +} + +message CustomRenderer { + // Input for the custom renderer + bytes data = 1; + // Format => content map. + // Results of custom render of the `data` to `format` are stored in this cache + // Repeaded renders to the same format should use it, instead of calling the plugin. + // Changes to data (i.e. editing via web interface) should clear the cache + map cache = 2; +} + +message OtherKind { + BaseNode base = 1; + bool is_block = 2; + + string name = 3; + google.protobuf.Any other = 4; +}