gpreview
Version:
Preview Ghost themes locally without a full Ghost installation
242 lines • 10.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getHelper = getHelper;
function parseFilterString(filterStr) {
const filters = [];
const filterParts = [];
let current = '';
let inBrackets = false;
for (let i = 0; i < filterStr.length; i++) {
const char = filterStr[i];
if (char === '[') {
inBrackets = true;
current += char;
}
else if (char === ']') {
inBrackets = false;
current += char;
}
else if ((char === '+' || char === ',') && !inBrackets) {
if (current.trim()) {
filterParts.push(current.trim());
}
current = '';
}
else {
current += char;
}
}
if (current.trim()) {
filterParts.push(current.trim());
}
for (const part of filterParts) {
const match = part.match(/^([a-z_]+):(.+)$/);
if (match) {
const [, type, value] = match;
if (value.startsWith('-')) {
filters.push({
type: type,
operator: 'not',
value: value.substring(1)
});
}
else if (value.startsWith('[') && value.endsWith(']')) {
filters.push({
type: type,
operator: 'in',
value: value.slice(1, -1)
});
}
else {
filters.push({
type: type,
operator: 'equals',
value: value
});
}
}
}
return filters;
}
function parseGetHelperParams(args, options) {
const params = {};
if (options.hash && Object.keys(options.hash).length > 0) {
Object.assign(params, options.hash);
}
else {
for (let i = 1; i < args.length; i++) {
const arg = args[i];
if (i === args.length - 1)
break;
if (arg === 'as' || (typeof arg === 'string' && arg.startsWith('|'))) {
break;
}
if (typeof arg === 'string' && arg.includes('=')) {
const equalIndex = arg.indexOf('=');
const key = arg.substring(0, equalIndex);
const value = arg.substring(equalIndex + 1).replace(/^["']|["']$/g, '');
params[key] = value;
}
}
}
return params;
}
function getHelper(resource, ...args) {
const options = args[args.length - 1];
try {
if (!resource || typeof resource !== 'string') {
console.error('Get helper requires a resource parameter');
return options.inverse ? options.inverse(this) : '';
}
const params = parseGetHelperParams([resource, ...args], options);
let result = [];
const rootData = options.data?.root || this;
switch (resource) {
case 'posts':
result = (rootData.posts || this.posts || []);
if (!Array.isArray(result)) {
throw new Error('Posts data is not an array');
}
if (params.filter) {
const parsedFilters = parseFilterString(params.filter);
for (const filter of parsedFilters) {
switch (filter.type) {
case 'featured':
if (filter.operator === 'equals') {
result = result.filter((item) => {
const post = item;
return filter.value === 'true' ? post.featured : !post.featured;
});
}
else if (filter.operator === 'not') {
result = result.filter((item) => {
const post = item;
return filter.value === 'true' ? !post.featured : post.featured;
});
}
break;
case 'tag':
if (filter.operator === 'equals') {
result = result.filter((item) => {
const post = item;
return post.tags && post.tags.some((tag) => tag.slug === filter.value);
});
}
else if (filter.operator === 'not') {
result = result.filter((item) => {
const post = item;
return !post.tags || !post.tags.some((tag) => tag.slug === filter.value);
});
}
break;
case 'tags':
if (filter.operator === 'in') {
const tagSlugs = filter.value.split(',').map(s => s.trim());
result = result.filter((item) => {
const post = item;
return post.tags && post.tags.some((tag) => tagSlugs.includes(tag.slug));
});
}
break;
case 'author':
if (filter.operator === 'equals') {
result = result.filter((item) => {
const post = item;
return post.primary_author && post.primary_author.slug === filter.value;
});
}
else if (filter.operator === 'not') {
result = result.filter((item) => {
const post = item;
return !post.primary_author || post.primary_author.slug !== filter.value;
});
}
break;
case 'id':
if (filter.operator === 'not') {
result = result.filter((item) => item.id !== filter.value);
}
else if (filter.operator === 'equals') {
result = result.filter((item) => item.id === filter.value);
}
break;
case 'page':
if (filter.operator === 'equals') {
result = result.filter((item) => {
const post = item;
return filter.value === 'true'
? 'page' in post && post.page === true
: !('page' in post) || post.page !== true;
});
}
break;
}
}
}
if (params.order) {
const [field, direction] = params.order.split(' ');
result = [...result].sort((a, b) => {
const aVal = a[field] ?? '';
const bVal = b[field] ?? '';
if (typeof aVal === 'string' && typeof bVal === 'string') {
return direction === 'desc'
? bVal.localeCompare(aVal)
: aVal.localeCompare(bVal);
}
if (field.includes('_at') || field === 'date') {
const aDate = new Date(aVal).getTime();
const bDate = new Date(bVal).getTime();
return direction === 'desc' ? bDate - aDate : aDate - bDate;
}
if (direction === 'desc') {
return aVal > bVal ? -1 : aVal < bVal ? 1 : 0;
}
else {
return aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
}
});
}
if (params.limit) {
const limit = parseInt(params.limit, 10);
if (isNaN(limit) || limit < 0) {
console.warn(`Invalid limit value: ${params.limit}, using default`);
result = result.slice(0, 15);
}
else {
result = result.slice(0, limit);
}
}
break;
case 'tags':
result = (rootData.tags || this.tags || []);
if (!Array.isArray(result)) {
throw new Error('Tags data is not an array');
}
break;
case 'authors':
result = (rootData.authors || this.authors || []);
if (!Array.isArray(result)) {
throw new Error('Authors data is not an array');
}
break;
default:
return options.inverse ? options.inverse(this) : '';
}
if (options.blockParams && typeof options.blockParams === 'number' && options.blockParams > 0) {
const data = {
blockParams: [result]
};
return options.fn ? options.fn(this, data) : '';
}
else {
const context = {};
context[resource] = result;
return options.fn ? options.fn(context) : '';
}
}
catch (error) {
console.error(`Error in get helper for resource "${resource}":`, error);
return options.inverse ? options.inverse(this) : '';
}
}
//# sourceMappingURL=get.js.map