merge

package module
v0.0.0-...-cca7f24 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 28, 2024 License: MIT Imports: 4 Imported by: 0

README

Merge, with tailwind-merge

Go Reference

Merge is a simple Go package to merge HTML attributes.

merger := merge.New(map[string][]merge.MergeFunc{
    "class": {merge.ClassMergeFunc},
})
res := merger.Merge(map[string]any{
    "class": "px-4 mx-2 bg-red-500",
}, map[string]any{
    "class": "px-4 font-bold",
})
log.Println(res)
// map[class:px-4 font-bold mx-2 bg-red-500]
// 

tailwind-merge

It also supports tailwind-merge through goja.

twMerge, err := merge.NewTailwindMerge()
if err != nil {
    log.Fatalln(err)
}
merger := merge.New(map[string][]merge.MergeFunc{
    "class": {twMerge.TailwindMergeFunc},
})
res := merger.Merge(map[string]any{
    "class": "px-2 py-1 bg-red hover:bg-dark-red",
}, map[string]any{
    "class": "p-3 bg-[#B91C1C]",
})
log.Println(res)
// "map[class:hover:bg-dark-red p-3 bg-[#B91C1C]]"

⚠️ tailwind-merge support is rather slow due to the JavaScript runtime running in the background. Unfortunately this is the best solution I have found to use tailwind-merge for now. Please refer to the tailwind-merge documentation for details on usage.

The slowest function is by far merge.NewTailwindMerge(). I suggest you run this in a separate goroutine! Subsequent calls to merger.Merge will usually complete in under 1ms.

Custom merge logic

It allows you to define your own merge logic by defining a custom MergeFunc.

// MergeId prioritises any ID starting with '!'
func MergeId(existing any, incoming any) (remaining any, committed any) {
	const exclaimationMark = rune(33) // 33 is the char code for !
	existingString := fmt.Sprint(existing)
	existingId := strings.TrimSpace(existingString)

	if rune(existingId[0]) == exclaimationMark {
		return nil, existing
	}

	return existing, incoming
}

Then using it in your merger.

merger := merge.New(map[string][]merge.MergeFunc{
    "class": {merge.ClassMergeFunc},
    "id": {MergeId},
})
res := merger.Merge(map[string]any{
    "class": "px-4 mx-2 bg-red-500",
    "id": "!veryImportantId",
}, map[string]any{
    "class": "px-4 font-bold",
    "id": "lessImportantId",
})
log.Println(res)
// map[class:px-4 font-bold mx-2 bg-red-500 id:!veryImportantId]

Documentation

Overview

Package merge defines the main Merger interface and its implementation. Import and use this package to instantiate a Merger. This package is used primarily to manage the merging of HTML attribute sets.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ClassMergeFunc

func ClassMergeFunc(existing any, incoming any) (remaining any, committed any)

The ClassMergeFunc is designed to be used with CSS classes. All of the classes in the incoming string that are not duplicates of those in the existing string will be merged together.

func DefaultMergeFunc

func DefaultMergeFunc(existing any, incoming any) (remaining any, committed any)

The DefaultMergeFunc simply discards existing attributes. It is applied to all attributes without a defined merge behaviour.

Types

type MergeFunc

type MergeFunc func(existing any, incoming any) (remaining any, committed any)

A MergeFunc is a function that defines how two conflicting attributes should be merged. MergeFuncs should prioritise the incoming values and override existing values. If a MergeFunc does not know how to merge part of an attribute, it may return 'remaining'. Merged attributes should be returned in 'committed' in a type that is able to be converted to a string by fmt.Sprint(). 'remaining' attributes may be handled by downstream MergeFuncs.

type Merger

type Merger interface {
	Merge(existing map[string]any, incoming map[string]any) map[string]any
}

The Merger type merges two attribute sets. These may be any kind of attributes but this package was made for merging HTML attributes

func New

func New(attrsFuncMap map[string][]MergeFunc) Merger

New instantiates a Merger for you. You must pass an 'attrsFuncMap' that defines the MergeFuncs, though this may be empty. A string key is used for the name of the attribute. A slice of MergeFuncs is used to define the merge behaviour for this attribute. When Merger.Merge is called, the MergeFuncs are iterated through, with the 'remaining' and 'committed' values of each being passed into the following MergeFunc. The MergeFunc with index 0 is called first. If a MergeFunc leaves some part of an attribute un-merged in the 'remaining' variable, it will be handled by MergeFuncs defined with a higher index in the array. The DefaultMergeFunc is added to the end of all slices of MergeFuncs that simply discards all remaining attributes.

type TailwindMerge

type TailwindMerge interface {
	TailwindMergeFunc(existing any, incoming any) (remaining any, committed any)
}

func NewTailwindMerge

func NewTailwindMerge() (TailwindMerge, error)

NewTailwindMerge creates an instance of twMergeGoja, the provider of the tailwind-merge library in JavaScript. It runs in github.com/dop251/goja, making it far slower than the other included Merge functions. It is recommended that you run the NewTailwindMerge function in a seperate goroutine as it can have a runtime of up to 14ms. Subsequent calls of TailwindMergeFunc are much faster, and do not need to run in a goroutine.

Directories

Path Synopsis
Package twMergeGoja manages the Goja runtime and the running of the tailwind-merge JavaScript bundle.
Package twMergeGoja manages the Goja runtime and the running of the tailwind-merge JavaScript bundle.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL