URI: 
       chain.go - hugo - [fork] hugo port for 9front
  HTML git clone https://git.drkhsh.at/hugo.git
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
       chain.go (3229B)
       ---
            1 // Copyright 2018 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 transform
           15 
           16 import (
           17         "bytes"
           18         "io"
           19         "os"
           20 
           21         bp "github.com/gohugoio/hugo/bufferpool"
           22         "github.com/gohugoio/hugo/common/herrors"
           23         "github.com/gohugoio/hugo/hugofs"
           24 )
           25 
           26 // Transformer is the func that needs to be implemented by a transformation step.
           27 type Transformer func(ft FromTo) error
           28 
           29 // BytesReader wraps the Bytes method, usually implemented by bytes.Buffer, and an
           30 // io.Reader.
           31 type BytesReader interface {
           32         // The slice given by Bytes is valid for use only until the next buffer modification.
           33         // That is, if you want to use this value outside of the current transformer step,
           34         // you need to take a copy.
           35         Bytes() []byte
           36 
           37         io.Reader
           38 }
           39 
           40 // FromTo is sent to each transformation step in the chain.
           41 type FromTo interface {
           42         From() BytesReader
           43         To() io.Writer
           44 }
           45 
           46 // Chain is an ordered processing chain. The next transform operation will
           47 // receive the output from the previous.
           48 type Chain []Transformer
           49 
           50 // New creates a content transformer chain given the provided transform funcs.
           51 func New(trs ...Transformer) Chain {
           52         return trs
           53 }
           54 
           55 // NewEmpty creates a new slice of transformers with a capacity of 20.
           56 func NewEmpty() Chain {
           57         return make(Chain, 0, 20)
           58 }
           59 
           60 // Implements contentTransformer
           61 // Content is read from the from-buffer and rewritten to to the to-buffer.
           62 type fromToBuffer struct {
           63         from *bytes.Buffer
           64         to   *bytes.Buffer
           65 }
           66 
           67 func (ft fromToBuffer) From() BytesReader {
           68         return ft.from
           69 }
           70 
           71 func (ft fromToBuffer) To() io.Writer {
           72         return ft.to
           73 }
           74 
           75 // Apply passes the given from io.Reader through the transformation chain.
           76 // The result is written to to.
           77 func (c *Chain) Apply(to io.Writer, from io.Reader) error {
           78         if len(*c) == 0 {
           79                 _, err := io.Copy(to, from)
           80                 return err
           81         }
           82 
           83         b1 := bp.GetBuffer()
           84         defer bp.PutBuffer(b1)
           85 
           86         if _, err := b1.ReadFrom(from); err != nil {
           87                 return err
           88         }
           89 
           90         b2 := bp.GetBuffer()
           91         defer bp.PutBuffer(b2)
           92 
           93         fb := &fromToBuffer{from: b1, to: b2}
           94 
           95         for i, tr := range *c {
           96                 if i > 0 {
           97                         if fb.from == b1 {
           98                                 fb.from = b2
           99                                 fb.to = b1
          100                                 fb.to.Reset()
          101                         } else {
          102                                 fb.from = b1
          103                                 fb.to = b2
          104                                 fb.to.Reset()
          105                         }
          106                 }
          107 
          108                 if err := tr(fb); err != nil {
          109                         // Write output to a temp file so it can be read by the user for trouble shooting.
          110                         filename := "output.html"
          111                         tempfile, ferr := os.CreateTemp("", "hugo-transform-error")
          112                         if ferr == nil {
          113                                 filename = tempfile.Name()
          114                                 defer tempfile.Close()
          115                                 _, _ = io.Copy(tempfile, fb.from)
          116                                 return herrors.NewFileErrorFromFile(err, filename, hugofs.Os, nil)
          117                         }
          118                         return herrors.NewFileErrorFromName(err, filename).UpdateContent(fb.from, nil)
          119 
          120                 }
          121         }
          122 
          123         _, err := fb.to.WriteTo(to)
          124         return err
          125 }