Add skills-lock.json to manage skill dependencies for drawio-skill and prd
This commit is contained in:
@@ -1,101 +0,0 @@
|
||||
# pyright: reportMissingImports=false
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
from openpyxl import load_workbook
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
SOURCE_FILE = ROOT.parent / "202606 Conti Retail APP Component data source.xlsx"
|
||||
OUTPUT_FILE = ROOT / f"{SOURCE_FILE.stem}.md"
|
||||
|
||||
FIELDS = [
|
||||
("编号", 2),
|
||||
("模块", 3),
|
||||
("功能", 4),
|
||||
("负责人", 5),
|
||||
("前置任务", 6),
|
||||
("数据集", 7),
|
||||
("来源", 8),
|
||||
("安全", 9),
|
||||
("备注", 10),
|
||||
]
|
||||
|
||||
|
||||
def normalize_cell(value: object) -> str:
|
||||
if value is None:
|
||||
return ""
|
||||
|
||||
if isinstance(value, float) and value.is_integer():
|
||||
value = int(value)
|
||||
|
||||
text = str(value).replace("\r\n", "\n").replace("\r", "\n")
|
||||
lines = [re.sub(r"\s+", " ", line).strip() for line in text.split("\n")]
|
||||
return "\n".join(line for line in lines if line)
|
||||
|
||||
|
||||
def add_field(parts: list[str], name: str, value: str) -> None:
|
||||
if not value:
|
||||
return
|
||||
|
||||
parts.append(f"**{name}**")
|
||||
parts.append("")
|
||||
|
||||
lines = [line.strip() for line in value.splitlines() if line.strip()]
|
||||
if len(lines) > 1:
|
||||
parts.extend(f"- {line}" for line in lines)
|
||||
else:
|
||||
parts.extend(lines)
|
||||
|
||||
parts.append("")
|
||||
|
||||
|
||||
def extract_workbook_to_md() -> None:
|
||||
workbook = load_workbook(SOURCE_FILE, data_only=True)
|
||||
parts: list[str] = [f"# {SOURCE_FILE.stem}", ""]
|
||||
|
||||
for worksheet in workbook.worksheets:
|
||||
rows: list[dict[str, str]] = []
|
||||
|
||||
for row_index in range(2, worksheet.max_row + 1):
|
||||
row = {
|
||||
field: normalize_cell(worksheet.cell(row=row_index, column=column).value)
|
||||
for field, column in FIELDS
|
||||
}
|
||||
if not any(row.values()):
|
||||
continue
|
||||
if not any(row[key] for key in ("编号", "模块", "功能")):
|
||||
continue
|
||||
rows.append(row)
|
||||
|
||||
if not rows:
|
||||
continue
|
||||
|
||||
parts.append(f"## {worksheet.title}")
|
||||
parts.append("")
|
||||
|
||||
for row in rows:
|
||||
number = row["编号"]
|
||||
module = row["模块"]
|
||||
title = " ".join(part for part in (number, module) if part).strip()
|
||||
level = min(6, 3 + number.count(".")) if number else 3
|
||||
|
||||
parts.append(f"{'#' * level} {title or 'Untitled'}")
|
||||
parts.append("")
|
||||
add_field(parts, "功能", row["功能"])
|
||||
add_field(parts, "负责人", row["负责人"])
|
||||
add_field(parts, "前置任务", row["前置任务"])
|
||||
add_field(parts, "数据集", row["数据集"])
|
||||
add_field(parts, "来源", row["来源"])
|
||||
add_field(parts, "安全", row["安全"])
|
||||
add_field(parts, "备注", row["备注"])
|
||||
|
||||
OUTPUT_FILE.write_text("\n".join(parts).strip() + "\n", encoding="utf-8")
|
||||
print("Wrote workbook markdown output")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
extract_workbook_to_md()
|
||||
@@ -1,128 +0,0 @@
|
||||
# pyright: reportMissingImports=false
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
import fitz
|
||||
import numpy as np
|
||||
from pptx import Presentation
|
||||
from pptx.enum.shapes import MSO_SHAPE_TYPE
|
||||
from rapidocr_onnxruntime import RapidOCR
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
SOURCE_DIR = ROOT.parent
|
||||
|
||||
PDF_PATH = SOURCE_DIR / "User Journeys.pdf"
|
||||
PPTX_PATH = SOURCE_DIR / "零售商系统方案研讨会PPT.retro.pptx"
|
||||
|
||||
PDF_OUTPUT = ROOT / "User Journeys.md"
|
||||
PPTX_OUTPUT = ROOT / "零售商系统方案研讨会PPT.retro.md"
|
||||
|
||||
OCR = RapidOCR()
|
||||
|
||||
|
||||
def normalize_text(text: str) -> str:
|
||||
text = text.replace("\r\n", "\n").replace("\r", "\n")
|
||||
lines = [re.sub(r"\s+", " ", line).strip() for line in text.split("\n")]
|
||||
return "\n".join(line for line in lines if line)
|
||||
|
||||
|
||||
def extract_page_ocr_text(page: fitz.Page) -> str:
|
||||
pix = page.get_pixmap(matrix=fitz.Matrix(4, 4), alpha=False)
|
||||
image = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.height, pix.width, pix.n)
|
||||
result, _ = OCR(image)
|
||||
if not result:
|
||||
return ""
|
||||
return normalize_text("\n".join(str(item[1]) for item in result))
|
||||
|
||||
|
||||
def extract_pdf_to_md(pdf_path: Path, output_path: Path) -> None:
|
||||
doc = fitz.open(pdf_path)
|
||||
parts: list[str] = [f"# {pdf_path.stem}", ""]
|
||||
|
||||
try:
|
||||
for index in range(doc.page_count):
|
||||
page = doc.load_page(index)
|
||||
text = normalize_text(str(page.get_text("text") or ""))
|
||||
if not text:
|
||||
text = extract_page_ocr_text(page)
|
||||
parts.append(f"## Page {index + 1}")
|
||||
parts.append("")
|
||||
parts.append(text or "[No extractable text]")
|
||||
parts.append("")
|
||||
finally:
|
||||
doc.close()
|
||||
|
||||
output_path.write_text("\n".join(parts).strip() + "\n", encoding="utf-8")
|
||||
|
||||
|
||||
def iter_shape_text(shape) -> list[str]:
|
||||
chunks: list[str] = []
|
||||
|
||||
if hasattr(shape, "has_text_frame") and shape.has_text_frame:
|
||||
text = normalize_text(shape.text_frame.text)
|
||||
if text:
|
||||
chunks.append(text)
|
||||
|
||||
if hasattr(shape, "has_table") and shape.has_table:
|
||||
for row in shape.table.rows:
|
||||
cells = [normalize_text(cell.text) for cell in row.cells]
|
||||
cells = [cell for cell in cells if cell]
|
||||
if cells:
|
||||
chunks.append(" | ".join(cells))
|
||||
|
||||
if shape.shape_type == MSO_SHAPE_TYPE.GROUP:
|
||||
for subshape in shape.shapes:
|
||||
chunks.extend(iter_shape_text(subshape))
|
||||
|
||||
return chunks
|
||||
|
||||
|
||||
def extract_pptx_to_md(pptx_path: Path, output_path: Path) -> None:
|
||||
prs = Presentation(str(pptx_path))
|
||||
parts: list[str] = [f"# {pptx_path.stem}", ""]
|
||||
|
||||
for index, slide in enumerate(prs.slides, start=1):
|
||||
title = ""
|
||||
parts.append(f"## Slide {index}")
|
||||
parts.append("")
|
||||
|
||||
if slide.shapes.title and slide.shapes.title.text:
|
||||
title = normalize_text(slide.shapes.title.text)
|
||||
if title:
|
||||
parts.append(f"### {title}")
|
||||
parts.append("")
|
||||
|
||||
seen: set[str] = set()
|
||||
collected = []
|
||||
|
||||
for shape in slide.shapes:
|
||||
for chunk in iter_shape_text(shape):
|
||||
if title and chunk == title:
|
||||
continue
|
||||
if chunk and chunk not in seen:
|
||||
seen.add(chunk)
|
||||
collected.append(chunk)
|
||||
|
||||
if collected:
|
||||
parts.extend(f"- {chunk}" for chunk in collected)
|
||||
else:
|
||||
parts.append("[No extractable text]")
|
||||
|
||||
parts.append("")
|
||||
|
||||
output_path.write_text("\n".join(parts).strip() + "\n", encoding="utf-8")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
extract_pdf_to_md(PDF_PATH, PDF_OUTPUT)
|
||||
extract_pptx_to_md(PPTX_PATH, PPTX_OUTPUT)
|
||||
print("Wrote PDF markdown output")
|
||||
print("Wrote PPTX markdown output")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user