Documentation ¶
Index ¶
- Variables
- func CreationTime(absolutePath string, fileInfo fs.FileInfo) time.Time
- func DatabaseCatalog(dialect string) (*ddl.Catalog, error)
- func FilesCatalog(dialect string) (*ddl.Catalog, error)
- func HumanReadableFileSize(size int64) string
- func IsForeignKeyViolation(dialect string, errorCode string) bool
- func IsFulltextIndexed(filePath string) bool
- func IsKeyViolation(dialect string, errorCode string) bool
- func NewTemplateError(err error) error
- func RealClientIP(r *http.Request, realIPHeaders map[netip.Addr]string, ...) netip.Addr
- func ServeFile(w http.ResponseWriter, r *http.Request, name string, size int64, ...)
- func UnmarshalCatalog(dialect string, b []byte) (*ddl.Catalog, error)
- type AtomCDATA
- type AtomEntry
- type AtomFeed
- type AtomLink
- type AtomText
- type Attribute
- type DatabaseFS
- func (fsys *DatabaseFS) As(target any) bool
- func (fsys *DatabaseFS) Copy(srcName, destName string) error
- func (fsys *DatabaseFS) Mkdir(name string, _ fs.FileMode) error
- func (fsys *DatabaseFS) MkdirAll(name string, _ fs.FileMode) error
- func (fsys *DatabaseFS) Open(name string) (fs.File, error)
- func (fsys *DatabaseFS) OpenWriter(name string, _ fs.FileMode) (io.WriteCloser, error)
- func (fsys *DatabaseFS) ReadDir(name string) ([]fs.DirEntry, error)
- func (fsys *DatabaseFS) Remove(name string) error
- func (fsys *DatabaseFS) RemoveAll(name string) error
- func (fsys *DatabaseFS) Rename(oldName, newName string) error
- func (fsys *DatabaseFS) Stat(name string) (fs.FileInfo, error)
- func (fsys *DatabaseFS) WithContext(ctx context.Context) FS
- func (fsys *DatabaseFS) WithValues(values map[string]any) FS
- type DatabaseFSConfig
- type DatabaseFile
- type DatabaseFileInfo
- func (fileInfo *DatabaseFileInfo) Info() (fs.FileInfo, error)
- func (fileInfo *DatabaseFileInfo) IsDir() bool
- func (fileInfo *DatabaseFileInfo) ModTime() time.Time
- func (fileInfo *DatabaseFileInfo) Mode() fs.FileMode
- func (fileInfo *DatabaseFileInfo) Name() string
- func (fileInfo *DatabaseFileInfo) Size() int64
- func (fileInfo *DatabaseFileInfo) Sys() any
- func (fileInfo *DatabaseFileInfo) Type() fs.FileMode
- type DatabaseFileWriter
- type DirectoryFS
- func (fsys *DirectoryFS) As(target any) bool
- func (fsys *DirectoryFS) Copy(srcName, destName string) error
- func (fsys *DirectoryFS) Mkdir(name string, _ fs.FileMode) error
- func (fsys *DirectoryFS) MkdirAll(name string, _ fs.FileMode) error
- func (fsys *DirectoryFS) Open(name string) (fs.File, error)
- func (fsys *DirectoryFS) OpenWriter(name string, _ fs.FileMode) (io.WriteCloser, error)
- func (fsys *DirectoryFS) ReadDir(name string) ([]fs.DirEntry, error)
- func (fsys *DirectoryFS) Remove(name string) error
- func (fsys *DirectoryFS) RemoveAll(name string) error
- func (fsys *DirectoryFS) Rename(oldName, newName string) error
- func (fsys *DirectoryFS) Stat(name string) (fs.FileInfo, error)
- func (fsys *DirectoryFS) WithContext(ctx context.Context) FS
- type DirectoryFSConfig
- type DirectoryFileWriter
- type DirectoryObjectStorage
- func (storage *DirectoryObjectStorage) Copy(ctx context.Context, srcKey, destKey string) error
- func (storage *DirectoryObjectStorage) Delete(ctx context.Context, key string) error
- func (storage *DirectoryObjectStorage) Get(ctx context.Context, key string) (io.ReadCloser, error)
- func (storage *DirectoryObjectStorage) Put(ctx context.Context, key string, reader io.Reader) error
- type FS
- type FileType
- type Heading
- type ID
- type Image
- type LimitedWriter
- type Mail
- type Mailer
- type MailerConfig
- type MaxMindDBRecord
- type NavigationLink
- type Notebrew
- func (nbrew *Notebrew) AccountDisabled(w http.ResponseWriter, r *http.Request, disableReason string)
- func (nbrew *Notebrew) AddSecurityHeaders(w http.ResponseWriter)
- func (nbrew *Notebrew) BadRequest(w http.ResponseWriter, r *http.Request, serverErr error)
- func (nbrew *Notebrew) Close() error
- func (nbrew *Notebrew) ContentBaseURL(sitePrefix string) string
- func (nbrew *Notebrew) ExecuteTemplate(w http.ResponseWriter, r *http.Request, tmpl *template.Template, data any)
- func (nbrew *Notebrew) GetFlashSession(w http.ResponseWriter, r *http.Request, valuePtr any) (ok bool, err error)
- func (nbrew *Notebrew) GetLogger(ctx context.Context) *slog.Logger
- func (nbrew *Notebrew) GetReferer(r *http.Request) string
- func (nbrew *Notebrew) InternalServerError(w http.ResponseWriter, r *http.Request, serverErr error)
- func (nbrew *Notebrew) MethodNotAllowed(w http.ResponseWriter, r *http.Request)
- func (nbrew *Notebrew) NotAuthenticated(w http.ResponseWriter, r *http.Request)
- func (nbrew *Notebrew) NotAuthorized(w http.ResponseWriter, r *http.Request)
- func (nbrew *Notebrew) NotFound(w http.ResponseWriter, r *http.Request)
- func (nbrew *Notebrew) RedirectToHTTPS(w http.ResponseWriter, r *http.Request)
- func (nbrew *Notebrew) RegenerateSite(ctx context.Context, sitePrefix string) (RegenerationStats, error)
- func (nbrew *Notebrew) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (nbrew *Notebrew) SetFlashSession(w http.ResponseWriter, r *http.Request, value any) error
- func (nbrew *Notebrew) StorageLimitExceeded(w http.ResponseWriter, r *http.Request)
- func (nbrew *Notebrew) UnsupportedContentType(w http.ResponseWriter, r *http.Request)
- type ObjectStorage
- type Page
- type PageData
- type Pagination
- type Post
- type PostData
- type PostListData
- type RegenerationStats
- type ReplicatedFS
- func (fsys *ReplicatedFS) As(target any) bool
- func (fsys *ReplicatedFS) Close() error
- func (fsys *ReplicatedFS) Copy(srcName, destName string) error
- func (fsys *ReplicatedFS) Mkdir(name string, perm fs.FileMode) error
- func (fsys *ReplicatedFS) MkdirAll(name string, perm fs.FileMode) error
- func (fsys *ReplicatedFS) Open(name string) (fs.File, error)
- func (fsys *ReplicatedFS) OpenWriter(name string, perm fs.FileMode) (io.WriteCloser, error)
- func (fsys *ReplicatedFS) ReadDir(name string) ([]fs.DirEntry, error)
- func (fsys *ReplicatedFS) Remove(name string) error
- func (fsys *ReplicatedFS) RemoveAll(name string) error
- func (fsys *ReplicatedFS) Rename(oldName, newName string) error
- func (fsys *ReplicatedFS) Stat(name string) (fs.FileInfo, error)
- func (fsys *ReplicatedFS) WithContext(ctx context.Context) FS
- func (fsys *ReplicatedFS) WithValues(values map[string]any) FS
- type ReplicatedFSConfig
- type ReplicatedFileWriter
- type S3ObjectStorage
- func (storage *S3ObjectStorage) Copy(ctx context.Context, srcKey, destKey string) error
- func (storage *S3ObjectStorage) Delete(ctx context.Context, key string) error
- func (storage *S3ObjectStorage) Get(ctx context.Context, key string) (io.ReadCloser, error)
- func (storage *S3ObjectStorage) Put(ctx context.Context, key string, reader io.Reader) error
- type S3StorageConfig
- type SFTPClient
- type SFTPFS
- func (fsys *SFTPFS) As(target any) bool
- func (fsys *SFTPFS) Close() error
- func (fsys *SFTPFS) Copy(srcName, destName string) error
- func (fsys *SFTPFS) Mkdir(name string, _ fs.FileMode) error
- func (fsys *SFTPFS) MkdirAll(name string, _ fs.FileMode) error
- func (fsys *SFTPFS) Open(name string) (fs.File, error)
- func (fsys *SFTPFS) OpenWriter(name string, perm fs.FileMode) (io.WriteCloser, error)
- func (fsys *SFTPFS) ReadDir(name string) ([]fs.DirEntry, error)
- func (fsys *SFTPFS) Remove(name string) error
- func (fsys *SFTPFS) RemoveAll(name string) error
- func (fsys *SFTPFS) Rename(oldName, newName string) error
- func (fsys *SFTPFS) Stat(name string) (fs.FileInfo, error)
- func (fsys *SFTPFS) WithContext(ctx context.Context) FS
- type SFTPFSConfig
- type SFTPFileWriter
- type Site
- type SiteConfig
- type SiteGenerator
- func (siteGen *SiteGenerator) GeneratePage(ctx context.Context, filePath, text string, modTime, creationTime time.Time) error
- func (siteGen *SiteGenerator) GeneratePost(ctx context.Context, filePath, text string, modTime, creationTime time.Time, ...) error
- func (siteGen *SiteGenerator) GeneratePostList(ctx context.Context, category string, tmpl *template.Template) (int64, error)
- func (siteGen *SiteGenerator) GeneratePostListPage(ctx context.Context, category string, tmpl *template.Template, ...) error
- func (siteGen *SiteGenerator) GeneratePosts(ctx context.Context, category string, tmpl *template.Template) (int64, error)
- func (siteGen *SiteGenerator) ParseTemplate(ctx context.Context, name, text string) (*template.Template, error)
- func (siteGen *SiteGenerator) PostListTemplate(ctx context.Context, category string) (*template.Template, error)
- func (siteGen *SiteGenerator) PostTemplate(ctx context.Context, category string) (*template.Template, error)
- type SiteGeneratorConfig
- type TemplateError
- type User
Constants ¶
This section is empty.
Variables ¶
var ( // RuntimeFS is the FS containing the runtime files needed by notebrew for // operation. RuntimeFS fs.FS = embedFS // StylesCSS is the contents of the styles.css file in the embed/ // directory. StylesCSS string // StylesCSSHash is the sha256 hash of the StylesCSS contents. StylesCSSHash string // BaselineJS is the contents of the baseline.js file in the embed/ // directory. BaselineJS string // BaselineJSHash is the sha256 hash of the BaselineJS contents. BaselineJSHash string // Version holds the current notebrew git revision. Version string // CountryCodes is the ISO code to country mapping from country_codes.json // in the embed/ directory. CountryCodes map[string]string // ReservedSubdomains is the list of reserved subdomains that users will // not be able to use on the content domain. ReservedSubdomains = []string{"www", "cdn", "storage", "videocdn", "videostorage"} )
var AllowedFileTypes = map[string]FileType{ ".html": { Ext: ".html", ContentType: "text/html; charset=utf-8", SizeLimit: 1 << 20, Attribute: AttributeGzippable | AttributeEditable, }, ".css": { Ext: ".css", ContentType: "text/css; charset=utf-8", SizeLimit: 1 << 20, Attribute: AttributeGzippable | AttributeEditable, }, ".js": { Ext: ".js", ContentType: "text/javascript; charset=utf-8", SizeLimit: 1 << 20, Attribute: AttributeGzippable | AttributeEditable, }, ".md": { Ext: ".md", ContentType: "text/markdown; charset=utf-8", SizeLimit: 1 << 20, Attribute: AttributeGzippable | AttributeEditable, }, ".txt": { Ext: ".txt", ContentType: "text/plain; charset=utf-8", SizeLimit: 1 << 20, Attribute: AttributeGzippable | AttributeEditable, }, ".jpeg": { Ext: ".jpeg", ContentType: "image/jpeg", SizeLimit: 10 << 20, Attribute: AttributeObject | AttributeImg, }, ".jpg": { Ext: ".jpg", ContentType: "image/jpeg", SizeLimit: 10 << 20, Attribute: AttributeObject | AttributeImg, }, ".png": { Ext: ".png", ContentType: "image/png", SizeLimit: 10 << 20, Attribute: AttributeObject | AttributeImg, }, ".webp": { Ext: ".webp", ContentType: "image/webp", SizeLimit: 10 << 20, Attribute: AttributeObject | AttributeImg, }, ".gif": { Ext: ".gif", ContentType: "image/gif", SizeLimit: 10 << 20, Attribute: AttributeObject | AttributeImg, }, ".svg": { Ext: ".svg", ContentType: "image/svg+xml", SizeLimit: 1 << 20, Attribute: AttributeGzippable | AttributeImg, }, ".eot": { Ext: ".eot", ContentType: "font/eot", SizeLimit: 2 << 20, Attribute: AttributeGzippable | AttributeFont, }, ".otf": { Ext: ".otf", ContentType: "font/otf", SizeLimit: 2 << 20, Attribute: AttributeGzippable | AttributeFont, }, ".ttf": { Ext: ".ttf", ContentType: "font/ttf", SizeLimit: 2 << 20, Attribute: AttributeGzippable | AttributeFont, }, ".woff": { Ext: ".woff", ContentType: "font/woff", SizeLimit: 2 << 20, Attribute: AttributeFont, }, ".woff2": { Ext: ".woff2", ContentType: "font/woff2", SizeLimit: 2 << 20, Attribute: AttributeFont, }, ".atom": { Ext: ".atom", ContentType: "application/atom+xml; charset=utf-8", SizeLimit: 1 << 20, Attribute: AttributeGzippable, }, ".json": { Ext: ".json", ContentType: "application/json", SizeLimit: 1 << 20, Attribute: AttributeGzippable, }, ".tgz": { Ext: ".tgz", ContentType: "application/octet-stream", SizeLimit: -1, Attribute: AttributeObject | AttributeAttachment, }, }
AllowedFileTypes is a list of file types allowed by notebrew.
It is exported so that people using notebrew as a library may add their own file types to it, although no effort has been made to test whether such additions would work seamlessly with the rest of the library.
var ErrStorageLimitExceeded = fmt.Errorf("storage limit exceeded")
ErrStorageLimitExceeded is the error returned by an operation if a user exceeded their storage limit during the operation.
var LoggerKey = &contextKey{}
LoggerKey is the key used by notebrew for setting and getting a logger from the request context.
Functions ¶
func CreationTime ¶
CreationTime returns the creation time of a file given its absolute file path and fs.FileInfo.
func DatabaseCatalog ¶
DatabaseCatalog returns a catalog representing the desired catalog schema for the database.
func FilesCatalog ¶
FilesCatalog returns a catalog representing the desired catalog schema for the files database.
func HumanReadableFileSize ¶
HumanReadableFileSize returns a human readable file size of an int64 size in bytes.
func IsForeignKeyViolation ¶
IsForeignKeyViolation returns true if the provided errorCode matches the dialect-specific code for representing a foreign key constraint violation.
func IsFulltextIndexed ¶
IsFulltextIndexed reports whether a file is eligible for fulltext indexing by virtue of its position within the filesystem. For example, html files in the pages directory are fulltext indexed but not html files in the output directory because those are generated by notebrew itself (we don't want to index generated files, only user source files).
If a file is not fulltext-indexed, it is stored in a DatabaseFS in gzipped form to save space and also to save CPU cycles as we don't have to gzip again when serving it later.
func IsKeyViolation ¶
IsKeyViolation returns true if the provided errorCode matches the dialect-specific code for representing a primary key/unique constraint violation.
func NewTemplateError ¶
NewTemplateError constructs a new TemplateError from an error returned by the html/template package by parsing the error string, which is unfortunately the only way we can extract the template name and line number.
func RealClientIP ¶
func RealClientIP(r *http.Request, realIPHeaders map[netip.Addr]string, proxyIPs map[netip.Addr]struct{}) netip.Addr
RealClientIP returns the real client IP of the request.
func ServeFile ¶
func ServeFile(w http.ResponseWriter, r *http.Request, name string, size int64, fileType FileType, reader io.Reader, cacheControl string)
ServeFile serves a given file (in the form of an io.Reader). It applies a potential list of optimizations such as gzipping the response, handling Range requests, calculating the ETag and setting the Cache-Control header.
Types ¶
type AtomEntry ¶
type AtomEntry struct { ID string `xml:"id"` Title string `xml:"title"` Published string `xml:"published"` Updated string `xml:"updated"` Link []AtomLink `xml:"link"` Summary AtomText `xml:"summary"` Content AtomCDATA `xml:"content"` }
AtomEntry represents an atom entry (i.e. a post).
type AtomFeed ¶
type AtomFeed struct { XMLName xml.Name `xml:"feed"` Xmlns string `xml:"xmlns,attr"` ID string `xml:"id"` Title string `xml:"title"` Updated string `xml:"updated"` Link []AtomLink `xml:"link"` Entry []AtomEntry `xml:"entry"` }
AtomFeed represents an atom feed (i.e. a list of posts).
type Attribute ¶
type Attribute int
Attribute represents the various attributes that a file type have e.g. whether it is gzippable, whether it's an object, etc.
const ( AttributeGzippable Attribute = 1 << 0 // Should be gzipped when sent in the response body. AttributeObject Attribute = 1 << 1 // Should be stored in ObjectStorage (instead of the database). AttributeAttachment Attribute = 1 << 2 // Should be downloaded with Content-Disposition: attachment. AttributeEditable Attribute = 1 << 3 // Can be edited by the user. AttributeFont Attribute = 1 << 4 // Can be used as a @font-face src. AttributeImg Attribute = 1 << 5 // Can be displayed with an <img> tag. AttributeVideo Attribute = 1 << 6 // Can be displayed with a <video> tag. )
type DatabaseFS ¶
type DatabaseFS struct { // DB is the sql database. DB *sql.DB // Dialect is the database dialect. Currently, the only dialects supported // are "sqlite", "postgres" and "mysql". Dialect string // ErrorCode converts an error returned by a database query into a // dialect-specific error code. ErrorCode func(error) string // ObjectStorage is used for storage of binary objects. ObjectStorage ObjectStorage // Logger is used for reporting errors that cannot be handled and are // thrown away. Logger *slog.Logger // UpdateStorageUsed is called whenever the storage used by a site changes // (delta being the number of bytes that have been added or removed). // Specifically, this happens on calls to OpenWriter, Remove, RemoveAll and // Copy. UpdateStorageUsed func(ctx context.Context, siteName string, delta int64) error // contains filtered or unexported fields }
DatabaseFS implements a writeable filesystem using a database and an ObjectStorage provider.
func NewDatabaseFS ¶
func NewDatabaseFS(config DatabaseFSConfig) (*DatabaseFS, error)
NewDatabaseFS constructs a new DatabaseFS.
func (*DatabaseFS) As ¶
func (fsys *DatabaseFS) As(target any) bool
As writes the current databaseFS into the target if it is a valid DatabaseFS pointer.
func (*DatabaseFS) Copy ¶
func (fsys *DatabaseFS) Copy(srcName, destName string) error
Copy implements the Copy FS operation for DatabaseFS.
func (*DatabaseFS) Mkdir ¶
func (fsys *DatabaseFS) Mkdir(name string, _ fs.FileMode) error
Mkdir implements the Mkdir FS operation for DatabaseFS.
func (*DatabaseFS) MkdirAll ¶
func (fsys *DatabaseFS) MkdirAll(name string, _ fs.FileMode) error
MkdirAll implements the MkdirAll FS operation for DatabaseFS.
func (*DatabaseFS) Open ¶
func (fsys *DatabaseFS) Open(name string) (fs.File, error)
Open implements the Open FS operation for DatabaseFS.
func (*DatabaseFS) OpenWriter ¶
func (fsys *DatabaseFS) OpenWriter(name string, _ fs.FileMode) (io.WriteCloser, error)
OpenWriter implements the OpenWriter FS operation for DatabaseFS.
func (*DatabaseFS) ReadDir ¶
func (fsys *DatabaseFS) ReadDir(name string) ([]fs.DirEntry, error)
ReadDir implements the ReadDir FS operation for DatabaseFS.
func (*DatabaseFS) Remove ¶
func (fsys *DatabaseFS) Remove(name string) error
Remove implements the Remove FS operation for DatabaseFS.
func (*DatabaseFS) RemoveAll ¶
func (fsys *DatabaseFS) RemoveAll(name string) error
RemoveAll implements the RemoveAll FS operation for DatabaseFS.
func (*DatabaseFS) Rename ¶
func (fsys *DatabaseFS) Rename(oldName, newName string) error
Rename implements the Rename FS operation for DatabaseFS.
func (*DatabaseFS) Stat ¶
func (fsys *DatabaseFS) Stat(name string) (fs.FileInfo, error)
Stat implements the fs.StatFS interface.
func (*DatabaseFS) WithContext ¶
func (fsys *DatabaseFS) WithContext(ctx context.Context) FS
WithContext returns a new FS with the given context.
func (*DatabaseFS) WithValues ¶
func (fsys *DatabaseFS) WithValues(values map[string]any) FS
WithValues returns a new FS with the given values.
Currently, the following values are recognized:
- "modTime" => time.Time (sets the modTime for files created by OpenWriter/Mkdir/MkdirAll)
- "creationTime" => time.Time (sets the creationTime for files created by OpenWriter/Mkdir/MkdirAll)
- "caption" => string (sets the caption for images created by OpenWriter)
These values will apply to *all* filesystem operations, so if you only want to set the modTime or creationTime for a specific file you will have to create a new instance of a DatabaseFS using WithValues(), create that file, then throw the DatabaseFS instance away.
type DatabaseFSConfig ¶
type DatabaseFSConfig struct { // (Required) DB is the sql database. DB *sql.DB // (Required) Dialect is the database dialect. Currently, the only dialects // supported are "sqlite", "postgres" and "mysql". Dialect string // ErrorCode converts an error returned by a database query into a // dialect-specific error code. ErrorCode func(error) string // (Required) ObjectStorage is used for storage of binary objects. ObjectStorage ObjectStorage // (Required) Logger is used for reporting errors that cannot be handled // and are thrown away. Logger *slog.Logger // UpdateStorageUsed is called whenever the storage used by a site changes // (delta being the number of bytes that have been added or removed). // Specifically, this happens on calls to OpenWriter, Remove, RemoveAll and // Copy. UpdateStorageUsed func(ctx context.Context, siteName string, delta int64) error }
DatabaseFSConfig holds the parameters needed to construct a DatabaseFS.
type DatabaseFile ¶
type DatabaseFile struct {
// contains filtered or unexported fields
}
DatabaseFile represents a readable instance of a file returned by DatabaseFS.
func (*DatabaseFile) Close ¶
func (file *DatabaseFile) Close() error
Close closes the DatabaseFile from reading.
type DatabaseFileInfo ¶
type DatabaseFileInfo struct { FileID ID FilePath string CreationTime time.Time // contains filtered or unexported fields }
DatabaseFileInfo describes a file returned by DatabaseFS.
func (*DatabaseFileInfo) Info ¶
func (fileInfo *DatabaseFileInfo) Info() (fs.FileInfo, error)
Returns the file info (needed to implement fs.DirEntry).
func (*DatabaseFileInfo) IsDir ¶
func (fileInfo *DatabaseFileInfo) IsDir() bool
Whether the file is a directory.
func (*DatabaseFileInfo) ModTime ¶
func (fileInfo *DatabaseFileInfo) ModTime() time.Time
Modification time.
func (*DatabaseFileInfo) Mode ¶
func (fileInfo *DatabaseFileInfo) Mode() fs.FileMode
File mode bits.
func (*DatabaseFileInfo) Name ¶
func (fileInfo *DatabaseFileInfo) Name() string
Base name of the file.
func (*DatabaseFileInfo) Size ¶
func (fileInfo *DatabaseFileInfo) Size() int64
Size of the file in bytes.
func (*DatabaseFileInfo) Type ¶
func (fileInfo *DatabaseFileInfo) Type() fs.FileMode
Type bits (needed to implement fs.DirEntry).
type DatabaseFileWriter ¶
type DatabaseFileWriter struct {
// contains filtered or unexported fields
}
DatabaseFileWriter represents a writable file on a DatabaseFS.
func (*DatabaseFileWriter) Close ¶
func (file *DatabaseFileWriter) Close() error
Close saves the contents of the DatabaseFileWriter into the database and closes the DatabaseFileWriter.
type DirectoryFS ¶
type DirectoryFS struct { // RootDir is the root directory of the DirectoryFS. Has to be an absolute // path!! RootDir string // TempDir is used to store files while they are being written before being // renamed to their target destination when complete. // // Windows is the exception, as os.Rename on the temporary files (even // after I've closed them) intermittently returns "Access is denied" for no // discernable reason so I've skipped the temp file into rename workflow // for Windows entirely. TempDir string // contains filtered or unexported fields }
DirectoryFS implements a writeable filesystem using a local directory.
NOTE: Each FS method should only ever work with forward slash file path separators. Even on Windows, because Windows accepts forward slash file path separators just fine. This simplifies our implementation a lot because we only ever have to think about forward slashes.
func NewDirectoryFS ¶
func NewDirectoryFS(config DirectoryFSConfig) (*DirectoryFS, error)
NewDirectoryFS constructs a new DirectoryFS.
func (*DirectoryFS) As ¶
func (fsys *DirectoryFS) As(target any) bool
As writes the current directoryFS into the target if it is a valid DirectoryFS pointer.
func (*DirectoryFS) Copy ¶
func (fsys *DirectoryFS) Copy(srcName, destName string) error
Copy implements the Copy FS operation for DirectoryFS.
func (*DirectoryFS) Mkdir ¶
func (fsys *DirectoryFS) Mkdir(name string, _ fs.FileMode) error
Mkdir implements the Mkdir FS operation for DirectoryFS.
func (*DirectoryFS) MkdirAll ¶
func (fsys *DirectoryFS) MkdirAll(name string, _ fs.FileMode) error
MkdirAll implements the MkdirAll FS operation for DirectoryFS.
func (*DirectoryFS) Open ¶
func (fsys *DirectoryFS) Open(name string) (fs.File, error)
Open implements the Open FS operation for DirectoryFS.
func (*DirectoryFS) OpenWriter ¶
func (fsys *DirectoryFS) OpenWriter(name string, _ fs.FileMode) (io.WriteCloser, error)
OpenWriter implements the OpenWriter FS operation for DirectoryFS.
func (*DirectoryFS) ReadDir ¶
func (fsys *DirectoryFS) ReadDir(name string) ([]fs.DirEntry, error)
ReadDir implements the ReadDir FS operation for DirectoryFS.
func (*DirectoryFS) Remove ¶
func (fsys *DirectoryFS) Remove(name string) error
Remove implements the Remove FS operation for DirectoryFS.
func (*DirectoryFS) RemoveAll ¶
func (fsys *DirectoryFS) RemoveAll(name string) error
RemoveAll implements the RemoveAll FS operation for DirectoryFS.
func (*DirectoryFS) Rename ¶
func (fsys *DirectoryFS) Rename(oldName, newName string) error
Rename implements the Rename FS operation for DirectoryFS.
func (*DirectoryFS) Stat ¶
func (fsys *DirectoryFS) Stat(name string) (fs.FileInfo, error)
Stat implements the fs.StatFS interface.
func (*DirectoryFS) WithContext ¶
func (fsys *DirectoryFS) WithContext(ctx context.Context) FS
WithContext returns a new FS with the given context.
type DirectoryFSConfig ¶
type DirectoryFSConfig struct { // Root directory of the DirectoryFS. RootDir string // Temp directory of the DirectoryFS. TempDir string }
DirectoryFSConfig holds the parameters needed to construct a DirectoryFS.
type DirectoryFileWriter ¶
type DirectoryFileWriter struct {
// contains filtered or unexported fields
}
DirectoryFileWriter represents a writable file on a DirectoryFS.
func (*DirectoryFileWriter) Close ¶
func (file *DirectoryFileWriter) Close() error
Close saves the contents of the DirectoryFileWriter into a file and closes the DirectoryFileWriter.
type DirectoryObjectStorage ¶
type DirectoryObjectStorage struct { // Root directory to store objects in. RootDir string }
DirectoryObjectStorage implements ObjectStorage using a local directory.
func NewDirObjectStorage ¶
func NewDirObjectStorage(rootDir, tempDir string) (*DirectoryObjectStorage, error)
NewDirObjectStorage constructs a new DirectoryObjectStorage.
func (*DirectoryObjectStorage) Copy ¶
func (storage *DirectoryObjectStorage) Copy(ctx context.Context, srcKey, destKey string) error
Copy implements the Copy ObjectStorage operation for DirectoryObjectStorage.
func (*DirectoryObjectStorage) Delete ¶
func (storage *DirectoryObjectStorage) Delete(ctx context.Context, key string) error
Delete implements the Delete ObjectStorage operation for DirectoryObjectStorage.
func (*DirectoryObjectStorage) Get ¶
func (storage *DirectoryObjectStorage) Get(ctx context.Context, key string) (io.ReadCloser, error)
Get implements the Get ObjectStorage operation for DirectoryObjectStorage.
type FS ¶
type FS interface { // WithContext returns a new FS with the given context which applies to all // subsequent operations carried out by the filesystem. WithContext(context.Context) FS // Open opens the named file. Open(name string) (fs.File, error) // OpenWriter opens an io.WriteCloser that represents a writeable instance // of a file. The parent directory must exist. If the file doesn't exist, // it should be created. If the file exists, its should be truncated. Write // operations should ideally be atomic i.e. if two writers are writing to // the same file, last writer wins. OpenWriter(name string, perm fs.FileMode) (io.WriteCloser, error) // ReadDir reads the named directory and returns a list of directory // entries sorted by filename. ReadDir(name string) ([]fs.DirEntry, error) // Mkdir creates a new directory with the specified name. The directory // should not already exist. Mkdir(name string, perm fs.FileMode) error // MkdirAll creates a directory with the given name, along with any // necessary parents, and returns nil, or else returns an error. MkdirAll(name string, perm fs.FileMode) error // Remove removes the named file or directory. The file should exist. If // the file is a directory, the directory should be empty. Remove(name string) error // RemoveAll removes name and any children it contains. It removes // everything it can but returns the first error it encounters. If the path // does not exist, RemoveAll returns nil (no error). RemoveAll(name string) error // Rename renames (moves) oldName to newName. newName must not exist. Rename(oldName, newName string) error // Copy copies the srcName to destName. destName must not exist. Copy(srcName, destName string) error }
FS represents a writeable filesystem.
type FileType ¶
type FileType struct { Ext string // File extension. ContentType string // Content-Type that file should be served with. SizeLimit int64 // Size limit for the file type. Attribute Attribute // File type attributes. }
FileType represents a file type.
type Heading ¶
type Heading struct { // ID of the heading. ID string // Title of the heading. Title string // Level of the heading i.e. for h1 - h6. Level int // Subheadings of the heading. Subheadings []Heading // Running count of the heading. Position int }
Heading represents a markdown heading.
type ID ¶
type ID [16]byte
ID is a 16-byte UUID that is sortable by a timestamp component. The first 5 bytes of the ID are the timestamp component and the remaining 11 bytes are completely random. Unlike UUIDv7, there is no version byte and there are no monotonic guarantees, which makes generating a spec-compliant ID much simpler.
The timestamp component is 5 bytes so that it can be perfectly encoded by an 8-character Base32 string. While this feature is not used by IDs because they are always displayed in canonical UUID form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx for maxmimum compatibility, these 5 byte timestamps appear in other places in notebrew which do exploit the fact that they can be perfectly encoded by an 8-character Base32 string so it just seems like a good idea to ensure all timestamp prefixes occupy 5 bytes for consistency.
func ParseID ¶
ParseID parses a UUID string of the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx into an ID.
func (ID) IsZero ¶
IsZero reports if an ID is all zeroes, which is used to represent the null state.
func (ID) MarshalJSON ¶
MarshalJSON converts an ID to a JSON string in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
func (*ID) UnmarshalJSON ¶
UnmarshalJSON converts a JSON string in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx into an ID. If the JSON value is null, the existing ID's value is untouched.
type Image ¶
type Image struct { // Parent URL of the image. Parent string // Name of the image. Name string // AltText of the image. AltText string // Caption of the image. Caption string }
Image contains metadata about an image.
type LimitedWriter ¶
type LimitedWriter struct { W io.Writer // underlying writer N int64 // max bytes remaining Err error // error to be returned once limit is reached }
LimitedWriter is the missing counterpart of LimitedReader from the stdlib. https://github.com/golang/go/issues/54111#issuecomment-1220793565
type Mail ¶
type Mail struct { // MailFrom is the SMTP MAIL FROM instruction. MailFrom string // RcptTo is the SMTP RCPT TO instruction. RcptTo string // Headers are the SMTP headers, in the header name value pairs. Example: // // []string{ // "Subject", "Hello World!", // "Content-Type", "text/html; charset=utf-8", // "Reply-To", "helpdesk@example.com", // } Headers []string // Body is the SMTP email body. Body io.Reader }
Mail represents an SMTP email to be sent.
type Mailer ¶
type Mailer struct { // (Required) SMTP username. Username string // (Required) SMTP password. Password string // (Required) SMTP host. Host string // (Required) SMTP port. Port string // Limiter is a rate limiter set by the LimitInterval and LimitBurst fields // in MailerConfig. Limiter *rate.Limiter // C is the mail channel. C chan Mail // Logger is used for reporting errors that cannot be handled and are // thrown away. Logger *slog.Logger // contains filtered or unexported fields }
Mailer is responsible for sending emails (using SMTP). Send emails by writing to its C channel. Example:
mailer.C <- Mail{ MailFrom: "sender@email.com", RcptTo: "recipient@example.com", Headers: []string{ "Subject", "Hello World!", "Content-Type", "text/html; charset=utf-8", }, Body: strings.NewReader("<h1>Hello World!</h1>"), }
Once the mailer sends an email, it will keep the SMTP connection alive for up to 100 seconds. If another mail comes through the channel during that period, the SMTP connection will be reused to send that email and refreshes its timeout duration for another 100 seconds. When the mailer times out, the SMTP connection will be closed and any future mails will require establishing a new connection to the SMTP server.
Using rate limiter is opt-in (but advised) and has to be manually invoked by calling mailer.Limiter.Wait(ctx) or mailer.Limiter.Allow().
func NewMailer ¶
func NewMailer(config MailerConfig) (*Mailer, error)
NewMailer constructs a new Mailer. It starts a background job listening for incoming mails on the C channel, which can be shut down by calling the Close() method.
type MailerConfig ¶
type MailerConfig struct { // (Required) SMTP username. Username string // (Required) SMTP password. Password string // (Required) SMTP host. Host string // (Required) SMTP port. Port string // (Required) Interval for replenishing one token back to the rate limiter bucket. LimitInterval time.Duration // (Required) Maximum tokens that can be held by the rate limiter bucket at any time. LimitBurst int // (Required) Logger is used for reporting errors that cannot be handled // and are thrown away. Logger *slog.Logger }
MailerConfig holds the parameters needed to construct a Mailer.
type MaxMindDBRecord ¶
type MaxMindDBRecord struct { Country struct { ISOCode string `maxminddb:"iso_code"` } `maxminddb:"country"` }
MaxMindDBRecord is the struct used to retrieve the country for an IP address.
type NavigationLink ¶
NavigationLink represents a navigation link to be displayed in the site's navigation menu.
type Notebrew ¶
type Notebrew struct { // FS is the file system associated with the notebrew instance. FS FS // DB is the DB associated with the notebrew instance. DB *sql.DB // Dialect is Dialect of the database. Only sqlite, postgres and mysql // databases are supported. Dialect string // ErrorCode translates a database error into an dialect-specific error // code. If the error is not a database error or if no underlying // implementation is provided, ErrorCode should return an empty string. ErrorCode func(error) string // CMSDomain is the domain that the notebrew is using to serve the CMS. // Examples: localhost:6444, notebrew.com CMSDomain string // CMSDomainHTTPS indicates whether the CMS domain is currently being // served over HTTPS. CMSDomainHTTPS bool // ContentDomain is the domain that the notebrew instance is using to serve // the static generated content. Examples: localhost:6444, nbrew.net. ContentDomain string // ContentDomainHTTPS indicates whether the content domain is currently // being served over HTTPS. ContentDomainHTTPS bool // CDNDomain is the domain of the CDN that notebrew is using to host its // images. Examples: cdn.nbrew.net, nbrewcdn.net. CDNDomain string // ImgCmd is the command (must reside in $PATH) used to preprocess images // for the web before they are saved to the FS. Images in the notes folder // are never prerpocessed and are uploaded as-is. This serves as an a // escape hatch for users who wish to upload their images without any image // preprocessing, as they can upload images to the notes folder first // before moving it elsewhere. // // ImgCmd should take in arguments in the form of `<ImgCmd> $INPUT_PATH // $OUTPUT_PATH`, where $INPUT_PATH is the input path to the raw image and // $OUTPUT_PATH is output path where ImgCmd should save the preprocessed // image. ImgCmd string // (Required) Port is port that notebrew is listening on. Port int // IP4 is the IPv4 address of the current machine, if notebrew is currently // serving either port 80 (HTTP) or 443 (HTTPS). IP4 netip.Addr // IP6 is the IPv6 address of the current machine, if notebrew is currently // serving either port 80 (HTTP) or 443 (HTTPS). IP6 netip.Addr // Domains is the list of domains that need to point at notebrew for it to // work. Does not include user-created domains. Domains []string // ManagingDomains is the list of domains that the current instance of // notebrew is managing SSL certificates for. ManagingDomains []string // Captcha configuration. CaptchaConfig struct { // Captcha widget's script src. e.g. https://js.hcaptcha.com/1/api.js, // https://challenges.cloudflare.com/turnstile/v0/api.js WidgetScriptSrc template.URL // Captcha widget's container div class. e.g. h-captcha, cf-turnstile WidgetClass string // Captcha verification URL to make POST requests to. e.g. // https://api.hcaptcha.com/siteverify, // https://challenges.cloudflare.com/turnstile/v0/siteverify VerificationURL string // Captcha response token name. e.g. h-captcha-response, // cf-turnstile-response ResponseTokenName string // Captcha site key. SiteKey string // Captcha secret key. SecretKey string // CSP contains the Content-Security-Policy directive names and values // required for the captcha widget to work. CSP map[string]string } // Mailer is used to send out transactional emails e.g. password reset // emails. Mailer *Mailer // The default value for the SMTP MAIL FROM instruction. MailFrom string // The default value for the SMTP Reply-To header. ReplyTo string // Proxy configuration. ProxyConfig struct { // RealIPHeaders contains trusted IP addresses to HTTP headers that // they are known to populate the real client IP with. e.g. X-Real-IP, // True-Client-IP. RealIPHeaders map[netip.Addr]string // Contains the set of trusted proxy IP addresses. This is used when // resolving the real client IP from the X-Forwarded-For HTTP header // chain from right (most trusted) to left (most accurate). ProxyIPs map[netip.Addr]struct{} } // DNS provider (required for using wildcard certificates with // LetsEncrypt). DNSProvider interface { libdns.RecordAppender libdns.RecordDeleter libdns.RecordGetter libdns.RecordSetter } // CertStorage is the magic (certmagic) that automatically provisions SSL // certificates for notebrew. CertStorage certmagic.Storage // CertLogger is the logger used for a certmagic.Config. CertLogger *zap.Logger // ContentSecurityPolicy is the Content-Security-Policy HTTP header set for // every HTML response served on the CMS domain. ContentSecurityPolicy string // Logger is used for reporting errors that cannot be handled and are // thrown away. Logger *slog.Logger // MaxMindDBReader is the maxmind database reader used to reolve IP // addresses to their countries using a maxmind GeoIP database. MaxMindDBReader *maxminddb.Reader // contains filtered or unexported fields }
Notebrew represents a notebrew instance.
func New ¶
func New() *Notebrew
New returns a new instance of Notebrew. Each field within it still needs to be manually configured.
func (*Notebrew) AccountDisabled ¶
func (nbrew *Notebrew) AccountDisabled(w http.ResponseWriter, r *http.Request, disableReason string)
AccountDisabled indicates that a user's account is disabled.
func (*Notebrew) AddSecurityHeaders ¶
func (nbrew *Notebrew) AddSecurityHeaders(w http.ResponseWriter)
func (*Notebrew) BadRequest ¶
BadRequest indicates that something was wrong with the request data.
func (*Notebrew) Close ¶
Close shuts down the notebrew instance as well as any background jobs it may have spawned.
func (*Notebrew) ContentBaseURL ¶
ContentBaseURL returns the content site's base URL (starting with http:// or https://) for a given site prefix.
func (*Notebrew) ExecuteTemplate ¶
func (nbrew *Notebrew) ExecuteTemplate(w http.ResponseWriter, r *http.Request, tmpl *template.Template, data any)
ExecuteTemplate renders a given template with the given data into the ResponseWriter, but it first buffers the HTML output so that it can detect if any template errors occurred, and if so return 500 Internal Server Error instead. Additionally, it does on-the-fly gzipping of the HTML response as well as calculating the ETag so that the HTML may be cached by the client.
func (*Notebrew) GetFlashSession ¶
func (nbrew *Notebrew) GetFlashSession(w http.ResponseWriter, r *http.Request, valuePtr any) (ok bool, err error)
GetFlashSession retrieves a value from the user's flash session, unmarshals it into the valuePtr and then deletes the session. It returns a boolean result indicating if a flash session was retrieved.
func (*Notebrew) GetLogger ¶
GetLogger is a syntactic sugar operation for getting a request-specific logger from the context, or else it returns the default logger.
func (*Notebrew) GetReferer ¶
GetReferer is like (*http.Request).Referer() except it returns an empty string if the referer is the same as the current page's URL so that the user doesn't keep pressing back to the same page.
func (*Notebrew) InternalServerError ¶
InternalServerError is a catch-all handler for catching server errors and displaying it to the user.
This includes the error message as well as the stack trace and notebrew version, in hopes that a user will be able to give developers the detailed error and trace in order to diagnose the problem faster.
func (*Notebrew) MethodNotAllowed ¶
func (nbrew *Notebrew) MethodNotAllowed(w http.ResponseWriter, r *http.Request)
MethodNotAllowed indicates that the request method is not allowed.
func (*Notebrew) NotAuthenticated ¶
func (nbrew *Notebrew) NotAuthenticated(w http.ResponseWriter, r *http.Request)
NotAuthenticated indicates that the user is not logged in.
func (*Notebrew) NotAuthorized ¶
func (nbrew *Notebrew) NotAuthorized(w http.ResponseWriter, r *http.Request)
NotAuthorized indicates that the user is logged in, but is not authorized to view the current page or perform the current action.
func (*Notebrew) NotFound ¶
func (nbrew *Notebrew) NotFound(w http.ResponseWriter, r *http.Request)
NotFound indicates that a URL does not exist.
func (*Notebrew) RedirectToHTTPS ¶
func (nbrew *Notebrew) RedirectToHTTPS(w http.ResponseWriter, r *http.Request)
func (*Notebrew) RegenerateSite ¶
func (*Notebrew) ServeHTTP ¶
func (nbrew *Notebrew) ServeHTTP(w http.ResponseWriter, r *http.Request)
func (*Notebrew) SetFlashSession ¶
SetFlashSession writes a value into the user's flash session.
func (*Notebrew) StorageLimitExceeded ¶
func (nbrew *Notebrew) StorageLimitExceeded(w http.ResponseWriter, r *http.Request)
StorageLimitExceeded indicates that the user exceeded their storage limit.
func (*Notebrew) UnsupportedContentType ¶
func (nbrew *Notebrew) UnsupportedContentType(w http.ResponseWriter, r *http.Request)
UnsupportedContentType indicates that the request did not send a supported Content-Type.
type ObjectStorage ¶
type ObjectStorage interface { // Gets an object from a bucket. Get(ctx context.Context, key string) (io.ReadCloser, error) // Puts an object into a bucket. If key already exists, it should be // replaced. Put(ctx context.Context, key string, reader io.Reader) error // Deletes an object from a bucket. It returns no error if the object does // not exist. Delete(ctx context.Context, key string) error // Copies an object identified by srcKey into destKey. srcKey should exist. // If destKey already exists, it should be replaced. Copy(ctx context.Context, srcKey, destKey string) error }
ObjectStorage represents an object storage provider.
type Page ¶
type Page struct { // Parent URL of the page. Parent string // Name of the page. Name string // Title of the page. Title string }
Page contains metadata about a page.
type PageData ¶
type PageData struct { // Site information. Site Site // Parent URL of the page. Parent string // Name of the page. Name string // Title of the page. Title string // ChildPages of the page. ChildPages []Page // ContentMap of markdown file names to their file contents. Convert it to // HTML using the markdownToHTML template function. ContentMap map[string]string // Images belonging to the page. Images []Image // ModificationTime of the page. ModificationTime time.Time // CreationTime of the page. CreationTime time.Time }
PageData is the data used to render a page.
type Pagination ¶
type Pagination struct { // First page. First int // Previous page. Previous int // Current page. Current int // Next page. Next int // Last page. Last int // Numbers is the list of page numbers to display. Numbers []int }
Pagination represents the pagination information for a post list.
func NewPagination ¶
func NewPagination(currentPage, lastPage, visiblePages int) Pagination
NewPagination constructs a new pagination for a given range of pages.
type Post ¶
type Post struct { // Category of the post. Category string // Name of the post. Name string // Title of the post. Title string // Preview of the post. Preview string // Whether the post has more text after the preview. HasMore bool // Content of the post. Content string // Images belonging to the post. Images []Image // CreationTime of the post. CreationTime time.Time // ModificationTime of the post. ModificationTime time.Time // contains filtered or unexported fields }
Post contains metadata about a post.
type PostData ¶
type PostData struct { // Site information. Site Site // Category of the post. Category string // Name of the post. Name string // Title of the post. Title string // Content of the post. Content string // Images belonging to the post that are not already explicitly included in // the post content. Images []Image // CreationTime of the post. CreationTime time.Time // ModificationTime of the post. ModificationTime time.Time }
PostData is the data used to render a post.
type PostListData ¶
type PostListData struct { // Site information. Site Site // Category of the post list. Category string // Pagination information for the post list. Pagination Pagination // The lists of posts for the current page of the post list. Posts []Post }
PostListData is the data used to render a post list page.
type RegenerationStats ¶
type RegenerationStats struct { Count int64 `json:"count"` TimeTaken string `json:"timeTaken"` TemplateError TemplateError `json:"templateError"` }
type ReplicatedFS ¶
type ReplicatedFS struct { // Leader is the primary FS that we read from and write to. Leader FS // Followers are the secondary FSes that writes are replicated to. Followers []FS // If SynchronousReplication is true, writes will be synchronously // replicated to the followers. SynchronousReplication bool // (Required) Logger is used for reporting errors that cannot be handled // and are thrown away. Logger *slog.Logger // contains filtered or unexported fields }
SFTPFS implements a writeable filesystem on a leader FS and zero or more follower FSes. All reads come from the leader FS, while all writes will be sent to the leader FS as well as the follower FSes (synchronously or asynchronously depending on the SynchronousReplication field).
func NewReplicatedFS ¶
func NewReplicatedFS(config ReplicatedFSConfig) (*ReplicatedFS, error)
NewReplicatedFS constructs a new ReplicatedFS.
func (*ReplicatedFS) As ¶
func (fsys *ReplicatedFS) As(target any) bool
As calls the `As(any) bool` method on the leader FS if it exists.
func (*ReplicatedFS) Close ¶
func (fsys *ReplicatedFS) Close() error
Close initiates the shutdown of any background jobs currently synchronizing to the follower FSes and returns when all background jobs have completed.
func (*ReplicatedFS) Copy ¶
func (fsys *ReplicatedFS) Copy(srcName, destName string) error
Copy implements the Copy FS operation for ReplicatedFS.
func (*ReplicatedFS) Mkdir ¶
func (fsys *ReplicatedFS) Mkdir(name string, perm fs.FileMode) error
Mkdir implements the Mkdir FS operation for ReplicatedFS.
func (*ReplicatedFS) MkdirAll ¶
func (fsys *ReplicatedFS) MkdirAll(name string, perm fs.FileMode) error
MkdirAll implements the MkdirAll FS operation for ReplicatedFS.
func (*ReplicatedFS) Open ¶
func (fsys *ReplicatedFS) Open(name string) (fs.File, error)
Open implements the Open FS operation for SFTPFS.
func (*ReplicatedFS) OpenWriter ¶
func (fsys *ReplicatedFS) OpenWriter(name string, perm fs.FileMode) (io.WriteCloser, error)
OpenWriter implements the OpenWriter FS operation for ReplicatedFS.
func (*ReplicatedFS) ReadDir ¶
func (fsys *ReplicatedFS) ReadDir(name string) ([]fs.DirEntry, error)
ReadDir implements the ReadDir FS operation for ReplicatedFS.
func (*ReplicatedFS) Remove ¶
func (fsys *ReplicatedFS) Remove(name string) error
Remove implements the Remove FS operation for ReplicatedFS.
func (*ReplicatedFS) RemoveAll ¶
func (fsys *ReplicatedFS) RemoveAll(name string) error
RemoveAll implements the RemoveAll FS operation for ReplicatedFS.
func (*ReplicatedFS) Rename ¶
func (fsys *ReplicatedFS) Rename(oldName, newName string) error
Rename implements the Rename FS operation for ReplicatedFS.
func (*ReplicatedFS) Stat ¶
func (fsys *ReplicatedFS) Stat(name string) (fs.FileInfo, error)
Stat implements the fs.StatFS interface.
func (*ReplicatedFS) WithContext ¶
func (fsys *ReplicatedFS) WithContext(ctx context.Context) FS
WithContext returns a new FS with the given context.
func (*ReplicatedFS) WithValues ¶
func (fsys *ReplicatedFS) WithValues(values map[string]any) FS
WithValues returns a new ReplicatedFS where the leader FS and each follower FS has `WithValues(any) FS` method called on it if it exists.
type ReplicatedFSConfig ¶
type ReplicatedFSConfig struct { // (Required) Leader is the primary FS that we read from and write to. Leader FS // Followers are the secondary FSes that writes are replicated to. Followers []FS // If SynchronousReplication is true, writes will be synchronously // replicated to the followers. SynchronousReplication bool // (Required) Logger is used for reporting errors that cannot be handled // and are thrown away. Logger *slog.Logger }
ReplicatedFSConfig holds the parameters needed to construct a ReplicatedFS.
type ReplicatedFileWriter ¶
type ReplicatedFileWriter struct {
// contains filtered or unexported fields
}
ReplicatedFileWriter represents a writable file on a ReplicatedFS.
func (*ReplicatedFileWriter) Close ¶
func (file *ReplicatedFileWriter) Close() error
Close saves the contents of the ReplicatedFileWriter to the leader FS and follower FSes and closes the ReplicatedFileWriter.
type S3ObjectStorage ¶
type S3ObjectStorage struct { // S3 SDK client. Client *s3.Client // S3 Bucket to put objects in. Bucket string // File extension to Content-Type map. ContentTypeMap map[string]string // Logger is used for reporting errors that cannot be handled and are // thrown away. Logger *slog.Logger }
S3ObjectStorage implements ObjectStorage via an S3-compatible provider.
func NewS3Storage ¶
func NewS3Storage(ctx context.Context, config S3StorageConfig) (*S3ObjectStorage, error)
NewS3Storage constructs a new S3ObjectStorage.
func (*S3ObjectStorage) Copy ¶
func (storage *S3ObjectStorage) Copy(ctx context.Context, srcKey, destKey string) error
Copy implements the Copy ObjectStorage operation for S3ObjectStorage.
func (*S3ObjectStorage) Delete ¶
func (storage *S3ObjectStorage) Delete(ctx context.Context, key string) error
Delete implements the Delete ObjectStorage operation for S3ObjectStorage.
func (*S3ObjectStorage) Get ¶
func (storage *S3ObjectStorage) Get(ctx context.Context, key string) (io.ReadCloser, error)
Get implements the Get ObjectStorage operation for S3ObjectStorage.
type S3StorageConfig ¶
type S3StorageConfig struct { // (Required) S3 endpoint. Endpoint string // (Required) S3 region. Region string // (Required) S3 bucket. Bucket string // (Required) S3 access key ID. AccessKeyID string // (Required) S3 secret access key. SecretAccessKey string // File extension to Content-Type map. ContentTypeMap map[string]string // (Required) Logger is used for reporting errors that cannot be handled // and are thrown away. Logger *slog.Logger }
S3StorageConfig holds the parameters needed to construct an S3ObjectStorage.
type SFTPClient ¶
type SFTPClient struct {
// contains filtered or unexported fields
}
SFTPClient is a wrapper around an *sftp.Client which records the state of whether the *sftp.Client is disconnected.
type SFTPFS ¶
type SFTPFS struct { // ssh.Client constructor function. NewSSHClient func() (*ssh.Client, error) // Root directory on the SFTP server. RootDir string // Temp directory on the SFTP server. TempDir string // Logger is used for reporting errors that cannot be handled and are // thrown away. Logger *slog.Logger // Clients is the list of available sftp Clients we can use. Clients []*SFTPClient // contains filtered or unexported fields }
SFTPFS implements a writeable filesystem using an SFTP server. It maintains one or more persistent connections to an SFTP server.
func NewSFTPFS ¶
func NewSFTPFS(config SFTPFSConfig) (*SFTPFS, error)
NewSFTPFS constructs a new SFTPFS.
func (*SFTPFS) OpenWriter ¶
OpenWriter implements the OpenWriter FS operation for DatabaseFS.
type SFTPFSConfig ¶
type SFTPFSConfig struct { // (Required) ssh.Client constructor function. NewSSHClient func() (*ssh.Client, error) // (Required) Root directory on the SFTP server. RootDir string // Temp directory on the SFTP server. TempDir string // Max open connections to the SFTP server. MaxOpenConns int // (Required) Logger is used for reporting errors that cannot be handled // and are thrown away. Logger *slog.Logger }
SFTPFSConfig holds the parameters needed to construct a SFTPFS.
type SFTPFileWriter ¶
type SFTPFileWriter struct {
// contains filtered or unexported fields
}
SFTPFileWriter represents a writable file on an SFTPFS.
func (*SFTPFileWriter) Close ¶
func (file *SFTPFileWriter) Close() error
Close saves the contents of the SFTPFileWriter to a file on the SFTP server and closes the SFTPFileWriter.
type Site ¶
type Site struct { // Language code of the site. LanguageCode string // Title of the site. Title string // Tagline of the site. Tagline string // Favicon of the site. Favicon template.URL // The site's timezone offset in seconds. TimezoneOffsetSeconds int // Description of the site. Description string NavigationLinks []NavigationLink }
Site holds the global properties of a site.
type SiteConfig ¶
type SiteConfig struct { LanguageCode string `json:"languageCode"` Title string `json:"title"` Tagline string `json:"tagline"` Emoji string `json:"emoji"` Favicon string `json:"favicon"` CodeStyle string `json:"codeStyle"` TimezoneOffset string `json:"timezoneOffset"` Description string `json:"description"` }
type SiteGenerator ¶
type SiteGenerator struct { // Site information. Site Site // contains filtered or unexported fields }
SiteGenerator is used to generate pages and posts for a particular site.
func NewSiteGenerator ¶
func NewSiteGenerator(ctx context.Context, siteGenConfig SiteGeneratorConfig) (*SiteGenerator, error)
NewSiteGenerator constructs a new SiteGenerator.
func (*SiteGenerator) GeneratePage ¶
func (siteGen *SiteGenerator) GeneratePage(ctx context.Context, filePath, text string, modTime, creationTime time.Time) error
GeneratePage generates a page. filePath is the file path to the source .html page in the pages/ directory, text is the source text of the page, modTime and creationTime are when the page was modified and created.
func (*SiteGenerator) GeneratePost ¶
func (siteGen *SiteGenerator) GeneratePost(ctx context.Context, filePath, text string, modTime, creationTime time.Time, tmpl *template.Template) error
GeneratePost generates a post. filePath is the file path to the source post in the posts/ directory and text is the text of the source post.
func (*SiteGenerator) GeneratePostList ¶
func (siteGen *SiteGenerator) GeneratePostList(ctx context.Context, category string, tmpl *template.Template) (int64, error)
GeneratePostList generates the post list for a category, which contain one or more post list pages.
func (*SiteGenerator) GeneratePostListPage ¶
func (siteGen *SiteGenerator) GeneratePostListPage(ctx context.Context, category string, tmpl *template.Template, lastPage, currentPage int, posts []Post) error
GeneratePostListPage generates a singular page of the post list for a category.
func (*SiteGenerator) GeneratePosts ¶
func (siteGen *SiteGenerator) GeneratePosts(ctx context.Context, category string, tmpl *template.Template) (int64, error)
GeneratePosts generates all posts for a given category.
func (*SiteGenerator) ParseTemplate ¶
func (siteGen *SiteGenerator) ParseTemplate(ctx context.Context, name, text string) (*template.Template, error)
ParseTemplate parses text as a template body for name. Template references starting with "/themes/" and ending in ".html" will be looked for in the site's themes folder.
func (*SiteGenerator) PostListTemplate ¶
func (siteGen *SiteGenerator) PostListTemplate(ctx context.Context, category string) (*template.Template, error)
PostListTemplate returns the post list template for a category.
func (*SiteGenerator) PostTemplate ¶
func (siteGen *SiteGenerator) PostTemplate(ctx context.Context, category string) (*template.Template, error)
PostTemplate returns the post template for a category.
type SiteGeneratorConfig ¶
type SiteGeneratorConfig struct { // FS is the filesystem that holds the site content. FS FS // ContentDomain is the domain that the site's generated content is served // on. ContentDomain string // ContentDomainHTTPS indicates whether the content domain is served over // HTTPS. ContentDomainHTTPS bool // CDNDomain is the domain of the CDN that is used for hosting images. CDNDomain string // SitePrefix is the site prefix of the site. SitePrefix string }
SiteGeneratorConfig holds the parameters needed to construct a new SiteGenerator.
type TemplateError ¶
type TemplateError struct { // Name of the template that caused the error. Name string `json:"name"` // Line number in the template that caused the error. Line int `json:"line"` // ErrorMessage of the error. ErrorMessage string `json:"errorMessage"` }
TemplateError is used to represent an error when parsing or executing a template.
func (TemplateError) Error ¶
func (templateErr TemplateError) Error() string
Error implements the error interface.
type User ¶
type User struct { // UserID uniquely identifies a user. It cannot be changed. UserID ID // Username uniquely identifies a user. It can be changed. Username string // Email uniquely identifies a user. It can be changed. Email string // TimezoneOffsetSeconds represents a user's preferred timezone offset in // seconds. TimezoneOffsetSeconds int // Is not empty, DisableReason is the reason why the user's account is // marked as disabled. DisableReason string // SiteLimit is the limit on the number of sites the user can create. SiteLimit int64 // StorageLimit is the limit on the amount of storage the user can use. StorageLimit int64 // UserFlags are various properties on a user that may be enabled or // disabled e.g. UploadImages. UserFlags map[string]bool }
User represents a user in the users table.
Source Files ¶
- applytheme.go
- calculatestorage.go
- cancelexport.go
- cancelimport.go
- changepassword.go
- clipboard.go
- createfile.go
- createfolder.go
- createsession.go
- createsite.go
- creation_time_linux.go
- delete.go
- deletesession.go
- deletesite.go
- directory.go
- export.go
- exports.go
- file.go
- fs.go
- fs_database.go
- fs_directory.go
- fs_replicated.go
- fs_sftp.go
- id.go
- image.go
- import.go
- imports.go
- invite.go
- login.go
- logout.go
- mailer.go
- notebrew.go
- object_storage.go
- pin.go
- postlist_json.go
- profile.go
- rename.go
- resetpassword.go
- resettheme.go
- rootdirectory.go
- schema.go
- search.go
- serve_http.go
- site_generator.go
- site_json.go
- unpin.go
- updateemail.go
- updateprofile.go
- uploadfile.go
Directories ¶
Path | Synopsis |
---|---|
internal
|
|
highlighting
https://github.com/yuin/goldmark-highlighting/tree/v2
|
https://github.com/yuin/goldmark-highlighting/tree/v2 |