复制安装命令
用 Codex 或 Claude 安装复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它先审查 Skill 页面再帮你安装。
复制前请先查看来源、License 和安全提示。
This is the open-source content repository behind
用 Codex 或 Claude 安装复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它先审查 Skill 页面再帮你安装。
复制前请先查看来源、License 和安全提示。
来源文件:README.md
This is the open-source content repository behind Skill Store. It stores every approved Agent Skill, the records that go with it, and the automated security audits published with each skill.
This repo is a companion to the Skill Store platform, not the place to submit skills. Skills are added through skillstore.io — its review pipeline writes to this repo automatically. Please do not open a pull request here to add a skill; PRs adding skills will be closed. See Contributing a skill below.
The recommended way to install any skill is the skillstore CLI — one command works for both Claude Code and Codex:
npx skillstore add author/skill-name
For example:
npx skillstore add aiskillstore/code-review
It downloads the skill and drops it into the right skills/ directory for your tool. Claude Code auto-discovers it; for Codex, restart the session.
Prefer to do it by hand, or installing via Claude Web? See the full Installation Guides for every method (CLI, manual, and ZIP upload) and the scope directories (~/.agents/skills/, .claude/skills/, ~/.claude/skills/, .codex/skills/, …).
Submit through the platform — not through a pull request:
SKILL.md.SKILL.md — the skill definition (required, per the Agent Skills spec)LICENSE (recommended)Every submission is scanned automatically before it can be published. The audit flags things like:
eval, exec, raw system commands)Security analysis is report-only: findings inform maintainers and users, but a risk result does not automatically block an otherwise approved skill from being published. See our Security Trust Center for the methodology, limitations, and risk-level definitions.
Live Security Passport example:
.
├── skills/ # Approved, published skills (one folder each, with SKILL.md)
├── pending/ # Submissions awaiting review
├── packages/
│ ├── cli/ # The `skillstore` CLI (npx skillstore add …)
│ └── skillstore/
├── schemas/ # JSON schemas for skill records
├── scripts/ # Maintenance & scoring scripts
└── .github/workflows/ # Submission, audit, and sync automation
The contents of this repo are maintained by Skill Store's automated pipeline. Manual changes are limited to maintainers.
The marketplace catalog is MIT-licensed. Individual skills carry their own licenses — check each skill's LICENSE file.
name: delon-util
description: '@delon/util skill - Utility functions library for array, string, date, number manipulation. For ng-events construction site progress tracking system.'Trigger patterns: "utility", "helper", "@delon/util", "format", "deepCopy", "deepMerge"
@delon/util provides a comprehensive collection of utility functions for common data manipulation tasks in ng-alain applications.
Package: @delon/util@20.1.0
array/)import { deepCopy } from '@delon/util/array';
const original = { name: '任務', items: [1, 2, 3], meta: { id: 1 } };
const copy = deepCopy(original);
// Changes to copy won't affect original
copy.items.push(4);
console.log(original.items); // [1, 2, 3]
console.log(copy.items); // [1, 2, 3, 4]
Use Cases:
import { deepMerge } from '@delon/util/array';
const defaults = {
config: { theme: 'light', size: 'default' },
features: ['dashboard']
};
const custom = {
config: { theme: 'dark' },
features: ['reports']
};
const merged = deepMerge(defaults, custom);
// Result: {
// config: { theme: 'dark', size: 'default' },
// features: ['dashboard', 'reports']
// }
import {
groupBy, // Group array by property
uniq, // Remove duplicates
uniqBy, // Remove duplicates by property
orderBy // Sort array by properties
} from '@delon/util/array';
// Group tasks by status
const grouped = groupBy(tasks, 'status');
// { pending: [...], completed: [...] }
// Remove duplicate IDs
const uniqueIds = uniq([1, 2, 2, 3]); // [1, 2, 3]
// Remove duplicate tasks by ID
const uniqueTasks = uniqBy(tasks, 'id');
// Sort tasks
const sorted = orderBy(tasks, ['priority', 'createdAt'], ['asc', 'desc']);
string/)import { format } from '@delon/util/string';
// Template interpolation
const message = format('任務 {0} 已指派給 {1}', taskName, userName);
// Named parameters
const message2 = format('任務 {name} 的狀態為 {status}', {
name: '地基施工',
status: '進行中'
});
import {
toCamelCase, // Convert to camelCase
toPascalCase, // Convert to PascalCase
toKebabCase, // Convert to kebab-case
toSnakeCase, // Convert to snake_case
truncate // Truncate with ellipsis
} from '@delon/util/string';
toCamelCase('task-name'); // 'taskName'
toPascalCase('task-name'); // 'TaskName'
toKebabCase('TaskName'); // 'task-name'
toSnakeCase('TaskName'); // 'task_name'
truncate('Long text...', 10); // 'Long te...'
date/)import { getTimeDistance } from '@delon/util/date';
// Get today's date range
const today = getTimeDistance('today');
// [Date(2024-12-25 00:00:00), Date(2024-12-25 23:59:59)]
// Get this week's date range
const week = getTimeDistance('week');
// Get this month's date range
const month = getTimeDistance('month');
// Get this year's date range
const year = getTimeDistance('year');
// Custom range with offset
const lastWeek = getTimeDistance('week', -1);
Supported Types:
'today' - Current day'week' - Current week (Sunday to Saturday)'month' - Current month'year' - Current yearimport { formatDistanceToNow } from '@delon/util/date';
const createdAt = new Date('2024-12-20');
const relative = formatDistanceToNow(createdAt);
// "5 days ago"
const futureDate = new Date('2024-12-30');
const future = formatDistanceToNow(futureDate);
// "in 5 days"
number/)import { currency } from '@delon/util/number';
// Format as currency
currency(1234567.89); // "$1,234,567.89"
currency(1234567.89, { unit: '¥' }); // "¥1,234,567.89"
currency(1234.5, { precision: 0 }); // "$1,235"
import {
toFixed, // Round to fixed decimals
toPercent, // Convert to percentage
toThousands // Add thousands separators
} from '@delon/util/number';
toFixed(1.2345, 2); // "1.23"
toPercent(0.1234); // "12.34%"
toPercent(0.1234, 1); // "12.3%"
toThousands(1234567); // "1,234,567"
browser/)import { copy } from '@delon/util/browser';
async copyTaskLink(taskId: string) {
const link = `${window.location.origin}/tasks/${taskId}`;
const success = await copy(link);
if (success) {
this.messageService.success('連結已複製');
} else {
this.messageService.error('複製失敗');
}
}
import {
scrollToTop, // Smooth scroll to top
deepGet, // Get nested object property
deepSet, // Set nested object property
isEmpty, // Check if value is empty
isEqual, // Deep equality check
updateHostClass // Update host element classes
} from '@delon/util/browser';
scrollToTop();
scrollToTop({ duration: 500 });
const value = deepGet(obj, 'user.profile.name');
deepSet(obj, 'user.profile.name', 'New Name');
isEmpty(null); // true
isEmpty(''); // true
isEmpty([]); // true
isEmpty({}); // true
isEqual({ a: 1 }, { a: 1 }); // true
import { Component, signal, computed, inject } from '@angular/core';
import { deepCopy, groupBy, orderBy } from '@delon/util/array';
import { format } from '@delon/util/string';
import { getTimeDistance } from '@delon/util/date';
import { copy } from '@delon/util/browser';
import { NzMessageService } from 'ng-zorro-antd/message';
@Component({
selector: 'app-task-list',
standalone: true,
template: `
<nz-card>
<div nz-row [nzGutter]="16">
@for (group of groupedTasks() | keyvalue; track group.key) {
<div nz-col [nzSpan]="8">
<h3>{{ group.key }} ({{ group.value.length }})</h3>
@for (task of group.value; track task.id) {
<nz-card>
<h4>{{ task.title }}</h4>
<p>{{ formatTaskInfo(task) }}</p>
<button nz-button (click)="copyTaskLink(task.id)">
複製連結
</button>
</nz-card>
}
</div>
}
</div>
</nz-card>
`
})
export class TaskListComponent {
private messageService = inject(NzMessageService);
// Original tasks from service
tasks = signal<Task[]>([]);
// Group tasks by status using @delon/util
groupedTasks = computed(() =>
groupBy(this.sortedTasks(), 'status')
);
// Sort tasks by priority and date
sortedTasks = computed(() =>
orderBy(
this.tasks(),
['priority', 'createdAt'],
['asc', 'desc']
)
);
// Format task information
formatTaskInfo(task: Task): string {
return format(
'優先級: {priority}, 建立於 {date}',
{
priority: task.priority,
date: this.formatDate(task.createdAt)
}
);
}
// Copy task link to clipboard
async copyTaskLink(taskId: string): Promise<void> {
const link = `${window.location.origin}/tasks/${taskId}`;
const success = await copy(link);
if (success) {
this.messageService.success('任務連結已複製');
} else {
this.messageService.error('複製失敗,請手動複製');
}
}
// Clone task for editing
cloneTaskForEdit(task: Task): Task {
return deepCopy(task);
}
// Get this week's tasks
getThisWeekTasks(): Task[] {
const [start, end] = getTimeDistance('week');
return this.tasks().filter(t =>
t.createdAt >= start && t.createdAt <= end
);
}
private formatDate(date: Date): string {
return format(
'{year}-{month}-{day}',
{
year: date.getFullYear(),
month: String(date.getMonth() + 1).padStart(2, '0'),
day: String(date.getDate()).padStart(2, '0')
}
);
}
}
import { Component, signal } from '@angular/core';
import { deepCopy, deepMerge } from '@delon/util/array';
import { isEmpty } from '@delon/util/browser';
@Component({
selector: 'app-task-form',
standalone: true,
template: `
<form nz-form (ngSubmit)="handleSubmit()">
<!-- form fields -->
<button nz-button [disabled]="hasEmptyRequired()">
提交
</button>
</form>
`
})
export class TaskFormComponent {
// Default form values
private defaults = {
priority: 'medium',
status: 'pending',
assignee: null,
tags: []
};
// Form data with defaults
formData = signal(deepCopy(this.defaults));
// Original task (for editing)
originalTask = signal<Task | null>(null);
// Load task for editing
loadTask(task: Task): void {
// Merge task data with defaults
const merged = deepMerge(this.defaults, task);
this.formData.set(merged);
this.originalTask.set(deepCopy(task));
}
// Check if required fields are empty
hasEmptyRequired(): boolean {
const data = this.formData();
return isEmpty(data.title) || isEmpty(data.assignee);
}
// Check if form has changes
hasChanges(): boolean {
const original = this.originalTask();
if (!original) return true;
return !isEqual(original, this.formData());
}
handleSubmit(): void {
if (!this.hasEmptyRequired()) {
// Create clean copy for submission
const submitData = deepCopy(this.formData());
// Submit...
}
}
}
✅ DO:
const taskCopy = deepCopy(task);
taskCopy.status = 'completed';
this.tasks.update(tasks => [...tasks, taskCopy]);
❌ DON'T:
task.status = 'completed';
this.tasks.update(tasks => [...tasks, task]); // Mutates original
✅ DO:
groupedTasks = computed(() => groupBy(this.tasks(), 'status'));
sortedTasks = computed(() => orderBy(this.tasks(), ['priority'], ['asc']));
✅ DO:
import { deepCopy } from '@delon/util/array';
const copy: Task = deepCopy<Task>(originalTask);
Version: 1.0
Created: 2025-12-25
Maintainer: ng-events(GigHub) Development Team
评论 (0)
暂无评论,成为第一个评论者吧!