Compare commits

..

10 commits

6 changed files with 189 additions and 62 deletions

1
.gitignore vendored
View file

@ -1 +1,2 @@
__pycache__/
*.egg-info/

61
flake.lock generated Normal file
View file

@ -0,0 +1,61 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1681202837,
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1683014792,
"narHash": "sha256-6Va9iVtmmsw4raBc3QKvQT2KT/NGRWlvUlJj46zN8B8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "1a411f23ba299db155a5b45d5e145b85a7aafc42",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

13
flake.nix Normal file
View file

@ -0,0 +1,13 @@
{
inputs = {
nixpkgs.url = github:NixOS/nixpkgs/nixos-unstable;
flake-utils.url = github:numtide/flake-utils;
};
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system: {
defaultPackage = (import ./default.nix) { pkgs = nixpkgs.legacyPackages.${system}; };
});
nixConfig.bash-prompt-prefix = "\\e\[94;1m[xopp2py]\\e\[m ";
}

View file

@ -2,4 +2,4 @@
This exporter generates OML descriptions that use the following vocabulary:
https://msdl.uantwerpen.be/git/lucasalbertins/DTDesign/src/d070f9e9e932ad9910eaab92eabc368e7ee96058/examples/oml/CDF/src/oml/flandersmake.be/cdf/vocabulary/xopp.oml
https://msdl.uantwerpen.be/git/lucasalbertins/DTDesign/src/15c791c78589f9c064fc402feec5228b5a80f549/examples/oml/CDF/src/oml/flandersmake.be/cdf/vocabulary/xopp.oml

View file

@ -1,68 +1,69 @@
{%- macro attributes(pageindex, page, layerindex, layer, elementindex, element) -%}
{%- for key,value in element.attributes.items() %}
ci p{{pageindex}}l{{layerindex}}e{{elementindex}}a{{loop.index}} : xopp:XMLAttribute [
xopp:hasKey "{{key}}"
xopp:hasValue "{{value}}"
xopp:ofLayerElement p{{pageindex}}l{{layerindex}}e{{elementindex}}
object_diagram:inModel model
]
{% endfor %}
{%- endmacro -%}
{%- macro elements(pageindex, page, layerindex, layer) -%}
{% for el in layer.elements %}
ci p{{pageindex}}l{{layerindex}}e{{loop.index}} : xopp:{{el.__class__.__name__}} [
xopp:hasText "{{el.text}}"
xopp:inLayer p{{pageindex}}l{{layerindex}}
object_diagram:inModel model
]
{{ attributes(pageindex, page, layerindex, layer, loop.index, el) -}}
{% endfor %}
{%- endmacro -%}
{%- macro layers(pageindex, page) -%}
{% for layer in page.layers %}
ci p{{pageindex}}l{{loop.index}} : xopp:Layer [
xopp:inPage p{{pageindex}}
object_diagram:inModel model
]
{{ elements(pageindex, page, loop.index, layer) -}}
{% endfor %}
{%- endmacro -%}
{%- macro pages(file) -%}
{% for page in file.pages -%}
ci p{{loop.index}} : xopp:Page [
xopp:hasWidth {{ page.width }}
xopp:hasHeight {{ page.height }}
xopp:hasBackgroundType "{{ page.background_type }}"
xopp:hasBackgroundColor "{{ page.background_color }}"
xopp:hasBackgroundStyle "{{ page.background_style }}"
xopp:inFile file
object_diagram:inModel model
]
{{ layers(loop.index, page) -}}
{%- endfor %}
{%- endmacro -%}
// Warning: Generated code! Do not edit!
// Input file: '{{inputfile}}'
// Generator: https://msdl.uantwerpen.be/git/jexelmans/xopp2py
description <http://flandersmake.be/cdf/description/{{namespace}}#> as {{namespace}} {
{%- if minimal %}
// Minimal mode enabled: All XML attributes and non-text nodes are omitted.
{%- endif %}
uses <http://flandersmake.be/cdf/vocabulary/xopp#> as xopp
uses <http://flandersmake.be/cdf/vocabulary/object_diagram#> as object_diagram
description <{{output_namespace}}#> as {{shorthand}} {
ci model : xopp:Model []
uses <{{namespaces.xopp}}#> as xopp
uses <{{namespaces.object_diagram}}#> as object_diagram
{%- if not minimal %}
uses <{{namespaces.dict}}#> as dict
{%- endif %}
ci file : xopp:File [
xopp:hasCreator "{{ file.creator }}"
ci model : xopp:Model [
object_diagram:hasName "{{shorthand}}"
xopp:hasCreator {{ file.creator | to_oml_string_literal }}
xopp:hasFileVersion {{ file.fileversion }}
xopp:hasTitle "{{ file.title }}"
xopp:hasTitle {{ file.title | to_oml_string_literal }}
{%- if file.preview != None %}
xopp:hasPreview "{{ toBase64(file.preview).decode('utf-8') }}"
xopp:hasPreview {{ file.preview | to_base64_string }}
{%- endif %}
]
{%- for page_index, page in enumerate(file.pages) %}
ci p{{page_index}} : xopp:Page [
xopp:hasWidth {{ page.width }}
xopp:hasHeight {{ page.height }}
xopp:hasBackgroundType {{ page.background_type | to_oml_string_literal }}
xopp:hasBackgroundColor {{ page.background_color | to_oml_string_literal }}
xopp:hasBackgroundStyle {{ page.background_style | to_oml_string_literal }}
xopp:inFile model
object_diagram:inModel model
]
{{ pages(file) }}
{%- for layer_index, layer in enumerate(page.layers) %}
ci p{{page_index}}l{{layer_index}} : xopp:Layer [
xopp:inPage p{{page_index}}
object_diagram:inModel model
]
{%- for el_index, el in enumerate(layer.elements) %}
{%- if not minimal or el.__class__.__name__ == "Text" and el.text != None %}
ci p{{page_index}}l{{layer_index}}e{{el_index}} : xopp:{{el.__class__.__name__}} [
xopp:hasText {{el.text | to_oml_string_literal}}
xopp:inLayer p{{page_index}}l{{layer_index}}
object_diagram:inModel model
]
{%- if not minimal %}
{%- for key, value in el.attributes.items() %}
ci p{{page_index}}l{{layer_index}}e{{el_index}}a{{loop.index}} : xopp:XMLAttribute [
dict:hasKey {{key | to_oml_string_literal}}
dict:hasValue {{value | to_oml_string_literal}}
xopp:ofLayerElement p{{page_index}}l{{layer_index}}e{{el_index}}
object_diagram:inModel model
]
{%- endfor %}
{%- endif %}
{%- endif %}
{%- endfor %}
{%- endfor %}
{%- endfor %}
}

View file

@ -1,18 +1,69 @@
from xopp2py import abstract_syntax
import io
import base64
def writeOML(xournalFile: abstract_syntax.XournalFile, inputfile:str, namespace:str, ostream: io.TextIOBase):
CDF_NAMESPACES = {
# namespace of generated description
"description": "http://flandersmake.be/cdf/description/my_xopp",
"shorthand": "my_xopp",
# vocabulary namespaces
"xopp": "http://flandersmake.be/cdf/vocabulary/xopp",
"object_diagram": "http://flandersmake.be/cdf/vocabulary/object_diagram",
"dict": "http://flandersmake.be/cdf/vocabulary/dict",
}
DTDESIGN_NAMESPACES = {
# namespace of generated description
"description": "http://ua.be/sdo2l/description/artifacts/my_xopp",
"shorthand": "my_xopp",
# vocabulary namespaces
"xopp": "http://ua.be/sdo2l/vocabulary/formalisms/xopp",
"object_diagram": "http://ua.be/sdo2l/vocabulary/formalisms/object_diagram",
"dict": "http://ua.be/sdo2l/vocabulary/formalisms/dict",
"artifacts": "http://ua.be/sdo2l/description/artifacts/",
}
def to_oml_string_literal(python_string):
# Not sure which characters to escape in OML.
# At the very least, quotes should be escaped:
return '"' + python_string.replace('"', '\\"') + '"'
def to_base64_string(bytes):
return '"' + base64.b64encode(bytes).decode('utf-8') + '"'
def writeOML(
xournalFile: abstract_syntax.XournalFile,
inputfile:str,
model_name: str,
ostream: io.TextIOBase,
namespaces=DTDESIGN_NAMESPACES):
""" Write out a Xournal++ file as an OML description.
Parameters:
xournalFile: abstract syntax of a parsed .xopp file
inputfile: name of input file (only for documentation/traceability purposes - any value can be used here)
model_name: used to determine the namespace of the generated OML description
namespace: namespace of xopp-OML-vocabulary
ostream: output stream to write to
"""
import jinja2
import os
import base64
environment = jinja2.Environment(
loader=jinja2.FileSystemLoader(os.path.dirname(__file__)))
environment.filters['to_oml_string_literal'] = to_oml_string_literal
environment.filters['to_base64_string'] = to_base64_string
template = environment.get_template("template.oml")
for piece in template.generate(
minimal=True,
file=xournalFile,
toBase64=base64.b64encode,
inputfile=inputfile,
namespace=namespace):
ostream.write(piece)
enumerate=enumerate,
output_namespace=namespaces['artifacts']+model_name+"_xopp",
shorthand=model_name+"_xopp",
namespaces=namespaces):
ostream.write(piece)