diff --git a/docs/pipeline-api.md b/docs/pipeline-api.md
new file mode 100644
index 00000000000..e160a627d99
--- /dev/null
+++ b/docs/pipeline-api.md
@@ -0,0 +1,8550 @@
+
Packages:
+
+tekton.dev/v1alpha1
+
+
Package v1alpha1 contains API Schema definitions for the pipeline v1alpha1 API group
+
+Resource Types:
+
+ClusterTask
+
+
+
ClusterTask is a Task with a cluster scope. ClusterTasks are used to
+represent Tasks that should be publicly addressable from any namespace in the
+cluster.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+apiVersion
+string |
+
+
+tekton.dev/v1alpha1
+
+ |
+
+
+
+kind
+string
+ |
+ClusterTask |
+
+
+
+metadata
+
+
+Kubernetes meta/v1.ObjectMeta
+
+
+ |
+
+(Optional)
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+
+
+
+spec
+
+
+TaskSpec
+
+
+ |
+
+(Optional)
+ Spec holds the desired state of the Task from the client
+
+
+
+
+
+TaskSpec
+
+
+TaskSpec
+
+
+ |
+
+
+(Members of TaskSpec are embedded into this type.)
+
+ |
+
+
+
+inputs
+
+
+Inputs
+
+
+ |
+
+(Optional)
+ Inputs is an optional set of parameters and resources which must be
+supplied by the user when a Task is executed by a TaskRun.
+ |
+
+
+
+outputs
+
+
+Outputs
+
+
+ |
+
+(Optional)
+ Outputs is an optional set of resources and results produced when this
+Task is run.
+ |
+
+
+ |
+
+
+
+Condition
+
+
+
Condition declares a step that is used to gate the execution of a Task in a Pipeline.
+A condition execution (ConditionCheck) evaluates to either true or false
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+apiVersion
+string |
+
+
+tekton.dev/v1alpha1
+
+ |
+
+
+
+kind
+string
+ |
+Condition |
+
+
+
+metadata
+
+
+Kubernetes meta/v1.ObjectMeta
+
+
+ |
+
+(Optional)
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+
+
+
+spec
+
+
+ConditionSpec
+
+
+ |
+
+(Optional)
+ Spec holds the desired state of the Condition from the client
+
+
+
+
+
+check
+
+
+Step
+
+
+ |
+
+ Check declares container whose exit code determines where a condition is true or false
+ |
+
+
+
+description
+
+string
+
+ |
+
+(Optional)
+ Description is a user-facing description of the condition that may be
+used to populate a UI.
+ |
+
+
+
+params
+
+
+[]ParamSpec
+
+
+ |
+
+(Optional)
+ Params is an optional set of parameters which must be supplied by the user when a Condition
+is evaluated
+ |
+
+
+
+resources
+
+
+[]ResourceDeclaration
+
+
+ |
+
+(Optional)
+ Resources is a list of the ConditionResources required to run the condition.
+ |
+
+
+ |
+
+
+
+Pipeline
+
+
+
Pipeline describes a list of Tasks to execute. It expresses how outputs
+of tasks feed into inputs of subsequent tasks.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+apiVersion
+string |
+
+
+tekton.dev/v1alpha1
+
+ |
+
+
+
+kind
+string
+ |
+Pipeline |
+
+
+
+metadata
+
+
+Kubernetes meta/v1.ObjectMeta
+
+
+ |
+
+(Optional)
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+
+
+
+spec
+
+
+PipelineSpec
+
+
+ |
+
+(Optional)
+ Spec holds the desired state of the Pipeline from the client
+
+
+
+
+
+description
+
+string
+
+ |
+
+(Optional)
+ Description is a user-facing description of the pipeline that may be
+used to populate a UI.
+ |
+
+
+
+resources
+
+
+[]PipelineDeclaredResource
+
+
+ |
+
+ Resources declares the names and types of the resources given to the
+Pipeline’s tasks as inputs and outputs.
+ |
+
+
+
+tasks
+
+
+[]PipelineTask
+
+
+ |
+
+ Tasks declares the graph of Tasks that execute when this Pipeline is run.
+ |
+
+
+
+params
+
+
+[]ParamSpec
+
+
+ |
+
+ Params declares a list of input parameters that must be supplied when
+this Pipeline is run.
+ |
+
+
+
+workspaces
+
+
+[]PipelineWorkspaceDeclaration
+
+
+ |
+
+(Optional)
+ Workspaces declares a set of named workspaces that are expected to be
+provided by a PipelineRun.
+ |
+
+
+
+results
+
+
+[]PipelineResult
+
+
+ |
+
+(Optional)
+ Results are values that this pipeline can output once run
+ |
+
+
+ |
+
+
+
+status
+
+
+PipelineStatus
+
+
+ |
+
+(Optional)
+ Status is deprecated.
+It usually is used to communicate the observed state of the Pipeline from
+the controller, but was unused as there is no controller for Pipeline.
+ |
+
+
+
+PipelineRun
+
+
+
PipelineRun represents a single execution of a Pipeline. PipelineRuns are how
+the graph of Tasks declared in a Pipeline are executed; they specify inputs
+to Pipelines such as parameter values and capture operational aspects of the
+Tasks execution such as service account and tolerations. Creating a
+PipelineRun creates TaskRuns for Tasks in the referenced Pipeline.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+apiVersion
+string |
+
+
+tekton.dev/v1alpha1
+
+ |
+
+
+
+kind
+string
+ |
+PipelineRun |
+
+
+
+metadata
+
+
+Kubernetes meta/v1.ObjectMeta
+
+
+ |
+
+(Optional)
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+
+
+
+spec
+
+
+PipelineRunSpec
+
+
+ |
+
+(Optional)
+
+
+
+
+
+pipelineRef
+
+
+PipelineRef
+
+
+ |
+
+(Optional)
+ |
+
+
+
+pipelineSpec
+
+
+PipelineSpec
+
+
+ |
+
+(Optional)
+ |
+
+
+
+resources
+
+
+[]PipelineResourceBinding
+
+
+ |
+
+ Resources is a list of bindings specifying which actual instances of
+PipelineResources to use for the resources the Pipeline has declared
+it needs.
+ |
+
+
+
+params
+
+
+[]Param
+
+
+ |
+
+ Params is a list of parameter names and values.
+ |
+
+
+
+serviceAccountName
+
+string
+
+ |
+
+(Optional)
+ |
+
+
+
+serviceAccountNames
+
+
+[]PipelineRunSpecServiceAccountName
+
+
+ |
+
+(Optional)
+ |
+
+
+
+status
+
+
+PipelineRunSpecStatus
+
+
+ |
+
+(Optional)
+ Used for cancelling a pipelinerun (and maybe more later on)
+ |
+
+
+
+timeout
+
+
+Kubernetes meta/v1.Duration
+
+
+ |
+
+(Optional)
+ Time after which the Pipeline times out. Defaults to never.
+Refer to Go’s ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration
+ |
+
+
+
+podTemplate
+
+
+Template
+
+
+ |
+
+ PodTemplate holds pod specific configuration
+ |
+
+
+
+workspaces
+
+
+[]WorkspaceBinding
+
+
+ |
+
+(Optional)
+ Workspaces holds a set of workspace bindings that must match names
+with those declared in the pipeline.
+ |
+
+
+
+taskRunSpecs
+
+
+[]PipelineTaskRunSpec
+
+
+ |
+
+(Optional)
+ TaskRunSpecs holds a set of task specific specs
+ |
+
+
+ |
+
+
+
+status
+
+
+PipelineRunStatus
+
+
+ |
+
+(Optional)
+ |
+
+
+
+Run
+
+
+
Run represents a single execution of a Custom Task.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+apiVersion
+string |
+
+
+tekton.dev/v1alpha1
+
+ |
+
+
+
+kind
+string
+ |
+Run |
+
+
+
+metadata
+
+
+Kubernetes meta/v1.ObjectMeta
+
+
+ |
+
+(Optional)
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+
+
+
+spec
+
+
+RunSpec
+
+
+ |
+
+(Optional)
+
+
+
+
+
+ref
+
+
+TaskRef
+
+
+ |
+
+(Optional)
+ |
+
+
+
+spec
+
+
+EmbeddedRunSpec
+
+
+ |
+
+(Optional)
+ Spec is a specification of a custom task
+
+
+
+ |
+
+
+
+params
+
+
+[]Param
+
+
+ |
+
+(Optional)
+ |
+
+
+
+status
+
+
+RunSpecStatus
+
+
+ |
+
+(Optional)
+ Used for cancelling a run (and maybe more later on)
+ |
+
+
+
+retries
+
+int
+
+ |
+
+(Optional)
+ Used for propagating retries count to custom tasks
+ |
+
+
+
+serviceAccountName
+
+string
+
+ |
+
+(Optional)
+ |
+
+
+
+podTemplate
+
+
+Template
+
+
+ |
+
+(Optional)
+ PodTemplate holds pod specific configuration
+ |
+
+
+
+timeout
+
+
+Kubernetes meta/v1.Duration
+
+
+ |
+
+(Optional)
+ Time after which the custom-task times out.
+Refer Go’s ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration
+ |
+
+
+
+workspaces
+
+
+[]WorkspaceBinding
+
+
+ |
+
+(Optional)
+ Workspaces is a list of WorkspaceBindings from volumes to workspaces.
+ |
+
+
+ |
+
+
+
+status
+
+
+RunStatus
+
+
+ |
+
+(Optional)
+ |
+
+
+
+Task
+
+
+
Task represents a collection of sequential steps that are run as part of a
+Pipeline using a set of inputs and producing a set of outputs. Tasks execute
+when TaskRuns are created that provide the input parameters and resources and
+output resources the Task requires.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+apiVersion
+string |
+
+
+tekton.dev/v1alpha1
+
+ |
+
+
+
+kind
+string
+ |
+Task |
+
+
+
+metadata
+
+
+Kubernetes meta/v1.ObjectMeta
+
+
+ |
+
+(Optional)
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+
+
+
+spec
+
+
+TaskSpec
+
+
+ |
+
+(Optional)
+ Spec holds the desired state of the Task from the client
+
+
+
+
+
+TaskSpec
+
+
+TaskSpec
+
+
+ |
+
+
+(Members of TaskSpec are embedded into this type.)
+
+ |
+
+
+
+inputs
+
+
+Inputs
+
+
+ |
+
+(Optional)
+ Inputs is an optional set of parameters and resources which must be
+supplied by the user when a Task is executed by a TaskRun.
+ |
+
+
+
+outputs
+
+
+Outputs
+
+
+ |
+
+(Optional)
+ Outputs is an optional set of resources and results produced when this
+Task is run.
+ |
+
+
+ |
+
+
+
+TaskRun
+
+
+
TaskRun represents a single execution of a Task. TaskRuns are how the steps
+specified in a Task are executed; they specify the parameters and resources
+used to run the steps in a Task.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+apiVersion
+string |
+
+
+tekton.dev/v1alpha1
+
+ |
+
+
+
+kind
+string
+ |
+TaskRun |
+
+
+
+metadata
+
+
+Kubernetes meta/v1.ObjectMeta
+
+
+ |
+
+(Optional)
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+
+
+
+spec
+
+
+TaskRunSpec
+
+
+ |
+
+(Optional)
+
+
+
+
+
+serviceAccountName
+
+string
+
+ |
+
+(Optional)
+ |
+
+
+
+taskRef
+
+
+TaskRef
+
+
+ |
+
+(Optional)
+ no more than one of the TaskRef and TaskSpec may be specified.
+ |
+
+
+
+taskSpec
+
+
+TaskSpec
+
+
+ |
+
+(Optional)
+ |
+
+
+
+status
+
+
+TaskRunSpecStatus
+
+
+ |
+
+(Optional)
+ Used for cancelling a taskrun (and maybe more later on)
+ |
+
+
+
+timeout
+
+
+Kubernetes meta/v1.Duration
+
+
+ |
+
+(Optional)
+ Time after which the build times out. Defaults to 10 minutes.
+Specified build timeout should be less than 24h.
+Refer Go’s ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration
+ |
+
+
+
+podTemplate
+
+
+Template
+
+
+ |
+
+(Optional)
+ PodTemplate holds pod specific configuration
+ |
+
+
+
+workspaces
+
+
+[]WorkspaceBinding
+
+
+ |
+
+(Optional)
+ Workspaces is a list of WorkspaceBindings from volumes to workspaces.
+ |
+
+
+
+params
+
+
+[]Param
+
+
+ |
+
+(Optional)
+ From v1beta1
+ |
+
+
+
+resources
+
+
+TaskRunResources
+
+
+ |
+
+(Optional)
+ |
+
+
+
+inputs
+
+
+TaskRunInputs
+
+
+ |
+
+(Optional)
+ Deprecated
+ |
+
+
+
+outputs
+
+
+TaskRunOutputs
+
+
+ |
+
+(Optional)
+ |
+
+
+ |
+
+
+
+status
+
+
+TaskRunStatus
+
+
+ |
+
+(Optional)
+ |
+
+
+
+PipelineResource
+
+
+
PipelineResource describes a resource that is an input to or output from a
+Task.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+apiVersion
+string |
+
+
+tekton.dev/v1alpha1
+
+ |
+
+
+
+kind
+string
+ |
+PipelineResource |
+
+
+
+metadata
+
+
+Kubernetes meta/v1.ObjectMeta
+
+
+ |
+
+(Optional)
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+
+
+
+spec
+
+
+PipelineResourceSpec
+
+
+ |
+
+ Spec holds the desired state of the PipelineResource from the client
+
+
+
+
+
+description
+
+string
+
+ |
+
+(Optional)
+ Description is a user-facing description of the resource that may be
+used to populate a UI.
+ |
+
+
+
+type
+
+string
+
+ |
+
+ |
+
+
+
+params
+
+
+[]ResourceParam
+
+
+ |
+
+ |
+
+
+
+secrets
+
+
+[]SecretParam
+
+
+ |
+
+(Optional)
+ Secrets to fetch to populate some of resource fields
+ |
+
+
+ |
+
+
+
+status
+
+
+PipelineResourceStatus
+
+
+ |
+
+(Optional)
+ Status is deprecated.
+It usually is used to communicate the observed state of the PipelineResource from
+the controller, but was unused as there is no controller for PipelineResource.
+ |
+
+
+
+ConditionCheck
+
+
+
ConditionCheck represents a single evaluation of a Condition step.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+metadata
+
+
+Kubernetes meta/v1.ObjectMeta
+
+
+ |
+
+(Optional)
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+
+
+
+spec
+
+
+TaskRunSpec
+
+
+ |
+
+(Optional)
+
+
+
+
+
+serviceAccountName
+
+string
+
+ |
+
+(Optional)
+ |
+
+
+
+taskRef
+
+
+TaskRef
+
+
+ |
+
+(Optional)
+ no more than one of the TaskRef and TaskSpec may be specified.
+ |
+
+
+
+taskSpec
+
+
+TaskSpec
+
+
+ |
+
+(Optional)
+ |
+
+
+
+status
+
+
+TaskRunSpecStatus
+
+
+ |
+
+(Optional)
+ Used for cancelling a taskrun (and maybe more later on)
+ |
+
+
+
+timeout
+
+
+Kubernetes meta/v1.Duration
+
+
+ |
+
+(Optional)
+ Time after which the build times out. Defaults to 10 minutes.
+Specified build timeout should be less than 24h.
+Refer Go’s ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration
+ |
+
+
+
+podTemplate
+
+
+Template
+
+
+ |
+
+(Optional)
+ PodTemplate holds pod specific configuration
+ |
+
+
+
+workspaces
+
+
+[]WorkspaceBinding
+
+
+ |
+
+(Optional)
+ Workspaces is a list of WorkspaceBindings from volumes to workspaces.
+ |
+
+
+
+params
+
+
+[]Param
+
+
+ |
+
+(Optional)
+ From v1beta1
+ |
+
+
+
+resources
+
+
+TaskRunResources
+
+
+ |
+
+(Optional)
+ |
+
+
+
+inputs
+
+
+TaskRunInputs
+
+
+ |
+
+(Optional)
+ Deprecated
+ |
+
+
+
+outputs
+
+
+TaskRunOutputs
+
+
+ |
+
+(Optional)
+ |
+
+
+ |
+
+
+
+status
+
+
+TaskRunStatus
+
+
+ |
+
+(Optional)
+ |
+
+
+
+ConditionSpec
+
+
+(Appears on:Condition)
+
+
+
ConditionSpec defines the desired state of the Condition
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+check
+
+
+Step
+
+
+ |
+
+ Check declares container whose exit code determines where a condition is true or false
+ |
+
+
+
+description
+
+string
+
+ |
+
+(Optional)
+ Description is a user-facing description of the condition that may be
+used to populate a UI.
+ |
+
+
+
+params
+
+
+[]ParamSpec
+
+
+ |
+
+(Optional)
+ Params is an optional set of parameters which must be supplied by the user when a Condition
+is evaluated
+ |
+
+
+
+resources
+
+
+[]ResourceDeclaration
+
+
+ |
+
+(Optional)
+ Resources is a list of the ConditionResources required to run the condition.
+ |
+
+
+
+EmbeddedRunSpec
+
+
+(Appears on:RunSpec)
+
+
+
EmbeddedRunSpec allows custom task definitions to be embedded
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+metadata
+
+
+PipelineTaskMetadata
+
+
+ |
+
+(Optional)
+ |
+
+
+
+spec
+
+k8s.io/apimachinery/pkg/runtime.RawExtension
+
+ |
+
+(Optional)
+ Spec is a specification of a custom task
+
+
+
+
+
+-
+
+[]byte
+
+ |
+
+ Raw is the underlying serialization of this object.
+TODO: Determine how to detect ContentType and ContentEncoding of ‘Raw’ data.
+ |
+
+
+
+-
+
+k8s.io/apimachinery/pkg/runtime.Object
+
+ |
+
+ Object can hold a representation of this extension - useful for working with versioned
+structs.
+ |
+
+
+ |
+
+
+
+
+
+(Appears on:TaskSpec)
+
+
+
Inputs are the requirements that a task needs to run a Build.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+resources
+
+
+[]TaskResource
+
+
+ |
+
+(Optional)
+ Resources is a list of the input resources required to run the task.
+Resources are represented in TaskRuns as bindings to instances of
+PipelineResources.
+ |
+
+
+
+params
+
+
+[]ParamSpec
+
+
+ |
+
+(Optional)
+ Params is a list of input parameters required to run the task. Params
+must be supplied as inputs in TaskRuns unless they declare a default
+value.
+ |
+
+
+
+Outputs
+
+
+(Appears on:TaskSpec)
+
+
+
Outputs allow a task to declare what data the Build/Task will be producing,
+i.e. results such as logs and artifacts such as images.
+
+
+PipelineObject
+
+
+
PipelineObject is implemented by Pipeline and ClusterPipeline
+
+PipelineResourceInterface
+
+
+
PipelineResourceInterface interface to be implemented by different PipelineResource types
+
+PipelineRunSpec
+
+
+(Appears on:PipelineRun)
+
+
+
PipelineRunSpec defines the desired state of PipelineRun
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+pipelineRef
+
+
+PipelineRef
+
+
+ |
+
+(Optional)
+ |
+
+
+
+pipelineSpec
+
+
+PipelineSpec
+
+
+ |
+
+(Optional)
+ |
+
+
+
+resources
+
+
+[]PipelineResourceBinding
+
+
+ |
+
+ Resources is a list of bindings specifying which actual instances of
+PipelineResources to use for the resources the Pipeline has declared
+it needs.
+ |
+
+
+
+params
+
+
+[]Param
+
+
+ |
+
+ Params is a list of parameter names and values.
+ |
+
+
+
+serviceAccountName
+
+string
+
+ |
+
+(Optional)
+ |
+
+
+
+serviceAccountNames
+
+
+[]PipelineRunSpecServiceAccountName
+
+
+ |
+
+(Optional)
+ |
+
+
+
+status
+
+
+PipelineRunSpecStatus
+
+
+ |
+
+(Optional)
+ Used for cancelling a pipelinerun (and maybe more later on)
+ |
+
+
+
+timeout
+
+
+Kubernetes meta/v1.Duration
+
+
+ |
+
+(Optional)
+ Time after which the Pipeline times out. Defaults to never.
+Refer to Go’s ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration
+ |
+
+
+
+podTemplate
+
+
+Template
+
+
+ |
+
+ PodTemplate holds pod specific configuration
+ |
+
+
+
+workspaces
+
+
+[]WorkspaceBinding
+
+
+ |
+
+(Optional)
+ Workspaces holds a set of workspace bindings that must match names
+with those declared in the pipeline.
+ |
+
+
+
+taskRunSpecs
+
+
+[]PipelineTaskRunSpec
+
+
+ |
+
+(Optional)
+ TaskRunSpecs holds a set of task specific specs
+ |
+
+
+
+PipelineSpec
+
+
+(Appears on:Pipeline, PipelineRunSpec)
+
+
+
PipelineSpec defines the desired state of Pipeline.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+description
+
+string
+
+ |
+
+(Optional)
+ Description is a user-facing description of the pipeline that may be
+used to populate a UI.
+ |
+
+
+
+resources
+
+
+[]PipelineDeclaredResource
+
+
+ |
+
+ Resources declares the names and types of the resources given to the
+Pipeline’s tasks as inputs and outputs.
+ |
+
+
+
+tasks
+
+
+[]PipelineTask
+
+
+ |
+
+ Tasks declares the graph of Tasks that execute when this Pipeline is run.
+ |
+
+
+
+params
+
+
+[]ParamSpec
+
+
+ |
+
+ Params declares a list of input parameters that must be supplied when
+this Pipeline is run.
+ |
+
+
+
+workspaces
+
+
+[]PipelineWorkspaceDeclaration
+
+
+ |
+
+(Optional)
+ Workspaces declares a set of named workspaces that are expected to be
+provided by a PipelineRun.
+ |
+
+
+
+results
+
+
+[]PipelineResult
+
+
+ |
+
+(Optional)
+ Results are values that this pipeline can output once run
+ |
+
+
+
+PipelineStatus
+
+
+(Appears on:Pipeline)
+
+
+
PipelineStatus does not contain anything because Pipelines on their own
+do not have a status, they just hold data which is later used by a
+PipelineRun.
+Deprecated
+
+PipelineTask
+
+
+(Appears on:PipelineSpec)
+
+
+
PipelineTask defines a task in a Pipeline, passing inputs from both
+Params and from the output of previous tasks.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name is the name of this task within the context of a Pipeline. Name is
+used as a coordinate with the from and runAfter fields to establish
+the execution order of tasks relative to one another.
+ |
+
+
+
+taskRef
+
+
+TaskRef
+
+
+ |
+
+(Optional)
+ TaskRef is a reference to a task definition.
+ |
+
+
+
+taskSpec
+
+
+TaskSpec
+
+
+ |
+
+(Optional)
+ TaskSpec is specification of a task
+ |
+
+
+
+conditions
+
+
+[]PipelineTaskCondition
+
+
+ |
+
+(Optional)
+ Conditions is a list of conditions that need to be true for the task to run
+ |
+
+
+
+retries
+
+int
+
+ |
+
+(Optional)
+ Retries represents how many times this task should be retried in case of task failure: ConditionSucceeded set to False
+ |
+
+
+
+runAfter
+
+[]string
+
+ |
+
+(Optional)
+ RunAfter is the list of PipelineTask names that should be executed before
+this Task executes. (Used to force a specific ordering in graph execution.)
+ |
+
+
+
+resources
+
+
+PipelineTaskResources
+
+
+ |
+
+(Optional)
+ Resources declares the resources given to this task as inputs and
+outputs.
+ |
+
+
+
+params
+
+
+[]Param
+
+
+ |
+
+(Optional)
+ Parameters declares parameters passed to this task.
+ |
+
+
+
+workspaces
+
+
+[]WorkspacePipelineTaskBinding
+
+
+ |
+
+(Optional)
+ Workspaces maps workspaces from the pipeline spec to the workspaces
+declared in the Task.
+ |
+
+
+
+timeout
+
+
+Kubernetes meta/v1.Duration
+
+
+ |
+
+(Optional)
+ Time after which the TaskRun times out. Defaults to 1 hour.
+Specified TaskRun timeout should be less than 24h.
+Refer Go’s ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration
+ |
+
+
+
+PipelineTaskRunSpec
+
+
+(Appears on:PipelineRunSpec)
+
+
+
PipelineTaskRunSpec holds task specific specs
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+pipelineTaskName
+
+string
+
+ |
+
+ |
+
+
+
+taskServiceAccountName
+
+string
+
+ |
+
+ |
+
+
+
+taskPodTemplate
+
+
+Template
+
+
+ |
+
+ |
+
+
+
+RunSpec
+
+
+(Appears on:Run)
+
+
+
RunSpec defines the desired state of Run
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+ref
+
+
+TaskRef
+
+
+ |
+
+(Optional)
+ |
+
+
+
+spec
+
+
+EmbeddedRunSpec
+
+
+ |
+
+(Optional)
+ Spec is a specification of a custom task
+
+
+
+ |
+
+
+
+params
+
+
+[]Param
+
+
+ |
+
+(Optional)
+ |
+
+
+
+status
+
+
+RunSpecStatus
+
+
+ |
+
+(Optional)
+ Used for cancelling a run (and maybe more later on)
+ |
+
+
+
+retries
+
+int
+
+ |
+
+(Optional)
+ Used for propagating retries count to custom tasks
+ |
+
+
+
+serviceAccountName
+
+string
+
+ |
+
+(Optional)
+ |
+
+
+
+podTemplate
+
+
+Template
+
+
+ |
+
+(Optional)
+ PodTemplate holds pod specific configuration
+ |
+
+
+
+timeout
+
+
+Kubernetes meta/v1.Duration
+
+
+ |
+
+(Optional)
+ Time after which the custom-task times out.
+Refer Go’s ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration
+ |
+
+
+
+workspaces
+
+
+[]WorkspaceBinding
+
+
+ |
+
+(Optional)
+ Workspaces is a list of WorkspaceBindings from volumes to workspaces.
+ |
+
+
+
+RunSpecStatus
+(string
alias)
+
+(Appears on:RunSpec)
+
+
+
RunSpecStatus defines the taskrun spec status the user can provide
+
+TaskObject
+
+
+
TaskObject is implemented by Task and ClusterTask
+
+
+
+(Appears on:TaskRunSpec)
+
+
+
TaskRunInputs holds the input values that this task was invoked with.
+
+
+TaskRunOutputs
+
+
+(Appears on:TaskRunSpec)
+
+
+
TaskRunOutputs holds the output values that this task was invoked with.
+
+
+TaskRunSpec
+
+
+(Appears on:TaskRun, ConditionCheck)
+
+
+
TaskRunSpec defines the desired state of TaskRun
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+serviceAccountName
+
+string
+
+ |
+
+(Optional)
+ |
+
+
+
+taskRef
+
+
+TaskRef
+
+
+ |
+
+(Optional)
+ no more than one of the TaskRef and TaskSpec may be specified.
+ |
+
+
+
+taskSpec
+
+
+TaskSpec
+
+
+ |
+
+(Optional)
+ |
+
+
+
+status
+
+
+TaskRunSpecStatus
+
+
+ |
+
+(Optional)
+ Used for cancelling a taskrun (and maybe more later on)
+ |
+
+
+
+timeout
+
+
+Kubernetes meta/v1.Duration
+
+
+ |
+
+(Optional)
+ Time after which the build times out. Defaults to 10 minutes.
+Specified build timeout should be less than 24h.
+Refer Go’s ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration
+ |
+
+
+
+podTemplate
+
+
+Template
+
+
+ |
+
+(Optional)
+ PodTemplate holds pod specific configuration
+ |
+
+
+
+workspaces
+
+
+[]WorkspaceBinding
+
+
+ |
+
+(Optional)
+ Workspaces is a list of WorkspaceBindings from volumes to workspaces.
+ |
+
+
+
+params
+
+
+[]Param
+
+
+ |
+
+(Optional)
+ From v1beta1
+ |
+
+
+
+resources
+
+
+TaskRunResources
+
+
+ |
+
+(Optional)
+ |
+
+
+
+inputs
+
+
+TaskRunInputs
+
+
+ |
+
+(Optional)
+ Deprecated
+ |
+
+
+
+outputs
+
+
+TaskRunOutputs
+
+
+ |
+
+(Optional)
+ |
+
+
+
+TaskSpec
+
+
+(Appears on:ClusterTask, Task, PipelineTask, TaskRunSpec)
+
+
+
TaskSpec defines the desired state of Task.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+TaskSpec
+
+
+TaskSpec
+
+
+ |
+
+
+(Members of TaskSpec are embedded into this type.)
+
+ |
+
+
+
+inputs
+
+
+Inputs
+
+
+ |
+
+(Optional)
+ Inputs is an optional set of parameters and resources which must be
+supplied by the user when a Task is executed by a TaskRun.
+ |
+
+
+
+outputs
+
+
+Outputs
+
+
+ |
+
+(Optional)
+ Outputs is an optional set of resources and results produced when this
+Task is run.
+ |
+
+
+
+TestResult
+
+
+(Appears on:Outputs)
+
+
+
TestResult allows a task to specify the location where test logs
+can be found and what format they will be in.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name declares the name by which a result is referenced in the Task’s
+definition. Results may be referenced by name in the definition of a
+Task’s steps.
+ |
+
+
+
+format
+
+string
+
+ |
+
+ TODO: maybe this is an enum with types like “go test”, “junit”, etc.
+ |
+
+
+
+path
+
+string
+
+ |
+
+ |
+
+
+
+PipelineResourceSpec
+
+
+(Appears on:PipelineResource, PipelineResourceBinding)
+
+
+
PipelineResourceSpec defines an individual resources used in the pipeline.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+description
+
+string
+
+ |
+
+(Optional)
+ Description is a user-facing description of the resource that may be
+used to populate a UI.
+ |
+
+
+
+type
+
+string
+
+ |
+
+ |
+
+
+
+params
+
+
+[]ResourceParam
+
+
+ |
+
+ |
+
+
+
+secrets
+
+
+[]SecretParam
+
+
+ |
+
+(Optional)
+ Secrets to fetch to populate some of resource fields
+ |
+
+
+
+PipelineResourceStatus
+
+
+(Appears on:PipelineResource)
+
+
+
PipelineResourceStatus does not contain anything because PipelineResources on their own
+do not have a status
+Deprecated
+
+ResourceDeclaration
+
+
+(Appears on:ConditionSpec, TaskResource)
+
+
+
ResourceDeclaration defines an input or output PipelineResource declared as a requirement
+by another type such as a Task or Condition. The Name field will be used to refer to these
+PipelineResources within the type’s definition, and when provided as an Input, the Name will be the
+path to the volume mounted containing this PipelineResource as an input (e.g.
+an input Resource named workspace
will be mounted at /workspace
).
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name declares the name by which a resource is referenced in the
+definition. Resources may be referenced by name in the definition of a
+Task’s steps.
+ |
+
+
+
+type
+
+string
+
+ |
+
+ Type is the type of this resource;
+ |
+
+
+
+description
+
+string
+
+ |
+
+(Optional)
+ Description is a user-facing description of the declared resource that may be
+used to populate a UI.
+ |
+
+
+
+targetPath
+
+string
+
+ |
+
+(Optional)
+ TargetPath is the path in workspace directory where the resource
+will be copied.
+ |
+
+
+
+optional
+
+bool
+
+ |
+
+ Optional declares the resource as optional.
+By default optional is set to false which makes a resource required.
+optional: true - the resource is considered optional
+optional: false - the resource is considered required (equivalent of not specifying it)
+ |
+
+
+
+ResourceParam
+
+
+(Appears on:PipelineResourceSpec)
+
+
+
ResourceParam declares a string value to use for the parameter called Name, and is used in
+the specific context of PipelineResources.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+value
+
+string
+
+ |
+
+ |
+
+
+
+SecretParam
+
+
+(Appears on:PipelineResourceSpec)
+
+
+
SecretParam indicates which secret can be used to populate a field of the resource
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+fieldName
+
+string
+
+ |
+
+ |
+
+
+
+secretKey
+
+string
+
+ |
+
+ |
+
+
+
+secretName
+
+string
+
+ |
+
+ |
+
+
+
+RunResult
+
+
+(Appears on:RunStatusFields)
+
+
+
RunResult used to describe the results of a task
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name the given name
+ |
+
+
+
+value
+
+string
+
+ |
+
+ Value the given value of the result
+ |
+
+
+
+RunStatus
+
+
+(Appears on:Run, PipelineRunRunStatus, RunStatusFields)
+
+
+
RunStatus defines the observed state of Run
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+Status
+
+
+knative.dev/pkg/apis/duck/v1.Status
+
+
+ |
+
+
+(Members of Status are embedded into this type.)
+
+ |
+
+
+
+RunStatusFields
+
+
+RunStatusFields
+
+
+ |
+
+
+(Members of RunStatusFields are embedded into this type.)
+
+RunStatusFields inlines the status fields.
+ |
+
+
+
+RunStatusFields
+
+
+(Appears on:RunStatus)
+
+
+
RunStatusFields holds the fields of Run’s status. This is defined
+separately and inlined so that other types can readily consume these fields
+via duck typing.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+startTime
+
+
+Kubernetes meta/v1.Time
+
+
+ |
+
+(Optional)
+ StartTime is the time the build is actually started.
+ |
+
+
+
+completionTime
+
+
+Kubernetes meta/v1.Time
+
+
+ |
+
+(Optional)
+ CompletionTime is the time the build completed.
+ |
+
+
+
+results
+
+
+[]RunResult
+
+
+ |
+
+(Optional)
+ Results reports any output result values to be consumed by later
+tasks in a pipeline.
+ |
+
+
+
+retriesStatus
+
+
+[]RunStatus
+
+
+ |
+
+(Optional)
+ RetriesStatus contains the history of RunStatus, in case of a retry.
+ |
+
+
+
+extraFields
+
+k8s.io/apimachinery/pkg/runtime.RawExtension
+
+ |
+
+ ExtraFields holds arbitrary fields provided by the custom task
+controller.
+ |
+
+
+
+
+tekton.dev/v1beta1
+
+
Package v1beta1 contains API Schema definitions for the pipeline v1beta1 API group
+
+Resource Types:
+
+ClusterTask
+
+
+
ClusterTask is a Task with a cluster scope. ClusterTasks are used to
+represent Tasks that should be publicly addressable from any namespace in the
+cluster.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+apiVersion
+string |
+
+
+tekton.dev/v1beta1
+
+ |
+
+
+
+kind
+string
+ |
+ClusterTask |
+
+
+
+metadata
+
+
+Kubernetes meta/v1.ObjectMeta
+
+
+ |
+
+(Optional)
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+
+
+
+spec
+
+
+TaskSpec
+
+
+ |
+
+(Optional)
+ Spec holds the desired state of the Task from the client
+
+
+
+
+
+resources
+
+
+TaskResources
+
+
+ |
+
+(Optional)
+ Resources is a list input and output resource to run the task
+Resources are represented in TaskRuns as bindings to instances of
+PipelineResources.
+ |
+
+
+
+params
+
+
+[]ParamSpec
+
+
+ |
+
+(Optional)
+ Params is a list of input parameters required to run the task. Params
+must be supplied as inputs in TaskRuns unless they declare a default
+value.
+ |
+
+
+
+description
+
+string
+
+ |
+
+(Optional)
+ Description is a user-facing description of the task that may be
+used to populate a UI.
+ |
+
+
+
+steps
+
+
+[]Step
+
+
+ |
+
+ Steps are the steps of the build; each step is run sequentially with the
+source mounted into /workspace.
+ |
+
+
+
+volumes
+
+
+[]Kubernetes core/v1.Volume
+
+
+ |
+
+ Volumes is a collection of volumes that are available to mount into the
+steps of the build.
+ |
+
+
+
+stepTemplate
+
+
+Kubernetes core/v1.Container
+
+
+ |
+
+ StepTemplate can be used as the basis for all step containers within the
+Task, so that the steps inherit settings on the base container.
+ |
+
+
+
+sidecars
+
+
+[]Sidecar
+
+
+ |
+
+ Sidecars are run alongside the Task’s step containers. They begin before
+the steps start and end after the steps complete.
+ |
+
+
+
+workspaces
+
+
+[]WorkspaceDeclaration
+
+
+ |
+
+ Workspaces are the volumes that this Task requires.
+ |
+
+
+
+results
+
+
+[]TaskResult
+
+
+ |
+
+ Results are values that this Task can output
+ |
+
+
+ |
+
+
+
+Pipeline
+
+
+
Pipeline describes a list of Tasks to execute. It expresses how outputs
+of tasks feed into inputs of subsequent tasks.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+apiVersion
+string |
+
+
+tekton.dev/v1beta1
+
+ |
+
+
+
+kind
+string
+ |
+Pipeline |
+
+
+
+metadata
+
+
+Kubernetes meta/v1.ObjectMeta
+
+
+ |
+
+(Optional)
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+
+
+
+spec
+
+
+PipelineSpec
+
+
+ |
+
+(Optional)
+ Spec holds the desired state of the Pipeline from the client
+
+
+
+
+
+description
+
+string
+
+ |
+
+(Optional)
+ Description is a user-facing description of the pipeline that may be
+used to populate a UI.
+ |
+
+
+
+resources
+
+
+[]PipelineDeclaredResource
+
+
+ |
+
+ Resources declares the names and types of the resources given to the
+Pipeline’s tasks as inputs and outputs.
+ |
+
+
+
+tasks
+
+
+[]PipelineTask
+
+
+ |
+
+ Tasks declares the graph of Tasks that execute when this Pipeline is run.
+ |
+
+
+
+params
+
+
+[]ParamSpec
+
+
+ |
+
+ Params declares a list of input parameters that must be supplied when
+this Pipeline is run.
+ |
+
+
+
+workspaces
+
+
+[]PipelineWorkspaceDeclaration
+
+
+ |
+
+(Optional)
+ Workspaces declares a set of named workspaces that are expected to be
+provided by a PipelineRun.
+ |
+
+
+
+results
+
+
+[]PipelineResult
+
+
+ |
+
+(Optional)
+ Results are values that this pipeline can output once run
+ |
+
+
+
+finally
+
+
+[]PipelineTask
+
+
+ |
+
+ Finally declares the list of Tasks that execute just before leaving the Pipeline
+i.e. either after all Tasks are finished executing successfully
+or after a failure which would result in ending the Pipeline
+ |
+
+
+ |
+
+
+
+PipelineRun
+
+
+
PipelineRun represents a single execution of a Pipeline. PipelineRuns are how
+the graph of Tasks declared in a Pipeline are executed; they specify inputs
+to Pipelines such as parameter values and capture operational aspects of the
+Tasks execution such as service account and tolerations. Creating a
+PipelineRun creates TaskRuns for Tasks in the referenced Pipeline.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+apiVersion
+string |
+
+
+tekton.dev/v1beta1
+
+ |
+
+
+
+kind
+string
+ |
+PipelineRun |
+
+
+
+metadata
+
+
+Kubernetes meta/v1.ObjectMeta
+
+
+ |
+
+(Optional)
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+
+
+
+spec
+
+
+PipelineRunSpec
+
+
+ |
+
+(Optional)
+
+
+
+
+
+pipelineRef
+
+
+PipelineRef
+
+
+ |
+
+(Optional)
+ |
+
+
+
+pipelineSpec
+
+
+PipelineSpec
+
+
+ |
+
+(Optional)
+ |
+
+
+
+resources
+
+
+[]PipelineResourceBinding
+
+
+ |
+
+ Resources is a list of bindings specifying which actual instances of
+PipelineResources to use for the resources the Pipeline has declared
+it needs.
+ |
+
+
+
+params
+
+
+[]Param
+
+
+ |
+
+ Params is a list of parameter names and values.
+ |
+
+
+
+serviceAccountName
+
+string
+
+ |
+
+(Optional)
+ |
+
+
+
+serviceAccountNames
+
+
+[]PipelineRunSpecServiceAccountName
+
+
+ |
+
+(Optional)
+ Deprecated: use taskRunSpecs.ServiceAccountName instead
+ |
+
+
+
+status
+
+
+PipelineRunSpecStatus
+
+
+ |
+
+(Optional)
+ Used for cancelling a pipelinerun (and maybe more later on)
+ |
+
+
+
+timeouts
+
+
+TimeoutFields
+
+
+ |
+
+(Optional)
+ This is an alpha field. You must set the “enable-api-fields” feature flag to “alpha”
+for this field to be supported.
+Time after which the Pipeline times out.
+Currently three keys are accepted in the map
+pipeline, tasks and finally
+with Timeouts.pipeline >= Timeouts.tasks + Timeouts.finally
+ |
+
+
+
+timeout
+
+
+Kubernetes meta/v1.Duration
+
+
+ |
+
+(Optional)
+ Time after which the Pipeline times out. Defaults to never.
+Refer to Go’s ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration
+ |
+
+
+
+podTemplate
+
+
+Template
+
+
+ |
+
+ PodTemplate holds pod specific configuration
+ |
+
+
+
+workspaces
+
+
+[]WorkspaceBinding
+
+
+ |
+
+(Optional)
+ Workspaces holds a set of workspace bindings that must match names
+with those declared in the pipeline.
+ |
+
+
+
+taskRunSpecs
+
+
+[]PipelineTaskRunSpec
+
+
+ |
+
+(Optional)
+ TaskRunSpecs holds a set of runtime specs
+ |
+
+
+ |
+
+
+
+status
+
+
+PipelineRunStatus
+
+
+ |
+
+(Optional)
+ |
+
+
+
+Task
+
+
+
Task represents a collection of sequential steps that are run as part of a
+Pipeline using a set of inputs and producing a set of outputs. Tasks execute
+when TaskRuns are created that provide the input parameters and resources and
+output resources the Task requires.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+apiVersion
+string |
+
+
+tekton.dev/v1beta1
+
+ |
+
+
+
+kind
+string
+ |
+Task |
+
+
+
+metadata
+
+
+Kubernetes meta/v1.ObjectMeta
+
+
+ |
+
+(Optional)
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+
+
+
+spec
+
+
+TaskSpec
+
+
+ |
+
+(Optional)
+ Spec holds the desired state of the Task from the client
+
+
+
+
+
+resources
+
+
+TaskResources
+
+
+ |
+
+(Optional)
+ Resources is a list input and output resource to run the task
+Resources are represented in TaskRuns as bindings to instances of
+PipelineResources.
+ |
+
+
+
+params
+
+
+[]ParamSpec
+
+
+ |
+
+(Optional)
+ Params is a list of input parameters required to run the task. Params
+must be supplied as inputs in TaskRuns unless they declare a default
+value.
+ |
+
+
+
+description
+
+string
+
+ |
+
+(Optional)
+ Description is a user-facing description of the task that may be
+used to populate a UI.
+ |
+
+
+
+steps
+
+
+[]Step
+
+
+ |
+
+ Steps are the steps of the build; each step is run sequentially with the
+source mounted into /workspace.
+ |
+
+
+
+volumes
+
+
+[]Kubernetes core/v1.Volume
+
+
+ |
+
+ Volumes is a collection of volumes that are available to mount into the
+steps of the build.
+ |
+
+
+
+stepTemplate
+
+
+Kubernetes core/v1.Container
+
+
+ |
+
+ StepTemplate can be used as the basis for all step containers within the
+Task, so that the steps inherit settings on the base container.
+ |
+
+
+
+sidecars
+
+
+[]Sidecar
+
+
+ |
+
+ Sidecars are run alongside the Task’s step containers. They begin before
+the steps start and end after the steps complete.
+ |
+
+
+
+workspaces
+
+
+[]WorkspaceDeclaration
+
+
+ |
+
+ Workspaces are the volumes that this Task requires.
+ |
+
+
+
+results
+
+
+[]TaskResult
+
+
+ |
+
+ Results are values that this Task can output
+ |
+
+
+ |
+
+
+
+TaskRun
+
+
+
TaskRun represents a single execution of a Task. TaskRuns are how the steps
+specified in a Task are executed; they specify the parameters and resources
+used to run the steps in a Task.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+apiVersion
+string |
+
+
+tekton.dev/v1beta1
+
+ |
+
+
+
+kind
+string
+ |
+TaskRun |
+
+
+
+metadata
+
+
+Kubernetes meta/v1.ObjectMeta
+
+
+ |
+
+(Optional)
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+
+
+
+spec
+
+
+TaskRunSpec
+
+
+ |
+
+(Optional)
+
+
+
+
+
+debug
+
+
+TaskRunDebug
+
+
+ |
+
+(Optional)
+ |
+
+
+
+params
+
+
+[]Param
+
+
+ |
+
+(Optional)
+ |
+
+
+
+resources
+
+
+TaskRunResources
+
+
+ |
+
+(Optional)
+ |
+
+
+
+serviceAccountName
+
+string
+
+ |
+
+(Optional)
+ |
+
+
+
+taskRef
+
+
+TaskRef
+
+
+ |
+
+(Optional)
+ no more than one of the TaskRef and TaskSpec may be specified.
+ |
+
+
+
+taskSpec
+
+
+TaskSpec
+
+
+ |
+
+(Optional)
+ |
+
+
+
+status
+
+
+TaskRunSpecStatus
+
+
+ |
+
+(Optional)
+ Used for cancelling a taskrun (and maybe more later on)
+ |
+
+
+
+timeout
+
+
+Kubernetes meta/v1.Duration
+
+
+ |
+
+(Optional)
+ Time after which the build times out. Defaults to 1 hour.
+Specified build timeout should be less than 24h.
+Refer Go’s ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration
+ |
+
+
+
+podTemplate
+
+
+Template
+
+
+ |
+
+ PodTemplate holds pod specific configuration
+ |
+
+
+
+workspaces
+
+
+[]WorkspaceBinding
+
+
+ |
+
+(Optional)
+ Workspaces is a list of WorkspaceBindings from volumes to workspaces.
+ |
+
+
+ |
+
+
+
+status
+
+
+TaskRunStatus
+
+
+ |
+
+(Optional)
+ |
+
+
+
+ArrayOrString
+
+
+(Appears on:Param, ParamSpec)
+
+
+
ArrayOrString is a type that can hold a single string or string array.
+Used in JSON unmarshalling so that a single JSON field can accept
+either an individual string or an array of strings.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+type
+
+
+ParamType
+
+
+ |
+
+ |
+
+
+
+stringVal
+
+string
+
+ |
+
+ Represents the stored type of ArrayOrString.
+ |
+
+
+
+arrayVal
+
+[]string
+
+ |
+
+ |
+
+
+
+CloudEventCondition
+(string
alias)
+
+(Appears on:CloudEventDeliveryState)
+
+
+
CloudEventCondition is a string that represents the condition of the event.
+
+
+
+
+Value |
+Description |
+
+
+"Failed" |
+CloudEventConditionFailed means that there was one or more attempts to
+send the event, and none was successful so far.
+ |
+
"Sent" |
+CloudEventConditionSent means that the event was sent successfully
+ |
+
"Unknown" |
+CloudEventConditionUnknown means that the condition for the event to be
+triggered was not met yet, or we don’t know the state yet.
+ |
+
+
+CloudEventDelivery
+
+
+(Appears on:TaskRunStatusFields)
+
+
+
CloudEventDelivery is the target of a cloud event along with the state of
+delivery.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+target
+
+string
+
+ |
+
+ Target points to an addressable
+ |
+
+
+
+status
+
+
+CloudEventDeliveryState
+
+
+ |
+
+ |
+
+
+
+CloudEventDeliveryState
+
+
+(Appears on:CloudEventDelivery)
+
+
+
CloudEventDeliveryState reports the state of a cloud event to be sent.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+condition
+
+
+CloudEventCondition
+
+
+ |
+
+ Current status
+ |
+
+
+
+sentAt
+
+
+Kubernetes meta/v1.Time
+
+
+ |
+
+(Optional)
+ SentAt is the time at which the last attempt to send the event was made
+ |
+
+
+
+message
+
+string
+
+ |
+
+ Error is the text of error (if any)
+ |
+
+
+
+retryCount
+
+int32
+
+ |
+
+ RetryCount is the number of attempts of sending the cloud event
+ |
+
+
+
+ConditionCheck
+
+
+
ConditionCheck represents a single evaluation of a Condition step.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+metadata
+
+
+Kubernetes meta/v1.ObjectMeta
+
+
+ |
+
+(Optional)
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+
+
+
+spec
+
+
+TaskRunSpec
+
+
+ |
+
+(Optional)
+
+
+
+
+
+debug
+
+
+TaskRunDebug
+
+
+ |
+
+(Optional)
+ |
+
+
+
+params
+
+
+[]Param
+
+
+ |
+
+(Optional)
+ |
+
+
+
+resources
+
+
+TaskRunResources
+
+
+ |
+
+(Optional)
+ |
+
+
+
+serviceAccountName
+
+string
+
+ |
+
+(Optional)
+ |
+
+
+
+taskRef
+
+
+TaskRef
+
+
+ |
+
+(Optional)
+ no more than one of the TaskRef and TaskSpec may be specified.
+ |
+
+
+
+taskSpec
+
+
+TaskSpec
+
+
+ |
+
+(Optional)
+ |
+
+
+
+status
+
+
+TaskRunSpecStatus
+
+
+ |
+
+(Optional)
+ Used for cancelling a taskrun (and maybe more later on)
+ |
+
+
+
+timeout
+
+
+Kubernetes meta/v1.Duration
+
+
+ |
+
+(Optional)
+ Time after which the build times out. Defaults to 1 hour.
+Specified build timeout should be less than 24h.
+Refer Go’s ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration
+ |
+
+
+
+podTemplate
+
+
+Template
+
+
+ |
+
+ PodTemplate holds pod specific configuration
+ |
+
+
+
+workspaces
+
+
+[]WorkspaceBinding
+
+
+ |
+
+(Optional)
+ Workspaces is a list of WorkspaceBindings from volumes to workspaces.
+ |
+
+
+ |
+
+
+
+status
+
+
+TaskRunStatus
+
+
+ |
+
+(Optional)
+ |
+
+
+
+ConditionCheckStatus
+
+
+(Appears on:PipelineRunConditionCheckStatus)
+
+
+
ConditionCheckStatus defines the observed state of ConditionCheck
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+Status
+
+
+knative.dev/pkg/apis/duck/v1beta1.Status
+
+
+ |
+
+
+(Members of Status are embedded into this type.)
+
+ |
+
+
+
+ConditionCheckStatusFields
+
+
+ConditionCheckStatusFields
+
+
+ |
+
+
+(Members of ConditionCheckStatusFields are embedded into this type.)
+
+ConditionCheckStatusFields inlines the status fields.
+ |
+
+
+
+ConditionCheckStatusFields
+
+
+(Appears on:ConditionCheckStatus)
+
+
+
ConditionCheckStatusFields holds the fields of ConfigurationCheck’s status.
+This is defined separately and inlined so that other types can readily
+consume these fields via duck typing.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+podName
+
+string
+
+ |
+
+ PodName is the name of the pod responsible for executing this condition check.
+ |
+
+
+
+startTime
+
+
+Kubernetes meta/v1.Time
+
+
+ |
+
+(Optional)
+ StartTime is the time the check is actually started.
+ |
+
+
+
+completionTime
+
+
+Kubernetes meta/v1.Time
+
+
+ |
+
+(Optional)
+ CompletionTime is the time the check pod completed.
+ |
+
+
+
+check
+
+
+Kubernetes core/v1.ContainerState
+
+
+ |
+
+(Optional)
+ Check describes the state of the check container.
+ |
+
+
+
+EmbeddedTask
+
+
+(Appears on:PipelineTask)
+
+
+
EmbeddedTask is used to define a Task inline within a Pipeline’s PipelineTasks.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+spec
+
+k8s.io/apimachinery/pkg/runtime.RawExtension
+
+ |
+
+(Optional)
+ Spec is a specification of a custom task
+
+
+
+
+
+-
+
+[]byte
+
+ |
+
+ Raw is the underlying serialization of this object.
+TODO: Determine how to detect ContentType and ContentEncoding of ‘Raw’ data.
+ |
+
+
+
+-
+
+k8s.io/apimachinery/pkg/runtime.Object
+
+ |
+
+ Object can hold a representation of this extension - useful for working with versioned
+structs.
+ |
+
+
+ |
+
+
+
+metadata
+
+
+PipelineTaskMetadata
+
+
+ |
+
+(Optional)
+ |
+
+
+
+TaskSpec
+
+
+TaskSpec
+
+
+ |
+
+
+(Members of TaskSpec are embedded into this type.)
+
+(Optional)
+TaskSpec is a specification of a task
+ |
+
+
+
+InternalTaskModifier
+
+
+
InternalTaskModifier implements TaskModifier for resources that are built-in to Tekton Pipelines.
+
+
+Param
+
+
+(Appears on:PipelineRunSpec, PipelineTask, RunSpec, TaskRunInputs, TaskRunSpec, PipelineRunSpec, PipelineTask, PipelineTaskCondition, TaskRunInputs, TaskRunSpec)
+
+
+
Param declares an ArrayOrString to use for the parameter called name.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+value
+
+
+ArrayOrString
+
+
+ |
+
+ |
+
+
+
+ParamSpec
+
+
+(Appears on:ConditionSpec, Inputs, PipelineSpec, PipelineSpec, TaskSpec)
+
+
+
ParamSpec defines arbitrary parameters needed beyond typed inputs (such as
+resources). Parameter values are provided by users as inputs on a TaskRun
+or PipelineRun.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name declares the name by which a parameter is referenced.
+ |
+
+
+
+type
+
+
+ParamType
+
+
+ |
+
+(Optional)
+ Type is the user-specified type of the parameter. The possible types
+are currently “string” and “array”, and “string” is the default.
+ |
+
+
+
+description
+
+string
+
+ |
+
+(Optional)
+ Description is a user-facing description of the parameter that may be
+used to populate a UI.
+ |
+
+
+
+default
+
+
+ArrayOrString
+
+
+ |
+
+(Optional)
+ Default is the value a parameter takes if no input value is supplied. If
+default is set, a Task may be executed without a supplied value for the
+parameter.
+ |
+
+
+
+ParamType
+(string
alias)
+
+(Appears on:ArrayOrString, ParamSpec)
+
+
+
ParamType indicates the type of an input parameter;
+Used to distinguish between a single string and an array of strings.
+
+
+
+
+Value |
+Description |
+
+
+"array" |
+ |
+
"string" |
+ |
+
+
+PipelineDeclaredResource
+
+
+(Appears on:PipelineSpec, PipelineSpec)
+
+
+
PipelineDeclaredResource is used by a Pipeline to declare the types of the
+PipelineResources that it will required to run and names which can be used to
+refer to these PipelineResources in PipelineTaskResourceBindings.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name is the name that will be used by the Pipeline to refer to this resource.
+It does not directly correspond to the name of any PipelineResources Task
+inputs or outputs, and it does not correspond to the actual names of the
+PipelineResources that will be bound in the PipelineRun.
+ |
+
+
+
+type
+
+string
+
+ |
+
+ Type is the type of the PipelineResource.
+ |
+
+
+
+optional
+
+bool
+
+ |
+
+ Optional declares the resource as optional.
+optional: true - the resource is considered optional
+optional: false - the resource is considered required (default/equivalent of not specifying it)
+ |
+
+
+
+PipelineObject
+
+
+
PipelineObject is implemented by Pipeline and ClusterPipeline
+
+PipelineRef
+
+
+(Appears on:PipelineRunSpec, PipelineRunSpec)
+
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name of the referent; More info: http://kubernetes.io/docs/user-guide/identifiers#names
+ |
+
+
+
+apiVersion
+
+string
+
+ |
+
+(Optional)
+ API version of the referent
+ |
+
+
+
+bundle
+
+string
+
+ |
+
+(Optional)
+ Bundle url reference to a Tekton Bundle.
+ |
+
+
+
+PipelineResourceBinding
+
+
+(Appears on:PipelineRunSpec, PipelineRunSpec, TaskResourceBinding)
+
+
+
PipelineResourceBinding connects a reference to an instance of a PipelineResource
+with a PipelineResource dependency that the Pipeline has declared
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name is the name of the PipelineResource in the Pipeline’s declaration
+ |
+
+
+
+resourceRef
+
+
+PipelineResourceRef
+
+
+ |
+
+(Optional)
+ ResourceRef is a reference to the instance of the actual PipelineResource
+that should be used
+ |
+
+
+
+resourceSpec
+
+
+PipelineResourceSpec
+
+
+ |
+
+(Optional)
+ ResourceSpec is specification of a resource that should be created and
+consumed by the task
+ |
+
+
+
+PipelineResourceInterface
+
+
+
PipelineResourceInterface interface to be implemented by different PipelineResource types
+
+PipelineResourceRef
+
+
+(Appears on:PipelineResourceBinding, PipelineResourceResult)
+
+
+
PipelineResourceRef can be used to refer to a specific instance of a Resource
+
+
+PipelineResourceResult
+
+
+(Appears on:TaskRunStatusFields)
+
+
+
PipelineResourceResult used to export the image name and digest as json
+
+
+PipelineResult
+
+
+(Appears on:PipelineSpec, PipelineSpec)
+
+
+
PipelineResult used to describe the results of a pipeline
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name the given name
+ |
+
+
+
+description
+
+string
+
+ |
+
+(Optional)
+ Description is a human-readable description of the result
+ |
+
+
+
+value
+
+string
+
+ |
+
+ Value the expression used to retrieve the value
+ |
+
+
+
+PipelineRunConditionCheckStatus
+
+
+(Appears on:PipelineRunTaskRunStatus)
+
+
+
PipelineRunConditionCheckStatus returns the condition check status
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+conditionName
+
+string
+
+ |
+
+ ConditionName is the name of the Condition
+ |
+
+
+
+status
+
+
+ConditionCheckStatus
+
+
+ |
+
+(Optional)
+ Status is the ConditionCheckStatus for the corresponding ConditionCheck
+ |
+
+
+
+PipelineRunReason
+(string
alias)
+
+
PipelineRunReason represents a reason for the pipeline run “Succeeded” condition
+
+
+
+
+Value |
+Description |
+
+
+"Cancelled" |
+PipelineRunReasonCancelled is the reason set when the PipelineRun cancelled by the user
+This reason may be found with a corev1.ConditionFalse status, if the cancellation was processed successfully
+This reason may be found with a corev1.ConditionUnknown status, if the cancellation is being processed or failed
+ |
+
"CancelledRunningFinally" |
+PipelineRunReasonCancelledRunningFinally indicates that pipeline has been gracefully cancelled
+and no new Tasks will be scheduled by the controller, but final tasks are now running
+ |
+
"Completed" |
+PipelineRunReasonCompleted is the reason set when the PipelineRun completed successfully with one or more skipped Tasks
+ |
+
"Failed" |
+PipelineRunReasonFailed is the reason set when the PipelineRun completed with a failure
+ |
+
"PipelineRunPending" |
+PipelineRunReasonPending is the reason set when the PipelineRun is in the pending state
+ |
+
"Running" |
+PipelineRunReasonRunning is the reason set when the PipelineRun is running
+ |
+
"Started" |
+PipelineRunReasonStarted is the reason set when the PipelineRun has just started
+ |
+
"StoppedRunningFinally" |
+PipelineRunReasonStoppedRunningFinally indicates that pipeline has been gracefully stopped
+and no new Tasks will be scheduled by the controller, but final tasks are now running
+ |
+
"PipelineRunStopping" |
+PipelineRunReasonStopping indicates that no new Tasks will be scheduled by the controller, and the
+pipeline will stop once all running tasks complete their work
+ |
+
"Succeeded" |
+PipelineRunReasonSuccessful is the reason set when the PipelineRun completed successfully
+ |
+
"PipelineRunTimeout" |
+PipelineRunReasonTimedOut is the reason set when the PipelineRun has timed out
+ |
+
+
+PipelineRunResult
+
+
+(Appears on:PipelineRunStatusFields)
+
+
+
PipelineRunResult used to describe the results of a pipeline
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name is the result’s name as declared by the Pipeline
+ |
+
+
+
+value
+
+string
+
+ |
+
+ Value is the result returned from the execution of this PipelineRun
+ |
+
+
+
+PipelineRunRunStatus
+
+
+(Appears on:PipelineRunStatusFields)
+
+
+
PipelineRunRunStatus contains the name of the PipelineTask for this Run and the Run’s Status
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+pipelineTaskName
+
+string
+
+ |
+
+ PipelineTaskName is the name of the PipelineTask.
+ |
+
+
+
+status
+
+
+RunStatus
+
+
+ |
+
+(Optional)
+ Status is the RunStatus for the corresponding Run
+ |
+
+
+
+whenExpressions
+
+
+[]WhenExpression
+
+
+ |
+
+(Optional)
+ WhenExpressions is the list of checks guarding the execution of the PipelineTask
+ |
+
+
+
+PipelineRunSpec
+
+
+(Appears on:PipelineRun)
+
+
+
PipelineRunSpec defines the desired state of PipelineRun
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+pipelineRef
+
+
+PipelineRef
+
+
+ |
+
+(Optional)
+ |
+
+
+
+pipelineSpec
+
+
+PipelineSpec
+
+
+ |
+
+(Optional)
+ |
+
+
+
+resources
+
+
+[]PipelineResourceBinding
+
+
+ |
+
+ Resources is a list of bindings specifying which actual instances of
+PipelineResources to use for the resources the Pipeline has declared
+it needs.
+ |
+
+
+
+params
+
+
+[]Param
+
+
+ |
+
+ Params is a list of parameter names and values.
+ |
+
+
+
+serviceAccountName
+
+string
+
+ |
+
+(Optional)
+ |
+
+
+
+serviceAccountNames
+
+
+[]PipelineRunSpecServiceAccountName
+
+
+ |
+
+(Optional)
+ Deprecated: use taskRunSpecs.ServiceAccountName instead
+ |
+
+
+
+status
+
+
+PipelineRunSpecStatus
+
+
+ |
+
+(Optional)
+ Used for cancelling a pipelinerun (and maybe more later on)
+ |
+
+
+
+timeouts
+
+
+TimeoutFields
+
+
+ |
+
+(Optional)
+ This is an alpha field. You must set the “enable-api-fields” feature flag to “alpha”
+for this field to be supported.
+Time after which the Pipeline times out.
+Currently three keys are accepted in the map
+pipeline, tasks and finally
+with Timeouts.pipeline >= Timeouts.tasks + Timeouts.finally
+ |
+
+
+
+timeout
+
+
+Kubernetes meta/v1.Duration
+
+
+ |
+
+(Optional)
+ Time after which the Pipeline times out. Defaults to never.
+Refer to Go’s ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration
+ |
+
+
+
+podTemplate
+
+
+Template
+
+
+ |
+
+ PodTemplate holds pod specific configuration
+ |
+
+
+
+workspaces
+
+
+[]WorkspaceBinding
+
+
+ |
+
+(Optional)
+ Workspaces holds a set of workspace bindings that must match names
+with those declared in the pipeline.
+ |
+
+
+
+taskRunSpecs
+
+
+[]PipelineTaskRunSpec
+
+
+ |
+
+(Optional)
+ TaskRunSpecs holds a set of runtime specs
+ |
+
+
+
+PipelineRunSpecServiceAccountName
+
+
+(Appears on:PipelineRunSpec, PipelineRunSpec)
+
+
+
PipelineRunSpecServiceAccountName can be used to configure specific
+ServiceAccountName for a concrete Task
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+taskName
+
+string
+
+ |
+
+ |
+
+
+
+serviceAccountName
+
+string
+
+ |
+
+ |
+
+
+
+PipelineRunSpecStatus
+(string
alias)
+
+(Appears on:PipelineRunSpec, PipelineRunSpec)
+
+
+
PipelineRunSpecStatus defines the pipelinerun spec status the user can provide
+
+PipelineRunStatus
+
+
+(Appears on:PipelineRun, PipelineRun)
+
+
+
PipelineRunStatus defines the observed state of PipelineRun
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+Status
+
+
+knative.dev/pkg/apis/duck/v1beta1.Status
+
+
+ |
+
+
+(Members of Status are embedded into this type.)
+
+ |
+
+
+
+PipelineRunStatusFields
+
+
+PipelineRunStatusFields
+
+
+ |
+
+
+(Members of PipelineRunStatusFields are embedded into this type.)
+
+PipelineRunStatusFields inlines the status fields.
+ |
+
+
+
+PipelineRunStatusFields
+
+
+(Appears on:PipelineRunStatus)
+
+
+
PipelineRunStatusFields holds the fields of PipelineRunStatus’ status.
+This is defined separately and inlined so that other types can readily
+consume these fields via duck typing.
+
+
+PipelineRunTaskRunStatus
+
+
+(Appears on:PipelineRunStatusFields)
+
+
+
PipelineRunTaskRunStatus contains the name of the PipelineTask for this TaskRun and the TaskRun’s Status
+
+
+PipelineSpec
+
+
+(Appears on:Pipeline, PipelineRunSpec, PipelineRunStatusFields)
+
+
+
PipelineSpec defines the desired state of Pipeline.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+description
+
+string
+
+ |
+
+(Optional)
+ Description is a user-facing description of the pipeline that may be
+used to populate a UI.
+ |
+
+
+
+resources
+
+
+[]PipelineDeclaredResource
+
+
+ |
+
+ Resources declares the names and types of the resources given to the
+Pipeline’s tasks as inputs and outputs.
+ |
+
+
+
+tasks
+
+
+[]PipelineTask
+
+
+ |
+
+ Tasks declares the graph of Tasks that execute when this Pipeline is run.
+ |
+
+
+
+params
+
+
+[]ParamSpec
+
+
+ |
+
+ Params declares a list of input parameters that must be supplied when
+this Pipeline is run.
+ |
+
+
+
+workspaces
+
+
+[]PipelineWorkspaceDeclaration
+
+
+ |
+
+(Optional)
+ Workspaces declares a set of named workspaces that are expected to be
+provided by a PipelineRun.
+ |
+
+
+
+results
+
+
+[]PipelineResult
+
+
+ |
+
+(Optional)
+ Results are values that this pipeline can output once run
+ |
+
+
+
+finally
+
+
+[]PipelineTask
+
+
+ |
+
+ Finally declares the list of Tasks that execute just before leaving the Pipeline
+i.e. either after all Tasks are finished executing successfully
+or after a failure which would result in ending the Pipeline
+ |
+
+
+
+PipelineTask
+
+
+(Appears on:PipelineSpec)
+
+
+
PipelineTask defines a task in a Pipeline, passing inputs from both
+Params and from the output of previous tasks.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name is the name of this task within the context of a Pipeline. Name is
+used as a coordinate with the from and runAfter fields to establish
+the execution order of tasks relative to one another.
+ |
+
+
+
+taskRef
+
+
+TaskRef
+
+
+ |
+
+(Optional)
+ TaskRef is a reference to a task definition.
+ |
+
+
+
+taskSpec
+
+
+EmbeddedTask
+
+
+ |
+
+(Optional)
+ TaskSpec is a specification of a task
+ |
+
+
+
+conditions
+
+
+[]PipelineTaskCondition
+
+
+ |
+
+(Optional)
+ Conditions is a list of conditions that need to be true for the task to run
+Conditions are deprecated, use WhenExpressions instead
+ |
+
+
+
+when
+
+
+WhenExpressions
+
+
+ |
+
+(Optional)
+ WhenExpressions is a list of when expressions that need to be true for the task to run
+ |
+
+
+
+retries
+
+int
+
+ |
+
+(Optional)
+ Retries represents how many times this task should be retried in case of task failure: ConditionSucceeded set to False
+ |
+
+
+
+runAfter
+
+[]string
+
+ |
+
+(Optional)
+ RunAfter is the list of PipelineTask names that should be executed before
+this Task executes. (Used to force a specific ordering in graph execution.)
+ |
+
+
+
+resources
+
+
+PipelineTaskResources
+
+
+ |
+
+(Optional)
+ Resources declares the resources given to this task as inputs and
+outputs.
+ |
+
+
+
+params
+
+
+[]Param
+
+
+ |
+
+(Optional)
+ Parameters declares parameters passed to this task.
+ |
+
+
+
+workspaces
+
+
+[]WorkspacePipelineTaskBinding
+
+
+ |
+
+(Optional)
+ Workspaces maps workspaces from the pipeline spec to the workspaces
+declared in the Task.
+ |
+
+
+
+timeout
+
+
+Kubernetes meta/v1.Duration
+
+
+ |
+
+(Optional)
+ Time after which the TaskRun times out. Defaults to 1 hour.
+Specified TaskRun timeout should be less than 24h.
+Refer Go’s ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration
+ |
+
+
+
+PipelineTaskCondition
+
+
+(Appears on:PipelineTask, PipelineTask)
+
+
+
PipelineTaskCondition allows a PipelineTask to declare a Condition to be evaluated before
+the Task is run.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+conditionRef
+
+string
+
+ |
+
+ ConditionRef is the name of the Condition to use for the conditionCheck
+ |
+
+
+
+params
+
+
+[]Param
+
+
+ |
+
+(Optional)
+ Params declare parameters passed to this Condition
+ |
+
+
+
+resources
+
+
+[]PipelineTaskInputResource
+
+
+ |
+
+ Resources declare the resources provided to this Condition as input
+ |
+
+
+
+
+
+(Appears on:PipelineTaskCondition, PipelineTaskResources)
+
+
+
PipelineTaskInputResource maps the name of a declared PipelineResource input
+dependency in a Task to the resource in the Pipeline’s DeclaredPipelineResources
+that should be used. This input may come from a previous task.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name is the name of the PipelineResource as declared by the Task.
+ |
+
+
+
+resource
+
+string
+
+ |
+
+ Resource is the name of the DeclaredPipelineResource to use.
+ |
+
+
+
+from
+
+[]string
+
+ |
+
+(Optional)
+ From is the list of PipelineTask names that the resource has to come from.
+(Implies an ordering in the execution graph.)
+ |
+
+
+
+
+
+(Appears on:EmbeddedRunSpec, EmbeddedTask)
+
+
+
PipelineTaskMetadata contains the labels or annotations for an EmbeddedTask
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+labels
+
+map[string]string
+
+ |
+
+(Optional)
+ |
+
+
+
+annotations
+
+map[string]string
+
+ |
+
+(Optional)
+ |
+
+
+
+PipelineTaskOutputResource
+
+
+(Appears on:PipelineTaskResources)
+
+
+
PipelineTaskOutputResource maps the name of a declared PipelineResource output
+dependency in a Task to the resource in the Pipeline’s DeclaredPipelineResources
+that should be used.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name is the name of the PipelineResource as declared by the Task.
+ |
+
+
+
+resource
+
+string
+
+ |
+
+ Resource is the name of the DeclaredPipelineResource to use.
+ |
+
+
+
+PipelineTaskParam
+
+
+
PipelineTaskParam is used to provide arbitrary string parameters to a Task.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+value
+
+string
+
+ |
+
+ |
+
+
+
+PipelineTaskResources
+
+
+(Appears on:PipelineTask, PipelineTask)
+
+
+
PipelineTaskResources allows a Pipeline to declare how its DeclaredPipelineResources
+should be provided to a Task as its inputs and outputs.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+inputs
+
+
+[]PipelineTaskInputResource
+
+
+ |
+
+ Inputs holds the mapping from the PipelineResources declared in
+DeclaredPipelineResources to the input PipelineResources required by the Task.
+ |
+
+
+
+outputs
+
+
+[]PipelineTaskOutputResource
+
+
+ |
+
+ Outputs holds the mapping from the PipelineResources declared in
+DeclaredPipelineResources to the input PipelineResources required by the Task.
+ |
+
+
+
+PipelineTaskRun
+
+
+
PipelineTaskRun reports the results of running a step in the Task. Each
+task has the potential to succeed or fail (based on the exit code)
+and produces logs.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+PipelineTaskRunSpec
+
+
+(Appears on:PipelineRunSpec)
+
+
+
PipelineTaskRunSpec can be used to configure specific
+specs for a concrete Task
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+pipelineTaskName
+
+string
+
+ |
+
+ |
+
+
+
+taskServiceAccountName
+
+string
+
+ |
+
+ |
+
+
+
+taskPodTemplate
+
+
+Template
+
+
+ |
+
+ |
+
+
+
+PipelineWorkspaceDeclaration
+
+
+(Appears on:PipelineSpec, PipelineSpec)
+
+
+
WorkspacePipelineDeclaration creates a named slot in a Pipeline that a PipelineRun
+is expected to populate with a workspace binding.
+Deprecated: use PipelineWorkspaceDeclaration type instead
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name is the name of a workspace to be provided by a PipelineRun.
+ |
+
+
+
+description
+
+string
+
+ |
+
+(Optional)
+ Description is a human readable string describing how the workspace will be
+used in the Pipeline. It can be useful to include a bit of detail about which
+tasks are intended to have access to the data on the workspace.
+ |
+
+
+
+optional
+
+bool
+
+ |
+
+ Optional marks a Workspace as not being required in PipelineRuns. By default
+this field is false and so declared workspaces are required.
+ |
+
+
+
+ResultRef
+
+
+
ResultRef is a type that represents a reference to a task run result
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+PipelineTask
+
+string
+
+ |
+
+ |
+
+
+
+Result
+
+string
+
+ |
+
+ |
+
+
+
+ResultType
+(int
alias)
+
+(Appears on:PipelineResourceResult)
+
+
+
ResultType used to find out whether a PipelineResourceResult is from a task result or not
+
+
+
+
+Value |
+Description |
+
+
+1 |
+TaskRunResultType default task run result value
+ |
+
+
+Sidecar
+
+
+(Appears on:TaskSpec)
+
+
+
Sidecar has nearly the same data structure as Step, consisting of a Container and an optional Script, but does not have the ability to timeout.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+Container
+
+
+Kubernetes core/v1.Container
+
+
+ |
+
+
+(Members of Container are embedded into this type.)
+
+ |
+
+
+
+script
+
+string
+
+ |
+
+(Optional)
+ Script is the contents of an executable file to execute.
+If Script is not empty, the Step cannot have an Command or Args.
+ |
+
+
+
+workspaces
+
+
+[]WorkspaceUsage
+
+
+ |
+
+(Optional)
+ This is an alpha field. You must set the “enable-api-fields” feature flag to “alpha”
+for this field to be supported.
+Workspaces is a list of workspaces from the Task that this Sidecar wants
+exclusive access to. Adding a workspace to this list means that any
+other Step or Sidecar that does not also request this Workspace will
+not have access to it.
+ |
+
+
+
+SidecarState
+
+
+(Appears on:TaskRunStatusFields)
+
+
+
SidecarState reports the results of running a sidecar in a Task.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+ContainerState
+
+
+Kubernetes core/v1.ContainerState
+
+
+ |
+
+
+(Members of ContainerState are embedded into this type.)
+
+ |
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+container
+
+string
+
+ |
+
+ |
+
+
+
+imageID
+
+string
+
+ |
+
+ |
+
+
+
+SkippedTask
+
+
+(Appears on:PipelineRunStatusFields)
+
+
+
SkippedTask is used to describe the Tasks that were skipped due to their When Expressions
+evaluating to False. This is a struct because we are looking into including more details
+about the When Expressions that caused this Task to be skipped.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name is the Pipeline Task name
+ |
+
+
+
+whenExpressions
+
+
+[]WhenExpression
+
+
+ |
+
+(Optional)
+ WhenExpressions is the list of checks guarding the execution of the PipelineTask
+ |
+
+
+
+Step
+
+
+(Appears on:ConditionSpec, InternalTaskModifier, TaskSpec)
+
+
+
Step embeds the Container type, which allows it to include fields not
+provided by Container.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+Container
+
+
+Kubernetes core/v1.Container
+
+
+ |
+
+
+(Members of Container are embedded into this type.)
+
+ |
+
+
+
+script
+
+string
+
+ |
+
+(Optional)
+ Script is the contents of an executable file to execute.
+If Script is not empty, the Step cannot have an Command and the Args will be passed to the Script.
+ |
+
+
+
+timeout
+
+
+Kubernetes meta/v1.Duration
+
+
+ |
+
+(Optional)
+ Timeout is the time after which the step times out. Defaults to never.
+Refer to Go’s ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration
+ |
+
+
+
+workspaces
+
+
+[]WorkspaceUsage
+
+
+ |
+
+(Optional)
+ This is an alpha field. You must set the “enable-api-fields” feature flag to “alpha”
+for this field to be supported.
+Workspaces is a list of workspaces from the Task that this Step wants
+exclusive access to. Adding a workspace to this list means that any
+other Step or Sidecar that does not also request this Workspace will
+not have access to it.
+ |
+
+
+
+onError
+
+string
+
+ |
+
+ OnError defines the exiting behavior of a container on error
+can be set to [ continue | stopAndFail ]
+stopAndFail indicates exit the taskRun if the container exits with non-zero exit code
+continue indicates continue executing the rest of the steps irrespective of the container exit code
+ |
+
+
+
+StepState
+
+
+(Appears on:TaskRunStatusFields)
+
+
+
StepState reports the results of running a step in a Task.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+ContainerState
+
+
+Kubernetes core/v1.ContainerState
+
+
+ |
+
+
+(Members of ContainerState are embedded into this type.)
+
+ |
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+container
+
+string
+
+ |
+
+ |
+
+
+
+imageID
+
+string
+
+ |
+
+ |
+
+
+
+TaskKind
+(string
alias)
+
+(Appears on:TaskRef)
+
+
+
TaskKind defines the type of Task used by the pipeline.
+
+
+
+
+Value |
+Description |
+
+
+"ClusterTask" |
+ClusterTaskKind indicates that task type has a cluster scope.
+ |
+
"Task" |
+NamespacedTaskKind indicates that the task type has a namespaced scope.
+ |
+
+
+TaskModifier
+
+
+
TaskModifier is an interface to be implemented by different PipelineResources
+
+TaskObject
+
+
+
TaskObject is implemented by Task and ClusterTask
+
+TaskRef
+
+
+(Appears on:PipelineTask, RunSpec, TaskRunSpec, PipelineTask, TaskRunSpec)
+
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name of the referent; More info: http://kubernetes.io/docs/user-guide/identifiers#names
+ |
+
+
+
+kind
+
+
+TaskKind
+
+
+ |
+
+ TaskKind indicates the kind of the task, namespaced or cluster scoped.
+ |
+
+
+
+apiVersion
+
+string
+
+ |
+
+(Optional)
+ API version of the referent
+ |
+
+
+
+bundle
+
+string
+
+ |
+
+(Optional)
+ Bundle url reference to a Tekton Bundle.
+ |
+
+
+
+TaskResource
+
+
+(Appears on:Inputs, Outputs, TaskResources)
+
+
+
TaskResource defines an input or output Resource declared as a requirement
+by a Task. The Name field will be used to refer to these Resources within
+the Task definition, and when provided as an Input, the Name will be the
+path to the volume mounted containing this Resource as an input (e.g.
+an input Resource named workspace
will be mounted at /workspace
).
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+ResourceDeclaration
+
+
+ResourceDeclaration
+
+
+ |
+
+
+(Members of ResourceDeclaration are embedded into this type.)
+
+ |
+
+
+
+TaskResourceBinding
+
+
+(Appears on:TaskRunInputs, TaskRunOutputs, TaskRunInputs, TaskRunOutputs, TaskRunResources)
+
+
+
TaskResourceBinding points to the PipelineResource that
+will be used for the Task input or output called Name.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+PipelineResourceBinding
+
+
+PipelineResourceBinding
+
+
+ |
+
+
+(Members of PipelineResourceBinding are embedded into this type.)
+
+ |
+
+
+
+paths
+
+[]string
+
+ |
+
+(Optional)
+ Paths will probably be removed in #1284, and then PipelineResourceBinding can be used instead.
+The optional Path field corresponds to a path on disk at which the Resource can be found
+(used when providing the resource via mounted volume, overriding the default logic to fetch the Resource).
+ |
+
+
+
+TaskResources
+
+
+(Appears on:TaskSpec)
+
+
+
TaskResources allows a Pipeline to declare how its DeclaredPipelineResources
+should be provided to a Task as its inputs and outputs.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+inputs
+
+
+[]TaskResource
+
+
+ |
+
+ Inputs holds the mapping from the PipelineResources declared in
+DeclaredPipelineResources to the input PipelineResources required by the Task.
+ |
+
+
+
+outputs
+
+
+[]TaskResource
+
+
+ |
+
+ Outputs holds the mapping from the PipelineResources declared in
+DeclaredPipelineResources to the input PipelineResources required by the Task.
+ |
+
+
+
+TaskResult
+
+
+(Appears on:TaskSpec)
+
+
+
TaskResult used to describe the results of a task
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name the given name
+ |
+
+
+
+description
+
+string
+
+ |
+
+(Optional)
+ Description is a human-readable description of the result
+ |
+
+
+
+TaskRunDebug
+
+
+(Appears on:TaskRunSpec)
+
+
+
TaskRunDebug defines the breakpoint config for a particular TaskRun
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+breakpoint
+
+[]string
+
+ |
+
+(Optional)
+ |
+
+
+
+
+
+
TaskRunInputs holds the input values that this task was invoked with.
+
+
+TaskRunOutputs
+
+
+
TaskRunOutputs holds the output values that this task was invoked with.
+
+
+TaskRunReason
+(string
alias)
+
+
TaskRunReason is an enum used to store all TaskRun reason for
+the Succeeded condition that are controlled by the TaskRun itself. Failure
+reasons that emerge from underlying resources are not included here
+
+
+
+
+Value |
+Description |
+
+
+"TaskRunCancelled" |
+TaskRunReasonCancelled is the reason set when the Taskrun is cancelled by the user
+ |
+
"Failed" |
+TaskRunReasonFailed is the reason set when the TaskRun completed with a failure
+ |
+
"Running" |
+TaskRunReasonRunning is the reason set when the TaskRun is running
+ |
+
"Started" |
+TaskRunReasonStarted is the reason set when the TaskRun has just started
+ |
+
"Succeeded" |
+TaskRunReasonSuccessful is the reason set when the TaskRun completed successfully
+ |
+
"TaskRunTimeout" |
+TaskRunReasonTimedOut is the reason set when the Taskrun has timed out
+ |
+
+
+TaskRunResources
+
+
+(Appears on:TaskRunSpec, TaskRunSpec)
+
+
+
TaskRunResources allows a TaskRun to declare inputs and outputs TaskResourceBinding
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+inputs
+
+
+[]TaskResourceBinding
+
+
+ |
+
+ Inputs holds the inputs resources this task was invoked with
+ |
+
+
+
+outputs
+
+
+[]TaskResourceBinding
+
+
+ |
+
+ Outputs holds the inputs resources this task was invoked with
+ |
+
+
+
+TaskRunResult
+
+
+(Appears on:TaskRunStatusFields)
+
+
+
TaskRunResult used to describe the results of a task
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name the given name
+ |
+
+
+
+value
+
+string
+
+ |
+
+ Value the given value of the result
+ |
+
+
+
+TaskRunSpec
+
+
+(Appears on:TaskRun, ConditionCheck)
+
+
+
TaskRunSpec defines the desired state of TaskRun
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+debug
+
+
+TaskRunDebug
+
+
+ |
+
+(Optional)
+ |
+
+
+
+params
+
+
+[]Param
+
+
+ |
+
+(Optional)
+ |
+
+
+
+resources
+
+
+TaskRunResources
+
+
+ |
+
+(Optional)
+ |
+
+
+
+serviceAccountName
+
+string
+
+ |
+
+(Optional)
+ |
+
+
+
+taskRef
+
+
+TaskRef
+
+
+ |
+
+(Optional)
+ no more than one of the TaskRef and TaskSpec may be specified.
+ |
+
+
+
+taskSpec
+
+
+TaskSpec
+
+
+ |
+
+(Optional)
+ |
+
+
+
+status
+
+
+TaskRunSpecStatus
+
+
+ |
+
+(Optional)
+ Used for cancelling a taskrun (and maybe more later on)
+ |
+
+
+
+timeout
+
+
+Kubernetes meta/v1.Duration
+
+
+ |
+
+(Optional)
+ Time after which the build times out. Defaults to 1 hour.
+Specified build timeout should be less than 24h.
+Refer Go’s ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration
+ |
+
+
+
+podTemplate
+
+
+Template
+
+
+ |
+
+ PodTemplate holds pod specific configuration
+ |
+
+
+
+workspaces
+
+
+[]WorkspaceBinding
+
+
+ |
+
+(Optional)
+ Workspaces is a list of WorkspaceBindings from volumes to workspaces.
+ |
+
+
+
+TaskRunSpecStatus
+(string
alias)
+
+(Appears on:TaskRunSpec, TaskRunSpec)
+
+
+
TaskRunSpecStatus defines the taskrun spec status the user can provide
+
+TaskRunStatus
+
+
+(Appears on:TaskRun, TaskRun, ConditionCheck, ConditionCheck, PipelineRunTaskRunStatus, TaskRunStatusFields)
+
+
+
TaskRunStatus defines the observed state of TaskRun
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+Status
+
+
+knative.dev/pkg/apis/duck/v1beta1.Status
+
+
+ |
+
+
+(Members of Status are embedded into this type.)
+
+ |
+
+
+
+TaskRunStatusFields
+
+
+TaskRunStatusFields
+
+
+ |
+
+
+(Members of TaskRunStatusFields are embedded into this type.)
+
+TaskRunStatusFields inlines the status fields.
+ |
+
+
+
+TaskRunStatusFields
+
+
+(Appears on:TaskRunStatus)
+
+
+
TaskRunStatusFields holds the fields of TaskRun’s status. This is defined
+separately and inlined so that other types can readily consume these fields
+via duck typing.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+podName
+
+string
+
+ |
+
+ PodName is the name of the pod responsible for executing this task’s steps.
+ |
+
+
+
+startTime
+
+
+Kubernetes meta/v1.Time
+
+
+ |
+
+(Optional)
+ StartTime is the time the build is actually started.
+ |
+
+
+
+completionTime
+
+
+Kubernetes meta/v1.Time
+
+
+ |
+
+(Optional)
+ CompletionTime is the time the build completed.
+ |
+
+
+
+steps
+
+
+[]StepState
+
+
+ |
+
+(Optional)
+ Steps describes the state of each build step container.
+ |
+
+
+
+cloudEvents
+
+
+[]CloudEventDelivery
+
+
+ |
+
+(Optional)
+ CloudEvents describe the state of each cloud event requested via a
+CloudEventResource.
+ |
+
+
+
+retriesStatus
+
+
+[]TaskRunStatus
+
+
+ |
+
+(Optional)
+ RetriesStatus contains the history of TaskRunStatus in case of a retry in order to keep record of failures.
+All TaskRunStatus stored in RetriesStatus will have no date within the RetriesStatus as is redundant.
+ |
+
+
+
+resourcesResult
+
+
+[]PipelineResourceResult
+
+
+ |
+
+(Optional)
+ Results from Resources built during the taskRun. currently includes
+the digest of build container images
+ |
+
+
+
+taskResults
+
+
+[]TaskRunResult
+
+
+ |
+
+(Optional)
+ TaskRunResults are the list of results written out by the task’s containers
+ |
+
+
+
+sidecars
+
+
+[]SidecarState
+
+
+ |
+
+ The list has one entry per sidecar in the manifest. Each entry is
+represents the imageid of the corresponding sidecar.
+ |
+
+
+
+taskSpec
+
+
+TaskSpec
+
+
+ |
+
+ TaskSpec contains the Spec from the dereferenced Task definition used to instantiate this TaskRun.
+ |
+
+
+
+TaskSpec
+
+
+(Appears on:ClusterTask, Task, TaskSpec, EmbeddedTask, TaskRunSpec, TaskRunStatusFields)
+
+
+
TaskSpec defines the desired state of Task.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+resources
+
+
+TaskResources
+
+
+ |
+
+(Optional)
+ Resources is a list input and output resource to run the task
+Resources are represented in TaskRuns as bindings to instances of
+PipelineResources.
+ |
+
+
+
+params
+
+
+[]ParamSpec
+
+
+ |
+
+(Optional)
+ Params is a list of input parameters required to run the task. Params
+must be supplied as inputs in TaskRuns unless they declare a default
+value.
+ |
+
+
+
+description
+
+string
+
+ |
+
+(Optional)
+ Description is a user-facing description of the task that may be
+used to populate a UI.
+ |
+
+
+
+steps
+
+
+[]Step
+
+
+ |
+
+ Steps are the steps of the build; each step is run sequentially with the
+source mounted into /workspace.
+ |
+
+
+
+volumes
+
+
+[]Kubernetes core/v1.Volume
+
+
+ |
+
+ Volumes is a collection of volumes that are available to mount into the
+steps of the build.
+ |
+
+
+
+stepTemplate
+
+
+Kubernetes core/v1.Container
+
+
+ |
+
+ StepTemplate can be used as the basis for all step containers within the
+Task, so that the steps inherit settings on the base container.
+ |
+
+
+
+sidecars
+
+
+[]Sidecar
+
+
+ |
+
+ Sidecars are run alongside the Task’s step containers. They begin before
+the steps start and end after the steps complete.
+ |
+
+
+
+workspaces
+
+
+[]WorkspaceDeclaration
+
+
+ |
+
+ Workspaces are the volumes that this Task requires.
+ |
+
+
+
+results
+
+
+[]TaskResult
+
+
+ |
+
+ Results are values that this Task can output
+ |
+
+
+
+TimeoutFields
+
+
+(Appears on:PipelineRunSpec)
+
+
+
TimeoutFields allows granular specification of pipeline, task, and finally timeouts
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+pipeline
+
+
+Kubernetes meta/v1.Duration
+
+
+ |
+
+ Pipeline sets the maximum allowed duration for execution of the entire pipeline. The sum of individual timeouts for tasks and finally must not exceed this value.
+ |
+
+
+
+tasks
+
+
+Kubernetes meta/v1.Duration
+
+
+ |
+
+ Tasks sets the maximum allowed duration of this pipeline’s tasks
+ |
+
+
+
+finally
+
+
+Kubernetes meta/v1.Duration
+
+
+ |
+
+ Finally sets the maximum allowed duration of this pipeline’s finally
+ |
+
+
+
+WhenExpression
+
+
+(Appears on:PipelineRunRunStatus, PipelineRunTaskRunStatus, SkippedTask)
+
+
+
WhenExpression allows a PipelineTask to declare expressions to be evaluated before the Task is run
+to determine whether the Task should be executed or skipped
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+input
+
+string
+
+ |
+
+ Input is the string for guard checking which can be a static input or an output from a parent Task
+ |
+
+
+
+operator
+
+k8s.io/apimachinery/pkg/selection.Operator
+
+ |
+
+ Operator that represents an Input’s relationship to the values
+ |
+
+
+
+values
+
+[]string
+
+ |
+
+ Values is an array of strings, which is compared against the input, for guard checking
+It must be non-empty
+ |
+
+
+
+WhenExpressions
+([]github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1.WhenExpression
alias)
+
+(Appears on:PipelineTask)
+
+
+
WhenExpressions are used to specify whether a Task should be executed or skipped
+All of them need to evaluate to True for a guarded Task to be executed.
+
+WorkspaceBinding
+
+
+(Appears on:PipelineRunSpec, RunSpec, TaskRunSpec, PipelineRunSpec, TaskRunSpec)
+
+
+
WorkspaceBinding maps a Task’s declared workspace to a Volume.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name is the name of the workspace populated by the volume.
+ |
+
+
+
+subPath
+
+string
+
+ |
+
+(Optional)
+ SubPath is optionally a directory on the volume which should be used
+for this binding (i.e. the volume will be mounted at this sub directory).
+ |
+
+
+
+volumeClaimTemplate
+
+
+Kubernetes core/v1.PersistentVolumeClaim
+
+
+ |
+
+(Optional)
+ VolumeClaimTemplate is a template for a claim that will be created in the same namespace.
+The PipelineRun controller is responsible for creating a unique claim for each instance of PipelineRun.
+ |
+
+
+
+persistentVolumeClaim
+
+
+Kubernetes core/v1.PersistentVolumeClaimVolumeSource
+
+
+ |
+
+(Optional)
+ PersistentVolumeClaimVolumeSource represents a reference to a
+PersistentVolumeClaim in the same namespace. Either this OR EmptyDir can be used.
+ |
+
+
+
+emptyDir
+
+
+Kubernetes core/v1.EmptyDirVolumeSource
+
+
+ |
+
+(Optional)
+ EmptyDir represents a temporary directory that shares a Task’s lifetime.
+More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir
+Either this OR PersistentVolumeClaim can be used.
+ |
+
+
+
+configMap
+
+
+Kubernetes core/v1.ConfigMapVolumeSource
+
+
+ |
+
+(Optional)
+ ConfigMap represents a configMap that should populate this workspace.
+ |
+
+
+
+secret
+
+
+Kubernetes core/v1.SecretVolumeSource
+
+
+ |
+
+(Optional)
+ Secret represents a secret that should populate this workspace.
+ |
+
+
+
+WorkspaceDeclaration
+
+
+(Appears on:TaskSpec)
+
+
+
WorkspaceDeclaration is a declaration of a volume that a Task requires.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name is the name by which you can bind the volume at runtime.
+ |
+
+
+
+description
+
+string
+
+ |
+
+(Optional)
+ Description is an optional human readable description of this volume.
+ |
+
+
+
+mountPath
+
+string
+
+ |
+
+(Optional)
+ MountPath overrides the directory that the volume will be made available at.
+ |
+
+
+
+readOnly
+
+bool
+
+ |
+
+ ReadOnly dictates whether a mounted volume is writable. By default this
+field is false and so mounted volumes are writable.
+ |
+
+
+
+optional
+
+bool
+
+ |
+
+ Optional marks a Workspace as not being required in TaskRuns. By default
+this field is false and so declared workspaces are required.
+ |
+
+
+
+WorkspacePipelineTaskBinding
+
+
+(Appears on:PipelineTask, PipelineTask)
+
+
+
WorkspacePipelineTaskBinding describes how a workspace passed into the pipeline should be
+mapped to a task’s declared workspace.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name is the name of the workspace as declared by the task
+ |
+
+
+
+workspace
+
+string
+
+ |
+
+ Workspace is the name of the workspace declared by the pipeline
+ |
+
+
+
+subPath
+
+string
+
+ |
+
+(Optional)
+ SubPath is optionally a directory on the volume which should be used
+for this binding (i.e. the volume will be mounted at this sub directory).
+ |
+
+
+
+WorkspaceUsage
+
+
+(Appears on:Sidecar, Step)
+
+
+
WorkspaceUsage is used by a Step or Sidecar to declare that it wants isolated access
+to a Workspace defined in a Task.
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ Name is the name of the workspace this Step or Sidecar wants access to.
+ |
+
+
+
+mountPath
+
+string
+
+ |
+
+ MountPath is the path that the workspace should be mounted to inside the Step or Sidecar,
+overriding any MountPath specified in the Task’s WorkspaceDeclaration.
+ |
+
+
+
+
+
+Generated with gen-crd-api-reference-docs
+.
+
diff --git a/go.mod b/go.mod
index a5bca9188dd..405a2a674e6 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,7 @@ module github.com/tektoncd/pipeline
go 1.17
require (
+ github.com/abayer/gen-crd-api-reference-docs v0.999.0
github.com/cloudevents/sdk-go/v2 v2.5.0
github.com/containerd/containerd v1.5.10
github.com/ghodss/yaml v1.0.0
@@ -10,6 +11,7 @@ require (
github.com/google/go-containerregistry v0.8.1-0.20220216220642-00c59d91847c
github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20220216220642-00c59d91847c
github.com/google/uuid v1.3.0
+ github.com/hashicorp/errwrap v1.0.0
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/golang-lru v0.5.4
github.com/jenkins-x/go-scm v1.10.10
@@ -90,7 +92,6 @@ require (
github.com/google/gofuzz v1.2.0 // indirect
github.com/googleapis/gnostic v0.5.5 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
- github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
@@ -111,6 +112,7 @@ require (
github.com/prometheus/common v0.32.1 // indirect
github.com/prometheus/procfs v0.6.0 // indirect
github.com/prometheus/statsd_exporter v0.21.0 // indirect
+ github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shurcooL/githubv4 v0.0.0-20190718010115-4ba037080260 // indirect
github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
diff --git a/go.sum b/go.sum
index 3c994813ebc..1a5ee4f5394 100644
--- a/go.sum
+++ b/go.sum
@@ -153,6 +153,8 @@ github.com/Shopify/sarama v1.30.0/go.mod h1:zujlQQx1kzHsh4jfV1USnptCQrHAEZ2Hk8fT
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/Shopify/toxiproxy/v2 v2.1.6-0.20210914104332-15ea381dcdae/go.mod h1:/cvHQkZ1fst0EmZnA5dFtiQdWCNCFYzb+uE2vqVgvx0=
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
+github.com/abayer/gen-crd-api-reference-docs v0.999.0 h1:vWWWZtgG+te5YDpim37+zehuFDX0o/Sc2Mh953kTnhU=
+github.com/abayer/gen-crd-api-reference-docs v0.999.0/go.mod h1:hCZxQ/b99HVLLuijnYy7xY+z2P53IQ5A2dgGKJblO4Q=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
github.com/alecthomas/jsonschema v0.0.0-20180308105923-f2c93856175a/go.mod h1:qpebaTNSsyUn5rPSJMsfqEtDw71TTggXM6stUDI16HA=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
@@ -1198,8 +1200,10 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
+github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryancurrah/gomodguard v1.2.3/go.mod h1:rYbA/4Tg5c54mV1sv4sQTP5WOPBcoLtnBZ7/TEhXAbg=
github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA=
@@ -2172,9 +2176,11 @@ k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
+k8s.io/gengo v0.0.0-20201203183100-97869a43a9d9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/gengo v0.0.0-20220307231824-4627b89bbf1b h1:vEhKDJESYfeRiaBNmRvO+/12RAo1cFeu6vGm1fBFY34=
k8s.io/gengo v0.0.0-20220307231824-4627b89bbf1b/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
+k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
diff --git a/hack/reference-docs-gen-config.json b/hack/reference-docs-gen-config.json
new file mode 100644
index 00000000000..1cf8db3503c
--- /dev/null
+++ b/hack/reference-docs-gen-config.json
@@ -0,0 +1,42 @@
+{
+ "hideMemberFields": [
+ "TypeMeta"
+ ],
+ "hideTypePatterns": [
+ "ParseError$",
+ "List$"
+ ],
+ "externalPackages": [
+ {
+ "typeMatchPrefix": "^k8s\\.io/apimachinery/pkg/apis/meta/v1\\.Duration$",
+ "docsURLTemplate": "https://godoc.org/k8s.io/apimachinery/pkg/apis/meta/v1#Duration"
+ },
+ {
+ "typeMatchPrefix": "^k8s\\.io/(api|apimachinery/pkg/apis)/",
+ "docsURLTemplate": "https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#{{lower .TypeIdentifier}}-{{arrIndex .PackageSegments -1}}-{{arrIndex .PackageSegments -2}}"
+ },
+ {
+ "typeMatchPrefix": "^knative\\.dev/pkg/apis/duck",
+ "docsURLTemplate": "https://pkg.go.dev/knative.dev/pkg/apis/duck/{{arrIndex .PackageSegments -1}}#{{.TypeIdentifier}}"
+ },
+ {
+ "typeMatchPrefix": "^knative\\.dev/pkg/apis\\.URL$",
+ "docsURLTemplate": "https://pkg.go.dev/knative.dev/pkg/apis#URL"
+ },
+ {
+ "typeMatchPrefix": "^knative\\.dev/networking/pkg/apis/networking",
+ "docsURLTemplate": "https://pkg.go.dev/knative.dev/networking/pkg/apis/networking#{{.TypeIdentifier}}"
+ },
+ {
+ "typeMatchPrefix": "^time\\.Duration$",
+ "docsURLTemplate": "https://golang.org/pkg/time/#Duration"
+ }
+ ],
+ "typeDisplayNamePrefixOverrides": {
+ "k8s.io/api/": "Kubernetes ",
+ "k8s.io/apimachinery/pkg/apis/": "Kubernetes "
+ },
+ "markdownDisabled": false,
+ "gitCommitDisabled": true
+}
+
diff --git a/hack/reference-docs-template/members.tpl b/hack/reference-docs-template/members.tpl
new file mode 100644
index 00000000000..a529c671647
--- /dev/null
+++ b/hack/reference-docs-template/members.tpl
@@ -0,0 +1,48 @@
+{{ define "members" }}
+
+{{ range .Members }}
+{{ if not (hiddenMember .)}}
+
+
+ {{ fieldName . }}
+
+ {{ if linkForType .Type }}
+
+ {{ typeDisplayName .Type }}
+
+ {{ else }}
+ {{ typeDisplayName .Type }}
+ {{ end }}
+
+ |
+
+ {{ if fieldEmbedded . }}
+
+ (Members of {{ fieldName . }} are embedded into this type.)
+
+ {{ end}}
+
+ {{ if isOptionalMember .}}
+ (Optional)
+ {{ end }}
+
+ {{ safe (renderComments .CommentLines) }}
+
+ {{ if and (eq (.Type.Name.Name) "ObjectMeta") }}
+ Refer to the Kubernetes API documentation for the fields of the
+ metadata field.
+ {{ end }}
+
+ {{ if or (eq (fieldName .) "spec") }}
+
+
+
+ {{ template "members" .Type }}
+
+ {{ end }}
+ |
+
+{{ end }}
+{{ end }}
+
+{{ end }}
diff --git a/hack/reference-docs-template/pkg.tpl b/hack/reference-docs-template/pkg.tpl
new file mode 100644
index 00000000000..842ec93d493
--- /dev/null
+++ b/hack/reference-docs-template/pkg.tpl
@@ -0,0 +1,49 @@
+{{ define "packages" }}
+
+{{ with .packages}}
+Packages:
+
+{{ end}}
+
+{{ range .packages }}
+
+ {{- packageDisplayName . -}}
+
+
+ {{ with (index .GoPackages 0 )}}
+ {{ with .DocComments }}
+
+ {{ safe (renderComments .) }}
+
+ {{ end }}
+ {{ end }}
+
+ Resource Types:
+
+ {{- range (visibleTypes (sortedTypes .Types)) -}}
+ {{ if isExportedType . -}}
+ -
+ {{ typeDisplayName . }}
+
+ {{- end }}
+ {{- end -}}
+
+
+ {{ range (visibleTypes (sortedTypes .Types))}}
+ {{ template "type" . }}
+ {{ end }}
+
+{{ end }}
+
+
+ Generated with gen-crd-api-reference-docs
+ {{ with .gitCommit }} on git commit {{ . }}
{{end}}.
+
+
+{{ end }}
diff --git a/hack/reference-docs-template/placeholder.go b/hack/reference-docs-template/placeholder.go
new file mode 100644
index 00000000000..cc8f1453aca
--- /dev/null
+++ b/hack/reference-docs-template/placeholder.go
@@ -0,0 +1,2 @@
+// Placeholder file to make Go vendor this directory properly.
+package template
diff --git a/hack/reference-docs-template/type.tpl b/hack/reference-docs-template/type.tpl
new file mode 100644
index 00000000000..8f0d66b8bab
--- /dev/null
+++ b/hack/reference-docs-template/type.tpl
@@ -0,0 +1,81 @@
+{{ define "type" }}
+
+
+ {{- .Name.Name }}
+ {{ if eq .Kind "Alias" }}({{.Underlying}}
alias){{ end -}}
+
+{{ with (typeReferences .) }}
+
+ (Appears on:
+ {{- $prev := "" -}}
+ {{- range . -}}
+ {{- if $prev -}}, {{ end -}}
+ {{- $prev = . -}}
+ {{ typeDisplayName . }}
+ {{- end -}}
+ )
+
+{{ end }}
+
+
+ {{ safe (renderComments .CommentLines) }}
+
+
+{{ with (constantsOfType .) }}
+
+
+
+ Value |
+ Description |
+
+
+
+ {{- range . -}}
+
+ {{- /*
+ renderComments implicitly creates a element, so we
+ add one to the display name as well to make the contents
+ of the two cells align evenly.
+ */ -}}
+
{{ typeDisplayName . }} |
+ {{ safe (renderComments .CommentLines) }} |
+
+ {{- end -}}
+
+
+{{ end }}
+
+{{ if .Members }}
+
+
+
+ Field |
+ Description |
+
+
+
+ {{ if isExportedType . }}
+
+
+ apiVersion
+ string |
+
+
+ {{apiGroup .}}
+
+ |
+
+
+
+ kind
+ string
+ |
+ {{.Name.Name}} |
+
+ {{ end }}
+ {{ template "members" .}}
+
+
+{{ end }}
+
+{{ end }}
diff --git a/hack/tools.go b/hack/tools.go
index 7125f9423ea..f48534a456c 100644
--- a/hack/tools.go
+++ b/hack/tools.go
@@ -16,4 +16,7 @@ import (
_ "k8s.io/kube-openapi/cmd/openapi-gen"
_ "knative.dev/pkg/codegen/cmd/injection-gen"
+
+ // TODO(abayer): Switch to github.com/ahmetb/gen-crd-api-reference-docs once https://github.com/ahmetb/gen-crd-api-reference-docs/pull/43 is merged/released
+ _ "github.com/abayer/gen-crd-api-reference-docs"
)
diff --git a/hack/update-codegen.sh b/hack/update-codegen.sh
index ce40324fc08..2e0b92a719f 100755
--- a/hack/update-codegen.sh
+++ b/hack/update-codegen.sh
@@ -86,3 +86,6 @@ ${REPO_ROOT_DIR}/hack/update-deps.sh
# Make sure the OpenAPI specification and Swagger file are up-to-date
${REPO_ROOT_DIR}/hack/update-openapigen.sh
+
+# Make sure the generated API reference docs are up-to-date
+${REPO_ROOT_DIR}/hack/update-reference-docs.sh
diff --git a/hack/update-reference-docs.sh b/hack/update-reference-docs.sh
new file mode 100755
index 00000000000..e7c6305f70a
--- /dev/null
+++ b/hack/update-reference-docs.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+
+# Copyright 2020 The Tekton Authors
+#
+# 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.
+
+set -o errexit
+set -o nounset
+
+echo "Generating API reference docs ..."
+# TODO(abayer): Switch to github.com/ahmetb/gen-crd-api-reference-docs when https://github.com/ahmetb/gen-crd-api-reference-docs/pull/43 is merged/vendor is updated
+go run github.com/abayer/gen-crd-api-reference-docs \
+ -config "./hack/reference-docs-gen-config.json" \
+ -api-dir "github.com/tektoncd/pipeline/pkg/apis" \
+ -template-dir "./hack/reference-docs-template" \
+ -out-file "./docs/pipeline-api.md"
diff --git a/pkg/apis/doc.go b/pkg/apis/doc.go
new file mode 100644
index 00000000000..45a32127ac8
--- /dev/null
+++ b/pkg/apis/doc.go
@@ -0,0 +1,18 @@
+/*
+Copyright 2019 The Tekton Authors
+
+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.
+*/
+
+// Package apis contains API Schema definitions for the various API groups
+package apis
diff --git a/pkg/apis/pipeline/pod/doc.go b/pkg/apis/pipeline/pod/doc.go
index 2187544efad..9e7c8c3352c 100644
--- a/pkg/apis/pipeline/pod/doc.go
+++ b/pkg/apis/pipeline/pod/doc.go
@@ -14,7 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-// +k8s:openapi-gen=true
-
// Package pod contains non-versioned pod configuration
+// +k8s:openapi-gen=true
+// +gencrdrefdocs:unversionedTypes
+// +groupName=tekton.dev
package pod
diff --git a/pkg/apis/run/v1alpha1/doc.go b/pkg/apis/run/v1alpha1/doc.go
new file mode 100644
index 00000000000..dde2f9120d9
--- /dev/null
+++ b/pkg/apis/run/v1alpha1/doc.go
@@ -0,0 +1,19 @@
+/*
+Copyright 2019 The Tekton Authors
+
+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.
+*/
+
+// Package v1alpha1 contains API Schema definitions for the run v1alpha1 API group
+// +groupName=tekton.dev
+package v1alpha1
diff --git a/vendor/github.com/abayer/gen-crd-api-reference-docs/.gitignore b/vendor/github.com/abayer/gen-crd-api-reference-docs/.gitignore
new file mode 100644
index 00000000000..a4d184e80a8
--- /dev/null
+++ b/vendor/github.com/abayer/gen-crd-api-reference-docs/.gitignore
@@ -0,0 +1,16 @@
+# Binaries for programs and plugins
+refdocs
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# Test binary, build with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
+# goreleaser output
+dist
diff --git a/vendor/github.com/abayer/gen-crd-api-reference-docs/.goreleaser.yml b/vendor/github.com/abayer/gen-crd-api-reference-docs/.goreleaser.yml
new file mode 100644
index 00000000000..f1caccad8b0
--- /dev/null
+++ b/vendor/github.com/abayer/gen-crd-api-reference-docs/.goreleaser.yml
@@ -0,0 +1,24 @@
+builds:
+ - env:
+ - CGO_ENABLED=0
+ # travis ci currently sets GOPATH even with go1.11.
+ # force-setting GO111MODULE=on to use vgo
+ - GO111MODULE=on
+ goos:
+ - linux
+ - darwin
+ goarch:
+ - amd64
+archive:
+ name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}"
+ files:
+ - LICENSE
+ - template/**
+ - example-config.json
+checksum:
+ name_template: "checksums.txt"
+changelog:
+ skip: true
+release:
+ # releases are uploaded to github by .travis.yml
+ disable: true
diff --git a/vendor/github.com/abayer/gen-crd-api-reference-docs/.travis.yml b/vendor/github.com/abayer/gen-crd-api-reference-docs/.travis.yml
new file mode 100644
index 00000000000..d6845bab15e
--- /dev/null
+++ b/vendor/github.com/abayer/gen-crd-api-reference-docs/.travis.yml
@@ -0,0 +1,32 @@
+language: go
+go:
+ - 1.11.x
+install:
+ - echo noop
+before_script:
+ # travis ci currently sets GOPATH even with go1.11.
+ # force-setting GO111MODULE=on to use vgo
+ - env GO111MODULE=on go mod download
+script:
+ # travis ci currently sets GOPATH even with go1.11.
+ # force-setting GO111MODULE=on to use vgo
+ - env GO111MODULE=on go build -v -o /dev/null
+deploy:
+ # use goreleaser to prepare dist/
+ - provider: script
+ skip_cleanup: true
+ on:
+ tags: true
+ script: curl -sL https://git.io/goreleaser | bash
+ # use github release feature to upload dist/
+ - provider: releases
+ skip_cleanup: true
+ on:
+ tags: true
+ file_glob: true
+ file:
+ - dist/*.tar.gz
+ - dist/*.zip
+ - dist/checksums.txt
+ api_key:
+ secure: r1GMgbVDnZTUcny/PbIATW9dXGOTpm2U9iEGaWvpprMO2AGo7ju7SWEJWtjcap3pc0YasyR2/eon9LC0scWY0Xlpeb+g0pRCQ39FABk1Vo3DpmIPRUCFFkaescWmrWDj3ImzjJgZjCewwK6Fo8s8ngnqIlZnE1Hq6ls2xDp6jNVf+Pn7LyqxkK4axFFSPQM9zFX3N1PVUH5RT03bIJfojJZguqnhNfyTvKvHJidoeWU/Ie+fXc4AdPHyP85xrmGHYl68O0HziU6JCLXira8r1FjUgVeYFYC5nnNuylszO6JWqWh1nXYDxs5FGPnZd9N8bEi/2ahiqms8eV7S+/DGzhSoEdHikcBxTgJpZP2VOmvRSITyv3RleJzCeMULTGFQodoxRgA/Q8qZySvInNjstiBjV2Pyucrnn990XQbN8rIV4RmNggJvbAwJNCGjCwS2eB42EKNCODTuzHPbIV0ap4EjvfBBo0cZ2J9M2Q6VzdpNErdntpM1hZl9yymv3MNN4hOiLQKkofoo/QI3cffB8Y0PBPAL8Cs9Mx1bbx+Dr8iitTHBUAt4a5DHFen4MS8znrZ+Cr4kLDD9QPJ8G0oh4tDKq8CJ73Gt+xqkLZEuka0W1awz9essqE7MH20kRJbKa5woTIs0v9njHMpbeqd7KrNV+1e5F5aPRQyiCzaom7c=
diff --git a/vendor/github.com/abayer/gen-crd-api-reference-docs/LICENSE b/vendor/github.com/abayer/gen-crd-api-reference-docs/LICENSE
new file mode 100644
index 00000000000..261eeb9e9f8
--- /dev/null
+++ b/vendor/github.com/abayer/gen-crd-api-reference-docs/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/vendor/github.com/abayer/gen-crd-api-reference-docs/README.md b/vendor/github.com/abayer/gen-crd-api-reference-docs/README.md
new file mode 100644
index 00000000000..d481b8f57d2
--- /dev/null
+++ b/vendor/github.com/abayer/gen-crd-api-reference-docs/README.md
@@ -0,0 +1,80 @@
+# Kubernetes Custom Resource API Reference Docs generator
+
+If you have a project that is Custom Resource Definitions and wanted to generate
+API Reference Docs [like this][ar] this tool is for you.
+
+[ar]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.13/
+
+## Current Users
+
+- [**Knative** API reference docs](https://knative.dev/docs/reference/api/serving-api/)
+- [**Kubeflow** API reference docs](https://www.kubeflow.org/docs/reference/overview/)
+- [**Agones** API reference docs](https://agones.dev/site/docs/reference/agones_crd_api_reference/)
+- [**cert-manager** API reference docs](https://cert-manager.io/docs/reference/api-docs/)
+- [**Gardener** API reference docs](https://gardener.cloud/api-reference/)
+- [**New Relic Alert Manager** API reference docs](https://github.com/fpetkovski/newrelic-alert-manager/tree/master/docs)
+- _[[ADD YOUR PROJECT HERE]]_
+
+## Why
+
+Normally you would want to use the same [docs generator][dg] as [Kubernetes API
+reference][ar], but here's why I wrote a different parser/generator:
+
+1. Today, Kubernetes API [does not][pr] provide OpenAPI specs for CRDs (e.g.
+ Knative), therefore the [gen-apidocs][ga]
+ generator used by Kubernetes won't work.
+
+2. Even when Kubernetes API starts providing OpenAPI specs for CRDs, your CRD
+ must have a validation schema (e.g. Knative API doesn't!)
+
+3. Kubernetes [gen-apidocs][ga] parser relies on running a `kube-apiserver` and
+ calling `/apis` endpoint to get OpenAPI specs to generate docs. **This tool
+ doesn't need that!**
+
+[dg]: https://github.com/kubernetes-incubator/reference-docs/
+[ga]: https://github.com/kubernetes-incubator/reference-docs/tree/master/gen-apidocs/generators
+[pr]: https://github.com/kubernetes/kubernetes/pull/71192
+
+## How
+
+This is a custom API reference docs generator that uses the
+[k8s.io/gengo](https://godoc.org/k8s.io/gengo) project to parse types and
+generate API documentation from it.
+
+Capabilities of this tool include:
+
+- Doesn't depend on OpenAPI specs, or kube-apiserver, or a running cluster.
+- Relies only on the Go source code (pkg/apis/**/*.go) to parse API types.
+- Can link to other sites for external APIs. For example, if your types have a
+ reference to Kubernetes core/v1.PodSpec, you can link to it.
+- [Configurable](./example-config.json) settings to hide certain fields or types
+ entirely from the generated output.
+- Either output to a file or start a live http-server (for rapid iteration).
+- Supports markdown rendering from godoc type, package and field comments.
+
+## Try it out
+
+1. Clone this repository.
+
+2. Make sure you have go1.11+ instaled. Then run `go build`, you should get a
+ `gen-crd-api-reference-docs` binary executable in the current directory.
+
+3. Clone a Knative repository, set GOPATH correctly,
+ and call the compiled binary within that directory.
+
+ ```sh
+ # go into a repository root with GOPATH set. (I use my own script
+ # goclone(1) to have a separate GOPATH for each repo I clone.)
+ $ goclone knative/build
+
+ $ /path/to/gen-crd-api-reference-docs \
+ -config "/path/to/example-config.json" \
+ -api-dir "github.com/knative/build/pkg/apis/build/v1alpha1" \
+ -out-file docs.html
+ ```
+
+4. Visit `docs.html` to view the results.
+
+-----
+
+This is not an official Google project. See [LICENSE](./LICENSE).
diff --git a/vendor/github.com/abayer/gen-crd-api-reference-docs/example-config.json b/vendor/github.com/abayer/gen-crd-api-reference-docs/example-config.json
new file mode 100644
index 00000000000..298f00b64cc
--- /dev/null
+++ b/vendor/github.com/abayer/gen-crd-api-reference-docs/example-config.json
@@ -0,0 +1,28 @@
+{
+ "hideMemberFields": [
+ "TypeMeta"
+ ],
+ "hideTypePatterns": [
+ "ParseError$",
+ "List$"
+ ],
+ "externalPackages": [
+ {
+ "typeMatchPrefix": "^k8s\\.io/apimachinery/pkg/apis/meta/v1\\.Duration$",
+ "docsURLTemplate": "https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#Duration"
+ },
+ {
+ "typeMatchPrefix": "^k8s\\.io/(api|apimachinery/pkg/apis)/",
+ "docsURLTemplate": "https://v1-18.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#{{lower .TypeIdentifier}}-{{arrIndex .PackageSegments -1}}-{{arrIndex .PackageSegments -2}}"
+ },
+ {
+ "typeMatchPrefix": "^github\\.com/knative/pkg/apis/duck/",
+ "docsURLTemplate": "https://pkg.go.dev/github.com/knative/pkg/apis/duck/{{arrIndex .PackageSegments -1}}#{{.TypeIdentifier}}"
+ }
+ ],
+ "typeDisplayNamePrefixOverrides": {
+ "k8s.io/api/": "Kubernetes ",
+ "k8s.io/apimachinery/pkg/apis/": "Kubernetes "
+ },
+ "markdownDisabled": false
+}
diff --git a/vendor/github.com/abayer/gen-crd-api-reference-docs/main.go b/vendor/github.com/abayer/gen-crd-api-reference-docs/main.go
new file mode 100644
index 00000000000..8832321b849
--- /dev/null
+++ b/vendor/github.com/abayer/gen-crd-api-reference-docs/main.go
@@ -0,0 +1,722 @@
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "html/template"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "reflect"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+ texttemplate "text/template"
+ "time"
+ "unicode"
+
+ "github.com/pkg/errors"
+ "github.com/russross/blackfriday/v2"
+ "k8s.io/gengo/parser"
+ "k8s.io/gengo/types"
+ "k8s.io/klog"
+)
+
+var (
+ flConfig = flag.String("config", "", "path to config file")
+ flAPIDir = flag.String("api-dir", "", "api directory (or import path), point this to pkg/apis")
+ flTemplateDir = flag.String("template-dir", "template", "path to template/ dir")
+
+ flHTTPAddr = flag.String("http-addr", "", "start an HTTP server on specified addr to view the result (e.g. :8080)")
+ flOutFile = flag.String("out-file", "", "path to output file to save the result")
+)
+
+const (
+ docCommentForceIncludes = "+gencrdrefdocs:force"
+ docCommentIncludeUnversionedTypes = "+gencrdrefdocs:unversionedTypes"
+)
+
+type generatorConfig struct {
+ // HiddenMemberFields hides fields with specified names on all types.
+ HiddenMemberFields []string `json:"hideMemberFields"`
+
+ // HideTypePatterns hides types matching the specified patterns from the
+ // output.
+ HideTypePatterns []string `json:"hideTypePatterns"`
+
+ // ExternalPackages lists recognized external package references and how to
+ // link to them.
+ ExternalPackages []externalPackage `json:"externalPackages"`
+
+ // TypeDisplayNamePrefixOverrides is a mapping of how to override displayed
+ // name for types with certain prefixes with what value.
+ TypeDisplayNamePrefixOverrides map[string]string `json:"typeDisplayNamePrefixOverrides"`
+
+ // MarkdownDisabled controls markdown rendering for comment lines.
+ MarkdownDisabled bool `json:"markdownDisabled"`
+
+ // GitCommitDisabled causes the git commit information to be excluded from the output.
+ GitCommitDisabled bool `json:"gitCommitDisabled"`
+}
+
+type externalPackage struct {
+ TypeMatchPrefix string `json:"typeMatchPrefix"`
+ DocsURLTemplate string `json:"docsURLTemplate"`
+}
+
+type apiPackage struct {
+ apiGroup string
+ apiVersion string
+ GoPackages []*types.Package
+ Types []*types.Type // because multiple 'types.Package's can add types to an apiVersion
+ Constants []*types.Type
+}
+
+func (v *apiPackage) identifier() string { return fmt.Sprintf("%s/%s", v.apiGroup, v.apiVersion) }
+
+func init() {
+ klog.InitFlags(nil)
+ flag.Set("alsologtostderr", "true") // for klog
+ flag.Parse()
+
+ if *flConfig == "" {
+ panic("-config not specified")
+ }
+ if *flAPIDir == "" {
+ panic("-api-dir not specified")
+ }
+ if *flHTTPAddr == "" && *flOutFile == "" {
+ panic("-out-file or -http-addr must be specified")
+ }
+ if *flHTTPAddr != "" && *flOutFile != "" {
+ panic("only -out-file or -http-addr can be specified")
+ }
+ if err := resolveTemplateDir(*flTemplateDir); err != nil {
+ panic(err)
+ }
+
+}
+
+func resolveTemplateDir(dir string) error {
+ path, err := filepath.Abs(dir)
+ if err != nil {
+ return err
+ }
+ if fi, err := os.Stat(path); err != nil {
+ return errors.Wrapf(err, "cannot read the %s directory", path)
+ } else if !fi.IsDir() {
+ return errors.Errorf("%s path is not a directory", path)
+ }
+ return nil
+}
+
+func main() {
+ defer klog.Flush()
+
+ f, err := os.Open(*flConfig)
+ if err != nil {
+ klog.Fatalf("failed to open config file: %+v", err)
+ }
+ d := json.NewDecoder(f)
+ d.DisallowUnknownFields()
+ var config generatorConfig
+ if err := d.Decode(&config); err != nil {
+ klog.Fatalf("failed to parse config file: %+v", err)
+ }
+
+ klog.Infof("parsing go packages in directory %s", *flAPIDir)
+ pkgs, unversionedPkgs, err := parseAPIPackages(*flAPIDir)
+ if err != nil {
+ klog.Fatal(err)
+ }
+ if len(pkgs) == 0 {
+ klog.Fatalf("no API packages found in %s", *flAPIDir)
+ }
+
+ var unversionedPkgNames []string
+ for _, uvp := range unversionedPkgs {
+ unversionedPkgNames = append(unversionedPkgNames, uvp.Path)
+ }
+ apiPackages, err := combineAPIPackages(pkgs, unversionedPkgNames)
+ if err != nil {
+ klog.Fatal(err)
+ }
+
+ unversionedAPIPackages, err := combineAPIPackages(unversionedPkgs, unversionedPkgNames)
+ if err != nil {
+ klog.Fatal(err)
+ }
+
+ mkOutput := func() (string, error) {
+ var b bytes.Buffer
+ err := render(&b, apiPackages, unversionedAPIPackages, config)
+ if err != nil {
+ return "", errors.Wrap(err, "failed to render the result")
+ }
+
+ // remove trailing whitespace from each html line for markdown renderers
+ s := regexp.MustCompile(`(?m)^\s+`).ReplaceAllString(b.String(), "")
+ return s, nil
+ }
+
+ if *flOutFile != "" {
+ dir := filepath.Dir(*flOutFile)
+ if err := os.MkdirAll(dir, 0755); err != nil {
+ klog.Fatalf("failed to create dir %s: %v", dir, err)
+ }
+ s, err := mkOutput()
+ if err != nil {
+ klog.Fatalf("failed: %+v", err)
+ }
+ if err := ioutil.WriteFile(*flOutFile, []byte(s), 0644); err != nil {
+ klog.Fatalf("failed to write to out file: %v", err)
+ }
+ klog.Infof("written to %s", *flOutFile)
+ }
+
+ if *flHTTPAddr != "" {
+ h := func(w http.ResponseWriter, r *http.Request) {
+ now := time.Now()
+ defer func() { klog.Infof("request took %v", time.Since(now)) }()
+ s, err := mkOutput()
+ if err != nil {
+ fmt.Fprintf(w, "error: %+v", err)
+ klog.Warningf("failed: %+v", err)
+ }
+ if _, err := fmt.Fprint(w, s); err != nil {
+ klog.Warningf("response write error: %v", err)
+ }
+ }
+ http.HandleFunc("/", h)
+ klog.Infof("server listening at %s", *flHTTPAddr)
+ klog.Fatal(http.ListenAndServe(*flHTTPAddr, nil))
+ }
+}
+
+// groupName extracts the "//+groupName" meta-comment from the specified
+// package's comments, or returns empty string if it cannot be found.
+func groupName(pkg *types.Package) string {
+ m := types.ExtractCommentTags("+", pkg.Comments)
+ v := m["groupName"]
+ if len(v) == 1 {
+ return v[0]
+ }
+ return ""
+}
+
+func parseAPIPackages(dir string) ([]*types.Package, []*types.Package, error) {
+ b := parser.New()
+ // the following will silently fail (turn on -v=4 to see logs)
+ if err := b.AddDirRecursive(*flAPIDir); err != nil {
+ return nil, nil, err
+ }
+ scan, err := b.FindTypes()
+ if err != nil {
+ return nil, nil, errors.Wrap(err, "failed to parse pkgs and types")
+ }
+ var unversionedPkgs []*types.Package
+ var pkgNames []string
+ for p := range scan {
+ pkg := scan[p]
+ klog.V(3).Infof("trying package=%v groupName=%s", p, groupName(pkg))
+
+ // Do not pick up packages that are in vendor/ as API packages. (This
+ // happened in knative/eventing-sources/vendor/..., where a package
+ // matched the pattern, but it didn't have a compatible import path).
+ if isVendorPackage(pkg) {
+ klog.V(3).Infof("package=%v coming from vendor/, ignoring.", p)
+ continue
+ }
+
+ if len(pkg.Types) > 0 && containsString(pkg.DocComments, docCommentIncludeUnversionedTypes) {
+ klog.Infof("including package=%s as an additional unversioned include", p)
+ unversionedPkgs = append(unversionedPkgs, pkg)
+ } else if groupName(pkg) != "" && len(pkg.Types) > 0 || containsString(pkg.DocComments, docCommentForceIncludes) {
+ klog.V(3).Infof("package=%v has groupName and has types", p)
+ pkgNames = append(pkgNames, p)
+ }
+ }
+ sort.Strings(pkgNames)
+ var pkgs []*types.Package
+ for _, p := range pkgNames {
+ klog.Infof("using package=%s", p)
+ pkgs = append(pkgs, scan[p])
+ }
+ return pkgs, unversionedPkgs, nil
+}
+
+func containsString(sl []string, str string) bool {
+ for _, s := range sl {
+ if str == s {
+ return true
+ }
+ }
+ return false
+}
+
+// combineAPIPackages groups the Go packages by the they
+// offer, and combines the types in them.
+func combineAPIPackages(pkgs []*types.Package, unversionedPkgNames []string) ([]*apiPackage, error) {
+ pkgMap := make(map[string]*apiPackage)
+ var pkgIds []string
+
+ flattenTypes := func(typeMap map[string]*types.Type) []*types.Type {
+ typeList := make([]*types.Type, 0, len(typeMap))
+
+ for _, t := range typeMap {
+ typeList = append(typeList, t)
+ }
+
+ return typeList
+ }
+
+ for _, pkg := range pkgs {
+ apiGroup, apiVersion, err := apiVersionForPackage(pkg, unversionedPkgNames)
+ if err != nil {
+ return nil, errors.Wrapf(err, "could not get apiVersion for package %s", pkg.Path)
+ }
+
+ typeList := make([]*types.Type, 0, len(pkg.Types))
+ for _, t := range pkg.Types {
+ typeList = append(typeList, t)
+ }
+
+ id := fmt.Sprintf("%s/%s", apiGroup, apiVersion)
+ v, ok := pkgMap[id]
+ if !ok {
+ pkgMap[id] = &apiPackage{
+ apiGroup: apiGroup,
+ apiVersion: apiVersion,
+ Types: flattenTypes(pkg.Types),
+ Constants: flattenTypes(pkg.Constants),
+ GoPackages: []*types.Package{pkg},
+ }
+ pkgIds = append(pkgIds, id)
+ } else {
+ v.Types = append(v.Types, flattenTypes(pkg.Types)...)
+ v.Constants = append(v.Types, flattenTypes(pkg.Constants)...)
+ v.GoPackages = append(v.GoPackages, pkg)
+ }
+ }
+
+ sort.Sort(sort.StringSlice(pkgIds))
+
+ out := make([]*apiPackage, 0, len(pkgMap))
+ for _, id := range pkgIds {
+ out = append(out, pkgMap[id])
+ }
+ return out, nil
+}
+
+// isVendorPackage determines if package is coming from vendor/ dir.
+func isVendorPackage(pkg *types.Package) bool {
+ vendorPattern := string(os.PathSeparator) + "vendor" + string(os.PathSeparator)
+ return strings.Contains(pkg.SourcePath, vendorPattern)
+}
+
+func findTypeReferences(pkgs []*apiPackage) map[*types.Type][]*types.Type {
+ m := make(map[*types.Type][]*types.Type)
+ for _, pkg := range pkgs {
+ for _, typ := range pkg.Types {
+ for _, member := range typ.Members {
+ t := member.Type
+ t = tryDereference(t)
+ m[t] = append(m[t], typ)
+ }
+ }
+ }
+ return m
+}
+
+func isExportedType(t *types.Type) bool {
+ // TODO(ahmetb) use types.ExtractSingleBoolCommentTag() to parse +genclient
+ // https://godoc.org/k8s.io/gengo/types#ExtractCommentTags
+ return strings.Contains(strings.Join(t.SecondClosestCommentLines, "\n"), "+genclient")
+}
+
+func fieldName(m types.Member) string {
+ v := reflect.StructTag(m.Tags).Get("json")
+ v = strings.TrimSuffix(v, ",omitempty")
+ v = strings.TrimSuffix(v, ",inline")
+ if v != "" {
+ return v
+ }
+ return m.Name
+}
+
+func fieldEmbedded(m types.Member) bool {
+ return strings.Contains(reflect.StructTag(m.Tags).Get("json"), ",inline")
+}
+
+func isLocalType(t *types.Type, typePkgMap map[*types.Type]*apiPackage) bool {
+ t = tryDereference(t)
+ _, ok := typePkgMap[t]
+ return ok
+}
+
+func renderComments(s []string, markdown bool) string {
+ s = filterCommentTags(s)
+ doc := strings.Join(s, "\n")
+
+ if markdown {
+ // TODO(ahmetb): when a comment includes stuff like "http://"
+ // we treat this as a HTML tag with markdown renderer below. solve this.
+ return string(blackfriday.Run([]byte(doc)))
+ }
+ return nl2br(doc)
+}
+
+func safe(s string) template.HTML { return template.HTML(s) }
+
+func nl2br(s string) string {
+ return strings.Replace(s, "\n\n", string(template.HTML("
")), -1)
+}
+
+func hiddenMember(m types.Member, c generatorConfig) bool {
+ for _, v := range c.HiddenMemberFields {
+ if m.Name == v {
+ return true
+ }
+ }
+ return false
+}
+
+func typeIdentifier(t *types.Type) string {
+ t = tryDereference(t)
+ return t.Name.String() // {PackagePath.Name}
+}
+
+// apiGroupForType looks up apiGroup for the given type
+func apiGroupForType(t *types.Type, typePkgMap map[*types.Type]*apiPackage) string {
+ t = tryDereference(t)
+
+ v := typePkgMap[t]
+ if v == nil {
+ klog.Warningf("WARNING: cannot read apiVersion for %s from type=>pkg map", t.Name.String())
+ return ""
+ }
+
+ return v.identifier()
+}
+
+// anchorIDForLocalType returns the #anchor string for the local type
+func anchorIDForLocalType(t *types.Type, typePkgMap map[*types.Type]*apiPackage) string {
+ return fmt.Sprintf("%s.%s", apiGroupForType(t, typePkgMap), t.Name.Name)
+}
+
+// linkForType returns an anchor to the type if it can be generated. returns
+// empty string if it is not a local type or unrecognized external type.
+func linkForType(t *types.Type, c generatorConfig, typePkgMap map[*types.Type]*apiPackage) (string, error) {
+ t = tryDereference(t) // dereference kind=Pointer
+
+ if isLocalType(t, typePkgMap) {
+ return "#" + anchorIDForLocalType(t, typePkgMap), nil
+ }
+
+ var arrIndex = func(a []string, i int) string {
+ return a[(len(a)+i)%len(a)]
+ }
+
+ // types like k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta,
+ // k8s.io/api/core/v1.Container, k8s.io/api/autoscaling/v1.CrossVersionObjectReference,
+ // github.com/knative/build/pkg/apis/build/v1alpha1.BuildSpec
+ if t.Kind == types.Struct || t.Kind == types.Pointer || t.Kind == types.Interface || t.Kind == types.Alias {
+ id := typeIdentifier(t) // gives {{ImportPath.Identifier}} for type
+ segments := strings.Split(t.Name.Package, "/") // to parse [meta, v1] from "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+ for _, v := range c.ExternalPackages {
+ r, err := regexp.Compile(v.TypeMatchPrefix)
+ if err != nil {
+ return "", errors.Wrapf(err, "pattern %q failed to compile", v.TypeMatchPrefix)
+ }
+ if r.MatchString(id) {
+ tpl, err := texttemplate.New("").Funcs(map[string]interface{}{
+ "lower": strings.ToLower,
+ "arrIndex": arrIndex,
+ }).Parse(v.DocsURLTemplate)
+ if err != nil {
+ return "", errors.Wrap(err, "docs URL template failed to parse")
+ }
+
+ var b bytes.Buffer
+ if err := tpl.
+ Execute(&b, map[string]interface{}{
+ "TypeIdentifier": t.Name.Name,
+ "PackagePath": t.Name.Package,
+ "PackageSegments": segments,
+ }); err != nil {
+ return "", errors.Wrap(err, "docs url template execution error")
+ }
+ return b.String(), nil
+ }
+ }
+ klog.Warningf("not found external link source for type %v", t.Name)
+ }
+ return "", nil
+}
+
+// tryDereference returns the underlying type when t is a pointer, map, or slice.
+func tryDereference(t *types.Type) *types.Type {
+ for t.Elem != nil {
+ t = t.Elem
+ }
+ return t
+}
+
+// finalUnderlyingTypeOf walks the type hierarchy for t and returns
+// its base type (i.e. the type that has no further underlying type).
+func finalUnderlyingTypeOf(t *types.Type) *types.Type {
+ for {
+ if t.Underlying == nil {
+ return t
+ }
+
+ t = t.Underlying
+ }
+}
+
+func typeDisplayName(t *types.Type, c generatorConfig, typePkgMap map[*types.Type]*apiPackage) string {
+ s := typeIdentifier(t)
+
+ if isLocalType(t, typePkgMap) {
+ s = tryDereference(t).Name.Name
+ }
+
+ if t.Kind == types.Pointer {
+ s = strings.TrimLeft(s, "*")
+ }
+
+ switch t.Kind {
+ case types.Struct,
+ types.Interface,
+ types.Alias,
+ types.Pointer,
+ types.Slice,
+ types.Builtin:
+ // noop
+ case types.Map:
+ // return original name
+ return t.Name.Name
+ case types.DeclarationOf:
+ // For constants, we want to display the value
+ // rather than the name of the constant, since the
+ // value is what users will need to write into YAML
+ // specs.
+ if t.ConstValue != nil {
+ u := finalUnderlyingTypeOf(t)
+ // Quote string constants to make it clear to the documentation reader.
+ if u.Kind == types.Builtin && u.Name.Name == "string" {
+ return strconv.Quote(*t.ConstValue)
+ }
+
+ return *t.ConstValue
+ }
+ klog.Fatalf("type %s is a non-const declaration, which is unhandled", t.Name)
+ default:
+ klog.Fatalf("type %s has kind=%v which is unhandled", t.Name, t.Kind)
+ }
+
+ // substitute prefix, if registered
+ for prefix, replacement := range c.TypeDisplayNamePrefixOverrides {
+ if strings.HasPrefix(s, prefix) {
+ s = strings.Replace(s, prefix, replacement, 1)
+ }
+ }
+
+ if t.Kind == types.Slice {
+ s = "[]" + s
+ }
+
+ return s
+}
+
+func hideType(t *types.Type, c generatorConfig) bool {
+ for _, pattern := range c.HideTypePatterns {
+ if regexp.MustCompile(pattern).MatchString(t.Name.String()) {
+ return true
+ }
+ }
+ if !isExportedType(t) && unicode.IsLower(rune(t.Name.Name[0])) {
+ // types that start with lowercase
+ return true
+ }
+ return false
+}
+
+func typeReferences(t *types.Type, c generatorConfig, references map[*types.Type][]*types.Type) []*types.Type {
+ var out []*types.Type
+ m := make(map[*types.Type]struct{})
+ for _, ref := range references[t] {
+ if !hideType(ref, c) {
+ m[ref] = struct{}{}
+ }
+ }
+ for k := range m {
+ out = append(out, k)
+ }
+ sortTypes(out)
+ return out
+}
+
+func sortTypes(typs []*types.Type) []*types.Type {
+ sort.Slice(typs, func(i, j int) bool {
+ t1, t2 := typs[i], typs[j]
+ if isExportedType(t1) && !isExportedType(t2) {
+ return true
+ } else if !isExportedType(t1) && isExportedType(t2) {
+ return false
+ }
+ return t1.Name.String() < t2.Name.String()
+ })
+ return typs
+}
+
+func visibleTypes(in []*types.Type, c generatorConfig) []*types.Type {
+ var out []*types.Type
+ for _, t := range in {
+ if !hideType(t, c) {
+ out = append(out, t)
+ }
+ }
+ return out
+}
+
+func packageDisplayName(pkg *types.Package, apiVersions map[string]string) string {
+ apiGroupVersion, ok := apiVersions[pkg.Path]
+ if ok {
+ return apiGroupVersion
+ }
+ return pkg.Path // go import path
+}
+
+func filterCommentTags(comments []string) []string {
+ var out []string
+ for _, v := range comments {
+ if !strings.HasPrefix(strings.TrimSpace(v), "+") {
+ out = append(out, v)
+ }
+ }
+ return out
+}
+
+func isOptionalMember(m types.Member) bool {
+ tags := types.ExtractCommentTags("+", m.CommentLines)
+ _, ok := tags["optional"]
+ return ok
+}
+
+func apiVersionForPackage(pkg *types.Package, unversionedPkgNames []string) (string, string, error) {
+ group := groupName(pkg)
+ for _, upn := range unversionedPkgNames {
+ if upn == pkg.Path {
+ return group, "unversioned", nil
+ }
+ }
+ version := pkg.Name // assumes basename (i.e. "v1" in "core/v1") is apiVersion
+ r := `^v\d+((alpha|beta)\d+)?$`
+ if !regexp.MustCompile(r).MatchString(version) {
+ return "", "", errors.Errorf("cannot infer kubernetes apiVersion of go package %s (basename %q doesn't match expected pattern %s that's used to determine apiVersion)", pkg.Path, version, r)
+ }
+ return group, version, nil
+}
+
+// extractTypeToPackageMap creates a *types.Type map to apiPackage
+func extractTypeToPackageMap(pkgs []*apiPackage) map[*types.Type]*apiPackage {
+ out := make(map[*types.Type]*apiPackage)
+ for _, ap := range pkgs {
+ for _, t := range ap.Types {
+ out[t] = ap
+ }
+ for _, t := range ap.Constants {
+ out[t] = ap
+ }
+ }
+ return out
+}
+
+// packageMapToList flattens the map.
+func packageMapToList(pkgs map[string]*apiPackage) []*apiPackage {
+ // TODO(ahmetb): we should probably not deal with maps, this type can be
+ // a list everywhere.
+ out := make([]*apiPackage, 0, len(pkgs))
+ for _, v := range pkgs {
+ out = append(out, v)
+ }
+ return out
+}
+
+// constantsOfType finds all the constants in pkg that have the
+// same underlying type as t. This is intended for use by enum
+// type validation, where users need to specify one of a specific
+// set of constant values for a field.
+func constantsOfType(t *types.Type, pkg *apiPackage) []*types.Type {
+ constants := []*types.Type{}
+
+ for _, c := range pkg.Constants {
+ if c.Underlying == t {
+ constants = append(constants, c)
+ }
+ }
+
+ return sortTypes(constants)
+}
+
+func render(w io.Writer, pkgs []*apiPackage, unversionedPkgs []*apiPackage, config generatorConfig) error {
+ references := findTypeReferences(append(pkgs, unversionedPkgs...))
+ typePkgMap := extractTypeToPackageMap(append(pkgs, unversionedPkgs...))
+
+ t, err := template.New("").Funcs(map[string]interface{}{
+ "isExportedType": isExportedType,
+ "fieldName": fieldName,
+ "fieldEmbedded": fieldEmbedded,
+ "typeIdentifier": func(t *types.Type) string { return typeIdentifier(t) },
+ "typeDisplayName": func(t *types.Type) string { return typeDisplayName(t, config, typePkgMap) },
+ "visibleTypes": func(t []*types.Type) []*types.Type { return visibleTypes(t, config) },
+ "renderComments": func(s []string) string { return renderComments(s, !config.MarkdownDisabled) },
+ "packageDisplayName": func(p *apiPackage) string { return p.identifier() },
+ "apiGroup": func(t *types.Type) string { return apiGroupForType(t, typePkgMap) },
+ "packageAnchorID": func(p *apiPackage) string {
+ // TODO(ahmetb): currently this is the same as packageDisplayName
+ // func, and it's fine since it retuns valid DOM id strings like
+ // 'serving.knative.dev/v1alpha1' which is valid per HTML5, except
+ // spaces, so just trim those.
+ return strings.Replace(p.identifier(), " ", "", -1)
+ },
+ "linkForType": func(t *types.Type) string {
+ v, err := linkForType(t, config, typePkgMap)
+ if err != nil {
+ klog.Fatal(errors.Wrapf(err, "error getting link for type=%s", t.Name))
+ return ""
+ }
+ return v
+ },
+ "anchorIDForType": func(t *types.Type) string { return anchorIDForLocalType(t, typePkgMap) },
+ "safe": safe,
+ "sortedTypes": sortTypes,
+ "typeReferences": func(t *types.Type) []*types.Type { return typeReferences(t, config, references) },
+ "hiddenMember": func(m types.Member) bool { return hiddenMember(m, config) },
+ "isLocalType": isLocalType,
+ "isOptionalMember": isOptionalMember,
+ "constantsOfType": func(t *types.Type) []*types.Type { return constantsOfType(t, typePkgMap[t]) },
+ }).ParseGlob(filepath.Join(*flTemplateDir, "*.tpl"))
+ if err != nil {
+ return errors.Wrap(err, "parse error")
+ }
+
+ var gitCommit []byte
+ if !config.GitCommitDisabled {
+ gitCommit, _ = exec.Command("git", "rev-parse", "--short", "HEAD").Output()
+ }
+
+ return errors.Wrap(t.ExecuteTemplate(w, "packages", map[string]interface{}{
+ "packages": pkgs,
+ "config": config,
+ "gitCommit": strings.TrimSpace(string(gitCommit)),
+ }), "template execution error")
+}
diff --git a/vendor/github.com/russross/blackfriday/v2/.gitignore b/vendor/github.com/russross/blackfriday/v2/.gitignore
new file mode 100644
index 00000000000..75623dcccbb
--- /dev/null
+++ b/vendor/github.com/russross/blackfriday/v2/.gitignore
@@ -0,0 +1,8 @@
+*.out
+*.swp
+*.8
+*.6
+_obj
+_test*
+markdown
+tags
diff --git a/vendor/github.com/russross/blackfriday/v2/.travis.yml b/vendor/github.com/russross/blackfriday/v2/.travis.yml
new file mode 100644
index 00000000000..b0b525a5a8e
--- /dev/null
+++ b/vendor/github.com/russross/blackfriday/v2/.travis.yml
@@ -0,0 +1,17 @@
+sudo: false
+language: go
+go:
+ - "1.10.x"
+ - "1.11.x"
+ - tip
+matrix:
+ fast_finish: true
+ allow_failures:
+ - go: tip
+install:
+ - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step).
+script:
+ - go get -t -v ./...
+ - diff -u <(echo -n) <(gofmt -d -s .)
+ - go tool vet .
+ - go test -v ./...
diff --git a/vendor/github.com/russross/blackfriday/v2/LICENSE.txt b/vendor/github.com/russross/blackfriday/v2/LICENSE.txt
new file mode 100644
index 00000000000..2885af3602d
--- /dev/null
+++ b/vendor/github.com/russross/blackfriday/v2/LICENSE.txt
@@ -0,0 +1,29 @@
+Blackfriday is distributed under the Simplified BSD License:
+
+> Copyright © 2011 Russ Ross
+> All rights reserved.
+>
+> Redistribution and use in source and binary forms, with or without
+> modification, are permitted provided that the following conditions
+> are met:
+>
+> 1. Redistributions of source code must retain the above copyright
+> notice, this list of conditions and the following disclaimer.
+>
+> 2. Redistributions in binary form must reproduce the above
+> copyright notice, this list of conditions and the following
+> disclaimer in the documentation and/or other materials provided with
+> the distribution.
+>
+> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+> "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+> LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+> FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+> COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+> INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+> BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+> LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+> CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+> LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+> ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+> POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/russross/blackfriday/v2/README.md b/vendor/github.com/russross/blackfriday/v2/README.md
new file mode 100644
index 00000000000..d9c08a22fc5
--- /dev/null
+++ b/vendor/github.com/russross/blackfriday/v2/README.md
@@ -0,0 +1,335 @@
+Blackfriday
+[![Build Status][BuildV2SVG]][BuildV2URL]
+[![PkgGoDev][PkgGoDevV2SVG]][PkgGoDevV2URL]
+===========
+
+Blackfriday is a [Markdown][1] processor implemented in [Go][2]. It
+is paranoid about its input (so you can safely feed it user-supplied
+data), it is fast, it supports common extensions (tables, smart
+punctuation substitutions, etc.), and it is safe for all utf-8
+(unicode) input.
+
+HTML output is currently supported, along with Smartypants
+extensions.
+
+It started as a translation from C of [Sundown][3].
+
+
+Installation
+------------
+
+Blackfriday is compatible with modern Go releases in module mode.
+With Go installed:
+
+ go get github.com/russross/blackfriday/v2
+
+will resolve and add the package to the current development module,
+then build and install it. Alternatively, you can achieve the same
+if you import it in a package:
+
+ import "github.com/russross/blackfriday/v2"
+
+and `go get` without parameters.
+
+Legacy GOPATH mode is unsupported.
+
+
+Versions
+--------
+
+Currently maintained and recommended version of Blackfriday is `v2`. It's being
+developed on its own branch: https://github.com/russross/blackfriday/tree/v2 and the
+documentation is available at
+https://pkg.go.dev/github.com/russross/blackfriday/v2.
+
+It is `go get`-able in module mode at `github.com/russross/blackfriday/v2`.
+
+Version 2 offers a number of improvements over v1:
+
+* Cleaned up API
+* A separate call to [`Parse`][4], which produces an abstract syntax tree for
+ the document
+* Latest bug fixes
+* Flexibility to easily add your own rendering extensions
+
+Potential drawbacks:
+
+* Our benchmarks show v2 to be slightly slower than v1. Currently in the
+ ballpark of around 15%.
+* API breakage. If you can't afford modifying your code to adhere to the new API
+ and don't care too much about the new features, v2 is probably not for you.
+* Several bug fixes are trailing behind and still need to be forward-ported to
+ v2. See issue [#348](https://github.com/russross/blackfriday/issues/348) for
+ tracking.
+
+If you are still interested in the legacy `v1`, you can import it from
+`github.com/russross/blackfriday`. Documentation for the legacy v1 can be found
+here: https://pkg.go.dev/github.com/russross/blackfriday.
+
+
+Usage
+-----
+
+For the most sensible markdown processing, it is as simple as getting your input
+into a byte slice and calling:
+
+```go
+output := blackfriday.Run(input)
+```
+
+Your input will be parsed and the output rendered with a set of most popular
+extensions enabled. If you want the most basic feature set, corresponding with
+the bare Markdown specification, use:
+
+```go
+output := blackfriday.Run(input, blackfriday.WithNoExtensions())
+```
+
+### Sanitize untrusted content
+
+Blackfriday itself does nothing to protect against malicious content. If you are
+dealing with user-supplied markdown, we recommend running Blackfriday's output
+through HTML sanitizer such as [Bluemonday][5].
+
+Here's an example of simple usage of Blackfriday together with Bluemonday:
+
+```go
+import (
+ "github.com/microcosm-cc/bluemonday"
+ "github.com/russross/blackfriday/v2"
+)
+
+// ...
+unsafe := blackfriday.Run(input)
+html := bluemonday.UGCPolicy().SanitizeBytes(unsafe)
+```
+
+### Custom options
+
+If you want to customize the set of options, use `blackfriday.WithExtensions`,
+`blackfriday.WithRenderer` and `blackfriday.WithRefOverride`.
+
+### `blackfriday-tool`
+
+You can also check out `blackfriday-tool` for a more complete example
+of how to use it. Download and install it using:
+
+ go get github.com/russross/blackfriday-tool
+
+This is a simple command-line tool that allows you to process a
+markdown file using a standalone program. You can also browse the
+source directly on github if you are just looking for some example
+code:
+
+*
+
+Note that if you have not already done so, installing
+`blackfriday-tool` will be sufficient to download and install
+blackfriday in addition to the tool itself. The tool binary will be
+installed in `$GOPATH/bin`. This is a statically-linked binary that
+can be copied to wherever you need it without worrying about
+dependencies and library versions.
+
+### Sanitized anchor names
+
+Blackfriday includes an algorithm for creating sanitized anchor names
+corresponding to a given input text. This algorithm is used to create
+anchors for headings when `AutoHeadingIDs` extension is enabled. The
+algorithm has a specification, so that other packages can create
+compatible anchor names and links to those anchors.
+
+The specification is located at https://pkg.go.dev/github.com/russross/blackfriday/v2#hdr-Sanitized_Anchor_Names.
+
+[`SanitizedAnchorName`](https://pkg.go.dev/github.com/russross/blackfriday/v2#SanitizedAnchorName) exposes this functionality, and can be used to
+create compatible links to the anchor names generated by blackfriday.
+This algorithm is also implemented in a small standalone package at
+[`github.com/shurcooL/sanitized_anchor_name`](https://pkg.go.dev/github.com/shurcooL/sanitized_anchor_name). It can be useful for clients
+that want a small package and don't need full functionality of blackfriday.
+
+
+Features
+--------
+
+All features of Sundown are supported, including:
+
+* **Compatibility**. The Markdown v1.0.3 test suite passes with
+ the `--tidy` option. Without `--tidy`, the differences are
+ mostly in whitespace and entity escaping, where blackfriday is
+ more consistent and cleaner.
+
+* **Common extensions**, including table support, fenced code
+ blocks, autolinks, strikethroughs, non-strict emphasis, etc.
+
+* **Safety**. Blackfriday is paranoid when parsing, making it safe
+ to feed untrusted user input without fear of bad things
+ happening. The test suite stress tests this and there are no
+ known inputs that make it crash. If you find one, please let me
+ know and send me the input that does it.
+
+ NOTE: "safety" in this context means *runtime safety only*. In order to
+ protect yourself against JavaScript injection in untrusted content, see
+ [this example](https://github.com/russross/blackfriday#sanitize-untrusted-content).
+
+* **Fast processing**. It is fast enough to render on-demand in
+ most web applications without having to cache the output.
+
+* **Thread safety**. You can run multiple parsers in different
+ goroutines without ill effect. There is no dependence on global
+ shared state.
+
+* **Minimal dependencies**. Blackfriday only depends on standard
+ library packages in Go. The source code is pretty
+ self-contained, so it is easy to add to any project, including
+ Google App Engine projects.
+
+* **Standards compliant**. Output successfully validates using the
+ W3C validation tool for HTML 4.01 and XHTML 1.0 Transitional.
+
+
+Extensions
+----------
+
+In addition to the standard markdown syntax, this package
+implements the following extensions:
+
+* **Intra-word emphasis supression**. The `_` character is
+ commonly used inside words when discussing code, so having
+ markdown interpret it as an emphasis command is usually the
+ wrong thing. Blackfriday lets you treat all emphasis markers as
+ normal characters when they occur inside a word.
+
+* **Tables**. Tables can be created by drawing them in the input
+ using a simple syntax:
+
+ ```
+ Name | Age
+ --------|------
+ Bob | 27
+ Alice | 23
+ ```
+
+* **Fenced code blocks**. In addition to the normal 4-space
+ indentation to mark code blocks, you can explicitly mark them
+ and supply a language (to make syntax highlighting simple). Just
+ mark it like this:
+
+ ```go
+ func getTrue() bool {
+ return true
+ }
+ ```
+
+ You can use 3 or more backticks to mark the beginning of the
+ block, and the same number to mark the end of the block.
+
+ To preserve classes of fenced code blocks while using the bluemonday
+ HTML sanitizer, use the following policy:
+
+ ```go
+ p := bluemonday.UGCPolicy()
+ p.AllowAttrs("class").Matching(regexp.MustCompile("^language-[a-zA-Z0-9]+$")).OnElements("code")
+ html := p.SanitizeBytes(unsafe)
+ ```
+
+* **Definition lists**. A simple definition list is made of a single-line
+ term followed by a colon and the definition for that term.
+
+ Cat
+ : Fluffy animal everyone likes
+
+ Internet
+ : Vector of transmission for pictures of cats
+
+ Terms must be separated from the previous definition by a blank line.
+
+* **Footnotes**. A marker in the text that will become a superscript number;
+ a footnote definition that will be placed in a list of footnotes at the
+ end of the document. A footnote looks like this:
+
+ This is a footnote.[^1]
+
+ [^1]: the footnote text.
+
+* **Autolinking**. Blackfriday can find URLs that have not been
+ explicitly marked as links and turn them into links.
+
+* **Strikethrough**. Use two tildes (`~~`) to mark text that
+ should be crossed out.
+
+* **Hard line breaks**. With this extension enabled newlines in the input
+ translate into line breaks in the output. This extension is off by default.
+
+* **Smart quotes**. Smartypants-style punctuation substitution is
+ supported, turning normal double- and single-quote marks into
+ curly quotes, etc.
+
+* **LaTeX-style dash parsing** is an additional option, where `--`
+ is translated into `–`, and `---` is translated into
+ `—`. This differs from most smartypants processors, which
+ turn a single hyphen into an ndash and a double hyphen into an
+ mdash.
+
+* **Smart fractions**, where anything that looks like a fraction
+ is translated into suitable HTML (instead of just a few special
+ cases like most smartypant processors). For example, `4/5`
+ becomes `4⁄5`, which renders as
+ 4⁄5.
+
+
+Other renderers
+---------------
+
+Blackfriday is structured to allow alternative rendering engines. Here
+are a few of note:
+
+* [github_flavored_markdown](https://pkg.go.dev/github.com/shurcooL/github_flavored_markdown):
+ provides a GitHub Flavored Markdown renderer with fenced code block
+ highlighting, clickable heading anchor links.
+
+ It's not customizable, and its goal is to produce HTML output
+ equivalent to the [GitHub Markdown API endpoint](https://developer.github.com/v3/markdown/#render-a-markdown-document-in-raw-mode),
+ except the rendering is performed locally.
+
+* [markdownfmt](https://github.com/shurcooL/markdownfmt): like gofmt,
+ but for markdown.
+
+* [LaTeX output](https://gitlab.com/ambrevar/blackfriday-latex):
+ renders output as LaTeX.
+
+* [bfchroma](https://github.com/Depado/bfchroma/): provides convenience
+ integration with the [Chroma](https://github.com/alecthomas/chroma) code
+ highlighting library. bfchroma is only compatible with v2 of Blackfriday and
+ provides a drop-in renderer ready to use with Blackfriday, as well as
+ options and means for further customization.
+
+* [Blackfriday-Confluence](https://github.com/kentaro-m/blackfriday-confluence): provides a [Confluence Wiki Markup](https://confluence.atlassian.com/doc/confluence-wiki-markup-251003035.html) renderer.
+
+* [Blackfriday-Slack](https://github.com/karriereat/blackfriday-slack): converts markdown to slack message style
+
+
+TODO
+----
+
+* More unit testing
+* Improve Unicode support. It does not understand all Unicode
+ rules (about what constitutes a letter, a punctuation symbol,
+ etc.), so it may fail to detect word boundaries correctly in
+ some instances. It is safe on all UTF-8 input.
+
+
+License
+-------
+
+[Blackfriday is distributed under the Simplified BSD License](LICENSE.txt)
+
+
+ [1]: https://daringfireball.net/projects/markdown/ "Markdown"
+ [2]: https://golang.org/ "Go Language"
+ [3]: https://github.com/vmg/sundown "Sundown"
+ [4]: https://pkg.go.dev/github.com/russross/blackfriday/v2#Parse "Parse func"
+ [5]: https://github.com/microcosm-cc/bluemonday "Bluemonday"
+
+ [BuildV2SVG]: https://travis-ci.org/russross/blackfriday.svg?branch=v2
+ [BuildV2URL]: https://travis-ci.org/russross/blackfriday
+ [PkgGoDevV2SVG]: https://pkg.go.dev/badge/github.com/russross/blackfriday/v2
+ [PkgGoDevV2URL]: https://pkg.go.dev/github.com/russross/blackfriday/v2
diff --git a/vendor/github.com/russross/blackfriday/v2/block.go b/vendor/github.com/russross/blackfriday/v2/block.go
new file mode 100644
index 00000000000..dcd61e6e35b
--- /dev/null
+++ b/vendor/github.com/russross/blackfriday/v2/block.go
@@ -0,0 +1,1612 @@
+//
+// Blackfriday Markdown Processor
+// Available at http://github.com/russross/blackfriday
+//
+// Copyright © 2011 Russ Ross .
+// Distributed under the Simplified BSD License.
+// See README.md for details.
+//
+
+//
+// Functions to parse block-level elements.
+//
+
+package blackfriday
+
+import (
+ "bytes"
+ "html"
+ "regexp"
+ "strings"
+ "unicode"
+)
+
+const (
+ charEntity = "&(?:#x[a-f0-9]{1,8}|#[0-9]{1,8}|[a-z][a-z0-9]{1,31});"
+ escapable = "[!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]"
+)
+
+var (
+ reBackslashOrAmp = regexp.MustCompile("[\\&]")
+ reEntityOrEscapedChar = regexp.MustCompile("(?i)\\\\" + escapable + "|" + charEntity)
+)
+
+// Parse block-level data.
+// Note: this function and many that it calls assume that
+// the input buffer ends with a newline.
+func (p *Markdown) block(data []byte) {
+ // this is called recursively: enforce a maximum depth
+ if p.nesting >= p.maxNesting {
+ return
+ }
+ p.nesting++
+
+ // parse out one block-level construct at a time
+ for len(data) > 0 {
+ // prefixed heading:
+ //
+ // # Heading 1
+ // ## Heading 2
+ // ...
+ // ###### Heading 6
+ if p.isPrefixHeading(data) {
+ data = data[p.prefixHeading(data):]
+ continue
+ }
+
+ // block of preformatted HTML:
+ //
+ //
+ // ...
+ //
+ if data[0] == '<' {
+ if i := p.html(data, true); i > 0 {
+ data = data[i:]
+ continue
+ }
+ }
+
+ // title block
+ //
+ // % stuff
+ // % more stuff
+ // % even more stuff
+ if p.extensions&Titleblock != 0 {
+ if data[0] == '%' {
+ if i := p.titleBlock(data, true); i > 0 {
+ data = data[i:]
+ continue
+ }
+ }
+ }
+
+ // blank lines. note: returns the # of bytes to skip
+ if i := p.isEmpty(data); i > 0 {
+ data = data[i:]
+ continue
+ }
+
+ // indented code block:
+ //
+ // func max(a, b int) int {
+ // if a > b {
+ // return a
+ // }
+ // return b
+ // }
+ if p.codePrefix(data) > 0 {
+ data = data[p.code(data):]
+ continue
+ }
+
+ // fenced code block:
+ //
+ // ``` go
+ // func fact(n int) int {
+ // if n <= 1 {
+ // return n
+ // }
+ // return n * fact(n-1)
+ // }
+ // ```
+ if p.extensions&FencedCode != 0 {
+ if i := p.fencedCodeBlock(data, true); i > 0 {
+ data = data[i:]
+ continue
+ }
+ }
+
+ // horizontal rule:
+ //
+ // ------
+ // or
+ // ******
+ // or
+ // ______
+ if p.isHRule(data) {
+ p.addBlock(HorizontalRule, nil)
+ var i int
+ for i = 0; i < len(data) && data[i] != '\n'; i++ {
+ }
+ data = data[i:]
+ continue
+ }
+
+ // block quote:
+ //
+ // > A big quote I found somewhere
+ // > on the web
+ if p.quotePrefix(data) > 0 {
+ data = data[p.quote(data):]
+ continue
+ }
+
+ // table:
+ //
+ // Name | Age | Phone
+ // ------|-----|---------
+ // Bob | 31 | 555-1234
+ // Alice | 27 | 555-4321
+ if p.extensions&Tables != 0 {
+ if i := p.table(data); i > 0 {
+ data = data[i:]
+ continue
+ }
+ }
+
+ // an itemized/unordered list:
+ //
+ // * Item 1
+ // * Item 2
+ //
+ // also works with + or -
+ if p.uliPrefix(data) > 0 {
+ data = data[p.list(data, 0):]
+ continue
+ }
+
+ // a numbered/ordered list:
+ //
+ // 1. Item 1
+ // 2. Item 2
+ if p.oliPrefix(data) > 0 {
+ data = data[p.list(data, ListTypeOrdered):]
+ continue
+ }
+
+ // definition lists:
+ //
+ // Term 1
+ // : Definition a
+ // : Definition b
+ //
+ // Term 2
+ // : Definition c
+ if p.extensions&DefinitionLists != 0 {
+ if p.dliPrefix(data) > 0 {
+ data = data[p.list(data, ListTypeDefinition):]
+ continue
+ }
+ }
+
+ // anything else must look like a normal paragraph
+ // note: this finds underlined headings, too
+ data = data[p.paragraph(data):]
+ }
+
+ p.nesting--
+}
+
+func (p *Markdown) addBlock(typ NodeType, content []byte) *Node {
+ p.closeUnmatchedBlocks()
+ container := p.addChild(typ, 0)
+ container.content = content
+ return container
+}
+
+func (p *Markdown) isPrefixHeading(data []byte) bool {
+ if data[0] != '#' {
+ return false
+ }
+
+ if p.extensions&SpaceHeadings != 0 {
+ level := 0
+ for level < 6 && level < len(data) && data[level] == '#' {
+ level++
+ }
+ if level == len(data) || data[level] != ' ' {
+ return false
+ }
+ }
+ return true
+}
+
+func (p *Markdown) prefixHeading(data []byte) int {
+ level := 0
+ for level < 6 && level < len(data) && data[level] == '#' {
+ level++
+ }
+ i := skipChar(data, level, ' ')
+ end := skipUntilChar(data, i, '\n')
+ skip := end
+ id := ""
+ if p.extensions&HeadingIDs != 0 {
+ j, k := 0, 0
+ // find start/end of heading id
+ for j = i; j < end-1 && (data[j] != '{' || data[j+1] != '#'); j++ {
+ }
+ for k = j + 1; k < end && data[k] != '}'; k++ {
+ }
+ // extract heading id iff found
+ if j < end && k < end {
+ id = string(data[j+2 : k])
+ end = j
+ skip = k + 1
+ for end > 0 && data[end-1] == ' ' {
+ end--
+ }
+ }
+ }
+ for end > 0 && data[end-1] == '#' {
+ if isBackslashEscaped(data, end-1) {
+ break
+ }
+ end--
+ }
+ for end > 0 && data[end-1] == ' ' {
+ end--
+ }
+ if end > i {
+ if id == "" && p.extensions&AutoHeadingIDs != 0 {
+ id = SanitizedAnchorName(string(data[i:end]))
+ }
+ block := p.addBlock(Heading, data[i:end])
+ block.HeadingID = id
+ block.Level = level
+ }
+ return skip
+}
+
+func (p *Markdown) isUnderlinedHeading(data []byte) int {
+ // test of level 1 heading
+ if data[0] == '=' {
+ i := skipChar(data, 1, '=')
+ i = skipChar(data, i, ' ')
+ if i < len(data) && data[i] == '\n' {
+ return 1
+ }
+ return 0
+ }
+
+ // test of level 2 heading
+ if data[0] == '-' {
+ i := skipChar(data, 1, '-')
+ i = skipChar(data, i, ' ')
+ if i < len(data) && data[i] == '\n' {
+ return 2
+ }
+ return 0
+ }
+
+ return 0
+}
+
+func (p *Markdown) titleBlock(data []byte, doRender bool) int {
+ if data[0] != '%' {
+ return 0
+ }
+ splitData := bytes.Split(data, []byte("\n"))
+ var i int
+ for idx, b := range splitData {
+ if !bytes.HasPrefix(b, []byte("%")) {
+ i = idx // - 1
+ break
+ }
+ }
+
+ data = bytes.Join(splitData[0:i], []byte("\n"))
+ consumed := len(data)
+ data = bytes.TrimPrefix(data, []byte("% "))
+ data = bytes.Replace(data, []byte("\n% "), []byte("\n"), -1)
+ block := p.addBlock(Heading, data)
+ block.Level = 1
+ block.IsTitleblock = true
+
+ return consumed
+}
+
+func (p *Markdown) html(data []byte, doRender bool) int {
+ var i, j int
+
+ // identify the opening tag
+ if data[0] != '<' {
+ return 0
+ }
+ curtag, tagfound := p.htmlFindTag(data[1:])
+
+ // handle special cases
+ if !tagfound {
+ // check for an HTML comment
+ if size := p.htmlComment(data, doRender); size > 0 {
+ return size
+ }
+
+ // check for an
tag
+ if size := p.htmlHr(data, doRender); size > 0 {
+ return size
+ }
+
+ // no special case recognized
+ return 0
+ }
+
+ // look for an unindented matching closing tag
+ // followed by a blank line
+ found := false
+ /*
+ closetag := []byte("\n" + curtag + ">")
+ j = len(curtag) + 1
+ for !found {
+ // scan for a closing tag at the beginning of a line
+ if skip := bytes.Index(data[j:], closetag); skip >= 0 {
+ j += skip + len(closetag)
+ } else {
+ break
+ }
+
+ // see if it is the only thing on the line
+ if skip := p.isEmpty(data[j:]); skip > 0 {
+ // see if it is followed by a blank line/eof
+ j += skip
+ if j >= len(data) {
+ found = true
+ i = j
+ } else {
+ if skip := p.isEmpty(data[j:]); skip > 0 {
+ j += skip
+ found = true
+ i = j
+ }
+ }
+ }
+ }
+ */
+
+ // if not found, try a second pass looking for indented match
+ // but not if tag is "ins" or "del" (following original Markdown.pl)
+ if !found && curtag != "ins" && curtag != "del" {
+ i = 1
+ for i < len(data) {
+ i++
+ for i < len(data) && !(data[i-1] == '<' && data[i] == '/') {
+ i++
+ }
+
+ if i+2+len(curtag) >= len(data) {
+ break
+ }
+
+ j = p.htmlFindEnd(curtag, data[i-1:])
+
+ if j > 0 {
+ i += j - 1
+ found = true
+ break
+ }
+ }
+ }
+
+ if !found {
+ return 0
+ }
+
+ // the end of the block has been found
+ if doRender {
+ // trim newlines
+ end := i
+ for end > 0 && data[end-1] == '\n' {
+ end--
+ }
+ finalizeHTMLBlock(p.addBlock(HTMLBlock, data[:end]))
+ }
+
+ return i
+}
+
+func finalizeHTMLBlock(block *Node) {
+ block.Literal = block.content
+ block.content = nil
+}
+
+// HTML comment, lax form
+func (p *Markdown) htmlComment(data []byte, doRender bool) int {
+ i := p.inlineHTMLComment(data)
+ // needs to end with a blank line
+ if j := p.isEmpty(data[i:]); j > 0 {
+ size := i + j
+ if doRender {
+ // trim trailing newlines
+ end := size
+ for end > 0 && data[end-1] == '\n' {
+ end--
+ }
+ block := p.addBlock(HTMLBlock, data[:end])
+ finalizeHTMLBlock(block)
+ }
+ return size
+ }
+ return 0
+}
+
+// HR, which is the only self-closing block tag considered
+func (p *Markdown) htmlHr(data []byte, doRender bool) int {
+ if len(data) < 4 {
+ return 0
+ }
+ if data[0] != '<' || (data[1] != 'h' && data[1] != 'H') || (data[2] != 'r' && data[2] != 'R') {
+ return 0
+ }
+ if data[3] != ' ' && data[3] != '/' && data[3] != '>' {
+ // not an
tag after all; at least not a valid one
+ return 0
+ }
+ i := 3
+ for i < len(data) && data[i] != '>' && data[i] != '\n' {
+ i++
+ }
+ if i < len(data) && data[i] == '>' {
+ i++
+ if j := p.isEmpty(data[i:]); j > 0 {
+ size := i + j
+ if doRender {
+ // trim newlines
+ end := size
+ for end > 0 && data[end-1] == '\n' {
+ end--
+ }
+ finalizeHTMLBlock(p.addBlock(HTMLBlock, data[:end]))
+ }
+ return size
+ }
+ }
+ return 0
+}
+
+func (p *Markdown) htmlFindTag(data []byte) (string, bool) {
+ i := 0
+ for i < len(data) && isalnum(data[i]) {
+ i++
+ }
+ key := string(data[:i])
+ if _, ok := blockTags[key]; ok {
+ return key, true
+ }
+ return "", false
+}
+
+func (p *Markdown) htmlFindEnd(tag string, data []byte) int {
+ // assume data[0] == '<' && data[1] == '/' already tested
+ if tag == "hr" {
+ return 2
+ }
+ // check if tag is a match
+ closetag := []byte("" + tag + ">")
+ if !bytes.HasPrefix(data, closetag) {
+ return 0
+ }
+ i := len(closetag)
+
+ // check that the rest of the line is blank
+ skip := 0
+ if skip = p.isEmpty(data[i:]); skip == 0 {
+ return 0
+ }
+ i += skip
+ skip = 0
+
+ if i >= len(data) {
+ return i
+ }
+
+ if p.extensions&LaxHTMLBlocks != 0 {
+ return i
+ }
+ if skip = p.isEmpty(data[i:]); skip == 0 {
+ // following line must be blank
+ return 0
+ }
+
+ return i + skip
+}
+
+func (*Markdown) isEmpty(data []byte) int {
+ // it is okay to call isEmpty on an empty buffer
+ if len(data) == 0 {
+ return 0
+ }
+
+ var i int
+ for i = 0; i < len(data) && data[i] != '\n'; i++ {
+ if data[i] != ' ' && data[i] != '\t' {
+ return 0
+ }
+ }
+ if i < len(data) && data[i] == '\n' {
+ i++
+ }
+ return i
+}
+
+func (*Markdown) isHRule(data []byte) bool {
+ i := 0
+
+ // skip up to three spaces
+ for i < 3 && data[i] == ' ' {
+ i++
+ }
+
+ // look at the hrule char
+ if data[i] != '*' && data[i] != '-' && data[i] != '_' {
+ return false
+ }
+ c := data[i]
+
+ // the whole line must be the char or whitespace
+ n := 0
+ for i < len(data) && data[i] != '\n' {
+ switch {
+ case data[i] == c:
+ n++
+ case data[i] != ' ':
+ return false
+ }
+ i++
+ }
+
+ return n >= 3
+}
+
+// isFenceLine checks if there's a fence line (e.g., ``` or ``` go) at the beginning of data,
+// and returns the end index if so, or 0 otherwise. It also returns the marker found.
+// If info is not nil, it gets set to the syntax specified in the fence line.
+func isFenceLine(data []byte, info *string, oldmarker string) (end int, marker string) {
+ i, size := 0, 0
+
+ // skip up to three spaces
+ for i < len(data) && i < 3 && data[i] == ' ' {
+ i++
+ }
+
+ // check for the marker characters: ~ or `
+ if i >= len(data) {
+ return 0, ""
+ }
+ if data[i] != '~' && data[i] != '`' {
+ return 0, ""
+ }
+
+ c := data[i]
+
+ // the whole line must be the same char or whitespace
+ for i < len(data) && data[i] == c {
+ size++
+ i++
+ }
+
+ // the marker char must occur at least 3 times
+ if size < 3 {
+ return 0, ""
+ }
+ marker = string(data[i-size : i])
+
+ // if this is the end marker, it must match the beginning marker
+ if oldmarker != "" && marker != oldmarker {
+ return 0, ""
+ }
+
+ // TODO(shurcooL): It's probably a good idea to simplify the 2 code paths here
+ // into one, always get the info string, and discard it if the caller doesn't care.
+ if info != nil {
+ infoLength := 0
+ i = skipChar(data, i, ' ')
+
+ if i >= len(data) {
+ if i == len(data) {
+ return i, marker
+ }
+ return 0, ""
+ }
+
+ infoStart := i
+
+ if data[i] == '{' {
+ i++
+ infoStart++
+
+ for i < len(data) && data[i] != '}' && data[i] != '\n' {
+ infoLength++
+ i++
+ }
+
+ if i >= len(data) || data[i] != '}' {
+ return 0, ""
+ }
+
+ // strip all whitespace at the beginning and the end
+ // of the {} block
+ for infoLength > 0 && isspace(data[infoStart]) {
+ infoStart++
+ infoLength--
+ }
+
+ for infoLength > 0 && isspace(data[infoStart+infoLength-1]) {
+ infoLength--
+ }
+ i++
+ i = skipChar(data, i, ' ')
+ } else {
+ for i < len(data) && !isverticalspace(data[i]) {
+ infoLength++
+ i++
+ }
+ }
+
+ *info = strings.TrimSpace(string(data[infoStart : infoStart+infoLength]))
+ }
+
+ if i == len(data) {
+ return i, marker
+ }
+ if i > len(data) || data[i] != '\n' {
+ return 0, ""
+ }
+ return i + 1, marker // Take newline into account.
+}
+
+// fencedCodeBlock returns the end index if data contains a fenced code block at the beginning,
+// or 0 otherwise. It writes to out if doRender is true, otherwise it has no side effects.
+// If doRender is true, a final newline is mandatory to recognize the fenced code block.
+func (p *Markdown) fencedCodeBlock(data []byte, doRender bool) int {
+ var info string
+ beg, marker := isFenceLine(data, &info, "")
+ if beg == 0 || beg >= len(data) {
+ return 0
+ }
+ fenceLength := beg - 1
+
+ var work bytes.Buffer
+ work.Write([]byte(info))
+ work.WriteByte('\n')
+
+ for {
+ // safe to assume beg < len(data)
+
+ // check for the end of the code block
+ fenceEnd, _ := isFenceLine(data[beg:], nil, marker)
+ if fenceEnd != 0 {
+ beg += fenceEnd
+ break
+ }
+
+ // copy the current line
+ end := skipUntilChar(data, beg, '\n') + 1
+
+ // did we reach the end of the buffer without a closing marker?
+ if end >= len(data) {
+ return 0
+ }
+
+ // verbatim copy to the working buffer
+ if doRender {
+ work.Write(data[beg:end])
+ }
+ beg = end
+ }
+
+ if doRender {
+ block := p.addBlock(CodeBlock, work.Bytes()) // TODO: get rid of temp buffer
+ block.IsFenced = true
+ block.FenceLength = fenceLength
+ finalizeCodeBlock(block)
+ }
+
+ return beg
+}
+
+func unescapeChar(str []byte) []byte {
+ if str[0] == '\\' {
+ return []byte{str[1]}
+ }
+ return []byte(html.UnescapeString(string(str)))
+}
+
+func unescapeString(str []byte) []byte {
+ if reBackslashOrAmp.Match(str) {
+ return reEntityOrEscapedChar.ReplaceAllFunc(str, unescapeChar)
+ }
+ return str
+}
+
+func finalizeCodeBlock(block *Node) {
+ if block.IsFenced {
+ newlinePos := bytes.IndexByte(block.content, '\n')
+ firstLine := block.content[:newlinePos]
+ rest := block.content[newlinePos+1:]
+ block.Info = unescapeString(bytes.Trim(firstLine, "\n"))
+ block.Literal = rest
+ } else {
+ block.Literal = block.content
+ }
+ block.content = nil
+}
+
+func (p *Markdown) table(data []byte) int {
+ table := p.addBlock(Table, nil)
+ i, columns := p.tableHeader(data)
+ if i == 0 {
+ p.tip = table.Parent
+ table.Unlink()
+ return 0
+ }
+
+ p.addBlock(TableBody, nil)
+
+ for i < len(data) {
+ pipes, rowStart := 0, i
+ for ; i < len(data) && data[i] != '\n'; i++ {
+ if data[i] == '|' {
+ pipes++
+ }
+ }
+
+ if pipes == 0 {
+ i = rowStart
+ break
+ }
+
+ // include the newline in data sent to tableRow
+ if i < len(data) && data[i] == '\n' {
+ i++
+ }
+ p.tableRow(data[rowStart:i], columns, false)
+ }
+
+ return i
+}
+
+// check if the specified position is preceded by an odd number of backslashes
+func isBackslashEscaped(data []byte, i int) bool {
+ backslashes := 0
+ for i-backslashes-1 >= 0 && data[i-backslashes-1] == '\\' {
+ backslashes++
+ }
+ return backslashes&1 == 1
+}
+
+func (p *Markdown) tableHeader(data []byte) (size int, columns []CellAlignFlags) {
+ i := 0
+ colCount := 1
+ for i = 0; i < len(data) && data[i] != '\n'; i++ {
+ if data[i] == '|' && !isBackslashEscaped(data, i) {
+ colCount++
+ }
+ }
+
+ // doesn't look like a table header
+ if colCount == 1 {
+ return
+ }
+
+ // include the newline in the data sent to tableRow
+ j := i
+ if j < len(data) && data[j] == '\n' {
+ j++
+ }
+ header := data[:j]
+
+ // column count ignores pipes at beginning or end of line
+ if data[0] == '|' {
+ colCount--
+ }
+ if i > 2 && data[i-1] == '|' && !isBackslashEscaped(data, i-1) {
+ colCount--
+ }
+
+ columns = make([]CellAlignFlags, colCount)
+
+ // move on to the header underline
+ i++
+ if i >= len(data) {
+ return
+ }
+
+ if data[i] == '|' && !isBackslashEscaped(data, i) {
+ i++
+ }
+ i = skipChar(data, i, ' ')
+
+ // each column header is of form: / *:?-+:? *|/ with # dashes + # colons >= 3
+ // and trailing | optional on last column
+ col := 0
+ for i < len(data) && data[i] != '\n' {
+ dashes := 0
+
+ if data[i] == ':' {
+ i++
+ columns[col] |= TableAlignmentLeft
+ dashes++
+ }
+ for i < len(data) && data[i] == '-' {
+ i++
+ dashes++
+ }
+ if i < len(data) && data[i] == ':' {
+ i++
+ columns[col] |= TableAlignmentRight
+ dashes++
+ }
+ for i < len(data) && data[i] == ' ' {
+ i++
+ }
+ if i == len(data) {
+ return
+ }
+ // end of column test is messy
+ switch {
+ case dashes < 3:
+ // not a valid column
+ return
+
+ case data[i] == '|' && !isBackslashEscaped(data, i):
+ // marker found, now skip past trailing whitespace
+ col++
+ i++
+ for i < len(data) && data[i] == ' ' {
+ i++
+ }
+
+ // trailing junk found after last column
+ if col >= colCount && i < len(data) && data[i] != '\n' {
+ return
+ }
+
+ case (data[i] != '|' || isBackslashEscaped(data, i)) && col+1 < colCount:
+ // something else found where marker was required
+ return
+
+ case data[i] == '\n':
+ // marker is optional for the last column
+ col++
+
+ default:
+ // trailing junk found after last column
+ return
+ }
+ }
+ if col != colCount {
+ return
+ }
+
+ p.addBlock(TableHead, nil)
+ p.tableRow(header, columns, true)
+ size = i
+ if size < len(data) && data[size] == '\n' {
+ size++
+ }
+ return
+}
+
+func (p *Markdown) tableRow(data []byte, columns []CellAlignFlags, header bool) {
+ p.addBlock(TableRow, nil)
+ i, col := 0, 0
+
+ if data[i] == '|' && !isBackslashEscaped(data, i) {
+ i++
+ }
+
+ for col = 0; col < len(columns) && i < len(data); col++ {
+ for i < len(data) && data[i] == ' ' {
+ i++
+ }
+
+ cellStart := i
+
+ for i < len(data) && (data[i] != '|' || isBackslashEscaped(data, i)) && data[i] != '\n' {
+ i++
+ }
+
+ cellEnd := i
+
+ // skip the end-of-cell marker, possibly taking us past end of buffer
+ i++
+
+ for cellEnd > cellStart && cellEnd-1 < len(data) && data[cellEnd-1] == ' ' {
+ cellEnd--
+ }
+
+ cell := p.addBlock(TableCell, data[cellStart:cellEnd])
+ cell.IsHeader = header
+ cell.Align = columns[col]
+ }
+
+ // pad it out with empty columns to get the right number
+ for ; col < len(columns); col++ {
+ cell := p.addBlock(TableCell, nil)
+ cell.IsHeader = header
+ cell.Align = columns[col]
+ }
+
+ // silently ignore rows with too many cells
+}
+
+// returns blockquote prefix length
+func (p *Markdown) quotePrefix(data []byte) int {
+ i := 0
+ for i < 3 && i < len(data) && data[i] == ' ' {
+ i++
+ }
+ if i < len(data) && data[i] == '>' {
+ if i+1 < len(data) && data[i+1] == ' ' {
+ return i + 2
+ }
+ return i + 1
+ }
+ return 0
+}
+
+// blockquote ends with at least one blank line
+// followed by something without a blockquote prefix
+func (p *Markdown) terminateBlockquote(data []byte, beg, end int) bool {
+ if p.isEmpty(data[beg:]) <= 0 {
+ return false
+ }
+ if end >= len(data) {
+ return true
+ }
+ return p.quotePrefix(data[end:]) == 0 && p.isEmpty(data[end:]) == 0
+}
+
+// parse a blockquote fragment
+func (p *Markdown) quote(data []byte) int {
+ block := p.addBlock(BlockQuote, nil)
+ var raw bytes.Buffer
+ beg, end := 0, 0
+ for beg < len(data) {
+ end = beg
+ // Step over whole lines, collecting them. While doing that, check for
+ // fenced code and if one's found, incorporate it altogether,
+ // irregardless of any contents inside it
+ for end < len(data) && data[end] != '\n' {
+ if p.extensions&FencedCode != 0 {
+ if i := p.fencedCodeBlock(data[end:], false); i > 0 {
+ // -1 to compensate for the extra end++ after the loop:
+ end += i - 1
+ break
+ }
+ }
+ end++
+ }
+ if end < len(data) && data[end] == '\n' {
+ end++
+ }
+ if pre := p.quotePrefix(data[beg:]); pre > 0 {
+ // skip the prefix
+ beg += pre
+ } else if p.terminateBlockquote(data, beg, end) {
+ break
+ }
+ // this line is part of the blockquote
+ raw.Write(data[beg:end])
+ beg = end
+ }
+ p.block(raw.Bytes())
+ p.finalize(block)
+ return end
+}
+
+// returns prefix length for block code
+func (p *Markdown) codePrefix(data []byte) int {
+ if len(data) >= 1 && data[0] == '\t' {
+ return 1
+ }
+ if len(data) >= 4 && data[0] == ' ' && data[1] == ' ' && data[2] == ' ' && data[3] == ' ' {
+ return 4
+ }
+ return 0
+}
+
+func (p *Markdown) code(data []byte) int {
+ var work bytes.Buffer
+
+ i := 0
+ for i < len(data) {
+ beg := i
+ for i < len(data) && data[i] != '\n' {
+ i++
+ }
+ if i < len(data) && data[i] == '\n' {
+ i++
+ }
+
+ blankline := p.isEmpty(data[beg:i]) > 0
+ if pre := p.codePrefix(data[beg:i]); pre > 0 {
+ beg += pre
+ } else if !blankline {
+ // non-empty, non-prefixed line breaks the pre
+ i = beg
+ break
+ }
+
+ // verbatim copy to the working buffer
+ if blankline {
+ work.WriteByte('\n')
+ } else {
+ work.Write(data[beg:i])
+ }
+ }
+
+ // trim all the \n off the end of work
+ workbytes := work.Bytes()
+ eol := len(workbytes)
+ for eol > 0 && workbytes[eol-1] == '\n' {
+ eol--
+ }
+ if eol != len(workbytes) {
+ work.Truncate(eol)
+ }
+
+ work.WriteByte('\n')
+
+ block := p.addBlock(CodeBlock, work.Bytes()) // TODO: get rid of temp buffer
+ block.IsFenced = false
+ finalizeCodeBlock(block)
+
+ return i
+}
+
+// returns unordered list item prefix
+func (p *Markdown) uliPrefix(data []byte) int {
+ i := 0
+ // start with up to 3 spaces
+ for i < len(data) && i < 3 && data[i] == ' ' {
+ i++
+ }
+ if i >= len(data)-1 {
+ return 0
+ }
+ // need one of {'*', '+', '-'} followed by a space or a tab
+ if (data[i] != '*' && data[i] != '+' && data[i] != '-') ||
+ (data[i+1] != ' ' && data[i+1] != '\t') {
+ return 0
+ }
+ return i + 2
+}
+
+// returns ordered list item prefix
+func (p *Markdown) oliPrefix(data []byte) int {
+ i := 0
+
+ // start with up to 3 spaces
+ for i < 3 && i < len(data) && data[i] == ' ' {
+ i++
+ }
+
+ // count the digits
+ start := i
+ for i < len(data) && data[i] >= '0' && data[i] <= '9' {
+ i++
+ }
+ if start == i || i >= len(data)-1 {
+ return 0
+ }
+
+ // we need >= 1 digits followed by a dot and a space or a tab
+ if data[i] != '.' || !(data[i+1] == ' ' || data[i+1] == '\t') {
+ return 0
+ }
+ return i + 2
+}
+
+// returns definition list item prefix
+func (p *Markdown) dliPrefix(data []byte) int {
+ if len(data) < 2 {
+ return 0
+ }
+ i := 0
+ // need a ':' followed by a space or a tab
+ if data[i] != ':' || !(data[i+1] == ' ' || data[i+1] == '\t') {
+ return 0
+ }
+ for i < len(data) && data[i] == ' ' {
+ i++
+ }
+ return i + 2
+}
+
+// parse ordered or unordered list block
+func (p *Markdown) list(data []byte, flags ListType) int {
+ i := 0
+ flags |= ListItemBeginningOfList
+ block := p.addBlock(List, nil)
+ block.ListFlags = flags
+ block.Tight = true
+
+ for i < len(data) {
+ skip := p.listItem(data[i:], &flags)
+ if flags&ListItemContainsBlock != 0 {
+ block.ListData.Tight = false
+ }
+ i += skip
+ if skip == 0 || flags&ListItemEndOfList != 0 {
+ break
+ }
+ flags &= ^ListItemBeginningOfList
+ }
+
+ above := block.Parent
+ finalizeList(block)
+ p.tip = above
+ return i
+}
+
+// Returns true if the list item is not the same type as its parent list
+func (p *Markdown) listTypeChanged(data []byte, flags *ListType) bool {
+ if p.dliPrefix(data) > 0 && *flags&ListTypeDefinition == 0 {
+ return true
+ } else if p.oliPrefix(data) > 0 && *flags&ListTypeOrdered == 0 {
+ return true
+ } else if p.uliPrefix(data) > 0 && (*flags&ListTypeOrdered != 0 || *flags&ListTypeDefinition != 0) {
+ return true
+ }
+ return false
+}
+
+// Returns true if block ends with a blank line, descending if needed
+// into lists and sublists.
+func endsWithBlankLine(block *Node) bool {
+ // TODO: figure this out. Always false now.
+ for block != nil {
+ //if block.lastLineBlank {
+ //return true
+ //}
+ t := block.Type
+ if t == List || t == Item {
+ block = block.LastChild
+ } else {
+ break
+ }
+ }
+ return false
+}
+
+func finalizeList(block *Node) {
+ block.open = false
+ item := block.FirstChild
+ for item != nil {
+ // check for non-final list item ending with blank line:
+ if endsWithBlankLine(item) && item.Next != nil {
+ block.ListData.Tight = false
+ break
+ }
+ // recurse into children of list item, to see if there are spaces
+ // between any of them:
+ subItem := item.FirstChild
+ for subItem != nil {
+ if endsWithBlankLine(subItem) && (item.Next != nil || subItem.Next != nil) {
+ block.ListData.Tight = false
+ break
+ }
+ subItem = subItem.Next
+ }
+ item = item.Next
+ }
+}
+
+// Parse a single list item.
+// Assumes initial prefix is already removed if this is a sublist.
+func (p *Markdown) listItem(data []byte, flags *ListType) int {
+ // keep track of the indentation of the first line
+ itemIndent := 0
+ if data[0] == '\t' {
+ itemIndent += 4
+ } else {
+ for itemIndent < 3 && data[itemIndent] == ' ' {
+ itemIndent++
+ }
+ }
+
+ var bulletChar byte = '*'
+ i := p.uliPrefix(data)
+ if i == 0 {
+ i = p.oliPrefix(data)
+ } else {
+ bulletChar = data[i-2]
+ }
+ if i == 0 {
+ i = p.dliPrefix(data)
+ // reset definition term flag
+ if i > 0 {
+ *flags &= ^ListTypeTerm
+ }
+ }
+ if i == 0 {
+ // if in definition list, set term flag and continue
+ if *flags&ListTypeDefinition != 0 {
+ *flags |= ListTypeTerm
+ } else {
+ return 0
+ }
+ }
+
+ // skip leading whitespace on first line
+ for i < len(data) && data[i] == ' ' {
+ i++
+ }
+
+ // find the end of the line
+ line := i
+ for i > 0 && i < len(data) && data[i-1] != '\n' {
+ i++
+ }
+
+ // get working buffer
+ var raw bytes.Buffer
+
+ // put the first line into the working buffer
+ raw.Write(data[line:i])
+ line = i
+
+ // process the following lines
+ containsBlankLine := false
+ sublist := 0
+ codeBlockMarker := ""
+
+gatherlines:
+ for line < len(data) {
+ i++
+
+ // find the end of this line
+ for i < len(data) && data[i-1] != '\n' {
+ i++
+ }
+
+ // if it is an empty line, guess that it is part of this item
+ // and move on to the next line
+ if p.isEmpty(data[line:i]) > 0 {
+ containsBlankLine = true
+ line = i
+ continue
+ }
+
+ // calculate the indentation
+ indent := 0
+ indentIndex := 0
+ if data[line] == '\t' {
+ indentIndex++
+ indent += 4
+ } else {
+ for indent < 4 && line+indent < i && data[line+indent] == ' ' {
+ indent++
+ indentIndex++
+ }
+ }
+
+ chunk := data[line+indentIndex : i]
+
+ if p.extensions&FencedCode != 0 {
+ // determine if in or out of codeblock
+ // if in codeblock, ignore normal list processing
+ _, marker := isFenceLine(chunk, nil, codeBlockMarker)
+ if marker != "" {
+ if codeBlockMarker == "" {
+ // start of codeblock
+ codeBlockMarker = marker
+ } else {
+ // end of codeblock.
+ codeBlockMarker = ""
+ }
+ }
+ // we are in a codeblock, write line, and continue
+ if codeBlockMarker != "" || marker != "" {
+ raw.Write(data[line+indentIndex : i])
+ line = i
+ continue gatherlines
+ }
+ }
+
+ // evaluate how this line fits in
+ switch {
+ // is this a nested list item?
+ case (p.uliPrefix(chunk) > 0 && !p.isHRule(chunk)) ||
+ p.oliPrefix(chunk) > 0 ||
+ p.dliPrefix(chunk) > 0:
+
+ // to be a nested list, it must be indented more
+ // if not, it is either a different kind of list
+ // or the next item in the same list
+ if indent <= itemIndent {
+ if p.listTypeChanged(chunk, flags) {
+ *flags |= ListItemEndOfList
+ } else if containsBlankLine {
+ *flags |= ListItemContainsBlock
+ }
+
+ break gatherlines
+ }
+
+ if containsBlankLine {
+ *flags |= ListItemContainsBlock
+ }
+
+ // is this the first item in the nested list?
+ if sublist == 0 {
+ sublist = raw.Len()
+ }
+
+ // is this a nested prefix heading?
+ case p.isPrefixHeading(chunk):
+ // if the heading is not indented, it is not nested in the list
+ // and thus ends the list
+ if containsBlankLine && indent < 4 {
+ *flags |= ListItemEndOfList
+ break gatherlines
+ }
+ *flags |= ListItemContainsBlock
+
+ // anything following an empty line is only part
+ // of this item if it is indented 4 spaces
+ // (regardless of the indentation of the beginning of the item)
+ case containsBlankLine && indent < 4:
+ if *flags&ListTypeDefinition != 0 && i < len(data)-1 {
+ // is the next item still a part of this list?
+ next := i
+ for next < len(data) && data[next] != '\n' {
+ next++
+ }
+ for next < len(data)-1 && data[next] == '\n' {
+ next++
+ }
+ if i < len(data)-1 && data[i] != ':' && data[next] != ':' {
+ *flags |= ListItemEndOfList
+ }
+ } else {
+ *flags |= ListItemEndOfList
+ }
+ break gatherlines
+
+ // a blank line means this should be parsed as a block
+ case containsBlankLine:
+ raw.WriteByte('\n')
+ *flags |= ListItemContainsBlock
+ }
+
+ // if this line was preceded by one or more blanks,
+ // re-introduce the blank into the buffer
+ if containsBlankLine {
+ containsBlankLine = false
+ raw.WriteByte('\n')
+ }
+
+ // add the line into the working buffer without prefix
+ raw.Write(data[line+indentIndex : i])
+
+ line = i
+ }
+
+ rawBytes := raw.Bytes()
+
+ block := p.addBlock(Item, nil)
+ block.ListFlags = *flags
+ block.Tight = false
+ block.BulletChar = bulletChar
+ block.Delimiter = '.' // Only '.' is possible in Markdown, but ')' will also be possible in CommonMark
+
+ // render the contents of the list item
+ if *flags&ListItemContainsBlock != 0 && *flags&ListTypeTerm == 0 {
+ // intermediate render of block item, except for definition term
+ if sublist > 0 {
+ p.block(rawBytes[:sublist])
+ p.block(rawBytes[sublist:])
+ } else {
+ p.block(rawBytes)
+ }
+ } else {
+ // intermediate render of inline item
+ if sublist > 0 {
+ child := p.addChild(Paragraph, 0)
+ child.content = rawBytes[:sublist]
+ p.block(rawBytes[sublist:])
+ } else {
+ child := p.addChild(Paragraph, 0)
+ child.content = rawBytes
+ }
+ }
+ return line
+}
+
+// render a single paragraph that has already been parsed out
+func (p *Markdown) renderParagraph(data []byte) {
+ if len(data) == 0 {
+ return
+ }
+
+ // trim leading spaces
+ beg := 0
+ for data[beg] == ' ' {
+ beg++
+ }
+
+ end := len(data)
+ // trim trailing newline
+ if data[len(data)-1] == '\n' {
+ end--
+ }
+
+ // trim trailing spaces
+ for end > beg && data[end-1] == ' ' {
+ end--
+ }
+
+ p.addBlock(Paragraph, data[beg:end])
+}
+
+func (p *Markdown) paragraph(data []byte) int {
+ // prev: index of 1st char of previous line
+ // line: index of 1st char of current line
+ // i: index of cursor/end of current line
+ var prev, line, i int
+ tabSize := TabSizeDefault
+ if p.extensions&TabSizeEight != 0 {
+ tabSize = TabSizeDouble
+ }
+ // keep going until we find something to mark the end of the paragraph
+ for i < len(data) {
+ // mark the beginning of the current line
+ prev = line
+ current := data[i:]
+ line = i
+
+ // did we find a reference or a footnote? If so, end a paragraph
+ // preceding it and report that we have consumed up to the end of that
+ // reference:
+ if refEnd := isReference(p, current, tabSize); refEnd > 0 {
+ p.renderParagraph(data[:i])
+ return i + refEnd
+ }
+
+ // did we find a blank line marking the end of the paragraph?
+ if n := p.isEmpty(current); n > 0 {
+ // did this blank line followed by a definition list item?
+ if p.extensions&DefinitionLists != 0 {
+ if i < len(data)-1 && data[i+1] == ':' {
+ return p.list(data[prev:], ListTypeDefinition)
+ }
+ }
+
+ p.renderParagraph(data[:i])
+ return i + n
+ }
+
+ // an underline under some text marks a heading, so our paragraph ended on prev line
+ if i > 0 {
+ if level := p.isUnderlinedHeading(current); level > 0 {
+ // render the paragraph
+ p.renderParagraph(data[:prev])
+
+ // ignore leading and trailing whitespace
+ eol := i - 1
+ for prev < eol && data[prev] == ' ' {
+ prev++
+ }
+ for eol > prev && data[eol-1] == ' ' {
+ eol--
+ }
+
+ id := ""
+ if p.extensions&AutoHeadingIDs != 0 {
+ id = SanitizedAnchorName(string(data[prev:eol]))
+ }
+
+ block := p.addBlock(Heading, data[prev:eol])
+ block.Level = level
+ block.HeadingID = id
+
+ // find the end of the underline
+ for i < len(data) && data[i] != '\n' {
+ i++
+ }
+ return i
+ }
+ }
+
+ // if the next line starts a block of HTML, then the paragraph ends here
+ if p.extensions&LaxHTMLBlocks != 0 {
+ if data[i] == '<' && p.html(current, false) > 0 {
+ // rewind to before the HTML block
+ p.renderParagraph(data[:i])
+ return i
+ }
+ }
+
+ // if there's a prefixed heading or a horizontal rule after this, paragraph is over
+ if p.isPrefixHeading(current) || p.isHRule(current) {
+ p.renderParagraph(data[:i])
+ return i
+ }
+
+ // if there's a fenced code block, paragraph is over
+ if p.extensions&FencedCode != 0 {
+ if p.fencedCodeBlock(current, false) > 0 {
+ p.renderParagraph(data[:i])
+ return i
+ }
+ }
+
+ // if there's a definition list item, prev line is a definition term
+ if p.extensions&DefinitionLists != 0 {
+ if p.dliPrefix(current) != 0 {
+ ret := p.list(data[prev:], ListTypeDefinition)
+ return ret
+ }
+ }
+
+ // if there's a list after this, paragraph is over
+ if p.extensions&NoEmptyLineBeforeBlock != 0 {
+ if p.uliPrefix(current) != 0 ||
+ p.oliPrefix(current) != 0 ||
+ p.quotePrefix(current) != 0 ||
+ p.codePrefix(current) != 0 {
+ p.renderParagraph(data[:i])
+ return i
+ }
+ }
+
+ // otherwise, scan to the beginning of the next line
+ nl := bytes.IndexByte(data[i:], '\n')
+ if nl >= 0 {
+ i += nl + 1
+ } else {
+ i += len(data[i:])
+ }
+ }
+
+ p.renderParagraph(data[:i])
+ return i
+}
+
+func skipChar(data []byte, start int, char byte) int {
+ i := start
+ for i < len(data) && data[i] == char {
+ i++
+ }
+ return i
+}
+
+func skipUntilChar(text []byte, start int, char byte) int {
+ i := start
+ for i < len(text) && text[i] != char {
+ i++
+ }
+ return i
+}
+
+// SanitizedAnchorName returns a sanitized anchor name for the given text.
+//
+// It implements the algorithm specified in the package comment.
+func SanitizedAnchorName(text string) string {
+ var anchorName []rune
+ futureDash := false
+ for _, r := range text {
+ switch {
+ case unicode.IsLetter(r) || unicode.IsNumber(r):
+ if futureDash && len(anchorName) > 0 {
+ anchorName = append(anchorName, '-')
+ }
+ futureDash = false
+ anchorName = append(anchorName, unicode.ToLower(r))
+ default:
+ futureDash = true
+ }
+ }
+ return string(anchorName)
+}
diff --git a/vendor/github.com/russross/blackfriday/v2/doc.go b/vendor/github.com/russross/blackfriday/v2/doc.go
new file mode 100644
index 00000000000..57ff152a056
--- /dev/null
+++ b/vendor/github.com/russross/blackfriday/v2/doc.go
@@ -0,0 +1,46 @@
+// Package blackfriday is a markdown processor.
+//
+// It translates plain text with simple formatting rules into an AST, which can
+// then be further processed to HTML (provided by Blackfriday itself) or other
+// formats (provided by the community).
+//
+// The simplest way to invoke Blackfriday is to call the Run function. It will
+// take a text input and produce a text output in HTML (or other format).
+//
+// A slightly more sophisticated way to use Blackfriday is to create a Markdown
+// processor and to call Parse, which returns a syntax tree for the input
+// document. You can leverage Blackfriday's parsing for content extraction from
+// markdown documents. You can assign a custom renderer and set various options
+// to the Markdown processor.
+//
+// If you're interested in calling Blackfriday from command line, see
+// https://github.com/russross/blackfriday-tool.
+//
+// Sanitized Anchor Names
+//
+// Blackfriday includes an algorithm for creating sanitized anchor names
+// corresponding to a given input text. This algorithm is used to create
+// anchors for headings when AutoHeadingIDs extension is enabled. The
+// algorithm is specified below, so that other packages can create
+// compatible anchor names and links to those anchors.
+//
+// The algorithm iterates over the input text, interpreted as UTF-8,
+// one Unicode code point (rune) at a time. All runes that are letters (category L)
+// or numbers (category N) are considered valid characters. They are mapped to
+// lower case, and included in the output. All other runes are considered
+// invalid characters. Invalid characters that precede the first valid character,
+// as well as invalid character that follow the last valid character
+// are dropped completely. All other sequences of invalid characters
+// between two valid characters are replaced with a single dash character '-'.
+//
+// SanitizedAnchorName exposes this functionality, and can be used to
+// create compatible links to the anchor names generated by blackfriday.
+// This algorithm is also implemented in a small standalone package at
+// github.com/shurcooL/sanitized_anchor_name. It can be useful for clients
+// that want a small package and don't need full functionality of blackfriday.
+package blackfriday
+
+// NOTE: Keep Sanitized Anchor Name algorithm in sync with package
+// github.com/shurcooL/sanitized_anchor_name.
+// Otherwise, users of sanitized_anchor_name will get anchor names
+// that are incompatible with those generated by blackfriday.
diff --git a/vendor/github.com/russross/blackfriday/v2/entities.go b/vendor/github.com/russross/blackfriday/v2/entities.go
new file mode 100644
index 00000000000..a2c3edb691c
--- /dev/null
+++ b/vendor/github.com/russross/blackfriday/v2/entities.go
@@ -0,0 +1,2236 @@
+package blackfriday
+
+// Extracted from https://html.spec.whatwg.org/multipage/entities.json
+var entities = map[string]bool{
+ "Æ": true,
+ "Æ": true,
+ "&": true,
+ "&": true,
+ "Á": true,
+ "Á": true,
+ "Ă": true,
+ "Â": true,
+ "Â": true,
+ "А": true,
+ "𝔄": true,
+ "À": true,
+ "À": true,
+ "Α": true,
+ "Ā": true,
+ "⩓": true,
+ "Ą": true,
+ "𝔸": true,
+ "⁡": true,
+ "Å": true,
+ "Å": true,
+ "𝒜": true,
+ "≔": true,
+ "Ã": true,
+ "Ã": true,
+ "Ä": true,
+ "Ä": true,
+ "∖": true,
+ "⫧": true,
+ "⌆": true,
+ "Б": true,
+ "∵": true,
+ "ℬ": true,
+ "Β": true,
+ "𝔅": true,
+ "𝔹": true,
+ "˘": true,
+ "ℬ": true,
+ "≎": true,
+ "Ч": true,
+ "©": true,
+ "©": true,
+ "Ć": true,
+ "⋒": true,
+ "ⅅ": true,
+ "ℭ": true,
+ "Č": true,
+ "Ç": true,
+ "Ç": true,
+ "Ĉ": true,
+ "∰": true,
+ "Ċ": true,
+ "¸": true,
+ "·": true,
+ "ℭ": true,
+ "Χ": true,
+ "⊙": true,
+ "⊖": true,
+ "⊕": true,
+ "⊗": true,
+ "∲": true,
+ "”": true,
+ "’": true,
+ "∷": true,
+ "⩴": true,
+ "≡": true,
+ "∯": true,
+ "∮": true,
+ "ℂ": true,
+ "∐": true,
+ "∳": true,
+ "⨯": true,
+ "𝒞": true,
+ "⋓": true,
+ "≍": true,
+ "ⅅ": true,
+ "⤑": true,
+ "Ђ": true,
+ "Ѕ": true,
+ "Џ": true,
+ "‡": true,
+ "↡": true,
+ "⫤": true,
+ "Ď": true,
+ "Д": true,
+ "∇": true,
+ "Δ": true,
+ "𝔇": true,
+ "´": true,
+ "˙": true,
+ "˝": true,
+ "`": true,
+ "˜": true,
+ "⋄": true,
+ "ⅆ": true,
+ "𝔻": true,
+ "¨": true,
+ "⃜": true,
+ "≐": true,
+ "∯": true,
+ "¨": true,
+ "⇓": true,
+ "⇐": true,
+ "⇔": true,
+ "⫤": true,
+ "⟸": true,
+ "⟺": true,
+ "⟹": true,
+ "⇒": true,
+ "⊨": true,
+ "⇑": true,
+ "⇕": true,
+ "∥": true,
+ "↓": true,
+ "⤓": true,
+ "⇵": true,
+ "̑": true,
+ "⥐": true,
+ "⥞": true,
+ "↽": true,
+ "⥖": true,
+ "⥟": true,
+ "⇁": true,
+ "⥗": true,
+ "⊤": true,
+ "↧": true,
+ "⇓": true,
+ "𝒟": true,
+ "Đ": true,
+ "Ŋ": true,
+ "Ð": true,
+ "Ð": true,
+ "É": true,
+ "É": true,
+ "Ě": true,
+ "Ê": true,
+ "Ê": true,
+ "Э": true,
+ "Ė": true,
+ "𝔈": true,
+ "È": true,
+ "È": true,
+ "∈": true,
+ "Ē": true,
+ "◻": true,
+ "▫": true,
+ "Ę": true,
+ "𝔼": true,
+ "Ε": true,
+ "⩵": true,
+ "≂": true,
+ "⇌": true,
+ "ℰ": true,
+ "⩳": true,
+ "Η": true,
+ "Ë": true,
+ "Ë": true,
+ "∃": true,
+ "ⅇ": true,
+ "Ф": true,
+ "𝔉": true,
+ "◼": true,
+ "▪": true,
+ "𝔽": true,
+ "∀": true,
+ "ℱ": true,
+ "ℱ": true,
+ "Ѓ": true,
+ ">": true,
+ ">": true,
+ "Γ": true,
+ "Ϝ": true,
+ "Ğ": true,
+ "Ģ": true,
+ "Ĝ": true,
+ "Г": true,
+ "Ġ": true,
+ "𝔊": true,
+ "⋙": true,
+ "𝔾": true,
+ "≥": true,
+ "⋛": true,
+ "≧": true,
+ "⪢": true,
+ "≷": true,
+ "⩾": true,
+ "≳": true,
+ "𝒢": true,
+ "≫": true,
+ "Ъ": true,
+ "ˇ": true,
+ "^": true,
+ "Ĥ": true,
+ "ℌ": true,
+ "ℋ": true,
+ "ℍ": true,
+ "─": true,
+ "ℋ": true,
+ "Ħ": true,
+ "≎": true,
+ "≏": true,
+ "Е": true,
+ "IJ": true,
+ "Ё": true,
+ "Í": true,
+ "Í": true,
+ "Î": true,
+ "Î": true,
+ "И": true,
+ "İ": true,
+ "ℑ": true,
+ "Ì": true,
+ "Ì": true,
+ "ℑ": true,
+ "Ī": true,
+ "ⅈ": true,
+ "⇒": true,
+ "∬": true,
+ "∫": true,
+ "⋂": true,
+ "⁣": true,
+ "⁢": true,
+ "Į": true,
+ "𝕀": true,
+ "Ι": true,
+ "ℐ": true,
+ "Ĩ": true,
+ "І": true,
+ "Ï": true,
+ "Ï": true,
+ "Ĵ": true,
+ "Й": true,
+ "𝔍": true,
+ "𝕁": true,
+ "𝒥": true,
+ "Ј": true,
+ "Є": true,
+ "Х": true,
+ "Ќ": true,
+ "Κ": true,
+ "Ķ": true,
+ "К": true,
+ "𝔎": true,
+ "𝕂": true,
+ "𝒦": true,
+ "Љ": true,
+ "<": true,
+ "<": true,
+ "Ĺ": true,
+ "Λ": true,
+ "⟪": true,
+ "ℒ": true,
+ "↞": true,
+ "Ľ": true,
+ "Ļ": true,
+ "Л": true,
+ "⟨": true,
+ "←": true,
+ "⇤": true,
+ "⇆": true,
+ "⌈": true,
+ "⟦": true,
+ "⥡": true,
+ "⇃": true,
+ "⥙": true,
+ "⌊": true,
+ "↔": true,
+ "⥎": true,
+ "⊣": true,
+ "↤": true,
+ "⥚": true,
+ "⊲": true,
+ "⧏": true,
+ "⊴": true,
+ "⥑": true,
+ "⥠": true,
+ "↿": true,
+ "⥘": true,
+ "↼": true,
+ "⥒": true,
+ "⇐": true,
+ "⇔": true,
+ "⋚": true,
+ "≦": true,
+ "≶": true,
+ "⪡": true,
+ "⩽": true,
+ "≲": true,
+ "𝔏": true,
+ "⋘": true,
+ "⇚": true,
+ "Ŀ": true,
+ "⟵": true,
+ "⟷": true,
+ "⟶": true,
+ "⟸": true,
+ "⟺": true,
+ "⟹": true,
+ "𝕃": true,
+ "↙": true,
+ "↘": true,
+ "ℒ": true,
+ "↰": true,
+ "Ł": true,
+ "≪": true,
+ "⤅": true,
+ "М": true,
+ " ": true,
+ "ℳ": true,
+ "𝔐": true,
+ "∓": true,
+ "𝕄": true,
+ "ℳ": true,
+ "Μ": true,
+ "Њ": true,
+ "Ń": true,
+ "Ň": true,
+ "Ņ": true,
+ "Н": true,
+ "​": true,
+ "​": true,
+ "​": true,
+ "​": true,
+ "≫": true,
+ "≪": true,
+ "
": true,
+ "𝔑": true,
+ "⁠": true,
+ " ": true,
+ "ℕ": true,
+ "⫬": true,
+ "≢": true,
+ "≭": true,
+ "∦": true,
+ "∉": true,
+ "≠": true,
+ "≂̸": true,
+ "∄": true,
+ "≯": true,
+ "≱": true,
+ "≧̸": true,
+ "≫̸": true,
+ "≹": true,
+ "⩾̸": true,
+ "≵": true,
+ "≎̸": true,
+ "≏̸": true,
+ "⋪": true,
+ "⧏̸": true,
+ "⋬": true,
+ "≮": true,
+ "≰": true,
+ "≸": true,
+ "≪̸": true,
+ "⩽̸": true,
+ "≴": true,
+ "⪢̸": true,
+ "⪡̸": true,
+ "⊀": true,
+ "⪯̸": true,
+ "⋠": true,
+ "∌": true,
+ "⋫": true,
+ "⧐̸": true,
+ "⋭": true,
+ "⊏̸": true,
+ "⋢": true,
+ "⊐̸": true,
+ "⋣": true,
+ "⊂⃒": true,
+ "⊈": true,
+ "⊁": true,
+ "⪰̸": true,
+ "⋡": true,
+ "≿̸": true,
+ "⊃⃒": true,
+ "⊉": true,
+ "≁": true,
+ "≄": true,
+ "≇": true,
+ "≉": true,
+ "∤": true,
+ "𝒩": true,
+ "Ñ": true,
+ "Ñ": true,
+ "Ν": true,
+ "Œ": true,
+ "Ó": true,
+ "Ó": true,
+ "Ô": true,
+ "Ô": true,
+ "О": true,
+ "Ő": true,
+ "𝔒": true,
+ "Ò": true,
+ "Ò": true,
+ "Ō": true,
+ "Ω": true,
+ "Ο": true,
+ "𝕆": true,
+ "“": true,
+ "‘": true,
+ "⩔": true,
+ "𝒪": true,
+ "Ø": true,
+ "Ø": true,
+ "Õ": true,
+ "Õ": true,
+ "⨷": true,
+ "Ö": true,
+ "Ö": true,
+ "‾": true,
+ "⏞": true,
+ "⎴": true,
+ "⏜": true,
+ "∂": true,
+ "П": true,
+ "𝔓": true,
+ "Φ": true,
+ "Π": true,
+ "±": true,
+ "ℌ": true,
+ "ℙ": true,
+ "⪻": true,
+ "≺": true,
+ "⪯": true,
+ "≼": true,
+ "≾": true,
+ "″": true,
+ "∏": true,
+ "∷": true,
+ "∝": true,
+ "𝒫": true,
+ "Ψ": true,
+ """: true,
+ """: true,
+ "𝔔": true,
+ "ℚ": true,
+ "𝒬": true,
+ "⤐": true,
+ "®": true,
+ "®": true,
+ "Ŕ": true,
+ "⟫": true,
+ "↠": true,
+ "⤖": true,
+ "Ř": true,
+ "Ŗ": true,
+ "Р": true,
+ "ℜ": true,
+ "∋": true,
+ "⇋": true,
+ "⥯": true,
+ "ℜ": true,
+ "Ρ": true,
+ "⟩": true,
+ "→": true,
+ "⇥": true,
+ "⇄": true,
+ "⌉": true,
+ "⟧": true,
+ "⥝": true,
+ "⇂": true,
+ "⥕": true,
+ "⌋": true,
+ "⊢": true,
+ "↦": true,
+ "⥛": true,
+ "⊳": true,
+ "⧐": true,
+ "⊵": true,
+ "⥏": true,
+ "⥜": true,
+ "↾": true,
+ "⥔": true,
+ "⇀": true,
+ "⥓": true,
+ "⇒": true,
+ "ℝ": true,
+ "⥰": true,
+ "⇛": true,
+ "ℛ": true,
+ "↱": true,
+ "⧴": true,
+ "Щ": true,
+ "Ш": true,
+ "Ь": true,
+ "Ś": true,
+ "⪼": true,
+ "Š": true,
+ "Ş": true,
+ "Ŝ": true,
+ "С": true,
+ "𝔖": true,
+ "↓": true,
+ "←": true,
+ "→": true,
+ "↑": true,
+ "Σ": true,
+ "∘": true,
+ "𝕊": true,
+ "√": true,
+ "□": true,
+ "⊓": true,
+ "⊏": true,
+ "⊑": true,
+ "⊐": true,
+ "⊒": true,
+ "⊔": true,
+ "𝒮": true,
+ "⋆": true,
+ "⋐": true,
+ "⋐": true,
+ "⊆": true,
+ "≻": true,
+ "⪰": true,
+ "≽": true,
+ "≿": true,
+ "∋": true,
+ "∑": true,
+ "⋑": true,
+ "⊃": true,
+ "⊇": true,
+ "⋑": true,
+ "Þ": true,
+ "Þ": true,
+ "™": true,
+ "Ћ": true,
+ "Ц": true,
+ "	": true,
+ "Τ": true,
+ "Ť": true,
+ "Ţ": true,
+ "Т": true,
+ "𝔗": true,
+ "∴": true,
+ "Θ": true,
+ "  ": true,
+ " ": true,
+ "∼": true,
+ "≃": true,
+ "≅": true,
+ "≈": true,
+ "𝕋": true,
+ "⃛": true,
+ "𝒯": true,
+ "Ŧ": true,
+ "Ú": true,
+ "Ú": true,
+ "↟": true,
+ "⥉": true,
+ "Ў": true,
+ "Ŭ": true,
+ "Û": true,
+ "Û": true,
+ "У": true,
+ "Ű": true,
+ "𝔘": true,
+ "Ù": true,
+ "Ù": true,
+ "Ū": true,
+ "_": true,
+ "⏟": true,
+ "⎵": true,
+ "⏝": true,
+ "⋃": true,
+ "⊎": true,
+ "Ų": true,
+ "𝕌": true,
+ "↑": true,
+ "⤒": true,
+ "⇅": true,
+ "↕": true,
+ "⥮": true,
+ "⊥": true,
+ "↥": true,
+ "⇑": true,
+ "⇕": true,
+ "↖": true,
+ "↗": true,
+ "ϒ": true,
+ "Υ": true,
+ "Ů": true,
+ "𝒰": true,
+ "Ũ": true,
+ "Ü": true,
+ "Ü": true,
+ "⊫": true,
+ "⫫": true,
+ "В": true,
+ "⊩": true,
+ "⫦": true,
+ "⋁": true,
+ "‖": true,
+ "‖": true,
+ "∣": true,
+ "|": true,
+ "❘": true,
+ "≀": true,
+ " ": true,
+ "𝔙": true,
+ "𝕍": true,
+ "𝒱": true,
+ "⊪": true,
+ "Ŵ": true,
+ "⋀": true,
+ "𝔚": true,
+ "𝕎": true,
+ "𝒲": true,
+ "𝔛": true,
+ "Ξ": true,
+ "𝕏": true,
+ "𝒳": true,
+ "Я": true,
+ "Ї": true,
+ "Ю": true,
+ "Ý": true,
+ "Ý": true,
+ "Ŷ": true,
+ "Ы": true,
+ "𝔜": true,
+ "𝕐": true,
+ "𝒴": true,
+ "Ÿ": true,
+ "Ж": true,
+ "Ź": true,
+ "Ž": true,
+ "З": true,
+ "Ż": true,
+ "​": true,
+ "Ζ": true,
+ "ℨ": true,
+ "ℤ": true,
+ "𝒵": true,
+ "á": true,
+ "á": true,
+ "ă": true,
+ "∾": true,
+ "∾̳": true,
+ "∿": true,
+ "â": true,
+ "â": true,
+ "´": true,
+ "´": true,
+ "а": true,
+ "æ": true,
+ "æ": true,
+ "⁡": true,
+ "𝔞": true,
+ "à": true,
+ "à": true,
+ "ℵ": true,
+ "ℵ": true,
+ "α": true,
+ "ā": true,
+ "⨿": true,
+ "&": true,
+ "&": true,
+ "∧": true,
+ "⩕": true,
+ "⩜": true,
+ "⩘": true,
+ "⩚": true,
+ "∠": true,
+ "⦤": true,
+ "∠": true,
+ "∡": true,
+ "⦨": true,
+ "⦩": true,
+ "⦪": true,
+ "⦫": true,
+ "⦬": true,
+ "⦭": true,
+ "⦮": true,
+ "⦯": true,
+ "∟": true,
+ "⊾": true,
+ "⦝": true,
+ "∢": true,
+ "Å": true,
+ "⍼": true,
+ "ą": true,
+ "𝕒": true,
+ "≈": true,
+ "⩰": true,
+ "⩯": true,
+ "≊": true,
+ "≋": true,
+ "'": true,
+ "≈": true,
+ "≊": true,
+ "å": true,
+ "å": true,
+ "𝒶": true,
+ "*": true,
+ "≈": true,
+ "≍": true,
+ "ã": true,
+ "ã": true,
+ "ä": true,
+ "ä": true,
+ "∳": true,
+ "⨑": true,
+ "⫭": true,
+ "≌": true,
+ "϶": true,
+ "‵": true,
+ "∽": true,
+ "⋍": true,
+ "⊽": true,
+ "⌅": true,
+ "⌅": true,
+ "⎵": true,
+ "⎶": true,
+ "≌": true,
+ "б": true,
+ "„": true,
+ "∵": true,
+ "∵": true,
+ "⦰": true,
+ "϶": true,
+ "ℬ": true,
+ "β": true,
+ "ℶ": true,
+ "≬": true,
+ "𝔟": true,
+ "⋂": true,
+ "◯": true,
+ "⋃": true,
+ "⨀": true,
+ "⨁": true,
+ "⨂": true,
+ "⨆": true,
+ "★": true,
+ "▽": true,
+ "△": true,
+ "⨄": true,
+ "⋁": true,
+ "⋀": true,
+ "⤍": true,
+ "⧫": true,
+ "▪": true,
+ "▴": true,
+ "▾": true,
+ "◂": true,
+ "▸": true,
+ "␣": true,
+ "▒": true,
+ "░": true,
+ "▓": true,
+ "█": true,
+ "=⃥": true,
+ "≡⃥": true,
+ "⌐": true,
+ "𝕓": true,
+ "⊥": true,
+ "⊥": true,
+ "⋈": true,
+ "╗": true,
+ "╔": true,
+ "╖": true,
+ "╓": true,
+ "═": true,
+ "╦": true,
+ "╩": true,
+ "╤": true,
+ "╧": true,
+ "╝": true,
+ "╚": true,
+ "╜": true,
+ "╙": true,
+ "║": true,
+ "╬": true,
+ "╣": true,
+ "╠": true,
+ "╫": true,
+ "╢": true,
+ "╟": true,
+ "⧉": true,
+ "╕": true,
+ "╒": true,
+ "┐": true,
+ "┌": true,
+ "─": true,
+ "╥": true,
+ "╨": true,
+ "┬": true,
+ "┴": true,
+ "⊟": true,
+ "⊞": true,
+ "⊠": true,
+ "╛": true,
+ "╘": true,
+ "┘": true,
+ "└": true,
+ "│": true,
+ "╪": true,
+ "╡": true,
+ "╞": true,
+ "┼": true,
+ "┤": true,
+ "├": true,
+ "‵": true,
+ "˘": true,
+ "¦": true,
+ "¦": true,
+ "𝒷": true,
+ "⁏": true,
+ "∽": true,
+ "⋍": true,
+ "\": true,
+ "⧅": true,
+ "⟈": true,
+ "•": true,
+ "•": true,
+ "≎": true,
+ "⪮": true,
+ "≏": true,
+ "≏": true,
+ "ć": true,
+ "∩": true,
+ "⩄": true,
+ "⩉": true,
+ "⩋": true,
+ "⩇": true,
+ "⩀": true,
+ "∩︀": true,
+ "⁁": true,
+ "ˇ": true,
+ "⩍": true,
+ "č": true,
+ "ç": true,
+ "ç": true,
+ "ĉ": true,
+ "⩌": true,
+ "⩐": true,
+ "ċ": true,
+ "¸": true,
+ "¸": true,
+ "⦲": true,
+ "¢": true,
+ "¢": true,
+ "·": true,
+ "𝔠": true,
+ "ч": true,
+ "✓": true,
+ "✓": true,
+ "χ": true,
+ "○": true,
+ "⧃": true,
+ "ˆ": true,
+ "≗": true,
+ "↺": true,
+ "↻": true,
+ "®": true,
+ "Ⓢ": true,
+ "⊛": true,
+ "⊚": true,
+ "⊝": true,
+ "≗": true,
+ "⨐": true,
+ "⫯": true,
+ "⧂": true,
+ "♣": true,
+ "♣": true,
+ ":": true,
+ "≔": true,
+ "≔": true,
+ ",": true,
+ "@": true,
+ "∁": true,
+ "∘": true,
+ "∁": true,
+ "ℂ": true,
+ "≅": true,
+ "⩭": true,
+ "∮": true,
+ "𝕔": true,
+ "∐": true,
+ "©": true,
+ "©": true,
+ "℗": true,
+ "↵": true,
+ "✗": true,
+ "𝒸": true,
+ "⫏": true,
+ "⫑": true,
+ "⫐": true,
+ "⫒": true,
+ "⋯": true,
+ "⤸": true,
+ "⤵": true,
+ "⋞": true,
+ "⋟": true,
+ "↶": true,
+ "⤽": true,
+ "∪": true,
+ "⩈": true,
+ "⩆": true,
+ "⩊": true,
+ "⊍": true,
+ "⩅": true,
+ "∪︀": true,
+ "↷": true,
+ "⤼": true,
+ "⋞": true,
+ "⋟": true,
+ "⋎": true,
+ "⋏": true,
+ "¤": true,
+ "¤": true,
+ "↶": true,
+ "↷": true,
+ "⋎": true,
+ "⋏": true,
+ "∲": true,
+ "∱": true,
+ "⌭": true,
+ "⇓": true,
+ "⥥": true,
+ "†": true,
+ "ℸ": true,
+ "↓": true,
+ "‐": true,
+ "⊣": true,
+ "⤏": true,
+ "˝": true,
+ "ď": true,
+ "д": true,
+ "ⅆ": true,
+ "‡": true,
+ "⇊": true,
+ "⩷": true,
+ "°": true,
+ "°": true,
+ "δ": true,
+ "⦱": true,
+ "⥿": true,
+ "𝔡": true,
+ "⇃": true,
+ "⇂": true,
+ "⋄": true,
+ "⋄": true,
+ "♦": true,
+ "♦": true,
+ "¨": true,
+ "ϝ": true,
+ "⋲": true,
+ "÷": true,
+ "÷": true,
+ "÷": true,
+ "⋇": true,
+ "⋇": true,
+ "ђ": true,
+ "⌞": true,
+ "⌍": true,
+ "$": true,
+ "𝕕": true,
+ "˙": true,
+ "≐": true,
+ "≑": true,
+ "∸": true,
+ "∔": true,
+ "⊡": true,
+ "⌆": true,
+ "↓": true,
+ "⇊": true,
+ "⇃": true,
+ "⇂": true,
+ "⤐": true,
+ "⌟": true,
+ "⌌": true,
+ "𝒹": true,
+ "ѕ": true,
+ "⧶": true,
+ "đ": true,
+ "⋱": true,
+ "▿": true,
+ "▾": true,
+ "⇵": true,
+ "⥯": true,
+ "⦦": true,
+ "џ": true,
+ "⟿": true,
+ "⩷": true,
+ "≑": true,
+ "é": true,
+ "é": true,
+ "⩮": true,
+ "ě": true,
+ "≖": true,
+ "ê": true,
+ "ê": true,
+ "≕": true,
+ "э": true,
+ "ė": true,
+ "ⅇ": true,
+ "≒": true,
+ "𝔢": true,
+ "⪚": true,
+ "è": true,
+ "è": true,
+ "⪖": true,
+ "⪘": true,
+ "⪙": true,
+ "⏧": true,
+ "ℓ": true,
+ "⪕": true,
+ "⪗": true,
+ "ē": true,
+ "∅": true,
+ "∅": true,
+ "∅": true,
+ " ": true,
+ " ": true,
+ " ": true,
+ "ŋ": true,
+ " ": true,
+ "ę": true,
+ "𝕖": true,
+ "⋕": true,
+ "⧣": true,
+ "⩱": true,
+ "ε": true,
+ "ε": true,
+ "ϵ": true,
+ "≖": true,
+ "≕": true,
+ "≂": true,
+ "⪖": true,
+ "⪕": true,
+ "=": true,
+ "≟": true,
+ "≡": true,
+ "⩸": true,
+ "⧥": true,
+ "≓": true,
+ "⥱": true,
+ "ℯ": true,
+ "≐": true,
+ "≂": true,
+ "η": true,
+ "ð": true,
+ "ð": true,
+ "ë": true,
+ "ë": true,
+ "€": true,
+ "!": true,
+ "∃": true,
+ "ℰ": true,
+ "ⅇ": true,
+ "≒": true,
+ "ф": true,
+ "♀": true,
+ "ffi": true,
+ "ff": true,
+ "ffl": true,
+ "𝔣": true,
+ "fi": true,
+ "fj": true,
+ "♭": true,
+ "fl": true,
+ "▱": true,
+ "ƒ": true,
+ "𝕗": true,
+ "∀": true,
+ "⋔": true,
+ "⫙": true,
+ "⨍": true,
+ "½": true,
+ "½": true,
+ "⅓": true,
+ "¼": true,
+ "¼": true,
+ "⅕": true,
+ "⅙": true,
+ "⅛": true,
+ "⅔": true,
+ "⅖": true,
+ "¾": true,
+ "¾": true,
+ "⅗": true,
+ "⅜": true,
+ "⅘": true,
+ "⅚": true,
+ "⅝": true,
+ "⅞": true,
+ "⁄": true,
+ "⌢": true,
+ "𝒻": true,
+ "≧": true,
+ "⪌": true,
+ "ǵ": true,
+ "γ": true,
+ "ϝ": true,
+ "⪆": true,
+ "ğ": true,
+ "ĝ": true,
+ "г": true,
+ "ġ": true,
+ "≥": true,
+ "⋛": true,
+ "≥": true,
+ "≧": true,
+ "⩾": true,
+ "⩾": true,
+ "⪩": true,
+ "⪀": true,
+ "⪂": true,
+ "⪄": true,
+ "⋛︀": true,
+ "⪔": true,
+ "𝔤": true,
+ "≫": true,
+ "⋙": true,
+ "ℷ": true,
+ "ѓ": true,
+ "≷": true,
+ "⪒": true,
+ "⪥": true,
+ "⪤": true,
+ "≩": true,
+ "⪊": true,
+ "⪊": true,
+ "⪈": true,
+ "⪈": true,
+ "≩": true,
+ "⋧": true,
+ "𝕘": true,
+ "`": true,
+ "ℊ": true,
+ "≳": true,
+ "⪎": true,
+ "⪐": true,
+ ">": true,
+ ">": true,
+ "⪧": true,
+ "⩺": true,
+ "⋗": true,
+ "⦕": true,
+ "⩼": true,
+ "⪆": true,
+ "⥸": true,
+ "⋗": true,
+ "⋛": true,
+ "⪌": true,
+ "≷": true,
+ "≳": true,
+ "≩︀": true,
+ "≩︀": true,
+ "⇔": true,
+ " ": true,
+ "½": true,
+ "ℋ": true,
+ "ъ": true,
+ "↔": true,
+ "⥈": true,
+ "↭": true,
+ "ℏ": true,
+ "ĥ": true,
+ "♥": true,
+ "♥": true,
+ "…": true,
+ "⊹": true,
+ "𝔥": true,
+ "⤥": true,
+ "⤦": true,
+ "⇿": true,
+ "∻": true,
+ "↩": true,
+ "↪": true,
+ "𝕙": true,
+ "―": true,
+ "𝒽": true,
+ "ℏ": true,
+ "ħ": true,
+ "⁃": true,
+ "‐": true,
+ "í": true,
+ "í": true,
+ "⁣": true,
+ "î": true,
+ "î": true,
+ "и": true,
+ "е": true,
+ "¡": true,
+ "¡": true,
+ "⇔": true,
+ "𝔦": true,
+ "ì": true,
+ "ì": true,
+ "ⅈ": true,
+ "⨌": true,
+ "∭": true,
+ "⧜": true,
+ "℩": true,
+ "ij": true,
+ "ī": true,
+ "ℑ": true,
+ "ℐ": true,
+ "ℑ": true,
+ "ı": true,
+ "⊷": true,
+ "Ƶ": true,
+ "∈": true,
+ "℅": true,
+ "∞": true,
+ "⧝": true,
+ "ı": true,
+ "∫": true,
+ "⊺": true,
+ "ℤ": true,
+ "⊺": true,
+ "⨗": true,
+ "⨼": true,
+ "ё": true,
+ "į": true,
+ "𝕚": true,
+ "ι": true,
+ "⨼": true,
+ "¿": true,
+ "¿": true,
+ "𝒾": true,
+ "∈": true,
+ "⋹": true,
+ "⋵": true,
+ "⋴": true,
+ "⋳": true,
+ "∈": true,
+ "⁢": true,
+ "ĩ": true,
+ "і": true,
+ "ï": true,
+ "ï": true,
+ "ĵ": true,
+ "й": true,
+ "𝔧": true,
+ "ȷ": true,
+ "𝕛": true,
+ "𝒿": true,
+ "ј": true,
+ "є": true,
+ "κ": true,
+ "ϰ": true,
+ "ķ": true,
+ "к": true,
+ "𝔨": true,
+ "ĸ": true,
+ "х": true,
+ "ќ": true,
+ "𝕜": true,
+ "𝓀": true,
+ "⇚": true,
+ "⇐": true,
+ "⤛": true,
+ "⤎": true,
+ "≦": true,
+ "⪋": true,
+ "⥢": true,
+ "ĺ": true,
+ "⦴": true,
+ "ℒ": true,
+ "λ": true,
+ "〈": true,
+ "⦑": true,
+ "⟨": true,
+ "⪅": true,
+ "«": true,
+ "«": true,
+ "←": true,
+ "⇤": true,
+ "⤟": true,
+ "⤝": true,
+ "↩": true,
+ "↫": true,
+ "⤹": true,
+ "⥳": true,
+ "↢": true,
+ "⪫": true,
+ "⤙": true,
+ "⪭": true,
+ "⪭︀": true,
+ "⤌": true,
+ "❲": true,
+ "{": true,
+ "[": true,
+ "⦋": true,
+ "⦏": true,
+ "⦍": true,
+ "ľ": true,
+ "ļ": true,
+ "⌈": true,
+ "{": true,
+ "л": true,
+ "⤶": true,
+ "“": true,
+ "„": true,
+ "⥧": true,
+ "⥋": true,
+ "↲": true,
+ "≤": true,
+ "←": true,
+ "↢": true,
+ "↽": true,
+ "↼": true,
+ "⇇": true,
+ "↔": true,
+ "⇆": true,
+ "⇋": true,
+ "↭": true,
+ "⋋": true,
+ "⋚": true,
+ "≤": true,
+ "≦": true,
+ "⩽": true,
+ "⩽": true,
+ "⪨": true,
+ "⩿": true,
+ "⪁": true,
+ "⪃": true,
+ "⋚︀": true,
+ "⪓": true,
+ "⪅": true,
+ "⋖": true,
+ "⋚": true,
+ "⪋": true,
+ "≶": true,
+ "≲": true,
+ "⥼": true,
+ "⌊": true,
+ "𝔩": true,
+ "≶": true,
+ "⪑": true,
+ "↽": true,
+ "↼": true,
+ "⥪": true,
+ "▄": true,
+ "љ": true,
+ "≪": true,
+ "⇇": true,
+ "⌞": true,
+ "⥫": true,
+ "◺": true,
+ "ŀ": true,
+ "⎰": true,
+ "⎰": true,
+ "≨": true,
+ "⪉": true,
+ "⪉": true,
+ "⪇": true,
+ "⪇": true,
+ "≨": true,
+ "⋦": true,
+ "⟬": true,
+ "⇽": true,
+ "⟦": true,
+ "⟵": true,
+ "⟷": true,
+ "⟼": true,
+ "⟶": true,
+ "↫": true,
+ "↬": true,
+ "⦅": true,
+ "𝕝": true,
+ "⨭": true,
+ "⨴": true,
+ "∗": true,
+ "_": true,
+ "◊": true,
+ "◊": true,
+ "⧫": true,
+ "(": true,
+ "⦓": true,
+ "⇆": true,
+ "⌟": true,
+ "⇋": true,
+ "⥭": true,
+ "": true,
+ "⊿": true,
+ "‹": true,
+ "𝓁": true,
+ "↰": true,
+ "≲": true,
+ "⪍": true,
+ "⪏": true,
+ "[": true,
+ "‘": true,
+ "‚": true,
+ "ł": true,
+ "<": true,
+ "<": true,
+ "⪦": true,
+ "⩹": true,
+ "⋖": true,
+ "⋋": true,
+ "⋉": true,
+ "⥶": true,
+ "⩻": true,
+ "⦖": true,
+ "◃": true,
+ "⊴": true,
+ "◂": true,
+ "⥊": true,
+ "⥦": true,
+ "≨︀": true,
+ "≨︀": true,
+ "∺": true,
+ "¯": true,
+ "¯": true,
+ "♂": true,
+ "✠": true,
+ "✠": true,
+ "↦": true,
+ "↦": true,
+ "↧": true,
+ "↤": true,
+ "↥": true,
+ "▮": true,
+ "⨩": true,
+ "м": true,
+ "—": true,
+ "∡": true,
+ "𝔪": true,
+ "℧": true,
+ "µ": true,
+ "µ": true,
+ "∣": true,
+ "*": true,
+ "⫰": true,
+ "·": true,
+ "·": true,
+ "−": true,
+ "⊟": true,
+ "∸": true,
+ "⨪": true,
+ "⫛": true,
+ "…": true,
+ "∓": true,
+ "⊧": true,
+ "𝕞": true,
+ "∓": true,
+ "𝓂": true,
+ "∾": true,
+ "μ": true,
+ "⊸": true,
+ "⊸": true,
+ "⋙̸": true,
+ "≫⃒": true,
+ "≫̸": true,
+ "⇍": true,
+ "⇎": true,
+ "⋘̸": true,
+ "≪⃒": true,
+ "≪̸": true,
+ "⇏": true,
+ "⊯": true,
+ "⊮": true,
+ "∇": true,
+ "ń": true,
+ "∠⃒": true,
+ "≉": true,
+ "⩰̸": true,
+ "≋̸": true,
+ "ʼn": true,
+ "≉": true,
+ "♮": true,
+ "♮": true,
+ "ℕ": true,
+ " ": true,
+ " ": true,
+ "≎̸": true,
+ "≏̸": true,
+ "⩃": true,
+ "ň": true,
+ "ņ": true,
+ "≇": true,
+ "⩭̸": true,
+ "⩂": true,
+ "н": true,
+ "–": true,
+ "≠": true,
+ "⇗": true,
+ "⤤": true,
+ "↗": true,
+ "↗": true,
+ "≐̸": true,
+ "≢": true,
+ "⤨": true,
+ "≂̸": true,
+ "∄": true,
+ "∄": true,
+ "𝔫": true,
+ "≧̸": true,
+ "≱": true,
+ "≱": true,
+ "≧̸": true,
+ "⩾̸": true,
+ "⩾̸": true,
+ "≵": true,
+ "≯": true,
+ "≯": true,
+ "⇎": true,
+ "↮": true,
+ "⫲": true,
+ "∋": true,
+ "⋼": true,
+ "⋺": true,
+ "∋": true,
+ "њ": true,
+ "⇍": true,
+ "≦̸": true,
+ "↚": true,
+ "‥": true,
+ "≰": true,
+ "↚": true,
+ "↮": true,
+ "≰": true,
+ "≦̸": true,
+ "⩽̸": true,
+ "⩽̸": true,
+ "≮": true,
+ "≴": true,
+ "≮": true,
+ "⋪": true,
+ "⋬": true,
+ "∤": true,
+ "𝕟": true,
+ "¬": true,
+ "¬": true,
+ "∉": true,
+ "⋹̸": true,
+ "⋵̸": true,
+ "∉": true,
+ "⋷": true,
+ "⋶": true,
+ "∌": true,
+ "∌": true,
+ "⋾": true,
+ "⋽": true,
+ "∦": true,
+ "∦": true,
+ "⫽⃥": true,
+ "∂̸": true,
+ "⨔": true,
+ "⊀": true,
+ "⋠": true,
+ "⪯̸": true,
+ "⊀": true,
+ "⪯̸": true,
+ "⇏": true,
+ "↛": true,
+ "⤳̸": true,
+ "↝̸": true,
+ "↛": true,
+ "⋫": true,
+ "⋭": true,
+ "⊁": true,
+ "⋡": true,
+ "⪰̸": true,
+ "𝓃": true,
+ "∤": true,
+ "∦": true,
+ "≁": true,
+ "≄": true,
+ "≄": true,
+ "∤": true,
+ "∦": true,
+ "⋢": true,
+ "⋣": true,
+ "⊄": true,
+ "⫅̸": true,
+ "⊈": true,
+ "⊂⃒": true,
+ "⊈": true,
+ "⫅̸": true,
+ "⊁": true,
+ "⪰̸": true,
+ "⊅": true,
+ "⫆̸": true,
+ "⊉": true,
+ "⊃⃒": true,
+ "⊉": true,
+ "⫆̸": true,
+ "≹": true,
+ "ñ": true,
+ "ñ": true,
+ "≸": true,
+ "⋪": true,
+ "⋬": true,
+ "⋫": true,
+ "⋭": true,
+ "ν": true,
+ "#": true,
+ "№": true,
+ " ": true,
+ "⊭": true,
+ "⤄": true,
+ "≍⃒": true,
+ "⊬": true,
+ "≥⃒": true,
+ ">⃒": true,
+ "⧞": true,
+ "⤂": true,
+ "≤⃒": true,
+ "<⃒": true,
+ "⊴⃒": true,
+ "⤃": true,
+ "⊵⃒": true,
+ "∼⃒": true,
+ "⇖": true,
+ "⤣": true,
+ "↖": true,
+ "↖": true,
+ "⤧": true,
+ "Ⓢ": true,
+ "ó": true,
+ "ó": true,
+ "⊛": true,
+ "⊚": true,
+ "ô": true,
+ "ô": true,
+ "о": true,
+ "⊝": true,
+ "ő": true,
+ "⨸": true,
+ "⊙": true,
+ "⦼": true,
+ "œ": true,
+ "⦿": true,
+ "𝔬": true,
+ "˛": true,
+ "ò": true,
+ "ò": true,
+ "⧁": true,
+ "⦵": true,
+ "Ω": true,
+ "∮": true,
+ "↺": true,
+ "⦾": true,
+ "⦻": true,
+ "‾": true,
+ "⧀": true,
+ "ō": true,
+ "ω": true,
+ "ο": true,
+ "⦶": true,
+ "⊖": true,
+ "𝕠": true,
+ "⦷": true,
+ "⦹": true,
+ "⊕": true,
+ "∨": true,
+ "↻": true,
+ "⩝": true,
+ "ℴ": true,
+ "ℴ": true,
+ "ª": true,
+ "ª": true,
+ "º": true,
+ "º": true,
+ "⊶": true,
+ "⩖": true,
+ "⩗": true,
+ "⩛": true,
+ "ℴ": true,
+ "ø": true,
+ "ø": true,
+ "⊘": true,
+ "õ": true,
+ "õ": true,
+ "⊗": true,
+ "⨶": true,
+ "ö": true,
+ "ö": true,
+ "⌽": true,
+ "∥": true,
+ "¶": true,
+ "¶": true,
+ "∥": true,
+ "⫳": true,
+ "⫽": true,
+ "∂": true,
+ "п": true,
+ "%": true,
+ ".": true,
+ "‰": true,
+ "⊥": true,
+ "‱": true,
+ "𝔭": true,
+ "φ": true,
+ "ϕ": true,
+ "ℳ": true,
+ "☎": true,
+ "π": true,
+ "⋔": true,
+ "ϖ": true,
+ "ℏ": true,
+ "ℎ": true,
+ "ℏ": true,
+ "+": true,
+ "⨣": true,
+ "⊞": true,
+ "⨢": true,
+ "∔": true,
+ "⨥": true,
+ "⩲": true,
+ "±": true,
+ "±": true,
+ "⨦": true,
+ "⨧": true,
+ "±": true,
+ "⨕": true,
+ "𝕡": true,
+ "£": true,
+ "£": true,
+ "≺": true,
+ "⪳": true,
+ "⪷": true,
+ "≼": true,
+ "⪯": true,
+ "≺": true,
+ "⪷": true,
+ "≼": true,
+ "⪯": true,
+ "⪹": true,
+ "⪵": true,
+ "⋨": true,
+ "≾": true,
+ "′": true,
+ "ℙ": true,
+ "⪵": true,
+ "⪹": true,
+ "⋨": true,
+ "∏": true,
+ "⌮": true,
+ "⌒": true,
+ "⌓": true,
+ "∝": true,
+ "∝": true,
+ "≾": true,
+ "⊰": true,
+ "𝓅": true,
+ "ψ": true,
+ " ": true,
+ "𝔮": true,
+ "⨌": true,
+ "𝕢": true,
+ "⁗": true,
+ "𝓆": true,
+ "ℍ": true,
+ "⨖": true,
+ "?": true,
+ "≟": true,
+ """: true,
+ """: true,
+ "⇛": true,
+ "⇒": true,
+ "⤜": true,
+ "⤏": true,
+ "⥤": true,
+ "∽̱": true,
+ "ŕ": true,
+ "√": true,
+ "⦳": true,
+ "〉": true,
+ "⦒": true,
+ "⦥": true,
+ "⟩": true,
+ "»": true,
+ "»": true,
+ "→": true,
+ "⥵": true,
+ "⇥": true,
+ "⤠": true,
+ "⤳": true,
+ "⤞": true,
+ "↪": true,
+ "↬": true,
+ "⥅": true,
+ "⥴": true,
+ "↣": true,
+ "↝": true,
+ "⤚": true,
+ "∶": true,
+ "ℚ": true,
+ "⤍": true,
+ "❳": true,
+ "}": true,
+ "]": true,
+ "⦌": true,
+ "⦎": true,
+ "⦐": true,
+ "ř": true,
+ "ŗ": true,
+ "⌉": true,
+ "}": true,
+ "р": true,
+ "⤷": true,
+ "⥩": true,
+ "”": true,
+ "”": true,
+ "↳": true,
+ "ℜ": true,
+ "ℛ": true,
+ "ℜ": true,
+ "ℝ": true,
+ "▭": true,
+ "®": true,
+ "®": true,
+ "⥽": true,
+ "⌋": true,
+ "𝔯": true,
+ "⇁": true,
+ "⇀": true,
+ "⥬": true,
+ "ρ": true,
+ "ϱ": true,
+ "→": true,
+ "↣": true,
+ "⇁": true,
+ "⇀": true,
+ "⇄": true,
+ "⇌": true,
+ "⇉": true,
+ "↝": true,
+ "⋌": true,
+ "˚": true,
+ "≓": true,
+ "⇄": true,
+ "⇌": true,
+ "": true,
+ "⎱": true,
+ "⎱": true,
+ "⫮": true,
+ "⟭": true,
+ "⇾": true,
+ "⟧": true,
+ "⦆": true,
+ "𝕣": true,
+ "⨮": true,
+ "⨵": true,
+ ")": true,
+ "⦔": true,
+ "⨒": true,
+ "⇉": true,
+ "›": true,
+ "𝓇": true,
+ "↱": true,
+ "]": true,
+ "’": true,
+ "’": true,
+ "⋌": true,
+ "⋊": true,
+ "▹": true,
+ "⊵": true,
+ "▸": true,
+ "⧎": true,
+ "⥨": true,
+ "℞": true,
+ "ś": true,
+ "‚": true,
+ "≻": true,
+ "⪴": true,
+ "⪸": true,
+ "š": true,
+ "≽": true,
+ "⪰": true,
+ "ş": true,
+ "ŝ": true,
+ "⪶": true,
+ "⪺": true,
+ "⋩": true,
+ "⨓": true,
+ "≿": true,
+ "с": true,
+ "⋅": true,
+ "⊡": true,
+ "⩦": true,
+ "⇘": true,
+ "⤥": true,
+ "↘": true,
+ "↘": true,
+ "§": true,
+ "§": true,
+ ";": true,
+ "⤩": true,
+ "∖": true,
+ "∖": true,
+ "✶": true,
+ "𝔰": true,
+ "⌢": true,
+ "♯": true,
+ "щ": true,
+ "ш": true,
+ "∣": true,
+ "∥": true,
+ "­": true,
+ "": true,
+ "σ": true,
+ "ς": true,
+ "ς": true,
+ "∼": true,
+ "⩪": true,
+ "≃": true,
+ "≃": true,
+ "⪞": true,
+ "⪠": true,
+ "⪝": true,
+ "⪟": true,
+ "≆": true,
+ "⨤": true,
+ "⥲": true,
+ "←": true,
+ "∖": true,
+ "⨳": true,
+ "⧤": true,
+ "∣": true,
+ "⌣": true,
+ "⪪": true,
+ "⪬": true,
+ "⪬︀": true,
+ "ь": true,
+ "/": true,
+ "⧄": true,
+ "⌿": true,
+ "𝕤": true,
+ "♠": true,
+ "♠": true,
+ "∥": true,
+ "⊓": true,
+ "⊓︀": true,
+ "⊔": true,
+ "⊔︀": true,
+ "⊏": true,
+ "⊑": true,
+ "⊏": true,
+ "⊑": true,
+ "⊐": true,
+ "⊒": true,
+ "⊐": true,
+ "⊒": true,
+ "□": true,
+ "□": true,
+ "▪": true,
+ "▪": true,
+ "→": true,
+ "𝓈": true,
+ "∖": true,
+ "⌣": true,
+ "⋆": true,
+ "☆": true,
+ "★": true,
+ "ϵ": true,
+ "ϕ": true,
+ "¯": true,
+ "⊂": true,
+ "⫅": true,
+ "⪽": true,
+ "⊆": true,
+ "⫃": true,
+ "⫁": true,
+ "⫋": true,
+ "⊊": true,
+ "⪿": true,
+ "⥹": true,
+ "⊂": true,
+ "⊆": true,
+ "⫅": true,
+ "⊊": true,
+ "⫋": true,
+ "⫇": true,
+ "⫕": true,
+ "⫓": true,
+ "≻": true,
+ "⪸": true,
+ "≽": true,
+ "⪰": true,
+ "⪺": true,
+ "⪶": true,
+ "⋩": true,
+ "≿": true,
+ "∑": true,
+ "♪": true,
+ "¹": true,
+ "¹": true,
+ "²": true,
+ "²": true,
+ "³": true,
+ "³": true,
+ "⊃": true,
+ "⫆": true,
+ "⪾": true,
+ "⫘": true,
+ "⊇": true,
+ "⫄": true,
+ "⟉": true,
+ "⫗": true,
+ "⥻": true,
+ "⫂": true,
+ "⫌": true,
+ "⊋": true,
+ "⫀": true,
+ "⊃": true,
+ "⊇": true,
+ "⫆": true,
+ "⊋": true,
+ "⫌": true,
+ "⫈": true,
+ "⫔": true,
+ "⫖": true,
+ "⇙": true,
+ "⤦": true,
+ "↙": true,
+ "↙": true,
+ "⤪": true,
+ "ß": true,
+ "ß": true,
+ "⌖": true,
+ "τ": true,
+ "⎴": true,
+ "ť": true,
+ "ţ": true,
+ "т": true,
+ "⃛": true,
+ "⌕": true,
+ "𝔱": true,
+ "∴": true,
+ "∴": true,
+ "θ": true,
+ "ϑ": true,
+ "ϑ": true,
+ "≈": true,
+ "∼": true,
+ " ": true,
+ "≈": true,
+ "∼": true,
+ "þ": true,
+ "þ": true,
+ "˜": true,
+ "×": true,
+ "×": true,
+ "⊠": true,
+ "⨱": true,
+ "⨰": true,
+ "∭": true,
+ "⤨": true,
+ "⊤": true,
+ "⌶": true,
+ "⫱": true,
+ "𝕥": true,
+ "⫚": true,
+ "⤩": true,
+ "‴": true,
+ "™": true,
+ "▵": true,
+ "▿": true,
+ "◃": true,
+ "⊴": true,
+ "≜": true,
+ "▹": true,
+ "⊵": true,
+ "◬": true,
+ "≜": true,
+ "⨺": true,
+ "⨹": true,
+ "⧍": true,
+ "⨻": true,
+ "⏢": true,
+ "𝓉": true,
+ "ц": true,
+ "ћ": true,
+ "ŧ": true,
+ "≬": true,
+ "↞": true,
+ "↠": true,
+ "⇑": true,
+ "⥣": true,
+ "ú": true,
+ "ú": true,
+ "↑": true,
+ "ў": true,
+ "ŭ": true,
+ "û": true,
+ "û": true,
+ "у": true,
+ "⇅": true,
+ "ű": true,
+ "⥮": true,
+ "⥾": true,
+ "𝔲": true,
+ "ù": true,
+ "ù": true,
+ "↿": true,
+ "↾": true,
+ "▀": true,
+ "⌜": true,
+ "⌜": true,
+ "⌏": true,
+ "◸": true,
+ "ū": true,
+ "¨": true,
+ "¨": true,
+ "ų": true,
+ "𝕦": true,
+ "↑": true,
+ "↕": true,
+ "↿": true,
+ "↾": true,
+ "⊎": true,
+ "υ": true,
+ "ϒ": true,
+ "υ": true,
+ "⇈": true,
+ "⌝": true,
+ "⌝": true,
+ "⌎": true,
+ "ů": true,
+ "◹": true,
+ "𝓊": true,
+ "⋰": true,
+ "ũ": true,
+ "▵": true,
+ "▴": true,
+ "⇈": true,
+ "ü": true,
+ "ü": true,
+ "⦧": true,
+ "⇕": true,
+ "⫨": true,
+ "⫩": true,
+ "⊨": true,
+ "⦜": true,
+ "ϵ": true,
+ "ϰ": true,
+ "∅": true,
+ "ϕ": true,
+ "ϖ": true,
+ "∝": true,
+ "↕": true,
+ "ϱ": true,
+ "ς": true,
+ "⊊︀": true,
+ "⫋︀": true,
+ "⊋︀": true,
+ "⫌︀": true,
+ "ϑ": true,
+ "⊲": true,
+ "⊳": true,
+ "в": true,
+ "⊢": true,
+ "∨": true,
+ "⊻": true,
+ "≚": true,
+ "⋮": true,
+ "|": true,
+ "|": true,
+ "𝔳": true,
+ "⊲": true,
+ "⊂⃒": true,
+ "⊃⃒": true,
+ "𝕧": true,
+ "∝": true,
+ "⊳": true,
+ "𝓋": true,
+ "⫋︀": true,
+ "⊊︀": true,
+ "⫌︀": true,
+ "⊋︀": true,
+ "⦚": true,
+ "ŵ": true,
+ "⩟": true,
+ "∧": true,
+ "≙": true,
+ "℘": true,
+ "𝔴": true,
+ "𝕨": true,
+ "℘": true,
+ "≀": true,
+ "≀": true,
+ "𝓌": true,
+ "⋂": true,
+ "◯": true,
+ "⋃": true,
+ "▽": true,
+ "𝔵": true,
+ "⟺": true,
+ "⟷": true,
+ "ξ": true,
+ "⟸": true,
+ "⟵": true,
+ "⟼": true,
+ "⋻": true,
+ "⨀": true,
+ "𝕩": true,
+ "⨁": true,
+ "⨂": true,
+ "⟹": true,
+ "⟶": true,
+ "𝓍": true,
+ "⨆": true,
+ "⨄": true,
+ "△": true,
+ "⋁": true,
+ "⋀": true,
+ "ý": true,
+ "ý": true,
+ "я": true,
+ "ŷ": true,
+ "ы": true,
+ "¥": true,
+ "¥": true,
+ "𝔶": true,
+ "ї": true,
+ "𝕪": true,
+ "𝓎": true,
+ "ю": true,
+ "ÿ": true,
+ "ÿ": true,
+ "ź": true,
+ "ž": true,
+ "з": true,
+ "ż": true,
+ "ℨ": true,
+ "ζ": true,
+ "𝔷": true,
+ "ж": true,
+ "⇝": true,
+ "𝕫": true,
+ "𝓏": true,
+ "": true,
+ "": true,
+}
diff --git a/vendor/github.com/russross/blackfriday/v2/esc.go b/vendor/github.com/russross/blackfriday/v2/esc.go
new file mode 100644
index 00000000000..6ab60102c9b
--- /dev/null
+++ b/vendor/github.com/russross/blackfriday/v2/esc.go
@@ -0,0 +1,70 @@
+package blackfriday
+
+import (
+ "html"
+ "io"
+)
+
+var htmlEscaper = [256][]byte{
+ '&': []byte("&"),
+ '<': []byte("<"),
+ '>': []byte(">"),
+ '"': []byte("""),
+}
+
+func escapeHTML(w io.Writer, s []byte) {
+ escapeEntities(w, s, false)
+}
+
+func escapeAllHTML(w io.Writer, s []byte) {
+ escapeEntities(w, s, true)
+}
+
+func escapeEntities(w io.Writer, s []byte, escapeValidEntities bool) {
+ var start, end int
+ for end < len(s) {
+ escSeq := htmlEscaper[s[end]]
+ if escSeq != nil {
+ isEntity, entityEnd := nodeIsEntity(s, end)
+ if isEntity && !escapeValidEntities {
+ w.Write(s[start : entityEnd+1])
+ start = entityEnd + 1
+ } else {
+ w.Write(s[start:end])
+ w.Write(escSeq)
+ start = end + 1
+ }
+ }
+ end++
+ }
+ if start < len(s) && end <= len(s) {
+ w.Write(s[start:end])
+ }
+}
+
+func nodeIsEntity(s []byte, end int) (isEntity bool, endEntityPos int) {
+ isEntity = false
+ endEntityPos = end + 1
+
+ if s[end] == '&' {
+ for endEntityPos < len(s) {
+ if s[endEntityPos] == ';' {
+ if entities[string(s[end:endEntityPos+1])] {
+ isEntity = true
+ break
+ }
+ }
+ if !isalnum(s[endEntityPos]) && s[endEntityPos] != '&' && s[endEntityPos] != '#' {
+ break
+ }
+ endEntityPos++
+ }
+ }
+
+ return isEntity, endEntityPos
+}
+
+func escLink(w io.Writer, text []byte) {
+ unesc := html.UnescapeString(string(text))
+ escapeHTML(w, []byte(unesc))
+}
diff --git a/vendor/github.com/russross/blackfriday/v2/html.go b/vendor/github.com/russross/blackfriday/v2/html.go
new file mode 100644
index 00000000000..cb4f26e30fd
--- /dev/null
+++ b/vendor/github.com/russross/blackfriday/v2/html.go
@@ -0,0 +1,952 @@
+//
+// Blackfriday Markdown Processor
+// Available at http://github.com/russross/blackfriday
+//
+// Copyright © 2011 Russ Ross .
+// Distributed under the Simplified BSD License.
+// See README.md for details.
+//
+
+//
+//
+// HTML rendering backend
+//
+//
+
+package blackfriday
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "regexp"
+ "strings"
+)
+
+// HTMLFlags control optional behavior of HTML renderer.
+type HTMLFlags int
+
+// HTML renderer configuration options.
+const (
+ HTMLFlagsNone HTMLFlags = 0
+ SkipHTML HTMLFlags = 1 << iota // Skip preformatted HTML blocks
+ SkipImages // Skip embedded images
+ SkipLinks // Skip all links
+ Safelink // Only link to trusted protocols
+ NofollowLinks // Only link with rel="nofollow"
+ NoreferrerLinks // Only link with rel="noreferrer"
+ NoopenerLinks // Only link with rel="noopener"
+ HrefTargetBlank // Add a blank target
+ CompletePage // Generate a complete HTML page
+ UseXHTML // Generate XHTML output instead of HTML
+ FootnoteReturnLinks // Generate a link at the end of a footnote to return to the source
+ Smartypants // Enable smart punctuation substitutions
+ SmartypantsFractions // Enable smart fractions (with Smartypants)
+ SmartypantsDashes // Enable smart dashes (with Smartypants)
+ SmartypantsLatexDashes // Enable LaTeX-style dashes (with Smartypants)
+ SmartypantsAngledQuotes // Enable angled double quotes (with Smartypants) for double quotes rendering
+ SmartypantsQuotesNBSP // Enable « French guillemets » (with Smartypants)
+ TOC // Generate a table of contents
+)
+
+var (
+ htmlTagRe = regexp.MustCompile("(?i)^" + htmlTag)
+)
+
+const (
+ htmlTag = "(?:" + openTag + "|" + closeTag + "|" + htmlComment + "|" +
+ processingInstruction + "|" + declaration + "|" + cdata + ")"
+ closeTag = "" + tagName + "\\s*[>]"
+ openTag = "<" + tagName + attribute + "*" + "\\s*/?>"
+ attribute = "(?:" + "\\s+" + attributeName + attributeValueSpec + "?)"
+ attributeValue = "(?:" + unquotedValue + "|" + singleQuotedValue + "|" + doubleQuotedValue + ")"
+ attributeValueSpec = "(?:" + "\\s*=" + "\\s*" + attributeValue + ")"
+ attributeName = "[a-zA-Z_:][a-zA-Z0-9:._-]*"
+ cdata = ""
+ declaration = "]*>"
+ doubleQuotedValue = "\"[^\"]*\""
+ htmlComment = "|"
+ processingInstruction = "[<][?].*?[?][>]"
+ singleQuotedValue = "'[^']*'"
+ tagName = "[A-Za-z][A-Za-z0-9-]*"
+ unquotedValue = "[^\"'=<>`\\x00-\\x20]+"
+)
+
+// HTMLRendererParameters is a collection of supplementary parameters tweaking
+// the behavior of various parts of HTML renderer.
+type HTMLRendererParameters struct {
+ // Prepend this text to each relative URL.
+ AbsolutePrefix string
+ // Add this text to each footnote anchor, to ensure uniqueness.
+ FootnoteAnchorPrefix string
+ // Show this text inside the tag for a footnote return link, if the
+ // HTML_FOOTNOTE_RETURN_LINKS flag is enabled. If blank, the string
+ // [return] is used.
+ FootnoteReturnLinkContents string
+ // If set, add this text to the front of each Heading ID, to ensure
+ // uniqueness.
+ HeadingIDPrefix string
+ // If set, add this text to the back of each Heading ID, to ensure uniqueness.
+ HeadingIDSuffix string
+ // Increase heading levels: if the offset is 1, becomes etc.
+ // Negative offset is also valid.
+ // Resulting levels are clipped between 1 and 6.
+ HeadingLevelOffset int
+
+ Title string // Document title (used if CompletePage is set)
+ CSS string // Optional CSS file URL (used if CompletePage is set)
+ Icon string // Optional icon file URL (used if CompletePage is set)
+
+ Flags HTMLFlags // Flags allow customizing this renderer's behavior
+}
+
+// HTMLRenderer is a type that implements the Renderer interface for HTML output.
+//
+// Do not create this directly, instead use the NewHTMLRenderer function.
+type HTMLRenderer struct {
+ HTMLRendererParameters
+
+ closeTag string // how to end singleton tags: either " />" or ">"
+
+ // Track heading IDs to prevent ID collision in a single generation.
+ headingIDs map[string]int
+
+ lastOutputLen int
+ disableTags int
+
+ sr *SPRenderer
+}
+
+const (
+ xhtmlClose = " />"
+ htmlClose = ">"
+)
+
+// NewHTMLRenderer creates and configures an HTMLRenderer object, which
+// satisfies the Renderer interface.
+func NewHTMLRenderer(params HTMLRendererParameters) *HTMLRenderer {
+ // configure the rendering engine
+ closeTag := htmlClose
+ if params.Flags&UseXHTML != 0 {
+ closeTag = xhtmlClose
+ }
+
+ if params.FootnoteReturnLinkContents == "" {
+ // U+FE0E is VARIATION SELECTOR-15.
+ // It suppresses automatic emoji presentation of the preceding
+ // U+21A9 LEFTWARDS ARROW WITH HOOK on iOS and iPadOS.
+ params.FootnoteReturnLinkContents = "↩\ufe0e"
+ }
+
+ return &HTMLRenderer{
+ HTMLRendererParameters: params,
+
+ closeTag: closeTag,
+ headingIDs: make(map[string]int),
+
+ sr: NewSmartypantsRenderer(params.Flags),
+ }
+}
+
+func isHTMLTag(tag []byte, tagname string) bool {
+ found, _ := findHTMLTagPos(tag, tagname)
+ return found
+}
+
+// Look for a character, but ignore it when it's in any kind of quotes, it
+// might be JavaScript
+func skipUntilCharIgnoreQuotes(html []byte, start int, char byte) int {
+ inSingleQuote := false
+ inDoubleQuote := false
+ inGraveQuote := false
+ i := start
+ for i < len(html) {
+ switch {
+ case html[i] == char && !inSingleQuote && !inDoubleQuote && !inGraveQuote:
+ return i
+ case html[i] == '\'':
+ inSingleQuote = !inSingleQuote
+ case html[i] == '"':
+ inDoubleQuote = !inDoubleQuote
+ case html[i] == '`':
+ inGraveQuote = !inGraveQuote
+ }
+ i++
+ }
+ return start
+}
+
+func findHTMLTagPos(tag []byte, tagname string) (bool, int) {
+ i := 0
+ if i < len(tag) && tag[0] != '<' {
+ return false, -1
+ }
+ i++
+ i = skipSpace(tag, i)
+
+ if i < len(tag) && tag[i] == '/' {
+ i++
+ }
+
+ i = skipSpace(tag, i)
+ j := 0
+ for ; i < len(tag); i, j = i+1, j+1 {
+ if j >= len(tagname) {
+ break
+ }
+
+ if strings.ToLower(string(tag[i]))[0] != tagname[j] {
+ return false, -1
+ }
+ }
+
+ if i == len(tag) {
+ return false, -1
+ }
+
+ rightAngle := skipUntilCharIgnoreQuotes(tag, i, '>')
+ if rightAngle >= i {
+ return true, rightAngle
+ }
+
+ return false, -1
+}
+
+func skipSpace(tag []byte, i int) int {
+ for i < len(tag) && isspace(tag[i]) {
+ i++
+ }
+ return i
+}
+
+func isRelativeLink(link []byte) (yes bool) {
+ // a tag begin with '#'
+ if link[0] == '#' {
+ return true
+ }
+
+ // link begin with '/' but not '//', the second maybe a protocol relative link
+ if len(link) >= 2 && link[0] == '/' && link[1] != '/' {
+ return true
+ }
+
+ // only the root '/'
+ if len(link) == 1 && link[0] == '/' {
+ return true
+ }
+
+ // current directory : begin with "./"
+ if bytes.HasPrefix(link, []byte("./")) {
+ return true
+ }
+
+ // parent directory : begin with "../"
+ if bytes.HasPrefix(link, []byte("../")) {
+ return true
+ }
+
+ return false
+}
+
+func (r *HTMLRenderer) ensureUniqueHeadingID(id string) string {
+ for count, found := r.headingIDs[id]; found; count, found = r.headingIDs[id] {
+ tmp := fmt.Sprintf("%s-%d", id, count+1)
+
+ if _, tmpFound := r.headingIDs[tmp]; !tmpFound {
+ r.headingIDs[id] = count + 1
+ id = tmp
+ } else {
+ id = id + "-1"
+ }
+ }
+
+ if _, found := r.headingIDs[id]; !found {
+ r.headingIDs[id] = 0
+ }
+
+ return id
+}
+
+func (r *HTMLRenderer) addAbsPrefix(link []byte) []byte {
+ if r.AbsolutePrefix != "" && isRelativeLink(link) && link[0] != '.' {
+ newDest := r.AbsolutePrefix
+ if link[0] != '/' {
+ newDest += "/"
+ }
+ newDest += string(link)
+ return []byte(newDest)
+ }
+ return link
+}
+
+func appendLinkAttrs(attrs []string, flags HTMLFlags, link []byte) []string {
+ if isRelativeLink(link) {
+ return attrs
+ }
+ val := []string{}
+ if flags&NofollowLinks != 0 {
+ val = append(val, "nofollow")
+ }
+ if flags&NoreferrerLinks != 0 {
+ val = append(val, "noreferrer")
+ }
+ if flags&NoopenerLinks != 0 {
+ val = append(val, "noopener")
+ }
+ if flags&HrefTargetBlank != 0 {
+ attrs = append(attrs, "target=\"_blank\"")
+ }
+ if len(val) == 0 {
+ return attrs
+ }
+ attr := fmt.Sprintf("rel=%q", strings.Join(val, " "))
+ return append(attrs, attr)
+}
+
+func isMailto(link []byte) bool {
+ return bytes.HasPrefix(link, []byte("mailto:"))
+}
+
+func needSkipLink(flags HTMLFlags, dest []byte) bool {
+ if flags&SkipLinks != 0 {
+ return true
+ }
+ return flags&Safelink != 0 && !isSafeLink(dest) && !isMailto(dest)
+}
+
+func isSmartypantable(node *Node) bool {
+ pt := node.Parent.Type
+ return pt != Link && pt != CodeBlock && pt != Code
+}
+
+func appendLanguageAttr(attrs []string, info []byte) []string {
+ if len(info) == 0 {
+ return attrs
+ }
+ endOfLang := bytes.IndexAny(info, "\t ")
+ if endOfLang < 0 {
+ endOfLang = len(info)
+ }
+ return append(attrs, fmt.Sprintf("class=\"language-%s\"", info[:endOfLang]))
+}
+
+func (r *HTMLRenderer) tag(w io.Writer, name []byte, attrs []string) {
+ w.Write(name)
+ if len(attrs) > 0 {
+ w.Write(spaceBytes)
+ w.Write([]byte(strings.Join(attrs, " ")))
+ }
+ w.Write(gtBytes)
+ r.lastOutputLen = 1
+}
+
+func footnoteRef(prefix string, node *Node) []byte {
+ urlFrag := prefix + string(slugify(node.Destination))
+ anchor := fmt.Sprintf(`%d`, urlFrag, node.NoteID)
+ return []byte(fmt.Sprintf(``, urlFrag, anchor))
+}
+
+func footnoteItem(prefix string, slug []byte) []byte {
+ return []byte(fmt.Sprintf(`
`, prefix, slug))
+}
+
+func footnoteReturnLink(prefix, returnLink string, slug []byte) []byte {
+ const format = ` `
+ return []byte(fmt.Sprintf(format, prefix, slug, returnLink))
+}
+
+func itemOpenCR(node *Node) bool {
+ if node.Prev == nil {
+ return false
+ }
+ ld := node.Parent.ListData
+ return !ld.Tight && ld.ListFlags&ListTypeDefinition == 0
+}
+
+func skipParagraphTags(node *Node) bool {
+ grandparent := node.Parent.Parent
+ if grandparent == nil || grandparent.Type != List {
+ return false
+ }
+ tightOrTerm := grandparent.Tight || node.Parent.ListFlags&ListTypeTerm != 0
+ return grandparent.Type == List && tightOrTerm
+}
+
+func cellAlignment(align CellAlignFlags) string {
+ switch align {
+ case TableAlignmentLeft:
+ return "left"
+ case TableAlignmentRight:
+ return "right"
+ case TableAlignmentCenter:
+ return "center"
+ default:
+ return ""
+ }
+}
+
+func (r *HTMLRenderer) out(w io.Writer, text []byte) {
+ if r.disableTags > 0 {
+ w.Write(htmlTagRe.ReplaceAll(text, []byte{}))
+ } else {
+ w.Write(text)
+ }
+ r.lastOutputLen = len(text)
+}
+
+func (r *HTMLRenderer) cr(w io.Writer) {
+ if r.lastOutputLen > 0 {
+ r.out(w, nlBytes)
+ }
+}
+
+var (
+ nlBytes = []byte{'\n'}
+ gtBytes = []byte{'>'}
+ spaceBytes = []byte{' '}
+)
+
+var (
+ brTag = []byte("
")
+ brXHTMLTag = []byte("
")
+ emTag = []byte("")
+ emCloseTag = []byte("")
+ strongTag = []byte("")
+ strongCloseTag = []byte("")
+ delTag = []byte("")
+ delCloseTag = []byte("")
+ ttTag = []byte("")
+ ttCloseTag = []byte("")
+ aTag = []byte("")
+ preTag = []byte("")
+ preCloseTag = []byte("
")
+ codeTag = []byte("")
+ codeCloseTag = []byte("
")
+ pTag = []byte("")
+ pCloseTag = []byte("
")
+ blockquoteTag = []byte("")
+ blockquoteCloseTag = []byte("
")
+ hrTag = []byte("
")
+ hrXHTMLTag = []byte("
")
+ ulTag = []byte("")
+ ulCloseTag = []byte("
")
+ olTag = []byte("")
+ olCloseTag = []byte("
")
+ dlTag = []byte("")
+ dlCloseTag = []byte("
")
+ liTag = []byte("")
+ liCloseTag = []byte("")
+ ddTag = []byte("")
+ ddCloseTag = []byte("")
+ dtTag = []byte("")
+ dtCloseTag = []byte("")
+ tableTag = []byte("")
+ tableCloseTag = []byte("
")
+ tdTag = []byte("")
+ thTag = []byte(" | ")
+ theadTag = []byte("")
+ theadCloseTag = []byte("")
+ tbodyTag = []byte(" | ")
+ tbodyCloseTag = []byte("")
+ trTag = []byte("")
+ trCloseTag = []byte("
")
+ h1Tag = []byte("")
+ h2Tag = []byte("")
+ h3Tag = []byte("")
+ h4Tag = []byte("")
+ h5Tag = []byte("")
+ h6Tag = []byte("")
+
+ footnotesDivBytes = []byte("\n\n")
+)
+
+func headingTagsFromLevel(level int) ([]byte, []byte) {
+ if level <= 1 {
+ return h1Tag, h1CloseTag
+ }
+ switch level {
+ case 2:
+ return h2Tag, h2CloseTag
+ case 3:
+ return h3Tag, h3CloseTag
+ case 4:
+ return h4Tag, h4CloseTag
+ case 5:
+ return h5Tag, h5CloseTag
+ }
+ return h6Tag, h6CloseTag
+}
+
+func (r *HTMLRenderer) outHRTag(w io.Writer) {
+ if r.Flags&UseXHTML == 0 {
+ r.out(w, hrTag)
+ } else {
+ r.out(w, hrXHTMLTag)
+ }
+}
+
+// RenderNode is a default renderer of a single node of a syntax tree. For
+// block nodes it will be called twice: first time with entering=true, second
+// time with entering=false, so that it could know when it's working on an open
+// tag and when on close. It writes the result to w.
+//
+// The return value is a way to tell the calling walker to adjust its walk
+// pattern: e.g. it can terminate the traversal by returning Terminate. Or it
+// can ask the walker to skip a subtree of this node by returning SkipChildren.
+// The typical behavior is to return GoToNext, which asks for the usual
+// traversal to the next node.
+func (r *HTMLRenderer) RenderNode(w io.Writer, node *Node, entering bool) WalkStatus {
+ attrs := []string{}
+ switch node.Type {
+ case Text:
+ if r.Flags&Smartypants != 0 {
+ var tmp bytes.Buffer
+ escapeHTML(&tmp, node.Literal)
+ r.sr.Process(w, tmp.Bytes())
+ } else {
+ if node.Parent.Type == Link {
+ escLink(w, node.Literal)
+ } else {
+ escapeHTML(w, node.Literal)
+ }
+ }
+ case Softbreak:
+ r.cr(w)
+ // TODO: make it configurable via out(renderer.softbreak)
+ case Hardbreak:
+ if r.Flags&UseXHTML == 0 {
+ r.out(w, brTag)
+ } else {
+ r.out(w, brXHTMLTag)
+ }
+ r.cr(w)
+ case Emph:
+ if entering {
+ r.out(w, emTag)
+ } else {
+ r.out(w, emCloseTag)
+ }
+ case Strong:
+ if entering {
+ r.out(w, strongTag)
+ } else {
+ r.out(w, strongCloseTag)
+ }
+ case Del:
+ if entering {
+ r.out(w, delTag)
+ } else {
+ r.out(w, delCloseTag)
+ }
+ case HTMLSpan:
+ if r.Flags&SkipHTML != 0 {
+ break
+ }
+ r.out(w, node.Literal)
+ case Link:
+ // mark it but don't link it if it is not a safe link: no smartypants
+ dest := node.LinkData.Destination
+ if needSkipLink(r.Flags, dest) {
+ if entering {
+ r.out(w, ttTag)
+ } else {
+ r.out(w, ttCloseTag)
+ }
+ } else {
+ if entering {
+ dest = r.addAbsPrefix(dest)
+ var hrefBuf bytes.Buffer
+ hrefBuf.WriteString("href=\"")
+ escLink(&hrefBuf, dest)
+ hrefBuf.WriteByte('"')
+ attrs = append(attrs, hrefBuf.String())
+ if node.NoteID != 0 {
+ r.out(w, footnoteRef(r.FootnoteAnchorPrefix, node))
+ break
+ }
+ attrs = appendLinkAttrs(attrs, r.Flags, dest)
+ if len(node.LinkData.Title) > 0 {
+ var titleBuff bytes.Buffer
+ titleBuff.WriteString("title=\"")
+ escapeHTML(&titleBuff, node.LinkData.Title)
+ titleBuff.WriteByte('"')
+ attrs = append(attrs, titleBuff.String())
+ }
+ r.tag(w, aTag, attrs)
+ } else {
+ if node.NoteID != 0 {
+ break
+ }
+ r.out(w, aCloseTag)
+ }
+ }
+ case Image:
+ if r.Flags&SkipImages != 0 {
+ return SkipChildren
+ }
+ if entering {
+ dest := node.LinkData.Destination
+ dest = r.addAbsPrefix(dest)
+ if r.disableTags == 0 {
+ //if options.safe && potentiallyUnsafe(dest) {
+ //out(w, ``))
+ }
+ }
+ case Code:
+ r.out(w, codeTag)
+ escapeAllHTML(w, node.Literal)
+ r.out(w, codeCloseTag)
+ case Document:
+ break
+ case Paragraph:
+ if skipParagraphTags(node) {
+ break
+ }
+ if entering {
+ // TODO: untangle this clusterfuck about when the newlines need
+ // to be added and when not.
+ if node.Prev != nil {
+ switch node.Prev.Type {
+ case HTMLBlock, List, Paragraph, Heading, CodeBlock, BlockQuote, HorizontalRule:
+ r.cr(w)
+ }
+ }
+ if node.Parent.Type == BlockQuote && node.Prev == nil {
+ r.cr(w)
+ }
+ r.out(w, pTag)
+ } else {
+ r.out(w, pCloseTag)
+ if !(node.Parent.Type == Item && node.Next == nil) {
+ r.cr(w)
+ }
+ }
+ case BlockQuote:
+ if entering {
+ r.cr(w)
+ r.out(w, blockquoteTag)
+ } else {
+ r.out(w, blockquoteCloseTag)
+ r.cr(w)
+ }
+ case HTMLBlock:
+ if r.Flags&SkipHTML != 0 {
+ break
+ }
+ r.cr(w)
+ r.out(w, node.Literal)
+ r.cr(w)
+ case Heading:
+ headingLevel := r.HTMLRendererParameters.HeadingLevelOffset + node.Level
+ openTag, closeTag := headingTagsFromLevel(headingLevel)
+ if entering {
+ if node.IsTitleblock {
+ attrs = append(attrs, `class="title"`)
+ }
+ if node.HeadingID != "" {
+ id := r.ensureUniqueHeadingID(node.HeadingID)
+ if r.HeadingIDPrefix != "" {
+ id = r.HeadingIDPrefix + id
+ }
+ if r.HeadingIDSuffix != "" {
+ id = id + r.HeadingIDSuffix
+ }
+ attrs = append(attrs, fmt.Sprintf(`id="%s"`, id))
+ }
+ r.cr(w)
+ r.tag(w, openTag, attrs)
+ } else {
+ r.out(w, closeTag)
+ if !(node.Parent.Type == Item && node.Next == nil) {
+ r.cr(w)
+ }
+ }
+ case HorizontalRule:
+ r.cr(w)
+ r.outHRTag(w)
+ r.cr(w)
+ case List:
+ openTag := ulTag
+ closeTag := ulCloseTag
+ if node.ListFlags&ListTypeOrdered != 0 {
+ openTag = olTag
+ closeTag = olCloseTag
+ }
+ if node.ListFlags&ListTypeDefinition != 0 {
+ openTag = dlTag
+ closeTag = dlCloseTag
+ }
+ if entering {
+ if node.IsFootnotesList {
+ r.out(w, footnotesDivBytes)
+ r.outHRTag(w)
+ r.cr(w)
+ }
+ r.cr(w)
+ if node.Parent.Type == Item && node.Parent.Parent.Tight {
+ r.cr(w)
+ }
+ r.tag(w, openTag[:len(openTag)-1], attrs)
+ r.cr(w)
+ } else {
+ r.out(w, closeTag)
+ //cr(w)
+ //if node.parent.Type != Item {
+ // cr(w)
+ //}
+ if node.Parent.Type == Item && node.Next != nil {
+ r.cr(w)
+ }
+ if node.Parent.Type == Document || node.Parent.Type == BlockQuote {
+ r.cr(w)
+ }
+ if node.IsFootnotesList {
+ r.out(w, footnotesCloseDivBytes)
+ }
+ }
+ case Item:
+ openTag := liTag
+ closeTag := liCloseTag
+ if node.ListFlags&ListTypeDefinition != 0 {
+ openTag = ddTag
+ closeTag = ddCloseTag
+ }
+ if node.ListFlags&ListTypeTerm != 0 {
+ openTag = dtTag
+ closeTag = dtCloseTag
+ }
+ if entering {
+ if itemOpenCR(node) {
+ r.cr(w)
+ }
+ if node.ListData.RefLink != nil {
+ slug := slugify(node.ListData.RefLink)
+ r.out(w, footnoteItem(r.FootnoteAnchorPrefix, slug))
+ break
+ }
+ r.out(w, openTag)
+ } else {
+ if node.ListData.RefLink != nil {
+ slug := slugify(node.ListData.RefLink)
+ if r.Flags&FootnoteReturnLinks != 0 {
+ r.out(w, footnoteReturnLink(r.FootnoteAnchorPrefix, r.FootnoteReturnLinkContents, slug))
+ }
+ }
+ r.out(w, closeTag)
+ r.cr(w)
+ }
+ case CodeBlock:
+ attrs = appendLanguageAttr(attrs, node.Info)
+ r.cr(w)
+ r.out(w, preTag)
+ r.tag(w, codeTag[:len(codeTag)-1], attrs)
+ escapeAllHTML(w, node.Literal)
+ r.out(w, codeCloseTag)
+ r.out(w, preCloseTag)
+ if node.Parent.Type != Item {
+ r.cr(w)
+ }
+ case Table:
+ if entering {
+ r.cr(w)
+ r.out(w, tableTag)
+ } else {
+ r.out(w, tableCloseTag)
+ r.cr(w)
+ }
+ case TableCell:
+ openTag := tdTag
+ closeTag := tdCloseTag
+ if node.IsHeader {
+ openTag = thTag
+ closeTag = thCloseTag
+ }
+ if entering {
+ align := cellAlignment(node.Align)
+ if align != "" {
+ attrs = append(attrs, fmt.Sprintf(`align="%s"`, align))
+ }
+ if node.Prev == nil {
+ r.cr(w)
+ }
+ r.tag(w, openTag, attrs)
+ } else {
+ r.out(w, closeTag)
+ r.cr(w)
+ }
+ case TableHead:
+ if entering {
+ r.cr(w)
+ r.out(w, theadTag)
+ } else {
+ r.out(w, theadCloseTag)
+ r.cr(w)
+ }
+ case TableBody:
+ if entering {
+ r.cr(w)
+ r.out(w, tbodyTag)
+ // XXX: this is to adhere to a rather silly test. Should fix test.
+ if node.FirstChild == nil {
+ r.cr(w)
+ }
+ } else {
+ r.out(w, tbodyCloseTag)
+ r.cr(w)
+ }
+ case TableRow:
+ if entering {
+ r.cr(w)
+ r.out(w, trTag)
+ } else {
+ r.out(w, trCloseTag)
+ r.cr(w)
+ }
+ default:
+ panic("Unknown node type " + node.Type.String())
+ }
+ return GoToNext
+}
+
+// RenderHeader writes HTML document preamble and TOC if requested.
+func (r *HTMLRenderer) RenderHeader(w io.Writer, ast *Node) {
+ r.writeDocumentHeader(w)
+ if r.Flags&TOC != 0 {
+ r.writeTOC(w, ast)
+ }
+}
+
+// RenderFooter writes HTML document footer.
+func (r *HTMLRenderer) RenderFooter(w io.Writer, ast *Node) {
+ if r.Flags&CompletePage == 0 {
+ return
+ }
+ io.WriteString(w, "\n