# -*- coding: utf-8 -*- """扫描 Bruno collection 中 docs 块内的裸 JSON 段(未包 ```json fence 的)。""" import io, os, sys ROOT = r"D:/code/crm-api-docs" sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8") def find_json_blocks(lines): """返回 docs 内裸 JSON 块 [(start, end, nearest_heading, fenced)],行号 1-based。""" blocks, in_docs = [], False heading = "" i = 0 while i < len(lines): line = lines[i] s = line.strip() if not in_docs: if s == "docs {": in_docs = True i += 1 continue if s.startswith("## "): heading = s if s == "{": # 追踪 depth depth, j = 0, i while j < len(lines): t = lines[j].strip() depth += t.count("{") - t.count("}") if depth == 0: break if depth < 0: return None # 异常,交人工 j += 1 if j >= len(lines): return None # 未闭合 fenced = i > 0 and lines[i - 1].strip() == "```json" blocks.append((i + 1, j + 1, heading, fenced)) i = j + 1 continue i += 1 return blocks total_bare = 0 for dirpath, dirnames, filenames in os.walk(ROOT): dirnames[:] = [d for d in dirnames if d not in ("environments", ".git")] for fn in sorted(filenames): if not fn.endswith(".bru") or fn == "collection.bru": continue path = os.path.join(dirpath, fn) with io.open(path, encoding="utf-8-sig") as f: lines = f.read().splitlines() generated = any("generated" in l for l in lines[:15]) blocks = find_json_blocks(lines) if blocks is None: print("UNPARSEABLE\t%s\tgenerated=%s" % (path, generated)) continue bare = [b for b in blocks if not b[3]] fenced = [b for b in blocks if b[3]] if bare or fenced: for (a, b, h, f2) in blocks: tag = "FENCED" if f2 else "BARE" print("%s\t%s\tL%d-%d\t%s" % (tag, path.replace(ROOT + "/", ""), a, b, h)) if not f2: total_bare += 1 print("---- total bare json blocks: %d" % total_bare)