summaryrefslogtreecommitdiff
path: root/vendor/go.step.sm/cli-utils
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/go.step.sm/cli-utils')
-rw-r--r--vendor/go.step.sm/cli-utils/LICENSE201
-rw-r--r--vendor/go.step.sm/cli-utils/command/command.go44
-rw-r--r--vendor/go.step.sm/cli-utils/errs/errs.go330
-rw-r--r--vendor/go.step.sm/cli-utils/fileutil/file.go121
-rw-r--r--vendor/go.step.sm/cli-utils/fileutil/write.go231
-rw-r--r--vendor/go.step.sm/cli-utils/pkg/blackfriday/LICENSE.txt29
-rw-r--r--vendor/go.step.sm/cli-utils/pkg/blackfriday/README.md283
-rw-r--r--vendor/go.step.sm/cli-utils/pkg/blackfriday/block.go1559
-rw-r--r--vendor/go.step.sm/cli-utils/pkg/blackfriday/doc.go18
-rw-r--r--vendor/go.step.sm/cli-utils/pkg/blackfriday/esc.go34
-rw-r--r--vendor/go.step.sm/cli-utils/pkg/blackfriday/html.go941
-rw-r--r--vendor/go.step.sm/cli-utils/pkg/blackfriday/inline.go1217
-rw-r--r--vendor/go.step.sm/cli-utils/pkg/blackfriday/markdown.go945
-rw-r--r--vendor/go.step.sm/cli-utils/pkg/blackfriday/node.go355
-rw-r--r--vendor/go.step.sm/cli-utils/pkg/blackfriday/smartypants.go458
-rw-r--r--vendor/go.step.sm/cli-utils/step/config.go220
-rw-r--r--vendor/go.step.sm/cli-utils/step/context.go564
-rw-r--r--vendor/go.step.sm/cli-utils/ui/options.go172
-rw-r--r--vendor/go.step.sm/cli-utils/ui/templates.go93
-rw-r--r--vendor/go.step.sm/cli-utils/ui/ui.go334
-rw-r--r--vendor/go.step.sm/cli-utils/ui/ui_other.go8
-rw-r--r--vendor/go.step.sm/cli-utils/ui/ui_windows.go51
-rw-r--r--vendor/go.step.sm/cli-utils/ui/validators.go75
-rw-r--r--vendor/go.step.sm/cli-utils/usage/css.go764
-rw-r--r--vendor/go.step.sm/cli-utils/usage/help.go191
-rw-r--r--vendor/go.step.sm/cli-utils/usage/html.go350
-rw-r--r--vendor/go.step.sm/cli-utils/usage/printer.go234
-rw-r--r--vendor/go.step.sm/cli-utils/usage/renderer.go372
-rw-r--r--vendor/go.step.sm/cli-utils/usage/report.go148
-rw-r--r--vendor/go.step.sm/cli-utils/usage/usage.go214
30 files changed, 0 insertions, 10556 deletions
diff --git a/vendor/go.step.sm/cli-utils/LICENSE b/vendor/go.step.sm/cli-utils/LICENSE
deleted file mode 100644
index 261eeb9..0000000
--- a/vendor/go.step.sm/cli-utils/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- 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/go.step.sm/cli-utils/command/command.go b/vendor/go.step.sm/cli-utils/command/command.go
deleted file mode 100644
index a51c2ff..0000000
--- a/vendor/go.step.sm/cli-utils/command/command.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package command
-
-import (
- "os"
-
- "github.com/urfave/cli"
- "go.step.sm/cli-utils/step"
- "go.step.sm/cli-utils/usage"
-)
-
-var cmds []cli.Command
-var currentContext *cli.Context
-
-func init() {
- os.Unsetenv(step.IgnoreEnvVar)
- cmds = []cli.Command{
- usage.HelpCommand(),
- }
-}
-
-// Register adds the given command to the global list of commands.
-// It sets recursively the command Flags environment variables.
-func Register(c cli.Command) {
- step.SetEnvVar(&c)
- cmds = append(cmds, c)
-}
-
-// Retrieve returns all commands
-func Retrieve() []cli.Command {
- return cmds
-}
-
-// ActionFunc returns a cli.ActionFunc that stores the context.
-func ActionFunc(fn cli.ActionFunc) cli.ActionFunc {
- return func(ctx *cli.Context) error {
- currentContext = ctx
- return fn(ctx)
- }
-}
-
-// IsForce returns if the force flag was passed
-func IsForce() bool {
- return currentContext != nil && currentContext.Bool("force")
-}
diff --git a/vendor/go.step.sm/cli-utils/errs/errs.go b/vendor/go.step.sm/cli-utils/errs/errs.go
deleted file mode 100644
index 998c4f1..0000000
--- a/vendor/go.step.sm/cli-utils/errs/errs.go
+++ /dev/null
@@ -1,330 +0,0 @@
-package errs
-
-import (
- "fmt"
- "os"
- "strings"
-
- "errors"
-
- pkge "github.com/pkg/errors"
- "github.com/urfave/cli"
-)
-
-// NewError returns a new Error for the given format and arguments
-func NewError(format string, args ...interface{}) error {
- return fmt.Errorf(format, args...)
-}
-
-// NewExitError returns an error that the urfave/cli package will handle and
-// will show the given error and exit with the given code.
-func NewExitError(err error, exitCode int) error {
- return cli.NewExitError(err, exitCode)
-}
-
-// Wrap returns a new error wrapped by the given error with the given message.
-// If the given error implements the errors.Cause interface, the base error is
-// used. If the given error is wrapped by a package name, the error wrapped
-// will be the string after the last colon.
-//
-// TODO: this should be refactored to use Go's wrap facilities.
-func Wrap(err error, format string, args ...interface{}) error {
- if err == nil {
- return nil
- }
- cause := pkge.Cause(err)
- if errors.Is(err, cause) {
- str := err.Error()
- if i := strings.LastIndexByte(str, ':'); i >= 0 {
- str = strings.TrimSpace(str[i:])
- return pkge.Wrapf(errors.New(str), format, args...)
- }
- }
- return pkge.Wrapf(cause, format, args...)
-}
-
-// InsecureCommand returns an error with a message saying that the current
-// command requires the insecure flag.
-func InsecureCommand(ctx *cli.Context) error {
- return fmt.Errorf("'%s %s' requires the '--insecure' flag", ctx.App.Name, ctx.Command.Name)
-}
-
-// EqualArguments returns an error saying that the given positional arguments
-// cannot be equal.
-func EqualArguments(ctx *cli.Context, arg1, arg2 string) error {
- return fmt.Errorf("positional arguments <%s> and <%s> cannot be equal in '%s'", arg1, arg2, usage(ctx))
-}
-
-// MissingArguments returns an error with a missing arguments message for the
-// given positional argument names.
-func MissingArguments(ctx *cli.Context, argNames ...string) error {
- switch len(argNames) {
- case 0:
- return fmt.Errorf("missing positional arguments in '%s'", usage(ctx))
- case 1:
- return fmt.Errorf("missing positional argument <%s> in '%s'", argNames[0], usage(ctx))
- default:
- args := make([]string, len(argNames))
- for i, name := range argNames {
- args[i] = "<" + name + ">"
- }
- return fmt.Errorf("missing positional arguments %s in '%s'", strings.Join(args, " "), usage(ctx))
- }
-}
-
-// NumberOfArguments returns nil if the number of positional arguments is
-// equal to the required one. It will return an appropriate error if they are
-// not.
-func NumberOfArguments(ctx *cli.Context, required int) error {
- n := ctx.NArg()
- switch {
- case n < required:
- return TooFewArguments(ctx)
- case n > required:
- return TooManyArguments(ctx)
- default:
- return nil
- }
-}
-
-// MinMaxNumberOfArguments returns nil if the number of positional arguments
-// between the min/max range. It will return an appropriate error if they are
-// not.
-func MinMaxNumberOfArguments(ctx *cli.Context, min, max int) error {
- n := ctx.NArg()
- switch {
- case n < min:
- return TooFewArguments(ctx)
- case n > max:
- return TooManyArguments(ctx)
- default:
- return nil
- }
-}
-
-// TooFewArguments returns an error with a few arguments were provided message.
-func TooFewArguments(ctx *cli.Context) error {
- return fmt.Errorf("not enough positional arguments were provided in '%s'", usage(ctx))
-}
-
-// TooManyArguments returns an error with a too many arguments were provided
-// message.
-func TooManyArguments(ctx *cli.Context) error {
- return fmt.Errorf("too many positional arguments were provided in '%s'", usage(ctx))
-}
-
-// InsecureArgument returns an error with the given argument requiring the
-// --insecure flag.
-func InsecureArgument(_ *cli.Context, name string) error {
- return fmt.Errorf("positional argument <%s> requires the '--insecure' flag", name)
-}
-
-// FlagValueInsecure returns an error with the given flag and value requiring
-// the --insecure flag.
-func FlagValueInsecure(_ *cli.Context, flag, value string) error {
- return fmt.Errorf("flag '--%s %s' requires the '--insecure' flag", flag, value)
-}
-
-// InvalidFlagValue returns an error with the given value being missing or
-// invalid for the given flag. Optionally it lists the given formatted options
-// at the end.
-func InvalidFlagValue(ctx *cli.Context, flag, value, options string) error {
- if options != "" {
- options = fmt.Sprintf("options are %s", options)
- }
-
- return InvalidFlagValueMsg(ctx, flag, value, options)
-}
-
-// InvalidFlagValueMsg returns an error with the given value being missing or
-// invalid for the given flag. Optionally it returns an error message to aid
-// in debugging.
-func InvalidFlagValueMsg(_ *cli.Context, flag, value, msg string) error {
- var format string
- if value == "" {
- format = fmt.Sprintf("missing value for flag '--%s'", flag)
- } else {
- format = fmt.Sprintf("invalid value '%s' for flag '--%s'", value, flag)
- }
-
- if msg == "" {
- return errors.New(format)
- }
-
- return errors.New(format + "; " + msg)
-}
-
-// IncompatibleFlag returns an error with the flag being incompatible with the
-// given value.
-func IncompatibleFlag(_ *cli.Context, flag, value string) error {
- return fmt.Errorf("flag '--%s' is incompatible with '%s'", flag, value)
-}
-
-// IncompatibleFlagWithFlag returns an error with the flag being incompatible with the
-// given value.
-func IncompatibleFlagWithFlag(_ *cli.Context, flag, withFlag string) error {
- return fmt.Errorf("flag '--%s' is incompatible with '--%s'", flag, withFlag)
-}
-
-// IncompatibleFlagValue returns an error with the flag being incompatible with the
-// given value.
-func IncompatibleFlagValue(_ *cli.Context, flag, incompatibleWith,
- incompatibleWithValue string) error {
- return fmt.Errorf("flag '--%s' is incompatible with flag '--%s %s'",
- flag, incompatibleWith, incompatibleWithValue)
-}
-
-// IncompatibleFlagValues returns an error with the flag being incompatible with the
-// given value.
-func IncompatibleFlagValues(ctx *cli.Context, flag, value, incompatibleWith,
- incompatibleWithValue string) error {
- return IncompatibleFlagValueWithFlagValue(ctx, flag, value, incompatibleWith,
- incompatibleWithValue, "")
-}
-
-// IncompatibleFlagValueWithFlagValue returns an error with the given value
-// being missing or invalid for the given flag. Optionally it lists the given
-// formatted options at the end.
-func IncompatibleFlagValueWithFlagValue(_ *cli.Context, flag, value,
- withFlag, withValue, options string) error {
- format := fmt.Sprintf("flag '--%s %s' is incompatible with flag '--%s %s'",
- flag, value, withFlag, withValue)
-
- if options == "" {
- return errors.New(format)
- }
-
- // TODO: check whether double space before options is intended
- return fmt.Errorf("%s\n\n Option(s): --%s %s", format, withFlag, options)
-}
-
-// RequiredFlag returns an error with the required flag message.
-func RequiredFlag(ctx *cli.Context, flag string) error {
- return fmt.Errorf("'%s %s' requires the '--%s' flag", ctx.App.HelpName,
- ctx.Command.Name, flag)
-}
-
-// RequiredWithFlag returns an error with the required flag message with another flag.
-func RequiredWithFlag(_ *cli.Context, flag, required string) error {
- return fmt.Errorf("flag '--%s' requires the '--%s' flag", flag, required)
-}
-
-// RequiredWithFlagValue returns an error with the required flag message.
-func RequiredWithFlagValue(_ *cli.Context, flag, value, required string) error {
- return fmt.Errorf("'--%s %s' requires the '--%s' flag", flag, value, required)
-}
-
-// RequiredWithProvisionerTypeFlag returns an error with the required flag message.
-func RequiredWithProvisionerTypeFlag(_ *cli.Context, provisionerType, required string) error {
- return fmt.Errorf("provisioner type '%s' requires the '--%s' flag", provisionerType, required)
-}
-
-// RequiredInsecureFlag returns an error with the given flag requiring the
-// insecure flag message.
-func RequiredInsecureFlag(_ *cli.Context, flag string) error {
- return fmt.Errorf("flag '--%s' requires the '--insecure' flag", flag)
-}
-
-// RequiredSubtleFlag returns an error with the given flag requiring the
-// subtle flag message..
-func RequiredSubtleFlag(_ *cli.Context, flag string) error {
- return fmt.Errorf("flag '--%s' requires the '--subtle' flag", flag)
-}
-
-// RequiredUnlessInsecureFlag returns an error with the required flag message unless
-// the insecure flag is used.
-func RequiredUnlessInsecureFlag(ctx *cli.Context, flag string) error {
- return RequiredUnlessFlag(ctx, flag, "insecure")
-}
-
-// RequiredUnlessFlag returns an error with the required flag message unless
-// the specified flag is used.
-func RequiredUnlessFlag(_ *cli.Context, flag, unlessFlag string) error {
- return fmt.Errorf("flag '--%s' is required unless the '--%s' flag is provided", flag, unlessFlag)
-}
-
-// RequiredUnlessSubtleFlag returns an error with the required flag message unless
-// the subtle flag is used.
-func RequiredUnlessSubtleFlag(ctx *cli.Context, flag string) error {
- return RequiredUnlessFlag(ctx, flag, "subtle")
-}
-
-// RequiredOrFlag returns an error with a list of flags being required messages.
-func RequiredOrFlag(_ *cli.Context, flags ...string) error {
- params := make([]string, len(flags))
- for i, flag := range flags {
- params[i] = "--" + flag
- }
- return fmt.Errorf("one of flag %s is required", strings.Join(params, " or "))
-}
-
-// RequiredWithOrFlag returns an error with a list of flags at least one of which
-// is required in conjunction with the last flag in the list.
-func RequiredWithOrFlag(_ *cli.Context, withFlag string, flags ...string) error {
- params := make([]string, len(flags))
- for i := 0; i < len(flags); i++ {
- params[i] = "--" + flags[i]
- }
- return fmt.Errorf("one of flag %s is required with flag --%s", strings.Join(params, " or "), withFlag)
-}
-
-// MinSizeFlag returns an error with a greater or equal message message for
-// the given flag and size.
-func MinSizeFlag(_ *cli.Context, flag, size string) error {
- return fmt.Errorf("flag '--%s' must be greater than or equal to %s", flag, size)
-}
-
-// MinSizeInsecureFlag returns an error with a requiring --insecure flag
-// message with the given flag an size.
-func MinSizeInsecureFlag(_ *cli.Context, flag, size string) error {
- return fmt.Errorf("flag '--%s' requires at least %s unless '--insecure' flag is provided", flag, size)
-}
-
-// MutuallyExclusiveFlags returns an error with mutually exclusive message for
-// the given flags.
-func MutuallyExclusiveFlags(_ *cli.Context, flag1, flag2 string) error {
- return fmt.Errorf("flag '--%s' and flag '--%s' are mutually exclusive", flag1, flag2)
-}
-
-// UnsupportedFlag returns an error with a message saying that the given flag is
-// not yet supported.
-func UnsupportedFlag(_ *cli.Context, flag string) error {
- return fmt.Errorf("flag '--%s' is not yet supported", flag)
-}
-
-// usage returns the command usage text if set or a default usage string.
-func usage(ctx *cli.Context) string {
- if ctx.Command.UsageText == "" {
- return fmt.Sprintf("%s %s [command options]", ctx.App.HelpName, ctx.Command.Name)
- }
- // keep just the first line and remove markdown
- lines := strings.Split(ctx.Command.UsageText, "\n")
- return strings.ReplaceAll(lines[0], "**", "")
-}
-
-// FileError is a wrapper for errors of the os package.
-func FileError(err error, filename string) error {
- if err == nil {
- return nil
- }
- var (
- pathErr *os.PathError
- linkErr *os.LinkError
- syscallErr *os.SyscallError
- )
- switch {
- case errors.As(err, &pathErr):
- return fmt.Errorf("%s %s failed: %w", pathErr.Op, pathErr.Path, pathErr.Err)
- case errors.As(err, &linkErr):
- return fmt.Errorf("%s %s %s failed: %w", linkErr.Op, linkErr.Old, linkErr.New, linkErr.Err)
- case errors.As(err, &syscallErr):
- return fmt.Errorf("%s failed: %w", syscallErr.Syscall, syscallErr.Err)
- default:
- return Wrap(err, "unexpected error on %s", filename)
- }
-}
-
-// FriendlyError is an interface for returning friendly error messages to the user.
-type FriendlyError interface {
- Message() string
-}
diff --git a/vendor/go.step.sm/cli-utils/fileutil/file.go b/vendor/go.step.sm/cli-utils/fileutil/file.go
deleted file mode 100644
index 04e00a2..0000000
--- a/vendor/go.step.sm/cli-utils/fileutil/file.go
+++ /dev/null
@@ -1,121 +0,0 @@
-package fileutil
-
-import (
- "os"
-
- "github.com/pkg/errors"
-)
-
-// File represents a wrapper on os.File that supports read, write, seek and
-// close methods, but they won't be called if an error occurred before.
-type File struct {
- File *os.File
- err error
-}
-
-// OpenFile calls os.OpenFile method and returns the os.File wrapped.
-func OpenFile(name string, flag int, perm os.FileMode) (*File, error) {
- f, err := os.OpenFile(name, flag, perm)
- if err != nil {
- return nil, FileError(err, name)
- }
- return &File{
- File: f,
- }, nil
-}
-
-// error writes f.err if it's not set and returns f.err.
-func (f *File) error(err error) error {
- if f.err == nil && err != nil {
- f.err = FileError(err, f.File.Name())
- }
- return f.err
-}
-
-// Close wraps `func (*os.File) Close` it will always call Close but the error
-// return will be the first error thrown if any.
-func (f *File) Close() error {
- return f.error(f.File.Close())
-}
-
-// Read wraps `func (*os.File) Read` but doesn't perform the operation if a
-// previous error was thrown.
-func (f *File) Read(b []byte) (n int, err error) {
- if f.err != nil {
- return 0, f.err
- }
- n, err = f.File.Read(b)
- return n, f.error(err)
-}
-
-// ReadAt wraps `func (*os.File) ReadAt` but doesn't perform the operation if a
-// previous error was thrown.
-func (f *File) ReadAt(b []byte, off int64) (n int, err error) {
- if f.err != nil {
- return 0, f.err
- }
- n, err = f.File.ReadAt(b, off)
- return n, f.error(err)
-}
-
-// Seek wraps `func (*os.File) Seek` but doesn't perform the operation if a
-// previous error was thrown.
-func (f *File) Seek(offset int64, whence int) (ret int64, err error) {
- if f.err != nil {
- return 0, f.err
- }
- ret, err = f.File.Seek(offset, whence)
- return ret, f.error(err)
-}
-
-// Write wraps `func (*os.File) Write` but doesn't perform the operation if a
-// previous error was thrown.
-func (f *File) Write(b []byte) (n int, err error) {
- if f.err != nil {
- return 0, f.err
- }
- n, err = f.File.Write(b)
- return n, f.error(err)
-}
-
-// WriteAt wraps `func (*os.File) WriteAt` but doesn't perform the operation if
-// a previous error was thrown.
-func (f *File) WriteAt(b []byte, off int64) (n int, err error) {
- if f.err != nil {
- return 0, f.err
- }
- n, err = f.File.WriteAt(b, off)
- return n, f.error(err)
-}
-
-// WriteString wraps `func (*os.File) WriteString` but doesn't perform the
-// operation if a previous error was thrown.
-func (f *File) WriteString(s string) (n int, err error) {
- if f.err != nil {
- return 0, f.err
- }
- n, err = f.File.WriteString(s)
- return n, f.error(err)
-}
-
-// FileError is a wrapper for errors of the os package.
-func FileError(err error, filename string) error {
- if err == nil {
- return nil
- }
- var (
- pathErr *os.PathError
- linkErr *os.LinkError
- syscallErr *os.SyscallError
- )
- switch {
- case errors.As(err, &pathErr):
- return errors.Errorf("%s %s failed: %v", pathErr.Op, pathErr.Path, pathErr.Err)
- case errors.As(err, &linkErr):
- return errors.Errorf("%s %s %s failed: %v", linkErr.Op, linkErr.Old, linkErr.New, linkErr.Err)
- case errors.As(err, &syscallErr):
- return errors.Errorf("%s failed: %v", syscallErr.Syscall, syscallErr.Err)
- default:
- return errors.Wrapf(err, "unexpected error on %s", filename)
- }
-}
diff --git a/vendor/go.step.sm/cli-utils/fileutil/write.go b/vendor/go.step.sm/cli-utils/fileutil/write.go
deleted file mode 100644
index fd8b2cb..0000000
--- a/vendor/go.step.sm/cli-utils/fileutil/write.go
+++ /dev/null
@@ -1,231 +0,0 @@
-package fileutil
-
-import (
- "bufio"
- "bytes"
- "fmt"
- "io"
- "os"
- "strings"
- "time"
-
- "github.com/pkg/errors"
- "go.step.sm/cli-utils/command"
- "go.step.sm/cli-utils/ui"
-)
-
-var (
- // ErrFileExists is the error returned if a file exists.
- ErrFileExists = errors.New("file exists")
-
- // ErrIsDir is the error returned if the file is a directory.
- ErrIsDir = errors.New("file is a directory")
-
- // SnippetHeader is the header of a step generated snippet in a
- // configuration file.
- SnippetHeader = "# autogenerated by step"
-
- // SnippetFooter is the header of a step generated snippet in a
- // configuration file.
- SnippetFooter = "# end"
-)
-
-// WriteFile wraps ioutil.WriteFile with a prompt to overwrite a file if
-// the file exists. It returns ErrFileExists if the user picks to not overwrite
-// the file. If force is set to true, the prompt will not be presented and the
-// file if exists will be overwritten.
-func WriteFile(filename string, data []byte, perm os.FileMode) error {
- if command.IsForce() {
- return os.WriteFile(filename, data, perm)
- }
-
- st, err := os.Stat(filename)
- if err != nil {
- if os.IsNotExist(err) {
- return os.WriteFile(filename, data, perm)
- }
- return errors.Wrapf(err, "error reading information for %s", filename)
- }
-
- if st.IsDir() {
- return ErrIsDir
- }
-
- str, err := ui.Prompt(fmt.Sprintf("Would you like to overwrite %s [y/n]", filename), ui.WithValidateYesNo())
- if err != nil {
- return err
- }
- switch strings.ToLower(strings.TrimSpace(str)) {
- case "y", "yes":
- case "n", "no":
- return ErrFileExists
- }
-
- return os.WriteFile(filename, data, perm)
-}
-
-// AppendNewLine appends the given data at the end of the file. If the last
-// character of the file does not contain an LF it prepends it to the data.
-func AppendNewLine(filename string, data []byte, perm os.FileMode) error {
- f, err := OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_APPEND, perm)
- if err != nil {
- return err
- }
- // Read last character
- if st, err := f.File.Stat(); err == nil && st.Size() != 0 {
- last := make([]byte, 1)
- f.Seek(-1, 2)
- f.Read(last)
- if last[0] != '\n' {
- f.WriteString("\n")
- }
- }
- f.Write(data)
- return f.Close()
-}
-
-func writeChunk(filename string, data []byte, hasHeaderFooter bool, header, footer string, perm os.FileMode) error {
- // Get file permissions
- if st, err := os.Stat(filename); err == nil {
- perm = st.Mode()
- } else if !os.IsNotExist(err) {
- return FileError(err, filename)
- }
-
- // Read file contents
- b, err := os.ReadFile(filename)
- if err != nil && !os.IsNotExist(err) {
- return FileError(err, filename)
- }
-
- // Detect previous configuration
- _, start, end := findConfiguration(bytes.NewReader(b), header, footer)
-
- // Replace previous configuration
- f, err := OpenFile(filename, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, perm)
- if err != nil {
- return FileError(err, filename)
- }
- if len(b) > 0 {
- f.Write(b[:start])
- if start == end {
- f.WriteString("\n")
- }
- }
- if !hasHeaderFooter {
- fmt.Fprintf(f, "%s @ %s\n", header, time.Now().UTC().Format(time.RFC3339))
- }
- f.Write(data)
- if !bytes.HasSuffix(data, []byte("\n")) {
- f.WriteString("\n")
- }
- if !hasHeaderFooter {
- f.WriteString(footer + "\n")
- }
- if len(b) > 0 {
- f.Write(b[end:])
- }
- return f.Close()
-}
-
-// WriteSnippet writes the given data into the given filename. It surrounds the
-// data with a default header and footer, and it will replace the previous one.
-func WriteSnippet(filename string, data []byte, perm os.FileMode) error {
- return writeChunk(filename, data, false, SnippetHeader, SnippetFooter, perm)
-}
-
-// PrependLine prepends the given line into the given filename and removes
-// other instances of the line in the file.
-func PrependLine(filename string, data []byte, perm os.FileMode) error {
- // Get file permissions
- if st, err := os.Stat(filename); err == nil {
- perm = st.Mode()
- } else if !os.IsNotExist(err) {
- return FileError(err, filename)
- }
-
- // Read file contents
- b, err := os.ReadFile(filename)
- if err != nil && !os.IsNotExist(err) {
- return FileError(err, filename)
- }
-
- line := string(data)
- result := []string{string(data)}
- for _, l := range strings.Split(string(b), "\n") {
- if l != "" && !strings.HasPrefix(l, line) {
- result = append(result, l)
- }
- }
-
- if err := os.WriteFile(filename, []byte(strings.Join(result, "\n")), perm); err != nil {
- return FileError(err, filename)
- }
- return nil
-}
-
-// RemoveLine removes a single line which contains the given substring from the
-// given file.
-func RemoveLine(filename, substr string) error {
- var perm os.FileMode
- // Get file permissions
- st, err := os.Stat(filename)
- switch {
- case os.IsNotExist(err):
- return nil
- case err != nil:
- return FileError(err, filename)
- default:
- perm = st.Mode()
- }
-
- // Read file contents
- b, err := os.ReadFile(filename)
- if err != nil && !os.IsNotExist(err) {
- return FileError(err, filename)
- }
-
- old := strings.Split(string(b), "\n")
- for i, l := range old {
- if !strings.Contains(l, substr) {
- continue
- }
- if err := os.WriteFile(filename, []byte(strings.Join(append(old[:i], old[i+1:]...), "\n")), perm); err != nil {
- return FileError(err, filename)
- }
- break
- }
-
- return nil
-}
-
-type offsetCounter struct {
- offset int64
-}
-
-func (o *offsetCounter) ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
- advance, token, err = bufio.ScanLines(data, atEOF)
- o.offset += int64(advance)
- return
-}
-
-func findConfiguration(r io.Reader, header, footer string) (lines []string, start, end int64) {
- var inConfig bool
- counter := new(offsetCounter)
- scanner := bufio.NewScanner(r)
- scanner.Split(counter.ScanLines)
- for scanner.Scan() {
- line := scanner.Text()
- switch {
- case !inConfig && strings.HasPrefix(line, header):
- inConfig = true
- start = counter.offset - int64(len(line)+1)
- case inConfig && strings.HasPrefix(line, footer):
- return lines, start, counter.offset
- case inConfig:
- lines = append(lines, line)
- }
- }
-
- return lines, counter.offset, counter.offset
-}
diff --git a/vendor/go.step.sm/cli-utils/pkg/blackfriday/LICENSE.txt b/vendor/go.step.sm/cli-utils/pkg/blackfriday/LICENSE.txt
deleted file mode 100644
index 2885af3..0000000
--- a/vendor/go.step.sm/cli-utils/pkg/blackfriday/LICENSE.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-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/go.step.sm/cli-utils/pkg/blackfriday/README.md b/vendor/go.step.sm/cli-utils/pkg/blackfriday/README.md
deleted file mode 100644
index 2e0db35..0000000
--- a/vendor/go.step.sm/cli-utils/pkg/blackfriday/README.md
+++ /dev/null
@@ -1,283 +0,0 @@
-Blackfriday [![Build Status](https://travis-ci.org/russross/blackfriday.svg?branch=master)](https://travis-ci.org/russross/blackfriday)
-===========
-
-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 any modern Go release. With Go 1.7 and git
-installed:
-
- go get gopkg.in/russross/blackfriday.v2
-
-will download, compile, and install the package into your `$GOPATH`
-directory hierarchy. Alternatively, you can achieve the same if you
-import it into a project:
-
- import "gopkg.in/russross/blackfriday.v2"
-
-and `go get` without parameters.
-
-
-Versions
---------
-
-Currently maintained and recommended version of Blackfriday is `v2`. It's being
-developed on its own branch: https://github.com/russross/blackfriday/v2. You
-should install and import it via [gopkg.in][6] at
-`gopkg.in/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.
-
-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"
-)
-
-// ...
-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`.
-
-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:
-
-* <http://github.com/russross/blackfriday-tool>
-
-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.
-
-
-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.
-
-* **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 `&ndash;`, and `---` is translated into
- `&mdash;`. 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 `<sup>4</sup>&frasl;<sub>5</sub>`, which renders as
- <sup>4</sup>&frasl;<sub>5</sub>.
-
-
-Other renderers
----------------
-
-Blackfriday is structured to allow alternative rendering engines. Here
-are a few of note:
-
-* [github_flavored_markdown](https://godoc.org/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://bitbucket.org/ambrevar/blackfriday-latex):
- renders output as LaTeX.
-
-
-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://godoc.org/gopkg.in/russross/blackfriday.v2#Parse "Parse func"
- [5]: https://github.com/microcosm-cc/bluemonday "Bluemonday"
- [6]: https://labix.org/gopkg.in "gopkg.in"
diff --git a/vendor/go.step.sm/cli-utils/pkg/blackfriday/block.go b/vendor/go.step.sm/cli-utils/pkg/blackfriday/block.go
deleted file mode 100644
index 918d656..0000000
--- a/vendor/go.step.sm/cli-utils/pkg/blackfriday/block.go
+++ /dev/null
@@ -1,1559 +0,0 @@
-//
-// Blackfriday Markdown Processor
-// Available at http://github.com/russross/blackfriday
-//
-// Copyright © 2011 Russ Ross <russ@russross.com>.
-// Distributed under the Simplified BSD License.
-// See README.md for details.
-//
-
-//
-// Functions to parse block-level elements.
-//
-
-//nolint:gocritic,revive,ineffassign,gosimple,wastedassign // ignore blackfriday
-package blackfriday
-
-import (
- "bytes"
- "html"
- "regexp"
-
- "github.com/shurcooL/sanitized_anchor_name"
-)
-
-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:
- //
- // <div>
- // ...
- // </div>
- 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 = sanitized_anchor_name.Create(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 <hr> 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 <hr> 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 syntax is not nil, it gets set to the syntax specified in the fence line.
-func isFenceLine(data []byte, syntax *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 syntax, and discard it if the caller doesn't care.
- if syntax != nil {
- syn := 0
- i = skipChar(data, i, ' ')
-
- if i >= len(data) {
- if i == len(data) {
- return i, marker
- }
- return 0, ""
- }
-
- syntaxStart := i
-
- if data[i] == '{' {
- i++
- syntaxStart++
-
- for i < len(data) && data[i] != '}' && data[i] != '\n' {
- syn++
- i++
- }
-
- if i >= len(data) || data[i] != '}' {
- return 0, ""
- }
-
- // strip all whitespace at the beginning and the end
- // of the {} block
- for syn > 0 && isspace(data[syntaxStart]) {
- syntaxStart++
- syn--
- }
-
- for syn > 0 && isspace(data[syntaxStart+syn-1]) {
- syn--
- }
-
- i++
- } else {
- for i < len(data) && !isspace(data[i]) {
- syn++
- i++
- }
- }
-
- *syntax = string(data[syntaxStart : syntaxStart+syn])
- }
-
- i = skipChar(data, i, ' ')
- if i >= len(data) || data[i] != '\n' {
- if i == len(data) {
- return i, marker
- }
- 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 syntax string
- beg, marker := isFenceLine(data, &syntax, "")
- if beg == 0 || beg >= len(data) {
- return 0
- }
-
- var work bytes.Buffer
- work.Write([]byte(syntax))
- 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
- 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 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
- lastChunkSize := 0
-
-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]
-
- // 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:
-
- if containsBlankLine {
- *flags |= ListItemContainsBlock
- }
-
- // to be a nested list, it must be indented more
- // if not, it is the next item in the same list
- if indent <= itemIndent {
- break gatherlines
- }
-
- // is this the first item in the nested list?
- if sublist == 0 {
- if p.dliPrefix(chunk) > 0 {
- sublist = raw.Len() - lastChunkSize
- } else {
- 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])
-
- // remember how much was written into raw, if this turns out to be a
- // definition list we'll need this number to know where the sublist starts
- lastChunkSize = i - (line + indentIndex)
-
- 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 = sanitized_anchor_name.Create(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
-}
diff --git a/vendor/go.step.sm/cli-utils/pkg/blackfriday/doc.go b/vendor/go.step.sm/cli-utils/pkg/blackfriday/doc.go
deleted file mode 100644
index 5b3fa98..0000000
--- a/vendor/go.step.sm/cli-utils/pkg/blackfriday/doc.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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.
-package blackfriday
diff --git a/vendor/go.step.sm/cli-utils/pkg/blackfriday/esc.go b/vendor/go.step.sm/cli-utils/pkg/blackfriday/esc.go
deleted file mode 100644
index 6385f27..0000000
--- a/vendor/go.step.sm/cli-utils/pkg/blackfriday/esc.go
+++ /dev/null
@@ -1,34 +0,0 @@
-package blackfriday
-
-import (
- "html"
- "io"
-)
-
-var htmlEscaper = [256][]byte{
- '&': []byte("&amp;"),
- '<': []byte("&lt;"),
- '>': []byte("&gt;"),
- '"': []byte("&quot;"),
-}
-
-func escapeHTML(w io.Writer, s []byte) {
- var start, end int
- for end < len(s) {
- escSeq := htmlEscaper[s[end]]
- if escSeq != nil {
- 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 escLink(w io.Writer, text []byte) {
- unesc := html.UnescapeString(string(text))
- escapeHTML(w, []byte(unesc))
-}
diff --git a/vendor/go.step.sm/cli-utils/pkg/blackfriday/html.go b/vendor/go.step.sm/cli-utils/pkg/blackfriday/html.go
deleted file mode 100644
index 9fbf820..0000000
--- a/vendor/go.step.sm/cli-utils/pkg/blackfriday/html.go
+++ /dev/null
@@ -1,941 +0,0 @@
-//
-// Blackfriday Markdown Processor
-// Available at http://github.com/russross/blackfriday
-//
-// Copyright © 2011 Russ Ross <russ@russross.com>.
-// Distributed under the Simplified BSD License.
-// See README.md for details.
-//
-
-//
-//
-// HTML rendering backend
-//
-//
-
-//nolint:gocritic,unused,revive // ignore blackfriday
-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"
- 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 = "<!\\[CDATA\\[[\\s\\S]*?\\]\\]>"
- declaration = "<![A-Z]+" + "\\s+[^>]*>"
- 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 <a> tag for a footnote return link, if the
- // HTML_FOOTNOTE_RETURN_LINKS flag is enabled. If blank, the string
- // <sup>[return]</sup> 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
-
- 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 == "" {
- params.FootnoteReturnLinkContents = `<sup>[return]</sup>`
- }
-
- 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&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(`<a rel="footnote" href="#fn:%s">%d</a>`, urlFrag, node.NoteID)
- return []byte(fmt.Sprintf(`<sup class="footnote-ref" id="fnref:%s">%s</sup>`, urlFrag, anchor))
-}
-
-func footnoteItem(prefix string, slug []byte) []byte {
- return []byte(fmt.Sprintf(`<li id="fn:%s%s">`, prefix, slug))
-}
-
-func footnoteReturnLink(prefix, returnLink string, slug []byte) []byte {
- const format = ` <a class="footnote-return" href="#fnref:%s%s">%s</a>`
- 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("<br>")
- brXHTMLTag = []byte("<br />")
- emTag = []byte("<em>")
- emCloseTag = []byte("</em>")
- strongTag = []byte("<strong>")
- strongCloseTag = []byte("</strong>")
- delTag = []byte("<del>")
- delCloseTag = []byte("</del>")
- ttTag = []byte("<tt>")
- ttCloseTag = []byte("</tt>")
- aTag = []byte("<a")
- aCloseTag = []byte("</a>")
- preTag = []byte("<pre>")
- preCloseTag = []byte("</pre>")
- codeTag = []byte("<code>")
- codeCloseTag = []byte("</code>")
- pTag = []byte("<p>")
- pCloseTag = []byte("</p>")
- blockquoteTag = []byte("<blockquote>")
- blockquoteCloseTag = []byte("</blockquote>")
- hrTag = []byte("<hr>")
- hrXHTMLTag = []byte("<hr />")
- ulTag = []byte("<ul>")
- ulCloseTag = []byte("</ul>")
- olTag = []byte("<ol>")
- olCloseTag = []byte("</ol>")
- dlTag = []byte("<dl>")
- dlCloseTag = []byte("</dl>")
- liTag = []byte("<li>")
- liCloseTag = []byte("</li>")
- ddTag = []byte("<dd>")
- ddCloseTag = []byte("</dd>")
- dtTag = []byte("<dt>")
- dtCloseTag = []byte("</dt>")
- tableTag = []byte("<table>")
- tableCloseTag = []byte("</table>")
- tdTag = []byte("<td")
- tdCloseTag = []byte("</td>")
- thTag = []byte("<th")
- thCloseTag = []byte("</th>")
- theadTag = []byte("<thead>")
- theadCloseTag = []byte("</thead>")
- tbodyTag = []byte("<tbody>")
- tbodyCloseTag = []byte("</tbody>")
- trTag = []byte("<tr>")
- trCloseTag = []byte("</tr>")
- h1Tag = []byte("<h1")
- h1CloseTag = []byte("</h1>")
- h2Tag = []byte("<h2")
- h2CloseTag = []byte("</h2>")
- h3Tag = []byte("<h3")
- h3CloseTag = []byte("</h3>")
- h4Tag = []byte("<h4")
- h4CloseTag = []byte("</h4>")
- h5Tag = []byte("<h5")
- h5CloseTag = []byte("</h5>")
- h6Tag = []byte("<h6")
- h6CloseTag = []byte("</h6>")
-
- footnotesDivBytes = []byte("\n<div class=\"footnotes\">\n\n")
- footnotesCloseDivBytes = []byte("\n</div>\n")
-)
-
-func headingTagsFromLevel(level int) ([]byte, []byte) {
- switch level {
- case 1:
- return h1Tag, h1CloseTag
- case 2:
- return h2Tag, h2CloseTag
- case 3:
- return h3Tag, h3CloseTag
- case 4:
- return h4Tag, h4CloseTag
- case 5:
- return h5Tag, h5CloseTag
- default:
- 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, `<img src="" alt="`)
- //} else {
- r.out(w, []byte(`<img src="`))
- escLink(w, dest)
- r.out(w, []byte(`" alt="`))
- //}
- }
- r.disableTags++
- } else {
- r.disableTags--
- if r.disableTags == 0 {
- if node.LinkData.Title != nil {
- r.out(w, []byte(`" title="`))
- escapeHTML(w, node.LinkData.Title)
- }
- r.out(w, []byte(`" />`))
- }
- }
- case Code:
- r.out(w, codeTag)
- escapeHTML(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:
- openTag, closeTag := headingTagsFromLevel(node.Level)
- 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)
- escapeHTML(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</body>\n</html>\n")
-}
-
-func (r *HTMLRenderer) writeDocumentHeader(w io.Writer) {
- if r.Flags&CompletePage == 0 {
- return
- }
- ending := ""
- if r.Flags&UseXHTML != 0 {
- io.WriteString(w, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" ")
- io.WriteString(w, "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n")
- io.WriteString(w, "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n")
- ending = " /"
- } else {
- io.WriteString(w, "<!DOCTYPE html>\n")
- io.WriteString(w, "<html>\n")
- }
- io.WriteString(w, "<head>\n")
- io.WriteString(w, " <title>")
- if r.Flags&Smartypants != 0 {
- r.sr.Process(w, []byte(r.Title))
- } else {
- escapeHTML(w, []byte(r.Title))
- }
- io.WriteString(w, "</title>\n")
- io.WriteString(w, " <meta name=\"GENERATOR\" content=\"Blackfriday Markdown Processor v")
- io.WriteString(w, Version)
- io.WriteString(w, "\"")
- io.WriteString(w, ending)
- io.WriteString(w, ">\n")
- io.WriteString(w, " <meta charset=\"utf-8\"")
- io.WriteString(w, ending)
- io.WriteString(w, ">\n")
- if r.CSS != "" {
- io.WriteString(w, " <link rel=\"stylesheet\" type=\"text/css\" href=\"")
- escapeHTML(w, []byte(r.CSS))
- io.WriteString(w, "\"")
- io.WriteString(w, ending)
- io.WriteString(w, ">\n")
- }
- if r.Icon != "" {
- io.WriteString(w, " <link rel=\"icon\" type=\"image/x-icon\" href=\"")
- escapeHTML(w, []byte(r.Icon))
- io.WriteString(w, "\"")
- io.WriteString(w, ending)
- io.WriteString(w, ">\n")
- }
- io.WriteString(w, "</head>\n")
- io.WriteString(w, "<body>\n\n")
-}
-
-func (r *HTMLRenderer) writeTOC(w io.Writer, ast *Node) {
- buf := bytes.Buffer{}
-
- inHeading := false
- tocLevel := 0
- headingCount := 0
-
- ast.Walk(func(node *Node, entering bool) WalkStatus {
- if node.Type == Heading && !node.HeadingData.IsTitleblock {
- inHeading = entering
- if entering {
- node.HeadingID = fmt.Sprintf("toc_%d", headingCount)
- if node.Level == tocLevel {
- buf.WriteString("</li>\n\n<li>")
- } else if node.Level < tocLevel {
- for node.Level < tocLevel {
- tocLevel--
- buf.WriteString("</li>\n</ul>")
- }
- buf.WriteString("</li>\n\n<li>")
- } else {
- for node.Level > tocLevel {
- tocLevel++
- buf.WriteString("\n<ul>\n<li>")
- }
- }
-
- fmt.Fprintf(&buf, `<a href="#toc_%d">`, headingCount)
- headingCount++
- } else {
- buf.WriteString("</a>")
- }
- return GoToNext
- }
-
- if inHeading {
- return r.RenderNode(&buf, node, entering)
- }
-
- return GoToNext
- })
-
- for ; tocLevel > 0; tocLevel-- {
- buf.WriteString("</li>\n</ul>")
- }
-
- if buf.Len() > 0 {
- io.WriteString(w, "<nav>\n")
- w.Write(buf.Bytes())
- io.WriteString(w, "\n\n</nav>\n")
- }
- r.lastOutputLen = buf.Len()
-}
diff --git a/vendor/go.step.sm/cli-utils/pkg/blackfriday/inline.go b/vendor/go.step.sm/cli-utils/pkg/blackfriday/inline.go
deleted file mode 100644
index 70557d5..0000000
--- a/vendor/go.step.sm/cli-utils/pkg/blackfriday/inline.go
+++ /dev/null
@@ -1,1217 +0,0 @@
-//
-// Blackfriday Markdown Processor
-// Available at http://github.com/russross/blackfriday
-//
-// Copyright © 2011 Russ Ross <russ@russross.com>.
-// Distributed under the Simplified BSD License.
-// See README.md for details.
-//
-
-//
-// Functions to parse inline elements.
-//
-
-//nolint:gocritic,whitespace,wastedassign,revive // ignore blackfriday
-package blackfriday
-
-import (
- "bytes"
- "regexp"
- "strconv"
-)
-
-var (
- urlRe = `((https?|ftp):\/\/|\/)[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+`
- anchorRe = regexp.MustCompile(`^(<a\shref="` + urlRe + `"(\stitle="[^"<>]+")?\s?>` + urlRe + `<\/a>)`)
-
- // TODO: improve this regexp to catch all possible entities:
- htmlEntityRe = regexp.MustCompile(`&[a-z]{2,5};`)
-)
-
-// Functions to parse text within a block
-// Each function returns the number of chars taken care of
-// data is the complete block being rendered
-// offset is the number of valid chars before the current cursor
-
-func (p *Markdown) inline(currBlock *Node, data []byte) {
- // handlers might call us recursively: enforce a maximum depth
- if p.nesting >= p.maxNesting || len(data) == 0 {
- return
- }
- p.nesting++
- beg, end := 0, 0
- for end < len(data) {
- handler := p.inlineCallback[data[end]]
- if handler != nil {
- if consumed, node := handler(p, data, end); consumed == 0 {
- // No action from the callback.
- end++
- } else {
- // Copy inactive chars into the output.
- currBlock.AppendChild(text(data[beg:end]))
- if node != nil {
- currBlock.AppendChild(node)
- }
- // Skip past whatever the callback used.
- beg = end + consumed
- end = beg
- }
- } else {
- end++
- }
- }
- if beg < len(data) {
- if data[end-1] == '\n' {
- end--
- }
- currBlock.AppendChild(text(data[beg:end]))
- }
- p.nesting--
-}
-
-// single and double emphasis parsing
-func emphasis(p *Markdown, data []byte, offset int) (int, *Node) {
- data = data[offset:]
- c := data[0]
-
- if len(data) > 2 && data[1] != c {
- // whitespace cannot follow an opening emphasis;
- // strikethrough only takes two characters '~~'
- if c == '~' || isspace(data[1]) {
- return 0, nil
- }
- ret, node := helperEmphasis(p, data[1:], c)
- if ret == 0 {
- return 0, nil
- }
-
- return ret + 1, node
- }
-
- if len(data) > 3 && data[1] == c && data[2] != c {
- if isspace(data[2]) {
- return 0, nil
- }
- ret, node := helperDoubleEmphasis(p, data[2:], c)
- if ret == 0 {
- return 0, nil
- }
-
- return ret + 2, node
- }
-
- if len(data) > 4 && data[1] == c && data[2] == c && data[3] != c {
- if c == '~' || isspace(data[3]) {
- return 0, nil
- }
- ret, node := helperTripleEmphasis(p, data, 3, c)
- if ret == 0 {
- return 0, nil
- }
-
- return ret + 3, node
- }
-
- return 0, nil
-}
-
-func codeSpan(p *Markdown, data []byte, offset int) (int, *Node) {
- data = data[offset:]
-
- nb := 0
-
- // count the number of backticks in the delimiter
- for nb < len(data) && data[nb] == '`' {
- nb++
- }
-
- // find the next delimiter
- i, end := 0, 0
- for end = nb; end < len(data) && i < nb; end++ {
- if data[end] == '`' {
- i++
- } else {
- i = 0
- }
- }
-
- // no matching delimiter?
- if i < nb && end >= len(data) {
- return 0, nil
- }
-
- // trim outside whitespace
- fBegin := nb
- for fBegin < end && data[fBegin] == ' ' {
- fBegin++
- }
-
- fEnd := end - nb
- for fEnd > fBegin && data[fEnd-1] == ' ' {
- fEnd--
- }
-
- // render the code span
- if fBegin != fEnd {
- code := NewNode(Code)
- code.Literal = data[fBegin:fEnd]
- return end, code
- }
-
- return end, nil
-}
-
-// newline preceded by two spaces becomes <br>
-func maybeLineBreak(p *Markdown, data []byte, offset int) (int, *Node) {
- origOffset := offset
- for offset < len(data) && data[offset] == ' ' {
- offset++
- }
-
- if offset < len(data) && data[offset] == '\n' {
- if offset-origOffset >= 2 {
- return offset - origOffset + 1, NewNode(Hardbreak)
- }
- return offset - origOffset, nil
- }
- return 0, nil
-}
-
-// newline without two spaces works when HardLineBreak is enabled
-func lineBreak(p *Markdown, data []byte, offset int) (int, *Node) {
- if p.extensions&HardLineBreak != 0 {
- return 1, NewNode(Hardbreak)
- }
- return 0, nil
-}
-
-type linkType int
-
-const (
- linkNormal linkType = iota
- linkImg
- linkDeferredFootnote
- linkInlineFootnote
-)
-
-func isReferenceStyleLink(data []byte, pos int, t linkType) bool {
- if t == linkDeferredFootnote {
- return false
- }
- return pos < len(data)-1 && data[pos] == '[' && data[pos+1] != '^'
-}
-
-func maybeImage(p *Markdown, data []byte, offset int) (int, *Node) {
- if offset < len(data)-1 && data[offset+1] == '[' {
- return link(p, data, offset)
- }
- return 0, nil
-}
-
-func maybeInlineFootnote(p *Markdown, data []byte, offset int) (int, *Node) {
- if offset < len(data)-1 && data[offset+1] == '[' {
- return link(p, data, offset)
- }
- return 0, nil
-}
-
-// '[': parse a link or an image or a footnote
-func link(p *Markdown, data []byte, offset int) (int, *Node) {
- // no links allowed inside regular links, footnote, and deferred footnotes
- if p.insideLink && (offset > 0 && data[offset-1] == '[' || len(data)-1 > offset && data[offset+1] == '^') {
- return 0, nil
- }
-
- var t linkType
- switch {
- // special case: ![^text] == deferred footnote (that follows something with
- // an exclamation point)
- case p.extensions&Footnotes != 0 && len(data)-1 > offset && data[offset+1] == '^':
- t = linkDeferredFootnote
- // ![alt] == image
- case offset >= 0 && data[offset] == '!':
- t = linkImg
- offset++
- // ^[text] == inline footnote
- // [^refId] == deferred footnote
- case p.extensions&Footnotes != 0:
- if offset >= 0 && data[offset] == '^' {
- t = linkInlineFootnote
- offset++
- } else if len(data)-1 > offset && data[offset+1] == '^' {
- t = linkDeferredFootnote
- }
- // [text] == regular link
- default:
- t = linkNormal
- }
-
- data = data[offset:]
-
- var (
- i = 1
- noteID int
- title, link, altContent []byte
- textHasNl = false
- )
-
- if t == linkDeferredFootnote {
- i++
- }
-
- // look for the matching closing bracket
- for level := 1; level > 0 && i < len(data); i++ {
- switch {
- case data[i] == '\n':
- textHasNl = true
-
- case data[i-1] == '\\':
- continue
-
- case data[i] == '[':
- level++
-
- case data[i] == ']':
- level--
- if level <= 0 {
- i-- // compensate for extra i++ in for loop
- }
- }
- }
-
- if i >= len(data) {
- return 0, nil
- }
-
- txtE := i
- i++
- var footnoteNode *Node
-
- // skip any amount of whitespace or newline
- // (this is much more lax than original markdown syntax)
- for i < len(data) && isspace(data[i]) {
- i++
- }
-
- // inline style link
- switch {
- case i < len(data) && data[i] == '(':
- // skip initial whitespace
- i++
-
- for i < len(data) && isspace(data[i]) {
- i++
- }
-
- linkB := i
-
- // look for link end: ' " )
- findlinkend:
- for i < len(data) {
- switch {
- case data[i] == '\\':
- i += 2
-
- case data[i] == ')' || data[i] == '\'' || data[i] == '"':
- break findlinkend
-
- default:
- i++
- }
- }
-
- if i >= len(data) {
- return 0, nil
- }
- linkE := i
-
- // look for title end if present
- titleB, titleE := 0, 0
- if data[i] == '\'' || data[i] == '"' {
- i++
- titleB = i
-
- findtitleend:
- for i < len(data) {
- switch {
- case data[i] == '\\':
- i += 2
-
- case data[i] == ')':
- break findtitleend
-
- default:
- i++
- }
- }
-
- if i >= len(data) {
- return 0, nil
- }
-
- // skip whitespace after title
- titleE = i - 1
- for titleE > titleB && isspace(data[titleE]) {
- titleE--
- }
-
- // check for closing quote presence
- if data[titleE] != '\'' && data[titleE] != '"' {
- titleB, titleE = 0, 0
- linkE = i
- }
- }
-
- // remove whitespace at the end of the link
- for linkE > linkB && isspace(data[linkE-1]) {
- linkE--
- }
-
- // remove optional angle brackets around the link
- if data[linkB] == '<' {
- linkB++
- }
- if data[linkE-1] == '>' {
- linkE--
- }
-
- // build escaped link and title
- if linkE > linkB {
- link = data[linkB:linkE]
- }
-
- if titleE > titleB {
- title = data[titleB:titleE]
- }
-
- i++
-
- // reference style link
- case isReferenceStyleLink(data, i, t):
- var id []byte
- altContentConsidered := false
-
- // look for the id
- i++
- linkB := i
- for i < len(data) && data[i] != ']' {
- i++
- }
- if i >= len(data) {
- return 0, nil
- }
- linkE := i
-
- // find the reference
- if linkB == linkE {
- if textHasNl {
- var b bytes.Buffer
-
- for j := 1; j < txtE; j++ {
- switch {
- case data[j] != '\n':
- b.WriteByte(data[j])
- case data[j-1] != ' ':
- b.WriteByte(' ')
- }
- }
-
- id = b.Bytes()
- } else {
- id = data[1:txtE]
- altContentConsidered = true
- }
- } else {
- id = data[linkB:linkE]
- }
-
- // find the reference with matching id
- lr, ok := p.getRef(string(id))
- if !ok {
- return 0, nil
- }
-
- // keep link and title from reference
- link = lr.link
- title = lr.title
- if altContentConsidered {
- altContent = lr.text
- }
- i++
-
- // shortcut reference style link or reference or inline footnote
- default:
- var id []byte
-
- // craft the id
- if textHasNl {
- var b bytes.Buffer
-
- for j := 1; j < txtE; j++ {
- switch {
- case data[j] != '\n':
- b.WriteByte(data[j])
- case data[j-1] != ' ':
- b.WriteByte(' ')
- }
- }
-
- id = b.Bytes()
- } else {
- if t == linkDeferredFootnote {
- id = data[2:txtE] // get rid of the ^
- } else {
- id = data[1:txtE]
- }
- }
-
- footnoteNode = NewNode(Item)
- if t == linkInlineFootnote {
- // create a new reference
- noteID = len(p.notes) + 1
-
- var fragment []byte
- if len(id) > 0 {
- if len(id) < 16 {
- fragment = make([]byte, len(id))
- } else {
- fragment = make([]byte, 16)
- }
- copy(fragment, slugify(id))
- } else {
- fragment = append([]byte("footnote-"), []byte(strconv.Itoa(noteID))...)
- }
-
- ref := &reference{
- noteID: noteID,
- hasBlock: false,
- link: fragment,
- title: id,
- footnote: footnoteNode,
- }
-
- p.notes = append(p.notes, ref)
-
- link = ref.link
- title = ref.title
- } else {
- // find the reference with matching id
- lr, ok := p.getRef(string(id))
- if !ok {
- return 0, nil
- }
-
- if t == linkDeferredFootnote {
- lr.noteID = len(p.notes) + 1
- lr.footnote = footnoteNode
- p.notes = append(p.notes, lr)
- }
-
- // keep link and title from reference
- link = lr.link
- // if inline footnote, title == footnote contents
- title = lr.title
- noteID = lr.noteID
- }
-
- // rewind the whitespace
- i = txtE + 1
- }
-
- var uLink []byte
- if t == linkNormal || t == linkImg {
- if len(link) > 0 {
- var uLinkBuf bytes.Buffer
- unescapeText(&uLinkBuf, link)
- uLink = uLinkBuf.Bytes()
- }
-
- // links need something to click on and somewhere to go
- if len(uLink) == 0 || (t == linkNormal && txtE <= 1) {
- return 0, nil
- }
- }
-
- // call the relevant rendering function
- var linkNode *Node
- switch t {
- case linkNormal:
- linkNode = NewNode(Link)
- linkNode.Destination = normalizeURI(uLink)
- linkNode.Title = title
- if len(altContent) > 0 {
- linkNode.AppendChild(text(altContent))
- } else {
- // links cannot contain other links, so turn off link parsing
- // temporarily and recurse
- insideLink := p.insideLink
- p.insideLink = true
- p.inline(linkNode, data[1:txtE])
- p.insideLink = insideLink
- }
-
- case linkImg:
- linkNode = NewNode(Image)
- linkNode.Destination = uLink
- linkNode.Title = title
- linkNode.AppendChild(text(data[1:txtE]))
- i++
-
- case linkInlineFootnote, linkDeferredFootnote:
- linkNode = NewNode(Link)
- linkNode.Destination = link
- linkNode.Title = title
- linkNode.NoteID = noteID
- linkNode.Footnote = footnoteNode
- if t == linkInlineFootnote {
- i++
- }
-
- default:
- return 0, nil
- }
-
- return i, linkNode
-}
-
-func (p *Markdown) inlineHTMLComment(data []byte) int {
- if len(data) < 5 {
- return 0
- }
- if data[0] != '<' || data[1] != '!' || data[2] != '-' || data[3] != '-' {
- return 0
- }
- i := 5
- // scan for an end-of-comment marker, across lines if necessary
- for i < len(data) && !(data[i-2] == '-' && data[i-1] == '-' && data[i] == '>') {
- i++
- }
- // no end-of-comment marker
- if i >= len(data) {
- return 0
- }
- return i + 1
-}
-
-func stripMailto(link []byte) []byte {
- if bytes.HasPrefix(link, []byte("mailto://")) {
- return link[9:]
- } else if bytes.HasPrefix(link, []byte("mailto:")) {
- return link[7:]
- } else {
- return link
- }
-}
-
-// autolinkType specifies a kind of autolink that gets detected.
-type autolinkType int
-
-// These are the possible flag values for the autolink renderer.
-const (
- notAutolink autolinkType = iota
- normalAutolink
- emailAutolink
-)
-
-// '<' when tags or autolinks are allowed
-func leftAngle(p *Markdown, data []byte, offset int) (int, *Node) {
- data = data[offset:]
- altype, end := tagLength(data)
- if size := p.inlineHTMLComment(data); size > 0 {
- end = size
- }
- if end > 2 {
- if altype != notAutolink {
- var uLink bytes.Buffer
- unescapeText(&uLink, data[1:end+1-2])
- if uLink.Len() > 0 {
- link := uLink.Bytes()
- node := NewNode(Link)
- node.Destination = link
- if altype == emailAutolink {
- node.Destination = append([]byte("mailto:"), link...)
- }
- node.AppendChild(text(stripMailto(link)))
- return end, node
- }
- } else {
- htmlTag := NewNode(HTMLSpan)
- htmlTag.Literal = data[:end]
- return end, htmlTag
- }
- }
-
- return end, nil
-}
-
-// '\\' backslash escape
-var escapeChars = []byte("\\`*_{}[]()#+-.!:|&<>~")
-
-func escape(p *Markdown, data []byte, offset int) (int, *Node) {
- data = data[offset:]
-
- if len(data) > 1 {
- if p.extensions&BackslashLineBreak != 0 && data[1] == '\n' {
- return 2, NewNode(Hardbreak)
- }
- if bytes.IndexByte(escapeChars, data[1]) < 0 {
- return 0, nil
- }
-
- return 2, text(data[1:2])
- }
-
- return 2, nil
-}
-
-func unescapeText(ob *bytes.Buffer, src []byte) {
- i := 0
- for i < len(src) {
- org := i
- for i < len(src) && src[i] != '\\' {
- i++
- }
-
- if i > org {
- ob.Write(src[org:i])
- }
-
- if i+1 >= len(src) {
- break
- }
-
- ob.WriteByte(src[i+1])
- i += 2
- }
-}
-
-// '&' escaped when it doesn't belong to an entity
-// valid entities are assumed to be anything matching &#?[A-Za-z0-9]+;
-func entity(p *Markdown, data []byte, offset int) (int, *Node) {
- data = data[offset:]
-
- end := 1
-
- if end < len(data) && data[end] == '#' {
- end++
- }
-
- for end < len(data) && isalnum(data[end]) {
- end++
- }
-
- if end < len(data) && data[end] == ';' {
- end++ // real entity
- } else {
- return 0, nil // lone '&'
- }
-
- ent := data[:end]
- // undo &amp; escaping or it will be converted to &amp;amp; by another
- // escaper in the renderer
- if bytes.Equal(ent, []byte("&amp;")) {
- ent = []byte{'&'}
- }
-
- return end, text(ent)
-}
-
-func linkEndsWithEntity(data []byte, linkEnd int) bool {
- entityRanges := htmlEntityRe.FindAllIndex(data[:linkEnd], -1)
- return entityRanges != nil && entityRanges[len(entityRanges)-1][1] == linkEnd
-}
-
-// hasPrefixCaseInsensitive is a custom implementation of
-//
-// strings.HasPrefix(strings.ToLower(s), prefix)
-//
-// we rolled our own because ToLower pulls in a huge machinery of lowercasing
-// anything from Unicode and that's very slow. Since this func will only be
-// used on ASCII protocol prefixes, we can take shortcuts.
-func hasPrefixCaseInsensitive(s, prefix []byte) bool {
- if len(s) < len(prefix) {
- return false
- }
- delta := byte('a' - 'A')
- for i, b := range prefix {
- if b != s[i] && b != s[i]+delta {
- return false
- }
- }
- return true
-}
-
-var protocolPrefixes = [][]byte{
- []byte("http://"),
- []byte("https://"),
- []byte("ftp://"),
- []byte("file://"),
- []byte("mailto:"),
-}
-
-const shortestPrefix = 6 // len("ftp://"), the shortest of the above
-
-func maybeAutoLink(p *Markdown, data []byte, offset int) (int, *Node) {
- // quick check to rule out most false hits
- if p.insideLink || len(data) < offset+shortestPrefix {
- return 0, nil
- }
- for _, prefix := range protocolPrefixes {
- endOfHead := offset + 8 // 8 is the len() of the longest prefix
- if endOfHead > len(data) {
- endOfHead = len(data)
- }
- if hasPrefixCaseInsensitive(data[offset:endOfHead], prefix) {
- return autoLink(p, data, offset)
- }
- }
- return 0, nil
-}
-
-func autoLink(p *Markdown, data []byte, offset int) (int, *Node) {
- // Now a more expensive check to see if we're not inside an anchor element
- anchorStart := offset
- offsetFromAnchor := 0
- for anchorStart > 0 && data[anchorStart] != '<' {
- anchorStart--
- offsetFromAnchor++
- }
-
- anchorStr := anchorRe.Find(data[anchorStart:])
- if anchorStr != nil {
- anchorClose := NewNode(HTMLSpan)
- anchorClose.Literal = anchorStr[offsetFromAnchor:]
- return len(anchorStr) - offsetFromAnchor, anchorClose
- }
-
- // scan backward for a word boundary
- rewind := 0
- for offset-rewind > 0 && rewind <= 7 && isletter(data[offset-rewind-1]) {
- rewind++
- }
- if rewind > 6 { // longest supported protocol is "mailto" which has 6 letters
- return 0, nil
- }
-
- origData := data
- data = data[offset-rewind:]
-
- if !isSafeLink(data) {
- return 0, nil
- }
-
- linkEnd := 0
- for linkEnd < len(data) && !isEndOfLink(data[linkEnd]) {
- linkEnd++
- }
-
- // Skip punctuation at the end of the link
- if (data[linkEnd-1] == '.' || data[linkEnd-1] == ',') && data[linkEnd-2] != '\\' {
- linkEnd--
- }
-
- // But don't skip semicolon if it's a part of escaped entity:
- if data[linkEnd-1] == ';' && data[linkEnd-2] != '\\' && !linkEndsWithEntity(data, linkEnd) {
- linkEnd--
- }
-
- // See if the link finishes with a punctuation sign that can be closed.
- var copen byte
- switch data[linkEnd-1] {
- case '"':
- copen = '"'
- case '\'':
- copen = '\''
- case ')':
- copen = '('
- case ']':
- copen = '['
- case '}':
- copen = '{'
- default:
- copen = 0
- }
-
- if copen != 0 {
- bufEnd := offset - rewind + linkEnd - 2
-
- openDelim := 1
-
- /* Try to close the final punctuation sign in this same line;
- * if we managed to close it outside of the URL, that means that it's
- * not part of the URL. If it closes inside the URL, that means it
- * is part of the URL.
- *
- * Examples:
- *
- * foo http://www.pokemon.com/Pikachu_(Electric) bar
- * => http://www.pokemon.com/Pikachu_(Electric)
- *
- * foo (http://www.pokemon.com/Pikachu_(Electric)) bar
- * => http://www.pokemon.com/Pikachu_(Electric)
- *
- * foo http://www.pokemon.com/Pikachu_(Electric)) bar
- * => http://www.pokemon.com/Pikachu_(Electric))
- *
- * (foo http://www.pokemon.com/Pikachu_(Electric)) bar
- * => foo http://www.pokemon.com/Pikachu_(Electric)
- */
-
- for bufEnd >= 0 && origData[bufEnd] != '\n' && openDelim != 0 {
- if origData[bufEnd] == data[linkEnd-1] {
- openDelim++
- }
-
- if origData[bufEnd] == copen {
- openDelim--
- }
-
- bufEnd--
- }
-
- if openDelim == 0 {
- linkEnd--
- }
- }
-
- var uLink bytes.Buffer
- unescapeText(&uLink, data[:linkEnd])
-
- if uLink.Len() > 0 {
- node := NewNode(Link)
- node.Destination = uLink.Bytes()
- node.AppendChild(text(uLink.Bytes()))
- return linkEnd, node
- }
-
- return linkEnd, nil
-}
-
-func isEndOfLink(char byte) bool {
- return isspace(char) || char == '<'
-}
-
-var validUris = [][]byte{[]byte("http://"), []byte("https://"), []byte("ftp://"), []byte("mailto://")}
-var validPaths = [][]byte{[]byte("/"), []byte("./"), []byte("../")}
-
-func isSafeLink(link []byte) bool {
- for _, path := range validPaths {
- if len(link) >= len(path) && bytes.Equal(link[:len(path)], path) {
- if len(link) == len(path) {
- return true
- } else if isalnum(link[len(path)]) {
- return true
- }
- }
- }
-
- for _, prefix := range validUris {
- // TODO: handle unicode here
- // case-insensitive prefix test
- if len(link) > len(prefix) && bytes.Equal(bytes.ToLower(link[:len(prefix)]), prefix) && isalnum(link[len(prefix)]) {
- return true
- }
- }
-
- return false
-}
-
-// return the length of the given tag, or 0 is it's not valid
-func tagLength(data []byte) (autolink autolinkType, end int) {
- var i, j int
-
- // a valid tag can't be shorter than 3 chars
- if len(data) < 3 {
- return notAutolink, 0
- }
-
- // begins with a '<' optionally followed by '/', followed by letter or number
- if data[0] != '<' {
- return notAutolink, 0
- }
- if data[1] == '/' {
- i = 2
- } else {
- i = 1
- }
-
- if !isalnum(data[i]) {
- return notAutolink, 0
- }
-
- // scheme test
- autolink = notAutolink
-
- // try to find the beginning of an URI
- for i < len(data) && (isalnum(data[i]) || data[i] == '.' || data[i] == '+' || data[i] == '-') {
- i++
- }
-
- if i > 1 && i < len(data) && data[i] == '@' {
- if j = isMailtoAutoLink(data[i:]); j != 0 {
- return emailAutolink, i + j
- }
- }
-
- if i > 2 && i < len(data) && data[i] == ':' {
- autolink = normalAutolink
- i++
- }
-
- // complete autolink test: no whitespace or ' or "
- switch {
- case i >= len(data):
- autolink = notAutolink
- case autolink != notAutolink:
- j = i
-
- for i < len(data) {
- if data[i] == '\\' {
- i += 2
- } else if data[i] == '>' || data[i] == '\'' || data[i] == '"' || isspace(data[i]) {
- break
- } else {
- i++
- }
-
- }
-
- if i >= len(data) {
- return autolink, 0
- }
- if i > j && data[i] == '>' {
- return autolink, i + 1
- }
-
- // one of the forbidden chars has been found
- autolink = notAutolink
- }
- i += bytes.IndexByte(data[i:], '>')
- if i < 0 {
- return autolink, 0
- }
- return autolink, i + 1
-}
-
-// look for the address part of a mail autolink and '>'
-// this is less strict than the original markdown e-mail address matching
-func isMailtoAutoLink(data []byte) int {
- nb := 0
-
- // address is assumed to be: [-@._a-zA-Z0-9]+ with exactly one '@'
- for i := 0; i < len(data); i++ {
- if isalnum(data[i]) {
- continue
- }
-
- switch data[i] {
- case '@':
- nb++
-
- case '-', '.', '_':
- break
-
- case '>':
- if nb == 1 {
- return i + 1
- }
- return 0
- default:
- return 0
- }
- }
-
- return 0
-}
-
-// look for the next emph char, skipping other constructs
-func helperFindEmphChar(data []byte, c byte) int {
- i := 0
-
- for i < len(data) {
- for i < len(data) && data[i] != c && data[i] != '`' && data[i] != '[' {
- i++
- }
- if i >= len(data) {
- return 0
- }
- // do not count escaped chars
- if i != 0 && data[i-1] == '\\' {
- i++
- continue
- }
- if data[i] == c {
- return i
- }
-
- if data[i] == '`' {
- // skip a code span
- tmpI := 0
- i++
- for i < len(data) && data[i] != '`' {
- if tmpI == 0 && data[i] == c {
- tmpI = i
- }
- i++
- }
- if i >= len(data) {
- return tmpI
- }
- i++
- } else if data[i] == '[' {
- // skip a link
- tmpI := 0
- i++
- for i < len(data) && data[i] != ']' {
- if tmpI == 0 && data[i] == c {
- tmpI = i
- }
- i++
- }
- i++
- for i < len(data) && (data[i] == ' ' || data[i] == '\n') {
- i++
- }
- if i >= len(data) {
- return tmpI
- }
- if data[i] != '[' && data[i] != '(' { // not a link
- if tmpI > 0 {
- return tmpI
- }
- continue
- }
- cc := data[i]
- i++
- for i < len(data) && data[i] != cc {
- if tmpI == 0 && data[i] == c {
- return i
- }
- i++
- }
- if i >= len(data) {
- return tmpI
- }
- i++
- }
- }
- return 0
-}
-
-func helperEmphasis(p *Markdown, data []byte, c byte) (int, *Node) {
- i := 0
-
- // skip one symbol if coming from emph3
- if len(data) > 1 && data[0] == c && data[1] == c {
- i = 1
- }
-
- for i < len(data) {
- length := helperFindEmphChar(data[i:], c)
- if length == 0 {
- return 0, nil
- }
- i += length
- if i >= len(data) {
- return 0, nil
- }
-
- if i+1 < len(data) && data[i+1] == c {
- i++
- continue
- }
-
- if data[i] == c && !isspace(data[i-1]) {
-
- if p.extensions&NoIntraEmphasis != 0 {
- if !(i+1 == len(data) || isspace(data[i+1]) || ispunct(data[i+1])) {
- continue
- }
- }
-
- emph := NewNode(Emph)
- p.inline(emph, data[:i])
- return i + 1, emph
- }
- }
-
- return 0, nil
-}
-
-func helperDoubleEmphasis(p *Markdown, data []byte, c byte) (int, *Node) {
- i := 0
-
- for i < len(data) {
- length := helperFindEmphChar(data[i:], c)
- if length == 0 {
- return 0, nil
- }
- i += length
-
- if i+1 < len(data) && data[i] == c && data[i+1] == c && i > 0 && !isspace(data[i-1]) {
- nodeType := Strong
- if c == '~' {
- nodeType = Del
- }
- node := NewNode(nodeType)
- p.inline(node, data[:i])
- return i + 2, node
- }
- i++
- }
- return 0, nil
-}
-
-func helperTripleEmphasis(p *Markdown, data []byte, offset int, c byte) (int, *Node) {
- i := 0
- origData := data
- data = data[offset:]
-
- for i < len(data) {
- length := helperFindEmphChar(data[i:], c)
- if length == 0 {
- return 0, nil
- }
- i += length
-
- // skip whitespace preceded symbols
- if data[i] != c || isspace(data[i-1]) {
- continue
- }
-
- switch {
- case i+2 < len(data) && data[i+1] == c && data[i+2] == c:
- // triple symbol found
- strong := NewNode(Strong)
- em := NewNode(Emph)
- strong.AppendChild(em)
- p.inline(em, data[:i])
- return i + 3, strong
- case (i+1 < len(data) && data[i+1] == c):
- // double symbol found, hand over to emph1
- length, node := helperEmphasis(p, origData[offset-2:], c)
- if length == 0 {
- return 0, nil
- }
- return length - 2, node
- default:
- // single symbol found, hand over to emph2
- length, node := helperDoubleEmphasis(p, origData[offset-1:], c)
- if length == 0 {
- return 0, nil
- }
- return length - 1, node
- }
- }
- return 0, nil
-}
-
-func text(s []byte) *Node {
- node := NewNode(Text)
- node.Literal = s
- return node
-}
-
-func normalizeURI(s []byte) []byte {
- return s // TODO: implement
-}
diff --git a/vendor/go.step.sm/cli-utils/pkg/blackfriday/markdown.go b/vendor/go.step.sm/cli-utils/pkg/blackfriday/markdown.go
deleted file mode 100644
index 4d0a831..0000000
--- a/vendor/go.step.sm/cli-utils/pkg/blackfriday/markdown.go
+++ /dev/null
@@ -1,945 +0,0 @@
-// Blackfriday Markdown Processor
-// Available at http://github.com/russross/blackfriday
-//
-// Copyright © 2011 Russ Ross <russ@russross.com>.
-// Distributed under the Simplified BSD License.
-// See README.md for details.
-
-//nolint:gocritic,wastedassign,unused,revive,govet // ignore blackfriday
-package blackfriday
-
-import (
- "bytes"
- "fmt"
- "io"
- "strings"
- "unicode/utf8"
-)
-
-//
-// Markdown parsing and processing
-//
-
-// Version string of the package. Appears in the rendered document when
-// CompletePage flag is on.
-const Version = "2.0"
-
-// Extensions is a bitwise or'ed collection of enabled Blackfriday's
-// extensions.
-type Extensions int
-
-// These are the supported markdown parsing extensions.
-// OR these values together to select multiple extensions.
-const (
- NoExtensions Extensions = 0
- NoIntraEmphasis Extensions = 1 << iota // Ignore emphasis markers inside words
- Tables // Render tables
- FencedCode // Render fenced code blocks
- Autolink // Detect embedded URLs that are not explicitly marked
- Strikethrough // Strikethrough text using ~~test~~
- LaxHTMLBlocks // Loosen up HTML block parsing rules
- SpaceHeadings // Be strict about prefix heading rules
- HardLineBreak // Translate newlines into line breaks
- TabSizeEight // Expand tabs to eight spaces instead of four
- Footnotes // Pandoc-style footnotes
- NoEmptyLineBeforeBlock // No need to insert an empty line to start a (code, quote, ordered list, unordered list) block
- HeadingIDs // specify heading IDs with {#id}
- Titleblock // Titleblock ala pandoc
- AutoHeadingIDs // Create the heading ID from the text
- BackslashLineBreak // Translate trailing backslashes into line breaks
- DefinitionLists // Render definition lists
-
- CommonHTMLFlags HTMLFlags = UseXHTML | Smartypants |
- SmartypantsFractions | SmartypantsDashes | SmartypantsLatexDashes
-
- CommonExtensions Extensions = NoIntraEmphasis | Tables | FencedCode |
- Autolink | Strikethrough | SpaceHeadings | HeadingIDs |
- BackslashLineBreak | DefinitionLists
-)
-
-// ListType contains bitwise or'ed flags for list and list item objects.
-type ListType int
-
-// These are the possible flag values for the ListItem renderer.
-// Multiple flag values may be ORed together.
-// These are mostly of interest if you are writing a new output format.
-const (
- ListTypeOrdered ListType = 1 << iota
- ListTypeDefinition
- ListTypeTerm
-
- ListItemContainsBlock
- ListItemBeginningOfList // TODO: figure out if this is of any use now
- ListItemEndOfList
-)
-
-// CellAlignFlags holds a type of alignment in a table cell.
-type CellAlignFlags int
-
-// These are the possible flag values for the table cell renderer.
-// Only a single one of these values will be used; they are not ORed together.
-// These are mostly of interest if you are writing a new output format.
-const (
- TableAlignmentLeft CellAlignFlags = 1 << iota
- TableAlignmentRight
- TableAlignmentCenter = (TableAlignmentLeft | TableAlignmentRight)
-)
-
-// The size of a tab stop.
-const (
- TabSizeDefault = 4
- TabSizeDouble = 8
-)
-
-// blockTags is a set of tags that are recognized as HTML block tags.
-// Any of these can be included in markdown text without special escaping.
-var blockTags = map[string]struct{}{
- "blockquote": {},
- "del": {},
- "div": {},
- "dl": {},
- "fieldset": {},
- "form": {},
- "h1": {},
- "h2": {},
- "h3": {},
- "h4": {},
- "h5": {},
- "h6": {},
- "iframe": {},
- "ins": {},
- "math": {},
- "noscript": {},
- "ol": {},
- "pre": {},
- "p": {},
- "script": {},
- "style": {},
- "table": {},
- "ul": {},
-
- // HTML5
- "address": {},
- "article": {},
- "aside": {},
- "canvas": {},
- "figcaption": {},
- "figure": {},
- "footer": {},
- "header": {},
- "hgroup": {},
- "main": {},
- "nav": {},
- "output": {},
- "progress": {},
- "section": {},
- "video": {},
-}
-
-// Renderer is the rendering interface. This is mostly of interest if you are
-// implementing a new rendering format.
-//
-// Only an HTML implementation is provided in this repository, see the README
-// for external implementations.
-type Renderer interface {
- // RenderNode is the main rendering method. It will be called once for
- // every leaf node and twice for every non-leaf node (first with
- // entering=true, then with entering=false). The method should write its
- // rendition of the node to the supplied writer w.
- RenderNode(w io.Writer, node *Node, entering bool) WalkStatus
-
- // RenderHeader is a method that allows the renderer to produce some
- // content preceding the main body of the output document. The header is
- // understood in the broad sense here. For example, the default HTML
- // renderer will write not only the HTML document preamble, but also the
- // table of contents if it was requested.
- //
- // The method will be passed an entire document tree, in case a particular
- // implementation needs to inspect it to produce output.
- //
- // The output should be written to the supplied writer w. If your
- // implementation has no header to write, supply an empty implementation.
- RenderHeader(w io.Writer, ast *Node)
-
- // RenderFooter is a symmetric counterpart of RenderHeader.
- RenderFooter(w io.Writer, ast *Node)
-}
-
-// Callback functions for inline parsing. One such function is defined
-// for each character that triggers a response when parsing inline data.
-type inlineParser func(p *Markdown, data []byte, offset int) (int, *Node)
-
-// Markdown is a type that holds extensions and the runtime state used by
-// Parse, and the renderer. You can not use it directly, construct it with New.
-type Markdown struct {
- renderer Renderer
- referenceOverride ReferenceOverrideFunc
- refs map[string]*reference
- inlineCallback [256]inlineParser
- extensions Extensions
- nesting int
- maxNesting int
- insideLink bool
-
- // Footnotes need to be ordered as well as available to quickly check for
- // presence. If a ref is also a footnote, it's stored both in refs and here
- // in notes. Slice is nil if footnotes not enabled.
- notes []*reference
-
- doc *Node
- tip *Node // = doc
- oldTip *Node
- lastMatchedContainer *Node // = doc
- allClosed bool
-}
-
-func (p *Markdown) getRef(refid string) (ref *reference, found bool) {
- if p.referenceOverride != nil {
- r, overridden := p.referenceOverride(refid)
- if overridden {
- if r == nil {
- return nil, false
- }
- return &reference{
- link: []byte(r.Link),
- title: []byte(r.Title),
- noteID: 0,
- hasBlock: false,
- text: []byte(r.Text)}, true
- }
- }
- // refs are case insensitive
- ref, found = p.refs[strings.ToLower(refid)]
- return ref, found
-}
-
-func (p *Markdown) finalize(block *Node) {
- above := block.Parent
- block.open = false
- p.tip = above
-}
-
-func (p *Markdown) addChild(node NodeType, offset uint32) *Node {
- return p.addExistingChild(NewNode(node), offset)
-}
-
-func (p *Markdown) addExistingChild(node *Node, offset uint32) *Node {
- for !p.tip.canContain(node.Type) {
- p.finalize(p.tip)
- }
- p.tip.AppendChild(node)
- p.tip = node
- return node
-}
-
-func (p *Markdown) closeUnmatchedBlocks() {
- if !p.allClosed {
- for p.oldTip != p.lastMatchedContainer {
- parent := p.oldTip.Parent
- p.finalize(p.oldTip)
- p.oldTip = parent
- }
- p.allClosed = true
- }
-}
-
-//
-//
-// Public interface
-//
-//
-
-// Reference represents the details of a link.
-// See the documentation in Options for more details on use-case.
-type Reference struct {
- // Link is usually the URL the reference points to.
- Link string
- // Title is the alternate text describing the link in more detail.
- Title string
- // Text is the optional text to override the ref with if the syntax used was
- // [refid][]
- Text string
-}
-
-// ReferenceOverrideFunc is expected to be called with a reference string and
-// return either a valid Reference type that the reference string maps to or
-// nil. If overridden is false, the default reference logic will be executed.
-// See the documentation in Options for more details on use-case.
-type ReferenceOverrideFunc func(reference string) (ref *Reference, overridden bool)
-
-// New constructs a Markdown processor. You can use the same With* functions as
-// for Run() to customize parser's behavior and the renderer.
-func New(opts ...Option) *Markdown {
- var p Markdown
- for _, opt := range opts {
- opt(&p)
- }
- p.refs = make(map[string]*reference)
- p.maxNesting = 16
- p.insideLink = false
- docNode := NewNode(Document)
- p.doc = docNode
- p.tip = docNode
- p.oldTip = docNode
- p.lastMatchedContainer = docNode
- p.allClosed = true
- // register inline parsers
- p.inlineCallback[' '] = maybeLineBreak
- p.inlineCallback['*'] = emphasis
- p.inlineCallback['_'] = emphasis
- if p.extensions&Strikethrough != 0 {
- p.inlineCallback['~'] = emphasis
- }
- p.inlineCallback['`'] = codeSpan
- p.inlineCallback['\n'] = lineBreak
- p.inlineCallback['['] = link
- p.inlineCallback['<'] = leftAngle
- p.inlineCallback['\\'] = escape
- p.inlineCallback['&'] = entity
- p.inlineCallback['!'] = maybeImage
- p.inlineCallback['^'] = maybeInlineFootnote
- if p.extensions&Autolink != 0 {
- p.inlineCallback['h'] = maybeAutoLink
- p.inlineCallback['m'] = maybeAutoLink
- p.inlineCallback['f'] = maybeAutoLink
- p.inlineCallback['H'] = maybeAutoLink
- p.inlineCallback['M'] = maybeAutoLink
- p.inlineCallback['F'] = maybeAutoLink
- }
- if p.extensions&Footnotes != 0 {
- p.notes = make([]*reference, 0)
- }
- return &p
-}
-
-// Option customizes the Markdown processor's default behavior.
-type Option func(*Markdown)
-
-// WithRenderer allows you to override the default renderer.
-func WithRenderer(r Renderer) Option {
- return func(p *Markdown) {
- p.renderer = r
- }
-}
-
-// WithExtensions allows you to pick some of the many extensions provided by
-// Blackfriday. You can bitwise OR them.
-func WithExtensions(e Extensions) Option {
- return func(p *Markdown) {
- p.extensions = e
- }
-}
-
-// WithNoExtensions turns off all extensions and custom behavior.
-func WithNoExtensions() Option {
- return func(p *Markdown) {
- p.extensions = NoExtensions
- p.renderer = NewHTMLRenderer(HTMLRendererParameters{
- Flags: HTMLFlagsNone,
- })
- }
-}
-
-// WithRefOverride sets an optional function callback that is called every
-// time a reference is resolved.
-//
-// In Markdown, the link reference syntax can be made to resolve a link to
-// a reference instead of an inline URL, in one of the following ways:
-//
-// - [link text][refid]
-// - [refid][]
-//
-// Usually, the refid is defined at the bottom of the Markdown document. If
-// this override function is provided, the refid is passed to the override
-// function first, before consulting the defined refids at the bottom. If
-// the override function indicates an override did not occur, the refids at
-// the bottom will be used to fill in the link details.
-func WithRefOverride(o ReferenceOverrideFunc) Option {
- return func(p *Markdown) {
- p.referenceOverride = o
- }
-}
-
-// Run is the main entry point to Blackfriday. It parses and renders a
-// block of markdown-encoded text.
-//
-// The simplest invocation of Run takes one argument, input:
-//
-// output := Run(input)
-//
-// This will parse the input with CommonExtensions enabled and render it with
-// the default HTMLRenderer (with CommonHTMLFlags).
-//
-// Variadic arguments opts can customize the default behavior. Since Markdown
-// type does not contain exported fields, you can not use it directly. Instead,
-// use the With* functions. For example, this will call the most basic
-// functionality, with no extensions:
-//
-// output := Run(input, WithNoExtensions())
-//
-// You can use any number of With* arguments, even contradicting ones. They
-// will be applied in order of appearance and the latter will override the
-// former:
-//
-// output := Run(input, WithNoExtensions(), WithExtensions(exts),
-// WithRenderer(yourRenderer))
-func Run(input []byte, opts ...Option) []byte {
- r := NewHTMLRenderer(HTMLRendererParameters{
- Flags: CommonHTMLFlags,
- })
- optList := []Option{WithRenderer(r), WithExtensions(CommonExtensions)}
- optList = append(optList, opts...)
- parser := New(optList...)
- ast := parser.Parse(input)
- var buf bytes.Buffer
- parser.renderer.RenderHeader(&buf, ast)
- ast.Walk(func(node *Node, entering bool) WalkStatus {
- return parser.renderer.RenderNode(&buf, node, entering)
- })
- parser.renderer.RenderFooter(&buf, ast)
- return buf.Bytes()
-}
-
-// Parse is an entry point to the parsing part of Blackfriday. It takes an
-// input markdown document and produces a syntax tree for its contents. This
-// tree can then be rendered with a default or custom renderer, or
-// analyzed/transformed by the caller to whatever non-standard needs they have.
-// The return value is the root node of the syntax tree.
-func (p *Markdown) Parse(input []byte) *Node {
- p.block(input)
- // Walk the tree and finish up some of unfinished blocks
- for p.tip != nil {
- p.finalize(p.tip)
- }
- // Walk the tree again and process inline markdown in each block
- p.doc.Walk(func(node *Node, entering bool) WalkStatus {
- if node.Type == Paragraph || node.Type == Heading || node.Type == TableCell {
- p.inline(node, node.content)
- node.content = nil
- }
- return GoToNext
- })
- p.parseRefsToAST()
- return p.doc
-}
-
-func (p *Markdown) parseRefsToAST() {
- if p.extensions&Footnotes == 0 || len(p.notes) == 0 {
- return
- }
- p.tip = p.doc
- block := p.addBlock(List, nil)
- block.IsFootnotesList = true
- block.ListFlags = ListTypeOrdered
- flags := ListItemBeginningOfList
- // Note: this loop is intentionally explicit, not range-form. This is
- // because the body of the loop will append nested footnotes to p.notes and
- // we need to process those late additions. Range form would only walk over
- // the fixed initial set.
- for i := 0; i < len(p.notes); i++ {
- ref := p.notes[i]
- p.addExistingChild(ref.footnote, 0)
- block := ref.footnote
- block.ListFlags = flags | ListTypeOrdered
- block.RefLink = ref.link
- if ref.hasBlock {
- flags |= ListItemContainsBlock
- p.block(ref.title)
- } else {
- p.inline(block, ref.title)
- }
- flags &^= ListItemBeginningOfList | ListItemContainsBlock
- }
- above := block.Parent
- finalizeList(block)
- p.tip = above
- block.Walk(func(node *Node, entering bool) WalkStatus {
- if node.Type == Paragraph || node.Type == Heading {
- p.inline(node, node.content)
- node.content = nil
- }
- return GoToNext
- })
-}
-
-//
-// Link references
-//
-// This section implements support for references that (usually) appear
-// as footnotes in a document, and can be referenced anywhere in the document.
-// The basic format is:
-//
-// [1]: http://www.google.com/ "Google"
-// [2]: http://www.github.com/ "Github"
-//
-// Anywhere in the document, the reference can be linked by referring to its
-// label, i.e., 1 and 2 in this example, as in:
-//
-// This library is hosted on [Github][2], a git hosting site.
-//
-// Actual footnotes as specified in Pandoc and supported by some other Markdown
-// libraries such as php-markdown are also taken care of. They look like this:
-//
-// This sentence needs a bit of further explanation.[^note]
-//
-// [^note]: This is the explanation.
-//
-// Footnotes should be placed at the end of the document in an ordered list.
-// Inline footnotes such as:
-//
-// Inline footnotes^[Not supported.] also exist.
-//
-// are not yet supported.
-
-// reference holds all information necessary for a reference-style links or
-// footnotes.
-//
-// Consider this markdown with reference-style links:
-//
-// [link][ref]
-//
-// [ref]: /url/ "tooltip title"
-//
-// It will be ultimately converted to this HTML:
-//
-// <p><a href=\"/url/\" title=\"title\">link</a></p>
-//
-// And a reference structure will be populated as follows:
-//
-// p.refs["ref"] = &reference{
-// link: "/url/",
-// title: "tooltip title",
-// }
-//
-// Alternatively, reference can contain information about a footnote. Consider
-// this markdown:
-//
-// Text needing a footnote.[^a]
-//
-// [^a]: This is the note
-//
-// A reference structure will be populated as follows:
-//
-// p.refs["a"] = &reference{
-// link: "a",
-// title: "This is the note",
-// noteID: <some positive int>,
-// }
-//
-// TODO: As you can see, it begs for splitting into two dedicated structures
-// for refs and for footnotes.
-type reference struct {
- link []byte
- title []byte
- noteID int // 0 if not a footnote ref
- hasBlock bool
- footnote *Node // a link to the Item node within a list of footnotes
-
- text []byte // only gets populated by refOverride feature with Reference.Text
-}
-
-func (r *reference) String() string {
- return fmt.Sprintf("{link: %q, title: %q, text: %q, noteID: %d, hasBlock: %v}",
- r.link, r.title, r.text, r.noteID, r.hasBlock)
-}
-
-// Check whether or not data starts with a reference link.
-// If so, it is parsed and stored in the list of references
-// (in the render struct).
-// Returns the number of bytes to skip to move past it,
-// or zero if the first line is not a reference.
-func isReference(p *Markdown, data []byte, tabSize int) int {
- // up to 3 optional leading spaces
- if len(data) < 4 {
- return 0
- }
- i := 0
- for i < 3 && data[i] == ' ' {
- i++
- }
-
- noteID := 0
-
- // id part: anything but a newline between brackets
- if data[i] != '[' {
- return 0
- }
- i++
- if p.extensions&Footnotes != 0 {
- if i < len(data) && data[i] == '^' {
- // we can set it to anything here because the proper noteIds will
- // be assigned later during the second pass. It just has to be != 0
- noteID = 1
- i++
- }
- }
- idOffset := i
- for i < len(data) && data[i] != '\n' && data[i] != '\r' && data[i] != ']' {
- i++
- }
- if i >= len(data) || data[i] != ']' {
- return 0
- }
- idEnd := i
- // footnotes can have empty ID, like this: [^], but a reference can not be
- // empty like this: []. Break early if it's not a footnote and there's no ID
- if noteID == 0 && idOffset == idEnd {
- return 0
- }
- // spacer: colon (space | tab)* newline? (space | tab)*
- i++
- if i >= len(data) || data[i] != ':' {
- return 0
- }
- i++
- for i < len(data) && (data[i] == ' ' || data[i] == '\t') {
- i++
- }
- if i < len(data) && (data[i] == '\n' || data[i] == '\r') {
- i++
- if i < len(data) && data[i] == '\n' && data[i-1] == '\r' {
- i++
- }
- }
- for i < len(data) && (data[i] == ' ' || data[i] == '\t') {
- i++
- }
- if i >= len(data) {
- return 0
- }
-
- var (
- linkOffset, linkEnd int
- titleOffset, titleEnd int
- lineEnd int
- raw []byte
- hasBlock bool
- )
-
- if p.extensions&Footnotes != 0 && noteID != 0 {
- linkOffset, linkEnd, raw, hasBlock = scanFootnote(p, data, i, tabSize)
- lineEnd = linkEnd
- } else {
- linkOffset, linkEnd, titleOffset, titleEnd, lineEnd = scanLinkRef(p, data, i)
- }
- if lineEnd == 0 {
- return 0
- }
-
- // a valid ref has been found
-
- ref := &reference{
- noteID: noteID,
- hasBlock: hasBlock,
- }
-
- if noteID > 0 {
- // reusing the link field for the id since footnotes don't have links
- ref.link = data[idOffset:idEnd]
- // if footnote, it's not really a title, it's the contained text
- ref.title = raw
- } else {
- ref.link = data[linkOffset:linkEnd]
- ref.title = data[titleOffset:titleEnd]
- }
-
- // id matches are case-insensitive
- id := string(bytes.ToLower(data[idOffset:idEnd]))
-
- p.refs[id] = ref
-
- return lineEnd
-}
-
-func scanLinkRef(p *Markdown, data []byte, i int) (linkOffset, linkEnd, titleOffset, titleEnd, lineEnd int) {
- // link: whitespace-free sequence, optionally between angle brackets
- if data[i] == '<' {
- i++
- }
- linkOffset = i
- for i < len(data) && data[i] != ' ' && data[i] != '\t' && data[i] != '\n' && data[i] != '\r' {
- i++
- }
- linkEnd = i
- if data[linkOffset] == '<' && data[linkEnd-1] == '>' {
- linkOffset++
- linkEnd--
- }
-
- // optional spacer: (space | tab)* (newline | '\'' | '"' | '(' )
- for i < len(data) && (data[i] == ' ' || data[i] == '\t') {
- i++
- }
- if i < len(data) && data[i] != '\n' && data[i] != '\r' && data[i] != '\'' && data[i] != '"' && data[i] != '(' {
- return
- }
-
- // compute end-of-line
- if i >= len(data) || data[i] == '\r' || data[i] == '\n' {
- lineEnd = i
- }
- if i+1 < len(data) && data[i] == '\r' && data[i+1] == '\n' {
- lineEnd++
- }
-
- // optional (space|tab)* spacer after a newline
- if lineEnd > 0 {
- i = lineEnd + 1
- for i < len(data) && (data[i] == ' ' || data[i] == '\t') {
- i++
- }
- }
-
- // optional title: any non-newline sequence enclosed in '"() alone on its line
- if i+1 < len(data) && (data[i] == '\'' || data[i] == '"' || data[i] == '(') {
- i++
- titleOffset = i
-
- // look for EOL
- for i < len(data) && data[i] != '\n' && data[i] != '\r' {
- i++
- }
- if i+1 < len(data) && data[i] == '\n' && data[i+1] == '\r' {
- titleEnd = i + 1
- } else {
- titleEnd = i
- }
-
- // step back
- i--
- for i > titleOffset && (data[i] == ' ' || data[i] == '\t') {
- i--
- }
- if i > titleOffset && (data[i] == '\'' || data[i] == '"' || data[i] == ')') {
- lineEnd = titleEnd
- titleEnd = i
- }
- }
-
- return
-}
-
-// The first bit of this logic is the same as Parser.listItem, but the rest
-// is much simpler. This function simply finds the entire block and shifts it
-// over by one tab if it is indeed a block (just returns the line if it's not).
-// blockEnd is the end of the section in the input buffer, and contents is the
-// extracted text that was shifted over one tab. It will need to be rendered at
-// the end of the document.
-func scanFootnote(p *Markdown, data []byte, i, indentSize int) (blockStart, blockEnd int, contents []byte, hasBlock bool) {
- if i == 0 || len(data) == 0 {
- return
- }
-
- // skip leading whitespace on first line
- for i < len(data) && data[i] == ' ' {
- i++
- }
-
- blockStart = i
-
- // find the end of the line
- blockEnd = i
- for 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[blockEnd:i])
- blockEnd = i
-
- // process the following lines
- containsBlankLine := false
-
-gatherLines:
- for blockEnd < 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[blockEnd:i]) > 0 {
- containsBlankLine = true
- blockEnd = i
- continue
- }
-
- n := 0
- if n = isIndented(data[blockEnd:i], indentSize); n == 0 {
- // this is the end of the block.
- // we don't want to include this last line in the index.
- break gatherLines
- }
-
- // if there were blank lines before this one, insert a new one now
- if containsBlankLine {
- raw.WriteByte('\n')
- containsBlankLine = false
- }
-
- // get rid of that first tab, write to buffer
- raw.Write(data[blockEnd+n : i])
- hasBlock = true
-
- blockEnd = i
- }
-
- if data[blockEnd-1] != '\n' {
- raw.WriteByte('\n')
- }
-
- contents = raw.Bytes()
-
- return
-}
-
-//
-//
-// Miscellaneous helper functions
-//
-//
-
-// Test if a character is a punctuation symbol.
-// Taken from a private function in regexp in the stdlib.
-func ispunct(c byte) bool {
- for _, r := range []byte("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~") {
- if c == r {
- return true
- }
- }
- return false
-}
-
-// Test if a character is a whitespace character.
-func isspace(c byte) bool {
- return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v'
-}
-
-// Test if a character is letter.
-func isletter(c byte) bool {
- return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
-}
-
-// Test if a character is a letter or a digit.
-// TODO: check when this is looking for ASCII alnum and when it should use unicode
-func isalnum(c byte) bool {
- return (c >= '0' && c <= '9') || isletter(c)
-}
-
-// Replace tab characters with spaces, aligning to the next TAB_SIZE column.
-// always ends output with a newline
-func expandTabs(out *bytes.Buffer, line []byte, tabSize int) {
- // first, check for common cases: no tabs, or only tabs at beginning of line
- i, prefix := 0, 0
- slowcase := false
- for i = 0; i < len(line); i++ {
- if line[i] == '\t' {
- if prefix == i {
- prefix++
- } else {
- slowcase = true
- break
- }
- }
- }
-
- // no need to decode runes if all tabs are at the beginning of the line
- if !slowcase {
- for i = 0; i < prefix*tabSize; i++ {
- out.WriteByte(' ')
- }
- out.Write(line[prefix:])
- return
- }
-
- // the slow case: we need to count runes to figure out how
- // many spaces to insert for each tab
- column := 0
- i = 0
- for i < len(line) {
- start := i
- for i < len(line) && line[i] != '\t' {
- _, size := utf8.DecodeRune(line[i:])
- i += size
- column++
- }
-
- if i > start {
- out.Write(line[start:i])
- }
-
- if i >= len(line) {
- break
- }
-
- for {
- out.WriteByte(' ')
- column++
- if column%tabSize == 0 {
- break
- }
- }
-
- i++
- }
-}
-
-// Find if a line counts as indented or not.
-// Returns number of characters the indent is (0 = not indented).
-func isIndented(data []byte, indentSize int) int {
- if len(data) == 0 {
- return 0
- }
- if data[0] == '\t' {
- return 1
- }
- if len(data) < indentSize {
- return 0
- }
- for i := 0; i < indentSize; i++ {
- if data[i] != ' ' {
- return 0
- }
- }
- return indentSize
-}
-
-// Create a url-safe slug for fragments
-func slugify(in []byte) []byte {
- if len(in) == 0 {
- return in
- }
- out := make([]byte, 0, len(in))
- sym := false
-
- for _, ch := range in {
- if isalnum(ch) {
- sym = false
- out = append(out, ch)
- } else if sym {
- continue
- } else {
- out = append(out, '-')
- sym = true
- }
- }
- var a, b int
- var ch byte
- for a, ch = range out {
- if ch != '-' {
- break
- }
- }
- for b = len(out) - 1; b > 0; b-- {
- if out[b] != '-' {
- break
- }
- }
- return out[a : b+1]
-}
diff --git a/vendor/go.step.sm/cli-utils/pkg/blackfriday/node.go b/vendor/go.step.sm/cli-utils/pkg/blackfriday/node.go
deleted file mode 100644
index d820b83..0000000
--- a/vendor/go.step.sm/cli-utils/pkg/blackfriday/node.go
+++ /dev/null
@@ -1,355 +0,0 @@
-//nolint:gocritic,unused // ignore blackfriday
-package blackfriday
-
-import (
- "bytes"
- "fmt"
-)
-
-// NodeType specifies a type of a single node of a syntax tree. Usually one
-// node (and its type) corresponds to a single markdown feature, e.g. emphasis
-// or code block.
-type NodeType int
-
-// Constants for identifying different types of nodes. See NodeType.
-const (
- Document NodeType = iota
- BlockQuote
- List
- Item
- Paragraph
- Heading
- HorizontalRule
- Emph
- Strong
- Del
- Link
- Image
- Text
- HTMLBlock
- CodeBlock
- Softbreak
- Hardbreak
- Code
- HTMLSpan
- Table
- TableCell
- TableHead
- TableBody
- TableRow
-)
-
-var nodeTypeNames = []string{
- Document: "Document",
- BlockQuote: "BlockQuote",
- List: "List",
- Item: "Item",
- Paragraph: "Paragraph",
- Heading: "Heading",
- HorizontalRule: "HorizontalRule",
- Emph: "Emph",
- Strong: "Strong",
- Del: "Del",
- Link: "Link",
- Image: "Image",
- Text: "Text",
- HTMLBlock: "HTMLBlock",
- CodeBlock: "CodeBlock",
- Softbreak: "Softbreak",
- Hardbreak: "Hardbreak",
- Code: "Code",
- HTMLSpan: "HTMLSpan",
- Table: "Table",
- TableCell: "TableCell",
- TableHead: "TableHead",
- TableBody: "TableBody",
- TableRow: "TableRow",
-}
-
-func (t NodeType) String() string {
- return nodeTypeNames[t]
-}
-
-// ListData contains fields relevant to a List and Item node type.
-type ListData struct {
- ListFlags ListType
- Tight bool // Skip <p>s around list item data if true
- BulletChar byte // '*', '+' or '-' in bullet lists
- Delimiter byte // '.' or ')' after the number in ordered lists
- RefLink []byte // If not nil, turns this list item into a footnote item and triggers different rendering
- IsFootnotesList bool // This is a list of footnotes
-}
-
-// LinkData contains fields relevant to a Link node type.
-type LinkData struct {
- Destination []byte // Destination is what goes into a href
- Title []byte // Title is the tooltip thing that goes in a title attribute
- NoteID int // NoteID contains a serial number of a footnote, zero if it's not a footnote
- Footnote *Node // If it's a footnote, this is a direct link to the footnote Node. Otherwise nil.
-}
-
-// CodeBlockData contains fields relevant to a CodeBlock node type.
-type CodeBlockData struct {
- IsFenced bool // Specifies whether it's a fenced code block or an indented one
- Info []byte // This holds the info string
- FenceChar byte
- FenceLength int
- FenceOffset int
-}
-
-// TableCellData contains fields relevant to a TableCell node type.
-type TableCellData struct {
- IsHeader bool // This tells if it's under the header row
- Align CellAlignFlags // This holds the value for align attribute
-}
-
-// HeadingData contains fields relevant to a Heading node type.
-type HeadingData struct {
- Level int // This holds the heading level number
- HeadingID string // This might hold heading ID, if present
- IsTitleblock bool // Specifies whether it's a title block
-}
-
-// Node is a single element in the abstract syntax tree of the parsed document.
-// It holds connections to the structurally neighboring nodes and, for certain
-// types of nodes, additional information that might be needed when rendering.
-type Node struct {
- Type NodeType // Determines the type of the node
- Parent *Node // Points to the parent
- FirstChild *Node // Points to the first child, if any
- LastChild *Node // Points to the last child, if any
- Prev *Node // Previous sibling; nil if it's the first child
- Next *Node // Next sibling; nil if it's the last child
-
- Literal []byte // Text contents of the leaf nodes
-
- HeadingData // Populated if Type is Heading
- ListData // Populated if Type is List
- CodeBlockData // Populated if Type is CodeBlock
- LinkData // Populated if Type is Link
- TableCellData // Populated if Type is TableCell
-
- content []byte // Markdown content of the block nodes
- open bool // Specifies an open block node that has not been finished to process yet
-}
-
-// NewNode allocates a node of a specified type.
-func NewNode(typ NodeType) *Node {
- return &Node{
- Type: typ,
- open: true,
- }
-}
-
-func (n *Node) String() string {
- ellipsis := ""
- snippet := n.Literal
- if len(snippet) > 16 {
- snippet = snippet[:16]
- ellipsis = "..."
- }
- return fmt.Sprintf("%s: '%s%s'", n.Type, snippet, ellipsis)
-}
-
-// Unlink removes node 'n' from the tree.
-// It panics if the node is nil.
-func (n *Node) Unlink() {
- if n.Prev != nil {
- n.Prev.Next = n.Next
- } else if n.Parent != nil {
- n.Parent.FirstChild = n.Next
- }
- if n.Next != nil {
- n.Next.Prev = n.Prev
- } else if n.Parent != nil {
- n.Parent.LastChild = n.Prev
- }
- n.Parent = nil
- n.Next = nil
- n.Prev = nil
-}
-
-// AppendChild adds a node 'child' as a child of 'n'.
-// It panics if either node is nil.
-func (n *Node) AppendChild(child *Node) {
- child.Unlink()
- child.Parent = n
- if n.LastChild != nil {
- n.LastChild.Next = child
- child.Prev = n.LastChild
- n.LastChild = child
- } else {
- n.FirstChild = child
- n.LastChild = child
- }
-}
-
-// InsertBefore inserts 'sibling' immediately before 'n'.
-// It panics if either node is nil.
-func (n *Node) InsertBefore(sibling *Node) {
- sibling.Unlink()
- sibling.Prev = n.Prev
- if sibling.Prev != nil {
- sibling.Prev.Next = sibling
- }
- sibling.Next = n
- n.Prev = sibling
- sibling.Parent = n.Parent
- if sibling.Prev == nil {
- sibling.Parent.FirstChild = sibling
- }
-}
-
-func (n *Node) isContainer() bool {
- switch n.Type {
- case Document:
- fallthrough
- case BlockQuote:
- fallthrough
- case List:
- fallthrough
- case Item:
- fallthrough
- case Paragraph:
- fallthrough
- case Heading:
- fallthrough
- case Emph:
- fallthrough
- case Strong:
- fallthrough
- case Del:
- fallthrough
- case Link:
- fallthrough
- case Image:
- fallthrough
- case Table:
- fallthrough
- case TableHead:
- fallthrough
- case TableBody:
- fallthrough
- case TableRow:
- fallthrough
- case TableCell:
- return true
- default:
- return false
- }
-}
-
-func (n *Node) canContain(t NodeType) bool {
- if n.Type == List {
- return t == Item
- }
- if n.Type == Document || n.Type == BlockQuote || n.Type == Item {
- return t != Item
- }
- if n.Type == Table {
- return t == TableHead || t == TableBody
- }
- if n.Type == TableHead || n.Type == TableBody {
- return t == TableRow
- }
- if n.Type == TableRow {
- return t == TableCell
- }
- return false
-}
-
-// WalkStatus allows NodeVisitor to have some control over the tree traversal.
-// It is returned from NodeVisitor and different values allow Node.Walk to
-// decide which node to go to next.
-type WalkStatus int
-
-const (
- // GoToNext is the default traversal of every node.
- GoToNext WalkStatus = iota
- // SkipChildren tells walker to skip all children of current node.
- SkipChildren
- // Terminate tells walker to terminate the traversal.
- Terminate
-)
-
-// NodeVisitor is a callback to be called when traversing the syntax tree.
-// Called twice for every node: once with entering=true when the branch is
-// first visited, then with entering=false after all the children are done.
-type NodeVisitor func(node *Node, entering bool) WalkStatus
-
-// Walk is a convenience method that instantiates a walker and starts a
-// traversal of subtree rooted at n.
-func (n *Node) Walk(visitor NodeVisitor) {
- w := newNodeWalker(n)
- for w.current != nil {
- status := visitor(w.current, w.entering)
- switch status {
- case GoToNext:
- w.next()
- case SkipChildren:
- w.entering = false
- w.next()
- case Terminate:
- return
- }
- }
-}
-
-type nodeWalker struct {
- current *Node
- root *Node
- entering bool
-}
-
-func newNodeWalker(root *Node) *nodeWalker {
- return &nodeWalker{
- current: root,
- root: root,
- entering: true,
- }
-}
-
-func (nw *nodeWalker) next() {
- if (!nw.current.isContainer() || !nw.entering) && nw.current == nw.root {
- nw.current = nil
- return
- }
- if nw.entering && nw.current.isContainer() {
- if nw.current.FirstChild != nil {
- nw.current = nw.current.FirstChild
- nw.entering = true
- } else {
- nw.entering = false
- }
- } else if nw.current.Next == nil {
- nw.current = nw.current.Parent
- nw.entering = false
- } else {
- nw.current = nw.current.Next
- nw.entering = true
- }
-}
-
-func dump(ast *Node) {
- fmt.Println(dumpString(ast))
-}
-
-func dumpR(ast *Node, depth int) string {
- if ast == nil {
- return ""
- }
- indent := bytes.Repeat([]byte("\t"), depth)
- content := ast.Literal
- if content == nil {
- content = ast.content
- }
- result := fmt.Sprintf("%s%s(%q)\n", indent, ast.Type, content)
- for n := ast.FirstChild; n != nil; n = n.Next {
- result += dumpR(n, depth+1)
- }
- return result
-}
-
-func dumpString(ast *Node) string {
- return dumpR(ast, 0)
-}
diff --git a/vendor/go.step.sm/cli-utils/pkg/blackfriday/smartypants.go b/vendor/go.step.sm/cli-utils/pkg/blackfriday/smartypants.go
deleted file mode 100644
index e5f9e19..0000000
--- a/vendor/go.step.sm/cli-utils/pkg/blackfriday/smartypants.go
+++ /dev/null
@@ -1,458 +0,0 @@
-//
-// Blackfriday Markdown Processor
-// Available at http://github.com/russross/blackfriday
-//
-// Copyright © 2011 Russ Ross <russ@russross.com>.
-// Distributed under the Simplified BSD License.
-// See README.md for details.
-//
-
-//
-//
-// SmartyPants rendering
-//
-//
-
-//nolint:gocritic,revive // ignore blackfriday
-package blackfriday
-
-import (
- "bytes"
- "io"
-)
-
-// SPRenderer is a struct containing state of a Smartypants renderer.
-type SPRenderer struct {
- inSingleQuote bool
- inDoubleQuote bool
- callbacks [256]smartCallback
-}
-
-func wordBoundary(c byte) bool {
- return c == 0 || isspace(c) || ispunct(c)
-}
-
-func tolower(c byte) byte {
- if c >= 'A' && c <= 'Z' {
- return c - 'A' + 'a'
- }
- return c
-}
-
-func isdigit(c byte) bool {
- return c >= '0' && c <= '9'
-}
-
-func smartQuoteHelper(out *bytes.Buffer, previousChar byte, nextChar byte, quote byte, isOpen *bool, addNBSP bool) bool {
- // edge of the buffer is likely to be a tag that we don't get to see,
- // so we treat it like text sometimes
-
- // enumerate all sixteen possibilities for (previousChar, nextChar)
- // each can be one of {0, space, punct, other}
- switch {
- case previousChar == 0 && nextChar == 0:
- // context is not any help here, so toggle
- *isOpen = !*isOpen
- case isspace(previousChar) && nextChar == 0:
- // [ "] might be [ "<code>foo...]
- *isOpen = true
- case ispunct(previousChar) && nextChar == 0:
- // [!"] hmm... could be [Run!"] or [("<code>...]
- *isOpen = false
- case /* isnormal(previousChar) && */ nextChar == 0:
- // [a"] is probably a close
- *isOpen = false
- case previousChar == 0 && isspace(nextChar):
- // [" ] might be [...foo</code>" ]
- *isOpen = false
- case isspace(previousChar) && isspace(nextChar):
- // [ " ] context is not any help here, so toggle
- *isOpen = !*isOpen
- case ispunct(previousChar) && isspace(nextChar):
- // [!" ] is probably a close
- *isOpen = false
- case /* isnormal(previousChar) && */ isspace(nextChar):
- // [a" ] this is one of the easy cases
- *isOpen = false
- case previousChar == 0 && ispunct(nextChar):
- // ["!] hmm... could be ["$1.95] or [</code>"!...]
- *isOpen = false
- case isspace(previousChar) && ispunct(nextChar):
- // [ "!] looks more like [ "$1.95]
- *isOpen = true
- case ispunct(previousChar) && ispunct(nextChar):
- // [!"!] context is not any help here, so toggle
- *isOpen = !*isOpen
- case /* isnormal(previousChar) && */ ispunct(nextChar):
- // [a"!] is probably a close
- *isOpen = false
- case previousChar == 0 /* && isnormal(nextChar) */ :
- // ["a] is probably an open
- *isOpen = true
- case isspace(previousChar) /* && isnormal(nextChar) */ :
- // [ "a] this is one of the easy cases
- *isOpen = true
- case ispunct(previousChar) /* && isnormal(nextChar) */ :
- // [!"a] is probably an open
- *isOpen = true
- default:
- // [a'b] maybe a contraction?
- *isOpen = false
- }
-
- // Note that with the limited lookahead, this non-breaking
- // space will also be appended to single double quotes.
- if addNBSP && !*isOpen {
- out.WriteString("&nbsp;")
- }
-
- out.WriteByte('&')
- if *isOpen {
- out.WriteByte('l')
- } else {
- out.WriteByte('r')
- }
- out.WriteByte(quote)
- out.WriteString("quo;")
-
- if addNBSP && *isOpen {
- out.WriteString("&nbsp;")
- }
-
- return true
-}
-
-func (r *SPRenderer) smartSingleQuote(out *bytes.Buffer, previousChar byte, text []byte) int {
- if len(text) >= 2 {
- t1 := tolower(text[1])
-
- if t1 == '\'' {
- nextChar := byte(0)
- if len(text) >= 3 {
- nextChar = text[2]
- }
- if smartQuoteHelper(out, previousChar, nextChar, 'd', &r.inDoubleQuote, false) {
- return 1
- }
- }
-
- if (t1 == 's' || t1 == 't' || t1 == 'm' || t1 == 'd') && (len(text) < 3 || wordBoundary(text[2])) {
- out.WriteString("&rsquo;")
- return 0
- }
-
- if len(text) >= 3 {
- t2 := tolower(text[2])
-
- if ((t1 == 'r' && t2 == 'e') || (t1 == 'l' && t2 == 'l') || (t1 == 'v' && t2 == 'e')) &&
- (len(text) < 4 || wordBoundary(text[3])) {
- out.WriteString("&rsquo;")
- return 0
- }
- }
- }
-
- nextChar := byte(0)
- if len(text) > 1 {
- nextChar = text[1]
- }
- if smartQuoteHelper(out, previousChar, nextChar, 's', &r.inSingleQuote, false) {
- return 0
- }
-
- out.WriteByte(text[0])
- return 0
-}
-
-func (r *SPRenderer) smartParens(out *bytes.Buffer, previousChar byte, text []byte) int {
- if len(text) >= 3 {
- t1 := tolower(text[1])
- t2 := tolower(text[2])
-
- if t1 == 'c' && t2 == ')' {
- out.WriteString("&copy;")
- return 2
- }
-
- if t1 == 'r' && t2 == ')' {
- out.WriteString("&reg;")
- return 2
- }
-
- if len(text) >= 4 && t1 == 't' && t2 == 'm' && text[3] == ')' {
- out.WriteString("&trade;")
- return 3
- }
- }
-
- out.WriteByte(text[0])
- return 0
-}
-
-func (r *SPRenderer) smartDash(out *bytes.Buffer, previousChar byte, text []byte) int {
- if len(text) >= 2 {
- if text[1] == '-' {
- out.WriteString("&mdash;")
- return 1
- }
-
- if wordBoundary(previousChar) && wordBoundary(text[1]) {
- out.WriteString("&ndash;")
- return 0
- }
- }
-
- out.WriteByte(text[0])
- return 0
-}
-
-func (r *SPRenderer) smartDashLatex(out *bytes.Buffer, previousChar byte, text []byte) int {
- if len(text) >= 3 && text[1] == '-' && text[2] == '-' {
- out.WriteString("&mdash;")
- return 2
- }
- if len(text) >= 2 && text[1] == '-' {
- out.WriteString("&ndash;")
- return 1
- }
-
- out.WriteByte(text[0])
- return 0
-}
-
-func (r *SPRenderer) smartAmpVariant(out *bytes.Buffer, previousChar byte, text []byte, quote byte, addNBSP bool) int {
- if bytes.HasPrefix(text, []byte("&quot;")) {
- nextChar := byte(0)
- if len(text) >= 7 {
- nextChar = text[6]
- }
- if smartQuoteHelper(out, previousChar, nextChar, quote, &r.inDoubleQuote, addNBSP) {
- return 5
- }
- }
-
- if bytes.HasPrefix(text, []byte("&#0;")) {
- return 3
- }
-
- out.WriteByte('&')
- return 0
-}
-
-func (r *SPRenderer) smartAmp(angledQuotes, addNBSP bool) func(*bytes.Buffer, byte, []byte) int {
- var quote byte = 'd'
- if angledQuotes {
- quote = 'a'
- }
-
- return func(out *bytes.Buffer, previousChar byte, text []byte) int {
- return r.smartAmpVariant(out, previousChar, text, quote, addNBSP)
- }
-}
-
-func (r *SPRenderer) smartPeriod(out *bytes.Buffer, previousChar byte, text []byte) int {
- if len(text) >= 3 && text[1] == '.' && text[2] == '.' {
- out.WriteString("&hellip;")
- return 2
- }
-
- if len(text) >= 5 && text[1] == ' ' && text[2] == '.' && text[3] == ' ' && text[4] == '.' {
- out.WriteString("&hellip;")
- return 4
- }
-
- out.WriteByte(text[0])
- return 0
-}
-
-func (r *SPRenderer) smartBacktick(out *bytes.Buffer, previousChar byte, text []byte) int {
- if len(text) >= 2 && text[1] == '`' {
- nextChar := byte(0)
- if len(text) >= 3 {
- nextChar = text[2]
- }
- if smartQuoteHelper(out, previousChar, nextChar, 'd', &r.inDoubleQuote, false) {
- return 1
- }
- }
-
- out.WriteByte(text[0])
- return 0
-}
-
-func (r *SPRenderer) smartNumberGeneric(out *bytes.Buffer, previousChar byte, text []byte) int {
- if wordBoundary(previousChar) && previousChar != '/' && len(text) >= 3 {
- // is it of the form digits/digits(word boundary)?, i.e., \d+/\d+\b
- // note: check for regular slash (/) or fraction slash (⁄, 0x2044, or 0xe2 81 84 in utf-8)
- // and avoid changing dates like 1/23/2005 into fractions.
- numEnd := 0
- for len(text) > numEnd && isdigit(text[numEnd]) {
- numEnd++
- }
- if numEnd == 0 {
- out.WriteByte(text[0])
- return 0
- }
- denStart := numEnd + 1
- if len(text) > numEnd+3 && text[numEnd] == 0xe2 && text[numEnd+1] == 0x81 && text[numEnd+2] == 0x84 {
- denStart = numEnd + 3
- } else if len(text) < numEnd+2 || text[numEnd] != '/' {
- out.WriteByte(text[0])
- return 0
- }
- denEnd := denStart
- for len(text) > denEnd && isdigit(text[denEnd]) {
- denEnd++
- }
- if denEnd == denStart {
- out.WriteByte(text[0])
- return 0
- }
- if len(text) == denEnd || wordBoundary(text[denEnd]) && text[denEnd] != '/' {
- out.WriteString("<sup>")
- out.Write(text[:numEnd])
- out.WriteString("</sup>&frasl;<sub>")
- out.Write(text[denStart:denEnd])
- out.WriteString("</sub>")
- return denEnd - 1
- }
- }
-
- out.WriteByte(text[0])
- return 0
-}
-
-func (r *SPRenderer) smartNumber(out *bytes.Buffer, previousChar byte, text []byte) int {
- if wordBoundary(previousChar) && previousChar != '/' && len(text) >= 3 {
- if text[0] == '1' && text[1] == '/' && text[2] == '2' {
- if len(text) < 4 || wordBoundary(text[3]) && text[3] != '/' {
- out.WriteString("&frac12;")
- return 2
- }
- }
-
- if text[0] == '1' && text[1] == '/' && text[2] == '4' {
- if len(text) < 4 || wordBoundary(text[3]) && text[3] != '/' || (len(text) >= 5 && tolower(text[3]) == 't' && tolower(text[4]) == 'h') {
- out.WriteString("&frac14;")
- return 2
- }
- }
-
- if text[0] == '3' && text[1] == '/' && text[2] == '4' {
- if len(text) < 4 || wordBoundary(text[3]) && text[3] != '/' || (len(text) >= 6 && tolower(text[3]) == 't' && tolower(text[4]) == 'h' && tolower(text[5]) == 's') {
- out.WriteString("&frac34;")
- return 2
- }
- }
- }
-
- out.WriteByte(text[0])
- return 0
-}
-
-func (r *SPRenderer) smartDoubleQuoteVariant(out *bytes.Buffer, previousChar byte, text []byte, quote byte) int {
- nextChar := byte(0)
- if len(text) > 1 {
- nextChar = text[1]
- }
- if !smartQuoteHelper(out, previousChar, nextChar, quote, &r.inDoubleQuote, false) {
- out.WriteString("&quot;")
- }
-
- return 0
-}
-
-func (r *SPRenderer) smartDoubleQuote(out *bytes.Buffer, previousChar byte, text []byte) int {
- return r.smartDoubleQuoteVariant(out, previousChar, text, 'd')
-}
-
-func (r *SPRenderer) smartAngledDoubleQuote(out *bytes.Buffer, previousChar byte, text []byte) int {
- return r.smartDoubleQuoteVariant(out, previousChar, text, 'a')
-}
-
-func (r *SPRenderer) smartLeftAngle(out *bytes.Buffer, previousChar byte, text []byte) int {
- i := 0
-
- for i < len(text) && text[i] != '>' {
- i++
- }
-
- out.Write(text[:i+1])
- return i
-}
-
-type smartCallback func(out *bytes.Buffer, previousChar byte, text []byte) int
-
-// NewSmartypantsRenderer constructs a Smartypants renderer object.
-func NewSmartypantsRenderer(flags HTMLFlags) *SPRenderer {
- var (
- r SPRenderer
-
- smartAmpAngled = r.smartAmp(true, false)
- smartAmpAngledNBSP = r.smartAmp(true, true)
- smartAmpRegular = r.smartAmp(false, false)
- smartAmpRegularNBSP = r.smartAmp(false, true)
-
- addNBSP = flags&SmartypantsQuotesNBSP != 0
- )
-
- if flags&SmartypantsAngledQuotes == 0 {
- r.callbacks['"'] = r.smartDoubleQuote
- if !addNBSP {
- r.callbacks['&'] = smartAmpRegular
- } else {
- r.callbacks['&'] = smartAmpRegularNBSP
- }
- } else {
- r.callbacks['"'] = r.smartAngledDoubleQuote
- if !addNBSP {
- r.callbacks['&'] = smartAmpAngled
- } else {
- r.callbacks['&'] = smartAmpAngledNBSP
- }
- }
- r.callbacks['\''] = r.smartSingleQuote
- r.callbacks['('] = r.smartParens
- if flags&SmartypantsDashes != 0 {
- if flags&SmartypantsLatexDashes == 0 {
- r.callbacks['-'] = r.smartDash
- } else {
- r.callbacks['-'] = r.smartDashLatex
- }
- }
- r.callbacks['.'] = r.smartPeriod
- if flags&SmartypantsFractions == 0 {
- r.callbacks['1'] = r.smartNumber
- r.callbacks['3'] = r.smartNumber
- } else {
- for ch := '1'; ch <= '9'; ch++ {
- r.callbacks[ch] = r.smartNumberGeneric
- }
- }
- r.callbacks['<'] = r.smartLeftAngle
- r.callbacks['`'] = r.smartBacktick
- return &r
-}
-
-// Process is the entry point of the Smartypants renderer.
-func (r *SPRenderer) Process(w io.Writer, text []byte) {
- mark := 0
- for i := 0; i < len(text); i++ {
- if action := r.callbacks[text[i]]; action != nil {
- if i > mark {
- w.Write(text[mark:i])
- }
- previousChar := byte(0)
- if i > 0 {
- previousChar = text[i-1]
- }
- var tmp bytes.Buffer
- i += action(&tmp, previousChar, text[i:])
- w.Write(tmp.Bytes())
- mark = i + 1
- }
- }
- if mark < len(text) {
- w.Write(text[mark:])
- }
-}
diff --git a/vendor/go.step.sm/cli-utils/step/config.go b/vendor/go.step.sm/cli-utils/step/config.go
deleted file mode 100644
index 269f21a..0000000
--- a/vendor/go.step.sm/cli-utils/step/config.go
+++ /dev/null
@@ -1,220 +0,0 @@
-package step
-
-import (
- "fmt"
- "os"
- "os/user"
- "path/filepath"
- "runtime"
- "strings"
- "sync"
- "time"
-)
-
-// PathEnv defines the name of the environment variable that can overwrite
-// the default configuration path.
-const PathEnv = "STEPPATH"
-
-// HomeEnv defines the name of the environment variable that can overwrite the
-// default home directory.
-const HomeEnv = "HOME"
-
-var (
- // version and buildTime are filled in during build by the Makefile
- name = "Smallstep CLI"
- buildTime = "N/A"
- version = "N/A"
-)
-
-var cache struct {
- sync.Once
- err error
- stepBasePath string // stepBasePath will be populated in init() with the proper STEPPATH.
- homePath string // homePath will be populated in init() with the proper HOME.
-}
-
-// Init initializes the step environment.
-//
-// A program calling this function should fail because the step variables would
-// be undefined.
-func Init() error {
- if err := initStepPath(); err != nil {
- return err
- }
- return Contexts().Init()
-}
-
-func initStepPath() error {
- cache.Do(func() {
- // Get home path from environment or from the user object.
- homePath := os.Getenv(HomeEnv)
- if homePath == "" {
- usr, err := user.Current()
- if err == nil && usr.HomeDir != "" {
- homePath = usr.HomeDir
- } else {
- cache.err = fmt.Errorf("error obtaining home directory, please define environment variable %s", HomeEnv)
- return
- }
- }
-
- // Get step path from environment or relative to home.
- stepBasePath := os.Getenv(PathEnv)
- if stepBasePath == "" {
- stepBasePath = filepath.Join(homePath, ".step")
- }
-
- // cleanup and add paths to cache
- cache.homePath = filepath.Clean(homePath)
- cache.stepBasePath = filepath.Clean(stepBasePath)
- })
-
- return cache.err
-}
-
-// Home returns the user home directory using the environment variable HOME or
-// the os/user package.
-func Home() string {
- _ = initStepPath()
- return cache.homePath
-}
-
-// BasePath returns the base path for the step configuration directory.
-func BasePath() string {
- _ = initStepPath()
- return cache.stepBasePath
-}
-
-// Path returns the path for the step configuration directory.
-//
-// 1. If the base step path has a current context configured, then this method
-// returns the path to the authority configured in the context.
-// 2. If the base step path does not have a current context configured this
-// method returns the value defined by the environment variable STEPPATH, OR
-// 3. If no environment variable is set, this method returns `$HOME/.step`.
-func Path() string {
- c := Contexts().GetCurrent()
- if c == nil {
- return BasePath()
- }
- return filepath.Join(BasePath(), "authorities", c.Authority)
-}
-
-// ProfilePath returns the path for the currently selected profile path.
-//
-// 1. If the base step path has a current context configured, then this method
-// returns the path to the profile configured in the context.
-// 2. If the base step path does not have a current context configured this
-// method returns the value defined by the environment variable STEPPATH, OR
-// 3. If no environment variable is set, this method returns `$HOME/.step`.
-func ProfilePath() string {
- c := Contexts().GetCurrent()
- if c == nil {
- return BasePath()
- }
- return filepath.Join(BasePath(), "profiles", c.Profile)
-}
-
-// IdentityPath returns the location of the identity directory.
-func IdentityPath() string {
- return filepath.Join(Path(), "identity")
-}
-
-// IdentityFile returns the location of the identity file.
-func IdentityFile() string {
- return filepath.Join(Path(), "config", "identity.json")
-}
-
-// DefaultsFile returns the location of the defaults file at the base of the
-// authority path.
-func DefaultsFile() string {
- return filepath.Join(Path(), "config", "defaults.json")
-}
-
-// ProfileDefaultsFile returns the location of the defaults file at the base
-// of the profile path.
-func ProfileDefaultsFile() string {
- return filepath.Join(ProfilePath(), "config", "defaults.json")
-}
-
-// ConfigPath returns the location of the $(step path)/config directory.
-func ConfigPath() string {
- return filepath.Join(Path(), "config")
-}
-
-// ProfileConfigPath returns the location of the $(step path --profile)/config directory.
-func ProfileConfigPath() string {
- return filepath.Join(ProfilePath(), "config")
-}
-
-// CaConfigFile returns the location of the ca.json file -- configuration for
-// connecting to the CA.
-func CaConfigFile() string {
- return filepath.Join(Path(), "config", "ca.json")
-}
-
-// ContextsFile returns the location of the config file.
-func ContextsFile() string {
- return filepath.Join(BasePath(), "contexts.json")
-}
-
-// CurrentContextFile returns the path to the file containing the current context.
-func CurrentContextFile() string {
- return filepath.Join(BasePath(), "current-context.json")
-}
-
-// Abs returns the given path relative to the STEPPATH if it's not an
-// absolute path, relative to the home directory using the special string "~/",
-// or relative to the working directory using "./"
-//
-// Relative paths like 'certs/root_ca.crt' will be converted to
-// '$STEPPATH/certs/root_ca.crt', but paths like './certs/root_ca.crt' will be
-// relative to the current directory. Home relative paths like
-// ~/certs/root_ca.crt will be converted to '$HOME/certs/root_ca.crt'. And
-// absolute paths like '/certs/root_ca.crt' will remain the same.
-func Abs(path string) string {
- if filepath.IsAbs(path) {
- return path
- }
- // Windows accept both \ and /
- slashed := filepath.ToSlash(path)
- switch {
- case strings.HasPrefix(slashed, "~/"):
- return filepath.Join(Home(), path[2:])
- case strings.HasPrefix(slashed, "./"), strings.HasPrefix(slashed, "../"):
- if abs, err := filepath.Abs(path); err == nil {
- return abs
- }
- return path
- default:
- return filepath.Join(Path(), path)
- }
-}
-
-// Set updates the name, version, and build time
-func Set(n, v, t string) {
- name = n
- version = v
- buildTime = t
-}
-
-// Version returns the current version of the binary
-func Version() string {
- out := version
- if version == "N/A" {
- out = "0000000-dev"
- }
-
- return fmt.Sprintf("%s/%s (%s/%s)",
- name, out, runtime.GOOS, runtime.GOARCH)
-}
-
-// ReleaseDate returns the time of when the binary was built
-func ReleaseDate() string {
- out := buildTime
- if buildTime == "N/A" {
- out = time.Now().UTC().Format("2006-01-02 15:04 MST")
- }
-
- return out
-}
diff --git a/vendor/go.step.sm/cli-utils/step/context.go b/vendor/go.step.sm/cli-utils/step/context.go
deleted file mode 100644
index 0372fc9..0000000
--- a/vendor/go.step.sm/cli-utils/step/context.go
+++ /dev/null
@@ -1,564 +0,0 @@
-package step
-
-import (
- "encoding/json"
- "fmt"
- "os"
- "path/filepath"
- "reflect"
- "sort"
- "strings"
-
- "github.com/pkg/errors"
- "github.com/urfave/cli"
- "go.step.sm/cli-utils/errs"
- "go.step.sm/cli-utils/ui"
-)
-
-// IgnoreEnvVar is a value added to a flag EnvVar to avoid the use of
-// environment variables or configuration files.
-const IgnoreEnvVar = "STEP_IGNORE_ENV_VAR"
-
-// Context represents a Step Path configuration context. A context is the
-// combination of a profile and an authority.
-type Context struct {
- Name string `json:"-"`
- Profile string `json:"profile"`
- Authority string `json:"authority"`
- config map[string]interface{}
-}
-
-// Validate validates a context and returns an error if invalid.
-func (c *Context) Validate() error {
- suffix := "; check your $STEPPATH/contexts.json file"
- if c == nil {
- return errors.Errorf("context cannot be nil%s", suffix)
- }
- if c.Authority == "" {
- return errors.Errorf("context cannot have an empty authority value%s", suffix)
- }
- if c.Profile == "" {
- return errors.Errorf("context cannot have an empty profile value%s", suffix)
- }
- return nil
-}
-
-// Path return the base path relative to the context.
-func (c *Context) Path() string {
- return filepath.Join(BasePath(), "authorities", c.Authority)
-}
-
-// ProfilePath return the profile base path relative to the context.
-func (c *Context) ProfilePath() string {
- return filepath.Join(BasePath(), "profiles", c.Profile)
-}
-
-// DefaultsFile returns the location of the defaults file for the context.
-func (c *Context) DefaultsFile() string {
- return filepath.Join(c.Path(), "config", "defaults.json")
-}
-
-// ProfileDefaultsFile returns the location of the defaults file at the base
-// of the profile path.
-func (c *Context) ProfileDefaultsFile() string {
- return filepath.Join(c.ProfilePath(), "config", "defaults.json")
-}
-
-// Load loads the configuration for the given context.
-func (c *Context) Load() error {
- c.config = map[string]interface{}{}
- for _, f := range []string{c.DefaultsFile(), c.ProfileDefaultsFile()} {
- b, err := os.ReadFile(f)
- if os.IsNotExist(err) {
- continue
- } else if err != nil {
- return errs.FileError(err, f)
- }
-
- values := make(map[string]interface{})
- if err := json.Unmarshal(b, &values); err != nil {
- return errors.Wrapf(err, "error parsing %s", f)
- }
-
- for k, v := range values {
- c.config[k] = v
- }
- }
-
- attributesBannedFromConfig := []string{
- "context",
- "profile",
- "authority",
- }
- for _, attr := range attributesBannedFromConfig {
- if _, ok := c.config[attr]; ok {
- ui.Printf("cannot set '%s' attribute in config files\n", attr)
- delete(c.config, attr)
- }
- }
-
- return nil
-}
-
-// ContextMap represents the map of available Contexts that is stored
-// at the base of the Step Path.
-type ContextMap map[string]*Context
-
-type storedCurrent struct {
- Context string `json:"context"`
-}
-
-// CtxState is the type that manages context state for the cli.
-type CtxState struct {
- current *Context
- contexts ContextMap
- config map[string]interface{}
-}
-
-var ctxState = &CtxState{}
-
-// Init initializes the context map and current context state.
-func (cs *CtxState) Init() error {
- if err := cs.initMap(); err != nil {
- return err
- }
- if err := cs.initCurrent(); err != nil {
- return err
- }
- return cs.load()
-}
-
-func (cs *CtxState) initMap() error {
- contextsFile := ContextsFile()
- b, err := os.ReadFile(contextsFile)
- if os.IsNotExist(err) {
- return nil
- } else if err != nil {
- return errs.FileError(err, contextsFile)
- }
- cs.contexts = ContextMap{}
- if err := json.Unmarshal(b, &cs.contexts); err != nil {
- return errors.Wrap(err, "error unmarshaling context map")
- }
- for k, ctx := range cs.contexts {
- if err := ctx.Validate(); err != nil {
- return errors.Wrapf(err, "error in context '%s'", k)
- }
- ctx.Name = k
- }
- return nil
-}
-
-func (cs *CtxState) initCurrent() error {
- currentCtxFile := CurrentContextFile()
- b, err := os.ReadFile(currentCtxFile)
- if os.IsNotExist(err) {
- return nil
- } else if err != nil {
- return errs.FileError(err, currentCtxFile)
- }
-
- var sc storedCurrent
- if err := json.Unmarshal(b, &sc); err != nil {
- return errors.Wrap(err, "error unmarshaling current context")
- }
-
- return cs.SetCurrent(sc.Context)
-}
-
-func (cs *CtxState) load() error {
- if cs.Enabled() && cs.GetCurrent() != nil {
- if err := cs.GetCurrent().Load(); err != nil {
- return fmt.Errorf("failed loading current context configuration: %w", err)
- }
-
- return nil
- }
-
- if err := cs.LoadVintage(""); err != nil {
- return fmt.Errorf("failed loading context configuration: %w", err)
- }
-
- return nil
-}
-
-// LoadVintage loads context configuration from the vintage (non-context) path.
-func (cs *CtxState) LoadVintage(f string) error {
- if f == "" {
- f = DefaultsFile()
- }
-
- b, err := os.ReadFile(f)
- if os.IsNotExist(err) {
- return nil
- } else if err != nil {
- return errs.FileError(err, f)
- }
-
- cs.config = make(map[string]interface{})
- if err := json.Unmarshal(b, &cs.config); err != nil {
- return errors.Wrapf(err, "error parsing %s", f)
- }
- return nil
-}
-
-// GetConfig returns the current context configuration.
-func (cs *CtxState) GetConfig() (map[string]interface{}, error) {
- if cs.Enabled() {
- cur := cs.GetCurrent()
- if cur == nil {
- return nil, errors.New("cannot get context configuration; no current context set")
- }
- return cur.config, nil
- }
- return cs.config, nil
-}
-
-// SetCurrent sets the current context or returns an error if a context
-// with the given name does not exist.
-func (cs *CtxState) SetCurrent(name string) error {
- var ok bool
- cs.current, ok = cs.contexts[name]
- if !ok {
- return errors.Errorf("could not load context '%s'", name)
- }
- if len(cs.current.config) == 0 {
- if err := cs.current.Load(); err != nil {
- return err
- }
- }
- return nil
-}
-
-type contextSelect struct {
- Name string
- Context *Context
-}
-
-// PromptContext gets user input to select a context.
-func (cs *CtxState) PromptContext() error {
- var items []*contextSelect
- for _, context := range cs.List() {
- items = append(items, &contextSelect{
- Name: context.Name,
- Context: context,
- })
- }
-
- var ctxStr string
- if len(items) == 1 {
- if err := ui.PrintSelected("Context", items[0].Name); err != nil {
- return err
- }
- ctxStr = items[0].Name
- } else {
- i, _, err := ui.Select("Select a context for 'step':", items,
- ui.WithSelectTemplates(ui.NamedSelectTemplates("Context")))
- if err != nil {
- return err
- }
- ctxStr = items[i].Name
- }
- if err := cs.SetCurrent(ctxStr); err != nil {
- return err
- }
- return cs.SaveCurrent(ctxStr)
-}
-
-// Enabled returns true if one of the following is true:
-// - there is a current context configured
-// - the context map is (list of available contexts) is not empty.
-func (cs *CtxState) Enabled() bool {
- return cs.current != nil || len(cs.contexts) > 0
-}
-
-// Contexts returns an object that enables context management.
-func Contexts() *CtxState {
- return ctxState
-}
-
-// Add adds a new context to the context map. If current context is not
-// set then store the new context as the current context for future commands.
-func (cs *CtxState) Add(ctx *Context) error {
- if err := ctx.Validate(); err != nil {
- return errors.Wrapf(err, "error adding context")
- }
- if cs.contexts == nil {
- cs.contexts = map[string]*Context{ctx.Name: ctx}
- } else {
- cs.contexts[ctx.Name] = ctx
- }
-
- b, err := json.MarshalIndent(cs.contexts, "", " ")
- if err != nil {
- return err
- }
-
- cf := ContextsFile()
- if err := os.MkdirAll(filepath.Dir(cf), 0700); err != nil {
- return errs.FileError(err, cf)
- }
- if err := os.WriteFile(cf, b, 0600); err != nil {
- return errs.FileError(err, cf)
- }
-
- if cs.current == nil {
- if err := cs.SaveCurrent(ctx.Name); err != nil {
- return err
- }
- }
- return nil
-}
-
-// GetCurrent returns the current context.
-func (cs *CtxState) GetCurrent() *Context {
- return cs.current
-}
-
-// Get returns the context with the given name.
-func (cs *CtxState) Get(name string) (ctx *Context, ok bool) {
- ctx, ok = cs.contexts[name]
- return
-}
-
-// Remove removes a context from the context state.
-func (cs *CtxState) Remove(name string) error {
- if _, ok := cs.contexts[name]; !ok {
- return errors.Errorf("context '%s' not found", name)
- }
- if cs.current != nil && cs.current.Name == name {
- return errors.New("cannot remove current context; use 'step context select' to switch contexts")
- }
-
- delete(cs.contexts, name)
-
- b, err := json.MarshalIndent(cs.contexts, "", " ")
- if err != nil {
- return err
- }
-
- if err := os.WriteFile(ContextsFile(), b, 0600); err != nil {
- return fmt.Errorf("error writing file: %w", err)
- }
- return nil
-}
-
-// List returns a list of all contexts.
-func (cs *CtxState) List() []*Context {
- l := make([]*Context, 0, len(cs.contexts))
-
- for _, v := range cs.contexts {
- l = append(l, v)
- }
- return l
-}
-
-// ListAlphabetical returns a case-insensitive, alphabetically
-// sorted list of all contexts.
-func (cs *CtxState) ListAlphabetical() []*Context {
- l := cs.List()
-
- sort.Slice(l, func(i, j int) bool {
- return strings.ToLower(l[i].Name) < strings.ToLower(l[j].Name)
- })
-
- return l
-}
-
-// SaveCurrent stores the given context name as the selected default context for
-// future commands.
-func (cs *CtxState) SaveCurrent(name string) error {
- if _, ok := Contexts().Get(name); !ok {
- return errors.Errorf("context '%s' not found", name)
- }
-
- b, err := json.Marshal(storedCurrent{Context: name})
- if err != nil {
- return err
- }
- //nolint:gosec // this file does not contain sensitive info
- if err = os.WriteFile(CurrentContextFile(), b, 0644); err != nil {
- return errs.FileError(err, CurrentContextFile())
- }
- return nil
-}
-
-// Apply the current context configuration to the command line environment.
-func (cs *CtxState) Apply(ctx *cli.Context) error {
- cfg, err := cs.GetConfig()
- if err != nil {
- return err
- }
- for _, f := range ctx.Command.Flags {
- // Skip if EnvVar == IgnoreEnvVar
- if getFlagEnvVar(f) == IgnoreEnvVar {
- continue
- }
-
- for _, name := range strings.Split(f.GetName(), ",") {
- name = strings.TrimSpace(name)
- if ctx.IsSet(name) {
- break
- }
- // Set the flag for the first key that matches.
- if v, ok := cfg[name]; ok {
- ctx.Set(name, fmt.Sprintf("%v", v))
- break
- }
- }
- }
- return nil
-}
-
-// getEnvVar generates the environment variable for the given flag name.
-func getEnvVar(name string) string {
- parts := strings.Split(name, ",")
- name = strings.TrimSpace(parts[0])
- name = strings.ReplaceAll(name, "-", "_")
- return "STEP_" + strings.ToUpper(name)
-}
-
-// getFlagEnvVar returns the value of the EnvVar field of a flag.
-func getFlagEnvVar(f cli.Flag) string {
- v := reflect.ValueOf(f)
- if v.Kind() == reflect.Ptr {
- v = v.Elem()
- }
- if v.Kind() == reflect.Struct {
- envVar := v.FieldByName("EnvVar")
- if envVar.IsValid() {
- return envVar.String()
- }
- }
- return ""
-}
-
-// SetEnvVar sets the the EnvVar element to each flag recursively.
-func SetEnvVar(c *cli.Command) {
- if c == nil {
- return
- }
-
- // Enable getting the flags from a json file
- if c.Before == nil && c.Action != nil {
- c.Before = getConfigVars
- }
-
- // Enable getting the flags from environment variables
- for i := range c.Flags {
- envVar := getEnvVar(c.Flags[i].GetName())
- switch f := c.Flags[i].(type) {
- case cli.BoolFlag:
- if f.EnvVar == "" {
- f.EnvVar = envVar
- c.Flags[i] = f
- }
- case cli.BoolTFlag:
- if f.EnvVar == "" {
- f.EnvVar = envVar
- c.Flags[i] = f
- }
- case cli.DurationFlag:
- if f.EnvVar == "" {
- f.EnvVar = envVar
- c.Flags[i] = f
- }
- case cli.Float64Flag:
- if f.EnvVar == "" {
- f.EnvVar = envVar
- c.Flags[i] = f
- }
- case cli.GenericFlag:
- if f.EnvVar == "" {
- f.EnvVar = envVar
- c.Flags[i] = f
- }
- case cli.Int64Flag:
- if f.EnvVar == "" {
- f.EnvVar = envVar
- c.Flags[i] = f
- }
- case cli.IntFlag:
- if f.EnvVar == "" {
- f.EnvVar = envVar
- c.Flags[i] = f
- }
- case cli.IntSliceFlag:
- if f.EnvVar == "" {
- f.EnvVar = envVar
- c.Flags[i] = f
- }
- case cli.Int64SliceFlag:
- if f.EnvVar == "" {
- f.EnvVar = envVar
- c.Flags[i] = f
- }
- case cli.StringFlag:
- if f.EnvVar == "" {
- f.EnvVar = envVar
- c.Flags[i] = f
- }
- case cli.StringSliceFlag:
- if f.EnvVar == "" {
- f.EnvVar = envVar
- c.Flags[i] = f
- }
- case cli.Uint64Flag:
- if f.EnvVar == "" {
- f.EnvVar = envVar
- c.Flags[i] = f
- }
- case cli.UintFlag:
- if f.EnvVar == "" {
- f.EnvVar = envVar
- c.Flags[i] = f
- }
- }
- }
-
- for i := range c.Subcommands {
- SetEnvVar(&c.Subcommands[i])
- }
-}
-
-// GetConfigVars load the defaults.json file and sets the flags if they are not
-// already set or the EnvVar is set to IgnoreEnvVar.
-//
-// TODO(mariano): right now it only supports parameters at first level.
-func getConfigVars(ctx *cli.Context) (err error) {
- if ctx.Bool("no-context") {
- return nil
- }
-
- cs := Contexts()
-
- // Load the the current context into memory:
- // - If contexts enabled then make sure a current context is selected
- // and loaded.
- // - If vintage context then check if overwritten by --config flag.
- if cs.Enabled() {
- if ctx.IsSet("context") {
- err = cs.SetCurrent(ctx.String("context"))
- } else if cs.Enabled() && cs.GetCurrent() == nil {
- err = cs.PromptContext()
- }
- if err != nil {
- return err
- }
- } else if ctx.GlobalString("config") != "" {
- // Re-load the vintage context configuration if `--config` flag supplied.
- cs.LoadVintage(ctx.GlobalString("config"))
- }
-
- // TODO: a mock detail because of "add detail/assignee to this TODO/FIXME/BUG comment" lint issue
- fullCommandName := strings.ToLower(strings.TrimSpace(ctx.Command.FullName()))
- if strings.EqualFold(fullCommandName, "ca bootstrap-helper") {
- return nil
- }
-
- if err := cs.Apply(ctx); err != nil {
- return fmt.Errorf("error applying contexts: %w", err)
- }
-
- return nil
-}
diff --git a/vendor/go.step.sm/cli-utils/ui/options.go b/vendor/go.step.sm/cli-utils/ui/options.go
deleted file mode 100644
index 382c263..0000000
--- a/vendor/go.step.sm/cli-utils/ui/options.go
+++ /dev/null
@@ -1,172 +0,0 @@
-package ui
-
-import (
- "fmt"
- "regexp"
- "strings"
-
- "github.com/manifoldco/promptui"
-)
-
-type options struct {
- mask rune
- defaultValue string
- value string
- allowEdit bool
- printTemplate string
- promptTemplates *promptui.PromptTemplates
- selectTemplates *promptui.SelectTemplates
- validateFunc promptui.ValidateFunc
-}
-
-// apply applies the given options.
-func (o *options) apply(opts []Option) *options {
- for _, fn := range opts {
- fn(o)
- }
- return o
-}
-
-// valid returns true if the validate function passes on the value.
-func (o *options) valid() bool {
- if o.validateFunc == nil {
- return true
- }
- return o.validateFunc(o.value) == nil
-}
-
-// getValue validates the value and returns it.
-func (o *options) getValue() (string, error) {
- if o.validateFunc == nil {
- return o.value, nil
- }
- if err := o.validateFunc(o.value); err != nil {
- return "", err
- }
- return o.value, nil
-}
-
-// getValueBytes validates the value and returns it as a byte slice.
-func (o *options) getValueBytes() ([]byte, error) {
- if o.validateFunc == nil {
- return []byte(o.value), nil
- }
- if err := o.validateFunc(o.value); err != nil {
- return nil, err
- }
- return []byte(o.value), nil
-}
-
-// Option is the type of the functions that modify the prompt options.
-type Option func(*options)
-
-func extractOptions(args []interface{}) (opts []Option, rest []interface{}) {
- rest = args[:0]
- for _, arg := range args {
- if o, ok := arg.(Option); ok {
- opts = append(opts, o)
- } else {
- rest = append(rest, arg)
- }
- }
- return
-}
-
-// WithMask adds a mask to a prompt.
-func WithMask(r rune) Option {
- return func(o *options) {
- o.mask = r
- }
-}
-
-// WithDefaultValue adds a custom string as the default value.
-func WithDefaultValue(s string) Option {
- return func(o *options) {
- o.defaultValue = s
- }
-}
-
-// WithSliceValue sets a custom string as the result of a prompt. If value is set,
-// the prompt won't be displayed.
-func WithSliceValue(values []string) Option {
- return func(o *options) {
- o.value = strings.Join(values, ",")
- }
-}
-
-// WithValue sets a custom string as the result of a prompt. If value is set,
-// the prompt won't be displayed.
-func WithValue(value string) Option {
- return func(o *options) {
- o.value = value
- }
-}
-
-// WithAllowEdit if true, let's the user edit the default value set.
-func WithAllowEdit(b bool) Option {
- return func(o *options) {
- o.allowEdit = b
- }
-}
-
-// WithPrintTemplate sets the template to use on the print methods.
-func WithPrintTemplate(template string) Option {
- return func(o *options) {
- o.printTemplate = template
- }
-}
-
-// WithPromptTemplates adds a custom template to a prompt.
-func WithPromptTemplates(t *promptui.PromptTemplates) Option {
- return func(o *options) {
- o.promptTemplates = t
- }
-}
-
-// WithSelectTemplates adds a custom template to a select.
-func WithSelectTemplates(t *promptui.SelectTemplates) Option {
- return func(o *options) {
- o.selectTemplates = t
- }
-}
-
-// WithValidateFunc adds a custom validation function to a prompt.
-func WithValidateFunc(fn func(string) error) Option {
- return func(o *options) {
- o.validateFunc = fn
- }
-}
-
-// WithValidateNotEmpty adds a custom validation function to a prompt that
-// checks that the propted string is not empty.
-func WithValidateNotEmpty() Option {
- return WithValidateFunc(NotEmpty())
-}
-
-// WithValidateYesNo adds a custom validation function to a prompt for a Yes/No
-// prompt.
-func WithValidateYesNo() Option {
- return WithValidateFunc(YesNo())
-}
-
-// WithRichPrompt add the template option with rich templates.
-func WithRichPrompt() Option {
- return WithPromptTemplates(PromptTemplates())
-}
-
-// WithSimplePrompt add the template option with simple templates.
-func WithSimplePrompt() Option {
- return WithPromptTemplates(SimplePromptTemplates())
-}
-
-// WithValidateRegexp checks a prompt answer with a regular expression. If the
-// regular expression is not a valid one, the option will panic.
-func WithValidateRegexp(re string) Option {
- rx := regexp.MustCompile(re)
- return WithValidateFunc(func(s string) error {
- if rx.MatchString(s) {
- return nil
- }
- return fmt.Errorf("%s does not match the regular expresion %s", s, re)
- })
-}
diff --git a/vendor/go.step.sm/cli-utils/ui/templates.go b/vendor/go.step.sm/cli-utils/ui/templates.go
deleted file mode 100644
index cc37891..0000000
--- a/vendor/go.step.sm/cli-utils/ui/templates.go
+++ /dev/null
@@ -1,93 +0,0 @@
-package ui
-
-import (
- "fmt"
- "runtime"
-
- "github.com/chzyer/readline"
- "github.com/manifoldco/promptui"
-)
-
-var (
- // IconInitial is the icon used when starting in prompt mode and the icon next to the label when
- // starting in select mode.
- IconInitial = promptui.Styler(promptui.FGBlue)("?")
-
- // IconGood is the icon used when a good answer is entered in prompt mode.
- IconGood = promptui.Styler(promptui.FGGreen)("✔")
-
- // IconWarn is the icon used when a good, but potentially invalid answer is entered in prompt mode.
- IconWarn = promptui.Styler(promptui.FGYellow)("⚠")
-
- // IconBad is the icon used when a bad answer is entered in prompt mode.
- IconBad = promptui.Styler(promptui.FGRed)("✗")
-
- // IconSelect is the icon used to identify the currently selected item in select mode.
- IconSelect = promptui.Styler(promptui.FGBold)("▸")
-)
-
-func init() {
- // Set VT100 characters for windows too
- if runtime.GOOS == "windows" {
- promptui.KeyEnter = readline.CharEnter
- promptui.KeyBackspace = readline.CharBackspace
- promptui.KeyPrev = readline.CharPrev
- promptui.KeyPrevDisplay = "↑"
- promptui.KeyNext = readline.CharNext
- promptui.KeyNextDisplay = "↓"
- promptui.KeyBackward = readline.CharBackward
- promptui.KeyBackwardDisplay = "←"
- promptui.KeyForward = readline.CharForward
- promptui.KeyForwardDisplay = "→"
- }
-}
-
-// PrintSelectedTemplate returns the default template used in PrintSelected.
-func PrintSelectedTemplate() string {
- return fmt.Sprintf(`{{ %q | green }} {{ .Name | bold }}{{ ":" | bold }} {{ .Value }}`, IconGood) + "\n"
-}
-
-// PromptTemplates is the default style for a prompt.
-func PromptTemplates() *promptui.PromptTemplates {
- bold := promptui.Styler(promptui.FGBold)
- return &promptui.PromptTemplates{
- Prompt: fmt.Sprintf("%s {{ . | bold }}%s ", IconInitial, bold(":")),
- Success: fmt.Sprintf("%s {{ . | bold }}%s ", bold(IconGood), bold(":")),
- // Confirm: fmt.Sprintf(`{{ "%s" | bold }} {{ . | bold }}? {{ "[]" | faint }} `, IconInitial),
- Valid: fmt.Sprintf("%s {{ . | bold }}%s ", bold(IconGood), bold(":")),
- Invalid: fmt.Sprintf("%s {{ . | bold }}%s ", bold(IconBad), bold(":")),
- }
-}
-
-// SimplePromptTemplates is a prompt with a simple style, used by default on password prompts.
-func SimplePromptTemplates() *promptui.PromptTemplates {
- return &promptui.PromptTemplates{
- Prompt: "{{ . }}: ",
- Success: "{{ . }}: ",
- Valid: "{{ . }}: ",
- Invalid: "{{ . }}: ",
- }
-}
-
-// SelectTemplates returns the default promptui.SelectTemplate for string
-// slices. The given name is the prompt of the selected option.
-func SelectTemplates(name string) *promptui.SelectTemplates {
- return &promptui.SelectTemplates{
- Label: fmt.Sprintf("%s {{ . }}: ", IconInitial),
- Active: fmt.Sprintf("%s {{ . | underline }}", IconSelect),
- Inactive: " {{ . }}",
- Selected: fmt.Sprintf(`{{ %q | green }} {{ "%s:" | bold }} {{ .Name }}`, IconGood, name),
- }
-}
-
-// NamedSelectTemplates returns the default promptui.SelectTemplate for struct
-// slices with a name property. The given name is the prompt of the selected
-// option.
-func NamedSelectTemplates(name string) *promptui.SelectTemplates {
- return &promptui.SelectTemplates{
- Label: fmt.Sprintf("%s {{.Name}}: ", IconInitial),
- Active: fmt.Sprintf("%s {{ .Name | underline }}", IconSelect),
- Inactive: " {{.Name}}",
- Selected: fmt.Sprintf(`{{ %q | green }} {{ "%s:" | bold }} {{ .Name }}`, IconGood, name),
- }
-}
diff --git a/vendor/go.step.sm/cli-utils/ui/ui.go b/vendor/go.step.sm/cli-utils/ui/ui.go
deleted file mode 100644
index 82dcab9..0000000
--- a/vendor/go.step.sm/cli-utils/ui/ui.go
+++ /dev/null
@@ -1,334 +0,0 @@
-package ui
-
-import (
- "fmt"
- "os"
- "strings"
- "text/template"
-
- "github.com/chzyer/readline"
- "github.com/manifoldco/promptui"
- "github.com/pkg/errors"
- "go.step.sm/crypto/randutil"
-)
-
-// stderr implements an io.WriteCloser that skips the terminal bell character
-// (ASCII code 7), and writes the rest to os.Stderr. It's used to replace
-// readline.Stdout, that is the package used by promptui to display the prompts.
-type stderr struct{}
-
-// Write implements an io.WriterCloser over os.Stderr, but it skips the terminal
-// bell character.
-func (s *stderr) Write(b []byte) (int, error) {
- if len(b) == 1 && b[0] == readline.CharBell {
- return 0, nil
- }
- return os.Stderr.Write(b)
-}
-
-// Close implements an io.WriterCloser over os.Stderr.
-func (s *stderr) Close() error {
- return os.Stderr.Close()
-}
-
-func init() {
- readline.Stdout = &stderr{}
-}
-
-// Init initializes the terminal to be used by this package. This is generally a
-// noop except for windows.
-func Init() {
- setConsoleMode()
-}
-
-// Reset sets the terminal as it was before the initialization. This is
-// generally a noop except for windows.
-func Reset() {
- resetConsoleMode()
-}
-
-// Print uses templates to print the arguments formated to os.Stderr.
-func Print(args ...interface{}) error {
- var o options
- opts, args := extractOptions(args)
- o.apply(opts)
-
- // Return with a default value. This is useful when we split the question
- // and the response in two lines.
- if o.value != "" && o.valid() {
- return nil
- }
-
- text := fmt.Sprint(args...)
- t, err := template.New("Print").Funcs(promptui.FuncMap).Parse(text)
- if err != nil {
- return errors.Wrap(err, "error parsing template")
- }
- if err := t.Execute(os.Stderr, nil); err != nil {
- return errors.Wrap(err, "error executing template")
- }
- return nil
-}
-
-// Printf uses templates to print the string formated to os.Stderr.
-func Printf(format string, args ...interface{}) error {
- var o options
- opts, args := extractOptions(args)
- o.apply(opts)
-
- // Return with a default value. This is useful when we split the question
- // and the response in two lines.
- if o.value != "" && o.valid() {
- return nil
- }
-
- text := fmt.Sprintf(format, args...)
- t, err := template.New("Printf").Funcs(promptui.FuncMap).Parse(text)
- if err != nil {
- return errors.Wrap(err, "error parsing template")
- }
- if err := t.Execute(os.Stderr, nil); err != nil {
- return errors.Wrap(err, "error executing template")
- }
- return nil
-}
-
-// Println uses templates to print the given arguments to os.Stderr
-func Println(args ...interface{}) error {
- var o options
- opts, args := extractOptions(args)
- o.apply(opts)
-
- // Return with a default value. This is useful when we split the question
- // and the response in two lines.
- if o.value != "" && o.valid() {
- return nil
- }
-
- text := fmt.Sprintln(args...)
- t, err := template.New("Println").Funcs(promptui.FuncMap).Parse(text)
- if err != nil {
- return errors.Wrap(err, "error parsing template")
- }
- if err := t.Execute(os.Stderr, nil); err != nil {
- return errors.Wrap(err, "error executing template")
- }
- return nil
-}
-
-// PrintSelected prints the given name and value as if they were selected from a
-// promptui.Select.
-func PrintSelected(name, value string, opts ...Option) error {
- o := &options{
- printTemplate: PrintSelectedTemplate(),
- }
- o.apply(opts)
-
- t, err := template.New(name).Funcs(promptui.FuncMap).Parse(o.printTemplate)
- if err != nil {
- return errors.Wrap(err, "error parsing template")
- }
-
- data := struct {
- Name string
- Value string
- }{name, value}
- if err := t.Execute(os.Stderr, data); err != nil {
- return errors.Wrap(err, "error executing template")
- }
-
- return nil
-}
-
-// Prompt creates and runs a promptui.Prompt with the given label.
-func Prompt(label string, opts ...Option) (string, error) {
- o := &options{
- promptTemplates: PromptTemplates(),
- }
- o.apply(opts)
-
- // Return value if set
- if o.value != "" {
- return o.getValue()
- }
-
- // Prompt using the terminal
- clean, err := preparePromptTerminal()
- if err != nil {
- return "", err
- }
- defer clean()
-
- prompt := &promptui.Prompt{
- Label: label,
- Default: o.defaultValue,
- AllowEdit: o.allowEdit,
- Validate: o.validateFunc,
- Templates: o.promptTemplates,
- }
- value, err := prompt.Run()
- if err != nil {
- return "", errors.Wrap(err, "error running prompt")
- }
- return value, nil
-}
-
-// PromptPassword creates and runs a promptui.Prompt with the given label. This
-// prompt will mask the key entries with \r.
-func PromptPassword(label string, opts ...Option) ([]byte, error) {
- // Using a not printable character as they work better than \r
- o := &options{
- mask: 1,
- promptTemplates: SimplePromptTemplates(),
- }
- o.apply(opts)
-
- // Return value if set
- if o.value != "" {
- return o.getValueBytes()
- }
-
- // Prompt using the terminal
- clean, err := preparePromptTerminal()
- if err != nil {
- return nil, err
- }
- defer clean()
-
- prompt := &promptui.Prompt{
- Label: label,
- Mask: o.mask,
- Default: o.defaultValue,
- AllowEdit: o.allowEdit,
- Validate: o.validateFunc,
- Templates: o.promptTemplates,
- }
- pass, err := prompt.Run()
- if err != nil {
- return nil, errors.Wrap(err, "error reading password")
- }
- return []byte(pass), nil
-}
-
-// PromptPasswordGenerate creates and runs a promptui.Prompt with the given label.
-// This prompt will mask the key entries with \r. If the result password length
-// is 0, it will generate a new prompt with a generated password that can be
-// edited.
-func PromptPasswordGenerate(label string, opts ...Option) ([]byte, error) {
- pass, err := PromptPassword(label, opts...)
- if err != nil || len(pass) > 0 {
- return pass, err
- }
- passString, err := randutil.ASCII(32)
- if err != nil {
- return nil, err
- }
- passString, err = Prompt("Password", WithDefaultValue(passString), WithAllowEdit(true), WithValidateNotEmpty())
- if err != nil {
- return nil, err
- }
- return []byte(passString), nil
-}
-
-// PromptYesNo creates and runs a promptui.Prompt with the given label, and
-// returns true if the answer is y/yes and false if the answer is n/no.
-func PromptYesNo(label string, opts ...Option) (bool, error) {
- opts = append([]Option{WithValidateYesNo()}, opts...)
- s, err := Prompt(label, opts...)
- if err != nil {
- return false, err
- }
- switch strings.ToLower(strings.TrimSpace(s)) {
- case "y", "yes":
- return true, nil
- case "n", "no":
- return false, nil
- default:
- return false, fmt.Errorf("%s is not a valid answer", s)
- }
-}
-
-// Select creates and runs a promptui.Select with the given label and items.
-func Select(label string, items interface{}, opts ...Option) (int, string, error) {
- o := &options{
- selectTemplates: SelectTemplates(label),
- }
- o.apply(opts)
-
- clean, err := prepareSelectTerminal()
- if err != nil {
- return 0, "", err
- }
- defer clean()
-
- prompt := &promptui.Select{
- Label: label,
- Items: items,
- Templates: o.selectTemplates,
- }
- n, s, err := prompt.Run()
- if err != nil {
- return 0, "", errors.Wrap(err, "error running prompt")
- }
- return n, s, nil
-}
-
-func preparePromptTerminal() (func(), error) {
- nothing := func() {}
- if !readline.DefaultIsTerminal() {
- tty, err := os.Open("/dev/tty")
- if err != nil {
- return nothing, errors.Wrap(err, "error allocating terminal")
- }
- clean := func() {
- tty.Close()
- }
-
- fd := int(tty.Fd())
- state, err := readline.MakeRaw(fd)
- if err != nil {
- defer clean()
- return nothing, errors.Wrap(err, "error making raw terminal")
- }
- stdin := readline.Stdin
- readline.Stdin = tty
- clean = func() {
- readline.Stdin = stdin
- readline.Restore(fd, state)
- tty.Close()
- }
- return clean, nil
- }
-
- return nothing, nil
-}
-
-func prepareSelectTerminal() (func(), error) {
- nothing := func() {}
- if !readline.DefaultIsTerminal() {
- tty, err := os.Open("/dev/tty")
- if err != nil {
- return nothing, errors.Wrap(err, "error allocating terminal")
- }
- clean := func() {
- tty.Close()
- }
-
- fd := int(tty.Fd())
- state, err := readline.MakeRaw(fd)
- if err != nil {
- defer clean()
- return nothing, errors.Wrap(err, "error making raw terminal")
- }
- stdin := os.Stdin
- os.Stdin = tty
- clean = func() {
- os.Stdin = stdin
- readline.Restore(fd, state)
- tty.Close()
- }
- return clean, nil
- }
-
- return nothing, nil
-}
diff --git a/vendor/go.step.sm/cli-utils/ui/ui_other.go b/vendor/go.step.sm/cli-utils/ui/ui_other.go
deleted file mode 100644
index f449b57..0000000
--- a/vendor/go.step.sm/cli-utils/ui/ui_other.go
+++ /dev/null
@@ -1,8 +0,0 @@
-//go:build !windows
-// +build !windows
-
-package ui
-
-func setConsoleMode() {}
-
-func resetConsoleMode() {}
diff --git a/vendor/go.step.sm/cli-utils/ui/ui_windows.go b/vendor/go.step.sm/cli-utils/ui/ui_windows.go
deleted file mode 100644
index 573bfcb..0000000
--- a/vendor/go.step.sm/cli-utils/ui/ui_windows.go
+++ /dev/null
@@ -1,51 +0,0 @@
-//go:build windows
-// +build windows
-
-package ui
-
-import (
- "fmt"
- "os"
-
- "golang.org/x/sys/windows"
-)
-
-var inMode, outMode uint32
-
-func init() {
- var _ = windows.GetConsoleMode(windows.Stdin, &inMode)
- var _ = windows.GetConsoleMode(windows.Stdout, &outMode)
-}
-
-func setConsoleMode() {
- in := inMode | windows.ENABLE_VIRTUAL_TERMINAL_INPUT
- out := outMode | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
-
- if inMode != 0 && inMode != in {
- if err := windows.SetConsoleMode(windows.Stdin, in); err != nil {
- fmt.Fprintf(os.Stderr, "Failed to set console mode: %v\n", err)
- }
- }
-
- if outMode != 0 && outMode != out {
- if err := windows.SetConsoleMode(windows.Stdout, out); err != nil {
- fmt.Fprintf(os.Stderr, "Failed to set console mode: %v\n", err)
- }
- }
-}
-
-func resetConsoleMode() {
- in := inMode | windows.ENABLE_VIRTUAL_TERMINAL_INPUT
- out := outMode | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
-
- if inMode != 0 && inMode != in {
- if err := windows.SetConsoleMode(windows.Stdin, inMode); err != nil {
- fmt.Fprintf(os.Stderr, "Failed to reset console mode: %v\n", err)
- }
- }
- if outMode != 0 && outMode != out {
- if err := windows.SetConsoleMode(windows.Stdout, outMode); err != nil {
- fmt.Fprintf(os.Stderr, "Failed to reset console mode: %v\n", err)
- }
- }
-}
diff --git a/vendor/go.step.sm/cli-utils/ui/validators.go b/vendor/go.step.sm/cli-utils/ui/validators.go
deleted file mode 100644
index 7d8b603..0000000
--- a/vendor/go.step.sm/cli-utils/ui/validators.go
+++ /dev/null
@@ -1,75 +0,0 @@
-package ui
-
-import (
- "errors"
- "fmt"
- "net"
- "strings"
-
- "github.com/manifoldco/promptui"
-)
-
-var errEmptyValue = errors.New("value is empty")
-
-// NotEmpty is a validation function that checks that the prompted string is not
-// empty.
-func NotEmpty() promptui.ValidateFunc {
- return func(s string) error {
- if strings.TrimSpace(s) == "" {
- return errEmptyValue
- }
- return nil
- }
-}
-
-// Address is a validation function that checks that the prompted string is a
-// valid TCP address.
-func Address() promptui.ValidateFunc {
- return func(s string) error {
- if _, _, err := net.SplitHostPort(s); err != nil {
- return fmt.Errorf("%s is not an TCP address", s)
- }
- return nil
- }
-}
-
-// IPAddress is validation function that checks that the prompted string is a
-// valid IP address.
-func IPAddress() promptui.ValidateFunc {
- return func(s string) error {
- if net.ParseIP(s) == nil {
- return fmt.Errorf("%s is not an ip address", s)
- }
- return nil
- }
-}
-
-// DNS is a validation function that checks that the prompted string is a valid
-// DNS name or IP address.
-func DNS() promptui.ValidateFunc {
- return func(s string) error {
- if strings.TrimSpace(s) == "" {
- return errEmptyValue
- }
- if ip := net.ParseIP(s); ip != nil {
- return nil
- }
- if _, _, err := net.SplitHostPort(s + ":443"); err != nil {
- return fmt.Errorf("%s is not a valid DNS name or IP address", s)
- }
- return nil
- }
-}
-
-// YesNo is a validation function that checks for a Yes/No answer.
-func YesNo() promptui.ValidateFunc {
- return func(s string) error {
- s = strings.ToLower(strings.TrimSpace(s))
- switch s {
- case "y", "yes", "n", "no":
- return nil
- default:
- return fmt.Errorf("%s is not a valid answer", s)
- }
- }
-}
diff --git a/vendor/go.step.sm/cli-utils/usage/css.go b/vendor/go.step.sm/cli-utils/usage/css.go
deleted file mode 100644
index e552534..0000000
--- a/vendor/go.step.sm/cli-utils/usage/css.go
+++ /dev/null
@@ -1,764 +0,0 @@
-package usage
-
-// CSS code replicating Github style.
-// From https://github.com/sindresorhus/github-markdown-css
-// MIT license
-var css = `@font-face {
- font-family: octicons-link;
- src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAZwABAAAAAACFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEU0lHAAAGaAAAAAgAAAAIAAAAAUdTVUIAAAZcAAAACgAAAAoAAQAAT1MvMgAAAyQAAABJAAAAYFYEU3RjbWFwAAADcAAAAEUAAACAAJThvmN2dCAAAATkAAAABAAAAAQAAAAAZnBnbQAAA7gAAACyAAABCUM+8IhnYXNwAAAGTAAAABAAAAAQABoAI2dseWYAAAFsAAABPAAAAZwcEq9taGVhZAAAAsgAAAA0AAAANgh4a91oaGVhAAADCAAAABoAAAAkCA8DRGhtdHgAAAL8AAAADAAAAAwGAACfbG9jYQAAAsAAAAAIAAAACABiATBtYXhwAAACqAAAABgAAAAgAA8ASm5hbWUAAAToAAABQgAAAlXu73sOcG9zdAAABiwAAAAeAAAAME3QpOBwcmVwAAAEbAAAAHYAAAB/aFGpk3jaTY6xa8JAGMW/O62BDi0tJLYQincXEypYIiGJjSgHniQ6umTsUEyLm5BV6NDBP8Tpts6F0v+k/0an2i+itHDw3v2+9+DBKTzsJNnWJNTgHEy4BgG3EMI9DCEDOGEXzDADU5hBKMIgNPZqoD3SilVaXZCER3/I7AtxEJLtzzuZfI+VVkprxTlXShWKb3TBecG11rwoNlmmn1P2WYcJczl32etSpKnziC7lQyWe1smVPy/Lt7Kc+0vWY/gAgIIEqAN9we0pwKXreiMasxvabDQMM4riO+qxM2ogwDGOZTXxwxDiycQIcoYFBLj5K3EIaSctAq2kTYiw+ymhce7vwM9jSqO8JyVd5RH9gyTt2+J/yUmYlIR0s04n6+7Vm1ozezUeLEaUjhaDSuXHwVRgvLJn1tQ7xiuVv/ocTRF42mNgZGBgYGbwZOBiAAFGJBIMAAizAFoAAABiAGIAznjaY2BkYGAA4in8zwXi+W2+MjCzMIDApSwvXzC97Z4Ig8N/BxYGZgcgl52BCSQKAA3jCV8CAABfAAAAAAQAAEB42mNgZGBg4f3vACQZQABIMjKgAmYAKEgBXgAAeNpjYGY6wTiBgZWBg2kmUxoDA4MPhGZMYzBi1AHygVLYQUCaawqDA4PChxhmh/8ODDEsvAwHgMKMIDnGL0x7gJQCAwMAJd4MFwAAAHjaY2BgYGaA4DAGRgYQkAHyGMF8NgYrIM3JIAGVYYDT+AEjAwuDFpBmA9KMDEwMCh9i/v8H8sH0/4dQc1iAmAkALaUKLgAAAHjaTY9LDsIgEIbtgqHUPpDi3gPoBVyRTmTddOmqTXThEXqrob2gQ1FjwpDvfwCBdmdXC5AVKFu3e5MfNFJ29KTQT48Ob9/lqYwOGZxeUelN2U2R6+cArgtCJpauW7UQBqnFkUsjAY/kOU1cP+DAgvxwn1chZDwUbd6CFimGXwzwF6tPbFIcjEl+vvmM/byA48e6tWrKArm4ZJlCbdsrxksL1AwWn/yBSJKpYbq8AXaaTb8AAHja28jAwOC00ZrBeQNDQOWO//sdBBgYGRiYWYAEELEwMTE4uzo5Zzo5b2BxdnFOcALxNjA6b2ByTswC8jYwg0VlNuoCTWAMqNzMzsoK1rEhNqByEyerg5PMJlYuVueETKcd/89uBpnpvIEVomeHLoMsAAe1Id4AAAAAAAB42oWQT07CQBTGv0JBhagk7HQzKxca2sJCE1hDt4QF+9JOS0nbaaYDCQfwCJ7Au3AHj+LO13FMmm6cl7785vven0kBjHCBhfpYuNa5Ph1c0e2Xu3jEvWG7UdPDLZ4N92nOm+EBXuAbHmIMSRMs+4aUEd4Nd3CHD8NdvOLTsA2GL8M9PODbcL+hD7C1xoaHeLJSEao0FEW14ckxC+TU8TxvsY6X0eLPmRhry2WVioLpkrbp84LLQPGI7c6sOiUzpWIWS5GzlSgUzzLBSikOPFTOXqly7rqx0Z1Q5BAIoZBSFihQYQOOBEdkCOgXTOHA07HAGjGWiIjaPZNW13/+lm6S9FT7rLHFJ6fQbkATOG1j2OFMucKJJsxIVfQORl+9Jyda6Sl1dUYhSCm1dyClfoeDve4qMYdLEbfqHf3O/AdDumsjAAB42mNgYoAAZQYjBmyAGYQZmdhL8zLdDEydARfoAqIAAAABAAMABwAKABMAB///AA8AAQAAAAAAAAAAAAAAAAABAAAAAA==) format('woff');
-}
-
-.wrapper {
- margin: 0 auto;
- max-width: 700px;
- padding: 20px 10px;
-}
-
-.markdown-body {
- -ms-text-size-adjust: 100%;
- -webkit-text-size-adjust: 100%;
- line-height: 1.5;
- color: #24292e;
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
- font-size: 16px;
- line-height: 1.5;
- word-wrap: break-word;
-}
-
-.markdown-body .pl-c {
- color: #6a737d;
-}
-
-.markdown-body .pl-c1,
-.markdown-body .pl-s .pl-v {
- color: #005cc5;
-}
-
-.markdown-body .pl-e,
-.markdown-body .pl-en {
- color: #6f42c1;
-}
-
-.markdown-body .pl-smi,
-.markdown-body .pl-s .pl-s1 {
- color: #24292e;
-}
-
-.markdown-body .pl-ent {
- color: #22863a;
-}
-
-.markdown-body .pl-k {
- color: #d73a49;
-}
-
-.markdown-body .pl-s,
-.markdown-body .pl-pds,
-.markdown-body .pl-s .pl-pse .pl-s1,
-.markdown-body .pl-sr,
-.markdown-body .pl-sr .pl-cce,
-.markdown-body .pl-sr .pl-sre,
-.markdown-body .pl-sr .pl-sra {
- color: #032f62;
-}
-
-.markdown-body .pl-v,
-.markdown-body .pl-smw {
- color: #e36209;
-}
-
-.markdown-body .pl-bu {
- color: #b31d28;
-}
-
-.markdown-body .pl-ii {
- color: #fafbfc;
- background-color: #b31d28;
-}
-
-.markdown-body .pl-c2 {
- color: #fafbfc;
- background-color: #d73a49;
-}
-
-.markdown-body .pl-c2::before {
- content: "^M";
-}
-
-.markdown-body .pl-sr .pl-cce {
- font-weight: bold;
- color: #22863a;
-}
-
-.markdown-body .pl-ml {
- color: #735c0f;
-}
-
-.markdown-body .pl-mh,
-.markdown-body .pl-mh .pl-en,
-.markdown-body .pl-ms {
- font-weight: bold;
- color: #005cc5;
-}
-
-.markdown-body .pl-mi {
- font-style: italic;
- color: #24292e;
-}
-
-.markdown-body .pl-mb {
- font-weight: bold;
- color: #24292e;
-}
-
-.markdown-body .pl-md {
- color: #b31d28;
- background-color: #ffeef0;
-}
-
-.markdown-body .pl-mi1 {
- color: #22863a;
- background-color: #f0fff4;
-}
-
-.markdown-body .pl-mc {
- color: #e36209;
- background-color: #ffebda;
-}
-
-.markdown-body .pl-mi2 {
- color: #f6f8fa;
- background-color: #005cc5;
-}
-
-.markdown-body .pl-mdr {
- font-weight: bold;
- color: #6f42c1;
-}
-
-.markdown-body .pl-ba {
- color: #586069;
-}
-
-.markdown-body .pl-sg {
- color: #959da5;
-}
-
-.markdown-body .pl-corl {
- text-decoration: underline;
- color: #032f62;
-}
-
-.markdown-body .octicon {
- display: inline-block;
- vertical-align: text-top;
- fill: currentColor;
-}
-
-.markdown-body a {
- background-color: transparent;
-}
-
-.markdown-body a:active,
-.markdown-body a:hover {
- outline-width: 0;
-}
-
-.markdown-body strong {
- font-weight: inherit;
-}
-
-.markdown-body strong {
- font-weight: bolder;
-}
-
-.markdown-body h1 {
- font-size: 2em;
- margin: 0.67em 0;
-}
-
-.markdown-body img {
- border-style: none;
-}
-
-.markdown-body code,
-.markdown-body kbd,
-.markdown-body pre {
- font-family: monospace, monospace;
- font-size: 1em;
-}
-
-.markdown-body hr {
- box-sizing: content-box;
- height: 0;
- overflow: visible;
-}
-
-.markdown-body input {
- font: inherit;
- margin: 0;
-}
-
-.markdown-body input {
- overflow: visible;
-}
-
-.markdown-body [type="checkbox"] {
- box-sizing: border-box;
- padding: 0;
-}
-
-.markdown-body * {
- box-sizing: border-box;
-}
-
-.markdown-body input {
- font-family: inherit;
- font-size: inherit;
- line-height: inherit;
-}
-
-.markdown-body a {
- color: #0366d6;
- text-decoration: none;
-}
-
-.markdown-body a:hover {
- text-decoration: underline;
-}
-
-.markdown-body strong {
- font-weight: 600;
-}
-
-.markdown-body hr {
- height: 0;
- margin: 15px 0;
- overflow: hidden;
- background: transparent;
- border: 0;
- border-bottom: 1px solid #dfe2e5;
-}
-
-.markdown-body hr::before {
- display: table;
- content: "";
-}
-
-.markdown-body hr::after {
- display: table;
- clear: both;
- content: "";
-}
-
-.markdown-body table {
- border-spacing: 0;
- border-collapse: collapse;
-}
-
-.markdown-body td,
-.markdown-body th {
- padding: 0;
-}
-
-.markdown-body h1,
-.markdown-body h2,
-.markdown-body h3,
-.markdown-body h4,
-.markdown-body h5,
-.markdown-body h6 {
- margin-top: 0;
- margin-bottom: 0;
-}
-
-.markdown-body h1 {
- font-size: 32px;
- font-weight: 600;
-}
-
-.markdown-body h2 {
- font-size: 24px;
- font-weight: 600;
-}
-
-.markdown-body h3 {
- font-size: 20px;
- font-weight: 600;
-}
-
-.markdown-body h4 {
- font-size: 16px;
- font-weight: 600;
-}
-
-.markdown-body h5 {
- font-size: 14px;
- font-weight: 600;
-}
-
-.markdown-body h6 {
- font-size: 12px;
- font-weight: 600;
-}
-
-.markdown-body p {
- margin-top: 0;
- margin-bottom: 10px;
-}
-
-.markdown-body blockquote {
- margin: 0;
-}
-
-.markdown-body ul,
-.markdown-body ol {
- padding-left: 0;
- margin-top: 0;
- margin-bottom: 0;
-}
-
-.markdown-body ol ol,
-.markdown-body ul ol {
- list-style-type: lower-roman;
-}
-
-.markdown-body ul ul ol,
-.markdown-body ul ol ol,
-.markdown-body ol ul ol,
-.markdown-body ol ol ol {
- list-style-type: lower-alpha;
-}
-
-.markdown-body dd {
- margin-left: 0;
-}
-
-.markdown-body code {
- font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
- font-size: 12px;
-}
-
-.markdown-body pre {
- margin-top: 0;
- margin-bottom: 0;
- font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
- font-size: 12px;
-}
-
-.markdown-body .octicon {
- vertical-align: text-bottom;
-}
-
-.markdown-body .pl-0 {
- padding-left: 0 !important;
-}
-
-.markdown-body .pl-1 {
- padding-left: 4px !important;
-}
-
-.markdown-body .pl-2 {
- padding-left: 8px !important;
-}
-
-.markdown-body .pl-3 {
- padding-left: 16px !important;
-}
-
-.markdown-body .pl-4 {
- padding-left: 24px !important;
-}
-
-.markdown-body .pl-5 {
- padding-left: 32px !important;
-}
-
-.markdown-body .pl-6 {
- padding-left: 40px !important;
-}
-
-.markdown-body::before {
- display: table;
- content: "";
-}
-
-.markdown-body::after {
- display: table;
- clear: both;
- content: "";
-}
-
-.markdown-body>*:first-child {
- margin-top: 0 !important;
-}
-
-.markdown-body>*:last-child {
- margin-bottom: 0 !important;
-}
-
-.markdown-body a:not([href]) {
- color: inherit;
- text-decoration: none;
-}
-
-.markdown-body .anchor {
- float: left;
- padding-right: 4px;
- margin-left: -20px;
- line-height: 1;
-}
-
-.markdown-body .anchor:focus {
- outline: none;
-}
-
-.markdown-body p,
-.markdown-body blockquote,
-.markdown-body ul,
-.markdown-body ol,
-.markdown-body dl,
-.markdown-body table,
-.markdown-body pre {
- margin-top: 0;
- margin-bottom: 16px;
-}
-
-.markdown-body hr {
- height: 0.25em;
- padding: 0;
- margin: 24px 0;
- background-color: #e1e4e8;
- border: 0;
-}
-
-.markdown-body blockquote {
- padding: 0 1em;
- color: #6a737d;
- border-left: 0.25em solid #dfe2e5;
-}
-
-.markdown-body blockquote>:first-child {
- margin-top: 0;
-}
-
-.markdown-body blockquote>:last-child {
- margin-bottom: 0;
-}
-
-.markdown-body kbd {
- display: inline-block;
- padding: 3px 5px;
- font-size: 11px;
- line-height: 10px;
- color: #444d56;
- vertical-align: middle;
- background-color: #fafbfc;
- border: solid 1px #c6cbd1;
- border-bottom-color: #959da5;
- border-radius: 3px;
- box-shadow: inset 0 -1px 0 #959da5;
-}
-
-.markdown-body h1,
-.markdown-body h2,
-.markdown-body h3,
-.markdown-body h4,
-.markdown-body h5,
-.markdown-body h6 {
- margin-top: 24px;
- margin-bottom: 16px;
- font-weight: 600;
- line-height: 1.25;
-}
-
-.markdown-body h1 .octicon-link,
-.markdown-body h2 .octicon-link,
-.markdown-body h3 .octicon-link,
-.markdown-body h4 .octicon-link,
-.markdown-body h5 .octicon-link,
-.markdown-body h6 .octicon-link {
- color: #1b1f23;
- vertical-align: middle;
- visibility: hidden;
-}
-
-.markdown-body h1:hover .anchor,
-.markdown-body h2:hover .anchor,
-.markdown-body h3:hover .anchor,
-.markdown-body h4:hover .anchor,
-.markdown-body h5:hover .anchor,
-.markdown-body h6:hover .anchor {
- text-decoration: none;
-}
-
-.markdown-body h1:hover .anchor .octicon-link,
-.markdown-body h2:hover .anchor .octicon-link,
-.markdown-body h3:hover .anchor .octicon-link,
-.markdown-body h4:hover .anchor .octicon-link,
-.markdown-body h5:hover .anchor .octicon-link,
-.markdown-body h6:hover .anchor .octicon-link {
- visibility: visible;
-}
-
-.markdown-body h1 {
- padding-bottom: 0.3em;
- font-size: 2em;
- border-bottom: 1px solid #eaecef;
-}
-
-.markdown-body h2 {
- padding-bottom: 0.3em;
- font-size: 1.5em;
- border-bottom: 1px solid #eaecef;
-}
-
-.markdown-body h3 {
- font-size: 1.25em;
-}
-
-.markdown-body h4 {
- font-size: 1em;
-}
-
-.markdown-body h5 {
- font-size: 0.875em;
-}
-
-.markdown-body h6 {
- font-size: 0.85em;
- color: #6a737d;
-}
-
-.markdown-body ul,
-.markdown-body ol {
- padding-left: 2em;
-}
-
-.markdown-body ul ul,
-.markdown-body ul ol,
-.markdown-body ol ol,
-.markdown-body ol ul {
- margin-top: 0;
- margin-bottom: 0;
-}
-
-.markdown-body li {
- word-wrap: break-all;
-}
-
-.markdown-body li>p {
- margin-top: 16px;
-}
-
-.markdown-body li+li {
- margin-top: 0.25em;
-}
-
-.markdown-body dl {
- padding: 0;
-}
-
-.markdown-body dl dt {
- padding: 0;
- margin-top: 16px;
- font-size: 1em;
- font-style: italic;
- font-weight: 600;
-}
-
-.markdown-body dl dd {
- padding: 0 16px;
- margin-bottom: 16px;
-}
-
-.markdown-body table {
- display: block;
- width: 100%;
- overflow: auto;
-}
-
-.markdown-body table th {
- font-weight: 600;
-}
-
-.markdown-body table th,
-.markdown-body table td {
- padding: 6px 13px;
- border: 1px solid #dfe2e5;
-}
-
-.markdown-body table tr {
- background-color: #fff;
- border-top: 1px solid #c6cbd1;
-}
-
-.markdown-body table tr:nth-child(2n) {
- background-color: #f6f8fa;
-}
-
-.markdown-body img {
- max-width: 100%;
- box-sizing: content-box;
- background-color: #fff;
-}
-
-.markdown-body img[align=right] {
- padding-left: 20px;
-}
-
-.markdown-body img[align=left] {
- padding-right: 20px;
-}
-
-.markdown-body code {
- padding: 0.2em 0.4em;
- margin: 0;
- font-size: 85%;
- background-color: rgba(27,31,35,0.05);
- border-radius: 3px;
-}
-
-.markdown-body pre {
- word-wrap: normal;
-}
-
-.markdown-body pre>code {
- padding: 0;
- margin: 0;
- font-size: 100%;
- word-break: normal;
- white-space: pre;
- background: transparent;
- border: 0;
-}
-
-.markdown-body .highlight {
- margin-bottom: 16px;
-}
-
-.markdown-body .highlight pre {
- margin-bottom: 0;
- word-break: normal;
-}
-
-.markdown-body .highlight pre,
-.markdown-body pre {
- padding: 16px;
- overflow: auto;
- font-size: 85%;
- line-height: 1.45;
- background-color: #f6f8fa;
- border-radius: 3px;
-}
-
-.markdown-body pre code {
- display: inline;
- max-width: auto;
- padding: 0;
- margin: 0;
- overflow: visible;
- line-height: inherit;
- word-wrap: normal;
- background-color: transparent;
- border: 0;
-}
-
-.markdown-body .full-commit .btn-outline:not(:disabled):hover {
- color: #005cc5;
- border-color: #005cc5;
-}
-
-.markdown-body kbd {
- display: inline-block;
- padding: 3px 5px;
- font: 11px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
- line-height: 10px;
- color: #444d56;
- vertical-align: middle;
- background-color: #fafbfc;
- border: solid 1px #d1d5da;
- border-bottom-color: #c6cbd1;
- border-radius: 3px;
- box-shadow: inset 0 -1px 0 #c6cbd1;
-}
-
-.markdown-body :checked+.radio-label {
- position: relative;
- z-index: 1;
- border-color: #0366d6;
-}
-
-.markdown-body .task-list-item {
- list-style-type: none;
-}
-
-.markdown-body .task-list-item+.task-list-item {
- margin-top: 3px;
-}
-
-.markdown-body .task-list-item input {
- margin: 0 0.2em 0.25em -1.6em;
- vertical-align: middle;
-}
-
-.markdown-body hr {
- border-bottom-color: #eee;
-}
-
-.command {
- font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier,
- monospace;
- font-size: 16px;
- padding-left: 40px;
-
-}
-
-.command h1 {
- border: none;
- margin-left: -40px;
-}
-
-.command h2 {
- border: none;
- margin-top: 2em;
- margin-left: -40px;
- font-size: 18px;
-}
-
-.command>ul {
- padding-left: 0;
-}
-
-.command ul {
- list-style-type: none;
-}
-
-.command table {
- margin: 2em 0 1em;
- display: block;
- width: 100%;
- overflow: auto;
- border-collapse: collapse;
-}
-
-.command table th {
- font-weight: 600;
-}
-
-.command table th,
-.command table td {
- padding: 6px 13px;
- border: 1px solid #dfe2e5;
-}
-
-.command table tr {
- background-color: #fff;
- border-top: 1px solid #c6cbd1;
-}
-
-.command table tr:nth-child(2n) {
- background-color: #f6f8fa;
-}
-
-
-`
diff --git a/vendor/go.step.sm/cli-utils/usage/help.go b/vendor/go.step.sm/cli-utils/usage/help.go
deleted file mode 100644
index eef3273..0000000
--- a/vendor/go.step.sm/cli-utils/usage/help.go
+++ /dev/null
@@ -1,191 +0,0 @@
-package usage
-
-import (
- "fmt"
- "strings"
-
- "github.com/urfave/cli"
-)
-
-// HelpCommandAction is the action function of the overwritten help command.
-var HelpCommandAction = cli.ActionFunc(helpAction)
-
-// HelpCommand overwrites default urfvafe/cli help command to support one or
-// multiple subcommands like:
-//
-// step help
-// step help crypto
-// step help crypto jwt
-// step help crypto jwt sign
-// ...
-func HelpCommand() cli.Command {
- return cli.Command{
- Name: "help",
- Aliases: []string{"h"},
- Usage: "display help for the specified command or command group",
- UsageText: "**step help** <command>",
- Description: `**step help** command displays help for a command or command group.
-
-## EXAMPLES
-
-Display help for **step ca certificate**:
-'''
-$ step help ca certificate
-'''
-
-Display help for **step ssh**:
-'''
-$ step help ssh
-'''`,
- Action: HelpCommandAction,
- Flags: []cli.Flag{
- cli.StringFlag{
- Name: "http",
- Usage: "HTTP service address (e.g., ':8080')",
- },
- cli.StringFlag{
- Name: "html",
- Usage: "The export <directory> for HTML docs.",
- },
- cli.StringFlag{
- Name: "markdown",
- Usage: "The export <directory> for Markdown docs.",
- },
- cli.BoolFlag{
- Name: "report",
- Usage: "Writes a JSON report to the HTML docs directory.",
- },
- },
- }
-}
-
-func helpAction(ctx *cli.Context) error {
- // use html version
- if ctx.IsSet("http") {
- return httpHelpAction(ctx)
- }
-
- if ctx.IsSet("html") {
- return htmlHelpAction(ctx)
- }
-
- if ctx.IsSet("markdown") {
- return markdownHelpAction(ctx)
- }
-
- args := ctx.Args()
- if args.Present() {
- last := len(args) - 1
- lastName := args[last]
- subcmd := ctx.App.Commands
- parent := createParentCommand(ctx)
-
- for _, name := range args[:last] {
- for _, cmd := range subcmd {
- if cmd.HasName(name) {
- parent = cmd
- subcmd = cmd.Subcommands
- break
- }
- }
- }
-
- for _, cmd := range subcmd {
- if !cmd.HasName(lastName) {
- continue
- }
- cmd.HelpName = fmt.Sprintf("%s %s", ctx.App.HelpName, strings.Join(args, " "))
- parent.HelpName = fmt.Sprintf("%s %s", ctx.App.HelpName, strings.Join(args[:last], " "))
-
- ctx.Command = cmd
- if len(cmd.Subcommands) == 0 {
- ctx.App = createCliApp(ctx, parent)
- return cli.ShowCommandHelp(ctx, lastName)
- }
-
- ctx.App = createCliApp(ctx, cmd)
- return cli.ShowCommandHelp(ctx, "")
- }
-
- return cli.NewExitError(fmt.Sprintf("No help topic for '%s %s'", ctx.App.Name, strings.Join(args, " ")), 3)
- }
-
- cli.ShowAppHelp(ctx)
- return nil
-}
-
-// createParentCommand returns a command representation of the app.
-func createParentCommand(ctx *cli.Context) cli.Command {
- return cli.Command{
- Name: ctx.App.Name,
- HelpName: ctx.App.HelpName,
- Usage: ctx.App.Usage,
- UsageText: ctx.App.UsageText,
- ArgsUsage: ctx.App.ArgsUsage,
- Description: ctx.App.Description,
- Subcommands: ctx.App.Commands,
- Flags: ctx.App.Flags,
- }
-}
-
-// createCliApp is re-implementation of urfave/cli method (in command.go):
-//
-// func (c Command) startApp(ctx *Context) error
-//
-// It lets us show the subcommands when help is executed like:
-//
-// step help foo
-// step help foo bar
-// ...
-func createCliApp(ctx *cli.Context, cmd cli.Command) *cli.App {
- app := cli.NewApp()
- app.Metadata = ctx.App.Metadata
-
- // set the name and usage
- app.Name = cmd.HelpName
- app.HelpName = cmd.HelpName
-
- app.Usage = cmd.Usage
- app.UsageText = cmd.UsageText
- app.Description = cmd.Description
- app.ArgsUsage = cmd.ArgsUsage
-
- // set CommandNotFound
- app.CommandNotFound = ctx.App.CommandNotFound
- app.CustomAppHelpTemplate = cmd.CustomHelpTemplate
-
- // set the flags and commands
- app.Commands = cmd.Subcommands
- app.Flags = cmd.Flags
-
- app.Version = ctx.App.Version
- app.Compiled = ctx.App.Compiled
- app.Author = ctx.App.Author
- app.Email = ctx.App.Email
- app.Writer = ctx.App.Writer
- app.ErrWriter = ctx.App.ErrWriter
-
- // Do not show help or version on subcommands
- app.HideHelp = true
- app.HideVersion = true
-
- // bash completion
- app.EnableBashCompletion = ctx.App.EnableBashCompletion
- if cmd.BashComplete != nil {
- app.BashComplete = cmd.BashComplete
- }
-
- // set the actions
- app.Before = cmd.Before
- app.After = cmd.After
-
- if cmd.Action != nil {
- app.Action = cmd.Action
- } else {
- app.Action = helpAction
- }
- app.OnUsageError = cmd.OnUsageError
-
- app.Setup()
- return app
-}
diff --git a/vendor/go.step.sm/cli-utils/usage/html.go b/vendor/go.step.sm/cli-utils/usage/html.go
deleted file mode 100644
index 7ea8fd0..0000000
--- a/vendor/go.step.sm/cli-utils/usage/html.go
+++ /dev/null
@@ -1,350 +0,0 @@
-package usage
-
-import (
- "fmt"
- "net/http"
- "os"
- "path"
- "strings"
- "time"
-
- "github.com/urfave/cli"
- "go.step.sm/cli-utils/errs"
-)
-
-func httpHelpAction(ctx *cli.Context) error {
- addr := ctx.String("http")
- if addr == "" {
- return errs.RequiredFlag(ctx, "http")
- }
-
- fmt.Printf("Serving HTTP on %s ...\n", addr)
- server := http.Server{
- Addr: addr,
- Handler: &htmlHelpHandler{
- cliApp: ctx.App,
- },
- ReadHeaderTimeout: 15 * time.Second,
- }
- return server.ListenAndServe()
-}
-
-func markdownHelpAction(ctx *cli.Context) error {
- dir := path.Clean(ctx.String("markdown"))
- if err := os.MkdirAll(dir, 0755); err != nil {
- return errs.FileError(err, dir)
- }
-
- // app index
- index := path.Join(dir, "README.mdx")
- w, err := os.Create(index)
- if err != nil {
- return errs.FileError(err, index)
- }
- markdownHelpPrinter(w, mdAppHelpTemplate, "", ctx.App)
- if err := w.Close(); err != nil {
- return errs.FileError(err, index)
- }
-
- // Subcommands
- for _, cmd := range ctx.App.Commands {
- if err := markdownHelpCommand(ctx.App, cmd, cmd, path.Join(dir, cmd.Name)); err != nil {
- return err
- }
- }
- return nil
-}
-
-func markdownHelpCommand(app *cli.App, cmd, parent cli.Command, base string) error {
- if err := os.MkdirAll(base, 0755); err != nil {
- return errs.FileError(err, base)
- }
-
- fileName := "README.mdx"
-
- index := path.Join(base, fileName)
- w, err := os.Create(index)
- if err != nil {
- return errs.FileError(err, index)
- }
-
- parentName := parent.HelpName
- if cmd.HelpName == parent.HelpName {
- parentName = "step"
- }
-
- if len(cmd.Subcommands) == 0 {
- markdownHelpPrinter(w, mdCommandHelpTemplate, parentName, cmd)
- return errs.FileError(w.Close(), index)
- }
-
- ctx := cli.NewContext(app, nil, nil)
- ctx.App = createCliApp(ctx, cmd)
- markdownHelpPrinter(w, mdSubcommandHelpTemplate, parentName, ctx.App)
- if err := w.Close(); err != nil {
- return errs.FileError(err, index)
- }
-
- for _, sub := range cmd.Subcommands {
- sub.HelpName = fmt.Sprintf("%s %s", cmd.HelpName, sub.Name)
- if err := markdownHelpCommand(app, sub, cmd, path.Join(base, sub.Name)); err != nil {
- return err
- }
- }
-
- return nil
-}
-
-func htmlHelpAction(ctx *cli.Context) error {
- dir := path.Clean(ctx.String("html"))
-
- if err := os.MkdirAll(dir, 0755); err != nil {
- return errs.FileError(err, dir)
- }
-
- // app index
- index := path.Join(dir, "index.html")
- w, err := os.Create(index)
- if err != nil {
- return errs.FileError(err, index)
- }
-
- tophelp := htmlHelpPrinter(w, mdAppHelpTemplate, ctx.App)
- var report *Report
- if ctx.IsSet("report") {
- report = NewReport(ctx.App.Name, tophelp)
- }
-
- if err := w.Close(); err != nil {
- return errs.FileError(err, index)
- }
-
- // css style
- cssFile := path.Join(dir, "style.css")
- //nolint:gosec // not security sensitive
- if err := os.WriteFile(cssFile, []byte(css), 0666); err != nil {
- return errs.FileError(err, cssFile)
- }
-
- // Subcommands
- for _, cmd := range ctx.App.Commands {
- if err := htmlHelpCommand(ctx.App, cmd, path.Join(dir, cmd.Name), report); err != nil {
- return err
- }
- }
-
- // report
- if report != nil {
- repjson := path.Join(dir, "report.json")
- rjw, err := os.Create(repjson)
- if err != nil {
- return errs.FileError(err, repjson)
- }
-
- if err := report.Write(rjw); err != nil {
- return err
- }
-
- if err := rjw.Close(); err != nil {
- return errs.FileError(err, repjson)
- }
- }
-
- return nil
-}
-
-func htmlHelpCommand(app *cli.App, cmd cli.Command, base string, report *Report) error {
- if err := os.MkdirAll(base, 0755); err != nil {
- return errs.FileError(err, base)
- }
-
- index := path.Join(base, "index.html")
- w, err := os.Create(index)
- if err != nil {
- return errs.FileError(err, index)
- }
-
- if len(cmd.Subcommands) == 0 {
- cmdhelp := htmlHelpPrinter(w, mdCommandHelpTemplate, cmd)
-
- if report != nil {
- report.Process(cmd.HelpName, cmdhelp)
- }
-
- return errs.FileError(w.Close(), index)
- }
-
- ctx := cli.NewContext(app, nil, nil)
- ctx.App = createCliApp(ctx, cmd)
- subhelp := htmlHelpPrinter(w, mdSubcommandHelpTemplate, ctx.App)
-
- if report != nil {
- report.Process(cmd.HelpName, subhelp)
- }
-
- if err := w.Close(); err != nil {
- return errs.FileError(err, index)
- }
-
- for _, sub := range cmd.Subcommands {
- sub.HelpName = fmt.Sprintf("%s %s", cmd.HelpName, sub.Name)
- if err := htmlHelpCommand(app, sub, path.Join(base, sub.Name), report); err != nil {
- return err
- }
- }
-
- return nil
-}
-
-type htmlHelpHandler struct {
- cliApp *cli.App
-}
-
-func (h *htmlHelpHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
- ctx := cli.NewContext(h.cliApp, nil, nil)
-
- // clean request URI
- requestURI := path.Clean(req.RequestURI)
- if requestURI == "/" {
- htmlHelpPrinter(w, mdAppHelpTemplate, ctx.App)
- return
- }
-
- if requestURI == "/style.css" {
- w.Header().Set("Content-Type", `text/css; charset="utf-8"`)
- w.Write([]byte(css))
- return
- }
-
- args := strings.Split(requestURI, "/")
- last := len(args) - 1
- lastName := args[last]
- subcmd := ctx.App.Commands
- for _, name := range args[:last] {
- for _, cmd := range subcmd {
- if cmd.HasName(name) {
- subcmd = cmd.Subcommands
- break
- }
- }
- }
-
- for _, cmd := range subcmd {
- if !cmd.HasName(lastName) {
- continue
- }
- cmd.HelpName = fmt.Sprintf("%s %s", ctx.App.HelpName, strings.Join(args, " "))
-
- ctx.Command = cmd
- if len(cmd.Subcommands) == 0 {
- htmlHelpPrinter(w, mdCommandHelpTemplate, cmd)
- return
- }
-
- ctx.App = createCliApp(ctx, cmd)
- htmlHelpPrinter(w, mdSubcommandHelpTemplate, ctx.App)
- return
- }
-
- http.NotFound(w, req)
-}
-
-// AppHelpTemplate contains the modified template for the main app
-var mdAppHelpTemplate = `## NAME
-**{{.HelpName}}** -- {{.Usage}}
-
-## USAGE
-
-'''raw
-{{if .UsageText}}{{.UsageText}}{{else}}**{{.HelpName}}**{{if .Commands}} <command>{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments]{{end}}{{end}}
-'''
-{{- if .Description}}
-
-## DESCRIPTION
-{{.Description}}{{end}}{{if .VisibleCommands}}
-
-## COMMANDS
-
-{{range .VisibleCategories}}{{if .Name}}{{.Name}}:{{end}}
-| Name | Usage |
-|---|---|{{range .VisibleCommands}}
-| **[{{join .Names ", "}}]({{.Name}}/)** | {{.Usage}} |{{end}}
-{{end}}{{if .VisibleFlags}}{{end}}
-
-## OPTIONS
-
-{{range $index, $option := .VisibleFlags}}{{if $index}}
-{{end}}{{$option}}
-{{end}}{{end}}{{if .Copyright}}{{if len .Authors}}
-
-## AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
-
-{{range $index, $author := .Authors}}{{if $index}}
-{{end}}{{$author}}{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
-
-## VERSION
-
-{{.Version}}{{end}}{{end}}
-
-## COPYRIGHT
-
-{{.Copyright}}
-{{end}}
-`
-
-// SubcommandHelpTemplate contains the modified template for a sub command
-// Note that the weird "|||\n|---|---|" syntax sets up a markdown table with empty headers.
-var mdSubcommandHelpTemplate = `## NAME
-**{{.HelpName}}** -- {{.Usage}}
-
-## USAGE
-
-'''raw
-{{if .UsageText}}{{.UsageText}}{{else}}**{{.HelpName}}** <command>{{if .VisibleFlags}} [options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments]{{end}}{{end}}
-'''
-{{- if .Description}}
-
-## DESCRIPTION
-
-{{.Description}}{{end}}
-
-## COMMANDS
-
-{{range .VisibleCategories}}{{if .Name}}{{.Name}}:{{end}}
-| Name | Usage |
-|---|---|{{range .VisibleCommands}}
-| **[{{join .Names ", "}}]({{.Name}}/)** | {{.Usage}} |{{end}}
-{{end}}{{if .VisibleFlags}}
-
-## OPTIONS
-
-{{range .VisibleFlags}}
-{{.}}
-{{end}}{{end}}
-`
-
-// CommandHelpTemplate contains the modified template for a command
-var mdCommandHelpTemplate = `## NAME
-**{{.HelpName}}** -- {{.Usage}}
-
-## USAGE
-
-'''raw
-{{if .UsageText}}{{.UsageText}}{{else}}**{{.HelpName}}**{{if .VisibleFlags}} [options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments]{{end}}{{end}}
-'''
-{{- if .Category}}
-
-## CATEGORY
-
-{{.Category}}{{end}}{{if .Description}}
-
-## DESCRIPTION
-
-{{.Description}}{{end}}{{if .VisibleFlags}}
-
-## OPTIONS
-
-{{range .VisibleFlags}}
-{{.}}
-{{end}}{{end}}
-`
diff --git a/vendor/go.step.sm/cli-utils/usage/printer.go b/vendor/go.step.sm/cli-utils/usage/printer.go
deleted file mode 100644
index 2fbdeed..0000000
--- a/vendor/go.step.sm/cli-utils/usage/printer.go
+++ /dev/null
@@ -1,234 +0,0 @@
-package usage
-
-import (
- "bytes"
- "fmt"
- "io"
- "regexp"
- "strings"
- "text/template"
- "unicode"
-
- "github.com/urfave/cli"
- md "go.step.sm/cli-utils/pkg/blackfriday"
-)
-
-var sectionRe = regexp.MustCompile(`(?m:^##)`)
-var sectionNameRe = regexp.MustCompile(`(?m:^## [^\n]+)`)
-var indentRe = regexp.MustCompile(`(?m:^:[^\n]+)`)
-var definitionListRe = regexp.MustCompile(`(?m:^[\t ]+\*\*[^\*]+\*\*[^\n]*\s+:[^\n]+)`)
-
-//var sectionRe = regexp.MustCompile(`^## [^\n]*$`)
-
-type frontmatterData struct {
- Data interface{}
- Parent string
- Children []string
-}
-
-// HelpPrinter overwrites cli.HelpPrinter and prints the formatted help to the terminal.
-func HelpPrinter(w io.Writer, templ string, data interface{}) {
- b := helpPreprocessor(w, templ, data, false)
- w.Write(Render(b))
-}
-
-func htmlHelpPrinter(w io.Writer, templ string, data interface{}) []byte {
- b := helpPreprocessor(w, templ, data, true)
- w.Write([]byte(`<html><head><title>step command line documentation</title>`))
- w.Write([]byte(`<link href="/style.css" rel="stylesheet" type="text/css">`))
- w.Write([]byte(`</head><body><div class="wrapper markdown-body command">`))
- html := md.Run(b)
- w.Write(html)
- w.Write([]byte(`</div></body></html>`))
-
- return html
-}
-
-func markdownHelpPrinter(w io.Writer, templ, parent string, data interface{}) {
- b := helpPreprocessor(w, templ, data, true)
-
- frontmatter := frontmatterData{
- Data: data,
- Parent: parent,
- }
-
- if app, ok := data.(*cli.App); ok {
- for _, cmd := range app.Commands {
- frontmatter.Children = append(frontmatter.Children, cmd.Name)
- }
- }
-
- var frontMatterTemplate = `---
-layout: auto-doc
-category: reference
-title: {{.Data.HelpName}}
-menu:
- docs:
-{{- if .Parent}}
- parent: {{.Parent}}
-{{- end }}
-{{- if .Children }}
- children:
-{{- range .Children }}
- - {{.}}
-{{- end }}
-{{- end }}
----
-
-`
- t, err := template.New("frontmatter").Parse(frontMatterTemplate)
- if err != nil {
- panic(err)
- }
- err = t.Execute(w, frontmatter)
- if err != nil {
- panic(err)
- }
- w.Write(b)
-}
-
-func helpPreprocessor(_ io.Writer, templ string, data interface{}, applyRx bool) []byte {
- buf := new(bytes.Buffer)
- cli.HelpPrinterCustom(buf, templ, data, nil)
- //w.Write(buf.Bytes())
- // s := string(markdownify(buf.Bytes()))
- s := markdownify(buf)
- // Move the OPTIONS section to the right place. urfave puts them at the end
- // of the file, we want them to be after POSITIONAL ARGUMENTS, DESCRIPTION,
- // USAGE, or NAME (in that order, depending on which sections exist).
- optLoc := strings.Index(s, "## OPTIONS")
- if optLoc != -1 {
- optEnd := findSectionEnd("OPTIONS", s)
- if optEnd != -1 {
- options := s[optLoc:optEnd]
- s = s[:optLoc] + s[optEnd:]
- if newLoc := findSectionEnd("POSITIONAL ARGUMENTS", s); newLoc != -1 {
- s = s[:newLoc] + options + s[newLoc:]
- } else if newLoc := findSectionEnd("DESCRIPTION", s); newLoc != -1 {
- s = s[:newLoc] + options + s[newLoc:]
- } else if newLoc := findSectionEnd("USAGE", s); newLoc != -1 {
- s = s[:newLoc] + options + s[newLoc:]
- } else if newLoc := findSectionEnd("NAME", s); newLoc != -1 {
- s = s[:newLoc] + options + s[newLoc:]
- } else {
- // Keep it at the end I guess :/.
- s += options
- }
- }
- }
-
- if applyRx {
- // Keep capitalized only the first letter in arguments names.
- s = sectionNameRe.ReplaceAllStringFunc(s, func(s string) string {
- return s[0:4] + strings.ToLower(s[4:])
- })
- // Remove `:` at the start of a line.
- s = indentRe.ReplaceAllStringFunc(s, func(s string) string {
- return strings.TrimSpace(s[1:])
- })
- // Convert lines like:
- // **Foo**
- // : Bar zar ...
- // To:
- // - **Foo**: Bar zar ...
- s = definitionListRe.ReplaceAllStringFunc(s, func(s string) string {
- i := strings.Index(s, "\n")
- j := strings.Index(s, ":")
- return "- " + strings.TrimSpace(s[:i]) + ": " + strings.TrimSpace(s[j+1:])
- })
- }
-
- return []byte(s)
-}
-
-func findSectionEnd(h, s string) int {
- start := strings.Index(s, fmt.Sprintf("## %s", h))
- if start == -1 {
- return start
- }
- nextSection := sectionRe.FindStringIndex(s[start+2:])
- if nextSection == nil {
- return len(s)
- }
- return start + 2 + nextSection[0]
-}
-
-// Convert some stuff that we can't easily write in help files because
-//
-// backticks and raw strings don't mix:
-//
-// - "<foo>" to "`foo`"
-// - "”'" to "```"
-func markdownify(r *bytes.Buffer) string {
- const escapeByte = byte('\\')
- var last byte
- var inCode bool
-
- w := new(bytes.Buffer)
- for {
- b, err := r.ReadByte()
- if err != nil {
- return w.String()
- }
- loop:
- switch b {
- case '<':
- if last != escapeByte && !inCode {
- w.WriteByte('`')
- } else {
- w.WriteByte(b)
- }
- case '>':
- if last != escapeByte && !inCode {
- w.WriteByte('`')
- } else {
- w.WriteByte(b)
- }
- case '\'':
- b1, _ := r.ReadByte()
- b2, _ := r.ReadByte()
- if b1 == b && b2 == b {
- w.WriteString("```")
- if !inCode {
- if n, _, err := r.ReadRune(); err == nil {
- if unicode.IsSpace(n) {
- w.WriteString("shell")
- }
- r.UnreadRune()
- }
- }
- inCode = !inCode
- } else {
- // We can only unread the last one (b2)
- w.WriteByte(b)
- r.UnreadByte()
- b = b1
- last = b
- goto loop
- }
- case '*':
- if inCode {
- if b1, _ := r.ReadByte(); b1 != '*' {
- w.WriteByte(b)
- w.UnreadByte()
- }
- } else {
- w.WriteByte(b)
- }
- case escapeByte:
- if last == escapeByte {
- w.WriteByte(escapeByte)
- b = 0
- } else if n, _, err := r.ReadRune(); err == nil {
- if unicode.IsSpace(n) {
- w.WriteByte(escapeByte)
- }
- r.UnreadRune()
- }
- case 0: // probably because io.EOF
- default:
- w.WriteByte(b)
- }
- last = b
- }
-}
diff --git a/vendor/go.step.sm/cli-utils/usage/renderer.go b/vendor/go.step.sm/cli-utils/usage/renderer.go
deleted file mode 100644
index acc9766..0000000
--- a/vendor/go.step.sm/cli-utils/usage/renderer.go
+++ /dev/null
@@ -1,372 +0,0 @@
-package usage
-
-import (
- "bufio"
- "bytes"
- "fmt"
- "io"
- "regexp"
- "strings"
- "text/tabwriter"
- "unicode"
-
- "github.com/mgutz/ansi"
- md "go.step.sm/cli-utils/pkg/blackfriday"
-)
-
-// Render renders the given data with a custom markdown renderer.
-func Render(b []byte) []byte {
- return md.Run(b, md.WithRenderer(&Renderer{6, 0, nil, nil, false}))
-}
-
-var colorEscapeRe = regexp.MustCompile(`\033\[\d*(;\d*)?m?\]?`)
-var maxLineLength = 80
-
-func stripColors(b []byte) []byte {
- return colorEscapeRe.ReplaceAll(b, []byte(""))
-}
-
-type item struct {
- flags md.ListType
- term []byte
- definitions [][]byte
-}
-
-type list struct {
- items []item
- flags md.ListType
- parent *list
-}
-
-/* TODO: commented because unused
-func (l *list) isUnordered() bool {
- return !l.isOrdered() && !l.isDefinition()
-}
-
-func (l *list) isOrdered() bool {
- return l.flags&md.ListTypeOrdered != 0
-}
-
-func (l *list) containsBlock() bool {
- // TODO: Not sure if we have to check every item or if it gets
- // automatically set on the list?
- return l.flags&md.ListItemContainsBlock != 0
-}
-*/
-
-func (l *list) isDefinition() bool {
- return l.flags&md.ListTypeDefinition != 0
-}
-
-type bufqueue struct {
- w io.Writer
- buf *bytes.Buffer
- next *bufqueue
- mode RenderMode
-}
-
-// RenderMode enumerates different line breaks modes.
-type RenderMode int
-
-const (
- // RenderModeKeepBreaks will keep the line breaks in the docs.
- RenderModeKeepBreaks RenderMode = iota
- // RenderModeBreakLines will automatically wrap the lines.
- RenderModeBreakLines
-)
-
-// Renderer implements a custom markdown renderer for blackfriday.
-type Renderer struct {
- depth int
- listdepth int
- list *list
- out *bufqueue
- inpara bool
-}
-
-func (r *Renderer) write(b []byte) {
- r.out.w.Write(b)
-}
-
-func (r *Renderer) printf(s string, a ...interface{}) {
- fmt.Fprintf(r.out.w, s, a...)
-}
-
-func (r *Renderer) capture(mode RenderMode) {
- buf := new(bytes.Buffer)
- r.out = &bufqueue{buf, buf, r.out, mode}
-}
-
-func (r *Renderer) finishCapture() *bytes.Buffer {
- buf := r.out.buf
- r.out = r.out.next
- return buf
-}
-
-func (r *Renderer) inParagraph() bool {
- return r.inpara
-}
-
-/* TODO: commented because unused
-func (r *Renderer) inList() bool {
- return r.list != nil
-}
-*/
-
-func (r *Renderer) renderParagraphKeepBreaks(buf *bytes.Buffer) {
- scanner := bufio.NewScanner(buf)
- for scanner.Scan() {
- r.printf(strings.Repeat(" ", r.depth)+"%s\n", scanner.Text())
- }
-}
-
-func (r *Renderer) renderParagraphBreakLines(buf *bytes.Buffer, maxlen int) {
- maxlen -= r.depth
- scanner := bufio.NewScanner(buf)
- scanner.Split(bufio.ScanWords)
- line := []string{}
- length := 0
- for scanner.Scan() {
- word := scanner.Text()
- wordLength := len(stripColors([]byte(word)))
- // Print the line if we've got a collection of words over 80 characters, or if
- // we have a single word that is over 80 characters on an otherwise empty line.
- switch {
- case length+wordLength > maxlen:
- r.printf(strings.Repeat(" ", r.depth)+"%s\n", strings.Join(line, " "))
- line = []string{word}
- length = wordLength
- case length == 0 && wordLength > maxlen:
- r.printf(strings.Repeat(" ", r.depth)+"%s\n", word)
- default:
- line = append(line, word)
- length += wordLength + 1 // Plus one for space
- }
- }
- if len(line) > 0 {
- r.printf(strings.Repeat(" ", r.depth)+"%s\n", strings.Join(line, " "))
- }
-}
-
-func (r *Renderer) renderParagraph(buf *bytes.Buffer) {
- switch r.out.mode {
- case RenderModeKeepBreaks:
- r.renderParagraphKeepBreaks(buf)
- case RenderModeBreakLines:
- r.renderParagraphBreakLines(buf, maxLineLength)
- }
-}
-
-// RenderNode implements blackfriday.Renderer interface.
-func (r *Renderer) RenderNode(w io.Writer, node *md.Node, entering bool) md.WalkStatus {
- if r.out == nil {
- r.out = &bufqueue{w, nil, nil, RenderModeBreakLines}
- }
-
- switch node.Type {
- case md.Paragraph:
- // Alternative idea here: call r.RenderNode() with our new buffer as
- // `w`. In the `else` condition here render to the outter buffer and
- // always return md.Terminate. So when we enter a paragraph we start
- // parsing with a new output buffer and capture the output.
- if entering {
- if r.inParagraph() {
- panic("already in paragraph")
- }
- r.inpara = true
- //r.printf(out, "[paragraph:")
- r.capture(r.out.mode)
- } else {
- r.renderParagraph(r.finishCapture())
- // Write a newline unless the parent node is a definition list term.
- if node.Parent.Type != md.Item || node.Parent.ListFlags&md.ListTypeTerm == 0 {
- r.printf("\n")
- }
- r.inpara = false
- //r.printf(w, ":paragraph]")
- }
- case md.Text:
- // TODO: is this necessary? I think all text is in a paragraph.
- if r.inParagraph() {
- r.write(node.Literal)
- } else {
- s := strings.ReplaceAll(string(node.Literal), "\n", "\n"+strings.Repeat(" ", r.depth))
- r.printf(s)
- }
- case md.Heading:
- if entering {
- r.printf(ansi.ColorCode("default+bh"))
- } else {
- r.printf(ansi.Reset)
- r.printf("\n")
- }
- case md.Link:
- if entering {
- r.printf(ansi.ColorCode("default+b"))
- //r.printf("\033[2m") // Dim
- } else {
- r.printf(ansi.Reset)
- }
- case md.Strong:
- if entering {
- r.printf(ansi.ColorCode("default+bh"))
- } else {
- r.printf(ansi.Reset)
- }
- case md.Emph:
- if entering {
- r.printf(ansi.ColorCode("default+u"))
- } else {
- r.printf(ansi.Reset)
- }
- case md.Code:
- r.printf(ansi.ColorCode("default+u"))
- r.write(node.Literal)
- r.printf(ansi.Reset)
- case md.List:
- if entering {
- r.listdepth++
- r.list = &list{[]item{}, node.ListFlags, r.list}
- //r.printf("[list (type %s:", node.ListData.ListFlags)
- } else {
- if r.listdepth > 1 && r.list.isDefinition() {
- w := new(tabwriter.Writer)
- w.Init(r.out.w, 0, 8, 4, ' ', tabwriter.StripEscape)
- for _, item := range r.list.items {
- fmt.Fprint(w, strings.TrimRight(string(item.term), " \n"))
- fmt.Fprint(w, "\n")
- for _, def := range item.definitions {
- fmt.Fprint(w, strings.TrimRight(string(def), " \n"))
- }
- fmt.Fprintf(w, "\n\n")
- }
- w.Flush()
- } else {
- ordered := (node.ListFlags&md.ListTypeOrdered != 0)
- unordered := (node.ListFlags&md.ListTypeOrdered == 0 && node.ListFlags&md.ListTypeDefinition == 0)
- for i, item := range r.list.items {
- if ordered || unordered {
- p := bytes.IndexFunc(item.term, func(r rune) bool { return !unicode.IsSpace(r) })
- switch {
- case ordered: // add numbers on ordered lists
- item.term = append(item.term[:p], append([]byte(fmt.Sprintf("%d. ", i+1)), item.term[p:]...)...)
- case unordered: // add bullet points on unordered lists
- item.term = append(item.term[:p], append([]byte("• "), item.term[p:]...)...)
- }
- }
-
- r.write(item.term)
- for _, def := range item.definitions {
- r.write(def)
- }
- }
- }
- r.listdepth--
- r.list = r.list.parent
- //r.printf(":list]")
- }
- case md.Item:
- incdepth := 4
- //ltype := "normal"
- if node.ListFlags&md.ListTypeTerm != 0 {
- // Nested definition list terms get indented two spaces. Non-nested
- // definition list terms are not indented.
- if r.listdepth > 1 {
- incdepth = 2
- } else {
- incdepth = 0
- }
- //ltype = "dt"
- } else if node.ListFlags&md.ListTypeDefinition != 0 {
- incdepth = 4
- //ltype = "dd"
- }
-
- if entering {
- //fmt.Fprintf(out, "[list item %s:", ltype)
- r.depth += incdepth
- if r.listdepth > 1 && r.list.isDefinition() {
- r.capture(RenderModeKeepBreaks)
- } else {
- r.capture(RenderModeBreakLines)
- }
- if !r.list.isDefinition() || node.ListFlags&md.ListTypeTerm != 0 {
- r.list.items = append(r.list.items, item{node.ListFlags, nil, nil})
- }
- } else {
- //fmt.Fprintf(out, ":list item]")
- r.depth -= incdepth
- buf := r.finishCapture()
- if r.list.isDefinition() && node.ListFlags&md.ListTypeTerm == 0 {
- i := len(r.list.items) - 1
- r.list.items[i].definitions = append(r.list.items[i].definitions, buf.Bytes())
- } else {
- r.list.items[len(r.list.items)-1].term = buf.Bytes()
- }
- }
- case md.Table:
- if entering {
- r.capture(RenderModeKeepBreaks)
- w := new(tabwriter.Writer)
- w.Init(r.out.w, 1, 8, 2, ' ', tabwriter.StripEscape)
- r.out.w = w
- } else {
- r.out.w.(*tabwriter.Writer).Flush()
- buf := r.finishCapture()
- r.renderParagraphKeepBreaks(buf)
- r.printf("\n")
- }
- case md.TableBody:
- // Do nothing.
- case md.TableHead:
- if entering {
- r.capture(r.out.mode)
- } else {
- // Markdown doens't have a way to create a table without headers.
- // We've opted to fix that here by not rendering headers at all if
- // they're empty.
- result := r.finishCapture().Bytes()
- if strings.TrimSpace(string(stripColors(result))) != "" {
- parts := strings.Split(strings.TrimRight(string(result), "\t\n"), "\t")
- for i := 0; i < len(parts); i++ {
- parts[i] = "\xff" + ansi.ColorCode("default+bh") + "\xff" + parts[i] + "\xff" + ansi.Reset + "\xff"
- }
- r.printf(strings.Join(parts, "\t") + "\t\n")
- }
- }
- case md.TableRow:
- if entering {
- r.capture(r.out.mode)
- } else {
- // Escape any colors in the row before writing to the
- // tabwriter, otherwise they screw up the width calculations. The
- // escape character for tabwriter is \xff.
- result := r.finishCapture().Bytes()
- result = colorEscapeRe.ReplaceAll(result, []byte("\xff$0\xff"))
- r.write(result)
- r.printf("\n")
- }
- case md.TableCell:
- if !entering {
- r.printf("\t")
- }
- case md.CodeBlock:
- r.depth += 4
- r.renderParagraphKeepBreaks(bytes.NewBuffer(node.Literal))
- r.printf("\n")
- r.depth -= 4
- case md.Document:
- default:
- r.printf("unknown block %s:", node.Type)
- r.write(node.Literal)
- }
- //w.Write([]byte(fmt.Sprintf("node<%s; %t>", node.Type, entering)))
- //w.Write(node.Literal)
- return md.GoToNext
-}
-
-// RenderHeader implements blackfriday.Renderer interface.
-func (r *Renderer) RenderHeader(io.Writer, *md.Node) {}
-
-// RenderFooter implements blackfriday.Renderer interface.
-func (r *Renderer) RenderFooter(io.Writer, *md.Node) {}
diff --git a/vendor/go.step.sm/cli-utils/usage/report.go b/vendor/go.step.sm/cli-utils/usage/report.go
deleted file mode 100644
index 075fec4..0000000
--- a/vendor/go.step.sm/cli-utils/usage/report.go
+++ /dev/null
@@ -1,148 +0,0 @@
-package usage
-
-import (
- "bytes"
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "regexp"
- "strings"
-
- "golang.org/x/net/html"
-)
-
-// Section keeps track of individual sections
-type Section struct {
- Command string `json:"command"`
- Name string `json:"name"`
- Text string `json:"text"`
- Words int `json:"words"`
- Lines int `json:"lines"`
- Sections []*Section `json:"sections"`
-}
-
-// Report holds together a report of sections
-type Report struct {
- Report []*Section `json:"report"`
-}
-
-// NewReport returns report based on raw
-func NewReport(command string, top []byte) *Report {
- report := Report{}
- report.Process(command, top)
-
- return &report
-}
-
-// Write serializes the report to json
-func (report *Report) Write(w io.Writer) error {
- j, err := json.MarshalIndent(report, "", " ")
-
- if err != nil {
- return err
- }
-
- w.Write(j)
-
- return nil
-}
-
-// Process adds a html based help page to the report
-func (report *Report) Process(command string, raw []byte) error {
- r := bytes.NewBuffer(raw)
- doc, err := html.Parse(r)
-
- if err != nil {
- return err
- }
-
- if doc.FirstChild.Type != html.ElementNode ||
- doc.FirstChild.Data != "html" ||
- doc.FirstChild.FirstChild.NextSibling.Data != "body" {
- return errors.New("error parsing raw html")
- }
-
- body := doc.FirstChild.FirstChild.NextSibling
-
- report.addSection(command, body.FirstChild, nil)
-
- return nil
-}
-
-func (report *Report) addSection(command string, node *html.Node, section *Section) (*html.Node, *Section) {
- if node == nil ||
- node.Type != html.ElementNode ||
- node.Data != "h2" {
- return nil, nil
- }
-
- text, next := report.processNode(node)
- words := strings.Fields(text)
- lines := strings.Split(text, "\n")
-
- s := Section{
- Command: command,
- Name: node.FirstChild.Data,
- Text: text,
- Words: len(words),
- Lines: len(lines),
- }
-
- if section == nil {
- report.Report = append(report.Report, &s)
- return report.addSection(command, next, &s)
- }
-
- section.Sections = append(section.Sections, &s)
- return report.addSection(command, next, section)
-}
-
-func (report *Report) processNode(node *html.Node) (string, *html.Node) {
- text := ""
- current := node.NextSibling
-
- r := regexp.MustCompile(`<[^>]*>`)
-
- for current != nil {
- var buf bytes.Buffer
- w := io.Writer(&buf)
- html.Render(w, current)
-
- notags := r.ReplaceAllString(buf.String(), "")
- clean := strings.TrimSpace(notags)
-
- if len(text) > 0 && len(clean) > 0 {
- text = fmt.Sprintf("%s %s", text, clean)
- } else if len(clean) > 0 {
- text = clean
- }
-
- current = current.NextSibling
- if current == nil {
- return text, nil
- } else if current.Type == html.ElementNode &&
- current.Data == "h2" {
- node = current
- current = nil
- }
- }
-
- return text, node
-}
-
-// PerHeadline returns all sections across commands/pages with the same headline
-func (report *Report) PerHeadline(headline string) []Section {
- var results []Section
- for _, top := range report.Report {
- for _, section := range top.Sections {
- if section.Name != headline {
- continue
- }
-
- results = append(results, *section)
- }
- }
-
- return results
-}
diff --git a/vendor/go.step.sm/cli-utils/usage/usage.go b/vendor/go.step.sm/cli-utils/usage/usage.go
deleted file mode 100644
index 9ed88d9..0000000
--- a/vendor/go.step.sm/cli-utils/usage/usage.go
+++ /dev/null
@@ -1,214 +0,0 @@
-package usage
-
-import (
- "bytes"
- "fmt"
- "html"
- "strconv"
- "strings"
- "text/template"
-)
-
-var usageTextTempl = " {{.Name}}\n {{.Usage}} {{if .Required}}(Required){{else}}(Optional){{end}}{{if .Multiple}} (Multiple can be specified){{end}}\n"
-var templ *template.Template
-
-func init() {
- templ = template.Must(template.New("usageText").Parse(usageTextTempl))
-}
-
-// Argument specifies the Name, Usage, and whether or not an Argument is
-// required or not
-type Argument struct {
- Required bool
- Multiple bool
- Name string
- Usage string
-}
-
-// Decorate returns the name of an Argument and decorates it with notation to
-// indicate whether its required or not
-func (a Argument) Decorate() string {
- name := a.Name
- if a.Multiple {
- name += "(s)..."
- }
- if a.Required {
- return fmt.Sprintf("<%s>", name)
- }
-
- return fmt.Sprintf("[%s]", name)
-}
-
-// Arguments is an array of Argument structs that specify which arguments are
-// accepted by a Command
-type Arguments []Argument
-
-// UsageText returns the value of the UsageText property for a cli.Command for
-// these arguments
-func (args Arguments) UsageText() string {
- var buf bytes.Buffer
- for _, a := range args {
- data := map[string]interface{}{
- "Name": a.Decorate(),
- "Multiple": a.Multiple,
- "Required": a.Required,
- "Usage": a.Usage,
- }
-
- err := templ.Execute(&buf, data)
- if err != nil {
- panic(fmt.Sprintf("Could not generate args template for %s: %s", a.Name, err))
- }
- }
-
- return "\n\n" + buf.String()
-}
-
-// ArgsUsage returns the value of the ArgsUsage property for a cli.Command for
-// these arguments
-func (args Arguments) ArgsUsage() string {
- out := ""
- for i, a := range args {
- out += a.Decorate()
- if i < len(args)-1 {
- out += " "
- }
- }
-
- return out
-}
-
-// AppHelpTemplate contains the modified template for the main app
-var AppHelpTemplate = `## NAME
-**{{.HelpName}}** -- {{.Usage}}
-
-## USAGE
-{{if .UsageText}}{{.UsageText}}{{else}}**{{.HelpName}}**{{if .Commands}} <command>{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}_[arguments]_{{end}}{{end}}{{if .Description}}
-
-## DESCRIPTION
-{{.Description}}{{end}}{{if .VisibleCommands}}
-
-## COMMANDS
-
-{{range .VisibleCategories}}{{if .Name}}{{.Name}}:{{end}}
-|||
-|---|---|{{range .VisibleCommands}}
-| **{{join .Names ", "}}** | {{.Usage}} |{{end}}
-{{end}}{{if .VisibleFlags}}{{end}}
-
-## OPTIONS
-
-{{range $index, $option := .VisibleFlags}}{{if $index}}
-{{end}}{{$option}}
-{{end}}{{end}}{{if .Copyright}}{{if len .Authors}}
-
-## AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
-
-{{range $index, $author := .Authors}}{{if $index}}
-{{end}}{{$author}}{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
-
-## ONLINE
-
-This documentation is available online at https://smallstep.com/docs/cli
-
-## VERSION
-
-{{.Version}}{{end}}{{end}}
-
-## COPYRIGHT
-
-{{.Copyright}}
-
-## FEEDBACK ` +
- html.UnescapeString("&#"+strconv.Itoa(128525)+";") + " " +
- html.UnescapeString("&#"+strconv.Itoa(127867)+";") +
- `
-
-The **step** utility is not instrumented for usage statistics. It does not phone home.
-But your feedback is extremely valuable. Any information you can provide regarding how you’re using **step** helps.
-Please send us a sentence or two, good or bad: **feedback@smallstep.com** or ask in [GitHub Discussions](https://github.com/smallstep/certificates/discussions).
-{{end}}
-`
-
-// SubcommandHelpTemplate contains the modified template for a sub command
-// Note that the weird "|||\n|---|---|" syntax sets up a markdown table with empty headers.
-var SubcommandHelpTemplate = `## NAME
-**{{.HelpName}}** -- {{.Usage}}
-
-## USAGE
-
-{{if .UsageText}}{{.UsageText}}{{else}}**{{.HelpName}}** <command>{{if .VisibleFlags}} _[options]_{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}_[arguments]_{{end}}{{end}}{{if .Description}}
-
-## DESCRIPTION
-
-{{.Description}}{{end}}
-
-## COMMANDS
-
-{{range .VisibleCategories}}{{if .Name}}{{.Name}}:{{end}}
-|||
-|---|---|{{range .VisibleCommands}}
-| **{{join .Names ", "}}** | {{.Usage}} |{{end}}
-{{end}}{{if .VisibleFlags}}
-
-## OPTIONS
-
-{{range .VisibleFlags}}
-{{.}}
-{{end}}{{end}}
-`
-
-// CommandHelpTemplate contains the modified template for a command
-var CommandHelpTemplate = `## NAME
-**{{.HelpName}}** -- {{.Usage}}
-
-## USAGE
-
-{{if .UsageText}}{{.UsageText}}{{else}}**{{.HelpName}}**{{if .VisibleFlags}} _[options]_{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}_[arguments]_{{end}}{{end}}{{if .Category}}
-
-## CATEGORY
-
-{{.Category}}{{end}}{{if .Description}}
-
-## DESCRIPTION
-
-{{.Description}}{{end}}{{if .VisibleFlags}}
-
-## OPTIONS
-
-{{range .VisibleFlags}}
-{{.}}
-{{end}}{{end}}
-`
-
-// FlagNamePrefixer converts a full flag name and its placeholder into the help
-// message flag prefix. This is used by the default FlagStringer.
-//
-// This method clones urflave/cli functionality but adds a new line at the end.
-func FlagNamePrefixer(fullName, placeholder string) string {
- var prefixed string
- parts := strings.Split(fullName, ",")
- for i, name := range parts {
- name = strings.Trim(name, " ")
- prefixed += "**" + prefixFor(name) + name + "**"
-
- if placeholder != "" {
- prefixed += "=" + placeholder
- }
- if i < len(parts)-1 {
- prefixed += ", "
- }
- }
- //return "* " + prefixed + "\n"
- return prefixed + "\n: "
-}
-
-func prefixFor(name string) (prefix string) {
- if len(name) == 1 {
- prefix = "-"
- } else {
- prefix = "--"
- }
-
- return
-}