@industry-theme/backlogmd-kanban-panel 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Backlog.md Config Parser
3
+ *
4
+ * This parser implementation is copied verbatim from the official Backlog.md project:
5
+ * Source: https://github.com/MrLesk/Backlog.md/blob/main/src/file-system/operations.ts
6
+ * License: MIT
7
+ *
8
+ * This is a temporary solution with precedent in this codebase. We hope the Backlog.md
9
+ * maintainers will eventually publish this as a separate npm package that can be imported.
10
+ *
11
+ * The official Backlog.md project uses a custom line-by-line parser instead of a YAML library,
12
+ * which handles their config format more reliably than standard YAML parsers.
13
+ */
14
+ import type { BacklogConfig } from './types';
15
+ /**
16
+ * Parse Backlog.md config.yml content using the official parser logic
17
+ * Copied from: https://github.com/MrLesk/Backlog.md/blob/main/src/file-system/operations.ts
18
+ */
19
+ export declare function parseBacklogConfig(content: string): BacklogConfig;
20
+ /**
21
+ * Serialize BacklogConfig back to config.yml format
22
+ * Copied from: https://github.com/MrLesk/Backlog.md/blob/main/src/file-system/operations.ts
23
+ */
24
+ export declare function serializeBacklogConfig(config: BacklogConfig): string;
25
+ //# sourceMappingURL=backlog-config-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backlog-config-parser.d.ts","sourceRoot":"","sources":["../../src/adapters/backlog-config-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAI7C;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CA2GjE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAcpE"}
@@ -5,11 +5,12 @@
5
5
  */
6
6
  import type { Task, BacklogConfig } from './types';
7
7
  /**
8
- * Parse YAML string using the yaml library
8
+ * Parse YAML string using the yaml library (for task frontmatter only)
9
9
  */
10
10
  export declare function parseYaml(yamlString: string): Record<string, unknown>;
11
11
  /**
12
12
  * Parse Backlog.md config.yml file
13
+ * Uses the official Backlog.md parser implementation
13
14
  */
14
15
  export declare function parseBacklogConfig(content: string): BacklogConfig;
15
16
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"backlog-parser.d.ts","sourceRoot":"","sources":["../../src/adapters/backlog-parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EACV,IAAI,EAEJ,aAAa,EAEd,MAAM,SAAS,CAAC;AAGjB;;GAEG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAErE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAgCjE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAwCrE;AAsGD;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAqB/C"}
1
+ {"version":3,"file":"backlog-parser.d.ts","sourceRoot":"","sources":["../../src/adapters/backlog-parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EACV,IAAI,EAEJ,aAAa,EAEd,MAAM,SAAS,CAAC;AAIjB;;GAEG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAErE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAkCjE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAwCrE;AAsGD;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAqB/C"}
@@ -7,4 +7,5 @@ export { BacklogAdapter, createBacklogAdapter } from './BacklogAdapter';
7
7
  export type { FileAccessFunctions, IBacklogAdapter, BacklogConfig, Task, TaskMetadata, AcceptanceCriterion, } from './types';
8
8
  export { BacklogAdapterError } from './types';
9
9
  export { parseYaml, parseBacklogConfig, parseTaskFile, sortTasks, } from './backlog-parser';
10
+ export { serializeBacklogConfig } from './backlog-config-parser';
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxE,YAAY,EACV,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,IAAI,EACJ,YAAY,EACZ,mBAAmB,GACpB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,aAAa,EACb,SAAS,GACV,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxE,YAAY,EACV,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,IAAI,EACJ,YAAY,EACZ,mBAAmB,GACpB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,aAAa,EACb,SAAS,GACV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"KanbanPanel.d.ts","sourceRoot":"","sources":["../../src/panels/KanbanPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAiHpD;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAMrD,CAAC"}
1
+ {"version":3,"file":"KanbanPanel.d.ts","sourceRoot":"","sources":["../../src/panels/KanbanPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAgHpD;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAMrD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"KanbanColumn.d.ts","sourceRoot":"","sources":["../../../../src/panels/kanban/components/KanbanColumn.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,UAAU,iBAAiB;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CACpC;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAmMpD,CAAC"}
1
+ {"version":3,"file":"KanbanColumn.d.ts","sourceRoot":"","sources":["../../../../src/panels/kanban/components/KanbanColumn.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,UAAU,iBAAiB;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CACpC;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAkMpD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useKanbanData.d.ts","sourceRoot":"","sources":["../../../../src/panels/kanban/hooks/useKanbanData.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEtE,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACnC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxE;AAED,UAAU,oBAAoB;IAC5B,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,mBAAmB,CAqNjF"}
1
+ {"version":3,"file":"useKanbanData.d.ts","sourceRoot":"","sources":["../../../../src/panels/kanban/hooks/useKanbanData.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEtE,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACnC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxE;AAED,UAAU,oBAAoB;IAC5B,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,mBAAmB,CA6NjF"}
@@ -6819,36 +6819,115 @@ const YAML = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty
6819
6819
  visit: visit$1,
6820
6820
  visitAsync
6821
6821
  }, Symbol.toStringTag, { value: "Module" }));
6822
+ const DEFAULT_STATUSES = ["To Do", "In Progress", "Done"];
6823
+ function parseBacklogConfig$1(content) {
6824
+ const config = {};
6825
+ const lines = content.split("\n");
6826
+ for (const line of lines) {
6827
+ const trimmed = line.trim();
6828
+ if (!trimmed || trimmed.startsWith("#")) continue;
6829
+ const colonIndex = trimmed.indexOf(":");
6830
+ if (colonIndex === -1) continue;
6831
+ const key = trimmed.substring(0, colonIndex).trim();
6832
+ const value = trimmed.substring(colonIndex + 1).trim();
6833
+ switch (key) {
6834
+ case "project_name":
6835
+ config.projectName = value.replace(/['"]/g, "");
6836
+ break;
6837
+ case "default_assignee":
6838
+ config.defaultAssignee = value.replace(/['"]/g, "");
6839
+ break;
6840
+ case "default_reporter":
6841
+ config.defaultReporter = value.replace(/['"]/g, "");
6842
+ break;
6843
+ case "default_status":
6844
+ config.defaultStatus = value.replace(/['"]/g, "");
6845
+ break;
6846
+ case "statuses":
6847
+ case "labels":
6848
+ case "milestones":
6849
+ if (value.startsWith("[") && value.endsWith("]")) {
6850
+ const arrayContent = value.slice(1, -1);
6851
+ config[key] = arrayContent.split(",").map((item) => item.trim().replace(/['"]/g, "")).filter(Boolean);
6852
+ }
6853
+ break;
6854
+ case "date_format":
6855
+ config.dateFormat = value.replace(/['"]/g, "");
6856
+ break;
6857
+ case "max_column_width":
6858
+ config.maxColumnWidth = Number.parseInt(value, 10);
6859
+ break;
6860
+ case "default_editor":
6861
+ config.defaultEditor = value.replace(/["']/g, "");
6862
+ break;
6863
+ case "auto_open_browser":
6864
+ config.autoOpenBrowser = value.toLowerCase() === "true";
6865
+ break;
6866
+ case "default_port":
6867
+ config.defaultPort = Number.parseInt(value, 10);
6868
+ break;
6869
+ case "remote_operations":
6870
+ config.remoteOperations = value.toLowerCase() === "true";
6871
+ break;
6872
+ case "auto_commit":
6873
+ config.autoCommit = value.toLowerCase() === "true";
6874
+ break;
6875
+ case "zero_padded_ids":
6876
+ config.zeroPaddedIds = Number.parseInt(value, 10);
6877
+ break;
6878
+ case "bypass_git_hooks":
6879
+ config.bypassGitHooks = value.toLowerCase() === "true";
6880
+ break;
6881
+ case "check_active_branches":
6882
+ config.checkActiveBranches = value.toLowerCase() === "true";
6883
+ break;
6884
+ case "active_branch_days":
6885
+ config.activeBranchDays = Number.parseInt(value, 10);
6886
+ break;
6887
+ }
6888
+ }
6889
+ return {
6890
+ project_name: config.projectName || "",
6891
+ default_status: config.defaultStatus || DEFAULT_STATUSES[0],
6892
+ statuses: config.statuses || [...DEFAULT_STATUSES],
6893
+ labels: config.labels || [],
6894
+ milestones: config.milestones || [],
6895
+ date_format: config.dateFormat || "yyyy-mm-dd hh:mm",
6896
+ default_editor: config.defaultEditor,
6897
+ auto_commit: config.autoCommit,
6898
+ zero_padded_ids: config.zeroPaddedIds
6899
+ };
6900
+ }
6822
6901
  function parseYaml(yamlString) {
6823
6902
  return YAML.parse(yamlString);
6824
6903
  }
6825
6904
  function parseBacklogConfig(content) {
6826
- const parsed = parseYaml(content);
6827
- console.log("[parseBacklogConfig] Parsed YAML:", JSON.stringify(parsed, null, 2));
6828
- console.log("[parseBacklogConfig] project_name value:", parsed.project_name);
6829
- console.log("[parseBacklogConfig] project_name type:", typeof parsed.project_name);
6830
- if (!parsed.project_name || typeof parsed.project_name !== "string") {
6831
- console.error("[parseBacklogConfig] Validation failed - parsed keys:", Object.keys(parsed));
6832
- throw new BacklogAdapterError(
6833
- "Invalid config.yml: missing or invalid project_name"
6834
- );
6835
- }
6836
- if (!parsed.statuses || !Array.isArray(parsed.statuses)) {
6837
- throw new BacklogAdapterError(
6838
- "Invalid config.yml: missing or invalid statuses array"
6905
+ var _a;
6906
+ console.log("[parseBacklogConfig] Using official Backlog.md parser");
6907
+ try {
6908
+ const config = parseBacklogConfig$1(content);
6909
+ console.log("[parseBacklogConfig] Parsed config:", {
6910
+ project_name: config.project_name,
6911
+ statuses: config.statuses,
6912
+ labels: ((_a = config.labels) == null ? void 0 : _a.length) || 0
6913
+ });
6914
+ if (!config.project_name) {
6915
+ throw new BacklogAdapterError(
6916
+ "Invalid config.yml: missing or invalid project_name"
6917
+ );
6918
+ }
6919
+ if (!config.statuses || config.statuses.length === 0) {
6920
+ throw new BacklogAdapterError(
6921
+ "Invalid config.yml: missing or invalid statuses array"
6922
+ );
6923
+ }
6924
+ return config;
6925
+ } catch (error) {
6926
+ console.error("[parseBacklogConfig] Failed to parse config:", error);
6927
+ throw error instanceof BacklogAdapterError ? error : new BacklogAdapterError(
6928
+ `Failed to parse config.yml: ${error instanceof Error ? error.message : "Unknown error"}`
6839
6929
  );
6840
6930
  }
6841
- return {
6842
- project_name: parsed.project_name,
6843
- default_status: parsed.default_status || "To Do",
6844
- statuses: parsed.statuses,
6845
- labels: parsed.labels || [],
6846
- milestones: parsed.milestones || [],
6847
- date_format: parsed.date_format || "yyyy-mm-dd hh:mm",
6848
- default_editor: parsed.default_editor,
6849
- auto_commit: parsed.auto_commit,
6850
- zero_padded_ids: parsed.zero_padded_ids
6851
- };
6852
6931
  }
6853
6932
  function parseTaskFile(content, filepath) {
6854
6933
  const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
@@ -7222,7 +7301,8 @@ function useKanbanData(options) {
7222
7301
  setIsBacklogProject(true);
7223
7302
  const [loadedStatuses, tasksByStatus2] = await Promise.all([
7224
7303
  adapter.getStatuses(),
7225
- adapter.getTasksByStatus(true)
7304
+ adapter.getTasksByStatus(false)
7305
+ // false = exclude completed tasks
7226
7306
  ]);
7227
7307
  const allTasks = [];
7228
7308
  tasksByStatus2.forEach((tasks2) => {
@@ -7253,6 +7333,7 @@ function useKanbanData(options) {
7253
7333
  loadBacklogData();
7254
7334
  }, [loadBacklogData]);
7255
7335
  const tasksByStatus = useMemo(() => {
7336
+ const TASKS_PER_COLUMN_LIMIT = 3;
7256
7337
  const grouped = /* @__PURE__ */ new Map();
7257
7338
  for (const status of statuses) {
7258
7339
  grouped.set(status, []);
@@ -7264,13 +7345,18 @@ function useKanbanData(options) {
7264
7345
  list.push(task);
7265
7346
  }
7266
7347
  }
7348
+ grouped.forEach((taskList, status) => {
7349
+ if (taskList.length > TASKS_PER_COLUMN_LIMIT) {
7350
+ grouped.set(status, taskList.slice(0, TASKS_PER_COLUMN_LIMIT));
7351
+ }
7352
+ });
7267
7353
  return grouped;
7268
7354
  }, [tasks, statuses]);
7269
7355
  const refreshData = useCallback(async () => {
7270
7356
  await loadBacklogData();
7271
7357
  }, [loadBacklogData]);
7272
7358
  const updateTaskStatus = useCallback(
7273
- async (taskId, newStatus) => {
7359
+ async (_taskId, _newStatus) => {
7274
7360
  setError(null);
7275
7361
  console.warn(
7276
7362
  "[useKanbanData] Task status updates not yet implemented for Backlog.md"
@@ -7315,7 +7401,6 @@ const KanbanColumn = ({
7315
7401
  flex: "1",
7316
7402
  minWidth: "min(280px, 85vw)",
7317
7403
  // Responsive width for mobile
7318
- maxWidth: "400px",
7319
7404
  display: "flex",
7320
7405
  flexDirection: "column",
7321
7406
  gap: "12px",