mirror of
https://github.com/storytold/wordcraft.git
synced 2026-11-08 11:19:54 -06:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49b3adb858 | ||
|
|
6ba25ee491 |
@@ -224,6 +224,7 @@ Ranked, to beta (detail and remaining milestones in [docs/roadmap.md](docs/roadm
|
||||
- 2026-11-03: A long comment no longer grows its card or balloon without limit (#3382). Its field in the Comments pane and in a selected balloon stops at ten lines and scrolls, keeping the caret in view; a balloon that isn't selected shows the first ten lines of the comment and of each reply, and clicking it opens the scrolling field. The buttons and the next comment stay in view.
|
||||
- 2026-11-03: Arabic dialogs: the dialogs of the mirrored interface now read right to left. Rows of a label and its field, lists of columns (Compare, AutoCorrect, Special Characters, Track Changes Options, the Columns widths), the tile galleries (chart types, SmartArt layouts) and the ribbon Paragraph group start at the right edge, through an `rtl::Table` helper that is an `egui::Grid` in English; the Add >> and << Remove arrows swap, the Columns preset captions and the Macros buttons no longer overlap, and the Recipient List grid and About › Models scroll instead of running past the left edge. Readiness unchanged.
|
||||
- 2026-11-03: Shape Format › Size: the width and height fields show the interface unit (centimetres, inches…) instead of always points, and take a size typed in any unit, such as `3 cm` or `300 px`, applied once typed (Esc cancels), each side on its own, as Picture Format › Size does (#4196). In both, a field clicked and left with Enter or Tab without typing no longer resizes the object by the rounding of the size it shows (a 100 pt shape became 100.08 pt in inches).
|
||||
- 2026-11-03: Security: Paste Special with picture files on the clipboard refuses anything that isn't a regular file (a pipe or device reports no length and can produce endless data), and `cargo xtask stats` no longer follows directory symlinks. Readiness unchanged.
|
||||
- 2026-11-03: Security: pasting text boxes charges each copied story for its formatting too (run, mark, paragraph and section properties), not only its text and objects, so a story with huge style or font names can't copy past the paste's 32 MiB text box budget. Readiness unchanged.
|
||||
- 2026-11-03: Security: `.doc` import keeps one width, shading, alignment and merge override per table cell, the last one winning as before, instead of a copy every time a paragraph's properties repeat the sprm, so a shared PAPX can't pile up copies on every paragraph mark. Readiness unchanged.
|
||||
- 2026-11-03: Security: `.doc` import attaches each section to the paragraph that ends it through an index of paragraph ends, instead of scanning every paragraph for every section, so a file with a thousand sections that end nowhere can't multiply the work over its paragraphs. Readiness unchanged.
|
||||
|
||||
@@ -147,8 +147,14 @@ pub(crate) fn paste(app: &mut WordApp) -> Option<Result<Value, String>> {
|
||||
}
|
||||
let mut r = Err(String::new());
|
||||
for path in files {
|
||||
let size = std::fs::metadata(&path).map(|m| m.len()).unwrap_or(0);
|
||||
r = if size > MAX_FILE_BYTES {
|
||||
// A clipboard path can name a pipe or device that reports no length and never ends.
|
||||
let md = std::fs::metadata(&path).ok();
|
||||
let size = md.as_ref().map_or(0, |m| m.len());
|
||||
r = if md.as_ref().is_some_and(|m| !m.is_file()) {
|
||||
let e = format!("{} is not a regular file", path.display());
|
||||
app.status(e.clone());
|
||||
Err(e)
|
||||
} else if size > MAX_FILE_BYTES {
|
||||
let e = format!("{} is larger than 200 MB", path.display());
|
||||
app.status(e.clone());
|
||||
Err(e)
|
||||
|
||||
+4
-2
@@ -73,8 +73,10 @@ mod tests {
|
||||
fn a_failed_file_listing_fails_the_check() {
|
||||
// #1364: outside a git checkout `git ls-files` fails, and its empty output read as "no
|
||||
// files" passed the check.
|
||||
let dir = std::env::temp_dir().join(format!("wordcraft-xtask-assets-{}", std::process::id()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
// Created exclusively under a name no one can predict: an existing folder or link there would be someone else's.
|
||||
let nanos = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).map_or(0, |d| d.subsec_nanos());
|
||||
let dir = std::env::temp_dir().join(format!("wordcraft-xtask-assets-{}-{nanos}", std::process::id()));
|
||||
std::fs::create_dir(&dir).unwrap();
|
||||
std::fs::write(dir.join("ATTRIBUTION.md"), "").unwrap();
|
||||
let inside_git = Command::new("git").current_dir(&dir).args(["rev-parse", "--git-dir"]).output().is_ok_and(|o| o.status.success());
|
||||
let result = run(&dir);
|
||||
|
||||
+18
-2
@@ -18,12 +18,14 @@ fn walk(dir: &Path, c: &mut Counts) {
|
||||
let p = e.path();
|
||||
let name = e.file_name();
|
||||
let name = name.to_string_lossy();
|
||||
if p.is_dir() {
|
||||
// A symlink is never followed: several links to an ancestor would multiply the walk.
|
||||
if e.file_type().is_ok_and(|t| t.is_dir()) {
|
||||
// Nested fuzz workspaces and build output are not part of the crate.
|
||||
if name != "target" && name != "fuzz" && !name.starts_with('.') {
|
||||
walk(&p, c);
|
||||
}
|
||||
} else if name.ends_with(".rs")
|
||||
&& e.file_type().is_ok_and(|t| t.is_file())
|
||||
&& let Ok(s) = std::fs::read_to_string(&p)
|
||||
{
|
||||
c.files += 1;
|
||||
@@ -108,11 +110,25 @@ pub fn run(_root: &Path, exact: bool) -> Result<(), String> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::count_tests;
|
||||
use super::{Counts, count_tests, walk};
|
||||
|
||||
#[test]
|
||||
fn counts_attributes_and_proptest_blocks() {
|
||||
let src = "#[test]\nfn a() {}\n// #[test] commented\n #[test]\nfn b() {}\nproptest! {\n}\n";
|
||||
assert_eq!(count_tests(src), (2, 1));
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn a_walk_does_not_follow_directory_links() {
|
||||
let nanos = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).map_or(0, |d| d.subsec_nanos());
|
||||
let dir = std::env::temp_dir().join(format!("wordcraft-xtask-stats-{}-{nanos}", std::process::id()));
|
||||
std::fs::create_dir(&dir).unwrap();
|
||||
std::fs::write(dir.join("a.rs"), "#[test]\n").unwrap();
|
||||
std::os::unix::fs::symlink(&dir, dir.join("loop")).unwrap();
|
||||
let mut c = Counts::default();
|
||||
walk(&dir, &mut c);
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
assert_eq!((c.files, c.tests), (1, 1));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user