ast

package
v0.0.0-...-a456ec0 Latest Latest
Warning

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

Go to latest
Published: May 18, 2023 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package ast declares types representing a JavaScript AST.

# Warning The parser and AST interfaces are still works-in-progress (particularly where node types are concerned) and may change in the future.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Walk

func Walk(v Visitor, n Node)

Walk traverses an AST in depth-first order: It starts by calling v.Enter(node); node must not be nil. If the visitor v returned by v.Enter(node) is not nil, Walk is invoked recursively with visitor v for each of the non-nil children of node, followed by a call of v.Exit(node).

Types

type ArrayLiteral

type ArrayLiteral struct {
	LeftBracket  file.Idx
	RightBracket file.Idx
	Value        []Expression
}

ArrayLiteral represents an array literal.

func (*ArrayLiteral) Idx0

func (al *ArrayLiteral) Idx0() file.Idx

Idx0 implements Node.

func (*ArrayLiteral) Idx1

func (al *ArrayLiteral) Idx1() file.Idx

Idx1 implements Node.

type AssignExpression

type AssignExpression struct {
	Operator token.Token
	Left     Expression
	Right    Expression
}

AssignExpression represents an assignment expression.

func (*AssignExpression) Idx0

func (ae *AssignExpression) Idx0() file.Idx

Idx0 implements Node.

func (*AssignExpression) Idx1

func (ae *AssignExpression) Idx1() file.Idx

Idx1 implements Node.

type BadExpression

type BadExpression struct {
	From file.Idx
	To   file.Idx
}

BadExpression represents a bad expression.

func (*BadExpression) Idx0

func (be *BadExpression) Idx0() file.Idx

Idx0 implements Node.

func (*BadExpression) Idx1

func (be *BadExpression) Idx1() file.Idx

Idx1 implements Node.

type BadStatement

type BadStatement struct {
	From file.Idx
	To   file.Idx
}

BadStatement represents a bad statement.

func (*BadStatement) Idx0

func (bs *BadStatement) Idx0() file.Idx

Idx0 implements Node.

func (*BadStatement) Idx1

func (bs *BadStatement) Idx1() file.Idx

Idx1 implements Node.

type BinaryExpression

type BinaryExpression struct {
	Operator   token.Token
	Left       Expression
	Right      Expression
	Comparison bool
}

BinaryExpression represents a binary expression.

func (*BinaryExpression) Idx0

func (be *BinaryExpression) Idx0() file.Idx

Idx0 implements Node.

func (*BinaryExpression) Idx1

func (be *BinaryExpression) Idx1() file.Idx

Idx1 implements Node.

type BlockStatement

type BlockStatement struct {
	LeftBrace  file.Idx
	List       []Statement
	RightBrace file.Idx
}

BlockStatement represents a block statement.

func (*BlockStatement) Idx0

func (bs *BlockStatement) Idx0() file.Idx

Idx0 implements Node.

func (*BlockStatement) Idx1

func (bs *BlockStatement) Idx1() file.Idx

Idx1 implements Node.

type BooleanLiteral

type BooleanLiteral struct {
	Idx     file.Idx
	Literal string
	Value   bool
}

BooleanLiteral represents a boolean expression.

func (*BooleanLiteral) Idx0

func (bl *BooleanLiteral) Idx0() file.Idx

Idx0 implements Node.

func (*BooleanLiteral) Idx1

func (bl *BooleanLiteral) Idx1() file.Idx

Idx1 implements Node.

type BracketExpression

type BracketExpression struct {
	Left         Expression
	Member       Expression
	LeftBracket  file.Idx
	RightBracket file.Idx
}

BracketExpression represents a bracketed expression.

func (*BracketExpression) Idx0

func (be *BracketExpression) Idx0() file.Idx

Idx0 implements Node.

func (*BracketExpression) Idx1

func (be *BracketExpression) Idx1() file.Idx

Idx1 implements Node.

type BranchStatement

type BranchStatement struct {
	Idx   file.Idx
	Token token.Token
	Label *Identifier
}

BranchStatement represents a branch statement.

func (*BranchStatement) Idx0

func (bs *BranchStatement) Idx0() file.Idx

Idx0 implements Node.

func (*BranchStatement) Idx1

func (bs *BranchStatement) Idx1() file.Idx

Idx1 implements Node.

type CallExpression

type CallExpression struct {
	Callee           Expression
	LeftParenthesis  file.Idx
	ArgumentList     []Expression
	RightParenthesis file.Idx
}

CallExpression represents a call expression.

func (*CallExpression) Idx0

func (ce *CallExpression) Idx0() file.Idx

Idx0 implements Node.

func (*CallExpression) Idx1

func (ce *CallExpression) Idx1() file.Idx

Idx1 implements Node.

type CaseStatement

type CaseStatement struct {
	Case       file.Idx
	Test       Expression
	Consequent []Statement
}

CaseStatement represents a case statement.

func (*CaseStatement) Idx0

func (cs *CaseStatement) Idx0() file.Idx

Idx0 implements Node.

func (*CaseStatement) Idx1

func (cs *CaseStatement) Idx1() file.Idx

Idx1 implements Node.

type CatchStatement

type CatchStatement struct {
	Catch     file.Idx
	Parameter *Identifier
	Body      Statement
}

CatchStatement represents a catch statement.

func (*CatchStatement) Idx0

func (cs *CatchStatement) Idx0() file.Idx

Idx0 implements Node.

func (*CatchStatement) Idx1

func (cs *CatchStatement) Idx1() file.Idx

Idx1 implements Node.

type Comment

type Comment struct {
	Begin    file.Idx
	Text     string
	Position CommentPosition
}

Comment contains the data of the comment.

func NewComment

func NewComment(text string, idx file.Idx) *Comment

NewComment creates a new comment.

func (Comment) String

func (c Comment) String() string

String returns a stringified version of the comment.

type CommentMap

type CommentMap map[Node][]*Comment

CommentMap is the data structure where all found comments are stored.

func (CommentMap) AddComment

func (cm CommentMap) AddComment(node Node, comment *Comment)

AddComment adds a single comment to the map.

func (CommentMap) AddComments

func (cm CommentMap) AddComments(node Node, comments []*Comment, position CommentPosition)

AddComments adds a slice of comments, given a node and an updated position.

func (CommentMap) MoveComments

func (cm CommentMap) MoveComments(from, to Node, position CommentPosition)

MoveComments moves comments with a given position from a node to another.

func (CommentMap) Size

func (cm CommentMap) Size() int

Size returns the size of the map.

type CommentPosition

type CommentPosition int

CommentPosition determines where the comment is in a given context.

const (

	// LEADING is before the pertinent expression.
	LEADING CommentPosition
	// TRAILING is after the pertinent expression.
	TRAILING
	// KEY is before a key in an object.
	KEY
	// COLON is after a colon in a field declaration.
	COLON
	// FINAL is the final comments in a block, not belonging to a specific expression or the comment after a trailing , in an array or object literal.
	FINAL
	// IF is after an if keyword.
	IF
	// WHILE is after a while keyword.
	WHILE
	// DO is after do keyword.
	DO
	// FOR is after a for keyword.
	FOR
	// WITH is after a with keyword.
	WITH
	// TBD is unknown.
	TBD
)

Available comment positions.

func (CommentPosition) String

func (cp CommentPosition) String() string

String returns a stringified version of the position.

type Comments

type Comments struct {
	// CommentMap is a reference to the parser comment map
	CommentMap CommentMap
	// Comments lists the comments scanned, not linked to a node yet
	Comments []*Comment
	// Current is node for which comments are linked to
	Current Expression
	// contains filtered or unexported fields
}

Comments defines the current view of comments from the parser.

func NewComments

func NewComments() *Comments

NewComments returns a new Comments.

func (*Comments) AddComment

func (c *Comments) AddComment(comment *Comment)

AddComment adds a comment to the view. Depending on the context, comments are added normally or as post line break.

func (*Comments) AfterBlock

func (c *Comments) AfterBlock()

AfterBlock will mark the context as being after a block.

func (*Comments) AtLineBreak

func (c *Comments) AtLineBreak()

AtLineBreak will mark a line break.

func (*Comments) Fetch

func (c *Comments) Fetch() []*Comment

Fetch returns all the currently scanned comments.

func (*Comments) FetchAll

func (c *Comments) FetchAll() []*Comment

FetchAll returns all the currently scanned comments, including those from the next line.

func (*Comments) MarkComments

func (c *Comments) MarkComments(position CommentPosition)

MarkComments will mark the found comments as the given position.

func (*Comments) MarkPrimary

func (c *Comments) MarkPrimary()

MarkPrimary will mark the context as processing a primary expression.

func (*Comments) PostProcessNode

func (c *Comments) PostProcessNode(node Node)

PostProcessNode applies all found comments to the given node.

func (*Comments) ResetLineBreak

func (c *Comments) ResetLineBreak()

ResetLineBreak marks the beginning of a new statement.

func (*Comments) SetExpression

func (c *Comments) SetExpression(node Expression)

SetExpression sets the current expression. It is applied the found comments, unless the previous expression has not been unset. It is skipped if the node is already set or if it is a part of the previous node.

func (*Comments) String

func (c *Comments) String() string

func (*Comments) Unset

func (c *Comments) Unset()

Unset the current node and apply the comments to the current expression. Resets context variables.

type ConditionalExpression

type ConditionalExpression struct {
	Test       Expression
	Consequent Expression
	Alternate  Expression
}

ConditionalExpression represents a conditional expression.

func (*ConditionalExpression) Idx0

func (ce *ConditionalExpression) Idx0() file.Idx

Idx0 implements Node.

func (*ConditionalExpression) Idx1

func (ce *ConditionalExpression) Idx1() file.Idx

Idx1 implements Node.

type DebuggerStatement

type DebuggerStatement struct {
	Debugger file.Idx
}

DebuggerStatement represents a debugger statement.

func (*DebuggerStatement) Idx0

func (ds *DebuggerStatement) Idx0() file.Idx

Idx0 implements Node.

func (*DebuggerStatement) Idx1

func (ds *DebuggerStatement) Idx1() file.Idx

Idx1 implements Node.

type Declaration

type Declaration interface {
	// contains filtered or unexported methods
}

Declaration is implemented by type which represent declarations.

type DoWhileStatement

type DoWhileStatement struct {
	Do   file.Idx
	Test Expression
	Body Statement
}

DoWhileStatement represents a do while statement.

func (*DoWhileStatement) Idx0

func (dws *DoWhileStatement) Idx0() file.Idx

Idx0 implements Node.

func (*DoWhileStatement) Idx1

func (dws *DoWhileStatement) Idx1() file.Idx

Idx1 implements Node.

type DotExpression

type DotExpression struct {
	Left       Expression
	Identifier *Identifier
}

DotExpression represents a dot expression.

func (*DotExpression) Idx0

func (de *DotExpression) Idx0() file.Idx

Idx0 implements Node.

func (*DotExpression) Idx1

func (de *DotExpression) Idx1() file.Idx

Idx1 implements Node.

type EmptyExpression

type EmptyExpression struct {
	Begin file.Idx
	End   file.Idx
}

EmptyExpression represents an empty expression.

func (*EmptyExpression) Idx0

func (ee *EmptyExpression) Idx0() file.Idx

Idx0 implements Node.

func (*EmptyExpression) Idx1

func (ee *EmptyExpression) Idx1() file.Idx

Idx1 implements Node.

type EmptyStatement

type EmptyStatement struct {
	Semicolon file.Idx
}

EmptyStatement represents a empty statement.

func (*EmptyStatement) Idx0

func (es *EmptyStatement) Idx0() file.Idx

Idx0 implements Node.

func (*EmptyStatement) Idx1

func (es *EmptyStatement) Idx1() file.Idx

Idx1 implements Node.

type Expression

type Expression interface {
	Node
	// contains filtered or unexported methods
}

Expression is implemented by types that represent an Expression.

type ExpressionStatement

type ExpressionStatement struct {
	Expression Expression
}

ExpressionStatement represents a expression statement.

func (*ExpressionStatement) Idx0

func (es *ExpressionStatement) Idx0() file.Idx

Idx0 implements Node.

func (*ExpressionStatement) Idx1

func (es *ExpressionStatement) Idx1() file.Idx

Idx1 implements Node.

type ForInStatement

type ForInStatement struct {
	For    file.Idx
	Into   Expression
	Source Expression
	Body   Statement
}

ForInStatement represents a for in statement.

func (*ForInStatement) Idx0

func (fis *ForInStatement) Idx0() file.Idx

Idx0 implements Node.

func (*ForInStatement) Idx1

func (fis *ForInStatement) Idx1() file.Idx

Idx1 implements Node.

type ForStatement

type ForStatement struct {
	For         file.Idx
	Initializer Expression
	Update      Expression
	Test        Expression
	Body        Statement
}

ForStatement represents a for statement.

func (*ForStatement) Idx0

func (fs *ForStatement) Idx0() file.Idx

Idx0 implements Node.

func (*ForStatement) Idx1

func (fs *ForStatement) Idx1() file.Idx

Idx1 implements Node.

type FunctionDeclaration

type FunctionDeclaration struct {
	Function *FunctionLiteral
}

FunctionDeclaration represents a function declaration.

type FunctionLiteral

type FunctionLiteral struct {
	Function      file.Idx
	Name          *Identifier
	ParameterList *ParameterList
	Body          Statement
	Source        string

	DeclarationList []Declaration
}

FunctionLiteral represents a function literal.

func (*FunctionLiteral) Idx0

func (fl *FunctionLiteral) Idx0() file.Idx

Idx0 implements Node.

func (*FunctionLiteral) Idx1

func (fl *FunctionLiteral) Idx1() file.Idx

Idx1 implements Node.

type FunctionStatement

type FunctionStatement struct {
	Function *FunctionLiteral
}

FunctionStatement represents a function statement.

func (*FunctionStatement) Idx0

func (fs *FunctionStatement) Idx0() file.Idx

Idx0 implements Node.

func (*FunctionStatement) Idx1

func (fs *FunctionStatement) Idx1() file.Idx

Idx1 implements Node.

type Identifier

type Identifier struct {
	Name string
	Idx  file.Idx
}

Identifier represents an identifier.

func (*Identifier) Idx0

func (i *Identifier) Idx0() file.Idx

Idx0 implements Node.

func (*Identifier) Idx1

func (i *Identifier) Idx1() file.Idx

Idx1 implements Node.

type IfStatement

type IfStatement struct {
	If         file.Idx
	Test       Expression
	Consequent Statement
	Alternate  Statement
}

IfStatement represents a if statement.

func (*IfStatement) Idx0

func (is *IfStatement) Idx0() file.Idx

Idx0 implements Node.

func (*IfStatement) Idx1

func (is *IfStatement) Idx1() file.Idx

Idx1 implements Node.

type LabelledStatement

type LabelledStatement struct {
	Label     *Identifier
	Colon     file.Idx
	Statement Statement
}

LabelledStatement represents a labelled statement.

func (*LabelledStatement) Idx0

func (ls *LabelledStatement) Idx0() file.Idx

Idx0 implements Node.

func (*LabelledStatement) Idx1

func (ls *LabelledStatement) Idx1() file.Idx

Idx1 implements Node.

type NewExpression

type NewExpression struct {
	New              file.Idx
	Callee           Expression
	LeftParenthesis  file.Idx
	ArgumentList     []Expression
	RightParenthesis file.Idx
}

NewExpression represents a new expression.

func (*NewExpression) Idx0

func (ne *NewExpression) Idx0() file.Idx

Idx0 implements Node.

func (*NewExpression) Idx1

func (ne *NewExpression) Idx1() file.Idx

Idx1 implements Node.

type Node

type Node interface {
	Idx0() file.Idx // The index of the first character belonging to the node
	Idx1() file.Idx // The index of the first character immediately after the node
}

Node is implemented by types that represent a node.

type NullLiteral

type NullLiteral struct {
	Idx     file.Idx
	Literal string
}

NullLiteral represents a null literal.

func (*NullLiteral) Idx0

func (nl *NullLiteral) Idx0() file.Idx

Idx0 implements Node.

func (*NullLiteral) Idx1

func (nl *NullLiteral) Idx1() file.Idx

Idx1 implements Node.

type NumberLiteral

type NumberLiteral struct {
	Idx     file.Idx
	Literal string
	Value   interface{}
}

NumberLiteral represents a number literal.

func (*NumberLiteral) Idx0

func (nl *NumberLiteral) Idx0() file.Idx

Idx0 implements Node.

func (*NumberLiteral) Idx1

func (nl *NumberLiteral) Idx1() file.Idx

Idx1 implements Node.

type ObjectLiteral

type ObjectLiteral struct {
	LeftBrace  file.Idx
	RightBrace file.Idx
	Value      []Property
}

ObjectLiteral represents an object literal.

func (*ObjectLiteral) Idx0

func (ol *ObjectLiteral) Idx0() file.Idx

Idx0 implements Node.

func (*ObjectLiteral) Idx1

func (ol *ObjectLiteral) Idx1() file.Idx

Idx1 implements Node.

type ParameterList

type ParameterList struct {
	Opening file.Idx
	List    []*Identifier
	Closing file.Idx
}

ParameterList represents a parameter list.

type Program

type Program struct {
	Body []Statement

	DeclarationList []Declaration

	File *file.File

	Comments CommentMap
}

Program represents a full program.

func (*Program) Idx0

func (p *Program) Idx0() file.Idx

Idx0 implements Node.

func (*Program) Idx1

func (p *Program) Idx1() file.Idx

Idx1 implements Node.

type Property

type Property struct {
	Key   string
	Kind  string
	Value Expression
}

Property represents a property.

type RegExpLiteral

type RegExpLiteral struct {
	Idx     file.Idx
	Literal string
	Pattern string
	Flags   string
	Value   string
}

RegExpLiteral represents a regular expression literal.

func (*RegExpLiteral) Idx0

func (rl *RegExpLiteral) Idx0() file.Idx

Idx0 implements Node.

func (*RegExpLiteral) Idx1

func (rl *RegExpLiteral) Idx1() file.Idx

Idx1 implements Node.

type ReturnStatement

type ReturnStatement struct {
	Return   file.Idx
	Argument Expression
}

ReturnStatement represents a return statement.

func (*ReturnStatement) Idx0

func (rs *ReturnStatement) Idx0() file.Idx

Idx0 implements Node.

func (*ReturnStatement) Idx1

func (rs *ReturnStatement) Idx1() file.Idx

Idx1 implements Node.

type SequenceExpression

type SequenceExpression struct {
	Sequence []Expression
}

SequenceExpression represents a sequence literal.

func (*SequenceExpression) Idx0

func (se *SequenceExpression) Idx0() file.Idx

Idx0 implements Node.

func (*SequenceExpression) Idx1

func (se *SequenceExpression) Idx1() file.Idx

Idx1 implements Node.

type Statement

type Statement interface {
	Node
	// contains filtered or unexported methods
}

Statement is implemented by types which represent a statement.

type StringLiteral

type StringLiteral struct {
	Idx     file.Idx
	Literal string
	Value   string
}

StringLiteral represents a string literal.

func (*StringLiteral) Idx0

func (sl *StringLiteral) Idx0() file.Idx

Idx0 implements Node.

func (*StringLiteral) Idx1

func (sl *StringLiteral) Idx1() file.Idx

Idx1 implements Node.

type SwitchStatement

type SwitchStatement struct {
	Switch       file.Idx
	Discriminant Expression
	Default      int
	Body         []*CaseStatement
}

SwitchStatement represents a switch statement.

func (*SwitchStatement) Idx0

func (ss *SwitchStatement) Idx0() file.Idx

Idx0 implements Node.

func (*SwitchStatement) Idx1

func (ss *SwitchStatement) Idx1() file.Idx

Idx1 implements Node.

type ThisExpression

type ThisExpression struct {
	Idx file.Idx
}

ThisExpression represents a this expression.

func (*ThisExpression) Idx0

func (te *ThisExpression) Idx0() file.Idx

Idx0 implements Node.

func (*ThisExpression) Idx1

func (te *ThisExpression) Idx1() file.Idx

Idx1 implements Node.

type ThrowStatement

type ThrowStatement struct {
	Throw    file.Idx
	Argument Expression
}

ThrowStatement represents a throw statement.

func (*ThrowStatement) Idx0

func (ts *ThrowStatement) Idx0() file.Idx

Idx0 implements Node.

func (*ThrowStatement) Idx1

func (ts *ThrowStatement) Idx1() file.Idx

Idx1 implements Node.

type TryStatement

type TryStatement struct {
	Try     file.Idx
	Body    Statement
	Catch   *CatchStatement
	Finally Statement
}

TryStatement represents a try statement.

func (*TryStatement) Idx0

func (ts *TryStatement) Idx0() file.Idx

Idx0 implements Node.

func (*TryStatement) Idx1

func (ts *TryStatement) Idx1() file.Idx

Idx1 implements Node.

type UnaryExpression

type UnaryExpression struct {
	Operator token.Token
	Idx      file.Idx // If a prefix operation
	Operand  Expression
	Postfix  bool
}

UnaryExpression represents a unary expression.

func (*UnaryExpression) Idx0

func (ue *UnaryExpression) Idx0() file.Idx

Idx0 implements Node.

func (*UnaryExpression) Idx1

func (ue *UnaryExpression) Idx1() file.Idx

Idx1 implements Node.

type VariableDeclaration

type VariableDeclaration struct {
	Var  file.Idx
	List []*VariableExpression
}

VariableDeclaration represents a variable declaration.

type VariableExpression

type VariableExpression struct {
	Name        string
	Idx         file.Idx
	Initializer Expression
}

VariableExpression represents a variable expression.

func (*VariableExpression) Idx0

func (ve *VariableExpression) Idx0() file.Idx

Idx0 implements Node.

func (*VariableExpression) Idx1

func (ve *VariableExpression) Idx1() file.Idx

Idx1 implements Node.

type VariableStatement

type VariableStatement struct {
	Var  file.Idx
	List []Expression
}

VariableStatement represents a variable statement.

func (*VariableStatement) Idx0

func (vs *VariableStatement) Idx0() file.Idx

Idx0 implements Node.

func (*VariableStatement) Idx1

func (vs *VariableStatement) Idx1() file.Idx

Idx1 implements Node.

type Visitor

type Visitor interface {
	Enter(n Node) (v Visitor)
	Exit(n Node)
}

Visitor Enter method is invoked for each node encountered by Walk. If the result visitor w is not nil, Walk visits each of the children of node with the visitor v, followed by a call of the Exit method.

Example (CodeRewrite)
package main

import (
	"fmt"
	"log"

	"github.com/robertkrimen/otto/ast"
	"github.com/robertkrimen/otto/file"
	"github.com/robertkrimen/otto/parser"
)

type walkExample struct {
	source string
	shift  file.Idx
}

func (w *walkExample) Enter(n ast.Node) ast.Visitor {
	if id, ok := n.(*ast.Identifier); ok && id != nil {
		idx := n.Idx0() + w.shift - 1
		s := w.source[:idx] + "new_" + w.source[idx:]
		w.source = s
		w.shift += 4
	}
	if v, ok := n.(*ast.VariableExpression); ok && v != nil {
		idx := n.Idx0() + w.shift - 1
		s := w.source[:idx] + "varnew_" + w.source[idx:]
		w.source = s
		w.shift += 7
	}

	return w
}

func (w *walkExample) Exit(n ast.Node) {
	// AST node n has had all its children walked. Pop it out of your
	// stack, or do whatever processing you need to do, if any.
}

func main() {
	source := `var b = function() {test(); try {} catch(e) {} var test = "test(); var test = 1"} // test`
	program, err := parser.ParseFile(nil, "", source, 0)
	if err != nil {
		log.Fatal(err)
	}

	w := &walkExample{source: source}

	ast.Walk(w, program)

	fmt.Println(w.source)
}
Output:

var varnew_b = function() {new_test(); try {} catch(new_e) {} var varnew_test = "test(); var test = 1"} // test

type WhileStatement

type WhileStatement struct {
	While file.Idx
	Test  Expression
	Body  Statement
}

WhileStatement represents a while statement.

func (*WhileStatement) Idx0

func (ws *WhileStatement) Idx0() file.Idx

Idx0 implements Node.

func (*WhileStatement) Idx1

func (ws *WhileStatement) Idx1() file.Idx

Idx1 implements Node.

type WithStatement

type WithStatement struct {
	With   file.Idx
	Object Expression
	Body   Statement
}

WithStatement represents a with statement.

func (*WithStatement) Idx0

func (ws *WithStatement) Idx0() file.Idx

Idx0 implements Node.

func (*WithStatement) Idx1

func (ws *WithStatement) Idx1() file.Idx

Idx1 implements Node.

Jump to

Keyboard shortcuts

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