devendra-skill-package 1.0.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.
Files changed (223) hide show
  1. package/.github/skills/boiler-project-generator/SKILL.md +103 -0
  2. package/.github/skills/boiler-project-generator/assets/templates/android/README.md +3 -0
  3. package/.github/skills/boiler-project-generator/assets/templates/angular/README.md +3 -0
  4. package/.github/skills/boiler-project-generator/assets/templates/flutter/README.md +3 -0
  5. package/.github/skills/boiler-project-generator/assets/templates/ios/README.md +3 -0
  6. package/.github/skills/boiler-project-generator/assets/templates/react/README.md +3 -0
  7. package/.github/skills/boiler-project-generator/assets/templates/react-native/README.md +3 -0
  8. package/.github/skills/boiler-project-generator/assets/templates/react-native/api-setup.ts +76 -0
  9. package/.github/skills/boiler-project-generator/assets/templates/react-native/component-primary-button.tsx +29 -0
  10. package/.github/skills/boiler-project-generator/assets/templates/react-native/env-config.env +4 -0
  11. package/.github/skills/boiler-project-generator/assets/templates/react-native/feature-auth-screen.tsx +45 -0
  12. package/.github/skills/boiler-project-generator/assets/templates/react-native/feature-dashboard-screen.tsx +45 -0
  13. package/.github/skills/boiler-project-generator/assets/templates/react-native/feature-profile-screen.tsx +45 -0
  14. package/.github/skills/boiler-project-generator/assets/templates/react-native/hook-use-app-boot.ts +11 -0
  15. package/.github/skills/boiler-project-generator/assets/templates/react-native/navigation-setup.tsx +25 -0
  16. package/.github/skills/boiler-project-generator/assets/templates/react-native/project-structure.md +24 -0
  17. package/.github/skills/boiler-project-generator/assets/templates/react-native/redux-hooks.ts +5 -0
  18. package/.github/skills/boiler-project-generator/assets/templates/react-native/redux-session-slice.ts +29 -0
  19. package/.github/skills/boiler-project-generator/assets/templates/react-native/redux-store.ts +15 -0
  20. package/.github/skills/boiler-project-generator/assets/templates/react-native/theme-index.ts +23 -0
  21. package/.github/skills/boiler-project-generator/assets/templates/react-native/utils-helpers.ts +7 -0
  22. package/.github/skills/boiler-project-generator/metadata.yaml +29 -0
  23. package/.github/skills/boiler-project-generator/references/android.md +19 -0
  24. package/.github/skills/boiler-project-generator/references/angular.md +14 -0
  25. package/.github/skills/boiler-project-generator/references/flutter.md +17 -0
  26. package/.github/skills/boiler-project-generator/references/ios.md +17 -0
  27. package/.github/skills/boiler-project-generator/references/react-native.md +103 -0
  28. package/.github/skills/boiler-project-generator/references/react.md +17 -0
  29. package/.github/skills/boiler-project-generator/scripts/angular.js +43 -0
  30. package/.github/skills/boiler-project-generator/scripts/generate-project.mjs +107 -0
  31. package/.github/skills/boiler-project-generator/scripts/init.js +105 -0
  32. package/.github/skills/boiler-project-generator/scripts/react-native.js +1041 -0
  33. package/.github/skills/boiler-project-generator/scripts/react.js +32 -0
  34. package/.github/skills/clean-architecture-generator/SKILL.md +235 -0
  35. package/.github/skills/clean-architecture-generator/references/architecture-core.md +126 -0
  36. package/.github/skills/clean-architecture-generator/references/platform-angular.md +374 -0
  37. package/.github/skills/clean-architecture-generator/references/platform-flutter.md +366 -0
  38. package/.github/skills/clean-architecture-generator/references/platform-react-native.md +590 -0
  39. package/.github/skills/clean-architecture-generator/references/platform-react.md +261 -0
  40. package/.github/skills/code-test-coverage-analyzer/SKILL.md +1358 -0
  41. package/.github/skills/code-test-coverage-analyzer/assets/config-questionnaire.md +118 -0
  42. package/.github/skills/code-test-coverage-analyzer/assets/conflict-resolution-protocol.md +99 -0
  43. package/.github/skills/code-test-coverage-analyzer/assets/coverage-calculation-rules.md +294 -0
  44. package/.github/skills/code-test-coverage-analyzer/assets/multi-strategy-search.md +145 -0
  45. package/.github/skills/code-test-coverage-analyzer/assets/output-file-contracts.md +651 -0
  46. package/.github/skills/code-test-coverage-analyzer/assets/status-definitions.md +273 -0
  47. package/.github/skills/code-test-coverage-analyzer/examples/example-invocation.md +208 -0
  48. package/.github/skills/code-test-coverage-analyzer/references/android-patterns.md +229 -0
  49. package/.github/skills/code-test-coverage-analyzer/references/angular-patterns.md +177 -0
  50. package/.github/skills/code-test-coverage-analyzer/references/backend-patterns.md +383 -0
  51. package/.github/skills/code-test-coverage-analyzer/references/flutter-patterns.md +254 -0
  52. package/.github/skills/code-test-coverage-analyzer/references/ios-patterns.md +228 -0
  53. package/.github/skills/code-test-coverage-analyzer/references/react-native-patterns.md +431 -0
  54. package/.github/skills/code-test-coverage-analyzer/references/react-patterns.md +206 -0
  55. package/.github/skills/code-test-coverage-analyzer/scripts/detect-platform.ps1 +261 -0
  56. package/.github/skills/code-test-coverage-analyzer/scripts/scan-repository.ps1 +242 -0
  57. package/.github/skills/code-test-coverage-analyzer/templates/brd-compliance-row.md +107 -0
  58. package/.github/skills/code-test-coverage-analyzer/templates/test-case-row.md +130 -0
  59. package/.github/skills/code-test-coverage-analyzer/templates/user-story-compliance-row.md +170 -0
  60. package/.github/skills/custom-font-integrator/SKILL.md +373 -0
  61. package/.github/skills/custom-font-integrator/assets/FontTestScreen.js +150 -0
  62. package/.github/skills/custom-font-integrator/references/example-info-plist.xml +21 -0
  63. package/.github/skills/custom-font-integrator/scripts/setup-fonts.sh +99 -0
  64. package/.github/skills/encryption-decryption-utility/Instructions.md +282 -0
  65. package/.github/skills/encryption-decryption-utility/README.md +222 -0
  66. package/.github/skills/encryption-decryption-utility/SKILL.md +645 -0
  67. package/.github/skills/encryption-decryption-utility/assets/encryption-config-template.json +13 -0
  68. package/.github/skills/encryption-decryption-utility/assets/platform-matrix.json +180 -0
  69. package/.github/skills/encryption-decryption-utility/metadata.yaml +51 -0
  70. package/.github/skills/encryption-decryption-utility/references/android-crypto.md +157 -0
  71. package/.github/skills/encryption-decryption-utility/references/angular-crypto.md +130 -0
  72. package/.github/skills/encryption-decryption-utility/references/approach-1-webcrypto.md +95 -0
  73. package/.github/skills/encryption-decryption-utility/references/approach-2-rsa-aes-cbc.md +111 -0
  74. package/.github/skills/encryption-decryption-utility/references/approach-3-aes-sharedkey.md +114 -0
  75. package/.github/skills/encryption-decryption-utility/references/architecture.md +233 -0
  76. package/.github/skills/encryption-decryption-utility/references/backend-alignment.md +506 -0
  77. package/.github/skills/encryption-decryption-utility/references/dependency-guidance.md +234 -0
  78. package/.github/skills/encryption-decryption-utility/references/ec-implementation.md +832 -0
  79. package/.github/skills/encryption-decryption-utility/references/error-handling-playbook.md +234 -0
  80. package/.github/skills/encryption-decryption-utility/references/flutter-crypto.md +105 -0
  81. package/.github/skills/encryption-decryption-utility/references/ios-crypto.md +338 -0
  82. package/.github/skills/encryption-decryption-utility/references/native-rsa-implementation.md +373 -0
  83. package/.github/skills/encryption-decryption-utility/references/node-crypto.md +86 -0
  84. package/.github/skills/encryption-decryption-utility/references/react-crypto.md +105 -0
  85. package/.github/skills/encryption-decryption-utility/references/react-native-crypto.md +1001 -0
  86. package/.github/skills/encryption-decryption-utility/references/react-web-crypto.md +668 -0
  87. package/.github/skills/encryption-decryption-utility/references/security-checklist.md +176 -0
  88. package/.github/skills/encryption-decryption-utility/references/web-crypto.md +74 -0
  89. package/.github/skills/encryption-decryption-utility/scripts/detect.js +128 -0
  90. package/.github/skills/encryption-decryption-utility/scripts/install.js +1713 -0
  91. package/.github/skills/encryption-decryption-utility/scripts/setup.js +800 -0
  92. package/.github/skills/encryption-decryption-utility/template.md +241 -0
  93. package/.github/skills/encryption-decryption-utility/templates/config-questionnaire.md +467 -0
  94. package/.github/skills/encryption-decryption-utility/templates/delivery-checklist.md +206 -0
  95. package/.github/skills/encryption-decryption-utility/templates/implementation-plan.md +304 -0
  96. package/.github/skills/feature-generator/SKILL.MD +2741 -0
  97. package/.github/skills/feature-generator/assets/fingerprint-schema.json +385 -0
  98. package/.github/skills/feature-generator/assets/spec-template.md +172 -0
  99. package/.github/skills/feature-generator/assets/transform-rules.json +82 -0
  100. package/.github/skills/feature-generator/references/api-envelope-patterns.md +327 -0
  101. package/.github/skills/feature-generator/references/screen-logic-patterns.md +399 -0
  102. package/.github/skills/feature-generator/references/state-library-patterns.md +464 -0
  103. package/.github/skills/figma-ui-mapper/README.md +34 -0
  104. package/.github/skills/figma-ui-mapper/SKILL.md +101 -0
  105. package/.github/skills/figma-ui-mapper/assets/templates/component-map-template.md +30 -0
  106. package/.github/skills/figma-ui-mapper/assets/templates/generation-report-template.md +49 -0
  107. package/.github/skills/figma-ui-mapper/metadata.yaml +22 -0
  108. package/.github/skills/figma-ui-mapper/references/android.md +11 -0
  109. package/.github/skills/figma-ui-mapper/references/angular.md +18 -0
  110. package/.github/skills/figma-ui-mapper/references/capacitor.md +18 -0
  111. package/.github/skills/figma-ui-mapper/references/common.md +23 -0
  112. package/.github/skills/figma-ui-mapper/references/expo.md +18 -0
  113. package/.github/skills/figma-ui-mapper/references/flutter.md +18 -0
  114. package/.github/skills/figma-ui-mapper/references/frameworks/angular/rules.md +23 -0
  115. package/.github/skills/figma-ui-mapper/references/frameworks/capacitor/rules.md +23 -0
  116. package/.github/skills/figma-ui-mapper/references/frameworks/expo/rules.md +23 -0
  117. package/.github/skills/figma-ui-mapper/references/frameworks/flutter/rules.md +23 -0
  118. package/.github/skills/figma-ui-mapper/references/frameworks/ionic/rules.md +23 -0
  119. package/.github/skills/figma-ui-mapper/references/frameworks/kotlin-multiplatform/rules.md +23 -0
  120. package/.github/skills/figma-ui-mapper/references/frameworks/native-android/rules.md +23 -0
  121. package/.github/skills/figma-ui-mapper/references/frameworks/native-ios/rules.md +23 -0
  122. package/.github/skills/figma-ui-mapper/references/frameworks/next/rules.md +23 -0
  123. package/.github/skills/figma-ui-mapper/references/frameworks/nuxt/rules.md +23 -0
  124. package/.github/skills/figma-ui-mapper/references/frameworks/react/rules.md +19 -0
  125. package/.github/skills/figma-ui-mapper/references/frameworks/react-native/rules.md +23 -0
  126. package/.github/skills/figma-ui-mapper/references/frameworks/svelte/rules.md +23 -0
  127. package/.github/skills/figma-ui-mapper/references/frameworks/vue/rules.md +23 -0
  128. package/.github/skills/figma-ui-mapper/references/ionic.md +18 -0
  129. package/.github/skills/figma-ui-mapper/references/ios.md +11 -0
  130. package/.github/skills/figma-ui-mapper/references/kotlin-multiplatform.md +18 -0
  131. package/.github/skills/figma-ui-mapper/references/native-android.md +18 -0
  132. package/.github/skills/figma-ui-mapper/references/native-ios.md +18 -0
  133. package/.github/skills/figma-ui-mapper/references/next.md +18 -0
  134. package/.github/skills/figma-ui-mapper/references/nuxt.md +18 -0
  135. package/.github/skills/figma-ui-mapper/references/react-figma-guideline.md +21 -0
  136. package/.github/skills/figma-ui-mapper/references/react-native.md +18 -0
  137. package/.github/skills/figma-ui-mapper/references/react.md +18 -0
  138. package/.github/skills/figma-ui-mapper/references/script-usage.md +46 -0
  139. package/.github/skills/figma-ui-mapper/references/svelte.md +18 -0
  140. package/.github/skills/figma-ui-mapper/references/vue.md +18 -0
  141. package/.github/skills/figma-ui-mapper/references/workflow.md +74 -0
  142. package/.github/skills/figma-ui-mapper/scripts/generate-page-through-figma.js +635 -0
  143. package/.github/skills/figma-ui-mapper/scripts/generate-react-page-through-figma.js +4 -0
  144. package/.github/skills/frontend-task-breakdown/SKILL.md +734 -0
  145. package/.github/skills/md-file-converter/SKILL.md +291 -0
  146. package/.github/skills/md-file-converter/config/formats.json +114 -0
  147. package/.github/skills/md-file-converter/extractors/extract-docx.sh +120 -0
  148. package/.github/skills/md-file-converter/extractors/extract-eml.py +108 -0
  149. package/.github/skills/md-file-converter/extractors/extract-pdf.sh +97 -0
  150. package/.github/skills/md-file-converter/extractors/extract-pptx.py +143 -0
  151. package/.github/skills/md-file-converter/extractors/extract-xlsx.py +175 -0
  152. package/.github/skills/md-file-converter/scripts/check-tools.sh +47 -0
  153. package/.github/skills/md-file-converter/scripts/extract-archive.sh +83 -0
  154. package/.github/skills/md-file-converter/scripts/extract-ocr.sh +77 -0
  155. package/.github/skills/md-file-converter/scripts/get-metadata.sh +57 -0
  156. package/.github/skills/md-file-converter/templates/output.md +73 -0
  157. package/.github/skills/md-file-converter/templates/unsupported-object.md +6 -0
  158. package/.github/skills/mockAPI-contract-generator/SKILL.md +607 -0
  159. package/.github/skills/test-case-validator/CHANGELOG.md +155 -0
  160. package/.github/skills/test-case-validator/CONFIGURATION.md +130 -0
  161. package/.github/skills/test-case-validator/EXAMPLES.md +50 -0
  162. package/.github/skills/test-case-validator/QUALITY_SCORING.md +98 -0
  163. package/.github/skills/test-case-validator/README.md +111 -0
  164. package/.github/skills/test-case-validator/REPORT_TEMPLATE.md +116 -0
  165. package/.github/skills/test-case-validator/SKILL.md +209 -0
  166. package/.github/skills/test-case-validator/SYSTEM_PROMPT.md +127 -0
  167. package/.github/skills/test-case-validator/TRACEABILITY_ENGINE.md +152 -0
  168. package/.github/skills/test-case-validator/VALIDATION_RULES.md +411 -0
  169. package/.github/skills/test-case-validator/config/default.config.yaml +62 -0
  170. package/.github/skills/test-case-validator/docs/ARCHITECTURE.md +66 -0
  171. package/.github/skills/test-case-validator/docs/EXTENDING.md +85 -0
  172. package/.github/skills/test-case-validator/docs/FAQ.md +88 -0
  173. package/.github/skills/test-case-validator/docs/VERSIONING.md +55 -0
  174. package/.github/skills/test-case-validator/examples/example-1-manual-qa-ecommerce/input-brd.md +43 -0
  175. package/.github/skills/test-case-validator/examples/example-1-manual-qa-ecommerce/input-test-cases.csv +9 -0
  176. package/.github/skills/test-case-validator/examples/example-1-manual-qa-ecommerce/input-user-story.md +29 -0
  177. package/.github/skills/test-case-validator/examples/example-1-manual-qa-ecommerce/output-report.md +303 -0
  178. package/.github/skills/test-case-validator/examples/example-2-automated-frontend-suite/input-spec.md +43 -0
  179. package/.github/skills/test-case-validator/examples/example-2-automated-frontend-suite/input-test-files-index.md +56 -0
  180. package/.github/skills/test-case-validator/examples/example-2-automated-frontend-suite/output-report.md +274 -0
  181. package/.github/skills/test-case-validator/prompts/00-applicability-resolution.md +61 -0
  182. package/.github/skills/test-case-validator/prompts/01-extraction-user-story.md +58 -0
  183. package/.github/skills/test-case-validator/prompts/02-extraction-brd.md +64 -0
  184. package/.github/skills/test-case-validator/prompts/03-extraction-test-cases.md +92 -0
  185. package/.github/skills/test-case-validator/prompts/04-traceability-matrix.md +41 -0
  186. package/.github/skills/test-case-validator/prompts/05-coverage-analysis.md +46 -0
  187. package/.github/skills/test-case-validator/prompts/06-missing-scenario-detection.md +32 -0
  188. package/.github/skills/test-case-validator/prompts/07-duplicate-detection.md +36 -0
  189. package/.github/skills/test-case-validator/prompts/08-risk-analysis.md +39 -0
  190. package/.github/skills/test-case-validator/prompts/09-gated-wiring-validation.md +53 -0
  191. package/.github/skills/test-case-validator/prompts/10-observation-report.md +56 -0
  192. package/.github/skills/test-case-validator/prompts/11-final-report-assembly.md +57 -0
  193. package/.github/skills/test-case-validator/templates/coverage-table.md +25 -0
  194. package/.github/skills/test-case-validator/templates/executive-summary.md +38 -0
  195. package/.github/skills/test-case-validator/templates/final-summary-block.md +87 -0
  196. package/.github/skills/test-case-validator/templates/observation-entry.md +41 -0
  197. package/.github/skills/test-case-validator/templates/rtm-row.md +25 -0
  198. package/.github/skills/validation-engine-builder/README.md +50 -0
  199. package/.github/skills/validation-engine-builder/SKILL.md +241 -0
  200. package/.github/skills/validation-engine-builder/references/core.md +158 -0
  201. package/.github/skills/validation-engine-builder/references/platform-angular.md +166 -0
  202. package/.github/skills/validation-engine-builder/references/platform-flutter.md +118 -0
  203. package/.github/skills/validation-engine-builder/references/platform-react-native.md +170 -0
  204. package/.github/skills/validation-engine-builder/references/platform-react.md +94 -0
  205. package/.github/skills/validation-engine-builder/scripts/apply-to-project.js +80 -0
  206. package/.github/skills/validation-engine-builder/scripts/generate-angular.js +271 -0
  207. package/.github/skills/validation-engine-builder/scripts/generate-flutter.js +298 -0
  208. package/.github/skills/validation-engine-builder/scripts/generate-react-native.js +217 -0
  209. package/.github/skills/validation-engine-builder/scripts/generate-react.js +163 -0
  210. package/.github/skills/validation-engine-builder/scripts/install-deps.js +53 -0
  211. package/.github/skills/validation-engine-builder/scripts/shared/detect-platform.js +68 -0
  212. package/.github/skills/validation-engine-builder/scripts/shared/npm-deps.js +103 -0
  213. package/.github/skills/validation-engine-builder/scripts/shared/rhf-hook.js +43 -0
  214. package/.github/skills/validation-engine-builder/scripts/shared/ts-messages-regex.js +62 -0
  215. package/.github/skills/validation-engine-builder/scripts/shared/util.js +44 -0
  216. package/.github/skills/validation-engine-builder/scripts/shared/yup-schemas.js +80 -0
  217. package/.github/skills/validation-engine-builder/template.md +73 -0
  218. package/.github/skills/validation-engine-builder/templates/messages.json +22 -0
  219. package/.github/skills/validation-engine-builder/templates/regex.json +16 -0
  220. package/.github/skills/validation-engine-builder/templates/schemas.json +48 -0
  221. package/bin/index.js +145 -0
  222. package/package.json +22 -0
  223. package/readme.md +0 -0
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env bash
2
+ # PDF extractor. Tries pdftotext → pandoc → PyPDF2 in order.
3
+ # Usage: bash extractors/extract-pdf.sh <file.pdf> [start_page] [end_page]
4
+ # start_page and end_page are optional (1-based). Omit for full document.
5
+
6
+ FILE="$1"
7
+ START="${2:-}"
8
+ END="${3:-}"
9
+
10
+ if [ -z "$FILE" ]; then
11
+ echo "Usage: extract-pdf.sh <file.pdf> [start_page] [end_page]"
12
+ exit 1
13
+ fi
14
+
15
+ if [ ! -f "$FILE" ]; then
16
+ echo "Error: File not found: $FILE"
17
+ exit 1
18
+ fi
19
+
20
+ echo "=== PDF Extraction ==="
21
+ echo "File : $FILE"
22
+ [ -n "$START" ] && echo "Pages : $START to ${END:-end}"
23
+ echo ""
24
+
25
+ # Strategy 1: pdftotext (poppler-utils) — preserves layout best
26
+ if command -v pdftotext >/dev/null 2>&1; then
27
+ echo "Method: pdftotext"
28
+ echo ""
29
+ echo "--- Content ---"
30
+ if [ -n "$START" ] && [ -n "$END" ]; then
31
+ pdftotext -layout -f "$START" -l "$END" "$FILE" -
32
+ else
33
+ pdftotext -layout "$FILE" -
34
+ fi
35
+ EXIT_CODE=$?
36
+ if [ $EXIT_CODE -eq 0 ]; then
37
+ echo ""
38
+ echo "Extraction Status: SUCCESS (pdftotext)"
39
+ exit 0
40
+ fi
41
+ echo "pdftotext failed (exit $EXIT_CODE), trying fallback..."
42
+ fi
43
+
44
+ # Strategy 2: pandoc
45
+ if command -v pandoc >/dev/null 2>&1; then
46
+ echo "Method: pandoc"
47
+ echo ""
48
+ echo "--- Content ---"
49
+ pandoc "$FILE" -t markdown --wrap=none 2>/dev/null
50
+ EXIT_CODE=$?
51
+ if [ $EXIT_CODE -eq 0 ]; then
52
+ echo ""
53
+ echo "Extraction Status: SUCCESS (pandoc)"
54
+ exit 0
55
+ fi
56
+ echo "pandoc failed (exit $EXIT_CODE), trying fallback..."
57
+ fi
58
+
59
+ # Strategy 3: PyPDF2 via Python
60
+ if command -v python3 >/dev/null 2>&1 && python3 -c "import PyPDF2" 2>/dev/null; then
61
+ echo "Method: PyPDF2"
62
+ echo ""
63
+ echo "--- Content ---"
64
+ python3 - "$FILE" "${START:-}" "${END:-}" <<'PYEOF'
65
+ import PyPDF2, sys
66
+
67
+ path = sys.argv[1]
68
+ start = int(sys.argv[2]) - 1 if sys.argv[2] else 0
69
+ end = int(sys.argv[3]) if sys.argv[3] else None
70
+
71
+ try:
72
+ with open(path, "rb") as f:
73
+ reader = PyPDF2.PdfReader(f)
74
+ pages = reader.pages[start:end]
75
+ for i, page in enumerate(pages, start + 1):
76
+ print(f"\n--- Page {i} ---\n")
77
+ text = page.extract_text()
78
+ if text:
79
+ print(text)
80
+ else:
81
+ print("[No extractable text on this page — may require OCR]")
82
+ print("\nExtraction Status: SUCCESS (PyPDF2)")
83
+ except Exception as e:
84
+ print(f"PyPDF2 failed: {e}", file=sys.stderr)
85
+ sys.exit(1)
86
+ PYEOF
87
+ exit $?
88
+ fi
89
+
90
+ # All strategies failed
91
+ echo "Extraction Status: FAILED"
92
+ echo "No PDF extractor available."
93
+ echo "Install options:"
94
+ echo " pdftotext : sudo apt install poppler-utils (or brew install poppler)"
95
+ echo " pandoc : https://pandoc.org/installing.html"
96
+ echo " PyPDF2 : pip install PyPDF2"
97
+ exit 1
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ PowerPoint extractor. Converts every slide to Markdown.
4
+ Captures: titles, text boxes, tables, images, charts, speaker notes.
5
+ Usage: python3 extractors/extract-pptx.py <file.pptx> [start_slide] [end_slide]
6
+ Slide numbers are 1-based. Omit to process all slides.
7
+ """
8
+
9
+ import sys
10
+ import os
11
+
12
+ FILE = sys.argv[1] if len(sys.argv) > 1 else None
13
+ START_SLIDE = int(sys.argv[2]) if len(sys.argv) > 2 else 1
14
+ END_SLIDE = int(sys.argv[3]) if len(sys.argv) > 3 else None
15
+
16
+ if not FILE:
17
+ print("Usage: extract-pptx.py <file.pptx> [start_slide] [end_slide]")
18
+ sys.exit(1)
19
+
20
+ if not os.path.exists(FILE):
21
+ print(f"Error: File not found: {FILE}")
22
+ sys.exit(1)
23
+
24
+ try:
25
+ from pptx import Presentation
26
+ from pptx.util import Inches
27
+ from pptx.enum.shapes import MSO_SHAPE_TYPE
28
+ except ImportError:
29
+ print("Extraction Status: FAILED")
30
+ print("python-pptx not installed. Run: pip install python-pptx")
31
+ sys.exit(1)
32
+
33
+ print(f"=== PowerPoint Extraction ===")
34
+ print(f"File : {FILE}")
35
+ print(f"Slides : {START_SLIDE} to {END_SLIDE or 'end'}")
36
+ print("")
37
+
38
+ prs = Presentation(FILE)
39
+ total_slides = len(prs.slides)
40
+ end = min(END_SLIDE, total_slides) if END_SLIDE else total_slides
41
+
42
+ slide_range = range(START_SLIDE - 1, end)
43
+
44
+ images_found = 0
45
+ tables_found = 0
46
+ charts_found = 0
47
+ notes_found = 0
48
+
49
+ for idx in slide_range:
50
+ slide = prs.slides[idx]
51
+ slide_num = idx + 1
52
+
53
+ print(f"---")
54
+ print(f"## Slide {slide_num} of {total_slides}")
55
+ print("")
56
+
57
+ for shape in slide.shapes:
58
+ # Title
59
+ if shape.shape_type == MSO_SHAPE_TYPE.PLACEHOLDER and hasattr(shape, "placeholder_format"):
60
+ ph_type = shape.placeholder_format.type
61
+ if ph_type is not None and ph_type == 1: # PP_PLACEHOLDER.TITLE = 1
62
+ if shape.has_text_frame and shape.text_frame.text.strip():
63
+ print(f"### {shape.text_frame.text.strip()}")
64
+ print("")
65
+ continue
66
+
67
+ # Text frames
68
+ if shape.has_text_frame:
69
+ text = shape.text_frame.text.strip()
70
+ if text:
71
+ for para in shape.text_frame.paragraphs:
72
+ para_text = para.text.strip()
73
+ if para_text:
74
+ level = para.level
75
+ prefix = " " * level + "- " if level > 0 else ""
76
+ print(f"{prefix}{para_text}")
77
+ print("")
78
+
79
+ # Tables
80
+ if shape.has_table:
81
+ tables_found += 1
82
+ table = shape.table
83
+ print(f"**Table {tables_found}:**\n")
84
+ rows = table.rows
85
+ if rows:
86
+ # Header
87
+ header_cells = [cell.text.strip() for cell in rows[0].cells]
88
+ print("| " + " | ".join(header_cells) + " |")
89
+ print("| " + " | ".join(["---"] * len(header_cells)) + " |")
90
+ for row in rows[1:]:
91
+ cells = [cell.text.strip() for cell in row.cells]
92
+ print("| " + " | ".join(cells) + " |")
93
+ print("")
94
+
95
+ # Charts
96
+ if shape.shape_type == MSO_SHAPE_TYPE.CHART:
97
+ charts_found += 1
98
+ chart = shape.chart
99
+ chart_title = ""
100
+ try:
101
+ chart_title = chart.chart_title.text_frame.text if chart.has_title else "Untitled Chart"
102
+ except Exception:
103
+ chart_title = "Chart"
104
+
105
+ print(f"**Chart {charts_found}: {chart_title}**\n")
106
+
107
+ try:
108
+ for series in chart.series:
109
+ series_name = series.name if series.name else "Series"
110
+ values = list(series.values) if series.values else []
111
+ print(f"- Series: {series_name}")
112
+ if values:
113
+ print(f" Values: {values}")
114
+ except Exception:
115
+ print(" [Chart data not extractable — describe visually if needed]")
116
+ print("")
117
+
118
+ # Images
119
+ if shape.shape_type == MSO_SHAPE_TYPE.PICTURE:
120
+ images_found += 1
121
+ img_name = getattr(shape, "name", f"image{images_found}")
122
+ print(f"![{img_name}](slide{slide_num}-image{images_found}.png)")
123
+ print(f"> Image on slide {slide_num}. Run OCR extractor if text extraction needed.")
124
+ print("")
125
+
126
+ # Speaker notes
127
+ if slide.has_notes_slide:
128
+ notes_text = slide.notes_slide.notes_text_frame.text.strip()
129
+ if notes_text:
130
+ notes_found += 1
131
+ print(f"**Speaker Notes:**")
132
+ print(f"> {notes_text}")
133
+ print("")
134
+
135
+ print("---")
136
+ print(f"")
137
+ print(f"=== Extraction Summary ===")
138
+ print(f"Slides processed : {len(slide_range)} of {total_slides}")
139
+ print(f"Tables found : {tables_found}")
140
+ print(f"Charts found : {charts_found}")
141
+ print(f"Images found : {images_found}")
142
+ print(f"Slides with notes: {notes_found}")
143
+ print(f"Extraction Status: SUCCESS (python-pptx)")
@@ -0,0 +1,175 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Excel / ODS extractor. Converts every worksheet to Markdown tables.
4
+ Captures: cell values, formulas, merged cells, comments, hidden sheets.
5
+ Usage: python3 extractors/extract-xlsx.py <file> [sheet_name]
6
+ Omit sheet_name to process all sheets.
7
+ """
8
+
9
+ import sys
10
+ import os
11
+
12
+ FILE = sys.argv[1] if len(sys.argv) > 1 else None
13
+ SHEET_NAME = sys.argv[2] if len(sys.argv) > 2 else None
14
+
15
+ if not FILE:
16
+ print("Usage: extract-xlsx.py <file.xlsx> [sheet_name]")
17
+ sys.exit(1)
18
+
19
+ if not os.path.exists(FILE):
20
+ print(f"Error: File not found: {FILE}")
21
+ sys.exit(1)
22
+
23
+ EXT = os.path.splitext(FILE)[1].lower()
24
+
25
+ # ── openpyxl (primary — XLSX/XLSM) ─────────────────────────────────────────
26
+ def extract_openpyxl(path, target_sheet=None):
27
+ import openpyxl
28
+ from openpyxl.utils import get_column_letter
29
+
30
+ wb = openpyxl.load_workbook(path, data_only=False) # data_only=False keeps formulas
31
+ wb_vals = openpyxl.load_workbook(path, data_only=True) # data_only=True gets computed values
32
+
33
+ sheet_names = [target_sheet] if target_sheet else wb.sheetnames
34
+
35
+ for name in sheet_names:
36
+ if name not in wb.sheetnames:
37
+ print(f"## Sheet: {name}\n\n> Sheet not found.\n")
38
+ continue
39
+
40
+ ws = wb[name]
41
+ ws_vals = wb_vals[name] if name in wb_vals.sheetnames else ws
42
+ hidden = ws.sheet_state != "visible"
43
+
44
+ print(f"## Sheet: {name}{' [HIDDEN]' if hidden else ''}\n")
45
+
46
+ # Dimensions
47
+ if ws.max_row == 0:
48
+ print("> Empty sheet.\n")
49
+ continue
50
+
51
+ # Build table
52
+ rows = list(ws.iter_rows())
53
+ if not rows:
54
+ print("> Empty sheet.\n")
55
+ continue
56
+
57
+ # Collect all cell data
58
+ table_data = []
59
+ for row in rows:
60
+ row_data = []
61
+ for cell in row:
62
+ formula = str(cell.value) if cell.value is not None else ""
63
+ computed = ws_vals.cell(cell.row, cell.column).value
64
+ computed_str = str(computed) if computed is not None else ""
65
+
66
+ if formula.startswith("="):
67
+ display = f"{formula} → {computed_str}"
68
+ else:
69
+ display = formula
70
+
71
+ # Check for comment
72
+ if cell.comment:
73
+ display += f" [Comment: {cell.comment.text.strip()}]"
74
+
75
+ row_data.append(display)
76
+ table_data.append(row_data)
77
+
78
+ # Render as Markdown table
79
+ if table_data:
80
+ # Header row
81
+ header = table_data[0]
82
+ col_count = max(len(r) for r in table_data)
83
+
84
+ # Pad all rows to same column count
85
+ for r in table_data:
86
+ while len(r) < col_count:
87
+ r.append("")
88
+
89
+ # Print header
90
+ print("| " + " | ".join(header) + " |")
91
+ print("| " + " | ".join(["---"] * col_count) + " |")
92
+
93
+ # Print data rows
94
+ for row in table_data[1:]:
95
+ print("| " + " | ".join(row) + " |")
96
+
97
+ # Named ranges
98
+ if hasattr(wb, 'defined_names') and wb.defined_names:
99
+ named = []
100
+ defined_names_iter = (
101
+ wb.defined_names.definedName if hasattr(wb.defined_names, 'definedName')
102
+ else wb.defined_names.values()
103
+ )
104
+ for defn in defined_names_iter:
105
+ if name in str(defn.attr_text):
106
+ named.append(f" - `{defn.name}` = `{defn.attr_text}`")
107
+ if named:
108
+ print("\n**Named Ranges:**")
109
+ print("\n".join(named))
110
+
111
+ print("")
112
+
113
+ print("Extraction Status: SUCCESS (openpyxl)")
114
+
115
+
116
+ # ── xlrd (fallback — older .xls) ────────────────────────────────────────────
117
+ def extract_xlrd(path, target_sheet=None):
118
+ import xlrd
119
+ wb = xlrd.open_workbook(path)
120
+ sheet_names = [target_sheet] if target_sheet else wb.sheet_names()
121
+
122
+ for name in sheet_names:
123
+ try:
124
+ ws = wb.sheet_by_name(name)
125
+ except xlrd.XLRDError:
126
+ print(f"## Sheet: {name}\n\n> Sheet not found.\n")
127
+ continue
128
+
129
+ print(f"## Sheet: {name}\n")
130
+
131
+ if ws.nrows == 0:
132
+ print("> Empty sheet.\n")
133
+ continue
134
+
135
+ rows = [[str(ws.cell_value(r, c)) for c in range(ws.ncols)] for r in range(ws.nrows)]
136
+
137
+ print("| " + " | ".join(rows[0]) + " |")
138
+ print("| " + " | ".join(["---"] * ws.ncols) + " |")
139
+ for row in rows[1:]:
140
+ print("| " + " | ".join(row) + " |")
141
+
142
+ print("")
143
+
144
+ print("Extraction Status: SUCCESS (xlrd)")
145
+
146
+
147
+ # ── Main dispatch ────────────────────────────────────────────────────────────
148
+ print(f"=== Excel Extraction ===")
149
+ print(f"File : {FILE}")
150
+ print(f"Sheet : {SHEET_NAME or 'ALL'}")
151
+ print("")
152
+
153
+ if EXT in (".xlsx", ".xlsm", ".ods"):
154
+ try:
155
+ extract_openpyxl(FILE, SHEET_NAME)
156
+ sys.exit(0)
157
+ except ImportError:
158
+ print("openpyxl not available, trying xlrd...")
159
+ except Exception as e:
160
+ print(f"openpyxl failed: {e}, trying xlrd...")
161
+
162
+ if EXT in (".xls", ".xlsx"):
163
+ try:
164
+ extract_xlrd(FILE, SHEET_NAME)
165
+ sys.exit(0)
166
+ except ImportError:
167
+ print("xlrd not available.")
168
+ except Exception as e:
169
+ print(f"xlrd failed: {e}")
170
+
171
+ print("Extraction Status: FAILED")
172
+ print("No Excel library available.")
173
+ print("Install: pip install openpyxl (for .xlsx)")
174
+ print("Install: pip install xlrd (for legacy .xls)")
175
+ sys.exit(1)
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env bash
2
+ # Detects which extraction tools are available in the current environment.
3
+ # Run this FIRST before any conversion. Output is used to determine strategy.
4
+ # Usage: bash scripts/check-tools.sh
5
+
6
+ echo "=== Tool Detection Report ==="
7
+ echo ""
8
+
9
+ echo "--- Document Extractors ---"
10
+ command -v pandoc >/dev/null 2>&1 && echo "pandoc : AVAILABLE" || echo "pandoc : NOT available (DOCX/ODT/RTF fallback unavailable)"
11
+ command -v pdftotext >/dev/null 2>&1 && echo "pdftotext : AVAILABLE" || echo "pdftotext : NOT available (PDF text extraction unavailable)"
12
+ command -v pdfinfo >/dev/null 2>&1 && echo "pdfinfo : AVAILABLE" || echo "pdfinfo : NOT available (PDF metadata unavailable)"
13
+ command -v pdfimages >/dev/null 2>&1 && echo "pdfimages : AVAILABLE" || echo "pdfimages : NOT available (PDF image listing unavailable)"
14
+ command -v unrtf >/dev/null 2>&1 && echo "unrtf : AVAILABLE" || echo "unrtf : NOT available (RTF fallback unavailable)"
15
+
16
+ echo ""
17
+ echo "--- Python & Libraries ---"
18
+ command -v python3 >/dev/null 2>&1 && echo "python3 : AVAILABLE ($(python3 --version 2>&1))" || echo "python3 : NOT available"
19
+
20
+ if command -v python3 >/dev/null 2>&1; then
21
+ python3 -c "import openpyxl" 2>/dev/null && echo "openpyxl : AVAILABLE" || echo "openpyxl : NOT available (Excel extraction unavailable — pip install openpyxl)"
22
+ python3 -c "from pptx import Presentation" 2>/dev/null && echo "python-pptx : AVAILABLE" || echo "python-pptx : NOT available (PowerPoint extraction unavailable — pip install python-pptx)"
23
+ python3 -c "import PyPDF2" 2>/dev/null && echo "PyPDF2 : AVAILABLE" || echo "PyPDF2 : NOT available (PDF fallback unavailable)"
24
+ python3 -c "import easyocr" 2>/dev/null && echo "easyocr : AVAILABLE" || echo "easyocr : NOT available (OCR fallback unavailable — pip install easyocr)"
25
+ fi
26
+
27
+ echo ""
28
+ echo "--- OCR Tools ---"
29
+ command -v tesseract >/dev/null 2>&1 && echo "tesseract : AVAILABLE ($(tesseract --version 2>&1 | head -1))" || echo "tesseract : NOT available (primary OCR unavailable — install tesseract-ocr)"
30
+ command -v exiftool >/dev/null 2>&1 && echo "exiftool : AVAILABLE" || echo "exiftool : NOT available (extended metadata unavailable)"
31
+
32
+ echo ""
33
+ echo "--- Archive Tools ---"
34
+ command -v unzip >/dev/null 2>&1 && echo "unzip : AVAILABLE" || echo "unzip : NOT available (.zip extraction unavailable)"
35
+ command -v tar >/dev/null 2>&1 && echo "tar : AVAILABLE" || echo "tar : NOT available (.tar/.gz extraction unavailable)"
36
+ command -v 7z >/dev/null 2>&1 && echo "7z : AVAILABLE" || echo "7z : NOT available (.7z extraction unavailable)"
37
+ command -v unrar >/dev/null 2>&1 && echo "unrar : AVAILABLE" || echo "unrar : NOT available (.rar extraction unavailable)"
38
+ command -v gunzip >/dev/null 2>&1 && echo "gunzip : AVAILABLE" || echo "gunzip : NOT available (.gz extraction unavailable)"
39
+
40
+ echo ""
41
+ echo "--- Core Utilities ---"
42
+ command -v file >/dev/null 2>&1 && echo "file : AVAILABLE" || echo "file : NOT available"
43
+ command -v stat >/dev/null 2>&1 && echo "stat : AVAILABLE" || echo "stat : NOT available"
44
+ command -v wc >/dev/null 2>&1 && echo "wc : AVAILABLE" || echo "wc : NOT available"
45
+
46
+ echo ""
47
+ echo "=== End of Tool Detection ==="
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env bash
2
+ # Extracts any supported archive format into a target directory.
3
+ # Usage: bash scripts/extract-archive.sh <archive_path> <output_dir>
4
+ # After extraction, lists all files for Claude to process individually.
5
+
6
+ ARCHIVE="$1"
7
+ OUTPUT_DIR="$2"
8
+
9
+ if [ -z "$ARCHIVE" ] || [ -z "$OUTPUT_DIR" ]; then
10
+ echo "Usage: extract-archive.sh <archive_path> <output_dir>"
11
+ exit 1
12
+ fi
13
+
14
+ if [ ! -f "$ARCHIVE" ]; then
15
+ echo "Error: Archive not found: $ARCHIVE"
16
+ exit 1
17
+ fi
18
+
19
+ mkdir -p "$OUTPUT_DIR"
20
+
21
+ FILENAME=$(basename "$ARCHIVE")
22
+ EXT_LOWER=$(echo "$FILENAME" | tr '[:upper:]' '[:lower:]')
23
+
24
+ echo "=== Archive Extraction ==="
25
+ echo "Archive : $ARCHIVE"
26
+ echo "Output : $OUTPUT_DIR"
27
+ echo ""
28
+
29
+ # Detect format and extract
30
+ if echo "$EXT_LOWER" | grep -q '\.zip$'; then
31
+ echo "Format: ZIP"
32
+ unzip -o "$ARCHIVE" -d "$OUTPUT_DIR" && echo "Extraction: SUCCESS" || { echo "Extraction: FAILED"; exit 1; }
33
+
34
+ elif echo "$EXT_LOWER" | grep -qE '\.(tar\.gz|tgz)$'; then
35
+ echo "Format: TAR.GZ"
36
+ tar -xzf "$ARCHIVE" -C "$OUTPUT_DIR" && echo "Extraction: SUCCESS" || { echo "Extraction: FAILED"; exit 1; }
37
+
38
+ elif echo "$EXT_LOWER" | grep -q '\.tar\.bz2$'; then
39
+ echo "Format: TAR.BZ2"
40
+ tar -xjf "$ARCHIVE" -C "$OUTPUT_DIR" && echo "Extraction: SUCCESS" || { echo "Extraction: FAILED"; exit 1; }
41
+
42
+ elif echo "$EXT_LOWER" | grep -q '\.tar\.xz$'; then
43
+ echo "Format: TAR.XZ"
44
+ tar -xJf "$ARCHIVE" -C "$OUTPUT_DIR" && echo "Extraction: SUCCESS" || { echo "Extraction: FAILED"; exit 1; }
45
+
46
+ elif echo "$EXT_LOWER" | grep -q '\.tar$'; then
47
+ echo "Format: TAR"
48
+ tar -xf "$ARCHIVE" -C "$OUTPUT_DIR" && echo "Extraction: SUCCESS" || { echo "Extraction: FAILED"; exit 1; }
49
+
50
+ elif echo "$EXT_LOWER" | grep -q '\.gz$'; then
51
+ echo "Format: GZ (single file)"
52
+ DEST="$OUTPUT_DIR/$(basename "$ARCHIVE" .gz)"
53
+ gunzip -c "$ARCHIVE" > "$DEST" && echo "Extraction: SUCCESS" || { echo "Extraction: FAILED"; exit 1; }
54
+
55
+ elif echo "$EXT_LOWER" | grep -q '\.7z$'; then
56
+ echo "Format: 7Z"
57
+ if command -v 7z >/dev/null 2>&1; then
58
+ 7z x "$ARCHIVE" -o"$OUTPUT_DIR" -y && echo "Extraction: SUCCESS" || { echo "Extraction: FAILED"; exit 1; }
59
+ else
60
+ echo "Error: 7z not installed. Run: apt install p7zip-full"
61
+ exit 1
62
+ fi
63
+
64
+ elif echo "$EXT_LOWER" | grep -q '\.rar$'; then
65
+ echo "Format: RAR"
66
+ if command -v unrar >/dev/null 2>&1; then
67
+ unrar x "$ARCHIVE" "$OUTPUT_DIR/" && echo "Extraction: SUCCESS" || { echo "Extraction: FAILED"; exit 1; }
68
+ else
69
+ echo "Error: unrar not installed. Run: apt install unrar"
70
+ exit 1
71
+ fi
72
+
73
+ else
74
+ echo "Error: Unsupported archive format: $FILENAME"
75
+ exit 1
76
+ fi
77
+
78
+ echo ""
79
+ echo "=== Extracted Files ==="
80
+ find "$OUTPUT_DIR" -type f | sort
81
+ echo ""
82
+ echo "Total files: $(find "$OUTPUT_DIR" -type f | wc -l)"
83
+ echo "=== End Extraction ==="
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env bash
2
+ # OCR extractor for image files. Tries tesseract first, then easyocr.
3
+ # Usage: bash scripts/extract-ocr.sh <image_path> [language]
4
+ # language defaults to "eng". For multi-language: "eng+fra"
5
+
6
+ IMAGE="$1"
7
+ LANG="${2:-eng}"
8
+
9
+ if [ -z "$IMAGE" ]; then
10
+ echo "Usage: extract-ocr.sh <image_path> [language]"
11
+ exit 1
12
+ fi
13
+
14
+ if [ ! -f "$IMAGE" ]; then
15
+ echo "Error: Image not found: $IMAGE"
16
+ exit 1
17
+ fi
18
+
19
+ echo "=== OCR Extraction ==="
20
+ echo "Image : $IMAGE"
21
+ echo "Language : $LANG"
22
+ echo ""
23
+
24
+ # Strategy 1: tesseract (preferred — fast, no GPU needed)
25
+ if command -v tesseract >/dev/null 2>&1; then
26
+ echo "Method: tesseract"
27
+ echo ""
28
+ echo "--- Extracted Text ---"
29
+ tesseract "$IMAGE" stdout -l "$LANG" 2>/dev/null
30
+ EXIT_CODE=$?
31
+ if [ $EXIT_CODE -eq 0 ]; then
32
+ echo ""
33
+ echo "OCR Status: SUCCESS (tesseract)"
34
+ exit 0
35
+ else
36
+ echo "tesseract failed (exit $EXIT_CODE), trying fallback..."
37
+ fi
38
+ fi
39
+
40
+ # Strategy 2: easyocr via Python
41
+ if command -v python3 >/dev/null 2>&1 && python3 -c "import easyocr" 2>/dev/null; then
42
+ echo "Method: easyocr"
43
+ echo ""
44
+ echo "--- Extracted Text ---"
45
+ python3 - "$IMAGE" "$LANG" <<'PYEOF'
46
+ import easyocr
47
+ import sys
48
+
49
+ image_path = sys.argv[1]
50
+ lang_arg = sys.argv[2] if len(sys.argv) > 2 else "en"
51
+
52
+ # easyocr uses 2-letter codes: eng->en, fra->fr, etc.
53
+ lang = lang_arg.split("+")[0][:2]
54
+
55
+ try:
56
+ reader = easyocr.Reader([lang], gpu=False, verbose=False)
57
+ results = reader.readtext(image_path, detail=0, paragraph=True)
58
+ for line in results:
59
+ print(line)
60
+ print("")
61
+ print("OCR Status: SUCCESS (easyocr)")
62
+ except Exception as e:
63
+ print(f"easyocr failed: {e}", file=sys.stderr)
64
+ sys.exit(1)
65
+ PYEOF
66
+ exit $?
67
+ fi
68
+
69
+ # No OCR tool available
70
+ echo "OCR Status: FAILED"
71
+ echo "No OCR tool available."
72
+ echo "Install options:"
73
+ echo " tesseract : sudo apt install tesseract-ocr (or brew install tesseract)"
74
+ echo " easyocr : pip install easyocr"
75
+ echo ""
76
+ echo "Alternative: Upload the image directly into the Claude chat window to use vision-based OCR."
77
+ exit 1
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env bash
2
+ # Universal metadata extractor. Tries multiple tools in priority order.
3
+ # Usage: bash scripts/get-metadata.sh <file_path>
4
+ # Output: key-value pairs, one per line
5
+
6
+ FILE="$1"
7
+
8
+ if [ -z "$FILE" ]; then
9
+ echo "Usage: get-metadata.sh <file_path>"
10
+ exit 1
11
+ fi
12
+
13
+ if [ ! -f "$FILE" ]; then
14
+ echo "Error: File not found: $FILE"
15
+ exit 1
16
+ fi
17
+
18
+ echo "=== File Metadata ==="
19
+ echo "File Name : $(basename "$FILE")"
20
+ echo "File Path : $(realpath "$FILE" 2>/dev/null || echo "$FILE")"
21
+ echo "File Size : $(wc -c < "$FILE" 2>/dev/null) bytes"
22
+ echo "MIME Type : $(file --mime-type -b "$FILE" 2>/dev/null || echo "Not Available")"
23
+ echo "Encoding : $(file -b "$FILE" 2>/dev/null || echo "Not Available")"
24
+
25
+ # stat for timestamps (cross-platform safe subset)
26
+ if command -v stat >/dev/null 2>&1; then
27
+ echo "Modified Date : $(stat -c '%y' "$FILE" 2>/dev/null || stat -f '%Sm' "$FILE" 2>/dev/null || echo "Not Available")"
28
+ fi
29
+
30
+ EXT="${FILE##*.}"
31
+ EXT_LOWER=$(echo "$EXT" | tr '[:upper:]' '[:lower:]')
32
+
33
+ # PDF-specific metadata
34
+ if [ "$EXT_LOWER" = "pdf" ] && command -v pdfinfo >/dev/null 2>&1; then
35
+ echo ""
36
+ echo "=== PDF Metadata (pdfinfo) ==="
37
+ pdfinfo "$FILE" 2>/dev/null || echo "pdfinfo failed"
38
+ fi
39
+
40
+ # Extended metadata via exiftool (universal)
41
+ if command -v exiftool >/dev/null 2>&1; then
42
+ echo ""
43
+ echo "=== Extended Metadata (exiftool) ==="
44
+ exiftool "$FILE" 2>/dev/null || echo "exiftool failed"
45
+ fi
46
+
47
+ # Line/word count for text files
48
+ if file -b "$FILE" 2>/dev/null | grep -qi "text"; then
49
+ echo ""
50
+ echo "=== Text Statistics ==="
51
+ echo "Line Count : $(wc -l < "$FILE" 2>/dev/null)"
52
+ echo "Word Count : $(wc -w < "$FILE" 2>/dev/null)"
53
+ echo "Char Count : $(wc -m < "$FILE" 2>/dev/null)"
54
+ fi
55
+
56
+ echo ""
57
+ echo "=== End Metadata ==="