Skip to content

Commit

Permalink
Merge pull request #50 from agateau/add-appstream-file
Browse files Browse the repository at this point in the history
Add appstream file
  • Loading branch information
agateau authored Apr 2, 2023
2 parents 746efee + beab53e commit 714a748
Show file tree
Hide file tree
Showing 6 changed files with 318 additions and 10 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,6 @@

## 1.0.0 - 2018-12-30

First release
### Added

- First release
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Nanonote is a minimalist note taking application.

![Screenshot](screenshot.png)

It automatically saves anything you type. Being minimalist means it has no synchronisation, does not support multiple documents, images or any advanced formatting (the only formatting is highlighting URLs).
It automatically saves anything you type. Being minimalist means it has no synchronisation, does not support multiple documents, images or any advanced formatting (the only formatting is highlighting URLs and Markdown-like headings).

It is developed and tested on Linux but also works on macOS and Windows as well.

Expand Down
72 changes: 72 additions & 0 deletions changelog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any, Iterable


@dataclass
class Release:
version: str
date: str
# type => [changes]
changes: dict[str, list[str]] = field(default_factory=dict)


@dataclass
class Changelog:
# version => release
releases: dict[str, Release] = field(default_factory=dict)

@staticmethod
def from_path(changelog_path: Path) -> "Changelog":
with changelog_path.open() as f:
parser = Parser(f)
return parser.parse()


def _get_dict_last_added_item(dct: dict[Any, Any]) -> Any:
return list(dct.values())[-1]


class Parser:
def __init__(self, line_it: Iterable[str]):
self.changelog = Changelog()
self.line_it = line_it

def parse(self) -> Changelog:
self._parser = self._parse_prolog
for line in self.line_it:
line = line.strip()
if line:
self._parser(line)

return self.changelog

def _parse_prolog(self, line: str) -> None:
if line.startswith("## "):
self._parse_release_title(line)
self._parser = self._parse_release_content

def _parse_release_title(self, line: str) -> None:
version, date = line[3:].split(" - ", maxsplit=1)
release = Release(version=version, date=date)
self.changelog.releases[version] = release

def _parse_release_content(self, line: str) -> None:
if line.startswith("## "):
self._parse_release_title(line)
return

release = _get_dict_last_added_item(self.changelog.releases)

if line.startswith("### "):
change_type = line[4:]
release.changes[change_type] = []
else:
assert line.startswith("- "), line
current_changes = _get_dict_last_added_item(release.changes)
current_changes.append(line[2:])


if __name__ == "__main__":
changelog = Changelog.from_path(Path("CHANGELOG.md"))
print(changelog)
4 changes: 4 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ if (UNIX AND NOT APPLE)
DESTINATION share/applications
RENAME ${INVERSE_ORGANIZATION_NAME}.${APP_NAME}.desktop
)
install(FILES linux/${APP_NAME}.metainfo.xml
DESTINATION share/metainfo
RENAME ${INVERSE_ORGANIZATION_NAME}.${APP_NAME}.metainfo.xml
)
endif()

if (WIN32)
Expand Down
180 changes: 180 additions & 0 deletions src/linux/nanonote.metainfo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2023 Aurélien Gâteau -->
<component type="desktop-application">
<id>com.agateau.Nanonote</id>
<metadata_license>CC0-1.0</metadata_license>
<name>Nanonote</name>
<summary>
A minimalist note taking application.
</summary>
<description>
<p>
Nanonote is a minimalist note taking application.
</p>
<p>
It automatically saves anything you type. Being minimalist means it has no synchronisation, does not support multiple documents, images or any advanced formatting (the only formatting is highlighting URLs and Markdown-like headings).
Pixel Wheels is a retro top-down race game for Linux, macOS, Windows and Android.
</p>
</description>
<categories>
<category>Utility</category>
<category>TextEditor</category>
</categories>
<url type="homepage">https://agateau.com/projects/nanonote</url>
<url type="bugtracker">https://github.com/agateau/nanonote/issues</url>
<url type="donation">https://agateau.com/support</url>
<launchable type="desktop-id">com.agateau.nanonote.desktop</launchable>
<releases>
<release version="1.3.91" date="2023-03-12">
<description>
<p>
<em>Added</em>
</p>
<ul>
<li>Add support for Markdown-style tasks in lists (Daniel Laidig)</li>
<li>Add tips page (Aurelien Gateau)</li>
</ul>
<p>
<em>Changed</em>
</p>
<ul>
<li>Use Ctrl+G to open links and Ctrl+Enter for tasks (Daniel Laidig)</li>
</ul>
<p>
<em>Fixed</em>
</p>
<ul>
<li>Make sure standard actions like Copy or Paste are translated (Aurelien Gateau)</li>
<li>Show keyboard shortcuts in context menus on macOS (Daniel Laidig)</li>
<li>Do not change cursor to pointing-hand when not over a link (Aurelien Gateau)</li>
</ul>
<p>
<em>Internals</em>
</p>
<ul>
<li>CI: Bump Ubuntu to 20.04 and macOS to 11 (Aurelien Gateau)</li>
<li>CI: Install clang-format from muttleyxd/clang-tools-static-binaries (Aurelien Gateau)</li>
<li>Bump Qt to 5.15.2 on macOS and Windows (Aurelien Gateau)</li>
<li>Update singleaplication to 3.3.4 (Aurelien Gateau)</li>
<li>Update Catch2 to 3.3.0 (Aurelien Gateau)</li>
</ul>
</description>
</release>
<release version="1.3.0" date="2020-10-03">
<description>
<p>
<em>Changed</em>
</p>
<ul>
<li>Update Spanish translation (Victorhck)</li>
</ul>
<p>
<em>Fixed</em>
</p>
<ul>
<li>Properly encode URL of the note path (Aurelien Gateau)</li>
<li>Fix untranslated text in About tab on Linux (Aurelien Gateau)</li>
</ul>
</description>
</release>
<release version="1.2.91" date="2020-09-28">
<description>
<p>
<em>Added</em>
</p>
<ul>
<li>You can now search inside your notes with the new search bar (Pavol Oresky)</li>
<li>You can now move selected lines up and down with Alt+Shift+Up and Down (Aurelien Gateau)</li>
<li>macOS dmg (Aurelien Gateau)</li>
<li>Windows installer (Aurelien Gateau)</li>
</ul>
<p>
<em>Changed</em>
</p>
<ul>
<li>Reorganized context menu: added "Edit" and "View" submenus (Aurelien Gateau)</li>
</ul>
</description>
</release>
<release version="1.2.0" date="2019-05-11">
<description>
<p>
<em>Added</em>
</p>
<ul>
<li>New German translation by Vinzenz Vietzke</li>
<li>Allow changing the font size using Ctrl + mouse wheel (Daniel Laidig)</li>
<li>Use the link color of the color theme instead of an hardcoded blue (Daniel Laidig)</li>
<li>Added a way to reset the font size to the default value (Daniel Laidig)</li>
</ul>
<p>
<em>Fixed</em>
</p>
<ul>
<li>Added explanation of how to open URLs to the welcome text (Robert Barat)</li>
<li>Allow '@' in URLs (Aurelien Gateau)</li>
<li>Use QSaveFile for safer saving (Aurelien Gateau)</li>
</ul>
</description>
</release>
<release version="1.1.0" date="2019-02-04">
<description>
<p>
<em>Added</em>
</p>
<ul>
<li>Pressing tab now indents the whole line when the cursor is at the beginning of a list item (Daniel Laidig).</li>
<li>Pressing Enter on an empty list item now unindents, then removes the bullet (Aurelien Gateau).</li>
<li>Added French and Spanish translations (Aurelien Gateau, Victorhck).</li>
</ul>
<p>
<em>Fixed</em>
</p>
<ul>
<li>Improved url detection: '+', '%' and '~' are now allowed in the middle of urls (Aurelien Gateau).</li>
<li>Fixed wrong indentation behavior in upward selections (Aurelien Gateau).</li>
</ul>
</description>
</release>
<release version="1.0.1" date="2019-01-12">
<description>
<p>
<em>Added</em>
</p>
<ul>
<li>Added unit-tests.</li>
<li>Added Travis integration.</li>
<li>Added rpm and deb packages generated using CPack.</li>
</ul>
<p>
<em>Fixed</em>
</p>
<ul>
<li>Fixed indentation and make it respect indentation columns.</li>
<li>Made it possible to indent/unindent selected lines with Tab/Shift+Tab.</li>
<li>Update welcome text to reflect current shortcuts.</li>
</ul>
</description>
</release>
<release version="1.0.0" date="2018-12-30">
<description>
<p>
<em>Added</em>
</p>
<ul>
<li>First release</li>
</ul>
</description>
</release>
</releases>
<provides>
<binary>nanonote</binary>
</provides>
<project_license>GPL-3.0-or-later</project_license>
<screenshots>
<screenshot type="default">
<image type="source" width="1049" height="741">https://github.com/agateau/nanonote/raw/1.3.91/screenshot.png</image>
</screenshot>
</screenshots>
<content_rating type="oars-1.1"/>
</component>
66 changes: 58 additions & 8 deletions tasks.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import os
import re
import shutil
import subprocess
import sys
import xml.etree.ElementTree as ET

from pathlib import Path
from tempfile import NamedTemporaryFile
from typing import List

from invoke import task, run

from changelog import Changelog, Release


ARTIFACTS_DIR = Path("artifacts")

CHANGELOG_MD = Path("CHANGELOG.md")
APPSTREAM_XML = Path("src/linux/nanonote.metainfo.xml")

MAIN_BRANCH = "master"


Expand Down Expand Up @@ -64,6 +71,42 @@ def update_version(c):
path.write_text(text)


@task
def update_appstream_releases(c):
"""Regenerate the <releases> element of our appstream file from
CHANGELOG.md"""
changelog = Changelog.from_path(CHANGELOG_MD)

releases_et = ET.Element("releases")
for release in changelog.releases.values():
release_et = ET.SubElement(releases_et, "release",
{
"version": release.version,
"date": release.date
})
description_et = ET.SubElement(release_et, "description")
for change_type, changes in release.changes.items():
p_et = ET.SubElement(description_et, "p")
em_et = ET.SubElement(p_et, "em")
em_et.text = change_type
ul_et = ET.SubElement(description_et, "ul")
for change in changes:
li_et = ET.SubElement(ul_et, "li")
li_et.text = change
content = ET.tostring(releases_et, encoding="unicode")

# Replace the <releases> element by hand to avoid loosing comments, if any
appstream_content = APPSTREAM_XML.read_text()
appstream_content, count = re.subn("<releases>.*</releases>",
content,
appstream_content, flags=re.DOTALL)
assert count == 1
subprocess.run(["xmllint", "--format", "--output", APPSTREAM_XML, "-"],
check=True,
text=True,
input=appstream_content)


@task
def create_release_branch(c):
version = get_version()
Expand Down Expand Up @@ -98,6 +141,8 @@ def create_release_branch2(c):
if not is_ok("Looks good?"):
sys.exit(1)

update_appstream_releases(c)


@task
def update_ts(c):
Expand Down Expand Up @@ -145,23 +190,28 @@ def download_artifacts(c):
erun(f"gh run download --dir {ARTIFACTS_DIR}", pty=True)


def prepare_release_notes(version_md: Path) -> str:
def prepare_release_notes(release: Release) -> str:
"""
Take the content of $VERSION.md and return it ready to use as GitHub release notes:
- Remove header
- Turn all h3 into h2
Take a Release instance and produce markdown suitable for GitHub release
notes
"""
content = re.sub("^## .*", "", version_md.read_text())
content = re.sub("^### ", "## ", content, flags=re.MULTILINE)
return content.strip() + "\n"
lines = []
for change_type, changes in release.changes.items():
lines.append(f"## {change_type}")
for change in changes:
lines.append(f"- {change}")
return "\n\n".join(lines) + "\n"


@task(help={"pre": "This is a prerelease"})
def publish(c, pre=False):
version = get_version()
changelog = Changelog.from_path(CHANGELOG_MD)
release = changelog.releases[version]
content = prepare_release_notes(release)

files_str = " ".join(str(x) for x in get_artifact_list())
with NamedTemporaryFile() as tmp_file:
content = prepare_release_notes(Path(".changes") / f"{version}.md")
tmp_file.write(content.encode("utf-8"))
tmp_file.flush()
cmd = f"gh release create {version} -F{tmp_file.name} {files_str}"
Expand Down

0 comments on commit 714a748

Please sign in to comment.