github.com/minio/controller-tools@v0.4.7/pkg/crd/desc_visitor.go (about)

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package crd
    18  
    19  import (
    20  	"strings"
    21  	"unicode"
    22  
    23  	apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
    24  )
    25  
    26  // TruncateDescription truncates the description of fields in given schema if it
    27  // exceeds maxLen.
    28  // It tries to chop off the description at the closest sentence boundary.
    29  func TruncateDescription(schema *apiext.JSONSchemaProps, maxLen int) {
    30  	EditSchema(schema, descVisitor{maxLen: maxLen})
    31  }
    32  
    33  // descVisitor recursively visits all fields in the schema and truncates the
    34  // description of the fields to specified maxLen.
    35  type descVisitor struct {
    36  	// maxLen is the maximum allowed length for decription of a field
    37  	maxLen int
    38  }
    39  
    40  func (v descVisitor) Visit(schema *apiext.JSONSchemaProps) SchemaVisitor {
    41  	if schema == nil {
    42  		return v
    43  	}
    44  	if v.maxLen < 0 {
    45  		return nil /* no further work to be done for this schema */
    46  	}
    47  	if v.maxLen == 0 {
    48  		schema.Description = ""
    49  		return v
    50  	}
    51  	if len(schema.Description) > v.maxLen {
    52  		schema.Description = truncateString(schema.Description, v.maxLen)
    53  		return v
    54  	}
    55  	return v
    56  }
    57  
    58  // truncateString truncates given desc string if it exceeds maxLen. It may
    59  // return string with length less than maxLen even in cases where original desc
    60  // exceeds maxLen because it tries to chop off the desc at the closest sentence
    61  // boundary to avoid incomplete sentences.
    62  func truncateString(desc string, maxLen int) string {
    63  	desc = desc[0:maxLen]
    64  
    65  	// Trying to chop off at closest sentence boundary.
    66  	if n := strings.LastIndexFunc(desc, isSentenceTerminal); n > 0 {
    67  		return desc[0 : n+1]
    68  	}
    69  	// TODO(droot): Improve the logic to chop off at closest word boundary
    70  	// or add elipses (...) to indicate that it's chopped incase no closest
    71  	// sentence found within maxLen.
    72  	return desc
    73  }
    74  
    75  // helper function to determine if given rune is a sentence terminal or not.
    76  func isSentenceTerminal(r rune) bool {
    77  	return unicode.Is(unicode.STerm, r)
    78  }