FString

package
v0.4.3 Latest Latest
Warning

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

Go to latest
Published: Jul 19, 2024 License: MIT Imports: 7 Imported by: 2

Documentation

Index

Constants

View Source
const (
	// DefaultIndentation is the default indentation string.
	DefaultIndentation string = "   "

	// DefaultSeparator is the default separator string.
	DefaultSeparator string = ", "
)

Variables

View Source
var (
	// DefaultIndentationConfig is the default indentation configuration.
	DefaultIndentationConfig *IndentConfig

	// DefaultSeparatorConfig is the default separator configuration.
	DefaultSeparatorConfig *SeparatorConfig

	// DefaultFormatterConfig is the default formatter configuration.
	DefaultFormatterConfig *FormatterConfig
)
View Source
var (
	// NBSP is the non-breaking space rune.
	NBSP rune
)

Functions

func ApplyForm added in v0.3.6

func ApplyForm[T FStringer](form *FormatConfig, trav *Traversor, elem T) error

ApplyForm is a function that applies the format to an element.

Parameters:

  • form: The formatter to use for formatting.
  • trav: The traversor to use for formatting.
  • elem: The element to format.

Returns:

  • error: An error if the formatting fails.

Behaviors:

  • If the traversor is nil, the function does nothing.

func ApplyFormFunc added in v0.3.11

func ApplyFormFunc[T any](form *FormatConfig, trav *Traversor, elem T, f FStringFunc[T]) error

ApplyFormFunc is a function that applies the format to an element.

Parameters:

  • form: The formatter to use for formatting.
  • trav: The traversor to use for formatting.
  • elem: The element to format.

Returns:

  • error: An error if the formatting fails.

Behaviors:

  • If the traversor is nil, the function does nothing.

func ApplyFormMany added in v0.3.6

func ApplyFormMany[T FStringer](form *FormatConfig, trav *Traversor, elems []T) error

ApplyFormMany is a function that applies the format to multiple elements at once.

Parameters:

  • form: The formatter to use for formatting.
  • trav: The traversor to use for formatting.
  • elems: The elements to format.

Returns:

  • error: An error if type Errors.ErrAt if the formatting fails on a specific element.

Behaviors:

  • If the traversor is nil, the function does nothing.

func ApplyFormManyFunc added in v0.3.11

func ApplyFormManyFunc[T any](form *FormatConfig, trav *Traversor, elems []T, f FStringFunc[T]) error

ApplyFormManyFunc is a function that applies the format to multiple elements at once.

Parameters:

  • form: The formatter to use for formatting.
  • trav: The traversor to use for formatting.
  • elems: The elements to format.

Returns:

  • error: An error if type Errors.ErrAt if the formatting fails on a specific element.

Behaviors:

  • If the traversor is nil, the function does nothing.

func ApplyFuncMany added in v0.3.6

func ApplyFuncMany[T any](trav *Traversor, f FStringFunc[T], elems []T) error

ApplyFuncMany applies a format function to the StdPrinter.

Parameters:

  • p: The StdPrinter to use.
  • f: The function to apply.
  • elems: The elements to apply the function to.

Returns:

  • error: An error if the function fails.

Errors:

  • *ErrInvalidParameter: If the StdPrinter is nil.
  • *Errors.ErrAt: If an error occurs on a specific element.
  • any error returned by the function.

func ApplyMany added in v0.3.6

func ApplyMany[T FStringer](trav *Traversor, elems []T) error

ApplyMany applies a format to a stringer.

Parameters:

  • p: The StdPrinter to use.
  • elems: The elements to format.

Returns:

  • error: An error if the formatting fails.

Errors:

  • *ErrInvalidParameter: If the StdPrinter is nil.
  • *ErrFinalization: If the finalization of the page fails.
  • *Errors.ErrAt: If an error occurs on a specific element.

Behaviors:

  • If the formatter is nil, the function uses the nil formatter.
  • If an element is nil, the function skips the element.
  • If all elements are nil, the function does nothing.

func ApplyTravFunc added in v0.3.6

func ApplyTravFunc[T any](trav *Traversor, elem T, f FStringFunc[T]) error

ApplyTravFunc applies a function to the printer. Useful for when you want to apply a function that does not implement the FStringer interface.

Parameters:

  • trav: The traversor to use.
  • elem: The element to apply the function to.
  • f: The function to apply.

Returns:

  • error: An error if the function fails.

Errors:

  • *ErrFinalization: If the finalization of the page fails.
  • any error returned by the function.

func ApplyTravFuncMany added in v0.3.6

func ApplyTravFuncMany[T any](trav *Traversor, f FStringFunc[T], elems []T) error

ApplyTravFuncMany applies a function to the printer. Useful for when you want to apply a function that does not implement the FStringer interface.

Parameters:

  • trav: The traversor to use.
  • f: The function to apply.
  • elems: The elements to apply the function to.

Returns:

  • error: An error if the function fails.

Errors:

  • *ErrFinalization: If the finalization of the page fails.
  • *Errors.ErrAt: If an error occurs on a specific element.
  • any error returned by the function.

func FStringArray added in v0.3.8

func FStringArray(format *FormatConfig, values []string) (string, error)

FStringArray generates a formatted string representation of an array-like object.

Parameters:

  • format: The format to use for printing.
  • values: The values to print.

Returns:

  • string: The formatted string.
  • error: An error if the printing fails.

Behaviors:

  • If the format is nil, the function uses ArrayLikeFormat.

func NewStdPrinter added in v0.3.9

func NewStdPrinter(form *FormatConfig) (*StdPrinter, *Traversor)

NewStdPrinter creates a new StdPrinter.

Parameters:

  • form: The formatter to use.

Returns:

  • *StdPrinter: The new StdPrinter.
  • *Traversor: The traversor of the StdPrinter.

Behaviors:

  • If the formatter is nil, the function uses the default formatter.

func NewStdPrinterFromConfig added in v0.3.9

func NewStdPrinterFromConfig(opts ...uc.Copier) (*StdPrinter, *Traversor)

NewStdPrinterFromConfig creates a new StdPrinter from a configuration.

Parameters:

  • opts: The configuration to use.

Returns:

  • *StdPrinter: The new StdPrinter.
  • *Traversor: The traversor of the StdPrinter.

Behaviors:

  • If the configuration is nil, the function uses the default configuration.
  • Panics if an invalid configuration type is given (i.e., not IndentConfig, DelimiterConfig, or SeparatorConfig).

func Sfprint added in v0.3.9

func Sfprint(form *FormatConfig, a ...interface{}) ([][][][]string, error)

Sfprint prints a formatted string.

Parameters:

  • form: The formatter to use.
  • a: The elements to print.

Returns:

  • [][][][]string: The pages of the formatted strings.
  • error: An error if the printing fails.

Behaviors:

  • If the formatter is nil, the function uses the default formatter.

func Sfprintf added in v0.3.9

func Sfprintf(form *FormatConfig, format string, a ...interface{}) ([][][][]string, error)

Sfprintf prints a formatted string.

Parameters:

  • form: The formatter to use.
  • format: The format string.
  • a: The elements to print.

Returns:

  • [][][][]string: The pages of the formatted strings.
  • error: An error if the printing fails.

Behaviors:

  • If the formatter is nil, the function uses the default formatter.

func Sfprintln added in v0.3.9

func Sfprintln(form *FormatConfig, a ...interface{}) ([][][][]string, error)

Sfprintln prints a formatted string with a newline.

Parameters:

  • form: The formatter to use.
  • a: The elements to print.

Returns:

  • [][][][]string: The pages of the formatted strings.
  • error: An error if the printing fails.

Behaviors:

  • If the formatter is nil, the function uses the default formatter.

func Sprint added in v0.3.9

func Sprint(form *FormatConfig, strs ...string) ([][][][]string, error)

Sprint prints strings.

Parameters:

  • form: The formatter to use.
  • strs: The strings to print.

Returns:

  • [][][][]string: The pages of the formatted strings.
  • error: An error if the printing fails.

Behaviors:

  • If the formatter is nil, the function uses the default formatter.

func SprintFString added in v0.3.9

func SprintFString[T FStringer](form *FormatConfig, elem T) ([][][][]string, error)

SprintFString prints a formatted string.

Parameters:

  • form: The formatter to use.
  • elem: The element to print.

Returns:

  • [][][][]string: The pages of the formatted string.
  • error: An error if the printing fails.

Behaviors:

  • If the formatter is nil, the function uses the default formatter.

func Sprintj added in v0.3.9

func Sprintj(form *FormatConfig, sep string, strs ...string) ([][][][]string, error)

Sprintj prints a joined string.

Parameters:

  • form: The formatter to use.
  • sep: The separator to use.
  • strs: The strings to join.

Returns:

  • [][][][]string: The pages of the formatted strings.
  • error: An error if the printing fails.

Behaviors:

  • If the formatter is nil, the function uses the default formatter.

func Sprintjln added in v0.3.9

func Sprintjln(form *FormatConfig, sep string, lines ...string) ([][][][]string, error)

Sprintjln prints a joined string with a newline.

Parameters:

  • form: The formatter to use.
  • sep: The separator to use.
  • lines: The lines to join.

Returns:

  • [][][][]string: The pages of the formatted strings.
  • error: An error if the printing fails.

Behaviors:

  • If the formatter is nil, the function uses the default formatter.

func Sprintln added in v0.3.9

func Sprintln(form *FormatConfig, lines ...string) ([][][][]string, error)

Sprintln prints a string with a newline.

Parameters:

  • form: The formatter to use.
  • lines: The lines to print.

Returns:

  • [][][][]string: The pages of the formatted strings.
  • error: An error if the printing fails.

Behaviors:

  • If the formatter is nil, the function uses the default formatter.

func Stringfy added in v0.3.6

func Stringfy(doc [][][][]string, spacing int) []string

Stringify converts a formatted string to a string.

Parameters:

  • doc: The formatted string.
  • spacing: The spacing to use for the string.

Returns:

  • [][]string: The stringified formatted string.

Behaviors:

  • If the spacing is less than or equal to 0, the spacing is set to 1.

Types

type ConfigOption added in v0.3.6

type ConfigOption func(*FormatConfig)

ConfigOption is a type that represents a configuration option for a formatter.

func WithLeftDelimiter added in v0.3.11

func WithLeftDelimiter(str string) ConfigOption

WithLeftDelimiter is a function that modifies the left delimiter of the formatter.

Parameters:

  • str: The string to use as the left delimiter.

Returns:

  • ConfigOption: The configuration option.

Behaviors:

  • If str is empty, then the left delimiter is removed.

func WithModifiedIndent added in v0.3.6

func WithModifiedIndent(by int) ConfigOption

WithModifiedIndent is a function that modifies the indentation level of the formatter by a specified amount relative to the current indentation level.

Parameters:

  • by: The amount by which to modify the indentation level.

Returns:

  • ConfigOption: The configuration option.

Behaviors:

  • Negative values will decrease the indentation level while positive values will increase it. If the value is 0, then nothing is done and when the indentation level is 0, it is not decreased.

func WithRightDelimiter added in v0.3.19

func WithRightDelimiter(str string) ConfigOption

WithRightDelimiter is a function that modifies the right delimiter of the formatter.

Parameters:

  • str: The string to use as the right delimiter.

Returns:

  • ConfigOption: The configuration option.

Behaviors:

  • If str is empty, then the right delimiter is removed.

type DelimiterConfig

type DelimiterConfig struct {
	// contains filtered or unexported fields
}

DelimiterConfig is a type that represents the configuration for delimiters.

func NewDelimiterConfig

func NewDelimiterConfig(str string, isInline, left bool) *DelimiterConfig

NewDelimiterConfig is a function that creates a new delimiter configuration.

Parameters:

  • value: The string that is used as a delimiter.
  • inline: Whether the delimiter should be inline.

Returns:

  • *DelimiterConfig: A pointer to the new delimiter configuration.

Default values:

  • ==DelimiterConfig==
  • Value: ""
  • Inline: true

func (*DelimiterConfig) Copy added in v0.3.6

func (c *DelimiterConfig) Copy() uc.Copier

Copy implements the uc.Copier interface.

type FStringFunc added in v0.3.6

type FStringFunc[T any] func(trav *Traversor, elem T) error

FStringFunc is a function that generates a formatted string representation of an object.

Parameters:

  • trav: The traversor to use for printing.
  • elem: The element to print.

Returns:

  • error: An error if there was a problem generating the string.

type FStringer

type FStringer interface {
	// FString returns a string representation of the object.
	//
	// Parameters:
	//   - trav: The traversor to use for printing.
	//   - opts: The options to use for printing.
	//
	// Returns:
	//   - error: An error if there was a problem generating the string.
	FString(trav *Traversor, opts ...Option) error
}

FStringer is an interface that defines the behavior of a type that can be converted to a string representation.

type FormatConfig added in v0.3.6

type FormatConfig struct {
	// contains filtered or unexported fields
}

FormatterConfig is a type that represents a configuration for the general formatter.

var (
	// ArrayLikeFormat is the default options for an array-like object.
	// [1, 2, 3]
	ArrayLikeFormat *FormatConfig
)
var (
	// DefaultFormatter is the default formatter.
	//
	// ==IndentConfig==
	//   - DefaultIndentationConfig
	//
	// ==SeparatorConfig==
	//   - DefaultSeparatorConfig
	//
	// ==DelimiterConfig (Left and Right)==
	//   - Nil (no delimiters are used by default)
	DefaultFormatter *FormatConfig
)

func MergeForm added in v0.3.6

func MergeForm(form1, form2 *FormatConfig) *FormatConfig

MergeForm is a function that merges the given formatter with the current one; prioritizing the values of the first formatter.

Parameters:

  • form1: The first formatter.
  • form2: The second formatter.

Returns:

  • *FormatConfig: A pointer to the new formatter.

func NewFormatter added in v0.3.6

func NewFormatter(options ...uc.Copier) *FormatConfig

NewFormatter is a function that creates a new formatter with the given configuration.

Parameters:

  • options: The configuration for the formatter.

Returns:

  • form: A pointer to the new formatter.

Behaviors:

  • The function panics if an invalid configuration type is given. (i.e., not IndentConfig, DelimiterConfig, or SeparatorConfig)
  • If no formatter configuration is given, the default formatter configuration is used.

func (*FormatConfig) Copy added in v0.3.35

func (form *FormatConfig) Copy() uc.Copier

Copy implements the uc.Copier interface.

func (*FormatConfig) GetSpacingSize added in v0.3.27

func (form *FormatConfig) GetSpacingSize() int

GetIndentationSize is a function that returns the indentation size of the formatter.

Returns:

  • int: The indentation size.

func (*FormatConfig) GetTabSize added in v0.3.27

func (form *FormatConfig) GetTabSize() int

GetTabSize is a function that returns the tab size of the formatter.

Returns:

  • int: The tab size.

type FormatterConfig added in v0.3.27

type FormatterConfig struct {
	// contains filtered or unexported fields
}

FormatterConfig is a type that represents the configuration for formatting.

func NewFormatterConfig added in v0.3.27

func NewFormatterConfig(tabSize, spacingSize int) *FormatterConfig

NewFormatterConfig is a function that creates a new formatter configuration.

Parameters:

  • tabSize: The size of the tab.
  • spacingSize: The size of the spacing.

Returns:

  • *FormatterConfig: A pointer to the new formatter configuration.

Default values:

	==FormatterConfig==
  - TabSize: 3
  - SpacingSize: 1

Behaviors:

  • If tabSize is less than 1, it is set to 3.
  • If spacingSize is less than 1, it is set to 1.

func (*FormatterConfig) Copy added in v0.3.27

func (c *FormatterConfig) Copy() uc.Copier

Copy implements the uc.Copier interface.

type IndentConfig

type IndentConfig struct {
	// contains filtered or unexported fields
}

IndentConfig is a type that represents the configuration for indentation.

func NewIndentConfig

func NewIndentConfig(str string, initialLevel int) *IndentConfig

NewIndentConfig is a function that creates a new indentation configuration.

Parameters:

  • indentation: The string that is used for indentation.
  • initialLevel: The initial indentation level.

Returns:

  • *IndentConfig: A pointer to the new indentation configuration.

Default values:

	==IndentConfig==
  - Indentation: DefaultIndentation
  - InitialLevel: 0

Behaviors:

  • If initialLevel is negative, it is set to 0.
  • If indentation is empty, it is set to DefaultIndentation.

func (*IndentConfig) Copy added in v0.3.6

func (c *IndentConfig) Copy() uc.Copier

Copy implements the uc.Copier interface.

func (*IndentConfig) GetIndentStr added in v0.3.6

func (c *IndentConfig) GetIndentStr() string

GetIndentStr is a method that returns the indentation string.

Returns:

  • string: The indentation string.

func (*IndentConfig) GetIndentation added in v0.3.6

func (c *IndentConfig) GetIndentation() string

GetIndentation is a method that returns the applied indentation.

Returns:

  • string: The applied indentation.

type Option added in v0.3.13

type Option func(Settinger)

Option is a function that sets the settings for the formatting functions.

Parameters:

  • Settinger: The settings to set.

type SeparatorConfig

type SeparatorConfig struct {
	// contains filtered or unexported fields
}

SeparatorConfig is a type that represents the configuration for separators.

func NewSeparator

func NewSeparator(sep string, includeFinal bool) *SeparatorConfig

NewSeparator is a function that creates a new separator configuration.

Parameters:

  • separator: The string that is used as a separator.
  • hasFinalSeparator: Whether the last element should have a separator.

Returns:

  • *SeparatorConfig: A pointer to the new separator configuration.

Default values:

	==SeparatorConfig==
  - Separator: DefaultSeparator
  - HasFinalSeparator: false

Behaviors:

  • If separator is empty, it is set to DefaultSeparator.

func (*SeparatorConfig) Copy added in v0.3.6

func (c *SeparatorConfig) Copy() uc.Copier

Copy implements the uc.Copier interface.

type Settinger added in v0.3.13

type Settinger interface{}

Settinger is an interface that represents the settings for the formatting functions.

type SimplePrinter added in v0.3.5

type SimplePrinter[T comparable] struct {
	// contains filtered or unexported fields
}

SimplePrinter is a simple printer that prints a value with a name.

func NewSimplePrinter added in v0.3.5

func NewSimplePrinter[T comparable](name string, value T, fn func(T) (string, error)) *SimplePrinter[T]

NewSimplePrinter creates a new SimplePrinter with the provided name and value.

Parameters:

  • name: The name of the value.
  • value: The value to print.
  • fn: The function to use to convert the value to a string.

Returns:

  • *SimplePrinter: The new SimplePrinter.

Behaviors:

  • If the function is nil, the function uses uc.StringOf to convert the value to a string.

func (*SimplePrinter[T]) FString added in v0.3.5

func (sp *SimplePrinter[T]) FString(trav *Traversor) error

FString generates a formatted string representation of a SimplePrinter.

Format:

<name>: <value>

Parameters:

  • trav: The traversor to use for printing.

Returns:

  • error: An error if the printing fails.

type StdPrinter added in v0.3.9

type StdPrinter struct {
	// contains filtered or unexported fields
}

StdPrinter is a type that represents a formatted string.

func (*StdPrinter) Clean added in v0.3.9

func (p *StdPrinter) Clean()

Cleanup implements the Cleaner interface.

func (*StdPrinter) GetPages added in v0.3.9

func (p *StdPrinter) GetPages() [][][][]string

GetPages returns the pages of the StdPrinter.

Returns:

  • [][][][]string: The pages of the StdPrinter.

type Traversor added in v0.2.41

type Traversor struct {
	// contains filtered or unexported fields
}

Traversor is a type that represents a traversor for a formatted string.

func (*Traversor) AcceptLine added in v0.3.6

func (trav *Traversor) AcceptLine()

AcceptLine is a function that accepts the current line of the traversor.

Behaviors:

  • This also accepts the current word if any.

func (*Traversor) AcceptWord added in v0.3.6

func (trav *Traversor) AcceptWord()

AcceptWord is a function that, if there is any in-progress word, then said word is added to the source.

func (*Traversor) AddJoinedLine added in v0.3.5

func (trav *Traversor) AddJoinedLine(sep string, fields ...string) error

AddJoinedLine adds a joined line to the traversor. This is a more efficient way to do the same as AddLine(strings.Join(fields, sep)).

Parameters:

  • sep: The separator to use.
  • fields: The fields to join.

Returns:

  • error: An error of type *Errors.ErrInvalidRuneAt if there is an invalid rune in the line.

Behaviors:

  • If fields is empty, then nothing is done.

func (*Traversor) AddLine added in v0.3.5

func (trav *Traversor) AddLine(line string) error

AddLine adds a line to the traversor. If there is any in-progress line, then the line is appended to the line before accepting it. Otherwise, a new line with the line is added to the source.

Parameters:

  • line: The line to add.

Returns:

  • error: An error of type *Errors.ErrAt if there is an error adding the line.

Behaviors:

  • If line is empty, then an empty line is added to the source.

func (*Traversor) AddLines added in v0.2.41

func (trav *Traversor) AddLines(lines []string) error

AddLines adds multiple lines to the traversor in a more efficient way than adding each line individually.

Parameters:

  • lines: The lines to add.

Returns:

  • error: An error of type *Errors.ErrAt if there is an error adding a line.

Behaviors:

  • If there are no lines, then nothing is done.

func (*Traversor) AppendJoinedString added in v0.3.5

func (trav *Traversor) AppendJoinedString(sep string, fields ...string) error

AppendJoinedString appends a joined string to the half-line of the traversor.

Parameters:

  • sep: The separator to use.
  • fields: The fields to join.

Returns:

  • error: An error of type *Errors.ErrInvalidRuneAt if there is an invalid rune in the string.

Behaviors:

  • This is equivalent to calling AppendString(strings.Join(fields, sep)).

func (*Traversor) AppendRune added in v0.3.5

func (trav *Traversor) AppendRune(r rune) error

AppendRune appends a rune to the half-line of the traversor.

Parameters:

  • r: The rune to append.

Returns:

  • error: An error if the rune could not be appended.

Errors:

  • *Errors.ErrInvalidRune: If the rune is invalid.

Behaviors:

  • If the half-line is nil, then a new half-line is created.

func (*Traversor) AppendString added in v0.2.41

func (trav *Traversor) AppendString(str string) error

AppendString appends a string to the half-line of the traversor.

Parameters:

  • str: The string to append.

Returns:

  • error: An error of type *Errors.ErrInvalidRuneAt if there is an invalid rune in the string.

Behaviors:

  • IF str is empty: nothing is done.

func (*Traversor) AppendStrings added in v0.2.41

func (trav *Traversor) AppendStrings(strs []string) error

AppendStrings appends multiple strings to the half-line of the traversor.

Parameters:

  • strs: The strings to append.

Returns:

  • error: An error of type *Errors.ErrAt if there is an error appending a string.

Behaviors:

  • This is equivalent to calling AppendString for each string in strs but more efficient.

func (*Traversor) Clean added in v0.3.9

func (trav *Traversor) Clean()

Cleanup implements the Cleaner interface.

func (*Traversor) EmptyLine added in v0.2.41

func (trav *Traversor) EmptyLine()

EmptyLine adds an empty line to the traversor. This is a more efficient way to do the same as AddLine("") or AddLines([]string{""}).

Behaviors:

  • If the half-line is not empty, then the half-line is added to the source (half-line is reset) and an empty line is added to the source.

func (*Traversor) GetConfig added in v0.3.6

func (trav *Traversor) GetConfig(options ...ConfigOption) *FormatConfig

GetConfig is a method that returns a copy of the configuration of the traversor.

Parameters:

  • options: The options to apply to the configuration.

Returns:

  • FormatConfig: A copy of the configuration of the traversor.

func (*Traversor) Lock added in v0.3.32

func (trav *Traversor) Lock()

Lock locks the traversor. Be aware of deadlocks.

func (*Traversor) Print added in v0.3.6

func (trav *Traversor) Print(a ...interface{}) error

Print is a function that writes to the traversor using the fmt.Fprint function.

Parameters:

  • a: The arguments to write.

func (*Traversor) Printf added in v0.3.6

func (trav *Traversor) Printf(format string, a ...interface{}) error

Printf is a function that writes to the traversor using the fmt.Fprintf function.

Parameters:

  • format: The format string.
  • a: The arguments to write.

func (*Traversor) Println added in v0.3.6

func (trav *Traversor) Println(a ...interface{}) error

Println is a function that writes to the traversor using the fmt.Fprintln function.

Parameters:

  • a: The arguments to write.

func (*Traversor) Unlock added in v0.3.32

func (trav *Traversor) Unlock()

Unlock unlocks the traversor. Be aware of deadlocks.

func (*Traversor) Write added in v0.3.6

func (trav *Traversor) Write(p []byte) (int, error)

Write implements the io.Writer interface for the traversor.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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