Skip to content
This repository was archived by the owner on Sep 9, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions packages/core/src/__tests__/backend.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
createMockExpandedEntry,
createMockUnpublishedEntry,
} from '@staticcms/test/data/entry.mock';
import { applyDefaults } from '../actions/config';
import {
Backend,
expandSearchEntries,
Expand Down Expand Up @@ -327,8 +328,10 @@ describe('Backend', () => {
format: 'json-frontmatter',
}) as CollectionWithDefaults;

const config = applyDefaults(createMockConfig({ collections: [collection] }));

const backend = new Backend(initializer, {
config: createMockConfig({ collections: [collection] }),
config,
backendName: 'github',
});

Expand All @@ -343,10 +346,10 @@ describe('Backend', () => {
},
});

await backend.persistLocalDraftBackup(entry, collection);
await backend.persistLocalDraftBackup(entry, collection, config);

expect(backend.entryToRaw).toHaveBeenCalledTimes(1);
expect(backend.entryToRaw).toHaveBeenCalledWith(collection, entry);
expect(backend.entryToRaw).toHaveBeenCalledWith(collection, entry, config);
expect(localForage.setItem).toHaveBeenCalledTimes(0);
});

Expand All @@ -364,8 +367,10 @@ describe('Backend', () => {
format: 'json-frontmatter',
}) as CollectionWithDefaults;

const config = applyDefaults(createMockConfig({ collections: [collection] }));

const backend = new Backend(initializer, {
config: createMockConfig({ collections: [collection] }),
config,
backendName: 'github',
});

Expand All @@ -382,10 +387,10 @@ describe('Backend', () => {
},
});

await backend.persistLocalDraftBackup(entry, collection);
await backend.persistLocalDraftBackup(entry, collection, config);

expect(backend.entryToRaw).toHaveBeenCalledTimes(1);
expect(backend.entryToRaw).toHaveBeenCalledWith(collection, entry);
expect(backend.entryToRaw).toHaveBeenCalledWith(collection, entry, config);
expect(localForage.setItem).toHaveBeenCalledTimes(2);
expect(localForage.setItem).toHaveBeenCalledWith('backup.posts.slug', {
mediaFiles: [{ id: '1', name: 'file.png', path: '/path/to/file.png' }],
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/actions/editorialWorkflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ export function persistUnpublishedEntry(
let serializedEntry = getSerializedEntry(collection, entry);
serializedEntry = {
...serializedEntry,
raw: backend.entryToRaw(collection, serializedEntry),
raw: backend.entryToRaw(collection, serializedEntry, state.config.config),
};
const serializedEntryDraft: EntryDraft = {
...(entryDraft as EntryDraft),
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/actions/entries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@ export function persistLocalBackup(entry: Entry, collection: CollectionWithDefau

const backend = currentBackend(configState.config);

return backend.persistLocalDraftBackup(entry, collection);
return backend.persistLocalDraftBackup(entry, collection, configState.config);
};
}

Expand Down
22 changes: 14 additions & 8 deletions packages/core/src/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -780,11 +780,15 @@ export class Backend<EF extends BaseField = UnknownField, BC extends BackendClas
return { entry };
}

async persistLocalDraftBackup(entry: Entry, collection: CollectionWithDefaults) {
async persistLocalDraftBackup(
entry: Entry,
collection: CollectionWithDefaults,
config: ConfigWithDefaults,
) {
try {
await this.backupSync.acquire();
const key = getEntryBackupKey(collection.name, entry.slug);
const raw = this.entryToRaw(collection, entry);
const raw = this.entryToRaw(collection, entry, config);

if (!raw.trim()) {
return;
Expand All @@ -803,7 +807,9 @@ export class Backend<EF extends BaseField = UnknownField, BC extends BackendClas

let i18n;
if (hasI18n(collection)) {
i18n = getI18nBackup(collection, entry, entry => this.entryToRaw(collection, entry));
i18n = getI18nBackup(collection, entry, entry =>
this.entryToRaw(collection, entry, config),
);
}

await localForage.setItem<BackupEntry>(key, {
Expand Down Expand Up @@ -994,15 +1000,15 @@ export class Backend<EF extends BaseField = UnknownField, BC extends BackendClas
dataFile = {
path,
slug,
raw: this.entryToRaw(collection, entryDraft.entry),
raw: this.entryToRaw(collection, entryDraft.entry, config),
};
} else {
const slug = entryDraft.entry.slug;
dataFile = {
path: entryDraft.entry.path,
// for workflow entries we refresh the slug on publish
slug: customPath && !useWorkflow ? slugFromCustomPath(collection, customPath) : slug,
raw: this.entryToRaw(collection, entryDraft.entry),
raw: this.entryToRaw(collection, entryDraft.entry, config),
newPath: customPath,
};
}
Expand All @@ -1016,7 +1022,7 @@ export class Backend<EF extends BaseField = UnknownField, BC extends BackendClas
collection,
extension,
entryDraft.entry,
(draftData: Entry) => this.entryToRaw(collection, draftData),
(draftData: Entry) => this.entryToRaw(collection, draftData, config),
path,
slug,
newPath,
Expand Down Expand Up @@ -1164,11 +1170,11 @@ export class Backend<EF extends BaseField = UnknownField, BC extends BackendClas
return this.implementation.deleteFiles([path], commitMessage);
}

entryToRaw(collection: CollectionWithDefaults, entry: Entry): string {
entryToRaw(collection: CollectionWithDefaults, entry: Entry, config: ConfigWithDefaults): string {
const format = resolveFormat(collection, entry);
const fieldsOrder = this.fieldsOrder(collection, entry);
const fieldsComments = selectFieldsComments(collection, entry);
return format ? format.toFile(entry.data ?? {}, fieldsOrder, fieldsComments) : '';
return format ? format.toFile(entry.data ?? {}, config, fieldsOrder, fieldsComments) : '';
}

fieldsOrder(collection: CollectionWithDefaults, entry: Entry) {
Expand Down
11 changes: 9 additions & 2 deletions packages/core/src/formats/FileFormatter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import type { ConfigWithDefaults } from '../interface';

export default abstract class FileFormatter {
abstract name: string;
abstract fromFile(content: string): object;
abstract toFile(data: object, sortedKeys?: string[], comments?: Record<string, string>): string;
abstract fromFile(content: string, config: ConfigWithDefaults): object;
abstract toFile(
data: object,
config: ConfigWithDefaults,
sortedKeys?: string[],
comments?: Record<string, string>,
): string;
}
40 changes: 30 additions & 10 deletions packages/core/src/formats/YamlFormatter.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import yaml, { isNode, isMap } from 'yaml';
import yaml, { isMap, isNode } from 'yaml';

import { sortKeys } from './helpers';
import FileFormatter from './FileFormatter';
import { isNotNullish } from '../lib/util/null.util';
import FileFormatter from './FileFormatter';
import { sortKeys } from './helpers';

import type { Pair, YAMLMap, Node } from 'yaml';
import type { Node, Pair, YAMLMap } from 'yaml';
import type { ConfigWithDefaults } from '../interface';

function addComments(items: Array<Pair>, comments: Record<string, string>, prefix = '') {
items.forEach(item => {
Expand All @@ -25,23 +26,42 @@ function addComments(items: Array<Pair>, comments: Record<string, string>, prefi
class YamlFormatter extends FileFormatter {
name = 'yaml';

fromFile(content: string) {
fromFile(content: string, config: ConfigWithDefaults) {
if (content && content.trim().endsWith('---')) {
content = content.trim().slice(0, -3);
}
return yaml.parse(content);
return yaml.parse(content, {
...(config.yaml?.parseOptions ?? {}),
...(config.yaml?.documentOptions ?? {}),
...(config.yaml?.schemaOptions ?? {}),
...(config.yaml?.toJsOptions ?? {}),
});
}

toFile(data: object, sortedKeys: string[] = [], comments: Record<string, string> = {}) {
const doc = new yaml.Document({ aliasDuplicateObjects: false });
const contents = doc.createNode(data) as YAMLMap<Node>;
toFile(
data: object,
config: ConfigWithDefaults,
sortedKeys: string[] = [],
comments: Record<string, string> = {},
) {
const doc = new yaml.Document({
aliasDuplicateObjects: false,
...(config.yaml?.documentOptions ?? {}),
...(config.yaml?.schemaOptions ?? {}),
...(config.yaml?.parseOptions ?? {}),
...(config.yaml?.createNodeOptions ?? {}),
});
const contents = doc.createNode(data, {
aliasDuplicateObjects: false,
...(config.yaml?.createNodeOptions ?? {}),
}) as YAMLMap<Node>;

addComments(contents.items as Pair<Node>[], comments);

contents.items.sort(sortKeys(sortedKeys, item => item.key?.toString()));
doc.contents = contents;

return doc.toString();
return doc.toString(config.yaml?.toStringOptions);
}
}

Expand Down
Loading