Commit Diff


commit - db8b5d30426e62a68ac7358377dbeebf54071f8b
commit + c58a47f39bc5d848ad4f0d6e651b4e0c7f4691c2
blob - 09d7c9c2381e6b5755aecf63c0bb2c71e62b71aa
blob + 3f3f84b7208da6f1f442c7114028044b32097c2b
--- README.md
+++ README.md
@@ -369,22 +369,52 @@ SVG-файлы минифицируются.
 
 Связывает страницу с `manifest.json`, находящимся в корне `assets/`.
 
+### assets/require-css
+
+Регистрирует CSS-ресурс компонента для подключения в `<head>`.
+
+Ресурс должен находиться в `assets/`.
+Путь передаётся относительно этой директории:
+
+```go-html-template
+{{- partial "assets/require-css.html" "css/components/pagination.css" }}
+```
+
+Повторная регистрация одного и того же ресурса не приводит к его повторному подключению.
+
+### assets/require-js
+
+Регистрирует JavaScript-ресурс компонента для последующей сборки через `js.Batch` и подключения в `<head>`.
+
+Ресурс должен находиться в `assets/`.
+Путь передаётся относительно этой директории:
+
+```go-html-template
+{{- partial "assets/require-js.html" "js/pagefind.js" }}
+```
+
+Компоненту не требуется самостоятельно вызывать `js.Build`, выполнять минификацию или выводить `<script>`.
+
 ### head/css
 
-Подключает:
+Подключает основной файл стилей:
 
 ```text
 css/main.css
 ```
 
+а также CSS-ресурсы, зарегистрированные компонентами через `assets/require-css`.
+
 ### head/js
 
-Подключает:
+Подключает основной скрипт:
 
 ```text
 js/main.js
 ```
 
+а также JavaScript-ресурсы, зарегистрированные компонентами через `assets/require-js` и собранные через `js.Batch`.
+
 ### head/pagefind
 
 Подключает стили и скрипт Pagefind, если окружение не является development.
blob - /dev/null
blob + ec185efcb18932c63752a2b69f65daf87a855c50 (mode 644)
--- /dev/null
+++ layouts/_partials/assets/require-css.html
@@ -0,0 +1 @@
+{{- page.Store.SetInMap "styles" . . }}
blob - /dev/null
blob + 9c1e2ec4f34c256ff258eb565ed7522f7372795f (mode 644)
--- /dev/null
+++ layouts/_partials/assets/require-js.html
@@ -0,0 +1,9 @@
+{{- $resource := resources.Get . }}
+{{- $group := hash.XxHash page.RelPermalink }}
+{{- $id := hash.XxHash . }}
+
+{{- with (js.Batch "js/components").Group $group }}
+  {{- with .Script $id }}
+    {{- .SetOptions (dict "resource" $resource) }}
+  {{- end }}
+{{- end }}
blob - 73bc6d770f28e383dc16b74913e8da3e655217c9
blob + cfe0cbcc799dd2bc257b90eb2dfd932ff6161a4e
--- layouts/_partials/head/css.html
+++ layouts/_partials/head/css.html
@@ -1,11 +1,23 @@
-{{- with resources.Get "css/main.css" | postCSS }}
-  {{- if eq hugo.Environment "development" }}
-    {{- with . | css.Build }}
-      <link rel="stylesheet" href="{{ .RelPermalink }}">
+{{- partial "head/css/resource.html" "css/main.css" }}
+
+{{- range .Store.GetSortedMapValues "styles" }}
+  {{- partial "head/css/resource.html" . }}
+{{- end }}
+
+{{- define "_partials/head/css/resource.html" }}
+  {{- with resources.Get . | postCSS }}
+    {{- if hugo.IsDevelopment }}
+      {{- with . | css.Build }}
+        <link rel="stylesheet" href="{{ .RelPermalink }}">
+      {{- end }}
+    {{- else }}
+      {{- with . | css.Build (dict "minify" true) | fingerprint }}
+        <link
+          rel="stylesheet"
+          href="{{ .RelPermalink }}"
+          integrity="{{ .Data.Integrity }}"
+          crossorigin="anonymous">
+      {{- end }}
     {{- end }}
-  {{- else }}
-    {{- with . | css.Build (dict "minify" true) | fingerprint }}
-      <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
-    {{- end }}
   {{- end }}
 {{- end }}
blob - 658215dbef74411bc10718974db09a73cc5fb2df
blob + 9e77eeab7ada0bb6e7dd6ab8cef94f53eddfd1e3
--- layouts/_partials/head/js.html
+++ layouts/_partials/head/js.html
@@ -1,12 +1,54 @@
 {{- with resources.Get "js/main.js" }}
-  {{- if eq hugo.Environment "development" }}
-    {{- with . | js.Build }}
-      <script src="{{ .RelPermalink }}" defer></script>
+  {{- with . | js.Build (dict
+    "format" "esm"
+    "minify" (not hugo.IsDevelopment)
+  ) }}
+    {{- if hugo.IsDevelopment }}
+      <script type="module" src="{{ .RelPermalink }}"></script>
+    {{- else }}
+      {{- with . | fingerprint }}
+        <script
+          type="module"
+          src="{{ .RelPermalink }}"
+          integrity="{{ .Data.Integrity }}"
+          crossorigin="anonymous"></script>
+      {{- end }}
     {{- end }}
-  {{- else }}
-    {{- $opts := dict "minify" true }}
-    {{- with . | js.Build $opts | fingerprint }}
-      <script src="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous" defer></script>
+  {{- end }}
+{{- end }}
+
+{{- $group := hash.XxHash .RelPermalink }}
+
+{{- with js.Batch "js/components" }}
+  {{- with .Build }}
+    {{- with index .Groups $group }}
+      {{- range . }}
+        {{- if eq .MediaType.SubType "css" }}
+          {{- if hugo.IsDevelopment }}
+            <link rel="stylesheet" href="{{ .RelPermalink }}">
+          {{- else }}
+            {{- with . | fingerprint }}
+              <link
+                rel="stylesheet"
+                href="{{ .RelPermalink }}"
+                integrity="{{ .Data.Integrity }}"
+                crossorigin="anonymous">
+            {{- end }}
+          {{- end }}
+        {{- else }}
+          {{- if hugo.IsDevelopment }}
+            <script type="module" src="{{ .RelPermalink }}"></script>
+          {{- else }}
+            {{- with . | fingerprint }}
+              <script
+                type="module"
+                src="{{ .RelPermalink }}"
+                integrity="{{ .Data.Integrity }}"
+                crossorigin="anonymous"></script>
+            {{- end }}
+          {{- end }}
+        {{- end }}
+      {{- end }}
     {{- end }}
   {{- end }}
 {{- end }}