1// Copyright 2016-present The Hugo Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14package helpers
15
16import (
17	"strings"
18
19	"github.com/gohugoio/hugo/common/loggers"
20	"github.com/gohugoio/hugo/config"
21	"github.com/gohugoio/hugo/hugofs"
22	"github.com/gohugoio/hugo/hugolib/filesystems"
23	"github.com/gohugoio/hugo/hugolib/paths"
24)
25
26// PathSpec holds methods that decides how paths in URLs and files in Hugo should look like.
27type PathSpec struct {
28	*paths.Paths
29	*filesystems.BaseFs
30
31	ProcessingStats *ProcessingStats
32
33	// The file systems to use
34	Fs *hugofs.Fs
35
36	// The config provider to use
37	Cfg config.Provider
38}
39
40// NewPathSpec creates a new PathSpec from the given filesystems and language.
41func NewPathSpec(fs *hugofs.Fs, cfg config.Provider, logger loggers.Logger) (*PathSpec, error) {
42	return NewPathSpecWithBaseBaseFsProvided(fs, cfg, logger, nil)
43}
44
45// NewPathSpecWithBaseBaseFsProvided creats a new PathSpec from the given filesystems and language.
46// If an existing BaseFs is provided, parts of that is reused.
47func NewPathSpecWithBaseBaseFsProvided(fs *hugofs.Fs, cfg config.Provider, logger loggers.Logger, baseBaseFs *filesystems.BaseFs) (*PathSpec, error) {
48	p, err := paths.New(fs, cfg)
49	if err != nil {
50		return nil, err
51	}
52
53	var options []func(*filesystems.BaseFs) error
54	if baseBaseFs != nil {
55		options = []func(*filesystems.BaseFs) error{
56			filesystems.WithBaseFs(baseBaseFs),
57		}
58	}
59	bfs, err := filesystems.NewBase(p, logger, options...)
60	if err != nil {
61		return nil, err
62	}
63
64	ps := &PathSpec{
65		Paths:           p,
66		BaseFs:          bfs,
67		Fs:              fs,
68		Cfg:             cfg,
69		ProcessingStats: NewProcessingStats(p.Lang()),
70	}
71
72	basePath := ps.BaseURL.Path()
73	if basePath != "" && basePath != "/" {
74		ps.BasePath = basePath
75	}
76
77	return ps, nil
78}
79
80// PermalinkForBaseURL creates a permalink from the given link and baseURL.
81func (p *PathSpec) PermalinkForBaseURL(link, baseURL string) string {
82	link = strings.TrimPrefix(link, "/")
83	if !strings.HasSuffix(baseURL, "/") {
84		baseURL += "/"
85	}
86	return baseURL + link
87}
88