pasika 0.5.0 → 0.5.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.
@@ -92,15 +92,17 @@ function jsxTagName(element) {
92
92
  return ts.isIdentifier(tagName2) ? tagName2.text : void 0;
93
93
  }
94
94
  function rootFromExpression(expression) {
95
- if (ts.isJsxSelfClosingElement(expression)) {
96
- const tagName2 = jsxTagName(expression);
95
+ let unwrapped = expression;
96
+ while (ts.isParenthesizedExpression(unwrapped)) unwrapped = unwrapped.expression;
97
+ if (ts.isJsxSelfClosingElement(unwrapped)) {
98
+ const tagName2 = jsxTagName(unwrapped);
97
99
  if (!tagName2?.startsWith(tagName2[0]?.toLowerCase() ?? "")) return void 0;
98
- return { tagName: tagName2, attributes: [...expression.attributes.properties] };
100
+ return { tagName: tagName2, attributes: [...unwrapped.attributes.properties] };
99
101
  }
100
- if (ts.isJsxElement(expression)) {
101
- const tagName2 = jsxTagName(expression);
102
+ if (ts.isJsxElement(unwrapped)) {
103
+ const tagName2 = jsxTagName(unwrapped);
102
104
  if (!tagName2?.startsWith(tagName2[0]?.toLowerCase() ?? "")) return void 0;
103
- return { tagName: tagName2, attributes: [...expression.openingElement.attributes.properties] };
105
+ return { tagName: tagName2, attributes: [...unwrapped.openingElement.attributes.properties] };
104
106
  }
105
107
  return void 0;
106
108
  }
@@ -141,12 +143,21 @@ var NEXT_ROUTING_FILES = /* @__PURE__ */ new Set([
141
143
  "layout",
142
144
  "loading",
143
145
  "error",
146
+ "global-error",
144
147
  "not-found",
145
148
  "route",
146
149
  "template",
147
150
  "default",
148
151
  "middleware",
149
- "instrumentation"
152
+ "instrumentation",
153
+ // File conventions that Next.js requires to keep their exact kebab-case names
154
+ "apple-icon",
155
+ "icon",
156
+ "manifest",
157
+ "opengraph-image",
158
+ "robots",
159
+ "sitemap",
160
+ "twitter-image"
150
161
  ]);
151
162
  var COMPOUND_SUFFIXES = /* @__PURE__ */ new Set(["example", "test", "spec", "stories"]);
152
163
  function isKebabCase(str) {
@@ -1757,14 +1768,24 @@ var applicationStructureRule = {
1757
1768
  // eslint/rules/named-exports.ts
1758
1769
  import path13 from "path";
1759
1770
  var FRAMEWORK_DEFAULT_EXPORT_FILES = /* @__PURE__ */ new Set([
1771
+ // App Router routing files
1760
1772
  "default",
1761
1773
  "error",
1774
+ "global-error",
1762
1775
  "layout",
1763
1776
  "loading",
1764
1777
  "not-found",
1765
1778
  "page",
1766
1779
  "route",
1767
- "template"
1780
+ "template",
1781
+ // File conventions (metadata, icons) that must default-export their handler
1782
+ "apple-icon",
1783
+ "icon",
1784
+ "manifest",
1785
+ "opengraph-image",
1786
+ "robots",
1787
+ "sitemap",
1788
+ "twitter-image"
1768
1789
  ]);
1769
1790
  function isFrameworkDefaultExportFile(filename) {
1770
1791
  const normalized = filename.replaceAll(path13.sep, "/");
@@ -5704,18 +5725,37 @@ var huskyRules = {
5704
5725
  import { existsSync as existsSync3, readFileSync as readFileSync9 } from "fs";
5705
5726
  import path46 from "path";
5706
5727
  var PASIKA_REPO = "Bredansky/pasika";
5728
+ var BASE_REQUIRED_DOCS = [
5729
+ { name: "documentation-guide", path: "docs/documentation-guide" },
5730
+ { name: "framework-adoption-guide", path: "docs/framework-adoption-guide" },
5731
+ { name: "repository-policy", path: "docs/repository-policy.md" }
5732
+ ];
5733
+ var NEXTJS_REQUIRED_DOCS = [
5734
+ { name: "code-organization-guide", path: "docs/code-organization-guide" },
5735
+ { name: "styling-guide", path: "docs/styling-guide" }
5736
+ ];
5737
+ function memberName5(member) {
5738
+ return member.name.type === "String" ? member.name.value : member.name.name;
5739
+ }
5740
+ function hasDependency(root, name) {
5741
+ const section = root.members.find((member) => memberName5(member) === "dependencies");
5742
+ if (section?.value.type !== "Object") return false;
5743
+ return section.value.members.some((member) => memberName5(member) === name);
5744
+ }
5707
5745
  var vulykDocsRule = {
5708
5746
  meta: {
5709
5747
  schema: [],
5710
5748
  type: "problem",
5711
5749
  docs: {
5712
- description: "Require vulyk.config.ts to track the framework's docs from pasika and the generated AGENTS.md."
5750
+ description: "Require vulyk.config.ts to track the framework's required docs from pasika and the generated AGENTS.md."
5713
5751
  }
5714
5752
  },
5715
5753
  create(context) {
5716
5754
  return {
5717
5755
  Document(node) {
5718
5756
  if (!context.filename.endsWith("package.json")) return;
5757
+ const root = node.body;
5758
+ if (root.type !== "Object") return;
5719
5759
  const projectRoot = path46.dirname(path46.resolve(context.filename));
5720
5760
  const configPath = path46.join(projectRoot, "vulyk.config.ts");
5721
5761
  if (!existsSync3(configPath)) {
@@ -5731,6 +5771,16 @@ var vulykDocsRule = {
5731
5771
  node,
5732
5772
  message: "vulyk.config.ts must track the framework's docs from the pasika repository."
5733
5773
  });
5774
+ return;
5775
+ }
5776
+ const requiredDocs = hasDependency(root, "next") ? [...BASE_REQUIRED_DOCS, ...NEXTJS_REQUIRED_DOCS] : BASE_REQUIRED_DOCS;
5777
+ for (const doc of requiredDocs) {
5778
+ if (!config.includes(doc.path)) {
5779
+ context.report({
5780
+ node,
5781
+ message: `vulyk.config.ts must track the framework's ${doc.name} docs from pasika (${PASIKA_REPO}/${doc.path}).`
5782
+ });
5783
+ }
5734
5784
  }
5735
5785
  const agentsPath = path46.join(projectRoot, "AGENTS.md");
5736
5786
  if (!existsSync3(agentsPath)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pasika",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Reusable agent setup package",
5
5
  "repository": {
6
6
  "type": "git",