Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rmscene 0.4.0 #7

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[tool.poetry]
name = "rmc"
version = "0.1.1"
version = "0.1.2"
description = "Convert to/from v6 .rm files from the reMarkable tablet"
authors = ["Rick Lupton <mail@ricklupton.name>"]
license = "MIT"

[tool.poetry.dependencies]
python = "^3.10"
rmscene = ">=0.1.0, <0.3.0"
rmscene = "^0.4.0"
click = "^8.0"

[tool.poetry.dev-dependencies]
Expand Down
5 changes: 3 additions & 2 deletions src/rmc/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
from pathlib import Path
from contextlib import contextmanager
import click
from rmscene import read_blocks, write_blocks, TextFormat
from rmscene.text import extract_text, simple_text_document
from rmscene.scene_stream import read_blocks, write_blocks, simple_text_document
from rmscene.scene_items import ParagraphStyle

from .exporters.svg import blocks_to_svg
from .exporters.pdf import svg_to_pdf
from .exporters.markdown import print_text
Expand Down
50 changes: 33 additions & 17 deletions src/rmc/exporters/markdown.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,39 @@
"""Export text content of rm files as Markdown."""
import logging

from rmscene import TextFormat
from rmscene.text import extract_text
from rmscene.scene_items import ParagraphStyle
from rmscene.scene_stream import read_tree
from rmscene.text import TextDocument

import logging
# From rmscene tests: test_text_files.py
def formatted_lines(doc):
return [(p.style.value, str(p)) for p in doc.contents]

# From rmscene tests: test_text_files.py (modfied version extract_doc)
def extract_doc(fh):
tree = read_tree(fh)
if tree.root_text:
assert tree.root_text
TextDocument.from_scene_item(tree.root_text)
else:
return None

def print_text(fin, fout):

def print_text(f, fout):
for fmt, line in extract_text(f):
if fmt == TextFormat.BULLET:
print("- " + line, file=fout)
elif fmt == TextFormat.BULLET2:
print(" + " + line, file=fout)
elif fmt == TextFormat.BOLD:
print("> " + line, file=fout)
elif fmt == TextFormat.HEADING:
print("# " + line, file=fout)
elif fmt == TextFormat.PLAIN:
print(line, file=fout)
else:
print(("[unknown format %s] " % fmt) + line, file=fout)
doc = extract_doc(fin)
if doc is None:
print("No text content found")
else:
for fmt, line in formatted_lines(doc):
if fmt == ParagraphStyle.BULLET:
print("- " + line, file=fout)
elif fmt == ParagraphStyle.BULLET2:
print(" + " + line, file=fout)
elif fmt == ParagraphStyle.BOLD:
print("> " + line, file=fout)
elif fmt == ParagraphStyle.HEADING:
print("# " + line, file=fout)
elif fmt == ParagraphStyle.PLAIN:
print(line, file=fout)
else:
print(("[unknown format %s] " % fmt) + line, file=fout)
21 changes: 15 additions & 6 deletions src/rmc/exporters/pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@

from rmscene import read_blocks
from .svg import rm_to_svg, blocks_to_svg
from .utils import (
run_command,
)

_logger = logging.getLogger(__name__)

Expand All @@ -29,10 +26,22 @@ def rm_to_pdf(rm_path, pdf_path, debug=0):
def svg_to_pdf(svg_file, pdf_file):
"""Read svg data from `svg_file` and write PDF data to `pdf_file`."""

with NamedTemporaryFile("wt", suffix=".svg") as fsvg, NamedTemporaryFile("rb", suffix=".pdf") as fpdf:
with NamedTemporaryFile("w", suffix=".svg") as fsvg, NamedTemporaryFile("rb", suffix=".pdf") as fpdf:
fsvg.write(svg_file.read())

fsvg.flush() # Make sure content is writen to the file

# use inkscape to convert svg to pdf
check_call(["inkscape", fsvg.name, "--export-filename", fpdf.name])
try:
print("Convert SVG to PDF using Inkscape")
check_call(["inkscape", fsvg.name, "--export-filename", fpdf.name])
except FileNotFoundError:
print("Inkscape not found in path")

try:
print("Convert SVG to PDF using Inkscape (default MacOS path)")
check_call(["/Applications/Inkscape.app/Contents/MacOS/inkscape", fsvg.name, "--export-filename", fpdf.name])
except:
pass

pdf_file.write(fpdf.read())
pdf_file.flush()
36 changes: 21 additions & 15 deletions src/rmc/exporters/svg.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,17 @@ def draw_stroke(block, output, svg_doc_info, debug):
if debug > 0:
print('----SceneLineItemBlock')
# a SceneLineItemBlock contains a stroke
output.write(f' <!-- SceneLineItemBlock item_id: {block.item_id} -->\n')
output.write(f' <!-- SceneLineItemBlock item_id: {block.item.item_id} -->\n')

# make sure the object is not empty
if block.value is None:
if block.item.value is None:
return

# initiate the pen
pen = Pen.create(block.value.tool.value, block.value.color.value, block.value.thickness_scale)
pen = Pen.create(block.item.value.tool.value, block.item.value.color.value, block.item.value.thickness_scale)

# BEGIN stroke
output.write(f' <!-- Stroke tool: {block.value.tool.name} color: {block.value.color.name} thickness_scale: {block.value.thickness_scale} -->\n')
output.write(f' <!-- Stroke tool: {block.item.value.tool.name} color: {block.item.value.color.name} thickness_scale: {block.item.value.thickness_scale} -->\n')
output.write(' <polyline ')
output.write(f'style="fill:none;stroke:{pen.stroke_color};stroke-width:{pen.stroke_width};opacity:{pen.stroke_opacity}" ')
output.write(f'stroke-linecap="{pen.stroke_linecap}" ')
Expand All @@ -128,7 +128,7 @@ def draw_stroke(block, output, svg_doc_info, debug):
last_ypos = -1.
last_segment_width = 0
# Iterate through the point to form a polyline
for point_id, point in enumerate(block.value.points):
for point_id, point in enumerate(block.item.value.points):
# align the original position
xpos = point.x + svg_doc_info.xpos_delta
ypos = point.y + svg_doc_info.ypos_delta
Expand Down Expand Up @@ -180,14 +180,19 @@ def draw_text(block, output, svg_doc_info, debug):
output.write(' }\n')
output.write(' </style>\n')

for text_item in block.text_items:
# BEGIN text
# https://developer.mozilla.org/en-US/docs/Web/SVG/Element/text
xpos = block.pos_x + svg_doc_info.width / 2
ypos = block.pos_y + svg_doc_info.height / 2
output.write(f' <!-- TextItem item_id: {text_item.item_id} -->\n')
if text_item.text.strip():
output.write(f' <text x="{xpos}" y="{ypos}" class="default">{text_item.text.strip()}</text>\n')

sceneitem_text = block.value
text = "".join([i[1] for i in block.value.items.items()])

# A way to come up with some unique_id
textid = ",".join([repr(i[0]) for i in block.value.items.items()])

# BEGIN text
# https://developer.mozilla.org/en-US/docs/Web/SVG/Element/text
xpos = block.value.pos_x + svg_doc_info.width / 2
ypos = block.value.pos_y + svg_doc_info.height / 2
output.write(f' <!-- TextItem item_id: {textid} -->\n')
output.write(f' <text x="{xpos}" y="{ypos}" class="default">{text}</text>\n')


def get_limits(blocks):
Expand Down Expand Up @@ -216,11 +221,12 @@ def get_limits(blocks):

def get_limits_stroke(block):
# make sure the object is not empty
if block.value is None:

if block.item.value is None:
return None, None, None, None
xmin = xmax = None
ymin = ymax = None
for point in block.value.points:
for point in block.item.value.points:
xpos, ypos = point.x, point.y
if xmin is None or xmin > xpos:
xmin = xpos
Expand Down
29 changes: 0 additions & 29 deletions src/rmc/exporters/utils.py

This file was deleted.

42 changes: 42 additions & 0 deletions tests/run_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/bin/bash

# This script is made to run from the ./src directory

# We need the directory of this script to find the test files
# https://stackoverflow.com/questions/59895/how-do-i-get-the-directory-where-a-bash-script-is-located-from-within-the-script
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )


echo "Test the creation of Markdown files from RM files"
for FILE in $SCRIPT_DIR/rm/*.rm; do
python3 -m rmc.cli -t markdown $FILE > /dev/null
FAILED=$?
if [ $FAILED -eq 1 ]; then
echo "TEST FAILED"
echo "python3 -m rmc.cli -t markdown $FILE > /dev/null"
exit
fi
done

echo "Test the creation of SVG files from RM files"
for FILE in $SCRIPT_DIR/rm/*.rm; do
python3 -m rmc.cli -t svg $FILE > /dev/null
FAILED=$?
if [ $FAILED -eq 1 ]; then
echo "TEST FAILED"
echo "python3 -m rmc.cli -t svg $FILE > /dev/null"
exit
fi
done

echo "Test the creation of PDF files from RM files"
for FILE in $SCRIPT_DIR/rm/*.rm; do
python3 -m rmc.cli -t pdf $FILE > /dev/null
FAILED=$?
if [ $FAILED -eq 1 ]; then
echo "TEST FAILED"
echo "python3 -m rmc.cli -t pdf $FILE > /dev/null"
exit
fi
done