Skip to content

Instantly share code, notes, and snippets.

@Scoder12
Created December 20, 2023 02:55
Show Gist options
  • Save Scoder12/8b9ba6f898749381b2ed04f732777560 to your computer and use it in GitHub Desktop.
Save Scoder12/8b9ba6f898749381b2ed04f732777560 to your computer and use it in GitHub Desktop.
drawj2d remarkable notebook output

The drawj2d reMarkable notebook output wasn't working for me, so I wrote a script that patches the output to be in the newer format.

Tested on reMarkable version 3.8.3.1976.

Usage:

First, edit drawj2d command in the python file to match your installation.

python3 drawj2d_rm_patcher.py ./hello.txt Hello
scp ./processed.tar root@10.11.99.1:/tmp && ssh root@10.11.99.1 -- 'cd ~/.local/share/remarkable/xochitl/; tar -xvf /tmp/processed.tar; rm -f /tmp/processed.tar'
import subprocess as subp
from pathlib import Path
import tarfile
import zipfile
import json
import io
from contextlib import contextmanager
import sys
# drawj2d command
drawj2d = ["java", "-jar", "/path/to/drawj2d.jar"]
def get_uuid(files):
for f in files:
name, _, suffix = f.partition(".")
if suffix == "content":
if "/" in name:
raise AssertionError(name)
return name
def get_page_uuid(files, uuid):
for f in files:
_, _, rest = f.partition(uuid + "/")
if not rest:
continue
name, _, suffix = rest.partition(".")
if suffix == "rm":
if "/" in name:
raise AssertionError(name)
return name
def write_tar_member(tfile, fname, content):
# tarfile requires BytesIO
ti = tarfile.TarInfo(fname)
ti.size = len(content)
bytes_buf = io.BytesIO(initial_bytes=content)
tfile.addfile(ti, bytes_buf)
bytes_buf.close()
@contextmanager
def open_tar_member(tfile, fname):
# json.dump requires StringIO, so yield one.
string_buf = io.StringIO()
try:
yield string_buf
finally:
data_bytes = string_buf.getvalue().encode()
string_buf.close()
write_tar_member(tfile, fname, data_bytes)
def read_json_file(ifile, fname):
with ifile.extractfile(fname) as f:
return json.load(f)
@contextmanager
def update_json_file(ifile, ofile, fname):
data = read_json_file(ifile, fname)
try:
yield data
finally:
with open_tar_member(ofile, fname) as f:
json.dump(data, f, indent=4)
f.write("\n")
def update_content(content, template_name):
del content["transform"]
if len(content["pages"]) != 1:
raise AssertionError()
page_id = content["pages"][0]
new_pages = [
{
"id": page_id,
"idx": {"timestamp": "1:2", "value": "ba"},
"template": {"timestamp": "1:1", "value": template_name},
}
]
content["cPages"] = {
"lastOpened": {
"timestamp": "1:1",
"value": page_id,
},
"original": {"timestamp": "0:0", "value": -1},
"pages": new_pages,
# I'm not sure what this is but it's the same in every notebook I've seen
"uuids": [{"first": "f60f53d5-7257-5e4c-be5d-2fdac79498bd", "second": 1}],
}
content.update(
{
"customZoomCenterX": 0,
"customZoomCenterY": 936,
"customZoomOrientation": "portrait",
"customZoomPageHeight": 1872,
"customZoomPageWidth": 1404,
"customZoomScale": 1,
"documentMetadata": {},
"formatVersion": 2,
"pageTags": [],
"sizeInBytes": "2048",
"tags": [],
"zoomMode": "bestFit",
}
)
content["extraMetadata"]["LastTool"] = "Ballpointv2"
del content["pages"]
return page_id
def main():
if len(sys.argv) < 3:
print(f"Usage: {sys.argv[0]} <file.txt> <notebook name>", file=sys.stderr)
sys.exit(1)
_, textfilename, notebook_name = sys.argv
subp.check_call(drawj2d + ["-Trmn", "./write.hcl", textfilename])
template_name = "P Lines small"
with tarfile.open("out-write.rmn", "r") as a, tarfile.open(
"processed.tar", "w"
) as o:
a.list()
files = a.getnames()
uuid = get_uuid(files)
with update_json_file(a, o, uuid + ".metadata") as metadata:
metadata["createdTime"] = "0"
metadata["visibleName"] = notebook_name
for k in ["deleted", "metadatamodified", "modified", "synced", "version"]:
del metadata[k]
page_id = None
with update_json_file(a, o, uuid + ".content") as content:
page_id = update_content(content, template_name)
with open_tar_member(o, uuid + ".local") as f:
f.write("{\n}\n")
rm_bytes = None
with a.extractfile(f"{uuid}/{page_id}.rm") as f:
rm_bytes = f.read()
write_tar_member(o, f"{uuid}/{page_id}.rm", rm_bytes)
if __name__ == "__main__":
main()
# drawj2d
# usage: drawj2d write.hcl textfile
# preview: drawj2d -Tscr -W157 -H209 write.hcl textfile.txt
# reMarkable: drawj2d -Trmapi write.hcl textfile.txt
#
if {< $argc 1} {
puts {usage: drawj2d write.hcl textfile}
return
}
set textfile [lindex $argv 0]
set f [open $textfile]
font Lines 3.5
m 15 5
text {} 138
while {$f hasnext} {
text [$f readln]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment