| 
 | 1 | +// Copyright 2025 The Gitea Authors. All rights reserved.  | 
 | 2 | +// SPDX-License-Identifier: MIT  | 
 | 3 | + | 
 | 4 | +package attribute  | 
 | 5 | + | 
 | 6 | +import (  | 
 | 7 | +	"strings"  | 
 | 8 | + | 
 | 9 | +	"code.gitea.io/gitea/modules/optional"  | 
 | 10 | +)  | 
 | 11 | + | 
 | 12 | +type Attribute string  | 
 | 13 | + | 
 | 14 | +const (  | 
 | 15 | +	LinguistVendored      = "linguist-vendored"  | 
 | 16 | +	LinguistGenerated     = "linguist-generated"  | 
 | 17 | +	LinguistDocumentation = "linguist-documentation"  | 
 | 18 | +	LinguistDetectable    = "linguist-detectable"  | 
 | 19 | +	LinguistLanguage      = "linguist-language"  | 
 | 20 | +	GitlabLanguage        = "gitlab-language"  | 
 | 21 | +	Lockable              = "lockable"  | 
 | 22 | +	Filter                = "filter"  | 
 | 23 | +)  | 
 | 24 | + | 
 | 25 | +var LinguistAttributes = []string{  | 
 | 26 | +	LinguistVendored,  | 
 | 27 | +	LinguistGenerated,  | 
 | 28 | +	LinguistDocumentation,  | 
 | 29 | +	LinguistDetectable,  | 
 | 30 | +	LinguistLanguage,  | 
 | 31 | +	GitlabLanguage,  | 
 | 32 | +}  | 
 | 33 | + | 
 | 34 | +func (a Attribute) IsUnspecified() bool {  | 
 | 35 | +	return a == "" || a == "unspecified"  | 
 | 36 | +}  | 
 | 37 | + | 
 | 38 | +func (a Attribute) ToString() optional.Option[string] {  | 
 | 39 | +	if !a.IsUnspecified() {  | 
 | 40 | +		return optional.Some(string(a))  | 
 | 41 | +	}  | 
 | 42 | +	return optional.None[string]()  | 
 | 43 | +}  | 
 | 44 | + | 
 | 45 | +// ToBool converts the attribute value to optional boolean: true if "set"/"true", false if "unset"/"false", none otherwise  | 
 | 46 | +func (a Attribute) ToBool() optional.Option[bool] {  | 
 | 47 | +	switch a {  | 
 | 48 | +	case "set", "true":  | 
 | 49 | +		return optional.Some(true)  | 
 | 50 | +	case "unset", "false":  | 
 | 51 | +		return optional.Some(false)  | 
 | 52 | +	}  | 
 | 53 | +	return optional.None[bool]()  | 
 | 54 | +}  | 
 | 55 | + | 
 | 56 | +type Attributes struct {  | 
 | 57 | +	m map[string]Attribute  | 
 | 58 | +}  | 
 | 59 | + | 
 | 60 | +func NewAttributes() *Attributes {  | 
 | 61 | +	return &Attributes{m: make(map[string]Attribute)}  | 
 | 62 | +}  | 
 | 63 | + | 
 | 64 | +func (attrs *Attributes) Get(name string) Attribute {  | 
 | 65 | +	if value, has := attrs.m[name]; has {  | 
 | 66 | +		return value  | 
 | 67 | +	}  | 
 | 68 | +	return ""  | 
 | 69 | +}  | 
 | 70 | + | 
 | 71 | +func (attrs *Attributes) GetVendored() optional.Option[bool] {  | 
 | 72 | +	return attrs.Get(LinguistVendored).ToBool()  | 
 | 73 | +}  | 
 | 74 | + | 
 | 75 | +func (attrs *Attributes) GetGenerated() optional.Option[bool] {  | 
 | 76 | +	return attrs.Get(LinguistGenerated).ToBool()  | 
 | 77 | +}  | 
 | 78 | + | 
 | 79 | +func (attrs *Attributes) GetDocumentation() optional.Option[bool] {  | 
 | 80 | +	return attrs.Get(LinguistDocumentation).ToBool()  | 
 | 81 | +}  | 
 | 82 | + | 
 | 83 | +func (attrs *Attributes) GetDetectable() optional.Option[bool] {  | 
 | 84 | +	return attrs.Get(LinguistDetectable).ToBool()  | 
 | 85 | +}  | 
 | 86 | + | 
 | 87 | +func (attrs *Attributes) GetLinguistLanguage() optional.Option[string] {  | 
 | 88 | +	return attrs.Get(LinguistLanguage).ToString()  | 
 | 89 | +}  | 
 | 90 | + | 
 | 91 | +func (attrs *Attributes) GetGitlabLanguage() optional.Option[string] {  | 
 | 92 | +	attrStr := attrs.Get(GitlabLanguage).ToString()  | 
 | 93 | +	if attrStr.Has() {  | 
 | 94 | +		raw := attrStr.Value()  | 
 | 95 | +		// gitlab-language may have additional parameters after the language  | 
 | 96 | +		// ignore them and just use the main language  | 
 | 97 | +		// https://docs.gitlab.com/ee/user/project/highlighting.html#override-syntax-highlighting-for-a-file-type  | 
 | 98 | +		if idx := strings.IndexByte(raw, '?'); idx >= 0 {  | 
 | 99 | +			return optional.Some(raw[:idx])  | 
 | 100 | +		}  | 
 | 101 | +	}  | 
 | 102 | +	return attrStr  | 
 | 103 | +}  | 
 | 104 | + | 
 | 105 | +func (attrs *Attributes) GetLanguage() optional.Option[string] {  | 
 | 106 | +	// prefer linguist-language over gitlab-language  | 
 | 107 | +	// if linguist-language is not set, use gitlab-language  | 
 | 108 | +	// if both are not set, return none  | 
 | 109 | +	language := attrs.GetLinguistLanguage()  | 
 | 110 | +	if language.Value() == "" {  | 
 | 111 | +		language = attrs.GetGitlabLanguage()  | 
 | 112 | +	}  | 
 | 113 | +	return language  | 
 | 114 | +}  | 
0 commit comments