mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 12:53:43 +01:00 
			
		
		
		
	Auto-update the system status in admin dashboard (#29163)
- Refactor the system status list into its own template
- Change the backend to return only the system status if htmx initiated
the request
- `hx-get="{{$.Link}}/system_status`: reuse the backend handler
- `hx-swap="innerHTML"`: replace the `<div>`'s innerHTML (essentially
the new template)
- `hx-trigger="every 5s"`: call every 5 seconds
- `hx-indicator=".divider"`: the `is-loading` class shouldn't be added
to the div during the request, so set it on an element it has no effect
on
- Render "Since Last GC Time" with `<relative-time>`, so we send a
timestamp
# Auto-update in action GIF

---------
Signed-off-by: Yarden Shoham <git@yardenshoham.com>
Co-authored-by: silverwind <me@silverwind.io>
			
			
This commit is contained in:
		
							parent
							
								
									e9a1ffba2c
								
							
						
					
					
						commit
						c70f65e83b
					
				
							
								
								
									
										6
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -31,6 +31,7 @@
 | 
			
		||||
        "escape-goat": "4.0.0",
 | 
			
		||||
        "fast-glob": "3.3.2",
 | 
			
		||||
        "htmx.org": "1.9.10",
 | 
			
		||||
        "idiomorph": "0.3.0",
 | 
			
		||||
        "jquery": "3.7.1",
 | 
			
		||||
        "katex": "0.16.9",
 | 
			
		||||
        "license-checker-webpack-plugin": "0.2.1",
 | 
			
		||||
@ -6174,6 +6175,11 @@
 | 
			
		||||
        "postcss": "^8.1.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/idiomorph": {
 | 
			
		||||
      "version": "0.3.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/idiomorph/-/idiomorph-0.3.0.tgz",
 | 
			
		||||
      "integrity": "sha512-UhV1Ey5xCxIwR9B+OgIjQa+1Jx99XQ1vQHUsKBU1RpQzCx1u+b+N6SOXgf5mEJDqemUI/ffccu6+71l2mJUsRA=="
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/ieee754": {
 | 
			
		||||
      "version": "1.2.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
 | 
			
		||||
 | 
			
		||||
@ -30,6 +30,7 @@
 | 
			
		||||
    "escape-goat": "4.0.0",
 | 
			
		||||
    "fast-glob": "3.3.2",
 | 
			
		||||
    "htmx.org": "1.9.10",
 | 
			
		||||
    "idiomorph": "0.3.0",
 | 
			
		||||
    "jquery": "3.7.1",
 | 
			
		||||
    "katex": "0.16.9",
 | 
			
		||||
    "license-checker-webpack-plugin": "0.2.1",
 | 
			
		||||
 | 
			
		||||
@ -28,13 +28,14 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	tplDashboard   base.TplName = "admin/dashboard"
 | 
			
		||||
	tplSelfCheck   base.TplName = "admin/self_check"
 | 
			
		||||
	tplCron        base.TplName = "admin/cron"
 | 
			
		||||
	tplQueue       base.TplName = "admin/queue"
 | 
			
		||||
	tplStacktrace  base.TplName = "admin/stacktrace"
 | 
			
		||||
	tplQueueManage base.TplName = "admin/queue_manage"
 | 
			
		||||
	tplStats       base.TplName = "admin/stats"
 | 
			
		||||
	tplDashboard    base.TplName = "admin/dashboard"
 | 
			
		||||
	tplSystemStatus base.TplName = "admin/system_status"
 | 
			
		||||
	tplSelfCheck    base.TplName = "admin/self_check"
 | 
			
		||||
	tplCron         base.TplName = "admin/cron"
 | 
			
		||||
	tplQueue        base.TplName = "admin/queue"
 | 
			
		||||
	tplStacktrace   base.TplName = "admin/stacktrace"
 | 
			
		||||
	tplQueueManage  base.TplName = "admin/queue_manage"
 | 
			
		||||
	tplStats        base.TplName = "admin/stats"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var sysStatus struct {
 | 
			
		||||
@ -72,7 +73,7 @@ var sysStatus struct {
 | 
			
		||||
 | 
			
		||||
	// Garbage collector statistics.
 | 
			
		||||
	NextGC       string // next run in HeapAlloc time (bytes)
 | 
			
		||||
	LastGC       string // last run in absolute time (ns)
 | 
			
		||||
	LastGCTime   string // last run time
 | 
			
		||||
	PauseTotalNs string
 | 
			
		||||
	PauseNs      string // circular buffer of recent GC pause times, most recent at [(NumGC+255)%256]
 | 
			
		||||
	NumGC        uint32
 | 
			
		||||
@ -110,7 +111,7 @@ func updateSystemStatus() {
 | 
			
		||||
	sysStatus.OtherSys = base.FileSize(int64(m.OtherSys))
 | 
			
		||||
 | 
			
		||||
	sysStatus.NextGC = base.FileSize(int64(m.NextGC))
 | 
			
		||||
	sysStatus.LastGC = fmt.Sprintf("%.1fs", float64(time.Now().UnixNano()-int64(m.LastGC))/1000/1000/1000)
 | 
			
		||||
	sysStatus.LastGCTime = time.Unix(0, int64(m.LastGC)).Format(time.RFC3339)
 | 
			
		||||
	sysStatus.PauseTotalNs = fmt.Sprintf("%.1fs", float64(m.PauseTotalNs)/1000/1000/1000)
 | 
			
		||||
	sysStatus.PauseNs = fmt.Sprintf("%.3fs", float64(m.PauseNs[(m.NumGC+255)%256])/1000/1000/1000)
 | 
			
		||||
	sysStatus.NumGC = m.NumGC
 | 
			
		||||
@ -132,7 +133,6 @@ func Dashboard(ctx *context.Context) {
 | 
			
		||||
	ctx.Data["PageIsAdminDashboard"] = true
 | 
			
		||||
	ctx.Data["NeedUpdate"] = updatechecker.GetNeedUpdate(ctx)
 | 
			
		||||
	ctx.Data["RemoteVersion"] = updatechecker.GetRemoteVersion(ctx)
 | 
			
		||||
	// FIXME: update periodically
 | 
			
		||||
	updateSystemStatus()
 | 
			
		||||
	ctx.Data["SysStatus"] = sysStatus
 | 
			
		||||
	ctx.Data["SSH"] = setting.SSH
 | 
			
		||||
@ -140,6 +140,12 @@ func Dashboard(ctx *context.Context) {
 | 
			
		||||
	ctx.HTML(http.StatusOK, tplDashboard)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SystemStatus(ctx *context.Context) {
 | 
			
		||||
	updateSystemStatus()
 | 
			
		||||
	ctx.Data["SysStatus"] = sysStatus
 | 
			
		||||
	ctx.HTML(http.StatusOK, tplSystemStatus)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DashboardPost run an admin operation
 | 
			
		||||
func DashboardPost(ctx *context.Context) {
 | 
			
		||||
	form := web.GetForm(ctx).(*forms.AdminDashboardForm)
 | 
			
		||||
 | 
			
		||||
@ -677,6 +677,7 @@ func registerRoutes(m *web.Route) {
 | 
			
		||||
	// ***** START: Admin *****
 | 
			
		||||
	m.Group("/admin", func() {
 | 
			
		||||
		m.Get("", admin.Dashboard)
 | 
			
		||||
		m.Get("/system_status", admin.SystemStatus)
 | 
			
		||||
		m.Post("", web.Bind(forms.AdminDashboardForm{}), admin.DashboardPost)
 | 
			
		||||
 | 
			
		||||
		m.Get("/self_check", admin.SelfCheck)
 | 
			
		||||
 | 
			
		||||
@ -75,69 +75,9 @@
 | 
			
		||||
		<h4 class="ui top attached header">
 | 
			
		||||
			{{ctx.Locale.Tr "admin.dashboard.system_status"}}
 | 
			
		||||
		</h4>
 | 
			
		||||
		<div class="ui attached table segment">
 | 
			
		||||
			<dl class="admin-dl-horizontal">
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.server_uptime"}}</dt>
 | 
			
		||||
				<dd><relative-time format="duration" datetime="{{.SysStatus.StartTime}}">{{.SysStatus.StartTime}}</relative-time></dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.current_goroutine"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.NumGoroutine}}</dd>
 | 
			
		||||
				<div class="divider"></div>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.current_memory_usage"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.MemAllocated}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.total_memory_allocated"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.MemTotal}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.memory_obtained"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.MemSys}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.pointer_lookup_times"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.Lookups}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.memory_allocate_times"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.MemMallocs}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.memory_free_times"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.MemFrees}}</dd>
 | 
			
		||||
				<div class="divider"></div>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.current_heap_usage"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.HeapAlloc}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.heap_memory_obtained"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.HeapSys}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.heap_memory_idle"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.HeapIdle}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.heap_memory_in_use"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.HeapInuse}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.heap_memory_released"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.HeapReleased}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.heap_objects"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.HeapObjects}}</dd>
 | 
			
		||||
				<div class="divider"></div>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.bootstrap_stack_usage"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.StackInuse}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.stack_memory_obtained"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.StackSys}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.mspan_structures_usage"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.MSpanInuse}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.mspan_structures_obtained"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.MSpanSys}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.mcache_structures_usage"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.MCacheInuse}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.mcache_structures_obtained"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.MCacheSys}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.profiling_bucket_hash_table_obtained"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.BuckHashSys}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.gc_metadata_obtained"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.GCSys}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.other_system_allocation_obtained"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.OtherSys}}</dd>
 | 
			
		||||
				<div class="divider"></div>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.next_gc_recycle"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.NextGC}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.last_gc_time"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.LastGC}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.total_gc_pause"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.PauseTotalNs}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.last_gc_pause"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.PauseNs}}</dd>
 | 
			
		||||
				<dt>{{ctx.Locale.Tr "admin.dashboard.gc_times"}}</dt>
 | 
			
		||||
				<dd>{{.SysStatus.NumGC}}</dd>
 | 
			
		||||
			</dl>
 | 
			
		||||
		{{/* TODO: make these stats work in multi-server deployments, likely needs per-server stats in DB */}}
 | 
			
		||||
		<div hx-get="{{$.Link}}/system_status" hx-swap="morph:innerHTML" hx-trigger="every 5s" hx-indicator=".divider" class="ui attached table segment">
 | 
			
		||||
			{{template "admin/system_status" .}}
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
{{template "admin/layout_footer" .}}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										62
									
								
								templates/admin/system_status.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								templates/admin/system_status.tmpl
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,62 @@
 | 
			
		||||
<dl class="admin-dl-horizontal">
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.server_uptime"}}</dt>
 | 
			
		||||
	<dd><relative-time format="duration" datetime="{{.SysStatus.StartTime}}">{{.SysStatus.StartTime}}</relative-time></dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.current_goroutine"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.NumGoroutine}}</dd>
 | 
			
		||||
	<div class="divider"></div>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.current_memory_usage"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.MemAllocated}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.total_memory_allocated"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.MemTotal}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.memory_obtained"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.MemSys}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.pointer_lookup_times"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.Lookups}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.memory_allocate_times"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.MemMallocs}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.memory_free_times"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.MemFrees}}</dd>
 | 
			
		||||
	<div class="divider"></div>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.current_heap_usage"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.HeapAlloc}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.heap_memory_obtained"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.HeapSys}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.heap_memory_idle"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.HeapIdle}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.heap_memory_in_use"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.HeapInuse}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.heap_memory_released"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.HeapReleased}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.heap_objects"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.HeapObjects}}</dd>
 | 
			
		||||
	<div class="divider"></div>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.bootstrap_stack_usage"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.StackInuse}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.stack_memory_obtained"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.StackSys}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.mspan_structures_usage"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.MSpanInuse}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.mspan_structures_obtained"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.MSpanSys}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.mcache_structures_usage"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.MCacheInuse}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.mcache_structures_obtained"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.MCacheSys}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.profiling_bucket_hash_table_obtained"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.BuckHashSys}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.gc_metadata_obtained"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.GCSys}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.other_system_allocation_obtained"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.OtherSys}}</dd>
 | 
			
		||||
	<div class="divider"></div>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.next_gc_recycle"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.NextGC}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.last_gc_time"}}</dt>
 | 
			
		||||
	<dd><relative-time format="duration" datetime="{{.SysStatus.LastGCTime}}">{{.SysStatus.LastGCTime}}</relative-time></dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.total_gc_pause"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.PauseTotalNs}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.last_gc_pause"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.PauseNs}}</dd>
 | 
			
		||||
	<dt>{{ctx.Locale.Tr "admin.dashboard.gc_times"}}</dt>
 | 
			
		||||
	<dd>{{.SysStatus.NumGC}}</dd>
 | 
			
		||||
</dl>
 | 
			
		||||
@ -29,7 +29,7 @@
 | 
			
		||||
	{{template "base/head_style" .}}
 | 
			
		||||
	{{template "custom/header" .}}
 | 
			
		||||
</head>
 | 
			
		||||
<body hx-headers='{"x-csrf-token": "{{.CsrfToken}}"}' hx-swap="outerHTML" hx-push-url="false">
 | 
			
		||||
<body hx-headers='{"x-csrf-token": "{{.CsrfToken}}"}' hx-swap="outerHTML" hx-ext="morph" hx-push-url="false">
 | 
			
		||||
	{{ctx.DataRaceCheck $.Context}}
 | 
			
		||||
	{{template "custom/body_outer_pre" .}}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,9 @@
 | 
			
		||||
import * as htmx from 'htmx.org';
 | 
			
		||||
import {showErrorToast} from './modules/toast.js';
 | 
			
		||||
 | 
			
		||||
// https://github.com/bigskysoftware/idiomorph#htmx
 | 
			
		||||
import 'idiomorph/dist/idiomorph-ext.js';
 | 
			
		||||
 | 
			
		||||
// https://htmx.org/reference/#config
 | 
			
		||||
htmx.config.requestClass = 'is-loading';
 | 
			
		||||
htmx.config.scrollIntoViewOnBoost = false;
 | 
			
		||||
 | 
			
		||||
@ -169,6 +169,9 @@ export default {
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
  plugins: [
 | 
			
		||||
    new webpack.ProvidePlugin({ // for htmx extensions
 | 
			
		||||
      htmx: 'htmx.org',
 | 
			
		||||
    }),
 | 
			
		||||
    new DefinePlugin({
 | 
			
		||||
      __VUE_OPTIONS_API__: true, // at the moment, many Vue components still use the Vue Options API
 | 
			
		||||
      __VUE_PROD_DEVTOOLS__: false, // do not enable devtools support in production
 | 
			
		||||
@ -207,6 +210,7 @@ export default {
 | 
			
		||||
      override: {
 | 
			
		||||
        'khroma@*': {licenseName: 'MIT'}, // https://github.com/fabiospampinato/khroma/pull/33
 | 
			
		||||
        'htmx.org@1.9.10': {licenseName: 'BSD-2-Clause'}, // "BSD 2-Clause" -> "BSD-2-Clause"
 | 
			
		||||
        'idiomorph@0.3.0': {licenseName: 'BSD-2-Clause'}, // "BSD 2-Clause" -> "BSD-2-Clause"
 | 
			
		||||
      },
 | 
			
		||||
      emitError: true,
 | 
			
		||||
      allow: '(Apache-2.0 OR BSD-2-Clause OR BSD-3-Clause OR MIT OR ISC OR CPAL-1.0 OR Unlicense OR EPL-1.0 OR EPL-2.0)',
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user