with its
// art, lifted from the layout-stage example's default state, so the
// staged sign-in screens show the stage the layout documents. newSite
// calls it once and keeps the scene on the site.
func (s *site) stageScene() (string, error) {
const name = "layout-stage"
state, ok := s.m.Default(name)
if !ok {
return "", fmt.Errorf("the manifest has no %s example", name)
}
doc, err := example.Document(s.src, name, state)
if err != nil {
return "", err
}
scene := stageSceneTag.FindString(doc)
if scene == "" {
return "", fmt.Errorf("%s/%s carries no scene to lift", name, state)
}
return scene, nil
}
// stage puts a body whose first element is the sign-in card on the
// stage: the scene, then the card in the page column, as the stage
// shell lays a screen out. Ten of the twelve sign-in states; the two
// rst-box screens stay bare, as Rastrillo keeps them. The HTML tab
// still shows the bare card, which is what a reader copies.
func stage(scene, body string) string {
return `
` + scene + `
` + strings.TrimSpace(body) + `
`
}
// layoutLinks makes a layout document's own links live, so a shell demo
// opened full width works as the app it stands for: the back strip's
// way up goes to the shell's index document at its first nav id; the
// nav goes to the shell's page document where the manifest has one;
// the brand and the foot's "Back to the design system" go to the
// Overview; and the language menu's links go to the same layout
// document in each locale, the page's own marked current, lang and dir
// kept. Every link rewritten carries data-gallery-nav, which is what
// marks it the gallery's: the deadening pass leaves it alone and the
// URL gates resolve it. The rest of the body's links are a sample's
// and go to "#" afterwards.
//
// The shell of a layout is its name without layout- and -page: the
// index is layout-
, the page layout--page. The document
// in another locale is the same state's, the one being framed.
func (s *site) layoutLinks(doc string, e example.Entry, state, theme, locale string) (string, error) {
shell := strings.TrimSuffix(strings.TrimPrefix(e.Name, "layout-"), "-page")
index := "layout-" + shell
indexState, ok := s.m.Default(index)
if !ok {
return "", fmt.Errorf("%s: the manifest has no %s, the shell's index document", e.Name, index)
}
own := func(l string) string { return s.href(theme, l, "frames/"+e.Name+"/"+state+".html") }
overview := s.href(theme, locale, s.fileOf("overview"))
var err error
if shellBack.MatchString(doc) {
indexDoc, derr := example.Document(s.src, index, indexState)
if derr != nil {
return "", derr
}
id := firstNavID.FindStringSubmatch(indexDoc)
if id == nil {
return "", fmt.Errorf("%s: %s has no nav id for the way up to land on", e.Name, index)
}
up := s.href(theme, locale, "frames/"+index+"/"+indexState+".html") + "#" + id[1]
doc = shellBack.ReplaceAllStringFunc(doc, func(m string) string {
return anchorTag.ReplaceAllStringFunc(m, func(a string) string { return liveLink(a, up) })
})
}
if pageState, ok := s.m.Default(index + "-page"); ok {
page := s.href(theme, locale, "frames/"+index+"-page/"+pageState+".html")
doc = shellNav.ReplaceAllStringFunc(doc, func(m string) string {
return anchorTag.ReplaceAllStringFunc(m, func(a string) string { return liveLink(a, page) })
})
}
doc = shellBrand.ReplaceAllStringFunc(doc, func(a string) string { return liveLink(a, overview) })
if doc, err = s.localeLinks(doc, locale, own); err != nil {
return "", fmt.Errorf("%s: %w", e.Name, err)
}
doc = footLink(locale).ReplaceAllStringFunc(doc, func(m string) string {
return anchorTag.ReplaceAllString(m, liveLink(anchorTag.FindString(m), overview))
})
return doc, nil
}
// localeLinks points every link of a document's language menu at href
// of the link's own locale, marked the gallery's, with the seeded
// current mark removed and the page's own locale marked instead; lang
// and dir are kept. A link with no lang, or a lang the gallery renders
// no locale for, is an error. The layouts' frame documents and the demo
// application both write their menus through it.
func (s *site) localeLinks(doc, locale string, href func(locale string) string) (string, error) {
var err error
doc = localeMenu.ReplaceAllStringFunc(doc, func(m string) string {
return anchorTag.ReplaceAllStringFunc(m, func(a string) string {
lang := langAttr.FindStringSubmatch(a)
if lang == nil {
err = errors.New("a language link carries no lang")
return a
}
if !known(lang[1]) {
err = fmt.Errorf("the language menu names %s, which the gallery has no locale for", lang[1])
return a
}
a = currentOn.ReplaceAllString(a, "")
a = liveLink(a, href(lang[1]))
if lang[1] == locale {
a = tagEnd.ReplaceAllString(a, ` aria-current="true">`)
}
return a
})
})
return doc, err
}
// liveLink points one tag at href and marks it the gallery's own.
func liveLink(tag, href string) string {
tag = sampleRef.ReplaceAllStringFunc(tag, func(m string) string {
if sampleRef.FindStringSubmatch(m)[1] != "href" {
return m
}
return `href="` + href + `"`
})
return tagEnd.ReplaceAllString(tag, ` data-gallery-nav>`)
}
// known says whether the gallery renders the locale.
func known(locale string) bool {
for _, l := range Locales {
if l == locale {
return true
}
}
return false
}
// exampleDocument builds a document shaped like a seeded example, with
// the relative asset links the seeds carry, so frame treats it like
// any example: a title, the two stylesheets, the scripts by file name,
// one \n")
}
b.WriteString("\n\n" + body + "\n\n\n")
return b.String()
}