procesio-cli 0.1.1__py3-none-any.whl

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 (647) hide show
  1. procesio_cli/__init__.py +18 -0
  2. procesio_cli/_cli.py +71 -0
  3. procesio_cli/agents/__init__.py +0 -0
  4. procesio_cli/agents/_lib/__init__.py +0 -0
  5. procesio_cli/agents/_lib/actiondef.py +24 -0
  6. procesio_cli/agents/_lib/errors.py +40 -0
  7. procesio_cli/agents/_lib/reversibility.py +236 -0
  8. procesio_cli/agents/_lib/toolrunner.py +141 -0
  9. procesio_cli/agents/connector-builder/CONNECTOR-BUILDER-PLAYBOOK.md +62 -0
  10. procesio_cli/agents/connector-builder/CONNECTOR-BUILDER-PROCESIO-INTEROP.md +76 -0
  11. procesio_cli/agents/connector-builder/CONNECTOR-BUILDER-TROUBLESHOOTING.md +60 -0
  12. procesio_cli/agents/connector-builder/README.md +51 -0
  13. procesio_cli/agents/connector-builder/agent.yaml +61 -0
  14. procesio_cli/agents/connector-builder/context.py +19 -0
  15. procesio_cli/agents/connector-builder/handlers/__init__.py +1 -0
  16. procesio_cli/agents/connector-builder/handlers/checklist.py +71 -0
  17. procesio_cli/agents/connector-builder/handlers/guidance.py +37 -0
  18. procesio_cli/agents/connector-builder/handlers/nextstep.py +221 -0
  19. procesio_cli/agents/connector-builder/handlers/status.py +35 -0
  20. procesio_cli/agents/connector-builder/knowledge.py +47 -0
  21. procesio_cli/agents/connector-builder/main.py +93 -0
  22. procesio_cli/agents/connector-builder/tests/conftest.py +95 -0
  23. procesio_cli/agents/connector-builder/tests/test_cba_agent.py +148 -0
  24. procesio_cli/agents/orchestrator/__init__.py +0 -0
  25. procesio_cli/agents/orchestrator/bootstraplib.py +166 -0
  26. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/00-INDEX.md +60 -0
  27. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/01-PROCESSES.md +230 -0
  28. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/02-FORMS.md +287 -0
  29. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/03-INTEGRATIONS.md +384 -0
  30. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/04-DATABASE.md +293 -0
  31. procesio_cli/agents/procesio/PROCESIO-API-RELIABILITY-DOCTRINE.md +113 -0
  32. procesio_cli/agents/procesio/PROCESIO-BEST-PRACTICES.md +316 -0
  33. procesio_cli/agents/procesio/PROCESIO-BUILD-AND-TEST-PLAYBOOK.md +217 -0
  34. procesio_cli/agents/procesio/PROCESIO-DATASTORE.md +72 -0
  35. procesio_cli/agents/procesio/PROCESIO-ENVIRONMENTS.md +62 -0
  36. procesio_cli/agents/procesio/PROCESIO-SCHEDULING.md +47 -0
  37. procesio_cli/agents/procesio/PROCESIO-VISUAL-ORGANIZATION.md +175 -0
  38. procesio_cli/agents/procesio/README.md +97 -0
  39. procesio_cli/agents/procesio/__init__.py +0 -0
  40. procesio_cli/agents/procesio/agent.yaml +73 -0
  41. procesio_cli/agents/procesio/audit.py +226 -0
  42. procesio_cli/agents/procesio/checklist.py +135 -0
  43. procesio_cli/agents/procesio/context.py +19 -0
  44. procesio_cli/agents/procesio/handlers/__init__.py +0 -0
  45. procesio_cli/agents/procesio/handlers/audit.py +39 -0
  46. procesio_cli/agents/procesio/handlers/checklist.py +34 -0
  47. procesio_cli/agents/procesio/handlers/guidance.py +36 -0
  48. procesio_cli/agents/procesio/handlers/status.py +33 -0
  49. procesio_cli/agents/procesio/handlers/verify.py +39 -0
  50. procesio_cli/agents/procesio/knowledge.py +115 -0
  51. procesio_cli/agents/procesio/main.py +89 -0
  52. procesio_cli/agents/procesio/tests/__init__.py +0 -0
  53. procesio_cli/agents/procesio/tests/conftest.py +62 -0
  54. procesio_cli/agents/procesio/tests/test_audit.py +91 -0
  55. procesio_cli/agents/procesio/tests/test_checklist.py +28 -0
  56. procesio_cli/agents/procesio/tests/test_guidance.py +78 -0
  57. procesio_cli/agents/procesio/tests/test_manifest_sync.py +48 -0
  58. procesio_cli/agents/procesio/tests/test_verify.py +134 -0
  59. procesio_cli/agents/procesio/tests/test_workspace_scope.py +97 -0
  60. procesio_cli/agents/procesio/verifylib.py +222 -0
  61. procesio_cli/dashboard/README.md +117 -0
  62. procesio_cli/dashboard/__init__.py +18 -0
  63. procesio_cli/dashboard/serve.py +98 -0
  64. procesio_cli/dashboard/server/__init__.py +1 -0
  65. procesio_cli/dashboard/server/config_schemas.py +92 -0
  66. procesio_cli/dashboard/server/google.py +103 -0
  67. procesio_cli/dashboard/server/handler.py +160 -0
  68. procesio_cli/dashboard/server/inventory.py +213 -0
  69. procesio_cli/dashboard/server/jobs.py +118 -0
  70. procesio_cli/dashboard/server/llmtest.py +181 -0
  71. procesio_cli/dashboard/server/procesio_env.py +94 -0
  72. procesio_cli/dashboard/server/routes.py +74 -0
  73. procesio_cli/dashboard/server/runner.py +150 -0
  74. procesio_cli/dashboard/server/security.py +29 -0
  75. procesio_cli/dashboard/server/setup.py +211 -0
  76. procesio_cli/dashboard/server/validate.py +152 -0
  77. procesio_cli/dashboard/tests/conftest.py +16 -0
  78. procesio_cli/dashboard/tests/test_dashboard.py +225 -0
  79. procesio_cli/dashboard/tests/test_procesio_env.py +159 -0
  80. procesio_cli/dashboard/web/actions.js +274 -0
  81. procesio_cli/dashboard/web/api.js +79 -0
  82. procesio_cli/dashboard/web/app.js +385 -0
  83. procesio_cli/dashboard/web/copilot.js +72 -0
  84. procesio_cli/dashboard/web/google.js +121 -0
  85. procesio_cli/dashboard/web/index.html +67 -0
  86. procesio_cli/dashboard/web/procesio_env.js +187 -0
  87. procesio_cli/dashboard/web/styles.css +207 -0
  88. procesio_cli/registry.py +370 -0
  89. procesio_cli/scripts/build-router.py +249 -0
  90. procesio_cli/scripts/build-tool-skill.py +202 -0
  91. procesio_cli/scripts/check-requirements.py +131 -0
  92. procesio_cli/scripts/check-skill-governance.py +174 -0
  93. procesio_cli/scripts/evaluate-skill-routing.py +217 -0
  94. procesio_cli/scripts/evaluate-skills.py +316 -0
  95. procesio_cli/scripts/get-skill.py +122 -0
  96. procesio_cli/scripts/list-skills.py +68 -0
  97. procesio_cli/scripts/list-tools.py +73 -0
  98. procesio_cli/scripts/run-agent.py +59 -0
  99. procesio_cli/scripts/run-tool.py +123 -0
  100. procesio_cli/scripts/secret_scan.py +584 -0
  101. procesio_cli/scripts/set-credential.py +126 -0
  102. procesio_cli/scripts/validate-skills.py +530 -0
  103. procesio_cli/skills/PORTFOLIO.md +134 -0
  104. procesio_cli/skills/__init__.py +6 -0
  105. procesio_cli/skills/agent-skill-engineer/SKILL.md +226 -0
  106. procesio_cli/skills/agent-skill-engineer/evals/evals.json +422 -0
  107. procesio_cli/skills/agent-skill-engineer/references/authoring-standard.md +178 -0
  108. procesio_cli/skills/agent-skill-engineer/references/decision-framework.md +107 -0
  109. procesio_cli/skills/agent-skill-engineer/references/domain-evidence-protocol.md +248 -0
  110. procesio_cli/skills/agent-skill-engineer/references/evaluation-standard.md +191 -0
  111. procesio_cli/skills/agent-skill-engineer/references/expert-lenses.md +167 -0
  112. procesio_cli/skills/agent-skill-engineer/references/field-gate-standard.md +231 -0
  113. procesio_cli/skills/agent-skill-engineer/references/optimization-protocol.md +233 -0
  114. procesio_cli/skills/agent-skill-engineer/references/optimizer-contract.md +268 -0
  115. procesio_cli/skills/agent-skill-engineer/references/portability-standard.md +99 -0
  116. procesio_cli/skills/agent-skill-engineer/references/research-basis.md +128 -0
  117. procesio_cli/skills/agent-skill-engineer/references/review-standard.md +143 -0
  118. procesio_cli/skills/agent-skill-engineer/scripts/audit_skill.py +959 -0
  119. procesio_cli/skills/agent-skill-engineer/scripts/optimize_skill.py +891 -0
  120. procesio_cli/skills/agent-skill-engineer/scripts/scaffold_skill.py +397 -0
  121. procesio_cli/skills/evals/baseline-catalog.json +14 -0
  122. procesio_cli/skills/evals/baseline-routing-v2.json +38 -0
  123. procesio_cli/skills/evals/baseline.json +37 -0
  124. procesio_cli/skills/evals/behavioral.json +367 -0
  125. procesio_cli/skills/evals/field-boundary-development-v1.json +126 -0
  126. procesio_cli/skills/evals/field-closeout-correction-development-v1.json +23 -0
  127. procesio_cli/skills/evals/field-closeout-development-v1.json +89 -0
  128. procesio_cli/skills/evals/portfolio-pressure-training-v1.json +83 -0
  129. procesio_cli/skills/evals/routing.json +363 -0
  130. procesio_cli/skills/evals/validation-baseline.json +4 -0
  131. procesio_cli/skills/procesio-cli/SKILL.md +134 -0
  132. procesio_cli/skills/procesio-cli/evals/evals.json +111 -0
  133. procesio_cli/skills/procesio-cli/evals/workflows.json +16 -0
  134. procesio_cli/skills/procesio-cli/references/connector-lifecycle.md +47 -0
  135. procesio_cli/skills/procesio-cli/references/credentials-admin.md +113 -0
  136. procesio_cli/skills/procesio-cli/references/data-verification.md +71 -0
  137. procesio_cli/skills/procesio-cli/references/documents-files.md +44 -0
  138. procesio_cli/skills/procesio-cli/references/form-e2e.md +57 -0
  139. procesio_cli/skills/procesio-cli/references/operation-contract.md +138 -0
  140. procesio_cli/skills/procesio-cli/references/process-debugging.md +65 -0
  141. procesio_cli/skills/procesio-cli/references/process-lifecycle.md +88 -0
  142. procesio_cli/skills/procesio-cli/references/schedules-webhooks.md +58 -0
  143. procesio_cli/skills/procesio-cli/references/transport-environments.md +53 -0
  144. procesio_cli/skills/procesio-cli-maintainer/SKILL.md +84 -0
  145. procesio_cli/skills/procesio-cli-maintainer/evals/evals.json +116 -0
  146. procesio_cli/skills/procesio-cli-maintainer/references/change-contract.md +34 -0
  147. procesio_cli/skills/procesio-cli-maintainer/references/mcp-compatibility.md +13 -0
  148. procesio_cli/skills/procesio-cli-maintainer/references/skill-authoring.md +51 -0
  149. procesio_cli/skills/procesio-platform-advisor/SKILL.md +82 -0
  150. procesio_cli/skills/procesio-platform-advisor/evals/evals.json +116 -0
  151. procesio_cli/skills/procesio-platform-advisor/references/capability-map.md +22 -0
  152. procesio_cli/skills/procesio-platform-advisor/references/fit-framework.md +35 -0
  153. procesio_cli/skills/procesio-platform-advisor/references/freshness-policy.md +25 -0
  154. procesio_cli/skills/procesio-platform-advisor/references/sizing-method.md +70 -0
  155. procesio_cli/skills/procesio-platform-advisor/scripts/estimate_capacity.py +99 -0
  156. procesio_cli/skills/procesio-setup/SKILL.md +180 -0
  157. procesio_cli/skills/sql-server-optimizer/SKILL.md +86 -0
  158. procesio_cli/skills/sql-server-optimizer/evals/evals.json +116 -0
  159. procesio_cli/skills/sql-server-optimizer/references/db-context.md +44 -0
  160. procesio_cli/skills/sql-server-optimizer/references/generic-mode.md +32 -0
  161. procesio_cli/skills/sql-server-optimizer/references/procesio-mode.md +40 -0
  162. procesio_cli/skills/sql-server-optimizer/references/sql-rules.md +43 -0
  163. procesio_cli/skills/sql-server-optimizer/scripts/export-indexes.sql +178 -0
  164. procesio_cli/skills/sql-server-optimizer/scripts/export-procs-and-functions.sql +118 -0
  165. procesio_cli/skills/sql-server-optimizer/scripts/export-tables.sql +367 -0
  166. procesio_cli/skills/tests/__init__.py +0 -0
  167. procesio_cli/skills/tests/test_agent_skill_engineer.py +240 -0
  168. procesio_cli/skills/tests/test_auth_failure_stop.py +25 -0
  169. procesio_cli/skills/tests/test_capacity_estimator.py +85 -0
  170. procesio_cli/skills/tests/test_field_boundary_learning.py +100 -0
  171. procesio_cli/skills/tests/test_field_closeout_learning.py +123 -0
  172. procesio_cli/skills/tests/test_field_gate_standard.py +76 -0
  173. procesio_cli/skills/tests/test_operational_playbooks.py +51 -0
  174. procesio_cli/skills/tests/test_portfolio_pressure_training.py +35 -0
  175. procesio_cli/skills/tests/test_process_lifecycle_single_run.py +25 -0
  176. procesio_cli/skills/tests/test_skill_evaluator.py +67 -0
  177. procesio_cli/skills/tests/test_skill_optimizer.py +473 -0
  178. procesio_cli/skills/tests/test_skill_portfolio_review.py +70 -0
  179. procesio_cli/skills/tests/test_skill_release_binding.py +204 -0
  180. procesio_cli/skills/tests/test_skill_routing.py +74 -0
  181. procesio_cli/skills/tests/test_skill_scaffold_v2.py +116 -0
  182. procesio_cli/skills/tests/test_validate_skills.py +115 -0
  183. procesio_cli/tools/__init__.py +0 -0
  184. procesio_cli/tools/_lib/README.md +119 -0
  185. procesio_cli/tools/_lib/__init__.py +0 -0
  186. procesio_cli/tools/_lib/accounting.py +120 -0
  187. procesio_cli/tools/_lib/contacts.py +544 -0
  188. procesio_cli/tools/_lib/creds.py +83 -0
  189. procesio_cli/tools/_lib/creds_backends.py +578 -0
  190. procesio_cli/tools/_lib/dbprofiles.py +147 -0
  191. procesio_cli/tools/_lib/dbquery.py +286 -0
  192. procesio_cli/tools/_lib/dbschema.py +225 -0
  193. procesio_cli/tools/_lib/io.py +54 -0
  194. procesio_cli/tools/_lib/manifest.py +297 -0
  195. procesio_cli/tools/_lib/skill_release.py +127 -0
  196. procesio_cli/tools/_lib/skill_resources.py +118 -0
  197. procesio_cli/tools/_lib/userdata.py +228 -0
  198. procesio_cli/tools/_lib/webserialize/__init__.py +16 -0
  199. procesio_cli/tools/_lib/webserialize/admin.py +61 -0
  200. procesio_cli/tools/_lib/webserialize/client.py +264 -0
  201. procesio_cli/tools/_lib/webserialize/config.py +96 -0
  202. procesio_cli/tools/_lib/webserialize/errors.py +27 -0
  203. procesio_cli/tools/_lib/webserialize/framing.py +45 -0
  204. procesio_cli/tools/_lib/webserialize/registry.py +47 -0
  205. procesio_cli/tools/_lib/webserialize/runtime.py +61 -0
  206. procesio_cli/tools/_lib/webserialize/server.py +510 -0
  207. procesio_cli/tools/_lib/websession.py +194 -0
  208. procesio_cli/tools/connector-builder/CONNECTOR-BUILDER-API-NOTES.md +91 -0
  209. procesio_cli/tools/connector-builder/README.md +101 -0
  210. procesio_cli/tools/connector-builder/SKILL.md +248 -0
  211. procesio_cli/tools/connector-builder/__init__.py +7 -0
  212. procesio_cli/tools/connector-builder/actiondef.py +24 -0
  213. procesio_cli/tools/connector-builder/client.py +251 -0
  214. procesio_cli/tools/connector-builder/errors.py +44 -0
  215. procesio_cli/tools/connector-builder/gen_manifest.py +142 -0
  216. procesio_cli/tools/connector-builder/handlers/__init__.py +1 -0
  217. procesio_cli/tools/connector-builder/handlers/admin.py +182 -0
  218. procesio_cli/tools/connector-builder/handlers/auth.py +74 -0
  219. procesio_cli/tools/connector-builder/handlers/builds.py +396 -0
  220. procesio_cli/tools/connector-builder/handlers/common.py +104 -0
  221. procesio_cli/tools/connector-builder/handlers/files.py +111 -0
  222. procesio_cli/tools/connector-builder/handlers/raw.py +38 -0
  223. procesio_cli/tools/connector-builder/handlers/telemetry.py +39 -0
  224. procesio_cli/tools/connector-builder/main.py +94 -0
  225. procesio_cli/tools/connector-builder/tests/conftest.py +146 -0
  226. procesio_cli/tools/connector-builder/tests/test_cb_client.py +86 -0
  227. procesio_cli/tools/connector-builder/tests/test_cb_dispatch.py +105 -0
  228. procesio_cli/tools/connector-builder/tests/test_cb_manifest_sync.py +76 -0
  229. procesio_cli/tools/connector-builder/tests/test_cb_wait.py +123 -0
  230. procesio_cli/tools/connector-builder/tool.yaml +671 -0
  231. procesio_cli/tools/framework-map/.gitattributes +2 -0
  232. procesio_cli/tools/framework-map/README.md +98 -0
  233. procesio_cli/tools/framework-map/SKILL.md +30 -0
  234. procesio_cli/tools/framework-map/app.js +188 -0
  235. procesio_cli/tools/framework-map/fm_builder.py +476 -0
  236. procesio_cli/tools/framework-map/fm_catalog.py +19 -0
  237. procesio_cli/tools/framework-map/fm_ro_catalog.py +94 -0
  238. procesio_cli/tools/framework-map/fm_strings.py +101 -0
  239. procesio_cli/tools/framework-map/main.py +95 -0
  240. procesio_cli/tools/framework-map/styles.css +214 -0
  241. procesio_cli/tools/framework-map/tests/conftest.py +33 -0
  242. procesio_cli/tools/framework-map/tests/test_fm_build.py +126 -0
  243. procesio_cli/tools/framework-map/tests/test_fm_manifest_sync.py +63 -0
  244. procesio_cli/tools/framework-map/tests/test_fm_store_tree.py +75 -0
  245. procesio_cli/tools/framework-map/tool.yaml +61 -0
  246. procesio_cli/tools/mysql/MOVED-TO-CENTRAL.md +29 -0
  247. procesio_cli/tools/mysql/README.md +196 -0
  248. procesio_cli/tools/mysql/SKILL.md +37 -0
  249. procesio_cli/tools/mysql/__init__.py +0 -0
  250. procesio_cli/tools/mysql/connection.py +191 -0
  251. procesio_cli/tools/mysql/main.py +487 -0
  252. procesio_cli/tools/mysql/profiles.template.json +1 -0
  253. procesio_cli/tools/mysql/schema.py +434 -0
  254. procesio_cli/tools/mysql/tests/__init__.py +0 -0
  255. procesio_cli/tools/mysql/tests/conftest.py +21 -0
  256. procesio_cli/tools/mysql/tests/test_manifest_sync.py +68 -0
  257. procesio_cli/tools/mysql/tests/test_mysql.py +201 -0
  258. procesio_cli/tools/mysql/tests/test_mysql_schema.py +337 -0
  259. procesio_cli/tools/mysql/tool.yaml +112 -0
  260. procesio_cli/tools/procesio/DTO-SUBTOOLS-NOTE.md +360 -0
  261. procesio_cli/tools/procesio/FORM-DEV-GUIDE/00-INDEX.md +67 -0
  262. procesio_cli/tools/procesio/FORM-DEV-GUIDE/01-ANATOMY.md +209 -0
  263. procesio_cli/tools/procesio/FORM-DEV-GUIDE/02-CODE-INJECTION.md +309 -0
  264. procesio_cli/tools/procesio/FORM-DEV-GUIDE/03-DOM-CONTRACT.md +370 -0
  265. procesio_cli/tools/procesio/FORM-DEV-GUIDE/04-INTERACTION-RECIPES.md +600 -0
  266. procesio_cli/tools/procesio/FORM-DEV-GUIDE/05-STEPPER-AND-MOTION.md +426 -0
  267. procesio_cli/tools/procesio/FORM-DEV-GUIDE/06-PROCESS-INTEGRATION.md +347 -0
  268. procesio_cli/tools/procesio/FORM-DEV-GUIDE/07-DEPLOY-WORKFLOW.md +294 -0
  269. procesio_cli/tools/procesio/FORM-DEV-GUIDE/08-PITFALLS.md +569 -0
  270. procesio_cli/tools/procesio/FORM-DEV-GUIDE/09-NAVIGATION-AND-HOSTING.md +308 -0
  271. procesio_cli/tools/procesio/PHASE4-E2E-NOTES.md +594 -0
  272. procesio_cli/tools/procesio/PROCESIO-API-CORRECTIONS.md +295 -0
  273. procesio_cli/tools/procesio/PROCESIO-API-NOTES.md +6976 -0
  274. procesio_cli/tools/procesio/PROCESIO-AUTH-NOTES.md +226 -0
  275. procesio_cli/tools/procesio/PROCESIO-CARD-BUILD-NOTES.md +183 -0
  276. procesio_cli/tools/procesio/PROCESIO-CONNECTORS-NOTES.md +141 -0
  277. procesio_cli/tools/procesio/PROCESIO-CUSTOM-ACTION-NOTES.md +179 -0
  278. procesio_cli/tools/procesio/PROCESIO-DOCS-FIX-REPORT.md +123 -0
  279. procesio_cli/tools/procesio/PROCESIO-ENVIRONMENTS-NOTES.md +94 -0
  280. procesio_cli/tools/procesio/PROCESIO-FE-VALIDATION-NOTES.md +107 -0
  281. procesio_cli/tools/procesio/PROCESIO-FOREACH-NOTES.md +199 -0
  282. procesio_cli/tools/procesio/PROCESIO-FORM-API-HANG-NOTE.md +101 -0
  283. procesio_cli/tools/procesio/PROCESIO-FORM-SUBMISSION-NOTES.md +172 -0
  284. procesio_cli/tools/procesio/PROCESIO-HTML-TO-DOCX-NOTES.md +110 -0
  285. procesio_cli/tools/procesio/PROCESIO-INSTANCE-HISTORY-NOTES.md +242 -0
  286. procesio_cli/tools/procesio/PROCESIO-METERING-NOTES.md +201 -0
  287. procesio_cli/tools/procesio/PROCESIO-NODE-CODE-NOTES.md +279 -0
  288. procesio_cli/tools/procesio/PROCESIO-NODE-MODULE-WHITELIST.md +113 -0
  289. procesio_cli/tools/procesio/PROCESIO-PYTHON-ACTION-NOTES.md +165 -0
  290. procesio_cli/tools/procesio/PROCESIO-QUERY-STORE-NOTES.md +826 -0
  291. procesio_cli/tools/procesio/PROCESIO-RECONCILIATION-PATTERNS.md +104 -0
  292. procesio_cli/tools/procesio/PROCESIO-RESOURCE-MODEL-NOTES.md +1100 -0
  293. procesio_cli/tools/procesio/PROCESIO-SEND-EMAIL-CRED-OPTIONALITY.md +45 -0
  294. procesio_cli/tools/procesio/PROCESIO-SEND-EMAIL-NOTES.md +252 -0
  295. procesio_cli/tools/procesio/PROCESIO-SQL-ACTIONS-NOTES.md +284 -0
  296. procesio_cli/tools/procesio/PROCESIO-USAGE-GUIDE.md +219 -0
  297. procesio_cli/tools/procesio/README.md +341 -0
  298. procesio_cli/tools/procesio/SCHEDULE-INPUT-SECURITY-NOTES.md +63 -0
  299. procesio_cli/tools/procesio/SKILL.md +694 -0
  300. procesio_cli/tools/procesio/__init__.py +1 -0
  301. procesio_cli/tools/procesio/actiondef.py +27 -0
  302. procesio_cli/tools/procesio/assets/html2docx/html2docx.js +2155 -0
  303. procesio_cli/tools/procesio/auth.py +354 -0
  304. procesio_cli/tools/procesio/autogen.py +121 -0
  305. procesio_cli/tools/procesio/client.py +355 -0
  306. procesio_cli/tools/procesio/config.py +96 -0
  307. procesio_cli/tools/procesio/data/endpoints.json +2901 -0
  308. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/01-authentication.md +180 -0
  309. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/02-conventions.md +116 -0
  310. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/ANONYMOUS-SURFACE.md +51 -0
  311. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/README.md +104 -0
  312. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/SYMBOL-INDEX.md +444 -0
  313. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/03-auth-users-workspaces.md +731 -0
  314. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/04-processes.md +913 -0
  315. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/05-actions.md +605 -0
  316. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/06-files.md +237 -0
  317. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/07-forms-documents.md +985 -0
  318. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/08-credentials.md +532 -0
  319. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/09-datastore-datatypes.md +830 -0
  320. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/10-custom-urls.md +319 -0
  321. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/11-subscriptions-resources-analytics.md +455 -0
  322. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/12-webhooks-notifications-misc.md +519 -0
  323. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/13-realtime-signalr.md +153 -0
  324. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/99-internal-and-other-services.md +52 -0
  325. procesio_cli/tools/procesio/docs_info/FormBuilder mock.ts +5725 -0
  326. procesio_cli/tools/procesio/docs_info/Procesio Platform Actions.json +30219 -0
  327. procesio_cli/tools/procesio/docs_info/form-config-enums.ts +92 -0
  328. procesio_cli/tools/procesio/docs_info/form-theme.ts +1603 -0
  329. procesio_cli/tools/procesio/docs_info/process-validation-reference-1.md +2739 -0
  330. procesio_cli/tools/procesio/dto/__init__.py +13 -0
  331. procesio_cli/tools/procesio/dto/credential/builder.py +179 -0
  332. procesio_cli/tools/procesio/dto/credential/config.schema.json +19 -0
  333. procesio_cli/tools/procesio/dto/credential/description.md +193 -0
  334. procesio_cli/tools/procesio/dto/credential/fixtures/rest.config.json +11 -0
  335. procesio_cli/tools/procesio/dto/credential/fixtures/rest.dto.json +28 -0
  336. procesio_cli/tools/procesio/dto/credential/fixtures/rest.template.json +44 -0
  337. procesio_cli/tools/procesio/dto/credential/template.dto.json +16 -0
  338. procesio_cli/tools/procesio/dto/data/_refresh.py +147 -0
  339. procesio_cli/tools/procesio/dto/data/action_catalog.json +30825 -0
  340. procesio_cli/tools/procesio/dto/data/action_families.json +55 -0
  341. procesio_cli/tools/procesio/dto/data/platform_types.json +182 -0
  342. procesio_cli/tools/procesio/dto/datatype/builder.py +223 -0
  343. procesio_cli/tools/procesio/dto/datatype/config.schema.json +47 -0
  344. procesio_cli/tools/procesio/dto/datatype/description.md +85 -0
  345. procesio_cli/tools/procesio/dto/datatype/fixtures/customer.config.json +41 -0
  346. procesio_cli/tools/procesio/dto/datatype/fixtures/customer.dto.json +164 -0
  347. procesio_cli/tools/procesio/dto/datatype/template.dto.json +37 -0
  348. procesio_cli/tools/procesio/dto/document/builder.py +193 -0
  349. procesio_cli/tools/procesio/dto/document/config.schema.json +33 -0
  350. procesio_cli/tools/procesio/dto/document/description.md +124 -0
  351. procesio_cli/tools/procesio/dto/document/fixtures/invoice.config.json +16 -0
  352. procesio_cli/tools/procesio/dto/document/fixtures/invoice.dto.json +32 -0
  353. procesio_cli/tools/procesio/dto/document/template.dto.json +14 -0
  354. procesio_cli/tools/procesio/dto/form/FORM-STYLING-NOTES.md +142 -0
  355. procesio_cli/tools/procesio/dto/form/GOLDEN-DRIFT-NOTES.md +72 -0
  356. procesio_cli/tools/procesio/dto/form/RUN-PROCESS-RESULT-NOTES.md +80 -0
  357. procesio_cli/tools/procesio/dto/form/addelement.py +277 -0
  358. procesio_cli/tools/procesio/dto/form/builder.py +1009 -0
  359. procesio_cli/tools/procesio/dto/form/capture_goldens.py +106 -0
  360. procesio_cli/tools/procesio/dto/form/code_cipher.py +67 -0
  361. procesio_cli/tools/procesio/dto/form/config.schema.json +76 -0
  362. procesio_cli/tools/procesio/dto/form/data_shell.json +1 -0
  363. procesio_cli/tools/procesio/dto/form/description.md +346 -0
  364. procesio_cli/tools/procesio/dto/form/elements/approval.json +259 -0
  365. procesio_cli/tools/procesio/dto/form/elements/assignee.json +137 -0
  366. procesio_cli/tools/procesio/dto/form/elements/button.json +125 -0
  367. procesio_cli/tools/procesio/dto/form/elements/chart.json +341 -0
  368. procesio_cli/tools/procesio/dto/form/elements/chat.json +199 -0
  369. procesio_cli/tools/procesio/dto/form/elements/checkbox.json +153 -0
  370. procesio_cli/tools/procesio/dto/form/elements/column.json +77 -0
  371. procesio_cli/tools/procesio/dto/form/elements/columns.json +78 -0
  372. procesio_cli/tools/procesio/dto/form/elements/datetime-input.json +304 -0
  373. procesio_cli/tools/procesio/dto/form/elements/divider.json +54 -0
  374. procesio_cli/tools/procesio/dto/form/elements/dropdown.json +130 -0
  375. procesio_cli/tools/procesio/dto/form/elements/dynamic-table-row.json +253 -0
  376. procesio_cli/tools/procesio/dto/form/elements/file-upload.json +196 -0
  377. procesio_cli/tools/procesio/dto/form/elements/file-viewer.json +169 -0
  378. procesio_cli/tools/procesio/dto/form/elements/heading.json +79 -0
  379. procesio_cli/tools/procesio/dto/form/elements/icon.json +107 -0
  380. procesio_cli/tools/procesio/dto/form/elements/image.json +174 -0
  381. procesio_cli/tools/procesio/dto/form/elements/input.json +206 -0
  382. procesio_cli/tools/procesio/dto/form/elements/list.json +202 -0
  383. procesio_cli/tools/procesio/dto/form/elements/number-input.json +202 -0
  384. procesio_cli/tools/procesio/dto/form/elements/paragraph.json +79 -0
  385. procesio_cli/tools/procesio/dto/form/elements/radiobox.json +174 -0
  386. procesio_cli/tools/procesio/dto/form/elements/section.json +114 -0
  387. procesio_cli/tools/procesio/dto/form/elements/select.json +217 -0
  388. procesio_cli/tools/procesio/dto/form/elements/side-panel.json +146 -0
  389. procesio_cli/tools/procesio/dto/form/elements/signature-pad.json +141 -0
  390. procesio_cli/tools/procesio/dto/form/elements/static-table-row.json +84 -0
  391. procesio_cli/tools/procesio/dto/form/elements/step.json +105 -0
  392. procesio_cli/tools/procesio/dto/form/elements/stepper.json +126 -0
  393. procesio_cli/tools/procesio/dto/form/elements/tab.json +77 -0
  394. procesio_cli/tools/procesio/dto/form/elements/table.json +279 -0
  395. procesio_cli/tools/procesio/dto/form/elements/tabs.json +114 -0
  396. procesio_cli/tools/procesio/dto/form/elements/textarea.json +213 -0
  397. procesio_cli/tools/procesio/dto/form/enum_map.json +68 -0
  398. procesio_cli/tools/procesio/dto/form/fieldpath.py +284 -0
  399. procesio_cli/tools/procesio/dto/form/fixtures/reg.config.json +32 -0
  400. procesio_cli/tools/procesio/dto/form/fixtures/reg.elements.json +638 -0
  401. procesio_cli/tools/procesio/dto/form/sync_from_mock.py +386 -0
  402. procesio_cli/tools/procesio/dto/framework.py +125 -0
  403. procesio_cli/tools/procesio/dto/process/builder.py +1991 -0
  404. procesio_cli/tools/procesio/dto/process/config.schema.json +159 -0
  405. procesio_cli/tools/procesio/dto/process/description.md +218 -0
  406. procesio_cli/tools/procesio/dto/process/fixtures/greet.config.json +32 -0
  407. procesio_cli/tools/procesio/dto/process/fixtures/greet.dto.json +317 -0
  408. procesio_cli/tools/procesio/dto/process/naming.py +305 -0
  409. procesio_cli/tools/procesio/dto/process/normalize.py +74 -0
  410. procesio_cli/tools/procesio/dto/process/template.dto.json +32 -0
  411. procesio_cli/tools/procesio/dto/refdata.py +87 -0
  412. procesio_cli/tools/procesio/dto/registry.py +27 -0
  413. procesio_cli/tools/procesio/dto/webhook/builder.py +142 -0
  414. procesio_cli/tools/procesio/dto/webhook/config.schema.json +25 -0
  415. procesio_cli/tools/procesio/dto/webhook/description.md +92 -0
  416. procesio_cli/tools/procesio/dto/webhook/fixtures/order.config.json +10 -0
  417. procesio_cli/tools/procesio/dto/webhook/fixtures/order.dto.json +25 -0
  418. procesio_cli/tools/procesio/dto/webhook/template.dto.json +14 -0
  419. procesio_cli/tools/procesio/environments.py +264 -0
  420. procesio_cli/tools/procesio/errors.py +166 -0
  421. procesio_cli/tools/procesio/flowmodel/README.md +37 -0
  422. procesio_cli/tools/procesio/flowmodel/__init__.py +14 -0
  423. procesio_cli/tools/procesio/flowmodel/digest.py +223 -0
  424. procesio_cli/tools/procesio/flowmodel/families.py +34 -0
  425. procesio_cli/tools/procesio/flowmodel/fevalidation.py +1098 -0
  426. procesio_cli/tools/procesio/flowmodel/formdigest.py +232 -0
  427. procesio_cli/tools/procesio/flowmodel/inspect.py +78 -0
  428. procesio_cli/tools/procesio/flowmodel/model.py +82 -0
  429. procesio_cli/tools/procesio/flowmodel/nodeparam.py +871 -0
  430. procesio_cli/tools/procesio/flowmodel/reader.py +191 -0
  431. procesio_cli/tools/procesio/flowmodel/sqlparam.py +410 -0
  432. procesio_cli/tools/procesio/form_code_keys.py +50 -0
  433. procesio_cli/tools/procesio/formlint.py +292 -0
  434. procesio_cli/tools/procesio/gen_manifest.py +118 -0
  435. procesio_cli/tools/procesio/handlers/__init__.py +1 -0
  436. procesio_cli/tools/procesio/handlers/auth_actions.py +103 -0
  437. procesio_cli/tools/procesio/handlers/catalog.py +147 -0
  438. procesio_cli/tools/procesio/handlers/common.py +90 -0
  439. procesio_cli/tools/procesio/handlers/customaction_ops.py +146 -0
  440. procesio_cli/tools/procesio/handlers/datastore_ops.py +482 -0
  441. procesio_cli/tools/procesio/handlers/datatype_ops.py +275 -0
  442. procesio_cli/tools/procesio/handlers/dto_actions.py +258 -0
  443. procesio_cli/tools/procesio/handlers/environment_admin.py +146 -0
  444. procesio_cli/tools/procesio/handlers/fevalidate.py +236 -0
  445. procesio_cli/tools/procesio/handlers/files.py +141 -0
  446. procesio_cli/tools/procesio/handlers/flowgraph.py +229 -0
  447. procesio_cli/tools/procesio/handlers/flowlint.py +269 -0
  448. procesio_cli/tools/procesio/handlers/form_chains.py +336 -0
  449. procesio_cli/tools/procesio/handlers/form_code.py +277 -0
  450. procesio_cli/tools/procesio/handlers/form_element.py +199 -0
  451. procesio_cli/tools/procesio/handlers/form_events.py +441 -0
  452. procesio_cli/tools/procesio/handlers/form_update.py +270 -0
  453. procesio_cli/tools/procesio/handlers/formprocess.py +211 -0
  454. procesio_cli/tools/procesio/handlers/generic.py +135 -0
  455. procesio_cli/tools/procesio/handlers/layout.py +137 -0
  456. procesio_cli/tools/procesio/handlers/nodeparams.py +1018 -0
  457. procesio_cli/tools/procesio/handlers/process_layout.py +189 -0
  458. procesio_cli/tools/procesio/handlers/process_naming.py +213 -0
  459. procesio_cli/tools/procesio/handlers/processes.py +416 -0
  460. procesio_cli/tools/procesio/handlers/profile_admin.py +184 -0
  461. procesio_cli/tools/procesio/handlers/resource_ops.py +447 -0
  462. procesio_cli/tools/procesio/handlers/schedules.py +320 -0
  463. procesio_cli/tools/procesio/handlers/sqlactions.py +232 -0
  464. procesio_cli/tools/procesio/handlers/transport.py +463 -0
  465. procesio_cli/tools/procesio/handlers/usageguide.py +222 -0
  466. procesio_cli/tools/procesio/layout/README.md +196 -0
  467. procesio_cli/tools/procesio/layout/__init__.py +11 -0
  468. procesio_cli/tools/procesio/layout/adapter.py +736 -0
  469. procesio_cli/tools/procesio/layout/cycles.py +186 -0
  470. procesio_cli/tools/procesio/layout/dispatch.py +39 -0
  471. procesio_cli/tools/procesio/layout/elk/elk_runner.mjs +50 -0
  472. procesio_cli/tools/procesio/layout/elk/package-lock.json +21 -0
  473. procesio_cli/tools/procesio/layout/elk/package.json +11 -0
  474. procesio_cli/tools/procesio/layout/elk_engine.py +568 -0
  475. procesio_cli/tools/procesio/layout/engine.py +1311 -0
  476. procesio_cli/tools/procesio/layout/report.py +187 -0
  477. procesio_cli/tools/procesio/main.py +179 -0
  478. procesio_cli/tools/procesio/profiles.py +193 -0
  479. procesio_cli/tools/procesio/reliability.py +193 -0
  480. procesio_cli/tools/procesio/sqlformat.py +167 -0
  481. procesio_cli/tools/procesio/swagger.py +51 -0
  482. procesio_cli/tools/procesio/tests/__init__.py +0 -0
  483. procesio_cli/tools/procesio/tests/conftest.py +129 -0
  484. procesio_cli/tools/procesio/tests/test_auth.py +200 -0
  485. procesio_cli/tools/procesio/tests/test_autogen.py +78 -0
  486. procesio_cli/tools/procesio/tests/test_builder_attrpath_sqlbind.py +180 -0
  487. procesio_cli/tools/procesio/tests/test_builder_custom_action_catalog.py +72 -0
  488. procesio_cli/tools/procesio/tests/test_client.py +114 -0
  489. procesio_cli/tools/procesio/tests/test_client_reliability.py +139 -0
  490. procesio_cli/tools/procesio/tests/test_customaction.py +103 -0
  491. procesio_cli/tools/procesio/tests/test_customaction_test.py +80 -0
  492. procesio_cli/tools/procesio/tests/test_cycles.py +69 -0
  493. procesio_cli/tools/procesio/tests/test_datastore.py +378 -0
  494. procesio_cli/tools/procesio/tests/test_datastore_node.py +94 -0
  495. procesio_cli/tools/procesio/tests/test_dispatch.py +170 -0
  496. procesio_cli/tools/procesio/tests/test_document_page_size.py +19 -0
  497. procesio_cli/tools/procesio/tests/test_dto.py +734 -0
  498. procesio_cli/tools/procesio/tests/test_edit_dryrun_preview.py +96 -0
  499. procesio_cli/tools/procesio/tests/test_elk_layout.py +221 -0
  500. procesio_cli/tools/procesio/tests/test_environments.py +214 -0
  501. procesio_cli/tools/procesio/tests/test_fevalidate_gate.py +104 -0
  502. procesio_cli/tools/procesio/tests/test_fevalidation.py +317 -0
  503. procesio_cli/tools/procesio/tests/test_fieldpath_variables.py +87 -0
  504. procesio_cli/tools/procesio/tests/test_files.py +72 -0
  505. procesio_cli/tools/procesio/tests/test_flow_digest.py +202 -0
  506. procesio_cli/tools/procesio/tests/test_flowlint.py +114 -0
  507. procesio_cli/tools/procesio/tests/test_flowmodel.py +158 -0
  508. procesio_cli/tools/procesio/tests/test_form_add_element.py +256 -0
  509. procesio_cli/tools/procesio/tests/test_form_approval_gaps.py +319 -0
  510. procesio_cli/tools/procesio/tests/test_form_auto_names.py +60 -0
  511. procesio_cli/tools/procesio/tests/test_form_chains.py +217 -0
  512. procesio_cli/tools/procesio/tests/test_form_code_actions.py +188 -0
  513. procesio_cli/tools/procesio/tests/test_form_code_keys.py +92 -0
  514. procesio_cli/tools/procesio/tests/test_form_code_style.py +178 -0
  515. procesio_cli/tools/procesio/tests/test_form_delete_element.py +99 -0
  516. procesio_cli/tools/procesio/tests/test_form_element_config.py +141 -0
  517. procesio_cli/tools/procesio/tests/test_form_event_maps.py +135 -0
  518. procesio_cli/tools/procesio/tests/test_form_event_ops.py +376 -0
  519. procesio_cli/tools/procesio/tests/test_form_event_replace.py +86 -0
  520. procesio_cli/tools/procesio/tests/test_form_events.py +92 -0
  521. procesio_cli/tools/procesio/tests/test_form_parity.py +171 -0
  522. procesio_cli/tools/procesio/tests/test_form_select_source.py +74 -0
  523. procesio_cli/tools/procesio/tests/test_form_sync.py +35 -0
  524. procesio_cli/tools/procesio/tests/test_form_update.py +133 -0
  525. procesio_cli/tools/procesio/tests/test_formlint.py +155 -0
  526. procesio_cli/tools/procesio/tests/test_formlint_css_scope.py +38 -0
  527. procesio_cli/tools/procesio/tests/test_formlint_field_names.py +83 -0
  528. procesio_cli/tools/procesio/tests/test_guards.py +110 -0
  529. procesio_cli/tools/procesio/tests/test_hidden_setting_types.py +39 -0
  530. procesio_cli/tools/procesio/tests/test_html2docx_asset.py +132 -0
  531. procesio_cli/tools/procesio/tests/test_key_handle_terminology.py +45 -0
  532. procesio_cli/tools/procesio/tests/test_layout.py +574 -0
  533. procesio_cli/tools/procesio/tests/test_layout_report.py +88 -0
  534. procesio_cli/tools/procesio/tests/test_manifest_sync.py +68 -0
  535. procesio_cli/tools/procesio/tests/test_nodedelete.py +151 -0
  536. procesio_cli/tools/procesio/tests/test_nodeparam.py +826 -0
  537. procesio_cli/tools/procesio/tests/test_normalize.py +70 -0
  538. procesio_cli/tools/procesio/tests/test_payload_docs.py +86 -0
  539. procesio_cli/tools/procesio/tests/test_process_action_naming.py +170 -0
  540. procesio_cli/tools/procesio/tests/test_process_call_api_seed.py +46 -0
  541. procesio_cli/tools/procesio/tests/test_process_ext.py +373 -0
  542. procesio_cli/tools/procesio/tests/test_process_invariants.py +183 -0
  543. procesio_cli/tools/procesio/tests/test_process_layout.py +117 -0
  544. procesio_cli/tools/procesio/tests/test_process_naming.py +188 -0
  545. procesio_cli/tools/procesio/tests/test_process_query_store.py +172 -0
  546. procesio_cli/tools/procesio/tests/test_processinfo_variable.py +56 -0
  547. procesio_cli/tools/procesio/tests/test_profiles.py +127 -0
  548. procesio_cli/tools/procesio/tests/test_put_projects.py +41 -0
  549. procesio_cli/tools/procesio/tests/test_reliability.py +107 -0
  550. procesio_cli/tools/procesio/tests/test_removal_gate.py +95 -0
  551. procesio_cli/tools/procesio/tests/test_resource_ops.py +173 -0
  552. procesio_cli/tools/procesio/tests/test_save_validity.py +207 -0
  553. procesio_cli/tools/procesio/tests/test_schedule_cron_shape.py +111 -0
  554. procesio_cli/tools/procesio/tests/test_schedules.py +309 -0
  555. procesio_cli/tools/procesio/tests/test_sqlconvert.py +234 -0
  556. procesio_cli/tools/procesio/tests/test_sqlformat.py +83 -0
  557. procesio_cli/tools/procesio/tests/test_sqlparam.py +187 -0
  558. procesio_cli/tools/procesio/tests/test_superseded_actions.py +54 -0
  559. procesio_cli/tools/procesio/tests/test_surgical_concurrency.py +156 -0
  560. procesio_cli/tools/procesio/tests/test_tier4.py +123 -0
  561. procesio_cli/tools/procesio/tests/test_transport.py +147 -0
  562. procesio_cli/tools/procesio/tests/test_transport_data_stores.py +168 -0
  563. procesio_cli/tools/procesio/tests/test_transport_mapper_repair.py +150 -0
  564. procesio_cli/tools/procesio/tests/test_transport_webhook_strip.py +253 -0
  565. procesio_cli/tools/procesio/tests/test_usage_guide.py +96 -0
  566. procesio_cli/tools/procesio/tool.yaml +12486 -0
  567. procesio_cli/tools/sqlserver/MOVED-TO-CENTRAL.md +29 -0
  568. procesio_cli/tools/sqlserver/README.md +192 -0
  569. procesio_cli/tools/sqlserver/SKILL.md +37 -0
  570. procesio_cli/tools/sqlserver/SQLSERVER-SCHEMA-NOTES.md +284 -0
  571. procesio_cli/tools/sqlserver/__init__.py +0 -0
  572. procesio_cli/tools/sqlserver/connection.py +242 -0
  573. procesio_cli/tools/sqlserver/main.py +521 -0
  574. procesio_cli/tools/sqlserver/profiles.template.json +1 -0
  575. procesio_cli/tools/sqlserver/schema.py +600 -0
  576. procesio_cli/tools/sqlserver/tests/__init__.py +0 -0
  577. procesio_cli/tools/sqlserver/tests/conftest.py +21 -0
  578. procesio_cli/tools/sqlserver/tests/test_connection.py +75 -0
  579. procesio_cli/tools/sqlserver/tests/test_dbprofiles.py +92 -0
  580. procesio_cli/tools/sqlserver/tests/test_dbquery.py +220 -0
  581. procesio_cli/tools/sqlserver/tests/test_manifest_sync.py +68 -0
  582. procesio_cli/tools/sqlserver/tests/test_sqlserver.py +326 -0
  583. procesio_cli/tools/sqlserver/tests/test_sqlserver_schema.py +488 -0
  584. procesio_cli/tools/sqlserver/tool.yaml +123 -0
  585. procesio_cli/tools/web/README.md +381 -0
  586. procesio_cli/tools/web/SKILL.md +37 -0
  587. procesio_cli/tools/web/WEB-AUTOMATION-NOTES.md +277 -0
  588. procesio_cli/tools/web/__init__.py +21 -0
  589. procesio_cli/tools/web/actiondef.py +24 -0
  590. procesio_cli/tools/web/api.py +444 -0
  591. procesio_cli/tools/web/brokered.py +107 -0
  592. procesio_cli/tools/web/driver.py +839 -0
  593. procesio_cli/tools/web/drivercontract.py +44 -0
  594. procesio_cli/tools/web/errors.py +54 -0
  595. procesio_cli/tools/web/handlers/__init__.py +1 -0
  596. procesio_cli/tools/web/handlers/archive.py +367 -0
  597. procesio_cli/tools/web/handlers/browse.py +182 -0
  598. procesio_cli/tools/web/handlers/contacts.py +74 -0
  599. procesio_cli/tools/web/handlers/sessmgmt.py +120 -0
  600. procesio_cli/tools/web/main.py +128 -0
  601. procesio_cli/tools/web/sessions.py +253 -0
  602. procesio_cli/tools/web/steps.py +162 -0
  603. procesio_cli/tools/web/tests/__init__.py +0 -0
  604. procesio_cli/tools/web/tests/conftest.py +197 -0
  605. procesio_cli/tools/web/tests/test_api.py +330 -0
  606. procesio_cli/tools/web/tests/test_archive.py +190 -0
  607. procesio_cli/tools/web/tests/test_brokered.py +138 -0
  608. procesio_cli/tools/web/tests/test_dispatch.py +132 -0
  609. procesio_cli/tools/web/tests/test_errors.py +60 -0
  610. procesio_cli/tools/web/tests/test_manifest_sync.py +76 -0
  611. procesio_cli/tools/web/tests/test_page_contacts.py +68 -0
  612. procesio_cli/tools/web/tests/test_sessions.py +145 -0
  613. procesio_cli/tools/web/tests/test_steps.py +210 -0
  614. procesio_cli/tools/web/tool.yaml +184 -0
  615. procesio_cli/tools/xlsx/README.md +34 -0
  616. procesio_cli/tools/xlsx/SKILL.md +28 -0
  617. procesio_cli/tools/xlsx/__init__.py +0 -0
  618. procesio_cli/tools/xlsx/main.py +129 -0
  619. procesio_cli/tools/xlsx/reader.py +91 -0
  620. procesio_cli/tools/xlsx/tests/__init__.py +0 -0
  621. procesio_cli/tools/xlsx/tests/conftest.py +39 -0
  622. procesio_cli/tools/xlsx/tests/test_xlsx.py +103 -0
  623. procesio_cli/tools/xlsx/tool.yaml +30 -0
  624. procesio_cli/webplatform/aat_mcp/AAT-MCP-NOTES.md +244 -0
  625. procesio_cli/webplatform/aat_mcp/README.md +78 -0
  626. procesio_cli/webplatform/aat_mcp/bridge.py +705 -0
  627. procesio_cli/webplatform/aat_mcp/chat_server.py +194 -0
  628. procesio_cli/webplatform/aat_mcp/chat_surface.snapshot.json +668 -0
  629. procesio_cli/webplatform/aat_mcp/chat_surface.yaml +372 -0
  630. procesio_cli/webplatform/aat_mcp/gate.py +68 -0
  631. procesio_cli/webplatform/aat_mcp/http_server.py +139 -0
  632. procesio_cli/webplatform/aat_mcp/protocol.py +175 -0
  633. procesio_cli/webplatform/aat_mcp/server.py +306 -0
  634. procesio_cli/webplatform/aat_mcp/tests/conftest.py +8 -0
  635. procesio_cli/webplatform/aat_mcp/tests/test_aat_mcp.py +255 -0
  636. procesio_cli/webplatform/aat_mcp/tests/test_chat_surface.py +247 -0
  637. procesio_cli/webplatform/aat_mcp/tests/test_discovery.py +489 -0
  638. procesio_cli/webplatform/aat_mcp/tests/test_multiuser.py +86 -0
  639. procesio_cli/webplatform/aat_mcp/tests/test_progressive_discovery.py +89 -0
  640. procesio_cli/webplatform/aat_mcp/tests/test_protocol.py +180 -0
  641. procesio_cli/webplatform/aat_mcp/tests/test_skill_discovery.py +23 -0
  642. procesio_cli-0.1.1.dist-info/METADATA +467 -0
  643. procesio_cli-0.1.1.dist-info/RECORD +647 -0
  644. procesio_cli-0.1.1.dist-info/WHEEL +4 -0
  645. procesio_cli-0.1.1.dist-info/entry_points.txt +7 -0
  646. procesio_cli-0.1.1.dist-info/licenses/LICENSE +201 -0
  647. procesio_cli-0.1.1.dist-info/licenses/NOTICE +5 -0
@@ -0,0 +1,2155 @@
1
+ // HTML -> DOCX (Word) converter for the PROCESIO Node action.
2
+ // Pure JavaScript: the sandbox has no require of fs/zlib/buffer, so base64, UTF-8, CRC-32 and a
3
+ // STORED zip are implemented here. Pipeline: parse HTML -> CSS cascade (style blocks, inline
4
+ // style, presentational attributes, a browser default sheet) -> layout into Word paragraphs and
5
+ // tables -> WordprocessingML -> .docx package -> base64.
6
+ var H2D = (function () {
7
+ 'use strict';
8
+
9
+ // ======================= 1. bytes: base64, UTF-8, CRC-32, zip =======================
10
+ var B64C = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
11
+ var B64R = new Int16Array(256);
12
+ (function () {
13
+ var i;
14
+ for (i = 0; i < 256; i++) B64R[i] = -1;
15
+ for (i = 0; i < 64; i++) B64R[B64C.charCodeAt(i)] = i;
16
+ B64R[45] = 62; B64R[95] = 63; // url-safe alphabet
17
+ })();
18
+
19
+ function b64decode(s) {
20
+ s = String(s == null ? '' : s);
21
+ var n = s.length, out = new Uint8Array(((n * 3) >> 2) + 4), o = 0, acc = 0, bits = 0;
22
+ for (var i = 0; i < n; i++) {
23
+ var c = s.charCodeAt(i);
24
+ if (c === 61) break;
25
+ var v = c < 256 ? B64R[c] : -1;
26
+ if (v < 0) continue;
27
+ acc = ((acc << 6) | v) & 0xFFFFFF; bits += 6;
28
+ if (bits >= 8) { bits -= 8; out[o++] = (acc >> bits) & 255; }
29
+ }
30
+ return out.subarray(0, o);
31
+ }
32
+
33
+ function b64encode(b) {
34
+ var parts = [], n = b.length, CH = 3 * 8192;
35
+ for (var i = 0; i < n; i += CH) {
36
+ var end = Math.min(i + CH, n), arr = [];
37
+ for (var j = i; j < end; j += 3) {
38
+ var a = b[j], has1 = j + 1 < end, has2 = j + 2 < end;
39
+ var t = (a << 16) | ((has1 ? b[j + 1] : 0) << 8) | (has2 ? b[j + 2] : 0);
40
+ arr.push(B64C.charAt((t >> 18) & 63) + B64C.charAt((t >> 12) & 63) +
41
+ (has1 ? B64C.charAt((t >> 6) & 63) : '=') + (has2 ? B64C.charAt(t & 63) : '='));
42
+ }
43
+ parts.push(arr.join(''));
44
+ }
45
+ return parts.join('');
46
+ }
47
+
48
+ var CP1252 = [8364, 0, 8218, 402, 8222, 8230, 8224, 8225, 710, 8240, 352, 8249, 338, 0, 381, 0,
49
+ 0, 8216, 8217, 8220, 8221, 8226, 8211, 8212, 732, 8482, 353, 8250, 339, 0, 382, 376];
50
+
51
+ function fromCP(cp) {
52
+ if (cp > 0xFFFF) { cp -= 0x10000; return String.fromCharCode(0xD800 + (cp >> 10), 0xDC00 + (cp & 1023)); }
53
+ return String.fromCharCode(cp);
54
+ }
55
+
56
+ function decodeUtf16(b, start, le) {
57
+ var out = [], chunk = [];
58
+ for (var i = start; i + 1 < b.length; i += 2) {
59
+ chunk.push(le ? (b[i] | (b[i + 1] << 8)) : ((b[i] << 8) | b[i + 1]));
60
+ if (chunk.length >= 8192) { out.push(String.fromCharCode.apply(null, chunk)); chunk = []; }
61
+ }
62
+ out.push(String.fromCharCode.apply(null, chunk));
63
+ return out.join('');
64
+ }
65
+
66
+ function decodeText(b) {
67
+ var n = b.length, i = 0;
68
+ if (n >= 2 && b[0] === 0xFF && b[1] === 0xFE) return decodeUtf16(b, 2, true);
69
+ if (n >= 2 && b[0] === 0xFE && b[1] === 0xFF) return decodeUtf16(b, 2, false);
70
+ if (n >= 3 && b[0] === 0xEF && b[1] === 0xBB && b[2] === 0xBF) i = 3;
71
+ else if (n >= 8) {
72
+ var z = 0, m = Math.min(n, 4000);
73
+ for (var k = 1; k < m; k += 2) if (b[k] === 0) z++;
74
+ if (z > m / 4) return decodeUtf16(b, 0, true);
75
+ }
76
+ var out = [], chunk = [];
77
+ while (i < n) {
78
+ var c = b[i++], cp;
79
+ if (c < 0x80) cp = c;
80
+ else if (c >= 0xC2 && c < 0xE0 && i < n && (b[i] & 0xC0) === 0x80) cp = ((c & 31) << 6) | (b[i++] & 63);
81
+ else if (c >= 0xE0 && c < 0xF0 && i + 1 < n && (b[i] & 0xC0) === 0x80 && (b[i + 1] & 0xC0) === 0x80) {
82
+ cp = ((c & 15) << 12) | ((b[i] & 63) << 6) | (b[i + 1] & 63); i += 2;
83
+ } else if (c >= 0xF0 && c < 0xF5 && i + 2 < n && (b[i] & 0xC0) === 0x80 && (b[i + 1] & 0xC0) === 0x80 && (b[i + 2] & 0xC0) === 0x80) {
84
+ cp = ((c & 7) << 18) | ((b[i] & 63) << 12) | ((b[i + 1] & 63) << 6) | (b[i + 2] & 63); i += 3;
85
+ } else cp = (c >= 0x80 && c < 0xA0 && CP1252[c - 0x80]) ? CP1252[c - 0x80] : c; // not UTF-8: Windows-1252
86
+ if (cp > 0xFFFF) { cp -= 0x10000; chunk.push(0xD800 + (cp >> 10), 0xDC00 + (cp & 1023)); } else chunk.push(cp);
87
+ if (chunk.length >= 8192) { out.push(String.fromCharCode.apply(null, chunk)); chunk = []; }
88
+ }
89
+ out.push(String.fromCharCode.apply(null, chunk));
90
+ return out.join('');
91
+ }
92
+
93
+ function utf8encode(s) {
94
+ var n = s.length, buf = new Uint8Array(n * 3 + 8), o = 0;
95
+ for (var i = 0; i < n; i++) {
96
+ var c = s.charCodeAt(i);
97
+ if (c < 0x80) buf[o++] = c;
98
+ else if (c < 0x800) { buf[o++] = 0xC0 | (c >> 6); buf[o++] = 0x80 | (c & 63); }
99
+ else if (c >= 0xD800 && c < 0xDC00 && i + 1 < n && (s.charCodeAt(i + 1) & 0xFC00) === 0xDC00) {
100
+ var cp = 0x10000 + ((c - 0xD800) << 10) + (s.charCodeAt(++i) - 0xDC00);
101
+ buf[o++] = 0xF0 | (cp >> 18); buf[o++] = 0x80 | ((cp >> 12) & 63);
102
+ buf[o++] = 0x80 | ((cp >> 6) & 63); buf[o++] = 0x80 | (cp & 63);
103
+ } else {
104
+ if (c >= 0xD800 && c < 0xE000) c = 0xFFFD;
105
+ buf[o++] = 0xE0 | (c >> 12); buf[o++] = 0x80 | ((c >> 6) & 63); buf[o++] = 0x80 | (c & 63);
106
+ }
107
+ }
108
+ return buf.subarray(0, o);
109
+ }
110
+
111
+ var CRC_T = (function () {
112
+ var t = new Int32Array(256);
113
+ for (var n = 0; n < 256; n++) {
114
+ var c = n;
115
+ for (var k = 0; k < 8; k++) c = (c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1);
116
+ t[n] = c;
117
+ }
118
+ return t;
119
+ })();
120
+
121
+ function crc32(b) {
122
+ var c = -1;
123
+ for (var i = 0; i < b.length; i++) c = CRC_T[(c ^ b[i]) & 255] ^ (c >>> 8);
124
+ return (c ^ -1) >>> 0;
125
+ }
126
+
127
+ // STORED (uncompressed) zip: Word reads it, and it needs no deflate.
128
+ function zipStore(files) {
129
+ var d = new Date();
130
+ var dosTime = (d.getHours() << 11) | (d.getMinutes() << 5) | (d.getSeconds() >> 1);
131
+ var dosDate = ((d.getFullYear() - 1980) << 9) | ((d.getMonth() + 1) << 5) | d.getDate();
132
+ var recs = [], total = 22, i;
133
+ for (i = 0; i < files.length; i++) {
134
+ var nm = utf8encode(files[i].name);
135
+ recs.push({ nm: nm, data: files[i].data, crc: crc32(files[i].data), off: 0 });
136
+ total += 30 + nm.length + files[i].data.length + 46 + nm.length;
137
+ }
138
+ var out = new Uint8Array(total), p = 0;
139
+ function u16(v) { out[p++] = v & 255; out[p++] = (v >>> 8) & 255; }
140
+ function u32(v) { out[p++] = v & 255; out[p++] = (v >>> 8) & 255; out[p++] = (v >>> 16) & 255; out[p++] = (v >>> 24) & 255; }
141
+ for (i = 0; i < recs.length; i++) {
142
+ var f = recs[i];
143
+ f.off = p;
144
+ u32(0x04034b50); u16(20); u16(0); u16(0); u16(dosTime); u16(dosDate);
145
+ u32(f.crc); u32(f.data.length); u32(f.data.length); u16(f.nm.length); u16(0);
146
+ out.set(f.nm, p); p += f.nm.length;
147
+ out.set(f.data, p); p += f.data.length;
148
+ }
149
+ var cd = p;
150
+ for (i = 0; i < recs.length; i++) {
151
+ var g = recs[i];
152
+ u32(0x02014b50); u16(20); u16(20); u16(0); u16(0); u16(dosTime); u16(dosDate);
153
+ u32(g.crc); u32(g.data.length); u32(g.data.length); u16(g.nm.length);
154
+ u16(0); u16(0); u16(0); u16(0); u32(0); u32(g.off);
155
+ out.set(g.nm, p); p += g.nm.length;
156
+ }
157
+ var cdSize = p - cd;
158
+ u32(0x06054b50); u16(0); u16(0); u16(recs.length); u16(recs.length); u32(cdSize); u32(cd); u16(0);
159
+ return out;
160
+ }
161
+
162
+ // ======================= 2. small helpers =======================
163
+ function toSet(s) { var o = Object.create(null); s.split(/\s+/).forEach(function (k) { if (k) o[k] = true; }); return o; }
164
+ function isSp(c) { return c === 32 || c === 9 || c === 10 || c === 13 || c === 12; }
165
+ function clamp(v, a, b) { return v < a ? a : v > b ? b : v; }
166
+ function twip(pt) { return Math.round(pt * 20); }
167
+ function xesc(s) {
168
+ return String(s).replace(/[&<>"]/g, function (c) { return c === '&' ? '&amp;' : c === '<' ? '&lt;' : c === '>' ? '&gt;' : '&quot;'; })
169
+ .replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F￾￿]/g, '')
170
+ .replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(^|[^\uD800-\uDBFF])[\uDC00-\uDFFF]/g, '$1');
171
+ }
172
+
173
+ // ======================= 3. HTML entities + parser =======================
174
+ var ENT = Object.create(null);
175
+ (function () {
176
+ var l1 = ('nbsp iexcl cent pound curren yen brvbar sect uml copy ordf laquo not shy reg macr deg plusmn sup2 sup3 ' +
177
+ 'acute micro para middot cedil sup1 ordm raquo frac14 frac12 frac34 iquest Agrave Aacute Acirc Atilde Auml Aring ' +
178
+ 'AElig Ccedil Egrave Eacute Ecirc Euml Igrave Iacute Icirc Iuml ETH Ntilde Ograve Oacute Ocirc Otilde Ouml times ' +
179
+ 'Oslash Ugrave Uacute Ucirc Uuml Yacute THORN szlig agrave aacute acirc atilde auml aring aelig ccedil egrave eacute ' +
180
+ 'ecirc euml igrave iacute icirc iuml eth ntilde ograve oacute ocirc otilde ouml divide oslash ugrave uacute ucirc ' +
181
+ 'uuml yacute thorn yuml').split(' ');
182
+ for (var i = 0; i < l1.length; i++) ENT[l1[i]] = 160 + i;
183
+ var more = 'amp:38 lt:60 gt:62 quot:34 apos:39 OElig:338 oelig:339 Scaron:352 scaron:353 Yuml:376 fnof:402 circ:710 ' +
184
+ 'tilde:732 ensp:8194 emsp:8195 thinsp:8201 zwnj:8204 zwj:8205 lrm:8206 rlm:8207 ndash:8211 mdash:8212 lsquo:8216 ' +
185
+ 'rsquo:8217 sbquo:8218 ldquo:8220 rdquo:8221 bdquo:8222 dagger:8224 Dagger:8225 bull:8226 hellip:8230 permil:8240 ' +
186
+ 'prime:8242 Prime:8243 lsaquo:8249 rsaquo:8250 oline:8254 frasl:8260 euro:8364 trade:8482 larr:8592 uarr:8593 ' +
187
+ 'rarr:8594 darr:8595 harr:8596 minus:8722 lowast:8727 le:8804 ge:8805 ne:8800 asymp:8776 infin:8734 sum:8721 ' +
188
+ 'prod:8719 radic:8730 part:8706 isin:8712 cap:8745 cup:8746 int:8747 there4:8756 sim:8764 equiv:8801 sub:8834 ' +
189
+ 'sup:8835 loz:9674 spades:9824 clubs:9827 hearts:9829 diams:9830 check:10003 cross:10007 Abreve:258 abreve:259 ' +
190
+ 'Scedil:350 scedil:351 Tcedil:354 tcedil:355 Zcaron:381 zcaron:382 alpha:945 beta:946 gamma:947 delta:948 ' +
191
+ 'epsilon:949 lambda:955 mu:956 pi:960 sigma:963 omega:969 Delta:916 Omega:937 nbhy:8209 hyphen:8208 dash:8208 ' +
192
+ 'Tab:9 NewLine:10 nobreak:8288 ballot:9744 boxv:9474';
193
+ more.split(' ').forEach(function (kv) { var p = kv.split(':'); ENT[p[0]] = +p[1]; });
194
+ })();
195
+
196
+ function decodeEntities(s) {
197
+ if (s.indexOf('&') < 0) return s;
198
+ return s.replace(/&(#[xX][0-9a-fA-F]{1,6}|#[0-9]{1,7}|[a-zA-Z][a-zA-Z0-9]{1,31});?/g, function (m, e) {
199
+ if (e.charAt(0) === '#') {
200
+ var hex = e.charAt(1) === 'x' || e.charAt(1) === 'X';
201
+ var cp = hex ? parseInt(e.slice(2), 16) : parseInt(e.slice(1), 10);
202
+ if (!(cp > 0) || cp > 0x10FFFF || (cp >= 0xD800 && cp < 0xE000)) cp = 0xFFFD;
203
+ if (cp >= 0x80 && cp < 0xA0 && CP1252[cp - 0x80]) cp = CP1252[cp - 0x80];
204
+ return fromCP(cp);
205
+ }
206
+ if (ENT[e] !== undefined) return fromCP(ENT[e]);
207
+ return m;
208
+ });
209
+ }
210
+
211
+ var VOID = toSet('area base br col embed hr img input keygen link meta param source track wbr');
212
+ var RAWTXT = toSet('script style textarea title xmp noscript iframe noembed noframes template svg math');
213
+ var P_CLOSERS = toSet('address article aside blockquote center details dialog dir div dl fieldset figcaption figure footer ' +
214
+ 'form h1 h2 h3 h4 h5 h6 header hgroup hr main menu nav ol p pre section table ul li dd dt');
215
+ var SCOPE = toSet('table td th caption html template applet marquee object button');
216
+ var LIST_SCOPE = toSet('table td th caption html template applet marquee object button ol ul');
217
+ var TABLE_SCOPE = toSet('table html template');
218
+ var ROW_SCOPE = toSet('tr table html template');
219
+ var NO_SCOPE = toSet('html');
220
+
221
+ function mkEl(tag, attrs, parent) { return { tag: tag, attrs: attrs || Object.create(null), children: [], parent: parent || null }; }
222
+
223
+ function parseStartTag(src, i) {
224
+ var n = src.length, j = i + 1, s0 = j, c;
225
+ while (j < n) { c = src.charCodeAt(j); if (isSp(c) || c === 47 || c === 62) break; j++; }
226
+ var tag = src.slice(s0, j).toLowerCase(), attrs = Object.create(null), selfClose = false;
227
+ while (j < n) {
228
+ c = src.charCodeAt(j);
229
+ if (isSp(c)) { j++; continue; }
230
+ if (c === 62) { j++; break; }
231
+ if (c === 47) { j++; if (src.charCodeAt(j) === 62) { selfClose = true; j++; break; } continue; }
232
+ var a0 = j;
233
+ while (j < n) {
234
+ c = src.charCodeAt(j);
235
+ if (isSp(c) || c === 61 || c === 62 || (c === 47 && src.charCodeAt(j + 1) === 62)) break;
236
+ j++;
237
+ }
238
+ if (j === a0) { j++; continue; }
239
+ var an = src.slice(a0, j).toLowerCase(), av = '';
240
+ while (j < n && isSp(src.charCodeAt(j))) j++;
241
+ if (src.charCodeAt(j) === 61) {
242
+ j++;
243
+ while (j < n && isSp(src.charCodeAt(j))) j++;
244
+ var q = src.charCodeAt(j);
245
+ if (q === 34 || q === 39) {
246
+ var qe = src.indexOf(q === 34 ? '"' : "'", j + 1);
247
+ if (qe < 0) qe = n;
248
+ av = src.slice(j + 1, qe); j = qe + 1;
249
+ } else {
250
+ var v0 = j;
251
+ while (j < n && !isSp(src.charCodeAt(j)) && src.charCodeAt(j) !== 62) j++;
252
+ av = src.slice(v0, j);
253
+ }
254
+ }
255
+ if (!(an in attrs)) attrs[an] = decodeEntities(av);
256
+ }
257
+ return { tag: tag, attrs: attrs, selfClose: selfClose, end: j };
258
+ }
259
+
260
+ function parseHTML(src) {
261
+ var root = mkEl('#root'), stack = [root], i = 0, n = src.length, lower = null;
262
+ function top() { return stack[stack.length - 1]; }
263
+ function addText(t) {
264
+ if (!t) return;
265
+ var p = top(), last = p.children[p.children.length - 1];
266
+ if (last && last.tag === '#text') last.text += t; else p.children.push({ tag: '#text', text: t, parent: p });
267
+ }
268
+ function findOpen(tag, scope) {
269
+ for (var k = stack.length - 1; k > 0; k--) {
270
+ var t = stack[k].tag;
271
+ if (t === tag) return k;
272
+ if (scope[t]) return -1;
273
+ }
274
+ return -1;
275
+ }
276
+ function closeTo(k) { if (k > 0) stack.length = k; }
277
+ function start(tag, attrs, selfClose) {
278
+ if (P_CLOSERS[tag]) closeTo(findOpen('p', SCOPE));
279
+ if (tag === 'li') closeTo(findOpen('li', LIST_SCOPE));
280
+ else if (tag === 'dt' || tag === 'dd') { closeTo(findOpen('dt', SCOPE)); closeTo(findOpen('dd', SCOPE)); }
281
+ else if (tag === 'tr') closeTo(findOpen('tr', TABLE_SCOPE));
282
+ else if (tag === 'td' || tag === 'th') { closeTo(findOpen('td', ROW_SCOPE)); closeTo(findOpen('th', ROW_SCOPE)); }
283
+ else if (tag === 'thead' || tag === 'tbody' || tag === 'tfoot') {
284
+ closeTo(findOpen('thead', TABLE_SCOPE)); closeTo(findOpen('tbody', TABLE_SCOPE)); closeTo(findOpen('tfoot', TABLE_SCOPE));
285
+ } else if (tag === 'option') closeTo(findOpen('option', SCOPE));
286
+ else if (tag === 'a') closeTo(findOpen('a', SCOPE));
287
+ else if (/^h[1-6]$/.test(tag) && /^h[1-6]$/.test(top().tag)) stack.pop();
288
+ var p = top(), e = mkEl(tag, attrs, p);
289
+ p.children.push(e);
290
+ if (!VOID[tag] && !selfClose && stack.length < 400) stack.push(e);
291
+ return e;
292
+ }
293
+ function end(tag) {
294
+ if (tag === 'br') { start('br', Object.create(null), true); return; }
295
+ if (VOID[tag]) return;
296
+ if (tag === 'p' && findOpen('p', SCOPE) < 0) { start('p', Object.create(null), true); return; }
297
+ var scope = tag === 'table' ? NO_SCOPE
298
+ : /^(td|th|tr|thead|tbody|tfoot|caption|colgroup)$/.test(tag) ? TABLE_SCOPE : SCOPE;
299
+ closeTo(findOpen(tag, scope));
300
+ }
301
+ while (i < n) {
302
+ var lt = src.indexOf('<', i);
303
+ if (lt < 0) { addText(decodeEntities(src.slice(i))); break; }
304
+ if (lt > i) addText(decodeEntities(src.slice(i, lt)));
305
+ i = lt;
306
+ var c1 = src.charCodeAt(i + 1);
307
+ if (c1 === 33) {
308
+ if (src.substr(i, 4) === '<!--') { var ce = src.indexOf('-->', i + 4); i = ce < 0 ? n : ce + 3; }
309
+ else if (src.substr(i, 9).toUpperCase() === '<![CDATA[') {
310
+ var cd = src.indexOf(']]>', i + 9); addText(src.slice(i + 9, cd < 0 ? n : cd)); i = cd < 0 ? n : cd + 3;
311
+ } else { var ge = src.indexOf('>', i); i = ge < 0 ? n : ge + 1; }
312
+ continue;
313
+ }
314
+ if (c1 === 63) { var qe = src.indexOf('>', i); i = qe < 0 ? n : qe + 1; continue; }
315
+ if (c1 === 47) {
316
+ var j = i + 2, s0 = j;
317
+ while (j < n) { var cc = src.charCodeAt(j); if (isSp(cc) || cc === 62 || cc === 47) break; j++; }
318
+ var ee = src.indexOf('>', j);
319
+ if (j > s0) end(src.slice(s0, j).toLowerCase());
320
+ i = ee < 0 ? n : ee + 1;
321
+ continue;
322
+ }
323
+ if ((c1 >= 65 && c1 <= 90) || (c1 >= 97 && c1 <= 122)) {
324
+ var st = parseStartTag(src, i);
325
+ i = st.end;
326
+ var node = start(st.tag, st.attrs, st.selfClose);
327
+ if (RAWTXT[st.tag] && !st.selfClose) {
328
+ if (!lower) lower = src.toLowerCase();
329
+ var close = lower.indexOf('</' + st.tag, i);
330
+ var raw = src.slice(i, close < 0 ? n : close);
331
+ if (raw) node.children.push({ tag: '#text', text: (st.tag === 'textarea' || st.tag === 'title') ? decodeEntities(raw) : raw, parent: node });
332
+ var k = stack.lastIndexOf(node);
333
+ if (k > 0) stack.length = k;
334
+ if (close < 0) i = n; else { var gt = src.indexOf('>', close); i = gt < 0 ? n : gt + 1; }
335
+ }
336
+ continue;
337
+ }
338
+ addText('<'); i++;
339
+ }
340
+ return root;
341
+ }
342
+
343
+ // a fragment without <body> gets one, the way a browser builds it
344
+ function ensureBody(root) {
345
+ var html = null, found = false;
346
+ (function walk(n) {
347
+ if (found) return;
348
+ if (n.tag === 'body') { found = true; return; }
349
+ if (n.tag === 'html' && !html) html = n;
350
+ for (var i = 0; i < n.children.length; i++) if (n.children[i].tag !== '#text') walk(n.children[i]);
351
+ })(root);
352
+ if (found) return;
353
+ var host = html || root, body = mkEl('body', Object.create(null), host), keep = [];
354
+ host.children.forEach(function (c) {
355
+ if (c.tag === 'head' || (c.tag === 'html' && c !== host)) keep.push(c);
356
+ else { c.parent = body; body.children.push(c); }
357
+ });
358
+ keep.push(body);
359
+ host.children = keep;
360
+ }
361
+
362
+ function annotate(node) {
363
+ var els = [];
364
+ for (var k = 0; k < node.children.length; k++) {
365
+ var ch = node.children[k];
366
+ ch.parent = node;
367
+ if (ch.tag !== '#text') { ch.eidx = els.length; els.push(ch); annotate(ch); }
368
+ }
369
+ node.els = els;
370
+ }
371
+
372
+ // ======================= 4. CSS: values =======================
373
+ var NAMED = Object.create(null);
374
+ ('aliceblue:f0f8ff antiquewhite:faebd7 aqua:00ffff aquamarine:7fffd4 azure:f0ffff beige:f5f5dc bisque:ffe4c4 black:000000 ' +
375
+ 'blanchedalmond:ffebcd blue:0000ff blueviolet:8a2be2 brown:a52a2a burlywood:deb887 cadetblue:5f9ea0 chartreuse:7fff00 ' +
376
+ 'chocolate:d2691e coral:ff7f50 cornflowerblue:6495ed cornsilk:fff8dc crimson:dc143c cyan:00ffff darkblue:00008b ' +
377
+ 'darkcyan:008b8b darkgoldenrod:b8860b darkgray:a9a9a9 darkgreen:006400 darkgrey:a9a9a9 darkkhaki:bdb76b ' +
378
+ 'darkmagenta:8b008b darkolivegreen:556b2f darkorange:ff8c00 darkorchid:9932cc darkred:8b0000 darksalmon:e9967a ' +
379
+ 'darkseagreen:8fbc8f darkslateblue:483d8b darkslategray:2f4f4f darkslategrey:2f4f4f darkturquoise:00ced1 ' +
380
+ 'darkviolet:9400d3 deeppink:ff1493 deepskyblue:00bfff dimgray:696969 dimgrey:696969 dodgerblue:1e90ff ' +
381
+ 'firebrick:b22222 floralwhite:fffaf0 forestgreen:228b22 fuchsia:ff00ff gainsboro:dcdcdc ghostwhite:f8f8ff gold:ffd700 ' +
382
+ 'goldenrod:daa520 gray:808080 green:008000 greenyellow:adff2f grey:808080 honeydew:f0fff0 hotpink:ff69b4 ' +
383
+ 'indianred:cd5c5c indigo:4b0082 ivory:fffff0 khaki:f0e68c lavender:e6e6fa lavenderblush:fff0f5 lawngreen:7cfc00 ' +
384
+ 'lemonchiffon:fffacd lightblue:add8e6 lightcoral:f08080 lightcyan:e0ffff lightgoldenrodyellow:fafad2 lightgray:d3d3d3 ' +
385
+ 'lightgreen:90ee90 lightgrey:d3d3d3 lightpink:ffb6c1 lightsalmon:ffa07a lightseagreen:20b2aa lightskyblue:87cefa ' +
386
+ 'lightslategray:778899 lightslategrey:778899 lightsteelblue:b0c4de lightyellow:ffffe0 lime:00ff00 limegreen:32cd32 ' +
387
+ 'linen:faf0e6 magenta:ff00ff maroon:800000 mediumaquamarine:66cdaa mediumblue:0000cd mediumorchid:ba55d3 ' +
388
+ 'mediumpurple:9370db mediumseagreen:3cb371 mediumslateblue:7b68ee mediumspringgreen:00fa9a mediumturquoise:48d1cc ' +
389
+ 'mediumvioletred:c71585 midnightblue:191970 mintcream:f5fffa mistyrose:ffe4e1 moccasin:ffe4b5 navajowhite:ffdead ' +
390
+ 'navy:000080 oldlace:fdf5e6 olive:808000 olivedrab:6b8e23 orange:ffa500 orangered:ff4500 orchid:da70d6 ' +
391
+ 'palegoldenrod:eee8aa palegreen:98fb98 paleturquoise:afeeee palevioletred:db7093 papayawhip:ffefd5 peachpuff:ffdab9 ' +
392
+ 'peru:cd853f pink:ffc0cb plum:dda0dd powderblue:b0e0e6 purple:800080 rebeccapurple:663399 red:ff0000 ' +
393
+ 'rosybrown:bc8f8f royalblue:4169e1 saddlebrown:8b4513 salmon:fa8072 sandybrown:f4a460 seagreen:2e8b57 ' +
394
+ 'seashell:fff5ee sienna:a0522d silver:c0c0c0 skyblue:87ceeb slateblue:6a5acd slategray:708090 slategrey:708090 ' +
395
+ 'snow:fffafa springgreen:00ff7f steelblue:4682b4 tan:d2b48c teal:008080 thistle:d8bfd8 tomato:ff6347 ' +
396
+ 'turquoise:40e0d0 violet:ee82ee wheat:f5deb3 white:ffffff whitesmoke:f5f5f5 yellow:ffff00 yellowgreen:9acd32 ' +
397
+ 'windowtext:000000 buttontext:000000 canvastext:000000 canvas:ffffff window:ffffff')
398
+ .split(' ').forEach(function (kv) { var p = kv.split(':'); NAMED[p[0]] = p[1].toUpperCase(); });
399
+
400
+ function hex2(n) { n = clamp(Math.round(n), 0, 255); return (n < 16 ? '0' : '') + n.toString(16).toUpperCase(); }
401
+ function blend(r, g, b, a) { // alpha over white
402
+ if (a >= 1) return hex2(r) + hex2(g) + hex2(b);
403
+ if (a <= 0.02) return null;
404
+ return hex2(r * a + 255 * (1 - a)) + hex2(g * a + 255 * (1 - a)) + hex2(b * a + 255 * (1 - a));
405
+ }
406
+ function hsl2rgb(h, s, l) {
407
+ h = ((h % 360) + 360) % 360 / 360; s = clamp(s, 0, 1); l = clamp(l, 0, 1);
408
+ function f(t) { t = (t + 1) % 1; return t < 1 / 6 ? p + (q - p) * 6 * t : t < 0.5 ? q : t < 2 / 3 ? p + (q - p) * (2 / 3 - t) * 6 : p; }
409
+ var q = l < 0.5 ? l * (1 + s) : l + s - l * s, p = 2 * l - q;
410
+ return [f(h + 1 / 3) * 255, f(h) * 255, f(h - 1 / 3) * 255];
411
+ }
412
+ // returns 'RRGGBB', null (transparent) or undefined (not a colour)
413
+ function parseColor(v, current) {
414
+ v = String(v).trim().toLowerCase();
415
+ if (!v) return undefined;
416
+ if (v === 'transparent' || v === 'none') return null;
417
+ if (v === 'currentcolor') return current;
418
+ if (v.charAt(0) === '#') {
419
+ var h = v.slice(1);
420
+ if (!/^[0-9a-f]+$/.test(h)) return undefined;
421
+ if (h.length === 3 || h.length === 4) {
422
+ var a3 = h.length === 4 ? parseInt(h.charAt(3) + h.charAt(3), 16) / 255 : 1;
423
+ return blend(parseInt(h.charAt(0) + h.charAt(0), 16), parseInt(h.charAt(1) + h.charAt(1), 16), parseInt(h.charAt(2) + h.charAt(2), 16), a3);
424
+ }
425
+ if (h.length === 6 || h.length === 8) {
426
+ var a6 = h.length === 8 ? parseInt(h.slice(6, 8), 16) / 255 : 1;
427
+ return blend(parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16), a6);
428
+ }
429
+ return undefined;
430
+ }
431
+ var m = /^(rgba?|hsla?)\(([^)]*)\)$/.exec(v);
432
+ if (m) {
433
+ var parts = m[2].replace(/\//g, ' ').split(/[\s,]+/).filter(Boolean);
434
+ if (parts.length < 3) return undefined;
435
+ var al = parts.length > 3 ? (parts[3].slice(-1) === '%' ? parseFloat(parts[3]) / 100 : parseFloat(parts[3])) : 1;
436
+ if (m[1].charAt(0) === 'r') {
437
+ var ch = parts.slice(0, 3).map(function (x) { return x.slice(-1) === '%' ? parseFloat(x) * 2.55 : parseFloat(x); });
438
+ return blend(ch[0], ch[1], ch[2], al);
439
+ }
440
+ var rgb = hsl2rgb(parseFloat(parts[0]), parseFloat(parts[1]) / 100, parseFloat(parts[2]) / 100);
441
+ return blend(rgb[0], rgb[1], rgb[2], al);
442
+ }
443
+ if (NAMED[v]) return NAMED[v];
444
+ return undefined;
445
+ }
446
+
447
+ var PT = { pt: 1, px: 0.75, cm: 28.3464567, mm: 2.83464567, 'in': 72, pc: 12, q: 0.708661 };
448
+ // length -> {pt} | {pct} | {auto:true} | null
449
+ function parseLen(v, fs, rootFs) {
450
+ if (v == null) return null;
451
+ v = String(v).trim().toLowerCase();
452
+ if (!v) return null;
453
+ if (v === 'auto') return { auto: true };
454
+ var m = /^(-?(?:\d+\.?\d*|\.\d+)(?:e-?\d+)?)\s*([a-z%]*)$/.exec(v);
455
+ if (!m) return null;
456
+ var x = parseFloat(m[1]), u = m[2];
457
+ if (u === '' || u === 'px') return { pt: x * 0.75 };
458
+ if (PT[u]) return { pt: x * PT[u] };
459
+ if (u === 'em') return { pt: x * fs };
460
+ if (u === 'rem') return { pt: x * rootFs };
461
+ if (u === 'ex' || u === 'ch') return { pt: x * fs * 0.5 };
462
+ if (u === '%') return { pct: x };
463
+ if (u === 'vw') return { pct: x };
464
+ return null;
465
+ }
466
+ function res(L, ref) { if (!L || L.auto) return null; return L.pct != null ? L.pct * (ref || 0) / 100 : L.pt; }
467
+ function res0(L, ref) { var r = res(L, ref); return r == null ? 0 : r; }
468
+
469
+ var FS_KEY = { 'xx-small': 6.75, 'x-small': 7.5, small: 9.75, medium: 12, large: 13.5, 'x-large': 18, 'xx-large': 24, 'xxx-large': 36 };
470
+ var BW_KEY = { thin: 0.75, medium: 2.25, thick: 3.75 };
471
+ var GENERIC = { serif: 'Times New Roman', 'sans-serif': 'Arial', monospace: 'Courier New', cursive: 'Comic Sans MS',
472
+ fantasy: 'Impact', 'system-ui': 'Arial', '-apple-system': 'Arial', blinkmacsystemfont: 'Arial', 'ui-sans-serif': 'Arial',
473
+ 'ui-serif': 'Times New Roman', 'ui-monospace': 'Courier New', 'liberation sans': 'Arial', arimo: 'Arial', helvetica: 'Arial',
474
+ 'helvetica neue': 'Arial', 'liberation serif': 'Times New Roman', tinos: 'Times New Roman', 'liberation mono': 'Courier New',
475
+ cousine: 'Courier New', carlito: 'Calibri', caladea: 'Cambria', times: 'Times New Roman' };
476
+ var LINE_FACTOR = { arial: 1.149, 'times new roman': 1.149, calibri: 1.2207, cambria: 1.1724, 'courier new': 1.1328,
477
+ verdana: 1.2153, tahoma: 1.2075, georgia: 1.1362, 'segoe ui': 1.33, 'trebuchet ms': 1.1621, garamond: 1.12,
478
+ 'book antiqua': 1.17, 'century gothic': 1.2, 'comic sans ms': 1.394, impact: 1.22, 'palatino linotype': 1.32,
479
+ 'dejavu sans': 1.164, 'open sans': 1.362, roboto: 1.172, lato: 1.2, 'arial narrow': 1.149 };
480
+
481
+ function splitTop(s, sep) {
482
+ var out = [], depth = 0, q = 0, last = 0;
483
+ for (var i = 0; i < s.length; i++) {
484
+ var c = s.charAt(i);
485
+ if (q) { if (c === '\\') i++; else if (c === q) q = 0; continue; }
486
+ if (c === '"' || c === "'") q = c;
487
+ else if (c === '(' || c === '[') depth++;
488
+ else if (c === ')' || c === ']') depth--;
489
+ else if (c === sep && depth <= 0) { out.push(s.slice(last, i)); last = i + 1; }
490
+ }
491
+ out.push(s.slice(last));
492
+ return out;
493
+ }
494
+ function tokens(v) { return splitTop(String(v).trim().replace(/\s+/g, ' '), ' ').filter(Boolean); }
495
+
496
+ function firstFamily(v) {
497
+ var fams = splitTop(v, ',');
498
+ for (var i = 0; i < fams.length; i++) {
499
+ var f = fams[i].trim().replace(/^["']|["']$/g, '').trim();
500
+ if (!f || /^(inherit|initial|unset)$/i.test(f)) continue;
501
+ var g = GENERIC[f.toLowerCase()];
502
+ return g || f;
503
+ }
504
+ return null;
505
+ }
506
+
507
+ // ======================= 5. CSS: parser =======================
508
+ var BORDER_STYLES = toSet('none hidden dotted dashed solid double groove ridge inset outset');
509
+ var SIDES = ['top', 'right', 'bottom', 'left'];
510
+
511
+ function box4(v) {
512
+ var t = tokens(v);
513
+ if (!t.length) return null;
514
+ return [t[0], t[1] || t[0], t[2] || t[0], t[3] || t[1] || t[0]];
515
+ }
516
+
517
+ function expandDecl(name, val, imp, out) {
518
+ function put(p, v) { out.push({ p: p, v: v, imp: imp }); }
519
+ var lv = val.toLowerCase(), t, i, k;
520
+ if (/^(inherit|initial|unset)$/.test(lv) && /^(margin|padding|border|border-(top|right|bottom|left)|background|font|list-style|text-decoration)$/.test(name)) {
521
+ if (name === 'margin' || name === 'padding') { SIDES.forEach(function (s) { put(name + '-' + s, lv); }); return; }
522
+ }
523
+ switch (name) {
524
+ case 'margin': case 'padding':
525
+ t = box4(val); if (t) for (i = 0; i < 4; i++) put(name + '-' + SIDES[i], t[i]);
526
+ return;
527
+ case 'border': case 'border-top': case 'border-right': case 'border-bottom': case 'border-left':
528
+ var w = null, s = null, c = null;
529
+ tokens(val).forEach(function (tk) {
530
+ var l = tk.toLowerCase();
531
+ if (BORDER_STYLES[l]) s = l;
532
+ else if (BW_KEY[l] !== undefined || /^-?[\d.]/.test(l)) w = l;
533
+ else c = tk;
534
+ });
535
+ var sides = name === 'border' ? SIDES : [name.slice(7)];
536
+ sides.forEach(function (sd) {
537
+ put('border-' + sd + '-style', s || 'none');
538
+ put('border-' + sd + '-width', w || 'medium');
539
+ put('border-' + sd + '-color', c || 'currentcolor');
540
+ });
541
+ return;
542
+ case 'border-width': case 'border-style': case 'border-color':
543
+ t = box4(val); k = name.slice(7);
544
+ if (t) for (i = 0; i < 4; i++) put('border-' + SIDES[i] + '-' + k, t[i]);
545
+ return;
546
+ case 'background':
547
+ var col = null;
548
+ tokens(val).forEach(function (tk) { if (col == null && parseColor(tk, null) !== undefined) col = tk; });
549
+ put('background-color', col || 'transparent');
550
+ return;
551
+ case 'font':
552
+ var tk = tokens(val), idx = -1;
553
+ for (i = 0; i < tk.length; i++) {
554
+ var x = tk[i].toLowerCase();
555
+ if (FS_KEY[x] !== undefined || x === 'smaller' || x === 'larger' || /^[\d.]+(px|pt|em|rem|%|cm|mm|in|pc|ex|ch)(\/.*)?$/.test(x)) { idx = i; break; }
556
+ }
557
+ if (idx < 0) return;
558
+ put('font-style', 'normal'); put('font-weight', 'normal'); put('font-variant', 'normal'); put('line-height', 'normal');
559
+ for (i = 0; i < idx; i++) {
560
+ var y = tk[i].toLowerCase();
561
+ if (y === 'italic' || y === 'oblique') put('font-style', y);
562
+ else if (y === 'bold' || y === 'bolder' || y === 'lighter' || /^\d{3}$/.test(y)) put('font-weight', y);
563
+ else if (y === 'small-caps') put('font-variant', y);
564
+ }
565
+ var sz = tk[idx], sl = sz.indexOf('/'), rest = tk.slice(idx + 1);
566
+ if (sl >= 0) { var lh = sz.slice(sl + 1); sz = sz.slice(0, sl); if (lh) put('line-height', lh); else if (rest.length) put('line-height', rest.shift()); }
567
+ else if (rest.length && rest[0].charAt(0) === '/') { var lh2 = rest.shift().slice(1) || rest.shift(); if (lh2) put('line-height', lh2); }
568
+ put('font-size', sz);
569
+ if (rest.length) put('font-family', rest.join(' '));
570
+ return;
571
+ case 'list-style':
572
+ tokens(val).forEach(function (tk2) {
573
+ var l = tk2.toLowerCase();
574
+ if (l === 'inside' || l === 'outside') put('list-style-position', l);
575
+ else if (!/^url\(/.test(l)) put('list-style-type', l);
576
+ });
577
+ return;
578
+ case 'text-decoration':
579
+ var line = [], st = null, cl = null;
580
+ tokens(val).forEach(function (tk3) {
581
+ var l = tk3.toLowerCase();
582
+ if (/^(underline|line-through|overline|none|blink)$/.test(l)) line.push(l);
583
+ else if (/^(solid|double|dotted|dashed|wavy)$/.test(l)) st = l;
584
+ else cl = tk3;
585
+ });
586
+ put('text-decoration-line', line.length ? line.join(' ') : 'none');
587
+ if (st) put('text-decoration-style', st);
588
+ if (cl) put('text-decoration-color', cl);
589
+ return;
590
+ case 'break-before': case 'break-after':
591
+ put('page-break-' + name.slice(6), /^(page|always|left|right|recto|verso)$/.test(lv) ? 'always' : lv === 'avoid' || lv === 'avoid-page' ? 'avoid' : 'auto');
592
+ return;
593
+ case 'break-inside':
594
+ put('page-break-inside', /^avoid/.test(lv) ? 'avoid' : 'auto');
595
+ return;
596
+ case 'background-image': case 'background-repeat': case 'background-position': case 'background-size':
597
+ return;
598
+ case 'margin-inline-start': put('margin-left', val); return;
599
+ case 'margin-inline-end': put('margin-right', val); return;
600
+ case 'margin-block-start': put('margin-top', val); return;
601
+ case 'margin-block-end': put('margin-bottom', val); return;
602
+ case 'padding-inline-start': put('padding-left', val); return;
603
+ case 'padding-inline-end': put('padding-right', val); return;
604
+ case 'padding-block-start': put('padding-top', val); return;
605
+ case 'padding-block-end': put('padding-bottom', val); return;
606
+ case 'word-wrap': case 'overflow-wrap': case 'word-break': case 'hyphens': return;
607
+ }
608
+ put(name, val);
609
+ }
610
+
611
+ function parseDecls(body) {
612
+ var out = [], parts = splitTop(body, ';');
613
+ for (var i = 0; i < parts.length; i++) {
614
+ var p = parts[i], k = p.indexOf(':');
615
+ if (k < 0) continue;
616
+ var name = p.slice(0, k).trim().toLowerCase(), val = p.slice(k + 1).trim(), imp = false;
617
+ var m = /!\s*important\s*$/i.exec(val);
618
+ if (m) { imp = true; val = val.slice(0, m.index).trim(); }
619
+ if (!name || !val || name.charAt(0) === '-' && name.indexOf('-webkit-') !== 0 && name.indexOf('-moz-') !== 0 && name.indexOf('--') === 0) continue;
620
+ expandDecl(name, val, imp, out);
621
+ }
622
+ return out;
623
+ }
624
+
625
+ function matchBrace(css, open) {
626
+ var depth = 0, q = 0;
627
+ for (var i = open; i < css.length; i++) {
628
+ var c = css.charAt(i);
629
+ if (q) { if (c === '\\') i++; else if (c === q) q = 0; continue; }
630
+ if (c === '"' || c === "'") q = c;
631
+ else if (c === '{') depth++;
632
+ else if (c === '}') { depth--; if (!depth) return i; }
633
+ }
634
+ return css.length;
635
+ }
636
+ function findTop(css, from, chars) {
637
+ var q = 0, depth = 0;
638
+ for (var i = from; i < css.length; i++) {
639
+ var c = css.charAt(i);
640
+ if (q) { if (c === '\\') i++; else if (c === q) q = 0; continue; }
641
+ if (c === '"' || c === "'") q = c;
642
+ else if (c === '(') depth++;
643
+ else if (c === ')') depth--;
644
+ else if (!depth && chars.indexOf(c) >= 0) return i;
645
+ }
646
+ return -1;
647
+ }
648
+
649
+ function mediaMatches(prelude, env) {
650
+ var list = splitTop(prelude.toLowerCase(), ',');
651
+ for (var i = 0; i < list.length; i++) {
652
+ var q = list[i].trim(), neg = false, ok = true;
653
+ if (!q) continue;
654
+ if (/^not\s/.test(q)) { neg = true; q = q.slice(4); } else if (/^only\s/.test(q)) q = q.slice(5);
655
+ q.split(/\s+and\s+/).forEach(function (part) {
656
+ part = part.trim();
657
+ if (!part) return;
658
+ if (part.charAt(0) === '(') {
659
+ var f = /^\(\s*([\w-]+)\s*(?::\s*([^)]+))?\)$/.exec(part);
660
+ if (!f) { ok = false; return; }
661
+ var name = f[1], val = f[2] ? f[2].trim() : null, L = val ? parseLen(val, 12, 12) : null, px = L && L.pt != null ? L.pt / 0.75 : null;
662
+ if (name === 'min-width') ok = ok && px != null && env.widthPx >= px;
663
+ else if (name === 'max-width') ok = ok && px != null && env.widthPx <= px;
664
+ else if (name === 'min-height') ok = ok && px != null && env.heightPx >= px;
665
+ else if (name === 'max-height') ok = ok && px != null && env.heightPx <= px;
666
+ else if (name === 'orientation') ok = ok && val === (env.widthPx > env.heightPx ? 'landscape' : 'portrait');
667
+ else if (name === 'color') ok = ok && true;
668
+ else ok = false;
669
+ } else if (part !== 'all' && part !== env.type) ok = false;
670
+ });
671
+ if (neg ? !ok : ok) return true;
672
+ }
673
+ return false;
674
+ }
675
+
676
+ var PSEUDO_EL = toSet('before after first-line first-letter marker selection placeholder backdrop');
677
+
678
+ function readIdent(s, i) {
679
+ var j = i;
680
+ while (j < s.length) {
681
+ var c = s.charAt(j);
682
+ if (c === '\\') { j += 2; continue; }
683
+ if (/[\w -￿-]/.test(c)) j++; else break;
684
+ }
685
+ return { v: s.slice(i, j).replace(/\\(.)/g, '$1'), i: j };
686
+ }
687
+ function matchParen(s, i) {
688
+ var d = 0;
689
+ for (var j = i; j < s.length; j++) { var c = s.charAt(j); if (c === '(') d++; else if (c === ')') { d--; if (!d) return j; } }
690
+ return s.length;
691
+ }
692
+ function parseAttrSel(body) {
693
+ var m = /^\s*([\w:-]+)\s*(?:([~|^$*]?=)\s*("[^"]*"|'[^']*'|[^\s\]]+)\s*(i)?)?\s*$/.exec(body);
694
+ if (!m) return null;
695
+ var v = m[3] || '';
696
+ if (/^["']/.test(v)) v = v.slice(1, -1);
697
+ return { n: m[1].toLowerCase(), op: m[2] || '', v: v, ci: !!m[4] };
698
+ }
699
+ function parseNth(arg) {
700
+ arg = String(arg || '').replace(/\s+/g, '').toLowerCase();
701
+ if (arg === 'odd') return [2, 1];
702
+ if (arg === 'even') return [2, 0];
703
+ var m = /^([+-]?\d*)n([+-]\d+)?$/.exec(arg);
704
+ if (m) { var a = m[1] === '' || m[1] === '+' ? 1 : m[1] === '-' ? -1 : parseInt(m[1], 10); return [a, m[2] ? parseInt(m[2], 10) : 0]; }
705
+ if (/^[+-]?\d+$/.test(arg)) return [0, parseInt(arg, 10)];
706
+ return null;
707
+ }
708
+ function parseCompoundOnly(s) { var r = parseComplex(s); return r && r.parts.length === 1 ? r.parts[0].c : null; }
709
+ function parseComplex(s) {
710
+ s = s.trim();
711
+ if (!s) return null;
712
+ var parts = [], i = 0, n = s.length, cur = { tag: null, id: null, cls: [], attrs: [], ps: [] }, has = false, comb = null, a = 0, b = 0, c = 0;
713
+ function push() { parts.push({ c: cur, comb: comb }); cur = { tag: null, id: null, cls: [], attrs: [], ps: [] }; has = false; }
714
+ while (i < n) {
715
+ var ch = s.charAt(i), r;
716
+ if (/[\s>+~]/.test(ch)) {
717
+ var cb = ' ';
718
+ while (i < n && /[\s>+~]/.test(s.charAt(i))) { if (!/\s/.test(s.charAt(i))) cb = s.charAt(i); i++; }
719
+ if (has) { push(); comb = cb; }
720
+ continue;
721
+ }
722
+ if (ch === '*') { i++; has = true; continue; }
723
+ if (ch === '#') { r = readIdent(s, i + 1); cur.id = r.v; i = r.i; a++; has = true; continue; }
724
+ if (ch === '.') { r = readIdent(s, i + 1); if (!r.v) return null; cur.cls.push(r.v); i = r.i; b++; has = true; continue; }
725
+ if (ch === '[') {
726
+ var e = s.indexOf(']', i);
727
+ if (e < 0) return null;
728
+ var at = parseAttrSel(s.slice(i + 1, e));
729
+ if (!at) return null;
730
+ cur.attrs.push(at); i = e + 1; b++; has = true; continue;
731
+ }
732
+ if (ch === ':') {
733
+ var dbl = s.charAt(i + 1) === ':';
734
+ i += dbl ? 2 : 1;
735
+ r = readIdent(s, i);
736
+ var name = r.v.toLowerCase(), arg = null;
737
+ i = r.i;
738
+ if (s.charAt(i) === '(') { var pe = matchParen(s, i); arg = s.slice(i + 1, pe); i = pe + 1; }
739
+ if (dbl || PSEUDO_EL[name]) return null;
740
+ var ps = { n: name, a: arg };
741
+ if (name === 'not' && arg) { ps.sub = splitTop(arg, ',').map(parseCompoundOnly); if (ps.sub.some(function (x) { return !x; })) return null; }
742
+ if (/^nth-/.test(name)) { ps.nth = parseNth(arg); if (!ps.nth) return null; }
743
+ cur.ps.push(ps); b++; has = true; continue;
744
+ }
745
+ if (/[\w -￿-]/.test(ch) || ch === '\\') { r = readIdent(s, i); cur.tag = r.v.toLowerCase(); i = r.i; c++; has = true; continue; }
746
+ return null;
747
+ }
748
+ if (has) push(); else return null;
749
+ return { parts: parts, spec: a * 10000 + b * 100 + c };
750
+ }
751
+
752
+ function parseCSS(css, sheet, env, origin, pageOnly) {
753
+ css = css.replace(/\/\*[\s\S]*?\*\//g, '').replace(/<!--|-->/g, ' ');
754
+ var i = 0, n = css.length;
755
+ while (i < n) {
756
+ while (i < n && /\s/.test(css.charAt(i))) i++;
757
+ if (i >= n) break;
758
+ if (css.charAt(i) === '@') {
759
+ var km = /^@([\w-]+)/.exec(css.slice(i, i + 40)), kw = km ? km[1].toLowerCase() : '';
760
+ var stop = findTop(css, i, '{;');
761
+ if (stop < 0) break;
762
+ if (css.charAt(stop) === ';') { i = stop + 1; continue; }
763
+ var close = matchBrace(css, stop), prelude = css.slice(i + 1 + kw.length, stop).trim(), inner = css.slice(stop + 1, close);
764
+ if (kw === 'media') parseCSS(inner, sheet, env, origin, pageOnly || !mediaMatches(prelude, env));
765
+ else if (kw === 'supports') parseCSS(inner, sheet, env, origin, pageOnly);
766
+ else if (kw === 'page' && !/:(left|right|blank)/i.test(prelude)) sheet.page.push(parseDecls(inner.replace(/@[\w-]+\s*\{[^}]*\}/g, '')));
767
+ i = close + 1;
768
+ continue;
769
+ }
770
+ var ob = findTop(css, i, '{');
771
+ if (ob < 0) break;
772
+ var cb = matchBrace(css, ob), selText = css.slice(i, ob).trim(), body = css.slice(ob + 1, cb);
773
+ i = cb + 1;
774
+ if (pageOnly || !selText) continue;
775
+ var decls = parseDecls(body);
776
+ if (!decls.length) continue;
777
+ var sels = splitTop(selText, ',');
778
+ for (var k = 0; k < sels.length; k++) {
779
+ var sel = parseComplex(sels[k]);
780
+ if (sel) sheet[origin].push({ parts: sel.parts, spec: sel.spec, decls: decls, order: sheet.seq++ });
781
+ }
782
+ }
783
+ }
784
+
785
+ // ======================= 6. selector matching =======================
786
+ function clsSet(e) {
787
+ if (!e.cset) { e.cset = Object.create(null); String(e.attrs['class'] || '').split(/\s+/).forEach(function (c) { if (c) e.cset[c] = true; }); }
788
+ return e.cset;
789
+ }
790
+ function nthOk(nth, pos) { // pos is 1-based
791
+ var a = nth[0], b = nth[1];
792
+ if (a === 0) return pos === b;
793
+ var k = (pos - b) / a;
794
+ return k >= 0 && Math.floor(k) === k;
795
+ }
796
+ function sameTypeIndex(e, fromEnd) {
797
+ var sib = e.parent ? e.parent.els : [e], pos = 0;
798
+ if (!fromEnd) { for (var i = 0; i <= e.eidx; i++) if (sib[i].tag === e.tag) pos++; }
799
+ else { for (var j = sib.length - 1; j >= e.eidx; j--) if (sib[j].tag === e.tag) pos++; }
800
+ return pos;
801
+ }
802
+ function matchCompound(e, c) {
803
+ if (c.tag && c.tag !== e.tag) return false;
804
+ if (c.id && e.attrs.id !== c.id) return false;
805
+ var k;
806
+ if (c.cls.length) { var cs = clsSet(e); for (k = 0; k < c.cls.length; k++) if (!cs[c.cls[k]]) return false; }
807
+ for (k = 0; k < c.attrs.length; k++) {
808
+ var at = c.attrs[k], v = e.attrs[at.n];
809
+ if (v === undefined) return false;
810
+ if (!at.op) continue;
811
+ var x = at.v, y = v;
812
+ if (at.ci) { x = x.toLowerCase(); y = y.toLowerCase(); }
813
+ if (at.op === '=' && y !== x) return false;
814
+ if (at.op === '~=' && y.split(/\s+/).indexOf(x) < 0) return false;
815
+ if (at.op === '|=' && y !== x && y.indexOf(x + '-') !== 0) return false;
816
+ if (at.op === '^=' && (!x || y.indexOf(x) !== 0)) return false;
817
+ if (at.op === '$=' && (!x || y.slice(-x.length) !== x)) return false;
818
+ if (at.op === '*=' && (!x || y.indexOf(x) < 0)) return false;
819
+ }
820
+ for (k = 0; k < c.ps.length; k++) {
821
+ var ps = c.ps[k], sib = e.parent ? e.parent.els : [e];
822
+ switch (ps.n) {
823
+ case 'first-child': if (e.eidx !== 0) return false; break;
824
+ case 'last-child': if (e.eidx !== sib.length - 1) return false; break;
825
+ case 'only-child': if (sib.length !== 1) return false; break;
826
+ case 'nth-child': if (!nthOk(ps.nth, e.eidx + 1)) return false; break;
827
+ case 'nth-last-child': if (!nthOk(ps.nth, sib.length - e.eidx)) return false; break;
828
+ case 'first-of-type': if (sameTypeIndex(e, false) !== 1) return false; break;
829
+ case 'last-of-type': if (sameTypeIndex(e, true) !== 1) return false; break;
830
+ case 'only-of-type': if (sameTypeIndex(e, false) !== 1 || sameTypeIndex(e, true) !== 1) return false; break;
831
+ case 'nth-of-type': if (!nthOk(ps.nth, sameTypeIndex(e, false))) return false; break;
832
+ case 'nth-last-of-type': if (!nthOk(ps.nth, sameTypeIndex(e, true))) return false; break;
833
+ case 'root': if (e.tag !== 'html') return false; break;
834
+ case 'empty':
835
+ for (var q = 0; q < e.children.length; q++) if (e.children[q].tag !== '#text' || e.children[q].text) return false;
836
+ break;
837
+ case 'link': case 'any-link': if (!(e.tag === 'a' && e.attrs.href !== undefined)) return false; break;
838
+ case 'checked': if (e.attrs.checked === undefined && e.attrs.selected === undefined) return false; break;
839
+ case 'disabled': if (e.attrs.disabled === undefined) return false; break;
840
+ case 'not': for (var z = 0; z < ps.sub.length; z++) if (matchCompound(e, ps.sub[z])) return false; break;
841
+ default: return false; // hover, focus, visited ...
842
+ }
843
+ }
844
+ return true;
845
+ }
846
+ function matchComplex(e, parts, idx) {
847
+ if (!matchCompound(e, parts[idx].c)) return false;
848
+ if (idx === 0) return true;
849
+ var comb = parts[idx].comb, p;
850
+ if (comb === ' ') {
851
+ for (p = e.parent; p && p.tag !== '#root'; p = p.parent) if (matchComplex(p, parts, idx - 1)) return true;
852
+ return false;
853
+ }
854
+ if (comb === '>') return !!(e.parent && e.parent.tag !== '#root' && matchComplex(e.parent, parts, idx - 1));
855
+ var sib = e.parent ? e.parent.els : [];
856
+ if (comb === '+') return e.eidx > 0 && matchComplex(sib[e.eidx - 1], parts, idx - 1);
857
+ if (comb === '~') { for (var k = e.eidx - 1; k >= 0; k--) if (matchComplex(sib[k], parts, idx - 1)) return true; return false; }
858
+ return false;
859
+ }
860
+
861
+ // ======================= 7. default (browser) stylesheet =======================
862
+ var UA_CSS =
863
+ 'html,address,blockquote,body,dd,div,dl,dt,fieldset,form,frame,frameset,h1,h2,h3,h4,h5,h6,noframes,ol,p,ul,center,dir,hr,menu,pre,' +
864
+ 'article,aside,footer,header,hgroup,main,nav,section,figure,figcaption,details,summary,legend,address{display:block}' +
865
+ 'li{display:list-item}' +
866
+ 'head,script,style,title,meta,link,template,noscript,base,param,datalist,map,area,svg,canvas,video,audio,iframe,object,embed,select,math{display:none}' +
867
+ '[hidden]{display:none}' +
868
+ 'table{display:table;border-collapse:separate}tr{display:table-row;vertical-align:middle}thead{display:table-header-group;vertical-align:middle}' +
869
+ 'tbody{display:table-row-group;vertical-align:middle}tfoot{display:table-footer-group;vertical-align:middle}col{display:table-column}' +
870
+ 'colgroup{display:table-column-group}td,th{display:table-cell;padding:1px}caption{display:table-caption;text-align:center}' +
871
+ 'th{font-weight:bold;text-align:center}' +
872
+ 'body{margin:8px}p{margin:1em 0}' +
873
+ 'h1{font-size:2em;margin:.67em 0;font-weight:bold;page-break-after:avoid}h2{font-size:1.5em;margin:.83em 0;font-weight:bold;page-break-after:avoid}' +
874
+ 'h3{font-size:1.17em;margin:1em 0;font-weight:bold;page-break-after:avoid}h4{margin:1.33em 0;font-weight:bold;page-break-after:avoid}' +
875
+ 'h5{font-size:.83em;margin:1.67em 0;font-weight:bold;page-break-after:avoid}h6{font-size:.67em;margin:2.33em 0;font-weight:bold;page-break-after:avoid}' +
876
+ 'blockquote,figure{margin:1em 40px}ul,ol,menu,dir{margin:1em 0;padding-left:40px}ul,menu,dir{list-style-type:disc}ol{list-style-type:decimal}' +
877
+ 'ul ul,ol ul,menu ul,ul menu{list-style-type:circle}ul ul ul,ul ol ul,ol ul ul,ol ol ul{list-style-type:square}' +
878
+ 'ol ol,ol ul,ul ol,ul ul{margin-top:0;margin-bottom:0}dl{margin:1em 0}dd{margin-left:40px}' +
879
+ 'b,strong{font-weight:bold}i,em,cite,var,dfn,address{font-style:italic}u,ins{text-decoration:underline}s,strike,del{text-decoration:line-through}' +
880
+ 'sub{vertical-align:sub;font-size:smaller}sup{vertical-align:super;font-size:smaller}small{font-size:smaller}big{font-size:larger}' +
881
+ 'pre,code,kbd,samp,tt,xmp,listing,plaintext{font-family:monospace}pre,xmp,listing,plaintext{white-space:pre;margin:1em 0}' +
882
+ 'a[href]{color:#0000EE;text-decoration:underline}mark{background-color:yellow;color:black}center{text-align:center}' +
883
+ 'hr{border:1px inset gray;margin:.5em 0}nobr{white-space:nowrap}fieldset{margin:0 2px;padding:.35em .75em .625em;border:2px groove #c0c0c0}';
884
+ var QUIRKS_CSS = 'table{font-size:medium;font-weight:normal;font-style:normal;font-variant:normal;line-height:normal;white-space:normal;text-align:left}';
885
+ var FROALA_CSS =
886
+ '.fr-view table{border:none;border-collapse:collapse;empty-cells:show}.fr-view table td,.fr-view table th{border:1px solid #dddddd}' +
887
+ '.fr-view table th{background:#ececec}.fr-view table.fr-dashed-borders td,.fr-view table.fr-dashed-borders th{border-style:dashed}' +
888
+ '.fr-view table.fr-alternate-rows tbody tr:nth-child(2n){background:#f5f5f5}.fr-view table td.fr-thick,.fr-view table th.fr-thick{border-width:2px}' +
889
+ '.fr-view table td.fr-highlighted,.fr-view table th.fr-highlighted{border:1px double red}' +
890
+ '.fr-view blockquote{border-left:solid 2px #5e35b1;margin-left:0;padding-left:5px;color:#5e35b1}' +
891
+ '.fr-view .fr-text-gray{color:#AAA}.fr-view .fr-text-bordered{border-top:solid 1px #222;border-bottom:solid 1px #222;padding:10px 0}' +
892
+ '.fr-view .fr-text-spaced{letter-spacing:1px}.fr-view .fr-text-uppercase{text-transform:uppercase}' +
893
+ '.fr-view img.fr-dib{display:block;margin:5px auto}.fr-view img.fr-dib.fr-fil{margin-left:0}.fr-view img.fr-dib.fr-fir{margin-right:0}' +
894
+ '.fr-view hr{border:0;border-bottom:1px solid #cccccc}';
895
+
896
+ // ======================= 8. presentational attributes =======================
897
+ var FONT_SIZE_ATTR = { 1: '7.5pt', 2: '10pt', 3: '12pt', 4: '13.5pt', 5: '18pt', 6: '24pt', 7: '36pt' };
898
+ function pxOrPct(v) { v = String(v).trim(); return /%$/.test(v) ? v : /^[\d.]+$/.test(v) ? v + 'px' : v; }
899
+ function hintDecls(e, out) {
900
+ var a = e.attrs, t = e.tag;
901
+ function put(p, v) { expandDecl(p, v, false, out); }
902
+ if (a.align) {
903
+ var al = a.align.toLowerCase();
904
+ if (t === 'table') { if (al === 'center') { put('margin-left', 'auto'); put('margin-right', 'auto'); } else if (al === 'right') put('margin-left', 'auto'); }
905
+ else if (t === 'img') { if (al === 'middle' || al === 'top' || al === 'bottom') put('vertical-align', al); }
906
+ else if (/^(p|div|h[1-6]|td|th|tr|tbody|thead|tfoot|caption|li|legend|center)$/.test(t)) put('text-align', al === 'middle' ? 'center' : al);
907
+ }
908
+ if (a.valign && /^(td|th|tr|tbody|thead|tfoot|col)$/.test(t)) put('vertical-align', a.valign.toLowerCase());
909
+ if (a.bgcolor) put('background-color', a.bgcolor);
910
+ if (t === 'font') {
911
+ if (a.color) put('color', a.color);
912
+ if (a.face) put('font-family', a.face);
913
+ if (a.size) {
914
+ var sz = String(a.size).trim(), base = /^[+-]/.test(sz) ? 3 + parseInt(sz, 10) : parseInt(sz, 10);
915
+ if (base > 0) put('font-size', FONT_SIZE_ATTR[clamp(base, 1, 7)]);
916
+ }
917
+ }
918
+ if (t === 'body' && a.text) put('color', a.text);
919
+ if (a.width && /^(table|td|th|col|colgroup|img|hr)$/.test(t)) put('width', pxOrPct(a.width));
920
+ if (a.height && /^(td|th|tr|img|table)$/.test(t)) put('height', pxOrPct(a.height));
921
+ if (t === 'table' && a.border !== undefined) {
922
+ var bw = a.border === '' ? 1 : parseInt(a.border, 10);
923
+ if (bw > 0) put('border', bw + 'px outset gray');
924
+ }
925
+ if (t === 'img' && a.border && parseInt(a.border, 10) > 0) put('border', parseInt(a.border, 10) + 'px solid');
926
+ if ((t === 'td' || t === 'th') && a.nowrap !== undefined) put('white-space', 'nowrap');
927
+ if (t === 'td' || t === 'th') {
928
+ var tbl = e.parent;
929
+ while (tbl && tbl.tag !== 'table' && tbl.tag !== '#root') tbl = tbl.parent;
930
+ if (tbl && tbl.tag === 'table') {
931
+ if (tbl.attrs.border !== undefined && (tbl.attrs.border === '' || parseInt(tbl.attrs.border, 10) > 0)) put('border', '1px inset gray');
932
+ if (tbl.attrs.cellpadding !== undefined) put('padding', pxOrPct(tbl.attrs.cellpadding));
933
+ }
934
+ }
935
+ if (t === 'hr') { if (a.color) { put('border-color', a.color); } if (a.size) put('border-top-width', pxOrPct(a.size)); }
936
+ if ((t === 'ol' || t === 'li') && a.type) {
937
+ var tp = { '1': 'decimal', a: 'lower-alpha', A: 'upper-alpha', i: 'lower-roman', I: 'upper-roman' }[a.type];
938
+ if (tp) put('list-style-type', tp);
939
+ }
940
+ if ((t === 'ul' || t === 'li') && /^(disc|circle|square)$/i.test(a.type || '')) put('list-style-type', a.type.toLowerCase());
941
+ }
942
+
943
+ // ======================= 9. computed style =======================
944
+ var INHERITED = toSet('color font-family font-size font-weight font-style font-variant line-height text-align text-indent ' +
945
+ 'text-transform letter-spacing white-space visibility list-style-type list-style-position border-collapse direction');
946
+
947
+ function rootStyle(o) {
948
+ return {
949
+ display: 'block', fontSize: o.fontSizePt || 12, fontFamily: o.fontFamily || 'Times New Roman', fontWeight: 400,
950
+ fontStyle: 'normal', fontVariant: 'normal', color: null, lineHeight: null, textAlign: 'left', textIndent: null,
951
+ textTransform: 'none', letterSpacing: 0, whiteSpace: 'normal', visibility: 'visible', listStyleType: 'disc',
952
+ listStylePosition: 'outside', borderCollapse: 'separate', deco: { u: null, s: false }, direction: 'ltr'
953
+ };
954
+ }
955
+
956
+ var U_STYLE = { solid: 'single', double: 'double', dotted: 'dotted', dashed: 'dash', wavy: 'wave' };
957
+
958
+ function computeStyle(e, d, p, rootFs) {
959
+ var cs = {};
960
+ function sv(prop) { var v = d[prop]; return v === undefined ? undefined : v; }
961
+ function isInh(v) { return v === 'inherit'; }
962
+ // font-size first (em units depend on it)
963
+ var fsv = sv('font-size'), fs = p.fontSize;
964
+ if (fsv !== undefined && !isInh(fsv) && fsv !== 'unset') {
965
+ var lf = fsv.toLowerCase();
966
+ if (lf === 'initial') fs = 12;
967
+ else if (FS_KEY[lf] !== undefined) fs = FS_KEY[lf];
968
+ else if (lf === 'smaller') fs = p.fontSize / 1.2;
969
+ else if (lf === 'larger') fs = p.fontSize * 1.2;
970
+ else { var L = parseLen(lf, p.fontSize, rootFs); if (L) fs = L.pct != null ? p.fontSize * L.pct / 100 : L.pt; }
971
+ }
972
+ cs.fontSize = Math.max(0, fs);
973
+ var ff = sv('font-family');
974
+ cs.fontFamily = ff && !isInh(ff) ? (firstFamily(ff) || p.fontFamily) : p.fontFamily;
975
+ var fw = sv('font-weight'), w = p.fontWeight;
976
+ if (fw && !isInh(fw)) {
977
+ fw = fw.toLowerCase();
978
+ w = fw === 'bold' ? 700 : fw === 'normal' ? 400 : fw === 'bolder' ? (p.fontWeight < 600 ? 700 : 900) : fw === 'lighter' ? (p.fontWeight > 500 ? 400 : 100) : (parseInt(fw, 10) || w);
979
+ }
980
+ cs.fontWeight = w;
981
+ var fst = sv('font-style');
982
+ cs.fontStyle = fst && !isInh(fst) ? (/italic|oblique/i.test(fst) ? 'italic' : 'normal') : p.fontStyle;
983
+ var fv = sv('font-variant');
984
+ cs.fontVariant = fv && !isInh(fv) ? (/small-caps/i.test(fv) ? 'small-caps' : 'normal') : p.fontVariant;
985
+ var col = sv('color');
986
+ if (col && !isInh(col)) { var pc = parseColor(col, p.color); cs.color = pc === undefined ? p.color : pc; } else cs.color = p.color;
987
+ var lh = sv('line-height');
988
+ if (lh && !isInh(lh)) {
989
+ var ll = lh.toLowerCase();
990
+ if (ll === 'normal' || ll === 'initial') cs.lineHeight = null;
991
+ else if (/^[\d.]+$/.test(ll)) cs.lineHeight = { m: parseFloat(ll) };
992
+ else { var LL = parseLen(ll, cs.fontSize, rootFs); cs.lineHeight = LL ? (LL.pct != null ? { pt: cs.fontSize * LL.pct / 100 } : { pt: LL.pt }) : p.lineHeight; }
993
+ } else cs.lineHeight = p.lineHeight;
994
+ var ta = sv('text-align');
995
+ if (ta && !isInh(ta)) {
996
+ ta = ta.toLowerCase().replace('-webkit-', '').replace('-moz-', '');
997
+ cs.textAlign = ta === 'start' ? 'left' : ta === 'end' ? 'right' : /^(left|right|center|justify)$/.test(ta) ? ta : p.textAlign;
998
+ } else cs.textAlign = p.textAlign;
999
+ var ti = sv('text-indent');
1000
+ cs.textIndent = ti && !isInh(ti) ? parseLen(ti, cs.fontSize, rootFs) : p.textIndent;
1001
+ var tt = sv('text-transform');
1002
+ cs.textTransform = tt && !isInh(tt) ? tt.toLowerCase() : p.textTransform;
1003
+ var ls = sv('letter-spacing');
1004
+ cs.letterSpacing = ls && !isInh(ls) ? (ls === 'normal' ? 0 : res0(parseLen(ls, cs.fontSize, rootFs), 0)) : p.letterSpacing;
1005
+ var ws = sv('white-space');
1006
+ cs.whiteSpace = ws && !isInh(ws) ? ws.toLowerCase() : p.whiteSpace;
1007
+ var vis = sv('visibility');
1008
+ cs.visibility = vis && !isInh(vis) ? vis.toLowerCase() : p.visibility;
1009
+ var lst = sv('list-style-type');
1010
+ cs.listStyleType = lst && !isInh(lst) ? lst.toLowerCase() : p.listStyleType;
1011
+ var lsp = sv('list-style-position');
1012
+ cs.listStylePosition = lsp && !isInh(lsp) ? lsp.toLowerCase() : p.listStylePosition;
1013
+ var bc = sv('border-collapse');
1014
+ cs.borderCollapse = bc && !isInh(bc) ? bc.toLowerCase() : p.borderCollapse;
1015
+ cs.direction = p.direction;
1016
+ // decorations propagate (union with the parent's)
1017
+ var tdl = sv('text-decoration-line'), tds = (sv('text-decoration-style') || 'solid').toLowerCase();
1018
+ var deco = { u: p.deco.u, s: p.deco.s };
1019
+ if (tdl && !isInh(tdl)) {
1020
+ tdl = tdl.toLowerCase();
1021
+ if (/underline/.test(tdl)) deco.u = U_STYLE[tds] || 'single';
1022
+ if (/line-through/.test(tdl)) deco.s = true;
1023
+ }
1024
+ cs.deco = deco;
1025
+ // non-inherited
1026
+ var disp = sv('display');
1027
+ cs.display = disp && !isInh(disp) ? disp.toLowerCase().replace(/^(-webkit-|-moz-)/, '') : 'inline';
1028
+ if (cs.display === 'contents') cs.display = 'inline';
1029
+ var bg = sv('background-color');
1030
+ cs.background = bg && !isInh(bg) ? (parseColor(bg, cs.color) || null) : null;
1031
+ cs.verticalAlign = (sv('vertical-align') || 'baseline').toLowerCase();
1032
+ if (cs.verticalAlign === 'inherit') cs.verticalAlign = p.verticalAlign || 'baseline';
1033
+ var fsz = cs.fontSize;
1034
+ function len(prop) { var v = sv(prop); if (v === undefined || v === 'initial' || v === 'unset') return null; if (isInh(v)) return p['_' + prop] || null; return parseLen(v, fsz, rootFs); }
1035
+ cs.m = [len('margin-top'), len('margin-right'), len('margin-bottom'), len('margin-left')];
1036
+ cs.pd = [len('padding-top'), len('padding-right'), len('padding-bottom'), len('padding-left')];
1037
+ cs.bd = SIDES.map(function (sd) {
1038
+ var st = (sv('border-' + sd + '-style') || 'none').toLowerCase();
1039
+ if (st === 'none' || st === 'hidden' || !BORDER_STYLES[st]) return null;
1040
+ var wv = (sv('border-' + sd + '-width') || 'medium').toLowerCase();
1041
+ var wpt = BW_KEY[wv] !== undefined ? BW_KEY[wv] : res0(parseLen(wv, fsz, rootFs), 0);
1042
+ if (!(wpt > 0)) return null;
1043
+ var cv = sv('border-' + sd + '-color'), cc = cv ? parseColor(cv, cs.color) : cs.color;
1044
+ if (cc === undefined) cc = cs.color;
1045
+ if (cc === null && cv && /transparent/i.test(cv)) return null;
1046
+ return { w: wpt, s: st, c: cc || '000000' };
1047
+ });
1048
+ cs.width = len('width'); cs.height = len('height');
1049
+ cs.minHeight = len('min-height'); cs.maxWidth = len('max-width'); cs.maxHeight = len('max-height');
1050
+ cs.pbBefore = (sv('page-break-before') || 'auto').toLowerCase();
1051
+ cs.pbAfter = (sv('page-break-after') || 'auto').toLowerCase();
1052
+ cs.pbInside = (sv('page-break-inside') || 'auto').toLowerCase();
1053
+ cs.tableLayout = (sv('table-layout') || 'auto').toLowerCase();
1054
+ cs.boxSizing = (sv('box-sizing') || 'content-box').toLowerCase();
1055
+ cs.float = (sv('float') || 'none').toLowerCase();
1056
+ var ta2 = sv('text-align-last');
1057
+ cs.textAlignLast = ta2 ? ta2.toLowerCase() : null;
1058
+ return cs;
1059
+ }
1060
+
1061
+ function computeAll(root, sheet, opts) {
1062
+ var rcs = rootStyle(opts), rootFs = 12;
1063
+ var uaRules = sheet.ua.slice().sort(function (a, b) { return a.spec - b.spec || a.order - b.order; });
1064
+ var auRules = sheet.author.slice().sort(function (a, b) { return a.spec - b.spec || a.order - b.order; });
1065
+ function matched(e, rules) {
1066
+ var out = [];
1067
+ for (var i = 0; i < rules.length; i++) { var r = rules[i]; if (matchComplex(e, r.parts, r.parts.length - 1)) out.push(r); }
1068
+ return out;
1069
+ }
1070
+ function walk(e, pcs) {
1071
+ var d = Object.create(null), i, j, k, dd;
1072
+ var mu = matched(e, uaRules), ma = matched(e, auRules), hints = [], inline = [];
1073
+ hintDecls(e, hints);
1074
+ if (e.attrs.style) inline = parseDecls(e.attrs.style);
1075
+ function apply(list, imp) { for (j = 0; j < list.length; j++) { dd = list[j]; if (dd.imp === imp) d[dd.p] = dd.v; } }
1076
+ for (i = 0; i < mu.length; i++) apply(mu[i].decls, false);
1077
+ apply(hints, false);
1078
+ for (i = 0; i < ma.length; i++) apply(ma[i].decls, false);
1079
+ apply(inline, false);
1080
+ for (i = 0; i < mu.length; i++) apply(mu[i].decls, true);
1081
+ for (i = 0; i < ma.length; i++) apply(ma[i].decls, true);
1082
+ apply(inline, true);
1083
+ var cs = computeStyle(e, d, pcs, rootFs);
1084
+ if (e.tag === 'html') rootFs = cs.fontSize;
1085
+ e.cs = cs;
1086
+ for (k = 0; k < e.els.length; k++) walk(e.els[k], cs);
1087
+ }
1088
+ root.cs = rcs;
1089
+ for (var k = 0; k < root.els.length; k++) walk(root.els[k], rcs);
1090
+ }
1091
+
1092
+ // ======================= 10. images =======================
1093
+ function imageInfo(bytes) {
1094
+ var b = bytes, n = b.length;
1095
+ if (n > 24 && b[0] === 0x89 && b[1] === 0x50 && b[2] === 0x4E && b[3] === 0x47)
1096
+ return { ext: 'png', mime: 'image/png', w: ((b[16] << 24) | (b[17] << 16) | (b[18] << 8) | b[19]) >>> 0, h: ((b[20] << 24) | (b[21] << 16) | (b[22] << 8) | b[23]) >>> 0 };
1097
+ if (n > 10 && b[0] === 0x47 && b[1] === 0x49 && b[2] === 0x46) return { ext: 'gif', mime: 'image/gif', w: b[6] | (b[7] << 8), h: b[8] | (b[9] << 8) };
1098
+ if (n > 26 && b[0] === 0x42 && b[1] === 0x4D) return { ext: 'bmp', mime: 'image/bmp', w: Math.abs(b[18] | (b[19] << 8) | (b[20] << 16) | (b[21] << 24)), h: Math.abs(b[22] | (b[23] << 8) | (b[24] << 16) | (b[25] << 24)) };
1099
+ if (n > 4 && b[0] === 0xFF && b[1] === 0xD8) {
1100
+ var i = 2;
1101
+ while (i + 9 < n) {
1102
+ if (b[i] !== 0xFF) { i++; continue; }
1103
+ var m = b[i + 1];
1104
+ if (m === 0xD8 || m === 0x01 || (m >= 0xD0 && m <= 0xD7) || m === 0xFF) { i += m === 0xFF ? 1 : 2; continue; }
1105
+ var len = (b[i + 2] << 8) | b[i + 3];
1106
+ if ((m >= 0xC0 && m <= 0xCF) && m !== 0xC4 && m !== 0xC8 && m !== 0xCC)
1107
+ return { ext: 'jpeg', mime: 'image/jpeg', h: (b[i + 5] << 8) | b[i + 6], w: (b[i + 7] << 8) | b[i + 8] };
1108
+ i += 2 + len;
1109
+ }
1110
+ return { ext: 'jpeg', mime: 'image/jpeg', w: 0, h: 0 };
1111
+ }
1112
+ return null;
1113
+ }
1114
+
1115
+ function loadImageSrc(src, remote) {
1116
+ src = String(src || '').trim();
1117
+ var m = /^data:([^;,]*)((?:;[^;,]*)*?);base64,/i.exec(src.slice(0, 200));
1118
+ if (m) {
1119
+ var bytes = b64decode(src.slice(m[0].length));
1120
+ var info = imageInfo(bytes);
1121
+ if (!info) return { error: 'unsupported image type ' + (m[1] || '?') };
1122
+ info.bytes = bytes;
1123
+ return info;
1124
+ }
1125
+ if (/^data:/i.test(src)) return { error: 'non-base64 data URI (' + src.slice(5, 30) + ')' };
1126
+ if (remote && remote[src]) {
1127
+ var rb = remote[src];
1128
+ if (rb.error) return rb;
1129
+ var inf = imageInfo(rb);
1130
+ if (!inf) return { error: 'unsupported image type at ' + src.slice(0, 80) };
1131
+ inf.bytes = rb;
1132
+ return inf;
1133
+ }
1134
+ return { error: 'image not embedded: ' + src.slice(0, 80) };
1135
+ }
1136
+
1137
+ // ======================= 11. layout =======================
1138
+ var JC = { left: 'left', right: 'right', center: 'center', justify: 'both' };
1139
+ var HL = { FFFF00: 'yellow', '00FF00': 'green', '00FFFF': 'cyan', FF00FF: 'magenta', '0000FF': 'blue', FF0000: 'red',
1140
+ '000080': 'darkBlue', '008080': 'darkCyan', '008000': 'darkGreen', '800080': 'darkMagenta', '800000': 'darkRed',
1141
+ '808000': 'darkYellow', '808080': 'darkGray', C0C0C0: 'lightGray', '000000': 'black' };
1142
+ var LIST_FMT = {
1143
+ disc: ['bullet', '•', 'Arial'], circle: ['bullet', 'o', 'Courier New'], square: ['bullet', '▪', 'Arial'],
1144
+ decimal: ['decimal', '.'], 'decimal-leading-zero': ['decimalZero', '.'], 'lower-alpha': ['lowerLetter', '.'],
1145
+ 'lower-latin': ['lowerLetter', '.'], 'upper-alpha': ['upperLetter', '.'], 'upper-latin': ['upperLetter', '.'],
1146
+ 'lower-roman': ['lowerRoman', '.'], 'upper-roman': ['upperRoman', '.'], none: ['none', '']
1147
+ };
1148
+
1149
+ function Layout(opts, page, warn) {
1150
+ this.opts = opts; this.page = page; this.warn = warn;
1151
+ this.media = []; this.mediaBySrc = Object.create(null); this.links = []; this.linkByUrl = Object.create(null);
1152
+ this.lists = []; this.absByFmt = Object.create(null); this.stats = { paragraphs: 0, tables: 0, images: 0, links: 0, lists: 0 };
1153
+ this.remote = null;
1154
+ }
1155
+
1156
+ function Flow() { this.items = []; this.para = null; this.pb = 0; this.pbFixed = 0; this.brk = false; }
1157
+
1158
+ function isBlockDisplay(d) { return d === 'block' || d === 'list-item' || d === 'table-caption' || d === 'flex' || d === 'grid' || d === 'flow-root' || d === 'table-row' || d === 'table-cell' || d === 'table-row-group' || d === 'table-header-group' || d === 'table-footer-group'; }
1159
+
1160
+ function hasBlockChild(e) {
1161
+ for (var i = 0; i < e.els.length; i++) {
1162
+ var c = e.els[i];
1163
+ if (c.cs.display !== 'none' && (isBlockDisplay(c.cs.display) || c.cs.display === 'table' || c.tag === 'table' || c.tag === 'hr')) return true;
1164
+ }
1165
+ return false;
1166
+ }
1167
+
1168
+ function hasContent(e) {
1169
+ if (e._hc !== undefined) return e._hc;
1170
+ var r = false;
1171
+ for (var i = 0; i < e.children.length && !r; i++) {
1172
+ var c = e.children[i];
1173
+ if (c.tag === '#text') { if (/[^ \t\n\r\f]/.test(c.text)) r = true; }
1174
+ else if (c.cs && c.cs.display === 'none') continue;
1175
+ else if (/^(img|br|hr|table|input|textarea)$/.test(c.tag)) r = true;
1176
+ else if (hasContent(c)) r = true;
1177
+ else if (isBlockDisplay(c.cs.display) && (res0(c.cs.height, 0) > 0 || res0(c.cs.minHeight, 0) > 0)) r = true;
1178
+ }
1179
+ e._hc = r;
1180
+ return r;
1181
+ }
1182
+
1183
+ Layout.prototype.runProps = function (cs, ctx) {
1184
+ var rp = {
1185
+ f: cs.fontFamily, sz: cs.fontSize, b: cs.fontWeight >= 600, i: cs.fontStyle === 'italic', u: cs.deco.u, s: cs.deco.s,
1186
+ c: cs.color, bg: ctx.bg || null, va: ctx.va || null, caps: cs.textTransform === 'uppercase',
1187
+ sc: cs.fontVariant === 'small-caps', ls: cs.letterSpacing || 0, hid: cs.visibility === 'hidden'
1188
+ };
1189
+ if (ctx.va && ctx.vaBase) rp.sz = ctx.vaBase;
1190
+ return rp;
1191
+ };
1192
+
1193
+ Layout.prototype.openPara = function (flow, ctx) {
1194
+ var b = ctx.block, cs = b.cs;
1195
+ var p = {
1196
+ kind: 'p', runs: [], cs: cs, before: flow.pbFixed + flow.pb, after: 0, lastSpace: true,
1197
+ ind: { l: ctx.indL, r: ctx.indR, first: 0, hang: 0 }, jc: cs.textAlign, lh: cs.lineHeight, family: cs.fontFamily,
1198
+ shd: ctx.blockBg || null, outline: b.outline, markRp: this.runProps(cs, { bg: null, va: null })
1199
+ };
1200
+ flow.pb = 0; flow.pbFixed = 0;
1201
+ if (flow.brk) { p.pageBreakBefore = true; flow.brk = false; }
1202
+ if (!b.used) { b.used = true; p.ind.first = res0(cs.textIndent, ctx.W); }
1203
+ if (ctx.li && !ctx.li.used) {
1204
+ ctx.li.used = true;
1205
+ if (ctx.li.numId) { p.num = { id: ctx.li.numId, ilvl: ctx.li.ilvl }; p.ind.hang = Math.min(18, Math.max(0, p.ind.l)); }
1206
+ }
1207
+ if (b.keepNext) p.keepNextBlock = true;
1208
+ flow.para = p;
1209
+ this.stats.paragraphs++;
1210
+ return p;
1211
+ };
1212
+
1213
+ function runVisible(r) { return r.img || r.tab || r.br || (r.t && /[^ ]/.test(r.t)); }
1214
+
1215
+ Layout.prototype.flush = function (flow) {
1216
+ var p = flow.para;
1217
+ if (!p) return;
1218
+ flow.para = null;
1219
+ var runs = p.runs;
1220
+ while (runs.length) { // trim trailing collapsible spaces
1221
+ var r = runs[runs.length - 1];
1222
+ if (r.t !== undefined && !r.pre) {
1223
+ r.t = r.t.replace(/ +$/, '');
1224
+ if (!r.t) { runs.pop(); continue; }
1225
+ }
1226
+ break;
1227
+ }
1228
+ var vis = runs.some(runVisible);
1229
+ if (!vis) {
1230
+ this.stats.paragraphs--;
1231
+ flow.pb = Math.max(flow.pb, p.before);
1232
+ if (p.pageBreakBefore) flow.brk = true;
1233
+ return;
1234
+ }
1235
+ if (runs.length > 1 && runs[runs.length - 1].br && !runs[runs.length - 1].pageBr) runs.pop();
1236
+ else if (runs.length === 1 && runs[0].br) runs.pop(); // a lone <br> is an empty line
1237
+ flow.items.push(p);
1238
+ };
1239
+
1240
+ Layout.prototype.addRun = function (flow, ctx, run) {
1241
+ var p = flow.para || this.openPara(flow, ctx);
1242
+ if (ctx.link) run.link = ctx.link;
1243
+ p.runs.push(run);
1244
+ return p;
1245
+ };
1246
+
1247
+ Layout.prototype.addText = function (text, cs, ctx, flow) {
1248
+ var ws = cs.whiteSpace || 'normal';
1249
+ var pre = ws === 'pre' || ws === 'pre-wrap' || ws === 'break-spaces', preLine = ws === 'pre-line';
1250
+ if (!pre) text = preLine ? text.replace(/[ \t\f\r]+/g, ' ').replace(/ ?\n ?/g, '\n') : text.replace(/[ \t\n\r\f]+/g, ' ');
1251
+ if (!text) return;
1252
+ var p = flow.para;
1253
+ if (!pre) {
1254
+ if (!p || p.lastSpace) text = text.replace(/^ /, '');
1255
+ if (!text) return;
1256
+ }
1257
+ var endsSpace = !pre && / $/.test(text);
1258
+ if (ws === 'nowrap') text = text.replace(/ (?=.)/g, ' ');
1259
+ if (cs.textTransform === 'lowercase') text = text.toLowerCase();
1260
+ else if (cs.textTransform === 'capitalize') {
1261
+ var prevSpace = !p || p.lastSpace;
1262
+ text = text.replace(/(^|[\s ("'“„«\[-])([^\s ])/g, function (m, a, c, off) {
1263
+ return off === 0 && !a && !prevSpace ? m : a + c.toUpperCase();
1264
+ });
1265
+ }
1266
+ var rp = this.runProps(cs, ctx), self = this;
1267
+ if (pre || preLine) {
1268
+ var lines = text.split('\n');
1269
+ lines.forEach(function (ln, idx) {
1270
+ if (idx > 0) self.addRun(flow, ctx, { br: true, rp: rp });
1271
+ if (pre) {
1272
+ ln.split('\t').forEach(function (seg, k) {
1273
+ if (k > 0) self.addRun(flow, ctx, { tab: true, rp: rp });
1274
+ if (seg) self.addRun(flow, ctx, { t: seg, rp: rp, pre: true });
1275
+ });
1276
+ } else if (ln) self.addRun(flow, ctx, { t: ln, rp: rp });
1277
+ });
1278
+ if (flow.para) flow.para.lastSpace = false;
1279
+ return;
1280
+ }
1281
+ p = this.addRun(flow, ctx, { t: text, rp: rp });
1282
+ p.lastSpace = endsSpace;
1283
+ };
1284
+
1285
+ Layout.prototype.children = function (e, ctx, flow) {
1286
+ for (var k = 0; k < e.children.length; k++) {
1287
+ var ch = e.children[k];
1288
+ if (ch.tag === '#text') this.addText(ch.text, e.cs, ctx, flow);
1289
+ else this.node(ch, ctx, flow);
1290
+ }
1291
+ };
1292
+
1293
+ Layout.prototype.node = function (e, ctx, flow) {
1294
+ var cs = e.cs, d = cs.display, t = e.tag;
1295
+ if (d === 'none') return;
1296
+ if (t === 'br') { var p = this.addRun(flow, ctx, { br: true, rp: this.runProps(cs, ctx) }); p.lastSpace = true; return; }
1297
+ if (t === 'img') { this.image(e, ctx, flow); return; }
1298
+ if (t === 'hr') { this.hr(e, ctx, flow); return; }
1299
+ if (t === 'input') { this.input(e, ctx, flow); return; }
1300
+ if (t === 'table' || d === 'table' || d === 'inline-table') { this.table(e, ctx, flow); return; }
1301
+ if (isBlockDisplay(d) || (d === 'inline-block' && hasBlockChild(e))) { this.block(e, ctx, flow); return; }
1302
+ // inline
1303
+ var c2 = ctx, va = cs.verticalAlign;
1304
+ var isVa = va === 'super' || va === 'sub';
1305
+ var href = t === 'a' && e.attrs.href ? String(e.attrs.href).trim() : null;
1306
+ if (href && (href.charAt(0) === '#' || /^javascript:/i.test(href))) href = null;
1307
+ if (cs.background || isVa || href) {
1308
+ c2 = Object.create(ctx);
1309
+ if (cs.background) c2.bg = cs.background;
1310
+ if (isVa && !ctx.va) { c2.va = va; c2.vaBase = e.parent && e.parent.cs ? e.parent.cs.fontSize : cs.fontSize; }
1311
+ if (href) { c2.link = href; this.stats.links++; }
1312
+ }
1313
+ this.children(e, c2, flow);
1314
+ if (d === 'inline-block' && cs.width && !cs.width.auto && res0(cs.width, ctx.W) > 0) {
1315
+ var pp = this.addRun(flow, c2, { tab: true, rp: this.runProps(cs, c2) });
1316
+ pp.lastSpace = true;
1317
+ }
1318
+ };
1319
+
1320
+ Layout.prototype.input = function (e, ctx, flow) {
1321
+ var ty = String(e.attrs.type || 'text').toLowerCase(), on = e.attrs.checked !== undefined, txt;
1322
+ if (ty === 'hidden') return;
1323
+ if (ty === 'checkbox') txt = on ? '☒' : '☐';
1324
+ else if (ty === 'radio') txt = on ? '◉' : '○';
1325
+ else txt = e.attrs.value || '';
1326
+ if (!txt) return;
1327
+ var p = this.addRun(flow, ctx, { t: txt, rp: this.runProps(e.cs, ctx) });
1328
+ p.lastSpace = false;
1329
+ };
1330
+
1331
+ function boxH(cs, W, folded) {
1332
+ if (folded) return { ml: 0, mr: 0, pl: 0, pr: 0, bl: 0, br: 0 };
1333
+ return {
1334
+ ml: res0(cs.m[3], W), mr: res0(cs.m[1], W), pl: Math.max(0, res0(cs.pd[3], W)), pr: Math.max(0, res0(cs.pd[1], W)),
1335
+ bl: cs.bd[3] ? cs.bd[3].w : 0, br: cs.bd[1] ? cs.bd[1].w : 0
1336
+ };
1337
+ }
1338
+ function isBreak(v) { return v === 'always' || v === 'page' || v === 'left' || v === 'right'; }
1339
+
1340
+ Layout.prototype.newList = function (e, cs) {
1341
+ var type = LIST_FMT[cs.listStyleType] ? cs.listStyleType : (e.tag === 'ol' ? 'decimal' : 'disc');
1342
+ if (!this.absByFmt[type]) this.absByFmt[type] = { id: Object.keys(this.absByFmt).length, type: type };
1343
+ var start = parseInt(e.attrs.start, 10);
1344
+ var lst = { numId: this.lists.length + 1, abs: this.absByFmt[type].id, start: start > 0 ? start : 1, ilvl: 0 };
1345
+ this.lists.push(lst);
1346
+ this.stats.lists++;
1347
+ return lst;
1348
+ };
1349
+
1350
+ Layout.prototype.block = function (e, ctx, flow) {
1351
+ var cs = e.cs, W = ctx.W;
1352
+ this.flush(flow);
1353
+ var h = boxH(cs, W, e.folded);
1354
+ var mt = res0(cs.m[0], W), mb = res0(cs.m[2], W), ptop = Math.max(0, res0(cs.pd[0], W)), pbot = Math.max(0, res0(cs.pd[2], W));
1355
+ var bt = cs.bd[0] ? cs.bd[0].w : 0, bb = cs.bd[2] ? cs.bd[2].w : 0;
1356
+ var wv = e.folded ? null : res(cs.width, W);
1357
+ if (wv != null && wv > 0) {
1358
+ var cw = cs.boxSizing === 'border-box' ? wv - h.pl - h.pr - h.bl - h.br : wv;
1359
+ var free = W - (cw + h.pl + h.pr + h.bl + h.br);
1360
+ var la = cs.m[3] && cs.m[3].auto, ra = cs.m[1] && cs.m[1].auto;
1361
+ if (la && ra) h.ml = h.mr = free / 2; else if (la) h.ml = free - h.mr; else h.mr = free - h.ml;
1362
+ }
1363
+ if (isBreak(cs.pbBefore)) flow.brk = true;
1364
+ if (ptop > 0 || bt > 0) { flow.pbFixed += Math.max(flow.pb, mt) + ptop + bt; flow.pb = 0; }
1365
+ else flow.pb = Math.max(flow.pb, mt);
1366
+ var start = flow.items.length;
1367
+ var hl = /^h([1-6])$/.exec(e.tag);
1368
+ var nctx = Object.create(ctx);
1369
+ nctx.W = Math.max(1, W - h.ml - h.mr - h.pl - h.pr - h.bl - h.br);
1370
+ nctx.indL = ctx.indL + h.ml + h.bl + h.pl;
1371
+ nctx.indR = ctx.indR + h.mr + h.br + h.pr;
1372
+ nctx.block = { cs: cs, el: e, used: false, outline: hl ? +hl[1] - 1 : null, keepNext: cs.pbAfter === 'avoid' };
1373
+ nctx.bg = null; nctx.va = null; nctx.vaBase = 0;
1374
+ if (cs.background) nctx.blockBg = cs.background;
1375
+ if (e.tag === 'ul' || e.tag === 'ol' || e.tag === 'menu' || e.tag === 'dir') {
1376
+ var lst = this.newList(e, cs);
1377
+ lst.ilvl = ctx.listDepth || 0;
1378
+ nctx.list = lst; nctx.listDepth = (ctx.listDepth || 0) + 1; nctx.li = null;
1379
+ } else if (cs.display === 'list-item') {
1380
+ var L = ctx.list;
1381
+ if (!L) { L = this.newList(e, cs); ctx.list = L; }
1382
+ var none = cs.listStyleType === 'none';
1383
+ nctx.li = { numId: none ? 0 : L.numId, ilvl: Math.min(8, L.ilvl), used: false };
1384
+ if (!none && cs.listStyleType !== this.lists[L.numId - 1].typeName) this.lists[L.numId - 1].typeName = cs.listStyleType;
1385
+ }
1386
+ if (!hasContent(e)) {
1387
+ var hh = res(cs.height, W);
1388
+ if (hh == null) hh = res(cs.minHeight, W);
1389
+ if (hh > 0.5) {
1390
+ var sp = { kind: 'p', runs: [], cs: cs, before: flow.pbFixed + flow.pb, after: 0, ind: { l: nctx.indL, r: nctx.indR, first: 0, hang: 0 }, exact: hh, markRp: { f: cs.fontFamily, sz: 1 }, shd: nctx.blockBg || null };
1391
+ if (flow.brk) { sp.pageBreakBefore = true; flow.brk = false; }
1392
+ flow.pb = 0; flow.pbFixed = 0;
1393
+ flow.items.push(sp);
1394
+ }
1395
+ } else this.children(e, nctx, flow);
1396
+ this.flush(flow);
1397
+ var last = flow.items.length > start ? flow.items[flow.items.length - 1] : null;
1398
+ var edgeB = pbot + bb;
1399
+ if (last && last.kind === 'p') {
1400
+ var a = Math.max(last.after, flow.pb);
1401
+ flow.pb = 0;
1402
+ last.after = edgeB > 0 ? a + edgeB + mb : Math.max(a, mb);
1403
+ if (flow.pbFixed) { last.after += flow.pbFixed; flow.pbFixed = 0; }
1404
+ } else if (last) flow.pb = Math.max(flow.pb, mb + edgeB);
1405
+ else { flow.pb = Math.max(flow.pb, mb); flow.pbFixed += edgeB; }
1406
+ if (isBreak(cs.pbAfter)) flow.brk = true;
1407
+ var bds = cs.bd;
1408
+ if (!e.folded && (bds[0] || bds[1] || bds[2] || bds[3])) {
1409
+ var bd = { t: bds[0], r: bds[1], b: bds[2], l: bds[3], sp: [ptop, h.pr, pbot, h.pl] };
1410
+ for (var k = start; k < flow.items.length; k++) if (flow.items[k].kind === 'p' && !flow.items[k].bdr) flow.items[k].bdr = bd;
1411
+ }
1412
+ if (cs.pbInside === 'avoid') applyKeep(flow.items, start);
1413
+ if (cs.pbAfter === 'avoid' && last && last.kind === 'p') last.keepNext = true;
1414
+ };
1415
+
1416
+ function eachPara(item, fn) {
1417
+ if (item.kind === 'p') { fn(item); return; }
1418
+ item.rows.forEach(function (r) { r.cells.forEach(function (c) { c.items.forEach(function (it) { eachPara(it, fn); }); }); });
1419
+ }
1420
+ function applyKeep(items, start) {
1421
+ for (var k = start; k < items.length; k++) {
1422
+ var it = items[k], isLast = k === items.length - 1;
1423
+ if (it.kind === 'p') { it.keepLines = true; if (!isLast) it.keepNext = true; }
1424
+ else {
1425
+ it.rows.forEach(function (r, ri) {
1426
+ r.cant = true;
1427
+ if (!isLast || ri < it.rows.length - 1) r.cells.forEach(function (c) { c.items.forEach(function (x) { eachPara(x, function (p) { p.keepNext = true; }); }); });
1428
+ });
1429
+ }
1430
+ }
1431
+ }
1432
+
1433
+ Layout.prototype.hr = function (e, ctx, flow) {
1434
+ var cs = e.cs, W = ctx.W;
1435
+ this.flush(flow);
1436
+ flow.pb = Math.max(flow.pb, res0(cs.m[0], W));
1437
+ var b = cs.bd[0] || cs.bd[2] || { w: 0.75, s: 'solid', c: '808080' };
1438
+ var p = { kind: 'p', runs: [], cs: cs, before: flow.pbFixed + flow.pb, after: 0, ind: { l: ctx.indL, r: ctx.indR, first: 0, hang: 0 }, exact: 1, markRp: { f: cs.fontFamily, sz: 1 }, bdr: { b: { w: b.w, s: b.s === 'inset' || b.s === 'outset' ? 'solid' : b.s, c: b.c }, sp: [0, 0, 0, 0] } };
1439
+ flow.pb = 0; flow.pbFixed = 0;
1440
+ if (flow.brk) { p.pageBreakBefore = true; flow.brk = false; }
1441
+ flow.items.push(p);
1442
+ p.after = res0(cs.m[2], W);
1443
+ };
1444
+
1445
+ Layout.prototype.image = function (e, ctx, flow) {
1446
+ var cs = e.cs, src = e.attrs.src || '';
1447
+ var info = this.mediaBySrc[src];
1448
+ if (!info) {
1449
+ info = loadImageSrc(src, this.remote);
1450
+ if (info.error) { this.warn(info.error); info = { error: info.error }; }
1451
+ else {
1452
+ info.idx = this.media.length + 1;
1453
+ info.name = 'image' + info.idx + '.' + info.ext;
1454
+ info.rid = 'rIdImg' + info.idx;
1455
+ this.media.push(info);
1456
+ }
1457
+ this.mediaBySrc[src] = info;
1458
+ }
1459
+ if (info.error) {
1460
+ var alt = e.attrs.alt;
1461
+ if (alt) { var pa = this.addRun(flow, ctx, { t: '[' + alt + ']', rp: this.runProps(cs, ctx) }); pa.lastSpace = false; }
1462
+ return;
1463
+ }
1464
+ var W = ctx.W;
1465
+ var w = res(cs.width, W), hgt = res(cs.height, null);
1466
+ var iw = info.w * 0.75, ih = info.h * 0.75;
1467
+ if (w == null && hgt == null) { w = iw; hgt = ih; }
1468
+ else if (w == null) w = ih ? hgt * iw / ih : hgt;
1469
+ else if (hgt == null) hgt = iw ? w * ih / iw : w;
1470
+ var mw = res(cs.maxWidth, W);
1471
+ if (mw != null && w > mw) { hgt = hgt * mw / w; w = mw; }
1472
+ if (w > W && W > 10) { hgt = hgt * W / w; w = W; }
1473
+ if (!(w > 0) || !(hgt > 0)) { w = w || 72; hgt = hgt || 72; }
1474
+ this.stats.images++;
1475
+ var run = { img: info, w: w, h: hgt, alt: e.attrs.alt || '', rp: this.runProps(cs, ctx) };
1476
+ if (cs.display === 'block') {
1477
+ this.flush(flow);
1478
+ var mt = res0(cs.m[0], W), mb = res0(cs.m[2], W);
1479
+ flow.pb = Math.max(flow.pb, mt);
1480
+ var bctx = Object.create(ctx);
1481
+ var la = cs.m[3] && cs.m[3].auto, ra = cs.m[1] && cs.m[1].auto;
1482
+ var jc = la && ra ? 'center' : la ? 'right' : 'left';
1483
+ bctx.block = { cs: Object.create(ctx.block.cs, { textAlign: { value: jc }, textIndent: { value: null }, lineHeight: { value: null } }), used: true };
1484
+ var p = this.openPara(flow, bctx);
1485
+ p.runs.push(run); p.lastSpace = false;
1486
+ this.flush(flow);
1487
+ p.after = Math.max(p.after, mb);
1488
+ return;
1489
+ }
1490
+ var pp = this.addRun(flow, ctx, run);
1491
+ pp.lastSpace = false;
1492
+ pp.hasImage = true;
1493
+ };
1494
+
1495
+ // ---------- tables ----------
1496
+ function textMetrics(e) { // rough min/max content widths in pt
1497
+ var mn = 0, mx = 0, line = 0;
1498
+ function walk(n, fs, bold) {
1499
+ if (n.tag === '#text') {
1500
+ var t = n.text.replace(/[ \t\n\r\f]+/g, ' ');
1501
+ var k = fs * (bold ? 0.56 : 0.52);
1502
+ t.split(' ').forEach(function (wd) { if (wd) mn = Math.max(mn, wd.length * k); });
1503
+ line += t.length * k;
1504
+ mx = Math.max(mx, line);
1505
+ return;
1506
+ }
1507
+ if (!n.cs || n.cs.display === 'none') return;
1508
+ if (n.tag === 'br') { line = 0; return; }
1509
+ if (n.tag === 'img') { var iw = res(n.cs.width, null) || 72; mn = Math.max(mn, iw); line += iw; mx = Math.max(mx, line); return; }
1510
+ var blk = isBlockDisplay(n.cs.display) || n.tag === 'table';
1511
+ if (blk) line = 0;
1512
+ for (var i = 0; i < n.children.length; i++) walk(n.children[i], n.cs.fontSize, n.cs.fontWeight >= 600);
1513
+ if (blk) line = 0;
1514
+ }
1515
+ walk(e, e.cs.fontSize, e.cs.fontWeight >= 600);
1516
+ return { min: mn, max: mx };
1517
+ }
1518
+
1519
+ Layout.prototype.table = function (e, ctx, flow) {
1520
+ var cs = e.cs, W = ctx.W, self = this;
1521
+ this.flush(flow);
1522
+ if (isBreak(cs.pbBefore)) flow.brk = true;
1523
+ var mt = res0(cs.m[0], W), mb = res0(cs.m[2], W);
1524
+ var before = flow.pbFixed + Math.max(flow.pb, mt);
1525
+ flow.pb = 0; flow.pbFixed = 0;
1526
+ var prev = flow.items[flow.items.length - 1];
1527
+ if (flow.brk) { flow.items.push(this.tinyPara(ctx, true)); flow.brk = false; }
1528
+ else if (before > 0.5) {
1529
+ if (prev && prev.kind === 'p') prev.after = Math.max(prev.after, before);
1530
+ else flow.items.push({ kind: 'p', runs: [], cs: cs, before: 0, after: 0, ind: { l: ctx.indL, r: ctx.indR, first: 0, hang: 0 }, exact: before, markRp: { f: cs.fontFamily, sz: 1 } });
1531
+ }
1532
+ // rows and columns
1533
+ var head = [], body = [], foot = [], cols = [], caption = null;
1534
+ function rowOf(tr, header) { return { el: tr, header: header, cells: tr.els.filter(function (c) { return (c.tag === 'td' || c.tag === 'th') && c.cs.display !== 'none'; }) }; }
1535
+ function scan(container, target, header) {
1536
+ var loose = null;
1537
+ container.els.forEach(function (c) {
1538
+ if (c.cs.display === 'none') return;
1539
+ if (c.tag === 'tr') { loose = null; target.push(rowOf(c, header)); }
1540
+ else if (c.tag === 'td' || c.tag === 'th') { if (!loose) { loose = { el: null, header: header, cells: [] }; target.push(loose); } loose.cells.push(c); }
1541
+ else if (c.tag === 'thead') scan(c, head, true);
1542
+ else if (c.tag === 'tbody') scan(c, body, false);
1543
+ else if (c.tag === 'tfoot') scan(c, foot, false);
1544
+ else if (c.tag === 'caption') caption = c;
1545
+ else if (c.tag === 'colgroup') {
1546
+ if (c.els.length) c.els.forEach(function (col) { if (col.tag === 'col') cols.push({ el: col, span: Math.max(1, parseInt(col.attrs.span, 10) || 1) }); });
1547
+ else cols.push({ el: c, span: Math.max(1, parseInt(c.attrs.span, 10) || 1) });
1548
+ } else if (c.tag === 'col') cols.push({ el: c, span: Math.max(1, parseInt(c.attrs.span, 10) || 1) });
1549
+ else if (c.tag === 'form') scan(c, target, header);
1550
+ });
1551
+ }
1552
+ scan(e, body, false);
1553
+ if (caption) this.block(caption, ctx, flow);
1554
+ var rows = head.concat(body, foot).filter(function (r) { return r.cells.length; });
1555
+ if (!rows.length) { flow.pb = Math.max(flow.pb, mb); return; }
1556
+ var R = rows.length, grid = [], cells = [], nC = 0, r, c;
1557
+ for (r = 0; r < R; r++) grid[r] = grid[r] || [];
1558
+ for (r = 0; r < R; r++) {
1559
+ c = 0;
1560
+ rows[r].cells.forEach(function (td) {
1561
+ while (grid[r][c]) c++;
1562
+ var csn = clamp(parseInt(td.attrs.colspan, 10) || 1, 1, 1000);
1563
+ var rsn = parseInt(td.attrs.rowspan, 10);
1564
+ rsn = isNaN(rsn) ? 1 : rsn === 0 ? R - r : clamp(rsn, 1, R - r);
1565
+ var cell = { el: td, r: r, c: c, cs: csn, rs: rsn };
1566
+ for (var rr = r; rr < r + rsn; rr++) for (var cc = c; cc < c + csn; cc++) grid[rr][cc] = (rr === r && cc === c) ? cell : { cont: cell, top: rr === r };
1567
+ cells.push(cell);
1568
+ c += csn;
1569
+ });
1570
+ }
1571
+ for (r = 0; r < R; r++) nC = Math.max(nC, grid[r].length);
1572
+ // widths
1573
+ var tw = res(cs.width, W);
1574
+ var mlL = cs.m[3], mrL = cs.m[1];
1575
+ var colL = new Array(nC), colPt = new Array(nC), i;
1576
+ for (i = 0; i < nC; i++) colL[i] = null;
1577
+ var ci = 0;
1578
+ cols.forEach(function (col) { for (var k = 0; k < col.span && ci < nC; k++, ci++) if (col.el.cs.width && !col.el.cs.width.auto) colL[ci] = col.el.cs.width; });
1579
+ cells.forEach(function (cl) {
1580
+ if (cl.cs === 1 && !colL[cl.c] && cl.el.cs.width && !cl.el.cs.width.auto) {
1581
+ var L = cl.el.cs.width;
1582
+ if (L.pt != null && cl.el.cs.boxSizing !== 'border-box') {
1583
+ var ccs = cl.el.cs, ref = tw || W;
1584
+ L = { pt: L.pt + res0(ccs.pd[1], ref) + res0(ccs.pd[3], ref) };
1585
+ }
1586
+ colL[cl.c] = L;
1587
+ }
1588
+ });
1589
+ var ref = tw != null ? tw : W, known = 0, unknown = [];
1590
+ for (i = 0; i < nC; i++) {
1591
+ var v = res(colL[i], ref);
1592
+ if (v != null && v > 0) { colPt[i] = v; known += v; } else { colPt[i] = null; unknown.push(i); }
1593
+ }
1594
+ if (unknown.length) {
1595
+ var mins = [], maxs = [];
1596
+ for (i = 0; i < nC; i++) { mins[i] = 0; maxs[i] = 0; }
1597
+ cells.forEach(function (cl) {
1598
+ if (cl.cs !== 1) return;
1599
+ var m = textMetrics(cl.el), ccs = cl.el.cs, padx = res0(ccs.pd[1], W) + res0(ccs.pd[3], W) + 2;
1600
+ mins[cl.c] = Math.max(mins[cl.c], m.min + padx);
1601
+ maxs[cl.c] = Math.max(maxs[cl.c], m.max + padx);
1602
+ });
1603
+ var avail = (tw != null ? tw : W) - known, smin = 0, smax = 0;
1604
+ unknown.forEach(function (k) { mins[k] = Math.max(mins[k], 14); maxs[k] = Math.max(maxs[k], mins[k]); smin += mins[k]; smax += maxs[k]; });
1605
+ if (tw == null && smax <= avail) unknown.forEach(function (k) { colPt[k] = maxs[k]; });
1606
+ else if (tw != null && smax <= avail) unknown.forEach(function (k) { colPt[k] = maxs[k] + (avail - smax) * (smax ? maxs[k] / smax : 1 / unknown.length); });
1607
+ else if (smin >= avail) unknown.forEach(function (k) { colPt[k] = Math.max(14, avail > 0 ? mins[k] * avail / smin : mins[k]); });
1608
+ else unknown.forEach(function (k) { colPt[k] = mins[k] + (maxs[k] - mins[k]) * (avail - smin) / (smax - smin); });
1609
+ }
1610
+ var sum = 0;
1611
+ for (i = 0; i < nC; i++) sum += colPt[i];
1612
+ if (tw == null) tw = sum;
1613
+ if (sum > 0 && Math.abs(sum - tw) > 0.5) for (i = 0; i < nC; i++) colPt[i] = colPt[i] * tw / sum;
1614
+ // position
1615
+ var ind;
1616
+ if (mlL && mlL.auto && mrL && mrL.auto) ind = ctx.indL + (W - tw) / 2;
1617
+ else if (mlL && mlL.auto) ind = ctx.indL + W - tw - res0(mrL, W);
1618
+ else ind = ctx.indL + res0(mlL, W);
1619
+ // twips grid
1620
+ var colTw = colPt.map(function (x) { return Math.max(1, twip(x)); });
1621
+ var tbl = { kind: 'tbl', ind: ind, cols: colTw, rows: [], borders: cs.bd, bg: cs.background };
1622
+ this.stats.tables++;
1623
+ var tableBg = cs.background;
1624
+ for (r = 0; r < R; r++) {
1625
+ var rowEl = rows[r].el, rcs = rowEl ? rowEl.cs : null;
1626
+ var row = { cells: [], h: rcs ? res0(rcs.height, null) : 0, cant: !!(rcs && rcs.pbInside === 'avoid'), header: rows[r].header && r < head.length };
1627
+ var rowBg = (rcs && rcs.background) || (rowEl && rowEl.parent && rowEl.parent.cs && rowEl.parent.tag !== 'table' ? rowEl.parent.cs.background : null);
1628
+ for (c = 0; c < nC;) {
1629
+ var g = grid[r][c];
1630
+ if (!g) {
1631
+ var c0 = c;
1632
+ while (c < nC && !grid[r][c]) c++;
1633
+ row.cells.push({ w: sumTw(colTw, c0, c), span: c - c0, items: [this.tinyPara(ctx, false)], bd: [null, null, null, null], pad: [0, 0, 0, 0], vAlign: 'top' });
1634
+ continue;
1635
+ }
1636
+ var cell = g.cont || g;
1637
+ var info = this.cell(cell, colTw, rowBg || tableBg, g.cont ? 'continue' : (cell.rs > 1 ? 'restart' : null), ctx);
1638
+ if (!g.cont) row.h = Math.max(row.h, info.h || 0);
1639
+ row.cells.push(info);
1640
+ c += cell.cs;
1641
+ }
1642
+ tbl.rows.push(row);
1643
+ }
1644
+ flow.items.push(tbl);
1645
+ flow.pb = mb;
1646
+ if (isBreak(cs.pbAfter)) flow.brk = true;
1647
+ if (cs.pbInside === 'avoid') applyKeep(flow.items, flow.items.length - 1);
1648
+ };
1649
+
1650
+ function sumTw(arr, a, b) { var s = 0; for (var i = a; i < b; i++) s += arr[i]; return s; }
1651
+
1652
+ Layout.prototype.tinyPara = function (ctx, pageBreak) {
1653
+ var p = { kind: 'p', runs: [], cs: ctx.block.cs, before: 0, after: 0, ind: { l: 0, r: 0, first: 0, hang: 0 }, exact: 1, markRp: { f: ctx.block.cs.fontFamily, sz: 1 } };
1654
+ if (pageBreak) p.pageBreakBefore = true;
1655
+ return p;
1656
+ };
1657
+
1658
+ Layout.prototype.cell = function (cell, colTw, bgFallback, vMerge, ctx) {
1659
+ var td = cell.el, ccs = td.cs;
1660
+ var wTw = sumTw(colTw, cell.c, cell.c + cell.cs), wPt = wTw / 20;
1661
+ var pad = [res0(ccs.pd[0], wPt), res0(ccs.pd[1], wPt), res0(ccs.pd[2], wPt), res0(ccs.pd[3], wPt)].map(function (x) { return Math.max(0, x); });
1662
+ var va = ccs.verticalAlign, vAlign = va === 'middle' ? 'center' : va === 'bottom' ? 'bottom' : 'top';
1663
+ var info = { w: wTw, span: cell.cs, vMerge: vMerge, bd: ccs.bd, pad: pad, shd: ccs.background || bgFallback || null, vAlign: vAlign, noWrap: ccs.whiteSpace === 'nowrap', h: res0(ccs.height, null) };
1664
+ var cflow = new Flow();
1665
+ var cctx = Object.create(ctx);
1666
+ cctx.W = Math.max(1, wPt - pad[1] - pad[3]); cctx.indL = 0; cctx.indR = 0;
1667
+ cctx.block = { cs: ccs, el: td, used: false, outline: null };
1668
+ cctx.bg = null; cctx.va = null; cctx.vaBase = 0; cctx.link = null; cctx.blockBg = null; cctx.li = null; cctx.list = null; cctx.listDepth = 0;
1669
+ if (vMerge !== 'continue') { this.children(td, cctx, cflow); this.flush(cflow); }
1670
+ var items = cflow.items, last = items[items.length - 1];
1671
+ if (last && last.kind === 'p' && cflow.pb > 0) last.after = Math.max(last.after, cflow.pb);
1672
+ if (!last || last.kind !== 'p') {
1673
+ var ep = { kind: 'p', runs: [], cs: ccs, before: 0, after: 0, ind: { l: 0, r: 0, first: 0, hang: 0 }, jc: ccs.textAlign, lh: ccs.lineHeight, family: ccs.fontFamily, markRp: this.runProps(ccs, { bg: null, va: null }) };
1674
+ if (last) { ep.exact = 1; ep.markRp = { f: ccs.fontFamily, sz: 1 }; }
1675
+ items.push(ep);
1676
+ }
1677
+ info.items = items;
1678
+ return info;
1679
+ };
1680
+
1681
+ // ======================= 12. serialization =======================
1682
+ var BSTYLE = { solid: 'single', dashed: 'dashed', dotted: 'dotted', double: 'double', groove: 'threeDEngrave', ridge: 'threeDEmboss', inset: 'single', outset: 'single' };
1683
+
1684
+ function bdrXml(tag, b, space) {
1685
+ if (!b) return '<w:' + tag + ' w:val="nil"/>';
1686
+ var st = BSTYLE[b.s] || 'single', w = b.w;
1687
+ if (st === 'double') w = w / 3;
1688
+ var sz = clamp(Math.round(w * 8), 2, 96);
1689
+ return '<w:' + tag + ' w:val="' + st + '" w:sz="' + sz + '" w:space="' + clamp(Math.round(space || 0), 0, 31) + '" w:color="' + (b.c || 'auto') + '"/>';
1690
+ }
1691
+
1692
+ function Writer(layout, defaults) {
1693
+ this.L = layout; this.D = defaults; this.docPr = 0; this.rels = []; this.relByUrl = Object.create(null);
1694
+ }
1695
+ Writer.prototype.rPr = function (rp) {
1696
+ if (!rp) return '';
1697
+ var D = this.D, x = '';
1698
+ if (rp.f && rp.f !== D.f) { var f = xesc(rp.f); x += '<w:rFonts w:ascii="' + f + '" w:hAnsi="' + f + '" w:eastAsia="' + f + '" w:cs="' + f + '"/>'; }
1699
+ if (rp.b) x += '<w:b/><w:bCs/>';
1700
+ if (rp.i) x += '<w:i/><w:iCs/>';
1701
+ if (rp.caps) x += '<w:caps/>';
1702
+ if (rp.sc) x += '<w:smallCaps/>';
1703
+ if (rp.s) x += '<w:strike/>';
1704
+ if (rp.hid) x += '<w:vanish/>';
1705
+ if (rp.c && rp.c !== '000000') x += '<w:color w:val="' + rp.c + '"/>';
1706
+ if (rp.ls) x += '<w:spacing w:val="' + twip(rp.ls) + '"/>';
1707
+ var hs = Math.max(2, Math.round((rp.sz || 1) * 2));
1708
+ if (hs !== D.sz2) x += '<w:sz w:val="' + hs + '"/><w:szCs w:val="' + hs + '"/>';
1709
+ if (rp.bg && HL[rp.bg]) x += '<w:highlight w:val="' + HL[rp.bg] + '"/>';
1710
+ if (rp.u) x += '<w:u w:val="' + rp.u + '"/>';
1711
+ if (rp.bg && !HL[rp.bg]) x += '<w:shd w:val="clear" w:color="auto" w:fill="' + rp.bg + '"/>';
1712
+ if (rp.va) x += '<w:vertAlign w:val="' + (rp.va === 'super' ? 'superscript' : 'subscript') + '"/>';
1713
+ return x ? '<w:rPr>' + x + '</w:rPr>' : '';
1714
+ };
1715
+ Writer.prototype.linkRel = function (url) {
1716
+ if (!this.relByUrl[url]) { var id = 'rIdLnk' + (this.rels.length + 1); this.relByUrl[url] = id; this.rels.push({ id: id, url: url }); }
1717
+ return this.relByUrl[url];
1718
+ };
1719
+ Writer.prototype.drawing = function (r) {
1720
+ var id = ++this.docPr, img = r.img, cx = Math.max(1, Math.round(r.w * 12700)), cy = Math.max(1, Math.round(r.h * 12700));
1721
+ return '<w:drawing><wp:inline distT="0" distB="0" distL="0" distR="0"><wp:extent cx="' + cx + '" cy="' + cy + '"/>' +
1722
+ '<wp:effectExtent l="0" t="0" r="0" b="0"/><wp:docPr id="' + id + '" name="Picture ' + id + '"' + (r.alt ? ' descr="' + xesc(r.alt) + '"' : '') + '/>' +
1723
+ '<wp:cNvGraphicFramePr><a:graphicFrameLocks xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" noChangeAspect="1"/></wp:cNvGraphicFramePr>' +
1724
+ '<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"><a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">' +
1725
+ '<pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:nvPicPr><pic:cNvPr id="' + id + '" name="' + img.name + '"/><pic:cNvPicPr/></pic:nvPicPr>' +
1726
+ '<pic:blipFill><a:blip r:embed="' + img.rid + '"/><a:stretch><a:fillRect/></a:stretch></pic:blipFill>' +
1727
+ '<pic:spPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="' + cx + '" cy="' + cy + '"/></a:xfrm><a:prstGeom prst="rect"><a:avLst/></a:prstGeom></pic:spPr>' +
1728
+ '</pic:pic></a:graphicData></a:graphic></wp:inline></w:drawing>';
1729
+ };
1730
+ Writer.prototype.runs = function (runs, out) {
1731
+ // merge adjacent text runs with identical formatting
1732
+ var merged = [], i;
1733
+ for (i = 0; i < runs.length; i++) {
1734
+ var r = runs[i];
1735
+ r.key = this.rPr(r.rp);
1736
+ var prev = merged[merged.length - 1];
1737
+ if (r.t !== undefined && prev && prev.t !== undefined && prev.key === r.key && prev.link === r.link) prev.t += r.t;
1738
+ else merged.push({ t: r.t, tab: r.tab, br: r.br, img: r.img ? r : null, key: r.key, link: r.link });
1739
+ }
1740
+ i = 0;
1741
+ while (i < merged.length) {
1742
+ var link = merged[i].link;
1743
+ if (link) {
1744
+ out.push('<w:hyperlink r:id="' + this.linkRel(link) + '" w:history="1">');
1745
+ while (i < merged.length && merged[i].link === link) this.run(merged[i++], out);
1746
+ out.push('</w:hyperlink>');
1747
+ } else this.run(merged[i++], out);
1748
+ }
1749
+ };
1750
+ Writer.prototype.run = function (m, out) {
1751
+ var body;
1752
+ if (m.t !== undefined) body = '<w:t xml:space="preserve">' + xesc(m.t) + '</w:t>';
1753
+ else if (m.tab) body = '<w:tab/>';
1754
+ else if (m.br) body = '<w:br/>';
1755
+ else if (m.img) body = this.drawing(m.img);
1756
+ else return;
1757
+ out.push('<w:r>' + m.key + body + '</w:r>');
1758
+ };
1759
+ Writer.prototype.para = function (p, out) {
1760
+ var x = '';
1761
+ if (p.keepNext) x += '<w:keepNext/>';
1762
+ if (p.keepLines) x += '<w:keepLines/>';
1763
+ if (p.pageBreakBefore) x += '<w:pageBreakBefore/>';
1764
+ if (p.num) x += '<w:numPr><w:ilvl w:val="' + p.num.ilvl + '"/><w:numId w:val="' + p.num.id + '"/></w:numPr>';
1765
+ if (p.bdr) {
1766
+ var b = p.bdr;
1767
+ x += '<w:pBdr>' + (b.t ? bdrXml('top', b.t, b.sp[0]) : '') + (b.l ? bdrXml('left', b.l, b.sp[3]) : '') +
1768
+ (b.b ? bdrXml('bottom', b.b, b.sp[2]) : '') + (b.r ? bdrXml('right', b.r, b.sp[1]) : '') + '</w:pBdr>';
1769
+ }
1770
+ if (p.shd) x += '<w:shd w:val="clear" w:color="auto" w:fill="' + p.shd + '"/>';
1771
+ var line = 240, rule = 'auto';
1772
+ if (p.exact != null) { line = Math.max(2, twip(p.exact)); rule = 'exact'; }
1773
+ else if (p.lh && p.lh.pt != null && p.lh.pt > 0) { line = Math.max(2, twip(p.lh.pt)); rule = p.hasImage ? 'atLeast' : 'exact'; }
1774
+ else if (p.lh && p.lh.m > 0) {
1775
+ var fac = LINE_FACTOR[String(p.family || '').toLowerCase()] || 1.15;
1776
+ line = Math.max(24, Math.round(240 * p.lh.m / fac));
1777
+ }
1778
+ x += '<w:spacing w:before="' + clamp(twip(p.before), 0, 31680) + '" w:after="' + clamp(twip(p.after), 0, 31680) + '" w:line="' + line + '" w:lineRule="' + rule + '"/>';
1779
+ var l = twip(p.ind.l), r = twip(p.ind.r), f = twip(p.ind.first || 0);
1780
+ if (p.num) x += '<w:ind w:left="' + l + '" w:right="' + r + '" w:hanging="' + twip(p.ind.hang) + '"/>';
1781
+ else if (l || r || f) x += '<w:ind w:left="' + l + '" w:right="' + r + '"' + (f > 0 ? ' w:firstLine="' + f + '"' : f < 0 ? ' w:hanging="' + (-f) + '"' : '') + '/>';
1782
+ var jc = JC[p.jc];
1783
+ if (jc && jc !== 'left') x += '<w:jc w:val="' + jc + '"/>';
1784
+ if (p.outline != null) x += '<w:outlineLvl w:val="' + p.outline + '"/>';
1785
+ x += this.rPr(p.markRp);
1786
+ out.push('<w:p>' + (x ? '<w:pPr>' + x + '</w:pPr>' : ''));
1787
+ this.runs(p.runs, out);
1788
+ out.push('</w:p>');
1789
+ };
1790
+ Writer.prototype.table = function (t, out) {
1791
+ var W = 0;
1792
+ t.cols.forEach(function (c) { W += c; });
1793
+ var x = '<w:tbl><w:tblPr><w:tblW w:w="' + W + '" w:type="dxa"/><w:tblInd w:w="' + twip(t.ind) + '" w:type="dxa"/>';
1794
+ var b = t.borders || [];
1795
+ x += '<w:tblBorders>' + bdrXml('top', b[0]) + bdrXml('left', b[3]) + bdrXml('bottom', b[2]) + bdrXml('right', b[1]) +
1796
+ '<w:insideH w:val="nil"/><w:insideV w:val="nil"/></w:tblBorders>';
1797
+ if (t.bg) x += '<w:shd w:val="clear" w:color="auto" w:fill="' + t.bg + '"/>';
1798
+ x += '<w:tblLayout w:type="fixed"/><w:tblCellMar><w:top w:w="0" w:type="dxa"/><w:left w:w="0" w:type="dxa"/>' +
1799
+ '<w:bottom w:w="0" w:type="dxa"/><w:right w:w="0" w:type="dxa"/></w:tblCellMar><w:tblLook w:val="0000"/></w:tblPr><w:tblGrid>';
1800
+ t.cols.forEach(function (c) { x += '<w:gridCol w:w="' + c + '"/>'; });
1801
+ out.push(x + '</w:tblGrid>');
1802
+ var self = this;
1803
+ t.rows.forEach(function (row) {
1804
+ var tr = '';
1805
+ if (row.cant) tr += '<w:cantSplit/>';
1806
+ if (row.h > 0.5) tr += '<w:trHeight w:val="' + twip(row.h) + '" w:hRule="atLeast"/>';
1807
+ if (row.header) tr += '<w:tblHeader/>';
1808
+ out.push('<w:tr>' + (tr ? '<w:trPr>' + tr + '</w:trPr>' : ''));
1809
+ row.cells.forEach(function (cl) {
1810
+ var bd = cl.bd || [], pd = cl.pad || [0, 0, 0, 0];
1811
+ var tc = '<w:tcW w:w="' + cl.w + '" w:type="dxa"/>';
1812
+ if (cl.span > 1) tc += '<w:gridSpan w:val="' + cl.span + '"/>';
1813
+ if (cl.vMerge === 'restart') tc += '<w:vMerge w:val="restart"/>';
1814
+ else if (cl.vMerge === 'continue') tc += '<w:vMerge/>';
1815
+ tc += '<w:tcBorders>' + bdrXml('top', bd[0]) + bdrXml('left', bd[3]) + bdrXml('bottom', bd[2]) + bdrXml('right', bd[1]) + '</w:tcBorders>';
1816
+ if (cl.shd) tc += '<w:shd w:val="clear" w:color="auto" w:fill="' + cl.shd + '"/>';
1817
+ if (cl.noWrap) tc += '<w:noWrap/>';
1818
+ tc += '<w:tcMar><w:top w:w="' + twip(pd[0]) + '" w:type="dxa"/><w:left w:w="' + twip(pd[3]) + '" w:type="dxa"/>' +
1819
+ '<w:bottom w:w="' + twip(pd[2]) + '" w:type="dxa"/><w:right w:w="' + twip(pd[1]) + '" w:type="dxa"/></w:tcMar>';
1820
+ tc += '<w:vAlign w:val="' + (cl.vAlign || 'top') + '"/>';
1821
+ out.push('<w:tc><w:tcPr>' + tc + '</w:tcPr>');
1822
+ self.items(cl.items, out);
1823
+ out.push('</w:tc>');
1824
+ });
1825
+ out.push('</w:tr>');
1826
+ });
1827
+ out.push('</w:tbl>');
1828
+ };
1829
+ Writer.prototype.items = function (items, out) {
1830
+ for (var i = 0; i < items.length; i++) {
1831
+ if (items[i].kind === 'p') this.para(items[i], out); else this.table(items[i], out);
1832
+ }
1833
+ };
1834
+
1835
+ function collapse(items) {
1836
+ for (var k = 0; k < items.length; k++) {
1837
+ var b = items[k], a = items[k - 1];
1838
+ if (b.kind === 'p') {
1839
+ b.before = Math.max(0, b.before); b.after = Math.max(0, b.after);
1840
+ if (b.keepNextBlock) b.keepNext = true;
1841
+ if (a && a.kind === 'p' && !b.pageBreakBefore) b.before = Math.max(0, b.before - Math.max(0, a.after));
1842
+ } else b.rows.forEach(function (r) { r.cells.forEach(function (c) { collapse(c.items); }); });
1843
+ }
1844
+ }
1845
+
1846
+ function countFonts(items, acc) {
1847
+ items.forEach(function (it) {
1848
+ if (it.kind === 'p') it.runs.forEach(function (r) {
1849
+ if (r.t && r.rp) { var k = r.rp.f + '|' + Math.round(r.rp.sz * 2); acc[k] = (acc[k] || 0) + r.t.length; }
1850
+ });
1851
+ else it.rows.forEach(function (r) { r.cells.forEach(function (c) { countFonts(c.items, acc); }); });
1852
+ });
1853
+ }
1854
+
1855
+ function lvlXml(fmt, ilvl, start) {
1856
+ var F = LIST_FMT[fmt] || LIST_FMT.disc, isBullet = F[0] === 'bullet';
1857
+ var text = isBullet ? F[1] : F[0] === 'none' ? '' : '%' + (ilvl + 1) + F[1];
1858
+ var x = '<w:lvl w:ilvl="' + ilvl + '"><w:start w:val="' + (start || 1) + '"/><w:numFmt w:val="' + F[0] + '"/><w:lvlText w:val="' + xesc(text) + '"/>' +
1859
+ '<w:lvlJc w:val="left"/><w:pPr><w:ind w:left="' + (720 * (ilvl + 1)) + '" w:hanging="360"/></w:pPr>';
1860
+ if (isBullet) x += '<w:rPr><w:rFonts w:ascii="' + F[2] + '" w:hAnsi="' + F[2] + '" w:hint="default"/></w:rPr>';
1861
+ return x + '</w:lvl>';
1862
+ }
1863
+
1864
+ function numberingXml(L) {
1865
+ var x = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:numbering xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">';
1866
+ var abs = L.absByFmt;
1867
+ Object.keys(abs).forEach(function (fmt) {
1868
+ x += '<w:abstractNum w:abstractNumId="' + abs[fmt].id + '"><w:multiLevelType w:val="hybridMultilevel"/>';
1869
+ for (var i = 0; i < 9; i++) x += lvlXml(fmt, i, 1);
1870
+ x += '</w:abstractNum>';
1871
+ });
1872
+ L.lists.forEach(function (l) {
1873
+ var absId = l.abs;
1874
+ if (l.typeName && LIST_FMT[l.typeName]) {
1875
+ if (!abs[l.typeName]) { /* registered lazily below */ } else absId = abs[l.typeName].id;
1876
+ }
1877
+ x += '<w:num w:numId="' + l.numId + '"><w:abstractNumId w:val="' + absId + '"/><w:lvlOverride w:ilvl="' + Math.min(8, l.ilvl) + '"><w:startOverride w:val="' + l.start + '"/></w:lvlOverride></w:num>';
1878
+ });
1879
+ return x + '</w:numbering>';
1880
+ }
1881
+
1882
+ var PAGE_SIZES = { a3: [841.89, 1190.55], a4: [595.28, 841.89], a5: [419.53, 595.28], letter: [612, 792], legal: [612, 1008], b5: [498.9, 708.66] };
1883
+
1884
+ function pageSetup(sheet, opts) {
1885
+ var w = 595.28, h = 841.89, m = { t: 28.35, r: 28.35, b: 28.35, l: 28.35 }, land = false;
1886
+ sheet.page.forEach(function (decls) {
1887
+ decls.forEach(function (d) {
1888
+ if (d.p === 'size') {
1889
+ var tk = tokens(d.v.toLowerCase()), lens = [];
1890
+ tk.forEach(function (x) {
1891
+ if (PAGE_SIZES[x]) { w = PAGE_SIZES[x][0]; h = PAGE_SIZES[x][1]; }
1892
+ else if (x === 'landscape') land = true;
1893
+ else if (x === 'portrait') land = false;
1894
+ else { var L = parseLen(x, 12, 12); if (L && L.pt) lens.push(L.pt); }
1895
+ });
1896
+ if (lens.length) { w = lens[0]; h = lens[1] || lens[0]; }
1897
+ }
1898
+ var mm = /^margin-(top|right|bottom|left)$/.exec(d.p);
1899
+ if (mm) { var L2 = parseLen(d.v, 12, 12); if (L2 && L2.pt != null) m[mm[1].charAt(0)] = L2.pt; }
1900
+ });
1901
+ });
1902
+ if (opts.pageSize) {
1903
+ var ps = opts.pageSize;
1904
+ if (typeof ps === 'string' && PAGE_SIZES[ps.toLowerCase()]) { w = PAGE_SIZES[ps.toLowerCase()][0]; h = PAGE_SIZES[ps.toLowerCase()][1]; }
1905
+ else if (ps && ps.widthCm && ps.heightCm) { w = ps.widthCm * PT.cm; h = ps.heightCm * PT.cm; }
1906
+ }
1907
+ if (opts.orientation) land = String(opts.orientation).toLowerCase() === 'landscape';
1908
+ if (land && w < h) { var tmp = w; w = h; h = tmp; }
1909
+ if (!land && opts.orientation && w > h) { var tmp2 = w; w = h; h = tmp2; }
1910
+ return { w: w, h: h, m: m, landscape: w > h };
1911
+ }
1912
+
1913
+ function findBody(root) {
1914
+ var stack = [root];
1915
+ while (stack.length) {
1916
+ var n = stack.shift();
1917
+ if (n.tag === 'body') return n;
1918
+ if (n.els) for (var i = 0; i < n.els.length; i++) stack.push(n.els[i]);
1919
+ }
1920
+ return null;
1921
+ }
1922
+
1923
+ // fold body + single wrapper chain horizontal box into the page margins
1924
+ function foldChain(body, page, contentW) {
1925
+ var el = body, addL = 0, addR = 0, W = contentW;
1926
+ while (el) {
1927
+ var cs = el.cs, h = boxH(cs, W, false);
1928
+ if (cs.width && !cs.width.auto && el !== body) break;
1929
+ if (h.ml < 0 || h.mr < 0) break;
1930
+ el.folded = true;
1931
+ addL += h.ml + h.bl + h.pl; addR += h.mr + h.br + h.pr;
1932
+ W -= h.ml + h.bl + h.pl + h.mr + h.br + h.pr;
1933
+ var kids = el.els.filter(function (c) { return c.cs.display !== 'none'; });
1934
+ var textual = el.children.some(function (c) { return c.tag === '#text' && /\S/.test(c.text); });
1935
+ if (kids.length !== 1 || textual) break;
1936
+ var k = kids[0];
1937
+ if (k.cs.display !== 'block' || k.tag === 'p' || /^h[1-6]$/.test(k.tag) || k.tag === 'ul' || k.tag === 'ol' || k.tag === 'pre' || k.tag === 'blockquote') break;
1938
+ if (k.cs.bd.some(Boolean) || k.cs.background) break;
1939
+ el = k;
1940
+ }
1941
+ page.m.l += addL; page.m.r += addR;
1942
+ }
1943
+
1944
+ // ======================= 13. driver =======================
1945
+ function normalizeOpts(o) {
1946
+ if (typeof o === 'string') { try { o = JSON.parse(o); } catch (e) { o = {}; } }
1947
+ if (!o || typeof o !== 'object') o = {};
1948
+ if (o.v && typeof o.v === 'object' && !o.pageSize && !o.marginsCm) o = o.v;
1949
+ return o;
1950
+ }
1951
+
1952
+ function collectRemote(root, out) {
1953
+ (function walk(n) {
1954
+ if (n.tag === 'img' && /^https:\/\//i.test(String(n.attrs.src || '').trim())) out[String(n.attrs.src).trim()] = true;
1955
+ if (n.els) n.els.forEach(walk);
1956
+ })(root);
1957
+ return Object.keys(out);
1958
+ }
1959
+
1960
+ function fetchAll(urls, done) {
1961
+ var req = null;
1962
+ try { req = typeof require === 'function' ? require('https') : null; } catch (e) { req = null; }
1963
+ var result = Object.create(null);
1964
+ if (!req || !urls.length) { done(result); return; }
1965
+ var pending = urls.length, finished = false;
1966
+ var timer = setTimeout(function () { if (!finished) { finished = true; done(result); } }, 30000);
1967
+ function one(url, hops) {
1968
+ var fin = function (val) { result[url] = val; if (--pending === 0 && !finished) { finished = true; clearTimeout(timer); done(result); } };
1969
+ try {
1970
+ req.get(url, { timeout: 15000 }, function (res) {
1971
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location && hops < 3) {
1972
+ res.resume();
1973
+ var loc = res.headers.location;
1974
+ if (/^https:/i.test(loc)) { pending++; one(loc, hops + 1); result[url] = null; var redirected = loc; pending--; setTimeout(function () { result[url] = result[redirected]; }, 0); }
1975
+ else fin({ error: 'redirect to non-https ' + loc });
1976
+ return;
1977
+ }
1978
+ if (res.statusCode !== 200) { res.resume(); fin({ error: 'HTTP ' + res.statusCode + ' for ' + url }); return; }
1979
+ var chunks = [], total = 0;
1980
+ res.on('data', function (c) { chunks.push(c); total += c.length; });
1981
+ res.on('end', function () { var b = new Uint8Array(total), o = 0; chunks.forEach(function (c) { b.set(c, o); o += c.length; }); fin(b); });
1982
+ res.on('error', function (e) { fin({ error: String(e && e.message || e) }); });
1983
+ }).on('error', function (e) { fin({ error: String(e && e.message || e) }); });
1984
+ } catch (e) { fin({ error: String(e && e.message || e) }); }
1985
+ }
1986
+ urls.forEach(function (u) { one(u, 0); });
1987
+ }
1988
+
1989
+ function build(html, opts, remote) {
1990
+ var t0 = Date.now(), warnings = [];
1991
+ function warn(m) { if (warnings.length < 50 && warnings.indexOf(m) < 0) warnings.push(m); }
1992
+ var root = parseHTML(html);
1993
+ ensureBody(root);
1994
+ annotate(root);
1995
+ // style sources
1996
+ var styles = [];
1997
+ (function walk(n) { if (n.tag === 'style' && n.children[0]) styles.push(n.children[0].text); if (n.tag === 'svg') warn('inline <svg> is not rendered'); if (n.els) n.els.forEach(walk); })(root);
1998
+ var pageGuess = PAGE_SIZES.a4;
1999
+ var env = { type: opts.media === 'print' ? 'print' : 'screen', widthPx: pageGuess[0] / 0.75, heightPx: pageGuess[1] / 0.75 };
2000
+ var sheet = { ua: [], author: [], page: [], seq: 0 };
2001
+ parseCSS(UA_CSS + (opts.quirks === false ? '' : QUIRKS_CSS), sheet, env, 'ua', false);
2002
+ parseCSS(FROALA_CSS, sheet, env, 'author', false);
2003
+ styles.forEach(function (css) { parseCSS(css, sheet, env, 'author', false); });
2004
+ if (opts.css) parseCSS(String(opts.css), sheet, env, 'author', false);
2005
+ computeAll(root, sheet, opts);
2006
+ (function preflight(n) {
2007
+ var cs = n.cs;
2008
+ if (cs && cs.display !== 'none') {
2009
+ if (cs.display === 'flex' || cs.display === 'inline-flex') warn('CSS flex layout is not supported: flex items stack as blocks. Use a table for side-by-side layout.');
2010
+ else if (cs.display === 'grid' || cs.display === 'inline-grid') warn('CSS grid layout is not supported: grid items stack as blocks. Use a table for side-by-side layout.');
2011
+ if (cs.float === 'left' || cs.float === 'right') warn('CSS float is not supported: floated elements stay in normal flow.');
2012
+ }
2013
+ if (n.els) n.els.forEach(preflight);
2014
+ })(root);
2015
+ var page = pageSetup(sheet, opts);
2016
+ var body = findBody(root) || root;
2017
+ if (!body.cs) body.cs = root.cs;
2018
+ var contentW = page.w - page.m.l - page.m.r;
2019
+ var userMargins = opts.marginsCm != null;
2020
+ if (opts.foldWrapper !== false && !userMargins) foldChain(body, page, contentW);
2021
+ if (userMargins) {
2022
+ var mc = opts.marginsCm, all = typeof mc === 'number' ? mc : null;
2023
+ ['top', 'right', 'bottom', 'left'].forEach(function (s) {
2024
+ var v = all != null ? all : mc[s];
2025
+ if (typeof v === 'number' && v >= 0) page.m[s.charAt(0)] = v * PT.cm;
2026
+ });
2027
+ if (opts.foldWrapper !== false) foldChain(body, { m: { l: 0, r: 0 } }, contentW); // still neutralise the wrapper indents
2028
+ }
2029
+ contentW = Math.max(36, page.w - page.m.l - page.m.r);
2030
+ var L = new Layout(opts, page, warn);
2031
+ L.remote = remote;
2032
+ var flow = new Flow();
2033
+ var ctx = { W: contentW, indL: 0, indR: 0, block: { cs: body.cs, el: body, used: false }, bg: null, va: null, vaBase: 0, link: null, blockBg: null, li: null, list: null, listDepth: 0 };
2034
+ if (body === root) L.children(root, ctx, flow); else L.block(body, ctx, flow);
2035
+ L.flush(flow);
2036
+ var items = flow.items;
2037
+ if (!items.length) items.push({ kind: 'p', runs: [], cs: body.cs, before: 0, after: 0, ind: { l: 0, r: 0, first: 0, hang: 0 }, markRp: L.runProps(body.cs, {}) });
2038
+ if (items[items.length - 1].kind === 'tbl') items.push(L.tinyPara(ctx, false));
2039
+ collapse(items);
2040
+ // document defaults = dominant font
2041
+ var acc = {};
2042
+ countFonts(items, acc);
2043
+ var best = null, bn = -1;
2044
+ Object.keys(acc).forEach(function (k) { if (acc[k] > bn) { bn = acc[k]; best = k; } });
2045
+ var D = { f: best ? best.split('|')[0] : body.cs.fontFamily, sz2: best ? +best.split('|')[1] : Math.round(body.cs.fontSize * 2) };
2046
+ var lang = opts.lang || (function () {
2047
+ var h = root.els.filter(function (e) { return e.tag === 'html'; })[0], l = h && h.attrs.lang ? h.attrs.lang : 'ro';
2048
+ l = l.replace('_', '-');
2049
+ if (!/-/.test(l)) l = { ro: 'ro-RO', en: 'en-US', de: 'de-DE', fr: 'fr-FR', it: 'it-IT', es: 'es-ES', hu: 'hu-HU', ru: 'ru-RU' }[l.toLowerCase()] || l;
2050
+ return l;
2051
+ })();
2052
+ var Wr = new Writer(L, D), out = [];
2053
+ Wr.items(items, out);
2054
+ var mT = twip(page.m.t), mB = twip(page.m.b);
2055
+ var sect = '<w:sectPr><w:pgSz w:w="' + twip(page.w) + '" w:h="' + twip(page.h) + '"' + (page.landscape ? ' w:orient="landscape"' : '') + '/>' +
2056
+ '<w:pgMar w:top="' + mT + '" w:right="' + twip(page.m.r) + '" w:bottom="' + mB + '" w:left="' + twip(page.m.l) + '" w:header="' + Math.min(708, mT) + '" w:footer="' + Math.min(708, mB) + '" w:gutter="0"/>' +
2057
+ '<w:cols w:space="708"/></w:sectPr>';
2058
+ var NS = 'xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" ' +
2059
+ 'xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" ' +
2060
+ 'xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"';
2061
+ var docXml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:document ' + NS + '><w:body>' + out.join('') + sect + '</w:body></w:document>';
2062
+ // most common paragraph spacing for the Normal style
2063
+ var fam = xesc(D.f);
2064
+ var stylesXml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:styles xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">' +
2065
+ '<w:docDefaults><w:rPrDefault><w:rPr><w:rFonts w:ascii="' + fam + '" w:hAnsi="' + fam + '" w:eastAsia="' + fam + '" w:cs="' + fam + '"/>' +
2066
+ '<w:sz w:val="' + D.sz2 + '"/><w:szCs w:val="' + D.sz2 + '"/><w:lang w:val="' + xesc(lang) + '" w:eastAsia="en-US" w:bidi="ar-SA"/></w:rPr></w:rPrDefault>' +
2067
+ '<w:pPrDefault><w:pPr><w:widowControl/><w:spacing w:after="0" w:line="240" w:lineRule="auto"/></w:pPr></w:pPrDefault></w:docDefaults>' +
2068
+ '<w:style w:type="paragraph" w:default="1" w:styleId="Normal"><w:name w:val="Normal"/><w:qFormat/></w:style>' +
2069
+ '<w:style w:type="character" w:default="1" w:styleId="DefaultParagraphFont"><w:name w:val="Default Paragraph Font"/><w:uiPriority w:val="1"/><w:semiHidden/><w:unhideWhenUsed/></w:style>' +
2070
+ '<w:style w:type="table" w:default="1" w:styleId="TableNormal"><w:name w:val="Normal Table"/><w:uiPriority w:val="99"/><w:semiHidden/><w:unhideWhenUsed/>' +
2071
+ '<w:tblPr><w:tblInd w:w="0" w:type="dxa"/><w:tblCellMar><w:top w:w="0" w:type="dxa"/><w:left w:w="108" w:type="dxa"/><w:bottom w:w="0" w:type="dxa"/><w:right w:w="108" w:type="dxa"/></w:tblCellMar></w:tblPr></w:style>' +
2072
+ '<w:style w:type="numbering" w:default="1" w:styleId="NoList"><w:name w:val="No List"/><w:uiPriority w:val="99"/><w:semiHidden/><w:unhideWhenUsed/></w:style>' +
2073
+ '</w:styles>';
2074
+ var settingsXml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:settings xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">' +
2075
+ '<w:zoom w:percent="100"/><w:defaultTabStop w:val="720"/><w:characterSpacingControl w:val="doNotCompress"/>' +
2076
+ '<w:compat><w:compatSetting w:name="compatibilityMode" w:uri="http://schemas.microsoft.com/office/word" w:val="15"/>' +
2077
+ '<w:compatSetting w:name="overrideTableStyleFontSizeAndJustification" w:uri="http://schemas.microsoft.com/office/word" w:val="1"/>' +
2078
+ '<w:compatSetting w:name="enableOpenTypeFeatures" w:uri="http://schemas.microsoft.com/office/word" w:val="1"/>' +
2079
+ '<w:compatSetting w:name="doNotFlipMirrorIndents" w:uri="http://schemas.microsoft.com/office/word" w:val="1"/></w:compat></w:settings>';
2080
+ var hasNum = L.lists.length > 0;
2081
+ var rels = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">' +
2082
+ '<Relationship Id="rIdStyles" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>' +
2083
+ '<Relationship Id="rIdSettings" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings" Target="settings.xml"/>' +
2084
+ (hasNum ? '<Relationship Id="rIdNumbering" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering" Target="numbering.xml"/>' : '');
2085
+ L.media.forEach(function (m) { rels += '<Relationship Id="' + m.rid + '" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/' + m.name + '"/>'; });
2086
+ Wr.rels.forEach(function (l) { rels += '<Relationship Id="' + l.id + '" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" Target="' + xesc(l.url) + '" TargetMode="External"/>'; });
2087
+ rels += '</Relationships>';
2088
+ var title = opts.title;
2089
+ if (!title) { var te = null; (function f(n) { if (te) return; if (n.tag === 'title') te = n; else if (n.els) n.els.forEach(f); })(root); title = te && te.children[0] ? te.children[0].text.trim() : ''; }
2090
+ var now = new Date().toISOString().replace(/\.\d+Z$/, 'Z');
2091
+ var core = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" ' +
2092
+ 'xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' +
2093
+ (title ? '<dc:title>' + xesc(title) + '</dc:title>' : '') + '<dc:creator>' + xesc(opts.author || 'PROCESIO') + '</dc:creator>' +
2094
+ '<dcterms:created xsi:type="dcterms:W3CDTF">' + now + '</dcterms:created><dcterms:modified xsi:type="dcterms:W3CDTF">' + now + '</dcterms:modified></cp:coreProperties>';
2095
+ var app = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" ' +
2096
+ 'xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"><Application>PROCESIO HTML to DOCX</Application></Properties>';
2097
+ var exts = {};
2098
+ L.media.forEach(function (m) { exts[m.ext] = m.mime; });
2099
+ var ct = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">' +
2100
+ '<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/>';
2101
+ Object.keys(exts).forEach(function (e) { ct += '<Default Extension="' + e + '" ContentType="' + exts[e] + '"/>'; });
2102
+ ct += '<Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>' +
2103
+ '<Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/>' +
2104
+ '<Override PartName="/word/settings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"/>' +
2105
+ (hasNum ? '<Override PartName="/word/numbering.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml"/>' : '') +
2106
+ '<Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>' +
2107
+ '<Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/></Types>';
2108
+ var rootRels = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">' +
2109
+ '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>' +
2110
+ '<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>' +
2111
+ '<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/></Relationships>';
2112
+ var files = [
2113
+ { name: '[Content_Types].xml', data: utf8encode(ct) },
2114
+ { name: '_rels/.rels', data: utf8encode(rootRels) },
2115
+ { name: 'docProps/core.xml', data: utf8encode(core) },
2116
+ { name: 'docProps/app.xml', data: utf8encode(app) },
2117
+ { name: 'word/document.xml', data: utf8encode(docXml) },
2118
+ { name: 'word/styles.xml', data: utf8encode(stylesXml) },
2119
+ { name: 'word/settings.xml', data: utf8encode(settingsXml) },
2120
+ { name: 'word/_rels/document.xml.rels', data: utf8encode(rels) }
2121
+ ];
2122
+ if (hasNum) files.push({ name: 'word/numbering.xml', data: utf8encode(numberingXml(L)) });
2123
+ L.media.forEach(function (m) { files.push({ name: 'word/media/' + m.name, data: m.bytes }); });
2124
+ var zip = zipStore(files);
2125
+ var st = L.stats;
2126
+ return {
2127
+ base64: b64encode(zip),
2128
+ report: {
2129
+ ok: true, bytes: zip.length, ms: Date.now() - t0, paragraphs: st.paragraphs, tables: st.tables, images: st.images,
2130
+ links: st.links, lists: st.lists, page: { widthCm: +(page.w / PT.cm).toFixed(2), heightCm: +(page.h / PT.cm).toFixed(2),
2131
+ marginsCm: { top: +(page.m.t / PT.cm).toFixed(3), right: +(page.m.r / PT.cm).toFixed(3), bottom: +(page.m.b / PT.cm).toFixed(3), left: +(page.m.l / PT.cm).toFixed(3) } },
2132
+ defaultFont: D.f + ' ' + (D.sz2 / 2) + 'pt', warnings: warnings
2133
+ }
2134
+ };
2135
+ }
2136
+
2137
+ // html: the HTML text, or { base64: '...' } when it arrives base64-encoded
2138
+ function convert(htmlOrB64, opts, isB64) {
2139
+ opts = normalizeOpts(opts);
2140
+ var html = isB64 ? decodeText(b64decode(htmlOrB64)) : String(htmlOrB64 == null ? '' : htmlOrB64);
2141
+ if (!/\S/.test(html)) throw new Error('HTML input is empty');
2142
+ var remoteUrls = opts.fetchImages === true ? collectRemote(annotateQuick(html), {}) : [];
2143
+ if (!remoteUrls.length) return build(html, opts, null);
2144
+ return new Promise(function (resolve, reject) {
2145
+ fetchAll(remoteUrls, function (remote) { try { resolve(build(html, opts, remote)); } catch (e) { reject(e); } });
2146
+ });
2147
+ }
2148
+ function annotateQuick(html) {
2149
+ var r = parseHTML(html);
2150
+ annotate(r);
2151
+ return r;
2152
+ }
2153
+
2154
+ return { convert: convert, b64decode: b64decode, decodeText: decodeText, _parseHTML: parseHTML };
2155
+ })();