backlog

package
v0.0.0-...-1ce83d5 Latest Latest
Warning

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

Go to latest
Published: Aug 5, 2018 License: MIT Imports: 22 Imported by: 0

Documentation

Index

Constants

View Source
const (
	CreatedMetadataKey  = "Created"
	ModifiedMetadataKey = "Modified"
)
View Source
const (
	BacklogIdeaAuthorMetadataKey = "Author"
	BacklogIdeaTagsMetadataKey   = "Tags"
	BacklogIdeaRankMetadataKey   = "Rank"
)
View Source
const (
	BacklogItemAuthorMetadataKey   = "Author"
	BacklogItemStatusMetadataKey   = "Status"
	BacklogItemAssignedMetadataKey = "Assigned"
	BacklogItemEstimateMetadataKey = "Estimate"
	BacklogItemTagsMetadataKey     = "Tags"
	BacklogItemArchiveMetadataKey  = "Archive"
	BacklogItemFinishedMetadataKey = "Finished"
	BacklogItemTimelineMetadataKey = "Timeline"
)
View Source
const (
	TagsDirectoryName = "tags"
	TagsFileName      = "tags.md"
)
View Source
const ArchiveFileName = "archive.md"
View Source
const (
	UserEmailMetadataKey = "Email"
)

Variables

View Source
var (
	DoingStatus     = &BacklogItemStatus{"d", "doing", "in doing"}
	PlannedStatus   = &BacklogItemStatus{"p", "planned", "planned"}
	UnplannedStatus = &BacklogItemStatus{"u", "unplanned", "unplanned"}
	FinishedStatus  = &BacklogItemStatus{"f", "finished", "finished"}
)
View Source
var (
	ForbiddenBacklogNames = []string{velocityDirectoryName, ideasDirectoryName, archiveDirectoryName, TagsDirectoryName, usersDirectoryName, timelineDirectoryName}
	ForbiddenItemNames    = []string{archiveDirectoryName}
)
View Source
var (
	OverviewFooterRe = regexp.MustCompile(`^\[Archived stories]\([^]]+\).*`)
)
View Source
var (
	RelatedItemsRegex = regexp.MustCompile(`(?i)^#+\s*stories\s*$`)
)

Functions

func AllStatusesList

func AllStatusesList() string

func FindArchiveFileInDirectory

func FindArchiveFileInDirectory(dir string) (string, bool)

func FindOverviewFileInRootDirectory

func FindOverviewFileInRootDirectory(backlogDir string) (string, bool)

func IsForbiddenBacklogName

func IsForbiddenBacklogName(backlogName string) bool

func IsForbiddenItemName

func IsForbiddenItemName(itemName string) bool

func IsValidStatusCode

func IsValidStatusCode(statusCode string) bool

func ItemsAndIdeasTags

func ItemsAndIdeasTags(root *BacklogsStructure) (allTags map[string]struct{}, itemsTags map[string][]*BacklogItem, ideasTags map[string][]*BacklogIdea, itemsOverviews map[*BacklogItem]*BacklogOverview, err error)
func MakeArchiveLink(archive *BacklogOverview, title string, baseDir string) string
func MakeIdeaLink(idea *BacklogIdea, baseDir string) string
func MakeIdeasLink(rootDir, baseDir string) string
func MakeIndexLink(rootDir, baseDir string) string
func MakeItemLink(item *BacklogItem, baseDir string) string
func MakeOverviewLink(overview *BacklogOverview, baseDir string) string
func MakeStandardLinks(rootDir, baseDir string) []string
func MakeTagLink(tag, tagsDir, baseDir string) string
func MakeTagLinks(tags []string, tagsDir, baseDir string) string
func MakeTagsLink(rootDir, baseDir string) string
func MakeTimelineLink(rootDir, baseDir string) string
func MakeUserLink(user *User, title string, baseDir string) string
func MakeUsersLink(rootDir, baseDir string) string
func MakeVelocityLink(rootDir, baseDir string) string

func StatusIndex

func StatusIndex(status *BacklogItemStatus) int

func StatusNameByCode

func StatusNameByCode(statusCode string) string

Types

type Backlog

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

func LoadBacklog

func LoadBacklog(backlogDir string) (*Backlog, error)

func (*Backlog) ActiveItems

func (bck *Backlog) ActiveItems() []*BacklogItem

func (*Backlog) AllItems

func (bck *Backlog) AllItems() []*BacklogItem

func (*Backlog) AllItemsByStatus

func (bck *Backlog) AllItemsByStatus(statusCode string) []*BacklogItem

func (*Backlog) ArchivedItems

func (bck *Backlog) ArchivedItems() []*BacklogItem

func (*Backlog) FilteredActiveItems

func (bck *Backlog) FilteredActiveItems(filter BacklogItemsFilter) []*BacklogItem

type BacklogIdea

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

func LoadBacklogIdea

func LoadBacklogIdea(ideaPath string) (*BacklogIdea, error)

func LoadIdeas

func LoadIdeas(ideasDir string) ([]*BacklogIdea, error)

func (*BacklogIdea) Author

func (idea *BacklogIdea) Author() string

func (*BacklogIdea) Comments

func (idea *BacklogIdea) Comments() []*Comment

func (*BacklogIdea) Content

func (idea *BacklogIdea) Content() []byte

func (*BacklogIdea) Created

func (idea *BacklogIdea) Created() time.Time

func (*BacklogIdea) HasMetadata

func (idea *BacklogIdea) HasMetadata() bool

func (*BacklogIdea) Modified

func (idea *BacklogIdea) Modified() time.Time

func (*BacklogIdea) Name

func (idea *BacklogIdea) Name() string

func (*BacklogIdea) Path

func (idea *BacklogIdea) Path() string

func (*BacklogIdea) Rank

func (idea *BacklogIdea) Rank() string

func (*BacklogIdea) Save

func (idea *BacklogIdea) Save() error

func (*BacklogIdea) SetAuthor

func (idea *BacklogIdea) SetAuthor(author string)

func (*BacklogIdea) SetCreated

func (idea *BacklogIdea) SetCreated(timestamp string)

func (*BacklogIdea) SetDescription

func (idea *BacklogIdea) SetDescription(description string)

func (*BacklogIdea) SetFooter

func (idea *BacklogIdea) SetFooter(footer []string)

func (*BacklogIdea) SetModified

func (idea *BacklogIdea) SetModified(timestamp string)

func (*BacklogIdea) SetRank

func (idea *BacklogIdea) SetRank(rank string)

func (*BacklogIdea) SetTags

func (idea *BacklogIdea) SetTags(tags []string)

func (*BacklogIdea) SetText

func (idea *BacklogIdea) SetText(text string)

func (*BacklogIdea) SetTitle

func (idea *BacklogIdea) SetTitle(title string)

func (*BacklogIdea) Tags

func (idea *BacklogIdea) Tags() []string

func (*BacklogIdea) Text

func (idea *BacklogIdea) Text() string

func (*BacklogIdea) Title

func (idea *BacklogIdea) Title() string

func (*BacklogIdea) UpdateComments

func (idea *BacklogIdea) UpdateComments(comments []*Comment) error
func (idea *BacklogIdea) UpdateLinks(rootDir string) error

type BacklogItem

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

func ActiveBacklogItems

func ActiveBacklogItems(root *BacklogsStructure) (items []*BacklogItem, itemsOverviews map[*BacklogItem]*BacklogOverview, err error)

func AllBacklogItems

func AllBacklogItems(root *BacklogsStructure) (items []*BacklogItem, itemsOverviews map[*BacklogItem]*BacklogOverview, err error)

func LoadBacklogItem

func LoadBacklogItem(itemPath string) (*BacklogItem, error)

func NewBacklogItem

func NewBacklogItem(name string, markdownData string) *BacklogItem

func (*BacklogItem) Archived

func (item *BacklogItem) Archived() bool

func (*BacklogItem) Assigned

func (item *BacklogItem) Assigned() string

func (*BacklogItem) Author

func (item *BacklogItem) Author() string

func (*BacklogItem) ClearTimeline

func (item *BacklogItem) ClearTimeline()

func (*BacklogItem) Comments

func (item *BacklogItem) Comments() []*Comment

func (*BacklogItem) Content

func (item *BacklogItem) Content() []byte

func (*BacklogItem) Created

func (item *BacklogItem) Created() time.Time

func (*BacklogItem) Estimate

func (item *BacklogItem) Estimate() string

func (*BacklogItem) Finished

func (item *BacklogItem) Finished() time.Time

func (*BacklogItem) Header

func (item *BacklogItem) Header() string
func (item *BacklogItem) Links() string

func (*BacklogItem) Modified

func (item *BacklogItem) Modified() time.Time

func (*BacklogItem) MoveToBacklogArchiveDirectory

func (item *BacklogItem) MoveToBacklogArchiveDirectory() error

func (*BacklogItem) MoveToBacklogDirectory

func (item *BacklogItem) MoveToBacklogDirectory() error

func (*BacklogItem) Name

func (item *BacklogItem) Name() string

func (*BacklogItem) Path

func (item *BacklogItem) Path() string

func (*BacklogItem) Save

func (item *BacklogItem) Save() error

func (*BacklogItem) SetArchived

func (item *BacklogItem) SetArchived(archived bool)

func (*BacklogItem) SetAssigned

func (item *BacklogItem) SetAssigned(assigned string)

func (*BacklogItem) SetAuthor

func (item *BacklogItem) SetAuthor(author string)

func (*BacklogItem) SetCreated

func (item *BacklogItem) SetCreated(timestamp string)

func (*BacklogItem) SetDescription

func (item *BacklogItem) SetDescription(description string)

func (*BacklogItem) SetEstimate

func (item *BacklogItem) SetEstimate(estimate string)

func (*BacklogItem) SetFinished

func (item *BacklogItem) SetFinished(timestamp string)

func (*BacklogItem) SetHeader

func (item *BacklogItem) SetHeader(header string)

func (*BacklogItem) SetModified

func (item *BacklogItem) SetModified(timestamp string)

func (*BacklogItem) SetStatus

func (item *BacklogItem) SetStatus(status *BacklogItemStatus)

func (*BacklogItem) SetTags

func (item *BacklogItem) SetTags(tags []string)

func (*BacklogItem) SetTimeline

func (item *BacklogItem) SetTimeline(startDate, endDate time.Time)

func (*BacklogItem) SetTitle

func (item *BacklogItem) SetTitle(title string)

func (*BacklogItem) Status

func (item *BacklogItem) Status() string

func (*BacklogItem) Tags

func (item *BacklogItem) Tags() []string

func (*BacklogItem) Timeline

func (item *BacklogItem) Timeline() (startDate, endDate time.Time)

func (*BacklogItem) TimelineStr

func (item *BacklogItem) TimelineStr() (startDate, endDate string)

func (*BacklogItem) Title

func (item *BacklogItem) Title() string

func (*BacklogItem) UpdateComments

func (item *BacklogItem) UpdateComments(comments []*Comment) error
func (item *BacklogItem) UpdateLinks(rootDir string, overviewPath, archivePath string) error

type BacklogItemStatus

type BacklogItemStatus struct {
	Code        string
	Name        string
	Description string
}

func StatusByCode

func StatusByCode(statusCode string) *BacklogItemStatus

func StatusByName

func StatusByName(statusName string) *BacklogItemStatus

func (*BacklogItemStatus) CapitalizedName

func (status *BacklogItemStatus) CapitalizedName() string

func (*BacklogItemStatus) Hint

func (status *BacklogItemStatus) Hint() string

type BacklogItemsActiveFilter

type BacklogItemsActiveFilter struct {
}

func (*BacklogItemsActiveFilter) Match

func (f *BacklogItemsActiveFilter) Match(item *BacklogItem) bool

type BacklogItemsAndFilter

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

func (*BacklogItemsAndFilter) And

func (*BacklogItemsAndFilter) Match

func (f *BacklogItemsAndFilter) Match(item *BacklogItem) bool

type BacklogItemsArchivedFilter

type BacklogItemsArchivedFilter struct {
}

func (*BacklogItemsArchivedFilter) Match

type BacklogItemsAssignedFilter

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

func NewBacklogItemsAssignedFilter

func NewBacklogItemsAssignedFilter(user string) *BacklogItemsAssignedFilter

func (*BacklogItemsAssignedFilter) Match

type BacklogItemsFilter

type BacklogItemsFilter interface {
	Match(item *BacklogItem) bool
}

type BacklogItemsOrFilter

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

func (*BacklogItemsOrFilter) Match

func (f *BacklogItemsOrFilter) Match(item *BacklogItem) bool

func (*BacklogItemsOrFilter) Or

type BacklogItemsSorter

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

func NewBacklogItemsSorter

func NewBacklogItemsSorter(overviews ...*BacklogOverview) *BacklogItemsSorter

func (*BacklogItemsSorter) SortItemsByModifiedDesc

func (s *BacklogItemsSorter) SortItemsByModifiedDesc(items []*BacklogItem)

func (*BacklogItemsSorter) SortItemsByStatus

func (s *BacklogItemsSorter) SortItemsByStatus(status *BacklogItemStatus, items []*BacklogItem)

func (*BacklogItemsSorter) SortedItemsByStatus

func (s *BacklogItemsSorter) SortedItemsByStatus() map[string][]string

type BacklogItemsStatusCodeFilter

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

func NewBacklogItemsStatusCodeFilter

func NewBacklogItemsStatusCodeFilter(statusCode string) *BacklogItemsStatusCodeFilter

func (*BacklogItemsStatusCodeFilter) Match

type BacklogItemsTagsFilter

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

func NewBacklogItemsTagsFilter

func NewBacklogItemsTagsFilter(filter string) *BacklogItemsTagsFilter

func (*BacklogItemsTagsFilter) Match

func (f *BacklogItemsTagsFilter) Match(item *BacklogItem) bool

type BacklogItemsTrueFilter

type BacklogItemsTrueFilter struct {
}

func (*BacklogItemsTrueFilter) Match

func (f *BacklogItemsTrueFilter) Match(item *BacklogItem) bool

type BacklogOverview

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

func LoadBacklogOverview

func LoadBacklogOverview(overviewPath string) (*BacklogOverview, error)

func NewBacklogOverview

func NewBacklogOverview(content *markdown.Content) *BacklogOverview

func (*BacklogOverview) Content

func (overview *BacklogOverview) Content() []byte

func (*BacklogOverview) Path

func (overview *BacklogOverview) Path() string

func (*BacklogOverview) RemoveVelocity

func (overview *BacklogOverview) RemoveVelocity(bck *Backlog) error

func (*BacklogOverview) Save

func (overview *BacklogOverview) Save() error

func (*BacklogOverview) SetCreated

func (overview *BacklogOverview) SetCreated(timestamp string)

func (*BacklogOverview) SetHideEmptyGroups

func (overview *BacklogOverview) SetHideEmptyGroups(value bool)

func (*BacklogOverview) SetTitle

func (overview *BacklogOverview) SetTitle(title string)

func (*BacklogOverview) Title

func (overview *BacklogOverview) Title() string

func (*BacklogOverview) Update

func (overview *BacklogOverview) Update(items []*BacklogItem, sorter *BacklogItemsSorter, userList *UserList) error

func (*BacklogOverview) UpdateItemLinkInOverviewFile

func (overview *BacklogOverview) UpdateItemLinkInOverviewFile(prevItemPath, newItemPath string) error
func (overview *BacklogOverview) UpdateLinks(lastLinkTitle, lastLinkPath, rootDir, baseDir string) error

type BacklogView

type BacklogView struct {
}

func (BacklogView) ShowBacklogItems

func (bv BacklogView) ShowBacklogItems(backlogDir, statusCode string) ([]*BacklogItem, error)

func (BacklogView) VelocityImage

func (bv BacklogView) VelocityImage(bck *Backlog, weekCount int) ([]byte, error)

func (BacklogView) VelocityText

func (bv BacklogView) VelocityText(bck *Backlog, weekCount, width int) (string, error)

func (BacklogView) WriteAsciiItems

func (bv BacklogView) WriteAsciiItems(items []*BacklogItem, status *BacklogItemStatus, withOrderNumber bool, withTotalPoints bool) []string

func (BacklogView) WriteAsciiItemsWithProjectAndStatus

func (bv BacklogView) WriteAsciiItemsWithProjectAndStatus(items []*BacklogItem, overviews map[*BacklogItem]*BacklogOverview, title string, withOrderNumber bool) []string

func (BacklogView) WriteMarkdownIdeas

func (bv BacklogView) WriteMarkdownIdeas(ideas []*BacklogIdea, baseDir, tagsDir string) []string

func (BacklogView) WriteMarkdownItems

func (bv BacklogView) WriteMarkdownItems(items []*BacklogItem, status *BacklogItemStatus, baseDir, tagsDir string, userList *UserList) []string

func (BacklogView) WriteMarkdownItemsWithProject

func (bv BacklogView) WriteMarkdownItemsWithProject(overviews map[*BacklogItem]*BacklogOverview, items []*BacklogItem, status *BacklogItemStatus, baseDir, tagsDir string, userList *UserList) []string

func (BacklogView) WriteMarkdownItemsWithProjectAndStatus

func (bv BacklogView) WriteMarkdownItemsWithProjectAndStatus(overviews map[*BacklogItem]*BacklogOverview, items []*BacklogItem, baseDir, tagsDir string, userList *UserList) []string

func (BacklogView) WriteMarkdownItemsWithoutAssigned

func (bv BacklogView) WriteMarkdownItemsWithoutAssigned(items []*BacklogItem, status *BacklogItemStatus, baseDir, tagsDir string) []string

type BacklogsStructure

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

func NewBacklogsStructure

func NewBacklogsStructure(root string) *BacklogsStructure

func (*BacklogsStructure) BacklogDirs

func (s *BacklogsStructure) BacklogDirs() ([]string, error)

func (*BacklogsStructure) ConfigFile

func (s *BacklogsStructure) ConfigFile() string

func (*BacklogsStructure) IdeasDirectory

func (s *BacklogsStructure) IdeasDirectory() string

func (*BacklogsStructure) IdeasFile

func (s *BacklogsStructure) IdeasFile() string

func (*BacklogsStructure) IndexFile

func (s *BacklogsStructure) IndexFile() string

func (*BacklogsStructure) Root

func (s *BacklogsStructure) Root() string

func (*BacklogsStructure) TagsDirectory

func (s *BacklogsStructure) TagsDirectory() string

func (*BacklogsStructure) TagsFile

func (s *BacklogsStructure) TagsFile() string

func (*BacklogsStructure) TimelineDirectory

func (s *BacklogsStructure) TimelineDirectory() string

func (*BacklogsStructure) TimelineFile

func (s *BacklogsStructure) TimelineFile() string

func (*BacklogsStructure) UsersDirectory

func (s *BacklogsStructure) UsersDirectory() string

func (*BacklogsStructure) UsersFile

func (s *BacklogsStructure) UsersFile() string

func (*BacklogsStructure) VelocityFile

func (s *BacklogsStructure) VelocityFile() string

type Comment

type Comment struct {
	Users []string
	Text  []string

	Closed bool
	Unsent bool
	// contains filtered or unexported fields
}

func (*Comment) AddLine

func (c *Comment) AddLine(line string)

type Commented

type Commented interface {
	Comments() []*Comment
	UpdateComments(comments []*Comment) error
	Path() string
	Title() string
}

type CsvImporter

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

func NewCsvImporter

func NewCsvImporter(csvPath string, backlogDir string) *CsvImporter

func (*CsvImporter) Import

func (imp *CsvImporter) Import() error

type GlobalIndex

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

func LoadGlobalIndex

func LoadGlobalIndex(indexPath string) (*GlobalIndex, error)

func NewGlobalIndex

func NewGlobalIndex(content *markdown.Content) *GlobalIndex

func (*GlobalIndex) FreeText

func (index *GlobalIndex) FreeText() []string

func (*GlobalIndex) Save

func (index *GlobalIndex) Save() error

func (*GlobalIndex) SetFooter

func (index *GlobalIndex) SetFooter(footer []string)

func (*GlobalIndex) SetFreeText

func (index *GlobalIndex) SetFreeText(freeText []string)

func (*GlobalIndex) UpdateBacklogs

func (index *GlobalIndex) UpdateBacklogs(overviews []*BacklogOverview, archives []*BacklogOverview, baseDir string) error
func (index *GlobalIndex) UpdateLinks(rootDir string) error

type MarkdownComments

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

func NewMarkdownComments

func NewMarkdownComments(content *markdown.Content) *MarkdownComments

func (*MarkdownComments) Comments

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

func (*MarkdownComments) UpdateComments

func (c *MarkdownComments) UpdateComments(comments []*Comment)

type TimelineGenerator

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

func NewTimelineGenerator

func NewTimelineGenerator(root *BacklogsStructure) *TimelineGenerator

func (*TimelineGenerator) Execute

func (tg *TimelineGenerator) Execute() error

func (*TimelineGenerator) ExecuteForTag

func (tg *TimelineGenerator) ExecuteForTag(tag string) error

func (*TimelineGenerator) RemoveTimeline

func (tg *TimelineGenerator) RemoveTimeline(tag string)

func (*TimelineGenerator) RenameTimeline

func (tg *TimelineGenerator) RenameTimeline(oldTag, newTag string) error

type User

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

func LoadUser

func LoadUser(userPath string) (*User, error)

func NewUser

func NewUser(markdownData, contentPath string) (*User, error)

func (*User) AddEmailIfNotExist

func (u *User) AddEmailIfNotExist(email string) bool

func (*User) Emails

func (u *User) Emails() []string

func (*User) HasEmail

func (u *User) HasEmail(email string) bool

func (*User) HasName

func (u *User) HasName(name string) bool

func (*User) Name

func (u *User) Name() string

func (*User) Nickname

func (u *User) Nickname() string

func (*User) Path

func (u *User) Path() string

func (*User) PrimaryEmail

func (u *User) PrimaryEmail() string

func (*User) Save

func (u *User) Save() error

func (*User) SetFreeText

func (u *User) SetFreeText(freeText []string)

func (*User) SetName

func (u *User) SetName(name string)

func (*User) UpdateItems

func (u *User) UpdateItems(rootDir, tagsDir string, items []*BacklogItem, overviews map[*BacklogItem]*BacklogOverview) (string, error)

type UserList

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

func NewUserList

func NewUserList(usersDir string) *UserList

func (*UserList) AddUser

func (ul *UserList) AddUser(name, email string) bool

func (*UserList) AllUsers

func (ul *UserList) AllUsers() []string

func (*UserList) DeleteUser

func (ul *UserList) DeleteUser(nameOrEmailOrNick string) bool

func (*UserList) ResolveGitUsers

func (ul *UserList) ResolveGitUsers(unknownUsers []string) (unresolvedUsers []string, err error)

func (*UserList) Save

func (ul *UserList) Save() error

func (*UserList) User

func (ul *UserList) User(nameOrNickOrEmail string) *User

func (*UserList) Users

func (ul *UserList) Users() []*User

type Velocity

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

func LoadGlobalVelocity

func LoadGlobalVelocity(velocityPath string) (*Velocity, error)

func NewGlobalVelocity

func NewGlobalVelocity(content *markdown.Content) *Velocity

func (*Velocity) Save

func (velocity *Velocity) Save() error

func (*Velocity) SetTitle

func (velocity *Velocity) SetTitle(title string)

func (*Velocity) Title

func (velocity *Velocity) Title() string

func (*Velocity) Update

func (velocity *Velocity) Update(backlogs []*Backlog, overviews []*BacklogOverview, backlogDirs []string, baseDir string) error
func (velocity *Velocity) UpdateLinks(rootDir string) error

Jump to

Keyboard shortcuts

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