planning
All checks were successful
Publish To Prod / deploy_and_publish (push) Successful in 35s

This commit is contained in:
2024-10-14 09:15:30 +02:00
parent bcba00a730
commit 6e64e138e2
21059 changed files with 2317811 additions and 1 deletions

126
node_modules/decap-cms-lib-widgets/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,126 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.0.2](https://github.com/decaporg/decap-cms/compare/decap-cms-lib-widgets@3.0.1...decap-cms-lib-widgets@3.0.2) (2024-03-21)
**Note:** Version bump only for package decap-cms-lib-widgets
## [3.0.1](https://github.com/decaporg/decap-cms/compare/decap-cms-lib-widgets@3.0.1-beta.2...decap-cms-lib-widgets@3.0.1) (2024-02-01)
**Note:** Version bump only for package decap-cms-lib-widgets
## [3.0.1-beta.2](https://github.com/decaporg/decap-cms/compare/decap-cms-lib-widgets@3.0.1-beta.1...decap-cms-lib-widgets@3.0.1-beta.2) (2024-01-31)
**Note:** Version bump only for package decap-cms-lib-widgets
## [3.0.1-beta.1](https://github.com/decaporg/decap-cms/compare/decap-cms-lib-widgets@3.0.1-beta.0...decap-cms-lib-widgets@3.0.1-beta.1) (2024-01-16)
### Bug Fixes
- change dayjs to per-package dependency ([#6992](https://github.com/decaporg/decap-cms/issues/6992)) ([0c278b0](https://github.com/decaporg/decap-cms/commit/0c278b0a83d93233d3b3e860d3029df20fe1c501))
## [3.0.1-beta.0](https://github.com/decaporg/decap-cms/compare/decap-cms-lib-widgets@3.0.0...decap-cms-lib-widgets@3.0.1-beta.0) (2023-11-23)
### Performance Improvements
- replace moment with dayjs ([#6980](https://github.com/decaporg/decap-cms/issues/6980)) ([22370b1](https://github.com/decaporg/decap-cms/commit/22370b13e49a4a5f58a60ebd4bc40ce4b141eb11))
# [3.0.0](https://github.com/decaporg/decap-cms/compare/decap-cms-lib-widgets@1.9.0...decap-cms-lib-widgets@3.0.0) (2023-08-18)
**Note:** Version bump only for package decap-cms-lib-widgets
# [1.9.0](https://github.com/decaporg/decap-cms/compare/decap-cms-lib-widgets@1.9.0-beta.0...decap-cms-lib-widgets@1.9.0) (2023-08-18)
**Note:** Version bump only for package decap-cms-lib-widgets
# 1.9.0-beta.0 (2023-08-18)
### Features
- rename packages ([#6863](https://github.com/decaporg/decap-cms/issues/6863)) ([d515e7b](https://github.com/decaporg/decap-cms/commit/d515e7bd33216a775d96887b08c4f7b1962941bb))
## [1.8.2-beta.0](https://github.com/decaporg/decap-cms/compare/decap-cms-lib-widgets@1.8.1...decap-cms-lib-widgets@1.8.2-beta.0) (2023-07-27)
**Note:** Version bump only for package decap-cms-lib-widgets
## [1.8.1](https://github.com/decaporg/decap-cms/compare/decap-cms-lib-widgets@1.8.0...decap-cms-lib-widgets@1.8.1) (2022-04-13)
**Note:** Version bump only for package decap-cms-lib-widgets
# [1.8.0](https://github.com/decaporg/decap-cms/compare/decap-cms-lib-widgets@1.7.0...decap-cms-lib-widgets@1.8.0) (2022-01-21)
### Features
- add truncate filter to summary tag ([#6105](https://github.com/decaporg/decap-cms/issues/6105)) ([d66c573](https://github.com/decaporg/decap-cms/commit/d66c573697c6a66919e048f0fde9cf2f8ea6acac))
# [1.7.0](https://github.com/decaporg/decap-cms/compare/decap-cms-lib-widgets@1.6.3...decap-cms-lib-widgets@1.7.0) (2021-10-11)
### Features
- add string template filters "default" and "ternary" ([#3677](https://github.com/decaporg/decap-cms/issues/3677)) ([#5878](https://github.com/decaporg/decap-cms/issues/5878)) ([c791158](https://github.com/decaporg/decap-cms/commit/c791158dd5ea8ea03930f9881a86c71cb1770836))
## [1.6.3](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/compare/decap-cms-lib-widgets@1.6.2...decap-cms-lib-widgets@1.6.3) (2021-06-01)
**Note:** Version bump only for package decap-cms-lib-widgets
## [1.6.2](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/compare/decap-cms-lib-widgets@1.6.1...decap-cms-lib-widgets@1.6.2) (2021-05-31)
**Note:** Version bump only for package decap-cms-lib-widgets
## [1.6.1](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/compare/decap-cms-lib-widgets@1.6.0...decap-cms-lib-widgets@1.6.1) (2021-02-10)
**Note:** Version bump only for package decap-cms-lib-widgets
# [1.6.0](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/compare/decap-cms-lib-widgets@1.5.0...decap-cms-lib-widgets@1.6.0) (2020-10-25)
### Features
- Support filters for template strings [#3677](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/issues/3677) ([#4396](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/issues/4396)) ([1fa108e](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/commit/1fa108ee67b7e992a4d2a61cde13df7917e103be))
# [1.5.0](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/compare/decap-cms-lib-widgets@1.4.0...decap-cms-lib-widgets@1.5.0) (2020-10-20)
### Features
- **widget-list:** add min max configuration ([#4394](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/issues/4394)) ([5fdfe40](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/commit/5fdfe40dd29e9e22c9ae7d6219bc057f7ea7280b))
# [1.4.0](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/compare/decap-cms-lib-widgets@1.3.5...decap-cms-lib-widgets@1.4.0) (2020-09-28)
### Features
- **core:** Add {{dirname}} to summary and preview_path ([#4279](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/issues/4279)) ([576e4f0](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/commit/576e4f0f1a158d6b587587c52fb288d8f6eea89f))
## [1.3.5](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/compare/decap-cms-lib-widgets@1.3.4...decap-cms-lib-widgets@1.3.5) (2020-09-15)
**Note:** Version bump only for package decap-cms-lib-widgets
## 1.3.4 (2020-09-08)
### Reverts
- Revert "chore(release): publish" ([828bb16](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/commit/828bb16415b8c22a34caa19c50c38b24ffe9ceae))
## 1.3.3 (2020-08-20)
### Reverts
- Revert "chore(release): publish" ([8262487](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/commit/82624879ccbcb16610090041db28f00714d924c8))
## 1.3.2 (2020-07-27)
### Reverts
- Revert "chore(release): publish" ([118d50a](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/commit/118d50a7a70295f25073e564b5161aa2b9883056))
## [1.3.1](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/compare/decap-cms-lib-widgets@1.3.0...decap-cms-lib-widgets@1.3.1) (2020-07-14)
### Bug Fixes
- relation widget performance ([#3975](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/issues/3975)) ([c7e0fe8](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/commit/c7e0fe8492d09a3d151c608f50da844f421362ed))
# 1.3.0 (2020-05-04)
### Features
- **widget-relation:** string templates support ([#3659](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/issues/3659)) ([213ae86](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets/commit/213ae86b54d02f5fc79fe11113507587ed062ff2))

22
node_modules/decap-cms-lib-widgets/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,22 @@
Copyright (c) 2016 Netlify <decap@p-m.si>
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

9
node_modules/decap-cms-lib-widgets/README.md generated vendored Normal file
View File

@@ -0,0 +1,9 @@
# Docs coming soon!
Decap CMS was converted from a single npm package to a "monorepo" of over 20 packages.
We haven't created a README for this package yet, but you can:
1. Check out the [main readme](https://github.com/decaporg/decap-cms/#readme) or the [documentation
site](https://www.decapcms.org) for more info.
2. Reach out to the [community chat](https://decapcms.org/chat/) if you need help.
3. Help out and [write the readme yourself](https://github.com/decaporg/decap-cms/edit/main/packages/decap-cms-lib-widgets/README.md)!

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

16
node_modules/decap-cms-lib-widgets/dist/esm/index.js generated vendored Normal file
View File

@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.validations = exports.stringTemplate = exports.DecapCmsLibWidgets = void 0;
var stringTemplate = _interopRequireWildcard(require("./stringTemplate"));
exports.stringTemplate = stringTemplate;
var validations = _interopRequireWildcard(require("./validations"));
exports.validations = validations;
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const DecapCmsLibWidgets = exports.DecapCmsLibWidgets = {
stringTemplate,
validations
};

View File

@@ -0,0 +1,223 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.SLUG_MISSING_REQUIRED_DATE = void 0;
exports.addFileTemplateFields = addFileTemplateFields;
exports.compileStringTemplate = compileStringTemplate;
exports.dateParsers = void 0;
exports.expandPath = expandPath;
exports.extractTemplateVars = extractTemplateVars;
exports.keyToPathArray = keyToPathArray;
exports.parseDateFromEntry = parseDateFromEntry;
var _truncate2 = _interopRequireDefault(require("lodash/truncate"));
var _trimEnd2 = _interopRequireDefault(require("lodash/trimEnd"));
var _get2 = _interopRequireDefault(require("lodash/get"));
var _immutable = require("immutable");
var _dayjs = _interopRequireDefault(require("dayjs"));
var _path = require("path");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const filters = [{
pattern: /^upper$/,
transform: str => str.toUpperCase()
}, {
pattern: /^lower$/,
transform: str => str.toLowerCase()
}, {
pattern: /^date\('(.+)'\)$/,
transform: (str, match) => (0, _dayjs.default)(str).format(match[1])
}, {
pattern: /^default\('(.+)'\)$/,
transform: (str, match) => str ? str : match[1]
}, {
pattern: /^ternary\('(.*)',\s*'(.*)'\)$/,
transform: (str, match) => str ? match[1] : match[2]
}, {
pattern: /^truncate\(([0-9]+)(?:(?:,\s*['"])([^'"]*)(?:['"]))?\)$/,
transform: (str, match) => {
const omission = match[2] || '...';
const length = parseInt(match[1]) + omission.length;
return (0, _truncate2.default)(str, {
length,
omission
});
}
}];
const FIELD_PREFIX = 'fields.';
const templateContentPattern = '([^}{|]+)';
const filterPattern = '( \\| ([^}{]+))?';
const templateVariablePattern = `{{${templateContentPattern}${filterPattern}}}`;
// prepends a Zero if the date has only 1 digit
function formatDate(date) {
return `0${date}`.slice(-2);
}
const dateParsers = exports.dateParsers = {
year: date => `${date.getUTCFullYear()}`,
month: date => formatDate(date.getUTCMonth() + 1),
day: date => formatDate(date.getUTCDate()),
hour: date => formatDate(date.getUTCHours()),
minute: date => formatDate(date.getUTCMinutes()),
second: date => formatDate(date.getUTCSeconds())
};
function parseDateFromEntry(entry, dateFieldName) {
if (!dateFieldName) {
return;
}
const dateValue = entry.getIn(['data', dateFieldName]);
const dateDayjs = dateValue && (0, _dayjs.default)(dateValue);
if (dateDayjs && dateDayjs.isValid()) {
return dateDayjs.toDate();
}
}
const SLUG_MISSING_REQUIRED_DATE = exports.SLUG_MISSING_REQUIRED_DATE = 'SLUG_MISSING_REQUIRED_DATE';
function keyToPathArray(key) {
if (!key) {
return [];
}
const parts = [];
const separator = '';
const chars = key.split(separator);
let currentChar;
let currentStr = [];
while (currentChar = chars.shift()) {
if (['[', ']', '.'].includes(currentChar)) {
if (currentStr.length > 0) {
parts.push(currentStr.join(separator));
}
currentStr = [];
} else {
currentStr.push(currentChar);
}
}
if (currentStr.length > 0) {
parts.push(currentStr.join(separator));
}
return parts;
}
function expandPath({
data,
path,
paths = []
}) {
if (path.endsWith('.*')) {
path = path + '.';
}
const sep = '.*.';
const parts = path.split(sep);
if (parts.length === 1) {
paths.push(path);
} else {
const partialPath = parts[0];
const value = (0, _get2.default)(data, partialPath);
if (Array.isArray(value)) {
value.forEach((_, index) => {
expandPath({
data,
path: (0, _trimEnd2.default)(`${partialPath}.${index}.${parts.slice(1).join(sep)}`, '.'),
paths
});
});
}
}
return paths;
}
// Allow `fields.` prefix in placeholder to override built in replacements
// like "slug" and "year" with values from fields of the same name.
function getExplicitFieldReplacement(key, data) {
if (!key.startsWith(FIELD_PREFIX)) {
return;
}
const fieldName = key.slice(FIELD_PREFIX.length);
const value = data.getIn(keyToPathArray(fieldName));
if (typeof value === 'object' && value !== null) {
return JSON.stringify(value);
}
return value;
}
function getFilterFunction(filterStr) {
if (filterStr) {
let match = null;
const filter = filters.find(filter => {
match = filterStr.match(filter.pattern);
return !!match;
});
if (filter) {
return str => filter.transform(str, match);
}
}
return null;
}
function compileStringTemplate(template, date, identifier = '', data = (0, _immutable.Map)(), processor) {
let missingRequiredDate;
// Turn off date processing (support for replacements like `{{year}}`), by passing in
// `null` as the date arg.
const useDate = date !== null;
const compiledString = template.replace(RegExp(templateVariablePattern, 'g'), (_full, key, _part, filter) => {
let replacement;
const explicitFieldReplacement = getExplicitFieldReplacement(key, data);
if (explicitFieldReplacement) {
replacement = explicitFieldReplacement;
} else if (dateParsers[key] && !date) {
missingRequiredDate = true;
return '';
} else if (dateParsers[key]) {
replacement = dateParsers[key](date);
} else if (key === 'slug') {
replacement = identifier;
} else {
replacement = data.getIn(keyToPathArray(key), '');
}
if (processor) {
return processor(replacement);
} else {
const filterFunction = getFilterFunction(filter);
if (filterFunction) {
replacement = filterFunction(replacement);
}
}
return replacement;
});
if (useDate && missingRequiredDate) {
const err = new Error();
err.name = SLUG_MISSING_REQUIRED_DATE;
throw err;
} else {
return compiledString;
}
}
function extractTemplateVars(template) {
const regexp = RegExp(templateVariablePattern, 'g');
const contentRegexp = RegExp(templateContentPattern, 'g');
const matches = template.match(regexp) || [];
return matches.map(elem => {
const match = elem.match(contentRegexp);
return match ? match[0] : '';
});
}
/**
* Appends `dirname`, `filename` and `extension` to the provided `fields` map.
* @param entryPath
* @param fields
* @param folder - optionally include a folder that the dirname will be relative to.
* eg: `addFileTemplateFields('foo/bar/baz.ext', fields, 'foo')`
* will result in: `{ dirname: 'bar', filename: 'baz', extension: 'ext' }`
*/
function addFileTemplateFields(entryPath, fields, folder = '') {
if (!entryPath) {
return fields;
}
const extension = (0, _path.extname)(entryPath);
const filename = (0, _path.basename)(entryPath, extension);
const dirnameExcludingFolder = (0, _path.dirname)(entryPath).replace(new RegExp(`^(/?)${folder}/?`), '$1');
fields = fields.withMutations(map => {
map.set('dirname', dirnameExcludingFolder);
map.set('filename', filename);
map.set('extension', extension === '' ? extension : extension.slice(1));
});
return fields;
}

View File

@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.validateMinMax = validateMinMax;
var _isNumber2 = _interopRequireDefault(require("lodash/isNumber"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function validateMinMax(t, fieldLabel, value, min, max) {
function minMaxError(messageKey) {
return {
type: 'RANGE',
message: t(`editor.editorControlPane.widget.${messageKey}`, {
fieldLabel,
minCount: min,
maxCount: max,
count: min
})
};
}
if ([min, max, value === null || value === void 0 ? void 0 : value.size].every(_isNumber2.default) && (value.size < min || value.size > max)) {
return minMaxError(min === max ? 'rangeCountExact' : 'rangeCount');
} else if ((0, _isNumber2.default)(min) && min > 0 && value !== null && value !== void 0 && value.size && value.size < min) {
return minMaxError('rangeMin');
} else if ((0, _isNumber2.default)(max) && value !== null && value !== void 0 && value.size && value.size > max) {
return minMaxError('rangeMax');
}
}

27
node_modules/decap-cms-lib-widgets/package.json generated vendored Normal file
View File

@@ -0,0 +1,27 @@
{
"name": "decap-cms-lib-widgets",
"description": "Shared utilities for Decap CMS.",
"version": "3.0.2",
"repository": "https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-widgets",
"bugs": "https://github.com/decaporg/decap-cms/issues",
"module": "dist/esm/index.js",
"main": "dist/decap-cms-lib-widgets.js",
"license": "MIT",
"keywords": [
"decap-cms"
],
"sideEffects": false,
"scripts": {
"develop": "npm run build:esm -- --watch",
"build": "cross-env NODE_ENV=production webpack",
"build:esm": "cross-env NODE_ENV=esm babel src --out-dir dist/esm --ignore \"**/__tests__\" --root-mode upward --extensions \".js,.jsx,.ts,.tsx\""
},
"dependencies": {
"dayjs": "^1.11.10"
},
"peerDependencies": {
"immutable": "^3.7.6",
"lodash": "^4.17.11"
},
"gitHead": "875f4cafa9a82283d28fc5d7871a34550b2a3870"
}

View File

@@ -0,0 +1,241 @@
import { fromJS } from 'immutable';
import {
compileStringTemplate,
expandPath,
extractTemplateVars,
keyToPathArray,
parseDateFromEntry,
} from '../stringTemplate';
describe('stringTemplate', () => {
describe('keyToPathArray', () => {
it('should return array of length 1 with simple path', () => {
expect(keyToPathArray('category')).toEqual(['category']);
});
it('should return path array for complex path', () => {
expect(keyToPathArray('categories[0].title.subtitles[0].welcome[2]')).toEqual([
'categories',
'0',
'title',
'subtitles',
'0',
'welcome',
'2',
]);
});
});
describe('parseDateFromEntry', () => {
it('should return date based on dateFieldName', () => {
const date = new Date().toISOString();
const dateFieldName = 'dateFieldName';
const entry = fromJS({ data: { dateFieldName: date } });
expect(parseDateFromEntry(entry, dateFieldName).toISOString()).toBe(date);
});
it('should return undefined on empty dateFieldName', () => {
const entry = fromJS({ data: {} });
expect(parseDateFromEntry(entry, '')).toBeUndefined();
expect(parseDateFromEntry(entry, null)).toBeUndefined();
expect(parseDateFromEntry(entry, undefined)).toBeUndefined();
});
it('should return undefined on invalid date', () => {
const entry = fromJS({ data: { date: '' } });
const dateFieldName = 'date';
expect(parseDateFromEntry(entry, dateFieldName)).toBeUndefined();
});
});
describe('extractTemplateVars', () => {
it('should extract template variables', () => {
expect(extractTemplateVars('{{slug}}-hello-{{date}}-world-{{fields.id}}')).toEqual([
'slug',
'date',
'fields.id',
]);
});
it('should return empty array on no matches', () => {
expect(extractTemplateVars('hello-world')).toEqual([]);
});
});
describe('compileStringTemplate', () => {
const date = new Date('2020-01-02T13:28:27.679Z');
it('should compile year variable', () => {
expect(compileStringTemplate('{{year}}', date)).toBe('2020');
});
it('should compile month variable', () => {
expect(compileStringTemplate('{{month}}', date)).toBe('01');
});
it('should compile day variable', () => {
expect(compileStringTemplate('{{day}}', date)).toBe('02');
});
it('should compile hour variable', () => {
expect(compileStringTemplate('{{hour}}', date)).toBe('13');
});
it('should compile minute variable', () => {
expect(compileStringTemplate('{{minute}}', date)).toBe('28');
});
it('should compile second variable', () => {
expect(compileStringTemplate('{{second}}', date)).toBe('27');
});
it('should error on missing date', () => {
expect(() => compileStringTemplate('{{year}}')).toThrowError();
});
it('return compiled template', () => {
expect(
compileStringTemplate(
'{{slug}}-{{year}}-{{fields.slug}}-{{title}}-{{date}}',
date,
'backendSlug',
fromJS({ slug: 'entrySlug', title: 'title', date }),
),
).toBe('backendSlug-2020-entrySlug-title-' + date.toString());
});
it('return apply processor to values', () => {
expect(
compileStringTemplate('{{slug}}', date, 'slug', fromJS({}), value => value.toUpperCase()),
).toBe('SLUG');
});
it('return apply filter to values', () => {
expect(
compileStringTemplate(
'{{slug | upper}}-{{title | lower}}-{{year}}',
date,
'backendSlug',
fromJS({ slug: 'entrySlug', title: 'Title', date }),
),
).toBe('BACKENDSLUG-title-2020');
});
it('return apply filter to date field', () => {
expect(
compileStringTemplate(
"{{slug | upper}}-{{title | lower}}-{{published | date('MM-DD')}}-{{year}}",
date,
'backendSlug',
fromJS({ slug: 'entrySlug', title: 'Title', published: date, date }),
),
).toBe('BACKENDSLUG-title-01-02-2020');
});
it('return apply filter for default value', () => {
expect(
compileStringTemplate(
"{{slug | upper}}-{{title | default('none')}}-{{subtitle | default('none')}}",
date,
'backendSlug',
fromJS({ slug: 'entrySlug', title: 'title', subtitle: null, published: date, date }),
),
).toBe('BACKENDSLUG-title-none');
});
it('return apply filter for ternary', () => {
expect(
compileStringTemplate(
"{{slug | upper}}-{{starred | ternary('star','nostar')}}-{{done | ternary('done', 'open')}}",
date,
'backendSlug',
fromJS({ slug: 'entrySlug', starred: true, done: false }),
),
).toBe('BACKENDSLUG-star-open');
});
it('return apply filter for truncate', () => {
expect(
compileStringTemplate(
'{{slug | truncate(6)}}',
date,
'backendSlug',
fromJS({ slug: 'entrySlug', starred: true, done: false }),
),
).toBe('backen...');
});
it('return apply filter for truncate', () => {
expect(
compileStringTemplate(
"{{slug | truncate(3,'***')}}",
date,
'backendSlug',
fromJS({ slug: 'entrySlug', starred: true, done: false }),
),
).toBe('bac***');
});
});
describe('expandPath', () => {
it('should expand wildcard paths', () => {
const data = {
categories: [
{
name: 'category 1',
},
{
name: 'category 2',
},
],
};
expect(expandPath({ data, path: 'categories.*.name' })).toEqual([
'categories.0.name',
'categories.1.name',
]);
});
it('should handle wildcard at the end of the path', () => {
const data = {
nested: {
otherNested: {
list: [
{
title: 'title 1',
nestedList: [{ description: 'description 1' }, { description: 'description 2' }],
},
{
title: 'title 2',
nestedList: [{ description: 'description 2' }, { description: 'description 2' }],
},
],
},
},
};
expect(expandPath({ data, path: 'nested.otherNested.list.*.nestedList.*' })).toEqual([
'nested.otherNested.list.0.nestedList.0',
'nested.otherNested.list.0.nestedList.1',
'nested.otherNested.list.1.nestedList.0',
'nested.otherNested.list.1.nestedList.1',
]);
});
it('should handle non wildcard index', () => {
const data = {
categories: [
{
name: 'category 1',
},
{
name: 'category 2',
},
],
};
const path = 'categories.0.name';
expect(expandPath({ data, path })).toEqual(['categories.0.name']);
});
});
});

8
node_modules/decap-cms-lib-widgets/src/index.ts generated vendored Normal file
View File

@@ -0,0 +1,8 @@
import * as stringTemplate from './stringTemplate';
import * as validations from './validations';
export const DecapCmsLibWidgets = {
stringTemplate,
validations,
};
export { stringTemplate, validations };

View File

@@ -0,0 +1,248 @@
import { Map } from 'immutable';
import { get, trimEnd, truncate } from 'lodash';
import dayjs from 'dayjs';
import { basename, dirname, extname } from 'path';
const filters = [
{ pattern: /^upper$/, transform: (str: string) => str.toUpperCase() },
{
pattern: /^lower$/,
transform: (str: string) => str.toLowerCase(),
},
{
pattern: /^date\('(.+)'\)$/,
transform: (str: string, match: RegExpMatchArray) => dayjs(str).format(match[1]),
},
{
pattern: /^default\('(.+)'\)$/,
transform: (str: string, match: RegExpMatchArray) => (str ? str : match[1]),
},
{
pattern: /^ternary\('(.*)',\s*'(.*)'\)$/,
transform: (str: string, match: RegExpMatchArray) => (str ? match[1] : match[2]),
},
{
pattern: /^truncate\(([0-9]+)(?:(?:,\s*['"])([^'"]*)(?:['"]))?\)$/,
transform: (str: string, match: RegExpMatchArray) => {
const omission = match[2] || '...';
const length = parseInt(match[1]) + omission.length;
return truncate(str, {
length,
omission,
});
},
},
];
const FIELD_PREFIX = 'fields.';
const templateContentPattern = '([^}{|]+)';
const filterPattern = '( \\| ([^}{]+))?';
const templateVariablePattern = `{{${templateContentPattern}${filterPattern}}}`;
// prepends a Zero if the date has only 1 digit
function formatDate(date: number) {
return `0${date}`.slice(-2);
}
export const dateParsers: Record<string, (date: Date) => string> = {
year: (date: Date) => `${date.getUTCFullYear()}`,
month: (date: Date) => formatDate(date.getUTCMonth() + 1),
day: (date: Date) => formatDate(date.getUTCDate()),
hour: (date: Date) => formatDate(date.getUTCHours()),
minute: (date: Date) => formatDate(date.getUTCMinutes()),
second: (date: Date) => formatDate(date.getUTCSeconds()),
};
export function parseDateFromEntry(entry: Map<string, unknown>, dateFieldName?: string | null) {
if (!dateFieldName) {
return;
}
const dateValue = entry.getIn(['data', dateFieldName]);
const dateDayjs = dateValue && dayjs(dateValue);
if (dateDayjs && dateDayjs.isValid()) {
return dateDayjs.toDate();
}
}
export const SLUG_MISSING_REQUIRED_DATE = 'SLUG_MISSING_REQUIRED_DATE';
export function keyToPathArray(key?: string) {
if (!key) {
return [];
}
const parts = [];
const separator = '';
const chars = key.split(separator);
let currentChar;
let currentStr = [];
while ((currentChar = chars.shift())) {
if (['[', ']', '.'].includes(currentChar)) {
if (currentStr.length > 0) {
parts.push(currentStr.join(separator));
}
currentStr = [];
} else {
currentStr.push(currentChar);
}
}
if (currentStr.length > 0) {
parts.push(currentStr.join(separator));
}
return parts;
}
export function expandPath({
data,
path,
paths = [],
}: {
data: Record<string, unknown>;
path: string;
paths?: string[];
}) {
if (path.endsWith('.*')) {
path = path + '.';
}
const sep = '.*.';
const parts = path.split(sep);
if (parts.length === 1) {
paths.push(path);
} else {
const partialPath = parts[0];
const value = get(data, partialPath);
if (Array.isArray(value)) {
value.forEach((_, index) => {
expandPath({
data,
path: trimEnd(`${partialPath}.${index}.${parts.slice(1).join(sep)}`, '.'),
paths,
});
});
}
}
return paths;
}
// Allow `fields.` prefix in placeholder to override built in replacements
// like "slug" and "year" with values from fields of the same name.
function getExplicitFieldReplacement(key: string, data: Map<string, unknown>) {
if (!key.startsWith(FIELD_PREFIX)) {
return;
}
const fieldName = key.slice(FIELD_PREFIX.length);
const value = data.getIn(keyToPathArray(fieldName));
if (typeof value === 'object' && value !== null) {
return JSON.stringify(value);
}
return value;
}
function getFilterFunction(filterStr: string) {
if (filterStr) {
let match: RegExpMatchArray | null = null;
const filter = filters.find(filter => {
match = filterStr.match(filter.pattern);
return !!match;
});
if (filter) {
return (str: string) => filter.transform(str, match as RegExpMatchArray);
}
}
return null;
}
export function compileStringTemplate(
template: string,
date: Date | undefined | null,
identifier = '',
data = Map<string, unknown>(),
processor?: (value: string) => string,
) {
let missingRequiredDate;
// Turn off date processing (support for replacements like `{{year}}`), by passing in
// `null` as the date arg.
const useDate = date !== null;
const compiledString = template.replace(
RegExp(templateVariablePattern, 'g'),
(_full, key: string, _part, filter: string) => {
let replacement;
const explicitFieldReplacement = getExplicitFieldReplacement(key, data);
if (explicitFieldReplacement) {
replacement = explicitFieldReplacement;
} else if (dateParsers[key] && !date) {
missingRequiredDate = true;
return '';
} else if (dateParsers[key]) {
replacement = dateParsers[key](date as Date);
} else if (key === 'slug') {
replacement = identifier;
} else {
replacement = data.getIn(keyToPathArray(key), '') as string;
}
if (processor) {
return processor(replacement);
} else {
const filterFunction = getFilterFunction(filter);
if (filterFunction) {
replacement = filterFunction(replacement);
}
}
return replacement;
},
);
if (useDate && missingRequiredDate) {
const err = new Error();
err.name = SLUG_MISSING_REQUIRED_DATE;
throw err;
} else {
return compiledString;
}
}
export function extractTemplateVars(template: string) {
const regexp = RegExp(templateVariablePattern, 'g');
const contentRegexp = RegExp(templateContentPattern, 'g');
const matches = template.match(regexp) || [];
return matches.map(elem => {
const match = elem.match(contentRegexp);
return match ? match[0] : '';
});
}
/**
* Appends `dirname`, `filename` and `extension` to the provided `fields` map.
* @param entryPath
* @param fields
* @param folder - optionally include a folder that the dirname will be relative to.
* eg: `addFileTemplateFields('foo/bar/baz.ext', fields, 'foo')`
* will result in: `{ dirname: 'bar', filename: 'baz', extension: 'ext' }`
*/
export function addFileTemplateFields(entryPath: string, fields: Map<string, string>, folder = '') {
if (!entryPath) {
return fields;
}
const extension = extname(entryPath);
const filename = basename(entryPath, extension);
const dirnameExcludingFolder = dirname(entryPath).replace(new RegExp(`^(/?)${folder}/?`), '$1');
fields = fields.withMutations(map => {
map.set('dirname', dirnameExcludingFolder);
map.set('filename', filename);
map.set('extension', extension === '' ? extension : extension.slice(1));
});
return fields;
}

31
node_modules/decap-cms-lib-widgets/src/validations.ts generated vendored Normal file
View File

@@ -0,0 +1,31 @@
import { isNumber } from 'lodash';
import type { List } from 'immutable';
export function validateMinMax(
t: (key: string, options: unknown) => string,
fieldLabel: string,
value?: List<unknown>,
min?: number,
max?: number,
) {
function minMaxError(messageKey: string) {
return {
type: 'RANGE',
message: t(`editor.editorControlPane.widget.${messageKey}`, {
fieldLabel,
minCount: min,
maxCount: max,
count: min,
}),
};
}
if ([min, max, value?.size].every(isNumber) && (value!.size < min! || value!.size > max!)) {
return minMaxError(min === max ? 'rangeCountExact' : 'rangeCount');
} else if (isNumber(min) && min > 0 && value?.size && value.size < min) {
return minMaxError('rangeMin');
} else if (isNumber(max) && value?.size && value.size > max) {
return minMaxError('rangeMax');
}
}

3
node_modules/decap-cms-lib-widgets/webpack.config.js generated vendored Normal file
View File

@@ -0,0 +1,3 @@
const { getConfig } = require('../../scripts/webpack.js');
module.exports = getConfig();