diff --git a/CHANGELOG.md b/CHANGELOG.md
index cfa4c7000..a212a06f2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,8 +1,29 @@
# Changelog
-## [v2.0.0-alpha.9](https://github.com/marcantondahmen/automad/commit/b0bebc0ddb73807dd5a217daa22989d003faf359)
+## [v2.0.0-alpha.10](https://github.com/marcantondahmen/automad/commit/9f07136e84fce6fc7306b57f479b5f625703e60c)
-Sat, 9 Nov 2024 14:00:18 +0100
+Sun, 24 Nov 2024 11:58:06 +0100
+
+### New Features
+
+- add download link to file cards ([461ece5e4](https://github.com/marcantondahmen/automad/commit/461ece5e4a39e3d038c56fbdc69d00129e9fcec9))
+- add option to define the order of fields inside the dashboard in the theme.json file ([55d93ec1a](https://github.com/marcantondahmen/automad/commit/55d93ec1a0164c6c7ba51bcd88488e6c8bac0350))
+- make sure that block ids are always unique in rendered html ([9f07136e8](https://github.com/marcantondahmen/automad/commit/9f07136e84fce6fc7306b57f479b5f625703e60c))
+
+### Bugfixes
+
+- **ui**: fix button text overflow breaking card layouts ([2bdfe5fa3](https://github.com/marcantondahmen/automad/commit/2bdfe5fa30b8876812b9c2494233df4109aadc21))
+- **ui**: fix datetime input field style on ios ([166e1dc7b](https://github.com/marcantondahmen/automad/commit/166e1dc7b434bf41fbdc5c3ce0f6a5ac74f224f5))
+- fix download links in file info modal ([0b81320a4](https://github.com/marcantondahmen/automad/commit/0b81320a4b774e7055d1de5d0b5df5a27437d88d))
+- fix navbar spacing in inpage edit form ([0fd31f749](https://github.com/marcantondahmen/automad/commit/0fd31f749ffccf14be8377d69db167dc75ae539f))
+- fix position of inpage edit overlay in dom ([486a455ed](https://github.com/marcantondahmen/automad/commit/486a455ed3688fb0b5195c9307136a71c4889c8b))
+- fix processing email addresses inside of markdown blocks ([af569f032](https://github.com/marcantondahmen/automad/commit/af569f032ff0ef47eef5a073042c4ace06ed2c26))
+- fix small display alert being copied with editor content ([cb7a6c73a](https://github.com/marcantondahmen/automad/commit/cb7a6c73a387d12b126f2547361120fc1d42a58c))
+- fix template name display in page data form ([451101ded](https://github.com/marcantondahmen/automad/commit/451101ded3cb4aa8b3e35467e300882b6d2f31b8))
+
+## [v2.0.0-alpha.9](https://github.com/marcantondahmen/automad/commit/c6118ae98545f0d2e2783f2894d1a6da00d57121)
+
+Sat, 9 Nov 2024 19:24:22 +0100
### New Features
@@ -421,12 +442,3 @@ Sun, 8 Aug 2021 22:25:34 +0200
### Bugfixes
- **themes**: fix thumbnail visibility ([45ed2eee5](https://github.com/marcantondahmen/automad/commit/45ed2eee5f1cf0b81148678820b6a796bf4791e2))
-
-## [v1.8.1](https://github.com/marcantondahmen/automad/commit/8be976c0215c549d3ac27016b8c9fee02c052cca)
-
-Sat, 7 Aug 2021 23:06:36 +0200
-
-### Bugfixes
-
-- **ui**: fix breadcrumbs position in safari ([0ed10e20d](https://github.com/marcantondahmen/automad/commit/0ed10e20d8d32f963be4d76c84d79bcf967b77c0))
-- **ui**: fix status badge for outdated packages ([8b53a821f](https://github.com/marcantondahmen/automad/commit/8b53a821fa0d9cdc57af25f0eb122dc0dd312050))
diff --git a/automad/lang/english.json b/automad/lang/english.json
index b1f335b80..06b567edb 100644
--- a/automad/lang/english.json
+++ b/automad/lang/english.json
@@ -117,7 +117,7 @@
"feedEnabled": "The RSS feed is enabled",
"fetchingDataError": "Error fetching data from API!",
"fieldsContent": "Content",
- "fieldsCustomize": "Customize",
+ "fieldsCustomizations": "Customizations",
"fieldsSettings": "Settings",
"file": "File",
"fileName": "Filename",
diff --git a/automad/src/client/admin/components/EditorJS.ts b/automad/src/client/admin/components/EditorJS.ts
index 0f153d03d..2268b8495 100644
--- a/automad/src/client/admin/components/EditorJS.ts
+++ b/automad/src/client/admin/components/EditorJS.ts
@@ -47,7 +47,7 @@ import { DragDrop } from '@/admin/editor/plugins/DragDrop';
import { LayoutTune } from '@/admin/editor/tunes/Layout';
import { EditorOutputData, KeyValueMap } from '@/admin/types';
import EditorJS, { EditorConfig, I18nDictionary } from 'automad-editorjs';
-import { App, Attr, create, CSS } from '@/admin/core';
+import { App, CSS } from '@/admin/core';
import { Delimiter } from '@/admin/editor/blocks/Delimiter';
import { ImageBlock } from '@/admin/editor/blocks/Image';
import { NestedListBlock } from '@/admin/editor/blocks/NestedList';
@@ -118,16 +118,6 @@ export class EditorJSComponent extends BaseComponent {
this.style.position = 'relative';
this.classList.add(CSS.contents);
- create(
- 'am-alert',
- [CSS.displaySmall],
- {
- [Attr.icon]: 'window',
- [Attr.text]: 'editorSmallDisplayAlert',
- },
- this
- );
-
this.editor = new EditorJS(
Object.assign(
{
diff --git a/automad/src/client/admin/components/Fields/EditorField.ts b/automad/src/client/admin/components/Fields/EditorField.ts
index 63c900081..b24475d8b 100644
--- a/automad/src/client/admin/components/Fields/EditorField.ts
+++ b/automad/src/client/admin/components/Fields/EditorField.ts
@@ -34,8 +34,10 @@
import {
App,
+ Attr,
create,
createEditor,
+ CSS,
debounce,
FieldTag,
fire,
@@ -80,8 +82,20 @@ class EditorFieldComponent extends BaseFieldComponent {
this.setAttribute('name', name);
this.value = value as EditorOutputData;
+ const wrapper = create('div', [], { id }, this);
+
+ create(
+ 'am-alert',
+ [CSS.displaySmall],
+ {
+ [Attr.icon]: 'window',
+ [Attr.text]: 'editorSmallDisplayAlert',
+ },
+ wrapper
+ );
+
this.editorJS = createEditor(
- create('div', [], { id }, this),
+ wrapper,
{ blocks: this.value.blocks },
{
onChange: async (api: API) => {
diff --git a/automad/src/client/admin/components/Fields/SelectField.ts b/automad/src/client/admin/components/Fields/SelectField.ts
index 89663be59..cff66228f 100644
--- a/automad/src/client/admin/components/Fields/SelectField.ts
+++ b/automad/src/client/admin/components/Fields/SelectField.ts
@@ -61,7 +61,8 @@ class SelectFieldComponent extends BaseFieldComponent {
`${value}`,
this,
name,
- id
+ id,
+ ' '
);
}
}
diff --git a/automad/src/client/admin/components/File/FileCard.ts b/automad/src/client/admin/components/File/FileCard.ts
index 0fd1eee5e..cfcdf90da 100644
--- a/automad/src/client/admin/components/File/FileCard.ts
+++ b/automad/src/client/admin/components/File/FileCard.ts
@@ -189,6 +189,16 @@ class FileCardComponent extends BaseComponent {
${Attr.text}="${App.text('copyUrlClipboard')}"
>
+
+
+
`;
diff --git a/automad/src/client/admin/components/File/FileInfo.ts b/automad/src/client/admin/components/File/FileInfo.ts
index b52792aa6..e101f63f0 100644
--- a/automad/src/client/admin/components/File/FileInfo.ts
+++ b/automad/src/client/admin/components/File/FileInfo.ts
@@ -136,9 +136,9 @@ export class FileInfoComponent extends BaseComponent {
${App.text('downloadFile')}
diff --git a/automad/src/client/admin/components/Forms/PageDataForm.ts b/automad/src/client/admin/components/Forms/PageDataForm.ts
index d90b8de00..d9b2cf660 100644
--- a/automad/src/client/admin/components/Forms/PageDataForm.ts
+++ b/automad/src/client/admin/components/Forms/PageDataForm.ts
@@ -446,6 +446,7 @@ export class PageDataFormComponent extends FormComponent {
fields: fieldGroups[item],
tooltips,
themeOptions,
+ renderEmptyAlert: item != 'customizations',
shared,
});
});
diff --git a/automad/src/client/admin/components/Forms/SharedDataForm.ts b/automad/src/client/admin/components/Forms/SharedDataForm.ts
index 017ba1e3e..7089653a5 100644
--- a/automad/src/client/admin/components/Forms/SharedDataForm.ts
+++ b/automad/src/client/admin/components/Forms/SharedDataForm.ts
@@ -245,6 +245,7 @@ export class SharedDataFormComponent extends FormComponent {
fields: fieldGroups[item],
tooltips,
themeOptions,
+ renderEmptyAlert: item != 'customizations',
});
});
}
diff --git a/automad/src/client/admin/components/Pages/Page.ts b/automad/src/client/admin/components/Pages/Page.ts
index 12185433f..dd157d8cf 100644
--- a/automad/src/client/admin/components/Pages/Page.ts
+++ b/automad/src/client/admin/components/Pages/Page.ts
@@ -198,9 +198,9 @@ const renderMenu = (): string => {
- ${App.text('fieldsCustomize')}
+ ${App.text('fieldsCustomizations')}
{
class="${CSS.button}"
${Attr.modal}="#am-add-user-modal"
>
- ${App.text('systemUsersAdd')}
+ ${App.text('systemUsersAdd')}
{
- ${App.text('fieldsCustomize')}
+ ${App.text('fieldsCustomizations')}
{
-
-
+
+
{
>
${App.text('save')}
+
+
+
-
-
-
diff --git a/automad/src/client/admin/core/factory.ts b/automad/src/client/admin/core/factory.ts
index 69215253c..7ea11c589 100644
--- a/automad/src/client/admin/core/factory.ts
+++ b/automad/src/client/admin/core/factory.ts
@@ -149,7 +149,7 @@ export const createFieldSections = (
const sections: FieldSectionCollection = {
settings: createSection(Section.settings),
text: createSection(Section.text),
- customize: createSection(Section.customize),
+ customizations: createSection(Section.customizations),
};
return sections;
diff --git a/automad/src/client/admin/core/form.ts b/automad/src/client/admin/core/form.ts
index 823eee32a..342f57bd3 100644
--- a/automad/src/client/admin/core/form.ts
+++ b/automad/src/client/admin/core/form.ts
@@ -149,35 +149,35 @@ export const createCustomizationFields = (
};
};
- create('p', [], {}, sections.customize, App.text('customization'));
+ create('p', [], {}, sections.customizations, App.text('customization'));
createField(
FieldTag.code,
- sections.customize,
+ sections.customizations,
buildFieldProps('CUSTOM_HTML_HEAD', App.text('customHTMLHead'))
);
createField(
FieldTag.code,
- sections.customize,
+ sections.customizations,
buildFieldProps('CUSTOM_HTML_BODY_END', App.text('customHTMLBodyEnd'))
);
createField(
FieldTag.code,
- sections.customize,
+ sections.customizations,
buildFieldProps('CUSTOM_JS_HEAD', App.text('customJSHead'))
);
createField(
FieldTag.code,
- sections.customize,
+ sections.customizations,
buildFieldProps('CUSTOM_JS_BODY_END', App.text('customJSBodyEnd'))
);
createField(
FieldTag.code,
- sections.customize,
+ sections.customizations,
buildFieldProps('CUSTOM_CSS', App.text('customCSS'))
);
};
@@ -215,9 +215,10 @@ export const fieldGroup = ({
fields,
tooltips,
themeOptions,
+ renderEmptyAlert,
shared,
}: FieldGroupData): void => {
- if (Object.values(fields).length == 0) {
+ if (Object.values(fields).length == 0 && renderEmptyAlert) {
create(
'am-alert',
[],
@@ -333,7 +334,7 @@ export const prepareFieldGroups = (fields: KeyValueMap): FieldGroups => {
const groups: FieldGroups = {
settings: {},
text: {},
- customize: {},
+ customizations: {},
};
Object.keys(fields).forEach((name) => {
@@ -345,7 +346,7 @@ export const prepareFieldGroups = (fields: KeyValueMap): FieldGroups => {
groups.text[name] = fields[name];
break;
case 'color':
- groups.customize[name] = fields[name];
+ groups.customizations[name] = fields[name];
break;
default:
groups.settings[name] = fields[name];
diff --git a/automad/src/client/admin/core/utils.ts b/automad/src/client/admin/core/utils.ts
index 8c3899caa..f4793ee38 100644
--- a/automad/src/client/admin/core/utils.ts
+++ b/automad/src/client/admin/core/utils.ts
@@ -192,7 +192,7 @@ export const titleCase = (str: string): string => {
return str
.replace(/\//g, ' / ')
.replace(/(?!^)([A-Z]+)/g, ' $1')
- .replace('_', ' ')
+ .replace(/_/g, ' ')
.split(' ')
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
diff --git a/automad/src/client/admin/styles/components/card.less b/automad/src/client/admin/styles/components/card.less
index b66b9476a..6916bc8a3 100644
--- a/automad/src/client/admin/styles/components/card.less
+++ b/automad/src/client/admin/styles/components/card.less
@@ -217,17 +217,9 @@
}
&-buttons {
- display: flex;
- gap: @am-card-padding;
-
- * + & {
- margin-top: @am-card-padding;
- }
-
- & > * {
- flex: 1;
- min-width: 0;
- }
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
+ gap: @am-flex-gap;
}
}
diff --git a/automad/src/client/admin/styles/elements/base.less b/automad/src/client/admin/styles/elements/base.less
index 11f21458e..1a26150af 100644
--- a/automad/src/client/admin/styles/elements/base.less
+++ b/automad/src/client/admin/styles/elements/base.less
@@ -129,8 +129,9 @@
& p {
margin: 0;
- max-width: 46rem;
+ max-width: @am-main-width-narrow;
color: hsl(var(--am-clr-text-paragraph));
+ text-wrap: balance;
&:not(:last-child) {
margin-bottom: @am-base-margin-y;
diff --git a/automad/src/client/admin/styles/elements/button.less b/automad/src/client/admin/styles/elements/button.less
index c0ceb5c0f..b9135f924 100644
--- a/automad/src/client/admin/styles/elements/button.less
+++ b/automad/src/client/admin/styles/elements/button.less
@@ -73,6 +73,7 @@
border-color: hsl(var(--border-hover));
}
+ &,
& > * {
overflow: hidden;
white-space: nowrap;
diff --git a/automad/src/client/admin/styles/form/input.less b/automad/src/client/admin/styles/form/input.less
index 223bf98bc..4a53dc46e 100644
--- a/automad/src/client/admin/styles/form/input.less
+++ b/automad/src/client/admin/styles/form/input.less
@@ -43,6 +43,7 @@
background-color: @am-form-background;
transition: all 0.2s;
outline: @am-outline;
+ appearance: none;
&::placeholder {
color: hsl(var(--am-clr-text-muted));
@@ -57,6 +58,10 @@
color: hsl(var(--am-clr-text-muted));
}
+ &::-webkit-date-and-time-value {
+ text-align: left;
+ }
+
&.am-validate:invalid {
color: hsl(var(--am-clr-text-danger));
border-color: hsl(var(--am-clr-border-danger));
diff --git a/automad/src/client/admin/styles/form/select.less b/automad/src/client/admin/styles/form/select.less
index 26e280c77..b4e223945 100644
--- a/automad/src/client/admin/styles/form/select.less
+++ b/automad/src/client/admin/styles/form/select.less
@@ -66,4 +66,9 @@
opacity: 0;
cursor: pointer;
}
+
+ & .bi {
+ font-size: 1.2em;
+ padding-right: 0.2em;
+ }
}
diff --git a/automad/src/client/admin/types/field.ts b/automad/src/client/admin/types/field.ts
index 543a5cd35..310c08309 100644
--- a/automad/src/client/admin/types/field.ts
+++ b/automad/src/client/admin/types/field.ts
@@ -32,10 +32,10 @@
* Licensed under the MIT license.
*/
-import { KeyValueMap, SelectComponentOption, ThemeOptions } from '.';
+import { KeyValueMap, ThemeOptions } from '.';
import { SwitcherSectionComponent } from '@/admin/components/Switcher/SwitcherSection';
-export type FieldSectionName = 'settings' | 'text' | 'customize';
+export type FieldSectionName = 'settings' | 'text' | 'customizations';
export type FieldSectionCollection = {
[name in FieldSectionName]: SwitcherSectionComponent;
@@ -64,6 +64,7 @@ export interface FieldGroupData {
fields: KeyValueMap;
tooltips: KeyValueMap;
themeOptions: ThemeOptions;
+ renderEmptyAlert: boolean;
shared?: KeyValueMap;
}
diff --git a/automad/src/client/common/sections.ts b/automad/src/client/common/sections.ts
index d78120c7a..2db7ec250 100644
--- a/automad/src/client/common/sections.ts
+++ b/automad/src/client/common/sections.ts
@@ -45,6 +45,6 @@ export const enum Section {
config = 'config',
settings = 'settings',
text = 'text',
- customize = 'customize',
+ customizations = 'customizations',
files = 'files',
}
diff --git a/automad/src/client/inpage/components/InPageEdit.ts b/automad/src/client/inpage/components/InPageEdit.ts
index d24eebb6d..5df05b0f7 100644
--- a/automad/src/client/inpage/components/InPageEdit.ts
+++ b/automad/src/client/inpage/components/InPageEdit.ts
@@ -56,27 +56,34 @@ export class InPageEditComponent extends BaseInPageComponent {
// in order to apply correct styles.
const field = this.getAttribute('field');
- const overlay = create('span', ['am-inpage-edit__overlay'], {}, this);
+ setTimeout(() => {
+ const overlay = create(
+ 'span',
+ ['am-inpage-edit__overlay'],
+ {},
+ this
+ );
- const button = create(
- 'span',
- ['am-inpage-edit__button'],
- {},
- overlay,
- label
- );
+ const button = create(
+ 'span',
+ ['am-inpage-edit__button'],
+ {},
+ overlay,
+ label
+ );
- button.addEventListener('click', () => {
- const query = new URLSearchParams({
- field,
- page,
- context,
- }).toString();
+ button.addEventListener('click', () => {
+ const query = new URLSearchParams({
+ field,
+ page,
+ context,
+ }).toString();
- saveScrollPosition();
+ saveScrollPosition();
- window.location.href = `${dashboard}/inpage?${query}`;
- });
+ window.location.href = `${dashboard}/inpage?${query}`;
+ });
+ }, 0);
}
}
diff --git a/automad/src/server/App.php b/automad/src/server/App.php
index 5abc206f1..75cb084fd 100644
--- a/automad/src/server/App.php
+++ b/automad/src/server/App.php
@@ -56,7 +56,7 @@
* @license MIT license - https://automad.org/license
*/
class App {
- const VERSION = '2.0.0-alpha.9';
+ const VERSION = '2.0.0-alpha.10';
/**
* Required PHP version.
diff --git a/automad/src/server/Blocks/Utils/Attr.php b/automad/src/server/Blocks/Utils/Attr.php
index 463199bce..1ca1f9320 100644
--- a/automad/src/server/Blocks/Utils/Attr.php
+++ b/automad/src/server/Blocks/Utils/Attr.php
@@ -48,6 +48,11 @@
* @psalm-import-type Tunes from \Automad\Blocks\AbstractBlock
*/
abstract class Attr {
+ /**
+ * The array of IDs that are already used.
+ */
+ private static array $uniqueIds = array();
+
/**
* Create an attribute string for id, class and style.
*
@@ -57,11 +62,19 @@ abstract class Attr {
* @return string
*/
public static function render(array $tunes, array $classes = array(), ?array $styles = null): string {
- $id = empty($tunes['id']) ? '' : 'id="' . $tunes['id'] . '"';
+ $id = self::uniqueId($tunes['id']);
+ $id = strlen($id) == 0 ? '' : 'id="' . $id . '"';
return join(' ', array_filter(array($id, self::classAttr($tunes, $classes), self::styleAttr($tunes, $styles))));
}
+ /**
+ * Reset the array on unique IDs.
+ */
+ public static function resetUniqueIds(): void {
+ self::$uniqueIds = array();
+ }
+
/**
* Return a class attribute for the wrapping block element.
*
@@ -123,4 +136,28 @@ private static function styleAttr(array $tunes, ?array $styles = null): string {
return 'style="' . join(' ', $rules) . '"';
}
+
+ /**
+ * Make sure an ID is unique.
+ *
+ * @param string $id
+ * @return string
+ */
+ private static function uniqueId(string $id): string {
+ if (strlen($id) == 0) {
+ return '';
+ }
+
+ $base = $id;
+ $suffix = 1;
+
+ while (in_array($id, self::$uniqueIds)) {
+ $id = "$base-$suffix";
+ $suffix++;
+ }
+
+ self::$uniqueIds[] = $id;
+
+ return $id;
+ }
}
diff --git a/automad/src/server/Controllers/API/PageController.php b/automad/src/server/Controllers/API/PageController.php
index 301b34488..572cb11af 100644
--- a/automad/src/server/Controllers/API/PageController.php
+++ b/automad/src/server/Controllers/API/PageController.php
@@ -178,8 +178,6 @@ public static function data(): Response {
$supportedFields
);
- ksort($fields);
-
return $Response->setData(
array(
'url' => $Page->origUrl,
diff --git a/automad/src/server/Controllers/API/SharedController.php b/automad/src/server/Controllers/API/SharedController.php
index a9602edd5..e273b9e06 100644
--- a/automad/src/server/Controllers/API/SharedController.php
+++ b/automad/src/server/Controllers/API/SharedController.php
@@ -100,8 +100,6 @@ public static function data(): Response {
$supportedFields
);
- ksort($fields);
-
return $Response->setData(array('fields' => $fields));
}
diff --git a/automad/src/server/Core/Blocks.php b/automad/src/server/Core/Blocks.php
index a7dc0ab8b..2af507fbb 100644
--- a/automad/src/server/Core/Blocks.php
+++ b/automad/src/server/Core/Blocks.php
@@ -36,6 +36,7 @@
namespace Automad\Core;
+use Automad\Blocks\Utils\Attr;
use Automad\System\Asset;
defined('AUTOMAD') or die('Direct access not permitted!');
@@ -50,6 +51,8 @@
* @psalm-import-type BlockData from \Automad\Blocks\AbstractBlock
*/
class Blocks {
+ private static bool $isRendering = false;
+
/**
* Inject block assets into the header of a page.
*
@@ -76,6 +79,13 @@ public static function injectAssets(string $str): string {
* @return string the rendered HTML
*/
public static function render(array $data, Automad $Automad): string {
+ $isSection = self::$isRendering;
+
+ if (!$isSection) {
+ self::$isRendering = true;
+ Attr::resetUniqueIds();
+ }
+
$flexOpen = false;
$html = '';
@@ -127,6 +137,10 @@ public static function render(array $data, Automad $Automad): string {
$html .= '';
}
+ if (!$isSection) {
+ self::$isRendering = false;
+ }
+
return $html;
}
}
diff --git a/automad/src/server/Engine/Processors/MailAddressProcessor.php b/automad/src/server/Engine/Processors/MailAddressProcessor.php
index f7ac88191..511cf593b 100644
--- a/automad/src/server/Engine/Processors/MailAddressProcessor.php
+++ b/automad/src/server/Engine/Processors/MailAddressProcessor.php
@@ -132,7 +132,7 @@ private function generateKey(string $email): string {
}
/**
- * The function that is used to process the mody in the regex matches matched in the obfuscate method.
+ * The function that is used to process the body in the regex matches matched in the obfuscate method.
*
* @param array $matches
* @return string
@@ -154,7 +154,7 @@ function ($matches) {
);
$body = preg_replace_callback(
- '/(]*>.+?<\/a>|(' . $regexEmail . '))/is',
+ '/(]*>.+?<\/a>|(' . $regexEmail . '))/is',
function ($matches) {
if (empty($matches[2])) {
return $matches[0];
diff --git a/automad/src/server/System/Fields.php b/automad/src/server/System/Fields.php
index 922b67e97..829a3877c 100644
--- a/automad/src/server/System/Fields.php
+++ b/automad/src/server/System/Fields.php
@@ -139,7 +139,7 @@ public static function inCurrentTemplate(Page $Page, ?Theme $Theme = null): arra
$file = AM_BASE_DIR . AM_DIR_PACKAGES . '/' . $Page->get(Fields::THEME) . '/' . $Page->template . '.php';
$fields = self::inTemplate($file);
- return self::cleanUp($fields, $Theme->getMask('page'));
+ return self::cleanUp($fields, $Theme->getMask('page'), $Theme->fieldOrder);
}
/**
@@ -196,28 +196,38 @@ public static function inTheme(Theme $Theme): array {
$fields = array_merge($fields, self::inTemplate($file));
}
- return self::cleanUp($fields, $Theme->getMask('shared'));
+ return self::cleanUp($fields, $Theme->getMask('shared'), $Theme->fieldOrder);
}
/**
* Cleans up an array of fields. All reserved and duplicate fields get removed
- * and the optional UI mask is applied.
+ * and the optional UI mask is applied. Fields are sorted according to a field order
+ * array.
*
* @param array $fields
* @param array $mask
+ * @param array $fieldOrder
* @return array The sorted and filtered fields array
*/
- private static function cleanUp(array $fields, array $mask = array()): array {
+ private static function cleanUp(array $fields, array $mask = array(), array $fieldOrder = array()): array {
if (empty($fields)) {
return array();
}
+ $fields = array_unique(array_diff($fields, array_values(self::$reserved)));
+
if (!empty($mask)) {
$fields = array_filter($fields, function ($key) use ($mask) {
return !in_array($key, $mask);
});
}
- return array_unique(array_diff($fields, array_values(self::$reserved)));
+ if (!empty($fieldOrder)) {
+ $fields = array_keys(array_merge(array_fill_keys($fieldOrder, true), array_fill_keys($fields, true)));
+ } else {
+ sort($fields);
+ }
+
+ return $fields;
}
}
diff --git a/automad/src/server/System/Theme.php b/automad/src/server/System/Theme.php
index 1e7387320..34e3729eb 100644
--- a/automad/src/server/System/Theme.php
+++ b/automad/src/server/System/Theme.php
@@ -61,6 +61,11 @@ class Theme {
*/
public string $description = '';
+ /**
+ * The field order array defines the order of fields in the dashboard.
+ */
+ public array $fieldOrder = array();
+
/**
* The theme license.
*/
@@ -118,15 +123,16 @@ public function __construct(string $themeJson, array $composerInstalled) {
$package = Package::getPackageForPath(dirname($themeJson));
$defaults = array(
- 'name' => $path,
- 'description' => false,
'author' => false,
- 'version' => false,
+ 'description' => false,
+ 'fieldOrder' => array(),
'license' => false,
'masks' => array(),
- 'tooltips' => array(),
+ 'name' => $path,
'options' => array(),
- 'readme' => ''
+ 'readme' => '',
+ 'tooltips' => array(),
+ 'version' => false
);
// Get Composer version and readme URL.
@@ -167,14 +173,15 @@ public function __construct(string $themeJson, array $composerInstalled) {
$this->author = $data['author'];
$this->description = $data['description'];
+ $this->fieldOrder = $data['fieldOrder'];
$this->license = $data['license'];
$this->masks = $data['masks'];
$this->name = $data['name'];
+ $this->options = $data['options'];
$this->path = $path;
$this->readme = $data['readme'];
$this->templates = $templates;
$this->tooltips = $data['tooltips'];
- $this->options = $data['options'];
$this->version = $data['version'];
}
diff --git a/automad/tests/bootstrap-i18n.php b/automad/tests/bootstrap-i18n.php
index b075a3940..828b40ea9 100644
--- a/automad/tests/bootstrap-i18n.php
+++ b/automad/tests/bootstrap-i18n.php
@@ -10,6 +10,7 @@
define('AM_DIR_PACKAGES', '/automad/tests/i18n/packages');
define('AM_DIR_PAGES', '/automad/tests/i18n/pages');
define('AM_DIR_SHARED', '/automad/tests/i18n/shared');
+define('AM_FILE_UI_TRANSLATION', '');
define('AM_FEED_ENABLED', false);
define('AM_I18N_ENABLED', true);
define('AM_REQUEST', '/');
diff --git a/automad/tests/bootstrap-main.php b/automad/tests/bootstrap-main.php
index bfbfa79dc..c69060a25 100644
--- a/automad/tests/bootstrap-main.php
+++ b/automad/tests/bootstrap-main.php
@@ -10,6 +10,7 @@
define('AM_DIR_PACKAGES', '/automad/tests/main/packages');
define('AM_DIR_PAGES', '/automad/tests/main/data');
define('AM_DIR_SHARED', '/automad/tests/main/shared');
+define('AM_FILE_UI_TRANSLATION', '');
define('AM_FEED_ENABLED', false);
define('AM_I18N_ENABLED', false);
define('AM_REQUEST', '/page');
diff --git a/automad/tests/main/src/Blocks/Utils/AttrTest.php b/automad/tests/main/src/Blocks/Utils/AttrTest.php
new file mode 100644
index 000000000..430162977
--- /dev/null
+++ b/automad/tests/main/src/Blocks/Utils/AttrTest.php
@@ -0,0 +1,158 @@
+Headline
+ Text
+
+ Headline
+ Text
+
+ Headline
+ Headline
+ Custom
+ Text
+ HTML
+ )
+ );
+ }
+
+ /**
+ * @dataProvider dataForTestUniqueIdsIsSame
+ * @testdox test block ids to be unique
+ * @param array $data
+ * @param string $html
+ */
+ public function testUniqueIdsIsSame(array $data, string $html) {
+ $Mock = new Mock();
+
+ $actual = preg_replace('/\>\s+\', '><', Blocks::render($data, $Mock->createAutomad()));
+ $expected = preg_replace('/\>\s+\', '><', $html);
+
+ $this->assertSame($expected, $actual);
+ }
+}
diff --git a/lib/composer.lock b/lib/composer.lock
index e24306c57..0dd062a17 100644
--- a/lib/composer.lock
+++ b/lib/composer.lock
@@ -12,12 +12,12 @@
"source": {
"type": "git",
"url": "https://github.com/automadcms/automad-language-packs.git",
- "reference": "f567705f09cdb0bdc5c69a279198d65fb7ea2565"
+ "reference": "edc5a3ddc486001aa309235095f36dccea67fca5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/automadcms/automad-language-packs/zipball/f567705f09cdb0bdc5c69a279198d65fb7ea2565",
- "reference": "f567705f09cdb0bdc5c69a279198d65fb7ea2565",
+ "url": "https://api.github.com/repos/automadcms/automad-language-packs/zipball/edc5a3ddc486001aa309235095f36dccea67fca5",
+ "reference": "edc5a3ddc486001aa309235095f36dccea67fca5",
"shasum": ""
},
"default-branch": true,
@@ -55,7 +55,7 @@
"type": "ko_fi"
}
],
- "time": "2024-11-09T12:38:26+00:00"
+ "time": "2024-11-12T19:58:59+00:00"
},
{
"name": "doctrine/lexer",
diff --git a/package-lock.json b/package-lock.json
index 8ed63c360..06f2f148e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "automad",
- "version": "2.0.0-alpha.9",
+ "version": "2.0.0-alpha.10",
"lockfileVersion": 2,
"requires": true,
"packages": {
diff --git a/package.json b/package.json
index 9d3476544..12094021c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "automad",
- "version": "2.0.0-alpha.9",
+ "version": "2.0.0-alpha.10",
"description": "Automad",
"author": "Marc Anton Dahmen",
"license": "MIT",