Use the schema package's Markdown parser and walk its AST to extract examples. These changes also rename StripNonRelevantExamples to FilterExamples. This is preparatory work for #4159 and #4632.
124 lines
3.2 KiB
Go
124 lines
3.2 KiB
Go
// Copyright 2016-2020, Pulumi Corporation.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Pulling out some of the repeated strings tokens into constants would harm readability, so we just ignore the
|
|
// goconst linter's warning.
|
|
//
|
|
// nolint: lll, goconst
|
|
package docs
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/pgavlin/goldmark/ast"
|
|
|
|
"github.com/pulumi/pulumi/pkg/v2/codegen"
|
|
"github.com/pulumi/pulumi/pkg/v2/codegen/schema"
|
|
"github.com/pulumi/pulumi/sdk/v2/go/common/util/contract"
|
|
)
|
|
|
|
const defaultMissingExampleSnippetPlaceholder = "Coming soon!"
|
|
|
|
type exampleSection struct {
|
|
Title string
|
|
// Snippets is a map of language to its code snippet, if any.
|
|
Snippets map[string]string
|
|
}
|
|
|
|
type docInfo struct {
|
|
description string
|
|
examples []exampleSection
|
|
}
|
|
|
|
func decomposeDocstring(docstring string) docInfo {
|
|
if docstring == "" {
|
|
return docInfo{}
|
|
}
|
|
|
|
languages := codegen.NewStringSet(snippetLanguages...)
|
|
|
|
source := []byte(docstring)
|
|
parsed := schema.ParseDocs(source)
|
|
|
|
var examplesShortcode *schema.Shortcode
|
|
var exampleShortcode *schema.Shortcode
|
|
var title string
|
|
var snippets map[string]string
|
|
var examples []exampleSection
|
|
err := ast.Walk(parsed, func(n ast.Node, enter bool) (ast.WalkStatus, error) {
|
|
if shortcode, ok := n.(*schema.Shortcode); ok {
|
|
name := string(shortcode.Name)
|
|
switch name {
|
|
case schema.ExamplesShortcode:
|
|
if examplesShortcode == nil {
|
|
examplesShortcode = shortcode
|
|
}
|
|
case schema.ExampleShortcode:
|
|
if exampleShortcode == nil {
|
|
exampleShortcode, title, snippets = shortcode, "", map[string]string{}
|
|
} else if !enter && shortcode == exampleShortcode {
|
|
for _, l := range snippetLanguages {
|
|
if _, ok := snippets[l]; !ok {
|
|
snippets[l] = defaultMissingExampleSnippetPlaceholder
|
|
}
|
|
}
|
|
|
|
examples = append(examples, exampleSection{
|
|
Title: title,
|
|
Snippets: snippets,
|
|
})
|
|
|
|
exampleShortcode = nil
|
|
}
|
|
}
|
|
return ast.WalkContinue, nil
|
|
}
|
|
if exampleShortcode == nil {
|
|
return ast.WalkContinue, nil
|
|
}
|
|
|
|
switch n := n.(type) {
|
|
case *ast.Heading:
|
|
if n.Level == 3 && title == "" {
|
|
title = strings.TrimSpace(schema.RenderDocsToString(source, n))
|
|
}
|
|
case *ast.FencedCodeBlock:
|
|
language := string(n.Language(source))
|
|
if !languages.Has(language) {
|
|
return ast.WalkContinue, nil
|
|
}
|
|
if _, ok := snippets[language]; ok {
|
|
return ast.WalkContinue, nil
|
|
}
|
|
|
|
snippet := schema.RenderDocsToString(source, n)
|
|
snippets[language] = snippet
|
|
}
|
|
|
|
return ast.WalkContinue, nil
|
|
})
|
|
contract.AssertNoError(err)
|
|
|
|
if examplesShortcode != nil {
|
|
p := examplesShortcode.Parent()
|
|
p.RemoveChild(p, examplesShortcode)
|
|
}
|
|
|
|
description := schema.RenderDocsToString(source, parsed)
|
|
|
|
return docInfo{
|
|
description: description,
|
|
examples: examples,
|
|
}
|
|
}
|