diff --git a/.gitignore b/.gitignore index e482470..ba0430d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ -__pycache__/ -*.egg-info/ \ No newline at end of file +__pycache__/ \ No newline at end of file diff --git a/flake.lock b/flake.lock deleted file mode 100644 index e6f9099..0000000 --- a/flake.lock +++ /dev/null @@ -1,61 +0,0 @@ -{ - "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 -} diff --git a/flake.nix b/flake.nix deleted file mode 100644 index 6383574..0000000 --- a/flake.nix +++ /dev/null @@ -1,13 +0,0 @@ -{ - 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 "; -} \ No newline at end of file diff --git a/src/xopp2oml/README.md b/src/xopp2oml/README.md index 114940f..34a1eed 100644 --- a/src/xopp2oml/README.md +++ b/src/xopp2oml/README.md @@ -2,4 +2,4 @@ This exporter generates OML descriptions that use the following vocabulary: -https://msdl.uantwerpen.be/git/lucasalbertins/DTDesign/src/15c791c78589f9c064fc402feec5228b5a80f549/examples/oml/CDF/src/oml/flandersmake.be/cdf/vocabulary/xopp.oml \ No newline at end of file +https://msdl.uantwerpen.be/git/lucasalbertins/DTDesign/src/d070f9e9e932ad9910eaab92eabc368e7ee96058/examples/oml/CDF/src/oml/flandersmake.be/cdf/vocabulary/xopp.oml \ No newline at end of file diff --git a/src/xopp2oml/template.oml b/src/xopp2oml/template.oml index 3c3076c..afd77db 100644 --- a/src/xopp2oml/template.oml +++ b/src/xopp2oml/template.oml @@ -1,69 +1,68 @@ +{%- 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 -{%- if minimal %} -// Minimal mode enabled: All XML attributes and non-text nodes are omitted. -{%- endif %} +description as {{namespace}} { -description <{{output_namespace}}#> as {{shorthand}} { + uses as xopp + uses as object_diagram - uses <{{namespaces.xopp}}#> as xopp - uses <{{namespaces.object_diagram}}#> as object_diagram - {%- if not minimal %} - uses <{{namespaces.dict}}#> as dict - {%- endif %} + ci model : xopp:Model [] - ci model : xopp:Model [ - object_diagram:hasName "{{shorthand}}" - xopp:hasCreator {{ file.creator | to_oml_string_literal }} + ci file : xopp:File [ + xopp:hasCreator "{{ file.creator }}" xopp:hasFileVersion {{ file.fileversion }} - xopp:hasTitle {{ file.title | to_oml_string_literal }} + xopp:hasTitle "{{ file.title }}" {%- if file.preview != None %} - xopp:hasPreview {{ file.preview | to_base64_string }} + xopp:hasPreview "{{ toBase64(file.preview).decode('utf-8') }}" {%- 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 ] - {%- 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 %} + {{ pages(file) }} } diff --git a/src/xopp2oml/writer.py b/src/xopp2oml/writer.py index 758d541..ad13c8f 100644 --- a/src/xopp2oml/writer.py +++ b/src/xopp2oml/writer.py @@ -1,69 +1,18 @@ from xopp2py import abstract_syntax import io -import base64 -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 - """ +def writeOML(xournalFile: abstract_syntax.XournalFile, inputfile:str, namespace:str, ostream: io.TextIOBase): 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, - enumerate=enumerate, - output_namespace=namespaces['artifacts']+model_name+"_xopp", - shorthand=model_name+"_xopp", - namespaces=namespaces): - ostream.write(piece) + namespace=namespace): + ostream.write(piece)