Skip to content

Commit

Permalink
Merge content finalization methods
Browse files Browse the repository at this point in the history
  • Loading branch information
kyoshino committed Nov 21, 2024
1 parent abc1d2d commit 0574c46
Showing 1 changed file with 51 additions and 47 deletions.
98 changes: 51 additions & 47 deletions src/lib/services/contents/draft/save.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,15 +209,26 @@ const createKeyPathList = (fields) => {
};

/**
* Sort the entry draft content’s object properties by the order of the configured collection
* fields. The result can be formatted as expected with `JSON.stringify()`, as the built-in method
* uses insertion order for string key ordering.
* @param {Field[]} fields - Field list of a collection or a file.
* @param {FlattenedEntryContent} valueMap - Flattened entry content.
* @param {string} [canonicalSlugKey] - Property name of a canonical slug.
* @returns {FlattenedEntryContent} Flattened entry content sorted by fields.
* Finalize the content by sorting the entry draft content’s object properties by the order of the
* configured collection fields. The result can be formatted as expected with `JSON.stringify()`, as
* the built-in method uses insertion order for string key ordering.
* @param {object} args - Options.
* @param {string} args.collectionName - Collection name.
* @param {string} [args.fileName] - File name.
* @param {Field[]} args.fields - Field list of a collection or a file.
* @param {FlattenedEntryContent} args.valueMap - Flattened entry content.
* @param {string} [args.canonicalSlugKey] - Property name of a canonical slug.
* @param {boolean} [args.isTomlOutput] - Whether the output it TOML format.
* @returns {Record<string, any>} Unflattened entry content sorted by fields.
*/
const sortContentProps = (fields, valueMap, canonicalSlugKey) => {
const finalizeContent = ({
collectionName,
fileName,
fields,
valueMap,
canonicalSlugKey,
isTomlOutput = false,
}) => {
/** @type {FlattenedEntryContent} */
const unsortedMap = toRaw(valueMap);
/** @type {FlattenedEntryContent} */
Expand All @@ -228,7 +239,25 @@ const sortContentProps = (fields, valueMap, canonicalSlugKey) => {
* @param {string} key - Property name.
*/
const copyProperty = (key) => {
sortedMap[key] = unsortedMap[key];
let value = unsortedMap[key];

// Use native date for TOML
// @see https://github.com/squirrelchat/smol-toml?tab=readme-ov-file#dates
// @see https://toml.io/en/v1.0.0#offset-date-time
if (
isTomlOutput &&
typeof value === 'string' &&
value.match(fullDateTimeRegEx) &&
getFieldConfig({ collectionName, fileName, valueMap, keyPath: key })?.widget === 'datetime'
) {
try {
value = new TomlDate(value);
} catch {
//
}
}

sortedMap[key] = value;
delete unsortedMap[key];
};

Expand Down Expand Up @@ -261,34 +290,6 @@ const sortContentProps = (fields, valueMap, canonicalSlugKey) => {
return sortedMap;
};

/**
* Modify the content for TOML output, particularly date/time.
* @param {object} args - Arguments.
* @param {string} args.collectionName - Collection name.
* @param {string} [args.fileName] - File name.
* @param {FlattenedEntryContent} args.valueMap - Object holding current entry values.
* @returns {FlattenedEntryContent} Modified content.
* @see https://github.com/squirrelchat/smol-toml?tab=readme-ov-file#dates
* @see https://toml.io/en/v1.0.0#offset-date-time
*/
const modifyContentForTOML = ({ collectionName, fileName, valueMap }) => {
Object.entries(valueMap).forEach(([keyPath, value]) => {
if (
typeof value === 'string' &&
value.match(fullDateTimeRegEx) &&
getFieldConfig({ collectionName, fileName, valueMap, keyPath })?.widget === 'datetime'
) {
try {
valueMap[keyPath] = new TomlDate(value);
} catch {
//
}
}
});

return valueMap;
};

/**
* Create saving entry data.
* @param {object} args - Arguments.
Expand Down Expand Up @@ -348,16 +349,19 @@ export const createSavingEntryData = async ({
const changes = [];

/**
* Finalize the content by modifying for a specific data format and unflattening the object.
* Serialize the content for the output.
* @param {FlattenedEntryContent} valueMap - Original content.
* @returns {RawEntryContent} Modified and unflattened content.
*/
const finalizeContent = (valueMap) => {
let content = sortContentProps(fields, valueMap, canonicalSlugKey);

if (isTomlOutput) {
content = modifyContentForTOML({ collectionName, fileName, valueMap: content });
}
const serializeContent = (valueMap) => {
let content = finalizeContent({
collectionName,
fileName,
fields,
valueMap,
canonicalSlugKey,
isTomlOutput,
});

content = unflatten(content);

Expand All @@ -379,10 +383,10 @@ export const createSavingEntryData = async ({
? Object.fromEntries(
Object.entries(savingEntry.locales).map(([locale, le]) => [
locale,
finalizeContent(le.content),
serializeContent(le.content),
]),
)
: finalizeContent(content),
: serializeContent(content),
_file,
});

Expand All @@ -396,7 +400,7 @@ export const createSavingEntryData = async ({

if (currentLocales[locale]) {
const action = isNew || !originalLocales[locale] ? 'create' : 'update';
const data = await formatEntryFile({ content: finalizeContent(content), _file });
const data = await formatEntryFile({ content: serializeContent(content), _file });

changes.push({ action, slug, path, data });
localizedEntry.sha = await getHash(new Blob([data], { type: 'text/plain' }));
Expand Down

0 comments on commit 0574c46

Please sign in to comment.