--- /dev/null
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+pip-wheel-metadata/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+.python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+#Pipfile.lock
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
--- /dev/null
+Copyright (c) 2022 Georgios Atheridis <georgios@atheridis.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
--- /dev/null
+Based off of the reddit post:
+https://old.reddit.com/r/ProgrammerHumor/comments/zd8ljb/i_taught_the_chat_bot_an_alternative_syntax_for/
+
+It translates HBML syntax into HTML
--- /dev/null
+:root[lang="en-GB"] {
+ head {
+ meta[charset="UTF-8"]
+ meta[
+ name="viewport"
+ content="width=device-width, initial-scale=1"
+ ]
+
+ title { "Title of webpage" }
+ style { "
+ body {
+ font-family: 'Roboto', sans-serif;
+ }
+
+ .highlight {
+ background-color: yellow;
+ }
+ " }
+ }
+ body {
+
+ section {
+ h1 { "Heading 1" }
+ h2 { "Heading 2" }
+ h3 { "Heading 3" }
+ h4 { "Heading 4" }
+ h5 { "Heading 5" }
+ h6 { "Heading 6" }
+ }
+
+
+
+ div {
+ p { "A paragraph inside a div" }
+ p { "This also works for a single piece of text" }
+ }
+
+ .layer-1 {
+ .layer-2 {
+ .layer-3 {
+ "Text directly inside the .layer-3 div"
+
+ br
+ { "Some text inside an implicit div" }
+ div { "Other text inside an explicit div" }
+ br
+
+ "Text inside the .layer-3 div after the child elements"
+ }
+ }
+ }
+
+ a[href="second.html"] { "Clickable link" }
+ br
+ a[href="inside/here.html"] { "Clickable link that goes inside a directory" }
+
+ p {"Text with a highlighted part " span#an-id.highlight{"right here"}" followed by more text"}
+
+ div {
+ "Double quote string" br 'Single quote string' br `Back tick string`
+ }
+ {
+ "I really like .hbml files"
+ }
+ }
+}
--- /dev/null
+:root {
+ head {}
+ body {
+ a[href="../index.html"] { "return to home" }
+ }
+}
--- /dev/null
+:root[lang="en-CA"] {
+ head {
+ meta[charset="UTF-8"]
+ meta[
+ name="viewport"
+ content="width=device-width, initial-scale=1"
+ ]
+
+ title { "Title of second webpage" }
+ }
+ body {
+
+
+ a[href="index.html"] { "Link back" }
+
+
+ div {
+ "Double quote string" br 'Single quote string' br `Back tick string`
+ }
+ }
+}
+
--- /dev/null
+<!DOCTYPE html><html lang="en-GB"><head><meta charset="UTF-8"/><meta
+ name="viewport"
+ content="width=device-width, initial-scale=1"
+ /><title>Title of webpage</title><style>
+ body {
+ font-family: 'Roboto', sans-serif;
+ }
+
+ .highlight {
+ background-color: yellow;
+ }
+ </style></head><body><section><h1>Heading 1</h1><h2>Heading 2</h2><h3>Heading 3</h3><h4>Heading 4</h4><h5>Heading 5</h5><h6>Heading 6</h6></section><div><p>A paragraph inside a div</p><p>This also works for a single piece of text</p></div><div class="layer-1"><div class="layer-2"><div class="layer-3">Text directly inside the .layer-3 div<br/><div>Some text inside an implicit div</div><div>Other text inside an explicit div</div><br/>Text inside the .layer-3 div after the child elements</div></div></div><a href="second.html">Clickable link</a><br/><a href="inside/here.html">Clickable link that goes inside a directory</a><p>Text with a highlighted part <span id="an-id" class="highlight">right here</span> followed by more text</p><div>Double quote string<br/>Single quote string<br/>Back tick string</div><div>I really like .hbml files</div></body></html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html><html><head></head><body><a href="../index.html">return to home</a></body></html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html><html lang="en-CA"><head><meta charset="UTF-8"/><meta
+ name="viewport"
+ content="width=device-width, initial-scale=1"
+ /><title>Title of second webpage</title></head><body><a href="index.html">Link back</a><div>Double quote string<br/>Single quote string<br/>Back tick string</div></body></html>
\ No newline at end of file
--- /dev/null
+head {
+ title { "This is my title" }
+}
+body {
+ h1 { "Heading 1" }
+}
--- /dev/null
+<head><title>This is my title</title></head><body><h1>Heading 1</h1></body>
\ No newline at end of file
--- /dev/null
+import os
+import sys
+import shutil
+from .tohtml import tohtml
+
+
+def read_file(file):
+ """
+ Read the contents of a file
+ :param file: The file to read
+ :return: The contents of the file
+ """
+ with open(file, "r") as f:
+ return f.read()
+
+
+def write_file(file, data):
+ """
+ Write data to a file
+ :param file: The file to write to
+ :param data: The data to write to the file
+ """
+ with open(file, "w") as f:
+ f.write(data)
+
+
+def main():
+ # Check if the user has given a directory as an argument
+ if len(sys.argv) != 2:
+ print("Please enter a directory as an argument")
+ sys.exit(1)
+
+ # Check if the directory given as an argument exists
+ if not os.path.isdir(sys.argv[1]):
+ print("The directory you entered does not exist")
+ sys.exit(1)
+
+ output_dir = "out"
+ if not os.path.exists(output_dir):
+ os.makedirs(output_dir)
+
+ for root, dirs, files in os.walk(sys.argv[1]):
+ dir = os.path.join(output_dir, root)
+ os.makedirs(dir)
+ for file in files:
+ if os.path.splitext(file)[1] == ".hbml":
+ html_data = tohtml(read_file(os.path.join(root, file)))
+
+ write_file(
+ os.path.join(dir, file.replace(".hbml", ".html")),
+ html_data,
+ )
+ else:
+ shutil.copy(os.path.join(root, file), dir)
+
+
+if __name__ == "__main__":
+ main()
--- /dev/null
+def tohtml(hbml: str):
+ html = ""
+ is_special = False
+ in_string_double = False
+ in_string_single = False
+ in_string_backtick = False
+ in_tags = False
+ in_id = False
+ in_class = False
+ tags = ""
+ id_tag = ""
+ class_tag = ""
+ mem = ""
+ inside = []
+ keywords = {
+ "area",
+ "base",
+ "br",
+ "col",
+ "meta",
+ "embed",
+ "hr",
+ "img",
+ "input",
+ "source",
+ "link",
+ "wbr",
+ "param",
+ "track",
+ "command",
+ "keygen",
+ "menuitem",
+ }
+ for cur in hbml:
+ if cur == "\\":
+ is_special = True
+ continue
+ if is_special:
+ if cur == "'" or cur == '"':
+ mem += cur
+ is_special = False
+ continue
+ if in_id:
+ if cur == " " or cur == "\n" or cur == "\r" or cur == "\t":
+ in_id = False
+ continue
+ if cur == "{" or cur == ".":
+ in_id = False
+ else:
+ if cur == "#":
+ cur = " "
+ id_tag += cur
+ continue
+ if in_class:
+ if cur == " " or cur == "\n" or cur == "\r" or cur == "\t":
+ in_class = False
+ continue
+ if cur == "{" or cur == "#":
+ in_class = False
+ else:
+ if cur == ".":
+ cur = " "
+ class_tag += cur
+ continue
+ if in_tags:
+ if cur == "]":
+ in_tags = False
+ continue
+ tags += cur
+ continue
+ if cur == '"' and (not in_string_single and not in_string_backtick):
+ in_string_double = not in_string_double
+ html += mem
+ mem = ""
+ continue
+ if cur == "'" and (not in_string_double and not in_string_backtick):
+ in_string_single = not in_string_single
+ html += mem
+ mem = ""
+ continue
+ if cur == "`" and (not in_string_single and not in_string_double):
+ in_string_backtick = not in_string_backtick
+ html += mem
+ mem = ""
+ continue
+ if in_string_double or in_string_single or in_string_backtick:
+ mem += cur
+ continue
+ if cur == " " or cur == "\n" or cur == "\r" or cur == "\t":
+ if mem in keywords:
+ html += f"<{mem}"
+ if id_tag:
+ html += f' id="{id_tag}"'
+ if class_tag:
+ html += f' class="{class_tag}"'
+ if tags:
+ html += f" {tags}"
+ html += "/>"
+ mem = ""
+ tags = ""
+ id_tag = ""
+ class_tag = ""
+ continue
+ continue
+ if cur == "[":
+ in_tags = True
+ in_id = False
+ in_class = False
+ continue
+ if cur == "{":
+ if not mem:
+ mem = "div"
+ if mem == ":root":
+ html += "<!DOCTYPE html>"
+ mem = "html"
+ inside.append(mem)
+ html += f"<{mem}"
+ if id_tag:
+ html += f' id="{id_tag}"'
+ if class_tag:
+ html += f' class="{class_tag}"'
+ if tags:
+ html += f" {tags}"
+ html += ">"
+ mem = ""
+ tags = ""
+ id_tag = ""
+ class_tag = ""
+ continue
+ if cur == "}":
+ html += f"</{inside.pop()}>"
+ mem = ""
+ continue
+ if cur == "#":
+ in_id = True
+ continue
+ if cur == ".":
+ in_class = True
+ continue
+ mem += cur
+ return html
--- /dev/null
+from setuptools import setup, find_packages
+
+setup(
+ name="hbml2html",
+ version="0.0.1",
+ author="Georgios Atheridis",
+ author_email="georgios@atheridis.com",
+ packages=find_packages(),
+ entry_points={
+ "console_scripts": [
+ "hbml2html=hbml2html.main:main",
+ ],
+ },
+)