# Changes since [4.0.0](./4.0.0.md) #

There are a lot of changes since last release, but here is what I could gather and organize!
Please see the commit list for more!

- Improvements in ui_gtk
- Improvements in ui_tk
- Improvements in ui_cmd_interactive
- Refactoring and improvements in ui-related codebase

- Fix not loading config with `--ui=none`
- Code style fixes and cleanup

- Documentation
	+ Update most documentations.
	+ Add comments for read/write options.
	+ Generate documentation for all formats
		- Placed in [doc/p](../p), linked to in `README.md`
		- Generating with `scripts/plugin-doc-gen.py` script
		- Read list of dictionary tools/applicatios from TOML files in [plugins-meta/tools](../../plugins-meta/tools)

- Add `Dockerfile` and `run-with-docker.sh` script

- New command-line flags:
	- `--json-read-options` and `--json-write-options`
		- To allow using `;` in option values
		- Example: `'--json-write-options={"delimiter": ";"}'`
	- `--gtk`, `--tk` and `--cmd` as shortcut for `--ui=gtk` etc
	- `--rtl` to change direction of definitions, [#268](https://github.com/ilius/pyglossary/issues/268), also added to `config.json`

- Fix non-working `--remove-html` flag

- Changes in `Glossary` class
	- Rename `glos.getPref` to `glos.getConfig`
	- Change `formatsReadOptions` and `formatsWriteOptions` to `Dict[str, OrderedDict[str, Any]]`
		+ to include default values
	- remove `glos.writeTabfile`, replace with a func in `pyglossary/text_writer.py`
	- `Glossary.init`: avoid showing error if user plugin directory does not exist


- Fixes and improvements code base
	- Prevent `dataEntry.save()` from raising exception because of invalid filename or permission
	- Avoid exception if removing temp file/folder failed
	- Avoid `mktemp` and more improvements
		+ use `~/.cache/pyglossary/` directory instead of `/tmp/`
	- Fixes and improvements in `runDictzip`
	- Raise `RuntimeError` instead of `StopIteration` when iterating over a non-open reader
	- Avoid exception if no zip command was found, fix [#294](https://github.com/ilius/pyglossary/issues/294)
	- Remove directory after creating .zip, and some refactoring, [#294](https://github.com/ilius/pyglossary/issues/294)
	- `DataEntry`: replace `inTmp` argument with `tmpPath` argument
	- `Entry`: fix html pattern for hyperlinks, [#330](https://github.com/ilius/pyglossary/issues/330)
	- Fix incorrect virutal env directory detection
	- Refactor `dataDir` detection, [#307](https://github.com/ilius/pyglossary/issues/307) [#316](https://github.com/ilius/pyglossary/issues/316)
	- Show warning if failed to create user plugins directory
	- fix possible exception in `log.emit`
	- Add support for Conda in `dataDir` detection, [#321](https://github.com/ilius/pyglossary/issues/321)
	- Fix f-string in `StdLogHandler.emit`



- Fixes and improvements in Windows
	+ Fix bad `dataDir` on Windows, [#307](https://github.com/ilius/pyglossary/issues/307)
	+ Fix `shutil.rmtree` exception on Windows
	+ Support creating .zip on Windows 10, [#294](https://github.com/ilius/pyglossary/issues/294)
	+ Check zip command before tar on Windows, [#294](https://github.com/ilius/pyglossary/issues/294)
	+ Show graphical error on exceptions on Windows
	+ Fix dataDir detection on Windows, [#323](https://github.com/ilius/pyglossary/issues/323) $324


- Changes in Config:
	- Rename config key `skipResources` to `skip_resources`
		+ Add it to config.json and configDefDict
	- Rename config key `utf8Check` to `utf8_check`
		+ User should edit ~/.pyglossary/config.json manually


- Implement direct compression and uncompression, and some refactoring
	+ change glos.detectInputFormat to return (filename, format, compression) or None
	+ remove Glossary.formatsReadFileObj and Glossary.formatsWriteFileObj
	+ remove `fileObj=` argument from `glos.writeTxt`
	+ use optional 'compressions' list/tuple from Writer or Reader classes for direct compression/uncompression
	+ refactoring in glossary_utils.py

- Update `setup.py`

- Show version from 'git describe --always' on `--version`

- `FileSize` option (used in many formats):
	+ Switch to metric (powers of 1000) for `K`, `M`, `G` units
	+ Add `KiB`, `MiB`, `GiB` for powers of 1024


- Add `extensionCreate` variable (str) to plugins and plugin API
	+ Use it to improve ui_tk



- Text-based glossary code-base (effecting Tabfile, Kobo Dictfile, LDF)
	- Optimize TextGlossaryReader 
	- Change multi-file text glossary file names from `.N.txt` to `.txt.N` (where `N>=1`)
	- Enable reading pyglossary-writen multi-file text glossary by adding `file_count=-1` to metadata
		+ because the number of files is not known when creating the first txt file


- Tabfile
	- Rename option `writeInfo` to `enable_info`
	- Reader: read resource files from `*.txt_res` directory if exists
	- Add `*.txt_res` directory to *.zip file

- Zim Reader:
	- Migrate to libzim 1.0
	- Add mimetype `image/webp`, fix [#329](https://github.com/ilius/pyglossary/issues/329)


- Slob and Tabfile Writer: add `file_size_approx` option to allow writing multi-part output
	+ support values like: `5500k`, `100m`, `1.2g`


- Add `word_title=False` option to some writers
	+ Slob Writer: add `word_title=False` option
	+ Tabfile Writer: add `word_title=False` option
	+ CSV Writer: add `word_title=False` option
	+ JSON Writer: add `word_title=False` option
	+ Dict.cc Reader: do not add word title
	+ FreeDict Reader: rename `keywords_header` option to `word_title`
	+ Add `glos.wordTitleStr`, used in plugins with `word_title` option
	+ Add `definition_has_headwords=True` info key to avoid adding the title next time we read the glossary

- Aard2 (slob)
	- Writer: add option `separate_alternates=False`, [#270](https://github.com/ilius/pyglossary/issues/270)
	- Writer: fix handling `content_type` option
	- Writer: use `~/.cache/pyglossary/` instead of `/tmp`
	- Writer: add mp3 to mime types, [#289](https://github.com/ilius/pyglossary/issues/289)
	- Writer: add support for .ini data file, [#289](https://github.com/ilius/pyglossary/issues/289)
	- Writer: support .webp files, [#329](https://github.com/ilius/pyglossary/issues/329)
	- Writer: supoort .tiff and .tif files
	- Reader: read glossary name/title and creation time from tags
	- Reader: extract all metedata / tags
	- `slob.py` library: Refactoring and cleanup


- StarDict:
	- Reader: add option unicode_errors for invalid UTF-8 data, [#309](https://github.com/ilius/pyglossary/issues/309)
	- Writer: add bool write-option `audio_goldendict`, [#327](https://github.com/ilius/pyglossary/issues/327)
	- Writer: add option `audio_icon=True`, and add option comment, [#327](https://github.com/ilius/pyglossary/issues/327)


- FreeDict Reader
	- Fix two slashes before and after `pron`
	- Avoid running `unescape_unicode` by `encoding="utf-8"` arg to `ET.htmlfile`
	- Fix exception if `edition` is missing in header, and few other fixes
	- Support `<cit type="example">` with `<cit type="trans">` inside it
	- Support `<cit type="trans">` inside nested second-level(nested) `<sense>`
	- Add `"lang"` attribute to html elements
	- Add option "example_padding"
	- Fix rendering `<def>`, refactoring and improvement
	- Handle `<note>` inside `<sense>`
	- Support `<note>` in `<gramGrp>`
	- Mark external refs with `<a ... class="external">`
	- Support comment in `<cit>`
	- Support `<xr>` inside `<sense>`
	- Implement many tags under `<sense>`
	- Improvements and refactoring

- XDXF
	+ Fix not finding `xdxf.xsl` in installed mode
		- Effecting XDXF and StarDict formats

	+ `xdxf.xsl`: generate `<font color=...>` instead of `<span style=...>`

	+ StarDict Reader: Add `xdxf_to_html=True` option, [#258](https://github.com/ilius/pyglossary/issues/258)
	+ StarDict Reader: Import `xdxf_transform` lazily
		- Remove forced dependency to `lxml`, [#261](https://github.com/ilius/pyglossary/issues/261)

	+ XDXF plugin: fix glos.setDefaultDefiFormat call

	- `xdxf_transform.py`: remove warnings for <opt>, [#322](https://github.com/ilius/pyglossary/issues/322)

	+ Merge PR [#317](https://github.com/ilius/pull/issues/317)
		+ Parse `sr`, `gr`, `ex_orig`, `ex_transl` tags and `audio`
		+ Remove `None` attribute from `audio` tag
		+ Use unicode symbols for audio and external link
		+ Use another speaker symbol for audio
		+ Add audio controls
		+ Use plain link without an audio tag


- Mobi
	- Update ebook_mobi.py and README.md, [#299](https://github.com/ilius/pyglossary/issues/299)
	- Add PR [#335](https://github.com/ilius/pyglossary/pull/335) with some modifications


- Changes in `ebook_base.py` (Mobi and EPUB)
	- Avoid exception if removing tmpDir failed
	- Use `style.css` dataEntry, [#299](https://github.com/ilius/pyglossary/issues/299)


- DSL Reader:
	- Strip whitespaces around language names, [#264](https://github.com/ilius/pyglossary/issues/264)
	- Add progressbar support, [#264](https://github.com/ilius/pyglossary/issues/264)
	- Run `html.escape` on text before adding html tags, [#265](https://github.com/ilius/pyglossary/issues/265)
	- Strip and unquote glossary name
	- Generate `<i>` and `<font color=...>` instead of `<span style=...>`
	- Avoid adding html comment
	- Remove `\ufeff` from header lines, [#306](https://github.com/ilius/pyglossary/issues/306)


- AppleDict Source
	+ Change path of Dictionary Development Kit, [#300](https://github.com/ilius/pyglossary/issues/300)
	+ Open all text files with `encoding="utf-8"`
	+ Some refactporing
	- Rename 4 options:
		- cleanHTML -> clean_html
		- defaultPrefs -> default_prefs
		- prefsHTML -> prefs_html
		- frontBackMatter -> front_back_matter

- AppleDict Binary
	+ Improvements, [#299](https://github.com/ilius/pyglossary/issues/299)
	+ Read `DefaultStyle.css` file, add as `style.css`, [#299](https://github.com/ilius/pyglossary/issues/299)
	+ Change default value of option: `html=True`

- Octopus MDict	(MDX)
	+ Fix image links
	+ Do not set empty title
	+ Minor improvement in `readmdict.py`
	+ Handle exception when reading from a corrupt MDD file
	+ Add bool flag same_dir_data_files, [#289](https://github.com/ilius/pyglossary/issues/289)
	+ Add read-option: `audio=True` (default: `False`), [#327](https://github.com/ilius/pyglossary/issues/327)
	+ `audio`: remove extra attrs and add comments

- DICT.org plugin:
	- `installToDictd`: skip if target directory does not exist
	- Make rendering dictd files a bit clear in pure txt
	- Fix indention issue and add bword prefix as url

- Fixes and improvements in Dict.cc (SQLite3) plugin:
	- Fix typo, and avoid iterating over cur, use `fetchall()`, [#296](https://github.com/ilius/pyglossary/issues/296)
	- Remove gender from headword, add it to definition, [#296](https://github.com/ilius/pyglossary/issues/296)
	- Avoid running `unescape_unicode`

- JMDict
	- Support reading compressed file directly
	- Show pos before gloss (translations)
	- Avoid running `unescape_unicode`

- DigitalNK: work around Python's sqlite bug, [#282](https://github.com/ilius/pyglossary/issues/282)


- Changes in `dict_org.py` plugin, By Justin Yang
	- Use <br /> to replace newline
	- Replace words with {} around to true web link


- CC-CEDICT Reader:
	+ Fix import error in `conv.py`
	+ Switch from jinja2 to lxml
		- Fix not escaping `<`, `>` and `&`
		- Note: lxml inserts `&[#160](https://github.com/ilius/pyglossary/issues/160);` instead of `&nbsp;`
	+ Use `<font>` instead of `<span style=...>`
	+ add option to use Traditional Chinese for entry name
	- Avoid colorizing if tones count does not match `len(syllables)`, [#328](https://github.com/ilius/pyglossary/issues/328)
	- Add `<font color="">` for each syllable in case of mismatch tones, [#328](https://github.com/ilius/pyglossary/issues/328)

- Rename read/write options:
	- DSL: rename option onlyFixMarkUp to only_fix_markup
	- SQL: rename 2 options:
		- `infoKeys` -> `info_keys`
		- `addExtraInfo` -> `add_extra_info`
	- EDLIN: rename option `havePrevLink` to `prev_link`
	- CSV: rename option `writeInfo` to `enable_info`
	- JSON: rename option `writeInfo` to `enable_info`
	- BGL: rename all read/write options (to cameCase to snake_case)

- New formats:
	- Read "ABC Medical Notes (SQLite3)", `plugins/abc_medical_notes.py`, [#267](https://github.com/ilius/pyglossary/issues/267)
	- Read "Almaany.com (SQLite3)", `plugins/almaany.py`, [#267](https://github.com/ilius/pyglossary/issues/267) [#268](https://github.com/ilius/pyglossary/issues/268)


- Remove TreeDict plugin, `plugins/treedict.py`

- Remove FreeDict writer

