Remove sourceRelativeLinks

Fixes #3766
This commit is contained in:
Bjørn Erik Pedersen 2017-08-02 21:37:03 +02:00
parent 481924b34d
commit 9891c0fb0e
6 changed files with 22 additions and 329 deletions

View file

@ -62,35 +62,31 @@ func NewContentSpec(cfg config.Provider) *ContentSpec {
// Blackfriday holds configuration values for Blackfriday rendering. // Blackfriday holds configuration values for Blackfriday rendering.
type Blackfriday struct { type Blackfriday struct {
Smartypants bool Smartypants bool
SmartypantsQuotesNBSP bool SmartypantsQuotesNBSP bool
AngledQuotes bool AngledQuotes bool
Fractions bool Fractions bool
HrefTargetBlank bool HrefTargetBlank bool
SmartDashes bool SmartDashes bool
LatexDashes bool LatexDashes bool
TaskLists bool TaskLists bool
PlainIDAnchors bool PlainIDAnchors bool
SourceRelativeLinksEval bool Extensions []string
SourceRelativeLinksProjectFolder string ExtensionsMask []string
Extensions []string
ExtensionsMask []string
} }
// NewBlackfriday creates a new Blackfriday filled with site config or some sane defaults. // NewBlackfriday creates a new Blackfriday filled with site config or some sane defaults.
func (c ContentSpec) NewBlackfriday() *Blackfriday { func (c ContentSpec) NewBlackfriday() *Blackfriday {
defaultParam := map[string]interface{}{ defaultParam := map[string]interface{}{
"smartypants": true, "smartypants": true,
"angledQuotes": false, "angledQuotes": false,
"smartypantsQuotesNBSP": false, "smartypantsQuotesNBSP": false,
"fractions": true, "fractions": true,
"hrefTargetBlank": false, "hrefTargetBlank": false,
"smartDashes": true, "smartDashes": true,
"latexDashes": true, "latexDashes": true,
"plainIDAnchors": true, "plainIDAnchors": true,
"taskLists": true, "taskLists": true,
"sourceRelativeLinks": false,
"sourceRelativeLinksProjectFolder": "/docs/content",
} }
ToLowerMap(defaultParam) ToLowerMap(defaultParam)
@ -112,13 +108,6 @@ func (c ContentSpec) NewBlackfriday() *Blackfriday {
jww.FATAL.Printf("Failed to get site rendering config\n%s", err.Error()) jww.FATAL.Printf("Failed to get site rendering config\n%s", err.Error())
} }
if combinedConfig.SourceRelativeLinksEval {
// Remove in Hugo 0.21
Deprecated("blackfriday", "sourceRelativeLinksEval",
`There is no replacement for this feature, as no developer has stepped up to the plate and volunteered to maintain this feature`, false)
}
return combinedConfig return combinedConfig
} }
@ -412,8 +401,6 @@ type RenderingContext struct {
DocumentName string DocumentName string
Config *Blackfriday Config *Blackfriday
RenderTOC bool RenderTOC bool
FileResolver FileResolverFunc
LinkResolver LinkResolverFunc
Cfg config.Provider Cfg config.Provider
} }

View file

@ -20,7 +20,6 @@ import (
"github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/config"
"github.com/miekg/mmark" "github.com/miekg/mmark"
"github.com/russross/blackfriday" "github.com/russross/blackfriday"
jww "github.com/spf13/jwalterweatherman"
) )
type LinkResolverFunc func(ref string) (string, error) type LinkResolverFunc func(ref string) (string, error)
@ -43,35 +42,6 @@ func (r *HugoHTMLRenderer) BlockCode(out *bytes.Buffer, text []byte, lang string
} }
} }
func (r *HugoHTMLRenderer) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) {
if r.LinkResolver == nil || bytes.HasPrefix(link, []byte("HAHAHUGOSHORTCODE")) {
// Use the blackfriday built in Link handler
r.Renderer.Link(out, link, title, content)
} else {
// set by SourceRelativeLinksEval
newLink, err := r.LinkResolver(string(link))
if err != nil {
newLink = string(link)
jww.ERROR.Printf("LinkResolver: %s", err)
}
r.Renderer.Link(out, []byte(newLink), title, content)
}
}
func (r *HugoHTMLRenderer) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) {
if r.FileResolver == nil || bytes.HasPrefix(link, []byte("HAHAHUGOSHORTCODE")) {
// Use the blackfriday built in Image handler
r.Renderer.Image(out, link, title, alt)
} else {
// set by SourceRelativeLinksEval
newLink, err := r.FileResolver(string(link))
if err != nil {
newLink = string(link)
jww.ERROR.Printf("FileResolver: %s", err)
}
r.Renderer.Image(out, []byte(newLink), title, alt)
}
}
// ListItem adds task list support to the Blackfriday renderer. // ListItem adds task list support to the Blackfriday renderer.
func (r *HugoHTMLRenderer) ListItem(out *bytes.Buffer, text []byte, flags int) { func (r *HugoHTMLRenderer) ListItem(out *bytes.Buffer, text []byte, flags int) {
if !r.Config.TaskLists { if !r.Config.TaskLists {

View file

@ -188,7 +188,6 @@ func TestGetHTMLRendererAllFlags(t *testing.T) {
ctx.Config.SmartDashes = true ctx.Config.SmartDashes = true
ctx.Config.Smartypants = true ctx.Config.Smartypants = true
ctx.Config.SmartypantsQuotesNBSP = true ctx.Config.SmartypantsQuotesNBSP = true
ctx.Config.SourceRelativeLinksEval = true
renderer := c.getHTMLRenderer(defaultFlags, ctx) renderer := c.getHTMLRenderer(defaultFlags, ctx)
actualFlags := renderer.GetFlags() actualFlags := renderer.GetFlags()
var expectedFlags int var expectedFlags int

View file

@ -622,22 +622,11 @@ func (p *Page) setAutoSummary() error {
} }
func (p *Page) renderContent(content []byte) []byte { func (p *Page) renderContent(content []byte) []byte {
var fn helpers.LinkResolverFunc
var fileFn helpers.FileResolverFunc
if p.getRenderingConfig().SourceRelativeLinksEval {
fn = func(ref string) (string, error) {
return p.Site.SourceRelativeLink(ref, p)
}
fileFn = func(ref string) (string, error) {
return p.Site.SourceRelativeLinkFile(ref, p)
}
}
return p.s.ContentSpec.RenderBytes(&helpers.RenderingContext{ return p.s.ContentSpec.RenderBytes(&helpers.RenderingContext{
Content: content, RenderTOC: true, PageFmt: p.determineMarkupType(), Content: content, RenderTOC: true, PageFmt: p.determineMarkupType(),
Cfg: p.Language(), Cfg: p.Language(),
DocumentID: p.UniqueID(), DocumentName: p.Path(), DocumentID: p.UniqueID(), DocumentName: p.Path(),
Config: p.getRenderingConfig(), LinkResolver: fn, FileResolver: fileFn}) Config: p.getRenderingConfig()})
} }
func (p *Page) getRenderingConfig() *helpers.Blackfriday { func (p *Page) getRenderingConfig() *helpers.Blackfriday {

View file

@ -493,126 +493,6 @@ func (s *SiteInfo) RelRef(ref string, page *Page, options ...string) (string, er
return s.refLink(ref, page, true, outputFormat) return s.refLink(ref, page, true, outputFormat)
} }
// SourceRelativeLink attempts to convert any source page relative links (like [../another.md]) into absolute links
func (s *SiteInfo) SourceRelativeLink(ref string, currentPage *Page) (string, error) {
var refURL *url.URL
var err error
refURL, err = url.Parse(strings.TrimPrefix(ref, currentPage.getRenderingConfig().SourceRelativeLinksProjectFolder))
if err != nil {
return "", err
}
if refURL.Scheme != "" {
// Not a relative source level path
return ref, nil
}
var target *Page
var link string
if refURL.Path != "" {
refPath := filepath.Clean(filepath.FromSlash(refURL.Path))
if strings.IndexRune(refPath, os.PathSeparator) == 0 { // filepath.IsAbs fails to me.
refPath = refPath[1:]
} else {
if currentPage != nil {
refPath = filepath.Join(currentPage.Source.Dir(), refURL.Path)
}
}
for _, page := range s.AllRegularPages {
if page.Source.Path() == refPath {
target = page
break
}
}
// need to exhaust the test, then try with the others :/
// if the refPath doesn't end in a filename with extension `.md`, then try with `.md` , and then `/index.md`
mdPath := strings.TrimSuffix(refPath, string(os.PathSeparator)) + ".md"
for _, page := range s.AllRegularPages {
if page.Source.Path() == mdPath {
target = page
break
}
}
indexPath := filepath.Join(refPath, "index.md")
for _, page := range s.AllRegularPages {
if page.Source.Path() == indexPath {
target = page
break
}
}
if target == nil {
return "", fmt.Errorf("No page found for \"%s\" on page \"%s\".\n", ref, currentPage.Source.Path())
}
link = target.RelPermalink()
}
if refURL.Fragment != "" {
link = link + "#" + refURL.Fragment
if refURL.Path != "" && target != nil && !target.getRenderingConfig().PlainIDAnchors {
link = link + ":" + target.UniqueID()
} else if currentPage != nil && !currentPage.getRenderingConfig().PlainIDAnchors {
link = link + ":" + currentPage.UniqueID()
}
}
return link, nil
}
// SourceRelativeLinkFile attempts to convert any non-md source relative links (like [../another.gif]) into absolute links
func (s *SiteInfo) SourceRelativeLinkFile(ref string, currentPage *Page) (string, error) {
var refURL *url.URL
var err error
refURL, err = url.Parse(strings.TrimPrefix(ref, currentPage.getRenderingConfig().SourceRelativeLinksProjectFolder))
if err != nil {
return "", err
}
if refURL.Scheme != "" {
// Not a relative source level path
return ref, nil
}
var target *source.File
var link string
if refURL.Path != "" {
refPath := filepath.Clean(filepath.FromSlash(refURL.Path))
if strings.IndexRune(refPath, os.PathSeparator) == 0 { // filepath.IsAbs fails to me.
refPath = refPath[1:]
} else {
if currentPage != nil {
refPath = filepath.Join(currentPage.Source.Dir(), refURL.Path)
}
}
for _, file := range *s.Files {
if file.Path() == refPath {
target = file
break
}
}
if target == nil {
return "", fmt.Errorf("No file found for \"%s\" on page \"%s\".\n", ref, currentPage.Source.Path())
}
link = target.Path()
return "/" + filepath.ToSlash(link), nil
}
return "", fmt.Errorf("failed to find a file to match \"%s\" on page \"%s\"", ref, currentPage.Source.Path())
}
func (s *SiteInfo) addToPaginationPageCount(cnt uint64) { func (s *SiteInfo) addToPaginationPageCount(cnt uint64) {
atomic.AddUint64(&s.paginationPageCount, cnt) atomic.AddUint64(&s.paginationPageCount, cnt)
} }

View file

@ -938,8 +938,7 @@ func setupLinkingMockSite(t *testing.T) *Site {
cfg.Set("pluralizeListTitles", false) cfg.Set("pluralizeListTitles", false)
cfg.Set("canonifyURLs", false) cfg.Set("canonifyURLs", false)
cfg.Set("blackfriday", cfg.Set("blackfriday",
map[string]interface{}{ map[string]interface{}{})
"sourceRelativeLinksProjectFolder": "/docs"})
writeSourcesToSource(t, "content", fs, sources...) writeSourcesToSource(t, "content", fs, sources...)
return buildSingleSite(t, deps.DepsCfg{Fs: fs, Cfg: cfg}, BuildCfg{}) return buildSingleSite(t, deps.DepsCfg{Fs: fs, Cfg: cfg}, BuildCfg{})
@ -973,134 +972,3 @@ func TestRefLinking(t *testing.T) {
// TODO: and then the failure cases. // TODO: and then the failure cases.
} }
func TestSourceRelativeLinksing(t *testing.T) {
t.Parallel()
site := setupLinkingMockSite(t)
type resultMap map[string]string
okresults := map[string]resultMap{
"index.md": map[string]string{
"/docs/rootfile.md": "/rootfile/",
"rootfile.md": "/rootfile/",
// See #3396 -- this may potentially be ambiguous (i.e. name conflict with home page).
// But the user have chosen so. This index.md patterns is more relevant in /sub-folders.
"index.md": "/",
"level2/2-root.md": "/level2/2-root/",
"/docs/level2/2-root.md": "/level2/2-root/",
"level2/level3/3-root.md": "/level2/level3/3-root/",
"/docs/level2/level3/3-root.md": "/level2/level3/3-root/",
"/docs/level2/2-root/": "/level2/2-root/",
"/docs/level2/2-root": "/level2/2-root/",
"/level2/2-root/": "/level2/2-root/",
"/level2/2-root": "/level2/2-root/",
}, "rootfile.md": map[string]string{
"/docs/rootfile.md": "/rootfile/",
"rootfile.md": "/rootfile/",
"level2/2-root.md": "/level2/2-root/",
"/docs/level2/2-root.md": "/level2/2-root/",
"level2/level3/3-root.md": "/level2/level3/3-root/",
"/docs/level2/level3/3-root.md": "/level2/level3/3-root/",
}, "level2/2-root.md": map[string]string{
"../rootfile.md": "/rootfile/",
"/docs/rootfile.md": "/rootfile/",
"2-root.md": "/level2/2-root/",
"../level2/2-root.md": "/level2/2-root/",
"./2-root.md": "/level2/2-root/",
"/docs/level2/2-root.md": "/level2/2-root/",
"level3/3-root.md": "/level2/level3/3-root/",
"../level2/level3/3-root.md": "/level2/level3/3-root/",
"/docs/level2/level3/3-root.md": "/level2/level3/3-root/",
}, "level2/index.md": map[string]string{
"../rootfile.md": "/rootfile/",
"/docs/rootfile.md": "/rootfile/",
"2-root.md": "/level2/2-root/",
"../level2/2-root.md": "/level2/2-root/",
"./2-root.md": "/level2/2-root/",
"/docs/level2/2-root.md": "/level2/2-root/",
"level3/3-root.md": "/level2/level3/3-root/",
"../level2/level3/3-root.md": "/level2/level3/3-root/",
"/docs/level2/level3/3-root.md": "/level2/level3/3-root/",
}, "level2/level3/3-root.md": map[string]string{
"../../rootfile.md": "/rootfile/",
"/docs/rootfile.md": "/rootfile/",
"../2-root.md": "/level2/2-root/",
"/docs/level2/2-root.md": "/level2/2-root/",
"3-root.md": "/level2/level3/3-root/",
"./3-root.md": "/level2/level3/3-root/",
"/docs/level2/level3/3-root.md": "/level2/level3/3-root/",
}, "level2/level3/index.md": map[string]string{
"../../rootfile.md": "/rootfile/",
"/docs/rootfile.md": "/rootfile/",
"../2-root.md": "/level2/2-root/",
"/docs/level2/2-root.md": "/level2/2-root/",
"3-root.md": "/level2/level3/3-root/",
"./3-root.md": "/level2/level3/3-root/",
"/docs/level2/level3/3-root.md": "/level2/level3/3-root/",
},
}
for currentFile, results := range okresults {
currentPage := findPage(site, currentFile)
if currentPage == nil {
t.Fatalf("failed to find current page in site")
}
for link, url := range results {
if out, err := site.Info.SourceRelativeLink(link, currentPage); err != nil || out != url {
t.Errorf("Expected %s to resolve to (%s), got (%s) - error: %s", link, url, out, err)
} else {
//t.Logf("tested ok %s maps to %s", link, out)
}
}
}
// TODO: and then the failure cases.
// "https://docker.com": "",
// site_test.go:1094: Expected https://docker.com to resolve to (), got () - error: Not a plain filepath link (https://docker.com)
}
func TestSourceRelativeLinkFileing(t *testing.T) {
t.Parallel()
site := setupLinkingMockSite(t)
type resultMap map[string]string
okresults := map[string]resultMap{
"index.md": map[string]string{
"/root-image.png": "/root-image.png",
"root-image.png": "/root-image.png",
}, "rootfile.md": map[string]string{
"/root-image.png": "/root-image.png",
}, "level2/2-root.md": map[string]string{
"/root-image.png": "/root-image.png",
"common.png": "/level2/common.png",
}, "level2/index.md": map[string]string{
"/root-image.png": "/root-image.png",
"common.png": "/level2/common.png",
"./common.png": "/level2/common.png",
}, "level2/level3/3-root.md": map[string]string{
"/root-image.png": "/root-image.png",
"common.png": "/level2/level3/common.png",
"../common.png": "/level2/common.png",
}, "level2/level3/index.md": map[string]string{
"/root-image.png": "/root-image.png",
"common.png": "/level2/level3/common.png",
"../common.png": "/level2/common.png",
},
}
for currentFile, results := range okresults {
currentPage := findPage(site, currentFile)
if currentPage == nil {
t.Fatalf("failed to find current page in site")
}
for link, url := range results {
if out, err := site.Info.SourceRelativeLinkFile(link, currentPage); err != nil || out != url {
t.Errorf("Expected %s to resolve to (%s), got (%s) - error: %s", link, url, out, err)
} else {
//t.Logf("tested ok %s maps to %s", link, out)
}
}
}
}