github.com/cilium/controller-tools@v0.3.1-0.20230329170030-f2b7ff866fde/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 }