summaryrefslogtreecommitdiffstats
path: root/source/fileInfo.go
diff options
context:
space:
mode:
Diffstat (limited to 'source/fileInfo.go')
-rw-r--r--source/fileInfo.go213
1 files changed, 213 insertions, 0 deletions
diff --git a/source/fileInfo.go b/source/fileInfo.go
new file mode 100644
index 000000000..e4b4a80fb
--- /dev/null
+++ b/source/fileInfo.go
@@ -0,0 +1,213 @@
+// Copyright 2017-present The Hugo Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package source
+
+import (
+ "io"
+ "os"
+ "path/filepath"
+ "strings"
+ "sync"
+
+ "github.com/gohugoio/hugo/helpers"
+)
+
+// fileInfo implements the File interface.
+var (
+ _ File = (*FileInfo)(nil)
+ _ ReadableFile = (*FileInfo)(nil)
+)
+
+type File interface {
+
+ // Filename gets the full path and filename to the file.
+ Filename() string
+
+ // Path gets the relative path including file name and extension.
+ // The directory is relative to the content root.
+ Path() string
+
+ // Dir gets the name of the directory that contains this file.
+ // The directory is relative to the content root.
+ Dir() string
+
+ // Extension gets the file extension, i.e "myblogpost.md" will return "md".
+ Extension() string
+ // Ext is an alias for Extension.
+ Ext() string // Hmm... Deprecate Extension
+
+ // Lang for this page, if `Multilingual` is enabled on your site.
+ Lang() string
+
+ // LogicalName is filename and extension of the file.
+ LogicalName() string
+
+ // Section is first directory below the content root.
+ Section() string
+
+ // BaseFileName is a filename without extension.
+ BaseFileName() string
+
+ // TranslationBaseName is a filename with no extension,
+ // not even the optional language extension part.
+ TranslationBaseName() string
+
+ // UniqueID is the MD5 hash of the file's path and is for most practical applications,
+ // Hugo content files being one of them, considered to be unique.
+ UniqueID() string
+
+ FileInfo() os.FileInfo
+
+ String() string
+
+ // Deprecated
+ Bytes() []byte
+}
+
+// A ReadableFile is a File that is readable.
+type ReadableFile interface {
+ File
+ Open() (io.ReadCloser, error)
+}
+
+type FileInfo struct {
+
+ // Absolute filename to the file on disk.
+ filename string
+ fi os.FileInfo
+
+ // Derived from filename
+ ext string // Extension without any "."
+ lang string
+
+ name string
+
+ dir string
+ relDir string
+ relPath string
+ baseName string
+ translationBaseName string
+ section string
+
+ uniqueID string
+
+ sp *SourceSpec
+
+ lazyInit sync.Once
+}
+
+func (fi *FileInfo) Filename() string { return fi.filename }
+func (fi *FileInfo) Path() string { return fi.relPath }
+func (fi *FileInfo) Dir() string { return fi.relDir }
+func (fi *FileInfo) Extension() string { return fi.Ext() }
+func (fi *FileInfo) Ext() string { return fi.ext }
+func (fi *FileInfo) Lang() string { return fi.lang }
+func (fi *FileInfo) LogicalName() string { return fi.name }
+func (fi *FileInfo) BaseFileName() string { return fi.baseName }
+func (fi *FileInfo) TranslationBaseName() string { return fi.translationBaseName }
+
+func (fi *FileInfo) Section() string {
+ fi.init()
+ return fi.section
+}
+
+func (fi *FileInfo) UniqueID() string {
+ fi.init()
+ return fi.uniqueID
+}
+func (fi *FileInfo) FileInfo() os.FileInfo {
+ return fi.fi
+}
+
+func (fi *FileInfo) Bytes() []byte {
+ // Remove in Hugo 0.34
+ helpers.Deprecated("File", "Bytes", "", false)
+ return []byte("")
+}
+
+func (fi *FileInfo) String() string { return fi.BaseFileName() }
+
+// We create a lot of these FileInfo objects, but there are parts of it used only
+// in some cases that is slightly expensive to construct.
+func (fi *FileInfo) init() {
+ fi.lazyInit.Do(func() {
+ parts := strings.Split(fi.relDir, helpers.FilePathSeparator)
+ var section string
+ if len(parts) == 1 {
+ section = parts[0]
+ } else if len(parts) > 1 {
+ if parts[0] == "" {
+ section = parts[1]
+ } else {
+ section = parts[0]
+ }
+ }
+
+ fi.section = section
+
+ fi.uniqueID = helpers.MD5String(filepath.ToSlash(fi.relPath))
+
+ })
+}
+
+func (sp *SourceSpec) NewFileInfo(baseDir, filename string, fi os.FileInfo) *FileInfo {
+ dir, name := filepath.Split(filename)
+
+ dir = strings.TrimSuffix(dir, helpers.FilePathSeparator)
+ baseDir = strings.TrimSuffix(baseDir, helpers.FilePathSeparator)
+
+ relDir := ""
+ if dir != baseDir {
+ relDir = strings.TrimPrefix(dir, baseDir)
+ }
+
+ relDir = strings.TrimPrefix(relDir, helpers.FilePathSeparator)
+
+ relPath := filepath.Join(relDir, name)
+
+ ext := strings.ToLower(strings.TrimPrefix(filepath.Ext(name), "."))
+ baseName := helpers.Filename(name)
+
+ lang := strings.TrimPrefix(filepath.Ext(baseName), ".")
+ var translationBaseName string
+
+ if _, ok := sp.Languages[lang]; lang == "" || !ok {
+ lang = sp.DefaultContentLanguage
+ translationBaseName = baseName
+ } else {
+ translationBaseName = helpers.Filename(baseName)
+ }
+
+ f := &FileInfo{
+ sp: sp,
+ filename: filename,
+ fi: fi,
+ lang: lang,
+ ext: ext,
+ dir: dir,
+ relDir: relDir,
+ relPath: relPath,
+ name: name,
+ baseName: baseName,
+ translationBaseName: translationBaseName,
+ }
+
+ return f
+
+}
+
+// Open implements ReadableFile.
+func (fi *FileInfo) Open() (io.ReadCloser, error) {
+ return fi.sp.Fs.Source.Open(fi.Filename())
+}