licos-dev-cli 0.2.21__tar.gz → 0.3.1__tar.gz

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.
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: licos-dev-cli
3
- Version: 0.2.21
3
+ Version: 0.3.1
4
4
  Summary: LICOS Dev CLI - generate files and call model capabilities
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: click>=8.1
7
- Requires-Dist: licos-dev-sdk>=0.2.22
7
+ Requires-Dist: licos-dev-sdk>=0.3.1
@@ -1,14 +1,14 @@
1
1
  [build-system]
2
- requires = ["hatchling"]
2
+ requires = ["hatchling>=1.27,<1.31"]
3
3
  build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "licos-dev-cli"
7
- version = "0.2.21"
7
+ version = "0.3.1"
8
8
  description = "LICOS Dev CLI - generate files and call model capabilities"
9
9
  requires-python = ">=3.10"
10
10
  dependencies = [
11
- "licos-dev-sdk>=0.2.22",
11
+ "licos-dev-sdk>=0.3.1",
12
12
  "click>=8.1",
13
13
  ]
14
14
 
@@ -123,14 +123,63 @@ def credit_check(estimated_points, resource_type, resource_code, request_id):
123
123
  @click.option("-o", "--output-dir", default=None, help="Output directory")
124
124
  @click.option("--format", "content_type", default="markdown", help="Content type: markdown|html")
125
125
  @click.option("--page-size", default="A4", help="Page size: A4|LETTER")
126
- def pdf(input_path, content, filename, output_dir, content_type, page_size):
126
+ @click.option("--theme", default="formal-blue", help="Theme: formal-blue|business|neutral")
127
+ @click.option("--title", default=None, help="Document title")
128
+ @click.option("--margin", default="20mm", help="Page margin CSS length, e.g. 20mm")
129
+ def pdf(input_path, content, filename, output_dir, content_type, page_size, theme, title, margin):
127
130
  """Generate PDF from Markdown or HTML."""
128
131
  from licos_dev_sdk import create_pdf
129
132
  text = _read_input(input_path, content)
130
- path = create_pdf(text, filename, content_type=content_type, output_dir=output_dir, page_size=page_size)
133
+ path = create_pdf(
134
+ text,
135
+ filename,
136
+ content_type=content_type,
137
+ output_dir=output_dir,
138
+ page_size=page_size,
139
+ theme=theme,
140
+ title=title,
141
+ margin=margin,
142
+ )
131
143
  _echo_path(path)
132
144
 
133
145
 
146
+ @cli.command("pdf-inspect")
147
+ @click.option("-f", "--file", "file_path", required=True, type=click.Path(exists=True, dir_okay=False))
148
+ @click.option("--min-pages", type=click.IntRange(min=1), default=None)
149
+ @click.option("--max-pages", type=click.IntRange(min=1), default=None)
150
+ @click.option(
151
+ "--sparse-text-threshold",
152
+ type=click.IntRange(min=0),
153
+ default=300,
154
+ show_default=True,
155
+ help="Flag non-cover pages with fewer extracted text characters; 0 disables the check.",
156
+ )
157
+ @click.option("--allow-sparse-cover/--check-sparse-cover", default=True, show_default=True)
158
+ @click.option("--check-orphan-headings/--allow-orphan-headings", default=True, show_default=True)
159
+ def pdf_inspect(
160
+ file_path,
161
+ min_pages,
162
+ max_pages,
163
+ sparse_text_threshold,
164
+ allow_sparse_cover,
165
+ check_orphan_headings,
166
+ ):
167
+ """Inspect PDF structure, page density, and requested page-count limits."""
168
+ from licos_dev_sdk import inspect_pdf
169
+
170
+ report = inspect_pdf(
171
+ file_path,
172
+ min_pages=min_pages,
173
+ max_pages=max_pages,
174
+ sparse_text_threshold=sparse_text_threshold,
175
+ allow_sparse_cover=allow_sparse_cover,
176
+ check_orphan_headings=check_orphan_headings,
177
+ )
178
+ click.echo(json.dumps(report, ensure_ascii=False, indent=2))
179
+ if not report["quality_passed"]:
180
+ raise click.exceptions.Exit(2)
181
+
182
+
134
183
  # ── DOCX ─────────────────────────────────────────────────────────────────────
135
184
 
136
185
  @cli.command()
@@ -139,13 +188,31 @@ def pdf(input_path, content, filename, output_dir, content_type, page_size):
139
188
  @click.option("-f", "--filename", required=True)
140
189
  @click.option("-o", "--output-dir", default=None)
141
190
  @click.option("--format", "content_type", default="markdown")
142
- @click.option("--font", default="Arial")
191
+ @click.option("--font", default="Microsoft YaHei")
143
192
  @click.option("--font-size", default=11, type=int)
144
- def docx(input_path, content, filename, output_dir, content_type, font, font_size):
193
+ @click.option("--theme", default="formal-blue", help="Theme: formal-blue|business|neutral")
194
+ @click.option("--title", default=None, help="Document title used when content has no H1")
195
+ @click.option("--header", default=None, help="Header text")
196
+ @click.option("--footer", default=None, help="Footer text placed before the page number")
197
+ @click.option("--toc/--no-toc", default=False, help="Insert an updatable Word table of contents")
198
+ def docx(input_path, content, filename, output_dir, content_type, font, font_size, theme, title, header, footer, toc):
145
199
  """Generate DOCX from Markdown or HTML."""
146
200
  from licos_dev_sdk import create_docx
147
201
  text = _read_input(input_path, content)
148
- path = create_docx(text, filename, content_type=content_type, output_dir=output_dir, font_name=font, font_size=font_size)
202
+ path = create_docx(
203
+ text,
204
+ filename,
205
+ content_type=content_type,
206
+ output_dir=output_dir,
207
+ font_name=font,
208
+ font_size=font_size,
209
+ theme=theme,
210
+ title=title,
211
+ header=header,
212
+ footer=footer,
213
+ include_toc=toc,
214
+ asset_base_path=str(Path(input_path).resolve().parent) if input_path else None,
215
+ )
149
216
  _echo_path(path)
150
217
 
151
218
 
@@ -174,11 +241,12 @@ def docx_template(template_path, input_path, data_content, filename, output_dir)
174
241
  @click.option("-o", "--output-dir", default=None)
175
242
  @click.option("--sheet-name", default="Sheet1")
176
243
  @click.option("--header-color", default="4472C4")
177
- def xlsx(input_path, content, filename, output_dir, sheet_name, header_color):
244
+ @click.option("--theme", default="professional-blue", help="Theme: professional-blue|business|neutral")
245
+ def xlsx(input_path, content, filename, output_dir, sheet_name, header_color, theme):
178
246
  """Generate XLSX from JSON data."""
179
247
  from licos_dev_sdk import create_xlsx
180
248
  data = _read_json(input_path, content)
181
- path = create_xlsx(data, filename, output_dir=output_dir, sheet_name=sheet_name, header_color=header_color)
249
+ path = create_xlsx(data, filename, output_dir=output_dir, sheet_name=sheet_name, header_color=header_color, theme=theme)
182
250
  _echo_path(path)
183
251
 
184
252
 
@@ -190,7 +258,8 @@ def xlsx(input_path, content, filename, output_dir, sheet_name, header_color):
190
258
  @click.option("--header-color", default="4472C4")
191
259
  @click.option("--freeze-header/--no-freeze-header", default=True)
192
260
  @click.option("--autofilter/--no-autofilter", default=True)
193
- def xlsx_workbook(input_path, content, filename, output_dir, header_color, freeze_header, autofilter):
261
+ @click.option("--theme", default="professional-blue", help="Theme: professional-blue|business|neutral")
262
+ def xlsx_workbook(input_path, content, filename, output_dir, header_color, freeze_header, autofilter, theme):
194
263
  """Generate multi-sheet XLSX from JSON workbook data."""
195
264
  from licos_dev_sdk import create_xlsx_workbook
196
265
  data = _read_json(input_path, content)
@@ -201,10 +270,20 @@ def xlsx_workbook(input_path, content, filename, output_dir, header_color, freez
201
270
  header_color=header_color,
202
271
  freeze_header=freeze_header,
203
272
  autofilter=autofilter,
273
+ theme=theme,
204
274
  )
205
275
  _echo_path(path)
206
276
 
207
277
 
278
+ @cli.command("xlsx-inspect")
279
+ @click.option("-f", "--file", "file_path", required=True, type=click.Path(exists=True, dir_okay=False))
280
+ def xlsx_inspect(file_path):
281
+ """Inspect generated XLSX formulas, charts, formatting, and validation features."""
282
+ from licos_dev_sdk import inspect_xlsx
283
+
284
+ click.echo(json.dumps(inspect_xlsx(file_path), ensure_ascii=False, indent=2))
285
+
286
+
208
287
  # ── CSV ──────────────────────────────────────────────────────────────────────
209
288
 
210
289
  @cli.command()
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import json
4
+ from pathlib import Path
4
5
  from unittest import mock
5
6
 
6
7
  from click.testing import CliRunner
@@ -37,3 +38,28 @@ def test_credit_check_forwards_structured_options() -> None:
37
38
  resource_code="IMAGE_GENERATE",
38
39
  request_id="request-1",
39
40
  )
41
+
42
+
43
+ def test_docx_uses_input_directory_as_asset_base_path(tmp_path: Path) -> None:
44
+ source_dir = tmp_path / "source"
45
+ source_dir.mkdir()
46
+ input_path = source_dir / "report.html"
47
+ input_path.write_text('<img src="chart.png">', encoding="utf-8")
48
+
49
+ with mock.patch(
50
+ "licos_dev_sdk.create_docx",
51
+ return_value=str(tmp_path / "report.docx"),
52
+ ) as create:
53
+ result = CliRunner().invoke(
54
+ cli,
55
+ [
56
+ "docx",
57
+ "--input",
58
+ str(input_path),
59
+ "--filename",
60
+ "report.docx",
61
+ ],
62
+ )
63
+
64
+ assert result.exit_code == 0
65
+ assert create.call_args.kwargs["asset_base_path"] == str(source_dir.resolve())
File without changes