hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

sourceSpec.go (3848B)

    1 // Copyright 2017-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 
   14 package source
   15 
   16 import (
   17 	"os"
   18 	"path/filepath"
   19 	"regexp"
   20 	"runtime"
   21 
   22 	"github.com/gohugoio/hugo/hugofs/glob"
   23 
   24 	"github.com/gohugoio/hugo/langs"
   25 	"github.com/spf13/afero"
   26 
   27 	"github.com/gohugoio/hugo/helpers"
   28 	"github.com/spf13/cast"
   29 )
   30 
   31 // SourceSpec abstracts language-specific file creation.
   32 // TODO(bep) rename to Spec
   33 type SourceSpec struct {
   34 	*helpers.PathSpec
   35 
   36 	SourceFs afero.Fs
   37 
   38 	shouldInclude func(filename string) bool
   39 
   40 	Languages              map[string]any
   41 	DefaultContentLanguage string
   42 	DisabledLanguages      map[string]bool
   43 }
   44 
   45 // NewSourceSpec initializes SourceSpec using languages the given filesystem and PathSpec.
   46 func NewSourceSpec(ps *helpers.PathSpec, inclusionFilter *glob.FilenameFilter, fs afero.Fs) *SourceSpec {
   47 	cfg := ps.Cfg
   48 	defaultLang := cfg.GetString("defaultContentLanguage")
   49 	languages := cfg.GetStringMap("languages")
   50 
   51 	disabledLangsSet := make(map[string]bool)
   52 
   53 	for _, disabledLang := range cfg.GetStringSlice("disableLanguages") {
   54 		disabledLangsSet[disabledLang] = true
   55 	}
   56 
   57 	if len(languages) == 0 {
   58 		l := langs.NewDefaultLanguage(cfg)
   59 		languages[l.Lang] = l
   60 		defaultLang = l.Lang
   61 	}
   62 
   63 	ignoreFiles := cast.ToStringSlice(cfg.Get("ignoreFiles"))
   64 	var regexps []*regexp.Regexp
   65 	if len(ignoreFiles) > 0 {
   66 		for _, ignorePattern := range ignoreFiles {
   67 			re, err := regexp.Compile(ignorePattern)
   68 			if err != nil {
   69 				helpers.DistinctErrorLog.Printf("Invalid regexp %q in ignoreFiles: %s", ignorePattern, err)
   70 			} else {
   71 				regexps = append(regexps, re)
   72 			}
   73 
   74 		}
   75 	}
   76 	shouldInclude := func(filename string) bool {
   77 		if !inclusionFilter.Match(filename, false) {
   78 			return false
   79 		}
   80 		for _, r := range regexps {
   81 			if r.MatchString(filename) {
   82 				return false
   83 			}
   84 		}
   85 		return true
   86 	}
   87 
   88 	return &SourceSpec{shouldInclude: shouldInclude, PathSpec: ps, SourceFs: fs, Languages: languages, DefaultContentLanguage: defaultLang, DisabledLanguages: disabledLangsSet}
   89 }
   90 
   91 // IgnoreFile returns whether a given file should be ignored.
   92 func (s *SourceSpec) IgnoreFile(filename string) bool {
   93 	if filename == "" {
   94 		if _, ok := s.SourceFs.(*afero.OsFs); ok {
   95 			return true
   96 		}
   97 		return false
   98 	}
   99 
  100 	base := filepath.Base(filename)
  101 
  102 	if len(base) > 0 {
  103 		first := base[0]
  104 		last := base[len(base)-1]
  105 		if first == '.' ||
  106 			first == '#' ||
  107 			last == '~' {
  108 			return true
  109 		}
  110 	}
  111 
  112 	if !s.shouldInclude(filename) {
  113 		return true
  114 	}
  115 
  116 	if runtime.GOOS == "windows" {
  117 		// Also check the forward slash variant if different.
  118 		unixFilename := filepath.ToSlash(filename)
  119 		if unixFilename != filename {
  120 			if !s.shouldInclude(unixFilename) {
  121 				return true
  122 			}
  123 		}
  124 	}
  125 
  126 	return false
  127 }
  128 
  129 // IsRegularSourceFile returns whether filename represents a regular file in the
  130 // source filesystem.
  131 func (s *SourceSpec) IsRegularSourceFile(filename string) (bool, error) {
  132 	fi, err := helpers.LstatIfPossible(s.SourceFs, filename)
  133 	if err != nil {
  134 		return false, err
  135 	}
  136 
  137 	if fi.IsDir() {
  138 		return false, nil
  139 	}
  140 
  141 	if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
  142 		link, err := filepath.EvalSymlinks(filename)
  143 		if err != nil {
  144 			return false, err
  145 		}
  146 
  147 		fi, err = helpers.LstatIfPossible(s.SourceFs, link)
  148 		if err != nil {
  149 			return false, err
  150 		}
  151 
  152 		if fi.IsDir() {
  153 			return false, nil
  154 		}
  155 	}
  156 
  157 	return true, nil
  158 }