# 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/applications 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 virtual 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-written 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 indentation 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
