Copilot commented on code in PR #979: URL: https://github.com/apache/fesod/pull/979#discussion_r3705516428
########## website/src/css/xl-sheet.css: ########## @@ -0,0 +1,412 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* + * Excel-like grids used in the write/fill docs in place of screenshots. + * + * Geometry is expressed in Excel's own units and scaled by --xl-scale. Each + * spreadsheet value gets its own class, named after that value: + * + * <td class="xl-cw-25"> @ColumnWidth(25) + * <td class="xl-rh-30"> @ContentRowHeight(30) + * <td class="xl-fs-20"> setFontHeightInPoints(20) + * <td class="xl-fill-red"> + * <td class="xl-fc-red"> + * + * The values have to be enumerated here rather than passed inline, because an + * MDX `style` attribute is parsed by hast-util-to-estree via style-to-js, and + * the version this site resolves throws on any `style` attribute at all. + */ + +.xl-sheet-container, +.xl-sheet, +.xl-sheet-tabs { + --xl-scale: 1; + --xl-col-unit: calc(7.2px * var(--xl-scale)); /* one Excel column-width unit */ + --xl-row-unit: calc(1.8px * var(--xl-scale)); /* one point of Excel row height */ + --xl-pt: calc(0.8pt * var(--xl-scale)); + + --xl-paper: #f5f5f5; + --xl-ink: #000; + --xl-grid: #e0e0e0; + --xl-head-bg: #bfbfbf; + --xl-chrome-bg: #f5f5f5; + --xl-chrome-grid: #e0e0e0; + --xl-tab-bg: #f5f5f5; + --xl-tab-fg: #555; + + --xl-white: #ffffff; + --xl-red: #ff0000; + --xl-magenta: #ff00ff; + --xl-green: #14824b; + --xl-sky: #1890ff; + --xl-bright-green: #168f52; + + font-family: system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", Helvetica, sans-serif, Arial; + line-height: 1.2; +} + +/* dark theme */ + +[data-theme='dark'] { + .xl-sheet-container { + border: none; + background: rgba(255, 255, 255, 0.05); + } + + .xl-sheet .xl-chrome { + background: rgba(255, 255, 255, 0.05); + color: var(--xl-white); + border-color: rgba(255, 255, 255, 0.05); + } Review Comment: This uses CSS nesting syntax (`[data-theme='dark'] { .xl-sheet-container { ... } }`). Unless the site’s CSS pipeline explicitly enables CSS Nesting (or a preprocessor), these rules won’t parse and dark theme styling will not apply. Use fully-qualified selectors instead (e.g., `[data-theme='dark'] .xl-sheet-container { ... }`, `[data-theme='dark'] .xl-sheet .xl-chrome { ... }`). ########## website/i18n/zh-cn/docusaurus-plugin-content-docs/current/sheet/write/image.md: ########## @@ -22,36 +39,164 @@ title: '图片' @ContentRowHeight(100) @ColumnWidth(25) public class ImageDemoData { - private File file; - private InputStream inputStream; - @ExcelProperty(converter = StringImageConverter.class) - private String string; - private byte[] byteArray; - private URL url; + private File image; } ``` -#### 代码示例 +### 代码示例 ```java @Test -public void imageWrite() throws Exception { +public void imageWrite() { String fileName = "imageWrite" + System.currentTimeMillis() + ".xlsx"; String imagePath = "path/to/image.jpg"; - List<ImageDemoData> list = new ArrayList<>(); ImageDemoData data = new ImageDemoData(); - data.setFile(new File(imagePath)); - data.setByteArray(Files.readAllBytes(Paths.get(imagePath))); - data.setUrl(new URL("https://example.com/image.jpg")); - list.add(data); + data.setImage(new File(imagePath)); FesodSheet.write(fileName, ImageDemoData.class) .sheet() - .doWrite(list); + .doWrite(Collections.singletonList(data)); +} +``` + +### 结果 + +没有用 `@ExcelProperty` 指定标题时,列名就是字段名。 + +<table class="xl-sheet"> +<tbody> +<tr><td class="xl-chrome"></td><td class="xl-chrome xl-cw-25">A</td></tr> +<tr><td class="xl-chrome">1</td><td class="xl-head">image</td></tr> +<tr class="xl-rh-100"><td class="xl-chrome">2</td><td class="xl-pic xl-rh-100"><img src="/img/docs/write/sample-image.svg" alt="图片"/></td></tr> +</tbody> +</table> Review Comment: This grid table isn’t wrapped in the `.xl-sheet-container` used elsewhere. Without the container, you lose the intended border/paper background and horizontal scrolling behavior defined in `xl-sheet.css`. Wrap these tables in `<div class=\"xl-sheet-container\">...</div>` for consistent rendering. ########## website/docs/sheet/write/image.md: ########## @@ -24,52 +24,205 @@ title: 'Image' This chapter introduces how to export files containing images. -## Image Export +## How Images Are Written -### Overview +An image is written as a floating picture anchored to its cell - the cell value itself stays empty. +The picture is stretched to the cell box, so its aspect ratio is not preserved: size the row and the +column to match with `@ContentRowHeight` and `@ColumnWidth`. -Supports exporting images through various methods including files, streams, byte arrays, URLs, etc. +## Image Sources -#### POJO Class +The declared field type selects the converter, so most sources need no configuration: -```java +| Field type | Converter | Notes | +| --- | --- | --- | +| `File` | `FileImageConverter` | A file on disk. | +| `InputStream` | `InputStreamImageConverter` | Read to the end; closing the stream stays your responsibility. | +| `byte[]`, `Byte[]` | `ByteArrayImageConverter`, `BoxingByteArrayImageConverter` | Raw image bytes. | +| `URL` | `UrlImageConverter` | Downloaded while the file is written, see [URL Sources](#url-sources). | +| `String` | none by default | Must be declared explicitly, see below. | + +`String` is the only source you have to declare, because an undeclared `String` field is written as +text. Choose the converter that matches the value: + +- `StringImageConverter` or `StringPathnameImageConverter` - a path to a file (the two behave identically). +- `StringBase64ImageConverter` - base64 data, with or without a `data:image/png;base64,` prefix. +## Image Export + +### POJO Class + +```java @Getter @Setter @EqualsAndHashCode @ContentRowHeight(100) @ColumnWidth(25) public class ImageDemoData { - private File file; - private InputStream inputStream; - @ExcelProperty(converter = StringImageConverter.class) - private String string; - private byte[] byteArray; - private URL url; + private File image; } ``` -#### Code Example +### Code Example ```java @Test -public void imageWrite() throws Exception { +public void imageWrite() { String fileName = "imageWrite" + System.currentTimeMillis() + ".xlsx"; String imagePath = "path/to/image.jpg"; - List<ImageDemoData> list = new ArrayList<>(); ImageDemoData data = new ImageDemoData(); - data.setFile(new File(imagePath)); - data.setByteArray(Files.readAllBytes(Paths.get(imagePath))); - data.setUrl(new URL("https://example.com/image.jpg")); - list.add(data); + data.setImage(new File(imagePath)); FesodSheet.write(fileName, ImageDemoData.class) .sheet() - .doWrite(list); + .doWrite(Collections.singletonList(data)); } ``` ### Result - +The column is named after the field, unless `@ExcelProperty` gives it a title. + +<div class="xl-sheet-container"> +<table class="xl-sheet"> +<tbody> +<tr><td class="xl-chrome"></td><td class="xl-chrome xl-cw-25">A</td></tr> +<tr><td class="xl-chrome">1</td><td class="xl-head">image</td></tr> +<tr class="xl-rh-100"><td class="xl-chrome">2</td><td class="xl-pic xl-rh-100"><img src="/img/docs/write/sample-image.svg" alt="image"/></td></tr> +</tbody> +</table> +</div> + +Switching to another source is only a change of field type - the written picture is the same: + +```java +private InputStream image; // or byte[], Byte[], URL + +@ExcelProperty(converter = StringImageConverter.class) +private String image; // String needs the converter declared +``` + +## Multiple Images and Text in One Cell + +A `WriteCellData<Void>` field carries a list of `ImageData`, which lets one cell hold several images +alongside its text. Each image is placed with `top`/`right`/`bottom`/`left` margins in points, and +`relativeLastColumnIndex` lets an image extend into the columns to its right. + +### POJO Class + +```java +@Getter +@Setter +@EqualsAndHashCode +@ContentRowHeight(100) +@ColumnWidth(25) +public class ImageCellDemoData { + private WriteCellData<Void> image; +} +``` + +### Code Example + +```java +@Test +public void imageCellWrite() throws Exception { + String fileName = "imageCellWrite" + System.currentTimeMillis() + ".xlsx"; + byte[] imageBytes = Files.readAllBytes(Paths.get("path/to/image.jpg")); + + WriteCellData<Void> writeCellData = new WriteCellData<>(); + // Use CellDataTypeEnum.EMPTY if the cell needs no text of its own + writeCellData.setType(CellDataTypeEnum.STRING); + writeCellData.setStringValue("Additional text content"); + + List<ImageData> imageDataList = new ArrayList<>(); + writeCellData.setImageDataList(imageDataList); + + // First image: inset within the cell, kept clear of the right edge + ImageData imageData = new ImageData(); + imageDataList.add(imageData); + imageData.setImage(imageBytes); + imageData.setTop(5); + imageData.setRight(95); + imageData.setBottom(5); + imageData.setLeft(5); + + // Second image: starts further right and extends into the next column + imageData = new ImageData(); + imageDataList.add(imageData); + imageData.setImage(imageBytes); + imageData.setTop(5); + imageData.setRight(5); + imageData.setBottom(5); + imageData.setLeft(50); + // End one column to the right of this cell, so the image covers both + imageData.setRelativeLastColumnIndex(1); + + ImageCellDemoData data = new ImageCellDemoData(); + data.setImage(writeCellData); + + FesodSheet.write(fileName, ImageCellDemoData.class) + .sheet() + .doWrite(Collections.singletonList(data)); +} +``` + +The image format is detected from the data itself, so `ImageData.imageType` does not have to be set. +Margins larger than the cell can make Excel prompt to repair the file when it is opened. + +### Result + +Column `A` holds the text and both images; the second image overlaps column `B`. + +<div class="xl-sheet-container"> +<table class="xl-sheet"> +<tbody> +<tr><td class="xl-chrome"></td><td class="xl-chrome xl-cw-25">A</td><td class="xl-chrome">B</td></tr> +<tr><td class="xl-chrome">1</td><td class="xl-head">image</td><td></td></tr> +<tr class="xl-rh-100"><td class="xl-chrome">2</td><td class="xl-pic-multi xl-rh-100"><img class="xl-pic-abs xl-pic-abs-left" src="/img/docs/write/sample-image.svg" alt="image"/><img class="xl-pic-abs xl-pic-abs-right" src="/img/docs/write/sample-image.svg" alt="image"/><b>Additional text content</b></td><td></td></tr> +</tbody> +</table> +</div> + +## URL Sources + +A `URL` field is fetched over the network while the file is written, under a fetch polices: Review Comment: Fix typo/grammar: `polices` should be `policy` (or `policies`). ########## website/docs/sheet/fill/fill.md: ########## @@ -74,11 +115,27 @@ public void simpleFill() { ### Template - +<div class="xl-sheet-container"> +<table class="xl-sheet"> +<tbody> +<tr><td class="xl-chrome"></td><td class="xl-chrome">A</td><td class="xl-chrome">B</td><td class="xl-chrome">C</td><td class="xl-chrome">D</td><td class="xl-chrome">E</td></tr> +<tr><td class="xl-chrome">1</td><td>Name</td><td>Number</td><td>Complex</td><td>Ignored</td><td>Empty</td></tr> +<tr><td class="xl-chrome">2</td><td>{name}</td><td>{number}</td><td>{name} is {number} years old</td><td>\{name\} ignored,{name}</td><td>Empty{.empty}</td></tr> Review Comment: The English doc uses a Chinese comma `,` in `ignored,...`. Replace with a standard comma `,` for consistency and readability. ########## website/.markdownlint-cli2.jsonc: ########## @@ -1,23 +1,40 @@ { - "globs": ["website/**/*.md"], + "globs": [ + "website/**/*.md" + ], "config": { "default": true, "MD001": true, "MD003": true, "MD022": false, "MD041": false, "MD013": { - "line_length": 600, - "code_blocks": false, - "tables": false + "line_length": 600, + "code_blocks": false, + "tables": false }, "MD024": { - "siblings_only": true + "siblings_only": true }, "MD025": false, "MD029": true, "MD033": { - "allowed_elements": ["table", "tr", "td", "a", "img", "sub", "b", "br", "img", "tbody", "mark", "font"] + "allowed_elements": [ + "div", + "table", + "tr", + "td", + "a", + "img", + "sub", + "b", + "br", + "img", + "tbody", + "mark", + "font", + "p" + ] Review Comment: `img` is listed twice in the `allowed_elements` array. Removing the duplicate reduces confusion and makes future edits less error-prone. ########## website/docs/sheet/fill/fill.md: ########## @@ -74,11 +115,27 @@ public void simpleFill() { ### Template - +<div class="xl-sheet-container"> +<table class="xl-sheet"> +<tbody> +<tr><td class="xl-chrome"></td><td class="xl-chrome">A</td><td class="xl-chrome">B</td><td class="xl-chrome">C</td><td class="xl-chrome">D</td><td class="xl-chrome">E</td></tr> +<tr><td class="xl-chrome">1</td><td>Name</td><td>Number</td><td>Complex</td><td>Ignored</td><td>Empty</td></tr> +<tr><td class="xl-chrome">2</td><td>{name}</td><td>{number}</td><td>{name} is {number} years old</td><td>\{name\} ignored,{name}</td><td>Empty{.empty}</td></tr> +</tbody> +</table> +</div> ### Result - +<div class="xl-sheet-container"> +<table class="xl-sheet"> +<tbody> +<tr><td class="xl-chrome"></td><td class="xl-chrome">A</td><td class="xl-chrome">B</td><td class="xl-chrome">C</td><td class="xl-chrome">D</td><td class="xl-chrome">E</td></tr> +<tr><td class="xl-chrome">1</td><td>Name</td><td>Number</td><td>Complex</td><td>Ignored</td><td>Empty</td></tr> +<tr><td class="xl-chrome">2</td><td>John Doe</td><td class="xl-num">5.2</td><td>John Doe is 5.2 years old</td><td>{name} ignored,John Doe</td><td>Empty</td></tr> Review Comment: The English doc uses a Chinese comma `,` in `ignored,...`. Replace with a standard comma `,` for consistency and readability. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
