Codync
免费开源的 1:1 Grok Bot 与 Muse 替代方案。可在 iPhone、Mac 或 Linux 桌面上将 Claude 代码、Codex、Cursor 以及 40 多个编码代理作为持久机器人使用。支持群组聊天、线程、应用。
AI 翻译
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Simplify your data management with effortless ease. Experience the power of simplicity, allowing you to organize, analyze, and visualize your data with intuitive features and a clean interface.
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗A minimalistic, zero-dependency JavaScript/TypeScript library for creating reactive data tables with built-in sorting, searching, and pagination.
table.data (push, splice, sort, ...) and the table updates automaticallynpm install ezytables
Or use via CDN:
<script type="module" src="https://esm.sh/ezytables"></script>
import { EzyTables } from "ezytables";
const data = [
{ name: "Alice", email: "[email protected]", role: "Admin" },
{ name: "Bob", email: "[email protected]", role: "User" },
{ name: "Charlie", email: "[email protected]", role: "Moderator" },
];
const table = new EzyTables({
data,
clientEnabled: true,
client: { perPage: 10 },
renderFunction: pageData => {
const tbody = document.querySelector("#myTable tbody");
tbody.innerHTML = "";
pageData.forEach(item => {
const row = document.createElement("tr");
row.innerHTML = `
<td>${item.name}</td>
<td>${item.email}</td>
<td>${item.role}</td>
`;
tbody.appendChild(row);
});
},
});
// Search
document.querySelector("#search").addEventListener("input", e => {
table.setSearchDebounced(e.target.value);
});
// Pagination
document
.querySelector("#prev")
.addEventListener("click", () => table.prevPage());
document
.querySelector("#next")
.addEventListener("click", () => table.nextPage());
Point EzyTables at an existing HTML table and it handles everything:
import { EzyTables } from "ezytables";
const table = new EzyTables({
target: "#myTable",
data: myData,
classes: {
container: "shadow rounded-lg p-4",
table: {
container: "min-w-full",
thead: { th: "px-3 py-3 text-left text-sm font-semibold" },
tbody: { td: "px-3 py-4 text-sm" },
},
},
});
| Method | Returns | Description |
|---|---|---|
new EzyTables(options) | EasyTables | Create a new table instance |
setSearchDebounced(query) | void | Search with 300ms debounce |
sortData(field, order?) | void | Sort by field ("asc" or "desc") |
nextPage() | void | Go to next page |
prevPage() | void | Go to previous page |
goToPage(page) | void | Jump to a specific page |
getCurrentPage() | number | Get current page number |
getTotalPages() | number | Get total page count |
getShowingInfo() | string | Get display info (e.g., "Showing 1 to 10 of 50 items") |
setPerPage(n) | void | Change items per page |
registerPlugin(plugin) | void | Register a data transform plugin |
setData(data) | void | Replace the data source |
getRawData() | any[] | Get a copy of the raw data |
data (property) | any[] | The live, reactive data array (see below) |
destroy() | void | Clean up and remove the table |
table.data is the live data array. Changing it re-renders the table and
calls onDataChange. Several changes made together trigger a single
re-render:
table.data.push({ name: "Dana", email: "[email protected]" });
table.data.splice(0, 1); // remove the first row
table.data.sort((a, b) => a.name.localeCompare(b.name));
table.data[0] = { ...table.data[0], name: "Alicia" }; // replace a row
Only changes to the array itself are observed. The array you passed in as
data is not watched, and editing a property of a row object
(table.data[0].name = "x") does not trigger an update, so replace the row
instead. In server mode the data is replaced on every fetch, so use the
server API to change it.
Transform cell data before rendering:
const datePlugin = {
name: "dateFormat",
field: "date",
transform: value => {
return new Date(value).toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
});
},
};
const table = new EzyTables({
data: myData,
plugins: [datePlugin],
target: "#myTable",
sanitize: true, // default: sanitize plugin HTML before inserting it
});
[!WARNING] Plugin
transform()results are inserted into the cell as HTML, not text. EzyTables sanitizes plugin output by default before assigning it toinnerHTML. Setsanitize: falseonly when the returned HTML is fully trusted.
The built-in sanitizer:
<script>, <iframe>, <object>, <embed>, <link>, <meta>,
<style> and <base>, plus SVG animation elements (<animate>, <set>,
<animateMotion>, <animateTransform>)on*), style and srcdoc attributeshttp:, https:, mailto: and tel: URLs in
href, src, xlink:href, action and formaction, and removes any other
scheme (such as javascript: or data:) and protocol-relative // URLsBecause inline style attributes are removed, plugins that style their output
should use classes instead (or set sanitize: false for trusted HTML).
Column labels passed in through the columns option are rendered as plain
text, so they are safe to build from user or API data. When EzyTables reads
the columns from an existing table's <th> elements, those labels keep their
HTML, since that markup is already part of your page.
interface EasyTablesOptions {
clientEnabled?: boolean; // Use client-side data (default: true, or false when server.api_url is set)
data?: any[]; // Data source array
target?: string; // CSS selector for existing table
renderFunction?: (data) => void; // Custom render callback
client?: {
limit: number;
perPage?: number; // Items per page (default: 10)
};
server?: {
api_url: string;
headers?: Record<string, string>;
limit: number;
page: number;
dataNames: string; // Dot-separated path to the rows in the response (e.g. "data.items")
};
columns?: Column[];
classes?: Classes; // CSS class overrides
plugins?: Plugin[]; // Data transform plugins
hideDetails?: {
header?: boolean; // Hide search/per-page controls
footer?: boolean; // Hide pagination footer
};
perPageOptions?: number[]; // Custom per-page dropdown options (default: [5, 10, 25, 50, 100])
onPageChange?: (page: number, totalPages: number) => void;
onSearch?: (query: string, resultCount: number) => void;
onSort?: (field: string, order: "asc" | "desc") => void;
onDataChange?: (newData: any[]) => void;
sanitize?: boolean; // Sanitize plugin transform HTML before assigning innerHTML (default: true)
}
# Install dependencies
npm install
# Start dev server
npm run dev
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Build for production
npm run build
See CONTRIBUTING.md for guidelines.