├── jsxloader
├── __init__.py
├── backends
│ ├── __init__.py
│ └── jsx.py
├── nodes
│ ├── __init__.py
│ ├── jsx_script.py
│ ├── file_component.py
│ ├── inline_component.py
│ ├── jsx_syntax.py
│ └── jsx.py
├── config.py
├── templatetags
│ └── jsx_loader.py
└── utils.py
├── tests
└── test_config.py
├── Readme.md
├── .gitignore
└── ReactLoader.excalidraw
/jsxloader/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/jsxloader/backends/__init__.py:
--------------------------------------------------------------------------------
1 | from .jsx import JSXLoaderEngine
--------------------------------------------------------------------------------
/jsxloader/nodes/__init__.py:
--------------------------------------------------------------------------------
1 | from .jsx import JsxNode, JSXNode
2 | from .file_component import JSXFileComponentNode
3 | from .inline_component import JSXInlineComponentNode
4 | from .jsx_syntax import JSXSyntaxNode
5 | from .jsx_script import JSXScriptNode
--------------------------------------------------------------------------------
/jsxloader/nodes/jsx_script.py:
--------------------------------------------------------------------------------
1 | from django import template
2 | from django.template import Context
3 | from ..utils import hash_string
4 |
5 | class JSXScriptNode(template.Node):
6 | def render(self, context: Context) -> str:
7 | self.template_id = self.get_template_id(context.template.origin.name)
8 | context["jsx_loader"] = {}
9 | context["jsx_loader"]["_counter"] = 0
10 | return ""
11 |
12 | def get_template_id(self, template_path):
13 | return hash_string(template_path)[:6]
--------------------------------------------------------------------------------
/jsxloader/nodes/file_component.py:
--------------------------------------------------------------------------------
1 | from django import template
2 | from django.template import Context
3 | from .jsx import JSXNode
4 |
5 | class JSXFileComponentNode(JSXNode):
6 | def __init__(self, path, *args, **kwargs):
7 | super(JSXFileComponentNode, self).__init__(*args, **kwargs)
8 | self.path = path
9 |
10 | def render(self, context: Context) -> str:
11 | super(JSXFileComponentNode, self).render(context)
12 | print(f"From JSX File Component Node: {self.id}")
13 | return self.path
14 |
--------------------------------------------------------------------------------
/jsxloader/nodes/inline_component.py:
--------------------------------------------------------------------------------
1 | from django import template
2 | from django.template import Context
3 | from .jsx import JSXNode
4 |
5 |
6 | class JSXInlineComponentNode(JSXNode):
7 | def __init__(self, nodelist, *args, **kwargs):
8 | super(JSXInlineComponentNode, self).__init__(*args, **kwargs)
9 | self.nodelist = nodelist
10 |
11 | def render(self, context: Context) -> str:
12 | super(JSXInlineComponentNode, self).render(context)
13 | print(f"From JSX Inline Component Node: {self.id}")
14 | return self.nodelist.render(context)
15 |
--------------------------------------------------------------------------------
/jsxloader/config.py:
--------------------------------------------------------------------------------
1 | from dataclasses import dataclass
2 | from django.conf import settings
3 |
4 | __all__ = ["Config", "load_config"]
5 |
6 | @dataclass(kw_only=True)
7 | class Config:
8 | base_dir: str = "jsx_modules"
9 | pre_bundle_dir: str = "prebundle"
10 | post_bundle_dir: str = "postbundle"
11 | config_dir: str = "config"
12 |
13 | def load_config():
14 | # check if "JSX_LOADER_CONFIG" is set in django's settings
15 | if hasattr(settings, "JSX_LOADER_CONFIG"):
16 | config_dict = settings.JSX_LOADER_CONFIG
17 | return dict_to_config(config_dict)
18 | else:
19 | return Config()
20 |
21 | def dict_to_config(config_dict: dict) -> Config:
22 | default_config = Config()
23 | config_dict = {key: value for key, value in config_dict.items() if hasattr(default_config, key)}
24 | return Config(**config_dict)
25 |
--------------------------------------------------------------------------------
/jsxloader/nodes/jsx_syntax.py:
--------------------------------------------------------------------------------
1 | from django import template
2 | from django.template import Context
3 | from .jsx import JSXNode
4 | from ..utils import clean_js_variable_name, hash_string
5 |
6 | class JSXSyntaxNode(JSXNode):
7 |
8 | def __init__(self, nodelist, *args, **kwargs):
9 | super(JSXSyntaxNode, self).__init__(*args, **kwargs)
10 | self.nodelist = nodelist
11 |
12 | def generate_component_id(self, template_name, jsx):
13 | pass
14 |
15 |
16 | def wrap_jsx_in_component(self) -> str:
17 | # component_name = clean_js_variable_name(hash_string())
18 | component_name = ""
19 |
20 | return """
21 | import React from 'react';
22 | import ReactDOM from 'react-dom';
23 |
24 | const """ + component_name + """ = () => {
25 | return (
26 | """ + self.jsx + """
27 | );
28 | }
29 | """
30 |
31 | def render(self, context: Context) -> str:
32 | super(JSXSyntaxNode, self).render(context)
33 | print(f"From JSX Syntax Node: {self.id}")
34 |
35 | self.jsx = self.nodelist.render(context)
36 | return self.wrap_jsx_in_component()
37 |
--------------------------------------------------------------------------------
/jsxloader/backends/jsx.py:
--------------------------------------------------------------------------------
1 | from django.template.backends.django import DjangoTemplates, reraise
2 | from django.template.context import make_context
3 | from django.template import TemplateDoesNotExist
4 |
5 |
6 | class JSXLoaderEngine(DjangoTemplates):
7 | def from_string(self, template_code):
8 | return JSXSupportedTemplate(self.engine.from_string(template_code), self)
9 |
10 | def get_template(self, template_name):
11 | try:
12 | return JSXSupportedTemplate(self.engine.get_template(template_name), self)
13 | except TemplateDoesNotExist as exc:
14 | reraise(exc, self)
15 |
16 |
17 | class JSXSupportedTemplate:
18 | def __init__(self, template, backend):
19 | self.template = template
20 | self.backend = backend
21 |
22 | @property
23 | def origin(self):
24 | return self.template.origin
25 |
26 | def render(self, context=None, request=None):
27 | context = make_context(
28 | context, request, autoescape=self.backend.engine.autoescape
29 | )
30 | print(context)
31 | try:
32 | result = self.template.render(context)
33 | # build jsx bundle
34 | return result
35 | except TemplateDoesNotExist as exc:
36 | reraise(exc, self.backend)
--------------------------------------------------------------------------------
/jsxloader/templatetags/jsx_loader.py:
--------------------------------------------------------------------------------
1 | from django import template
2 | from ..nodes import JsxNode, JSXFileComponentNode, JSXInlineComponentNode, JSXSyntaxNode, JSXScriptNode
3 |
4 |
5 | register = template.Library()
6 |
7 | @register.tag(name="JSXScript")
8 | def do_jsx_script(parser, token):
9 | return JSXScriptNode()
10 |
11 | @register.tag(name="JSX")
12 | def do_jsx(parser, token):
13 | nodelist = parser.parse(("endJSX",))
14 | parser.delete_first_token()
15 | return JSXSyntaxNode(nodelist)
16 |
17 | @register.tag(name='JSXComponentFile')
18 | def do_jsx_component_file(parser, token):
19 | try:
20 | tag_name, path = token.split_contents()
21 | except ValueError:
22 | raise template.TemplateSyntaxError(f"{token.contents} tag requires a Component path.")
23 |
24 | # Ensure the path is properly quoted
25 | if not (path[0] == path[-1] and path[0] in ('"', "'")):
26 | raise template.TemplateSyntaxError(f"Component path must be enclosed in quotes: {path}")
27 |
28 | # Strip the quotes from the path
29 | path = path[1:-1]
30 |
31 | return JSXFileComponentNode(path)
32 |
33 | @register.tag(name="JSXComponent")
34 | def do_jsx_component(parser, token):
35 | nodelist = parser.parse(("endJSXComponent",))
36 | parser.delete_first_token()
37 | return JSXInlineComponentNode(nodelist)
38 |
39 |
40 | # TODO: Add option in tag declaration for naming the JSX Component instead of using random.
41 |
--------------------------------------------------------------------------------
/jsxloader/utils.py:
--------------------------------------------------------------------------------
1 | import hashlib
2 | import re
3 |
4 |
5 | def clean_js_variable_name(var_name: str) -> str:
6 | """
7 | Cleans a JavaScript variable name by removing any non-alphanumeric characters and ensuring it starts with a letter or underscore.
8 |
9 | Args:
10 | var_name (str): The variable name to be cleaned.
11 |
12 | Returns:
13 | str: The cleaned variable name.
14 | """
15 | while var_name[0].isdigit():
16 | var_name = "_" + var_name
17 |
18 | var_name = re.sub("[^0-9a-zA-Z_]+", "", var_name)
19 |
20 | if len(var_name) < 1:
21 | var_name = "_"
22 |
23 | return var_name
24 |
25 |
26 | def hash_string(string: str) -> str:
27 | """
28 | Hashes a given string using SHA256 algorithm and returns the hash.
29 |
30 | Args:
31 | string (str): The string to be hashed.
32 |
33 | Returns:
34 | str: The alphanumeric characters of the hash.
35 | """
36 | hash_object = hashlib.sha256(string.encode())
37 | hex_digest = hash_object.hexdigest()
38 | hex_digest = str(hex_digest)
39 |
40 | # Keep only alphanumeric characters in the output
41 | result = "".join(char for char in hex_digest if char.isalnum())
42 |
43 | return result
44 |
45 |
46 | def template_name_to_dotted_path(template_name: str) -> str:
47 | """
48 | Converts a template name to a dotted path.
49 |
50 | Args:
51 | template_name (str): The template name to convert.
52 |
53 | Returns:
54 | str: The converted dotted path.
55 | """
56 | template_name = template_name.strip("/.\\")
57 | template_name = template_name.split(".")[0]
58 | return template_name.replace("/", ".")
59 |
--------------------------------------------------------------------------------
/tests/test_config.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from django.conf import settings
3 | settings.configure()
4 | from jsxloader.config import load_config, Config
5 |
6 | class ConfigTestCase(unittest.TestCase):
7 | def test_load_config_with_config_set(self):
8 | # Set the "JSX_LOADER_CONFIG" in Django's settings
9 | settings.JSX_LOADER_CONFIG = {
10 | "base_dir": "test_base_dir_value",
11 | "config_dir": "test_config_dir_value",
12 | }
13 |
14 | # Call the load_config function
15 | result = load_config()
16 |
17 | # Assert that the returned result is a Config object
18 | self.assertIsInstance(result, Config)
19 |
20 | # Assert that the Config object has the correct values
21 | self.assertEqual(result.base_dir, "test_base_dir_value")
22 | self.assertEqual(result.config_dir, "test_config_dir_value")
23 |
24 | def test_load_config_without_config_set(self):
25 | # Remove the "JSX_LOADER_CONFIG" from Django's settings
26 | if hasattr(settings, "JSX_LOADER_CONFIG"):
27 | del settings.JSX_LOADER_CONFIG
28 |
29 | # Call the load_config function
30 | result = load_config()
31 |
32 | # Assert that the returned result is a Config object
33 | self.assertIsInstance(result, Config, "load_config() should return a Config object")
34 |
35 | # Assert that the Config object is the default Config
36 | self.assertEqual(result, Config(), "Config object should be the default Config")
37 |
38 | def test_load_config_with_invalid_keys(self):
39 | # Set the "JSX_LOADER_CONFIG" in Django's settings
40 | settings.JSX_LOADER_CONFIG = {
41 | "base_dir": "test_base_dir_value",
42 | "config_dir": "test_config_dir_value",
43 | "invalid_key": "invalid_value",
44 | }
45 |
46 | # Call the load_config function
47 | result = load_config()
48 |
49 | # Assert that the returned result is a Config object
50 | self.assertIsInstance(result, Config)
51 |
52 | # Assert that the Config object has the correct values
53 | self.assertEqual(result.base_dir, "test_base_dir_value")
54 | self.assertEqual(result.config_dir, "test_config_dir_value")
55 | self.assertFalse(hasattr(result, "invalid_key"), "Config object should not have invalid keys.")
56 |
57 | if __name__ == "__main__":
58 | unittest.main()
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | ## Install :
2 | ```bash
3 | pip install django-jsx-loader
4 | ```
5 |
6 | install npm dependencies
7 |
8 | ```bash
9 | npm install --save-dev babel-loader @babel/preset-env @babel/preset-react webpack-cli react react-dom
10 | ```
11 | ## Setup :
12 | ```python
13 | # settings.py
14 | INSTALLED_APPS = [
15 | ...
16 | 'django_jsx_loader',
17 | ...
18 | ]
19 |
20 | ...
21 |
22 | TEMPLATES = [
23 | {
24 | 'BACKEND': 'jsxloader.backends.JSXLoaderEngine',
25 | ...
26 | },
27 | ]
28 |
29 | ```
30 |
31 | ## Configuration :
32 |
33 | You can change configuration inside django's `settings.py`
34 |
35 | ***All paths are relative to the base directory of the project(where manage.py is)*
36 |
37 |
38 | ```python
39 | # settings.py
40 |
41 | JSX_LOADER = {
42 | 'base_dir': 'frontend',
43 | 'output_dir': 'output',
44 | ...
45 | }
46 | ```
47 |
48 | ### Configuration Options :
49 |
50 |
51 | Configration | Type | Description | Default
52 | --- | --- | --- | ---
53 | base_dir | String | The name of the directory housing all other directories related to the jsx loader. | jsx_modules
54 | output_dir | String | The name of the directory where the output javascript files will be placed. | static
55 |
56 |
57 | ## Usage :
58 |
59 | - ### Inline JSX :
60 | ```html
61 |
62 | {% load jsx_loader %}
63 | {% JSX %}
64 |
65 |
Hi, I'm a React App
66 |
67 | {% endJSX %}
68 | ```
69 |
70 | - ### Jsx Component File :
71 |
72 | ```html
73 |
74 | {% load jsx_loader %}
75 | {% JSXComponentFile 'components/counter.jsx' %}
76 | ```
77 |
78 | - ### Inline Jsx Component :
79 |
80 | ```html
81 |
82 | {% load jsx_loader %}
83 | {% JSXComponent %}
84 | import React, { useState } from 'react';
85 |
86 | const Counter = () => {
87 | const [count, setCount] = useState()
88 | return (
89 |
90 |
Hi, I'm a React Counter
91 | {count}
92 |
93 |
94 | );
95 | }
96 |
97 | export default Counter;
98 | {% endJSXComponent %}
99 | ```
100 |
101 | ## Loading Steps :
102 | - Tag Content is copied to a temp file
103 | ```
104 |
105 | const componentID = () => {
106 | return (
107 |
108 |
109 |
Hi, I'm a React App
110 |
111 | );
112 | }
113 |
114 | export default componentID;
115 | ```
116 | - Component Rendering Script Is Made
117 | ```
118 | import JSXComponent from 'temp.component.file'
119 | import AnotherComponent from 'another.temp.file'
120 | import reactDOM from 'react-dom'
121 |
122 | reactDOM.render(, document.getElementById('component-id'))
123 | reactDOM.render(, document.getElementById('another-component-id'))
124 | ```
125 |
126 | - Tags are replaced with placeholder HTML elements.
127 | ```
128 |
129 | ```
130 | - Webpack Config file is made with Rendering Script as entry point
131 | - webpack command is run
132 | - output script file is added to the template
133 | ```
134 |
135 | ```
136 |
137 | #### *****All the steps should be done manually in production by running a command except for tags replacement.***
--------------------------------------------------------------------------------
/jsxloader/nodes/jsx.py:
--------------------------------------------------------------------------------
1 | from ..config import Config
2 | from ..utils import template_name_to_dotted_path
3 | import subprocess
4 | from django import template
5 | from django.conf import settings
6 | import os
7 | import random
8 | import string
9 | from pathlib import Path
10 |
11 |
12 | class JSXNode(template.Node):
13 | def increase_node_count(self):
14 | self.context["jsx_loader"]["_counter"] += 1
15 |
16 | def get_index(self):
17 | return self.context["jsx_loader"]["_counter"]
18 |
19 | def get_template_path(self):
20 | return self.context.template.origin.name
21 |
22 | def get_template_name(self):
23 | return self.context.template.name
24 |
25 | def get_component_id(self):
26 | return ".".join(
27 | [template_name_to_dotted_path(self.template_name), str(self.index)]
28 | )
29 |
30 | def render(self, context) -> str:
31 | self.context = context
32 | self.template_path = self.get_template_path()
33 | self.template_name = self.get_template_name()
34 | self.increase_node_count()
35 | self.index = self.get_index()
36 | self.id = self.get_component_id()
37 |
38 |
39 | class JsxNode(template.Node):
40 | def __init__(self, nodelist):
41 | self.nodelist = nodelist
42 | self.config = Config()
43 |
44 | self.base_dir = self.config.base_dir
45 | self.pre_bundle_dir = self.get_dir(self.config.pre_bundle_dir)
46 | self.post_bundle_dir = self.get_dir(self.config.post_bundle_dir)
47 | self.config_dir = self.get_dir(self.config.config_dir)
48 |
49 | self.id = self.generate_random_id()
50 | self.pre_bundle_file = self.pre_bundle_dir.joinpath(self.id + ".jsx")
51 | self.post_bundle_file = self.post_bundle_dir.joinpath(self.id + ".js")
52 | # self.content = self.nodelist.render({})
53 |
54 | def write_file(self, path, content):
55 | try:
56 | with open(path, "w") as file:
57 | file.write(content)
58 | return path
59 | except FileNotFoundError:
60 | print(f"Error writing '{path}' file: File not found.")
61 | except PermissionError:
62 | print(f"Error writing '{path}' file: Permission denied.")
63 | except Exception as e:
64 | print(f"Error writing '{path}' file: {str(e)}")
65 | return False
66 |
67 | def get_dir(self, name):
68 | project_path = Path(settings.BASE_DIR)
69 | base_path = project_path.joinpath(self.base_dir)
70 | path = base_path.joinpath(name)
71 |
72 | if not path.exists:
73 | os.makedirs(path, exist_ok=True)
74 |
75 | return path
76 |
77 | def generate_random_id(self):
78 | id = "".join(random.choices(string.ascii_uppercase + string.digits, k=6))
79 | return id
80 |
81 | def generate_placeholder_element(self):
82 | return f''
83 |
84 | def bundle_jsx_file(self):
85 | output_file = self.post_bundle_dir.joinpath(self.id + ".js")
86 |
87 | # command = f"npx webpack --mode development --entry {self.pre_bundle_file} --output-path {self.post_bundle_dir} --output-filename {self.id}.js --module-bind js=babel-loader"
88 | command = f'npx --yes webpack --mode development --config "{self.config_file}"'
89 | print(command)
90 | result = subprocess.run(command, shell=True, capture_output=True, text=True)
91 | print(result.stdout)
92 | try:
93 | result.check_returncode()
94 | except subprocess.CalledProcessError:
95 | print(f"Error bundling the jsx file #{self.id}: \n{result.stderr}")
96 |
97 | return output_file
98 |
99 | def generate_config_file(self):
100 | config_file = self.pre_bundle_dir.joinpath(f"{self.id}.config.js")
101 |
102 | config_content = (
103 | """
104 | module.exports = {
105 | entry: '"""
106 | + self.pre_bundle_file.as_posix()
107 | + """',
108 | output: {
109 | path: '"""
110 | + self.post_bundle_dir.as_posix()
111 | + """',
112 | filename: '"""
113 | + self.id
114 | + ".js"
115 | + """',
116 | },
117 | module: {
118 | rules: [
119 | {
120 | test: /\.jsx?$/,
121 | exclude: /(node_modules)/,
122 | use: {
123 | loader: 'babel-loader',
124 | options: {
125 | presets: ['@babel/preset-env', '@babel/preset-react']
126 | }
127 | }
128 | }
129 | ]
130 | }
131 | };
132 | """
133 | )
134 | return self.write_file(config_file, config_content)
135 |
136 | def generate_jsx_render_js_file(self, target_id, jsx_content):
137 | render_js_file = self.post_bundle_dir.joinpath(f"{self.id}.js")
138 |
139 | render_js_content = f"""
140 | import React from 'react';
141 | import ReactDOM from 'react-dom';
142 | import Component from '{self.post_bundle_file}';
143 |
144 | ReactDOM.render(, document.getElementById('{target_id}'));
145 | """
146 | return self.write_file(render_js_file, render_js_content)
147 |
148 | def render(self, context):
149 | self.content = self.nodelist.render(context)
150 | if self.write_file(self.pre_bundle_file, self.content):
151 | self.config_file = self.generate_config_file()
152 | self.bundle_jsx_file()
153 |
154 | return self.generate_placeholder_element()
155 | return ""
156 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | project/
2 | app/
3 | manage.py
4 | db.sqlite3
5 | prebundle/
6 | postbundle/
7 | config/
8 | jsx_modules/
9 | package.json
10 | package-lock.json
11 |
12 | # Byte-compiled / optimized / DLL files
13 | __pycache__/
14 | *.py[cod]
15 | *$py.class
16 |
17 | # C extensions
18 | *.so
19 |
20 | # Distribution / packaging
21 | .Python
22 | build/
23 | develop-eggs/
24 | dist/
25 | downloads/
26 | eggs/
27 | .eggs/
28 | lib/
29 | lib64/
30 | parts/
31 | sdist/
32 | var/
33 | wheels/
34 | share/python-wheels/
35 | *.egg-info/
36 | .installed.cfg
37 | *.egg
38 | MANIFEST
39 |
40 | # PyInstaller
41 | # Usually these files are written by a python script from a template
42 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
43 | *.manifest
44 | *.spec
45 |
46 | # Installer logs
47 | pip-log.txt
48 | pip-delete-this-directory.txt
49 |
50 | # Unit test / coverage reports
51 | htmlcov/
52 | .tox/
53 | .nox/
54 | .coverage
55 | .coverage.*
56 | .cache
57 | nosetests.xml
58 | coverage.xml
59 | *.cover
60 | *.py,cover
61 | .hypothesis/
62 | .pytest_cache/
63 | cover/
64 |
65 | # Translations
66 | *.mo
67 | *.pot
68 |
69 | # Django stuff:
70 | *.log
71 | local_settings.py
72 | db.sqlite3
73 | db.sqlite3-journal
74 |
75 | # Flask stuff:
76 | instance/
77 | .webassets-cache
78 |
79 | # Scrapy stuff:
80 | .scrapy
81 |
82 | # Sphinx documentation
83 | docs/_build/
84 |
85 | # PyBuilder
86 | .pybuilder/
87 | target/
88 |
89 | # Jupyter Notebook
90 | .ipynb_checkpoints
91 |
92 | # IPython
93 | profile_default/
94 | ipython_config.py
95 |
96 | # pyenv
97 | # For a library or package, you might want to ignore these files since the code is
98 | # intended to run in multiple environments; otherwise, check them in:
99 | # .python-version
100 |
101 | # pipenv
102 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
103 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
104 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
105 | # install all needed dependencies.
106 | #Pipfile.lock
107 |
108 | # poetry
109 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
110 | # This is especially recommended for binary packages to ensure reproducibility, and is more
111 | # commonly ignored for libraries.
112 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
113 | #poetry.lock
114 |
115 | # pdm
116 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
117 | #pdm.lock
118 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
119 | # in version control.
120 | # https://pdm.fming.dev/#use-with-ide
121 | .pdm.toml
122 |
123 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
124 | __pypackages__/
125 |
126 | # Celery stuff
127 | celerybeat-schedule
128 | celerybeat.pid
129 |
130 | # SageMath parsed files
131 | *.sage.py
132 |
133 | # Environments
134 | .env
135 | .venv
136 | env/
137 | venv/
138 | ENV/
139 | env.bak/
140 | venv.bak/
141 |
142 | # Spyder project settings
143 | .spyderproject
144 | .spyproject
145 |
146 | # Rope project settings
147 | .ropeproject
148 |
149 | # mkdocs documentation
150 | /site
151 |
152 | # mypy
153 | .mypy_cache/
154 | .dmypy.json
155 | dmypy.json
156 |
157 | # Pyre type checker
158 | .pyre/
159 |
160 | # pytype static type analyzer
161 | .pytype/
162 |
163 | # Cython debug symbols
164 | cython_debug/
165 |
166 | # PyCharm
167 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
168 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
169 | # and can be added to the global gitignore or merged into this file. For a more nuclear
170 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
171 | #.idea/
172 |
173 | # Logs
174 | logs
175 | *.log
176 | npm-debug.log*
177 | yarn-debug.log*
178 | yarn-error.log*
179 | lerna-debug.log*
180 | .pnpm-debug.log*
181 |
182 | # Diagnostic reports (https://nodejs.org/api/report.html)
183 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
184 |
185 | # Runtime data
186 | pids
187 | *.pid
188 | *.seed
189 | *.pid.lock
190 |
191 | # Directory for instrumented libs generated by jscoverage/JSCover
192 | lib-cov
193 |
194 | # Coverage directory used by tools like istanbul
195 | coverage
196 | *.lcov
197 |
198 | # nyc test coverage
199 | .nyc_output
200 |
201 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
202 | .grunt
203 |
204 | # Bower dependency directory (https://bower.io/)
205 | bower_components
206 |
207 | # node-waf configuration
208 | .lock-wscript
209 |
210 | # Compiled binary addons (https://nodejs.org/api/addons.html)
211 | build/Release
212 |
213 | # Dependency directories
214 | node_modules/
215 | jspm_packages/
216 |
217 | # Snowpack dependency directory (https://snowpack.dev/)
218 | web_modules/
219 |
220 | # TypeScript cache
221 | *.tsbuildinfo
222 |
223 | # Optional npm cache directory
224 | .npm
225 |
226 | # Optional eslint cache
227 | .eslintcache
228 |
229 | # Optional stylelint cache
230 | .stylelintcache
231 |
232 | # Microbundle cache
233 | .rpt2_cache/
234 | .rts2_cache_cjs/
235 | .rts2_cache_es/
236 | .rts2_cache_umd/
237 |
238 | # Optional REPL history
239 | .node_repl_history
240 |
241 | # Output of 'npm pack'
242 | *.tgz
243 |
244 | # Yarn Integrity file
245 | .yarn-integrity
246 |
247 | # dotenv environment variable files
248 | .env
249 | .env.development.local
250 | .env.test.local
251 | .env.production.local
252 | .env.local
253 |
254 | # parcel-bundler cache (https://parceljs.org/)
255 | .cache
256 | .parcel-cache
257 |
258 | # Next.js build output
259 | .next
260 | out
261 |
262 | # Nuxt.js build / generate output
263 | .nuxt
264 | dist
265 |
266 | # Gatsby files
267 | .cache/
268 | # Comment in the public line in if your project uses Gatsby and not Next.js
269 | # https://nextjs.org/blog/next-9-1#public-directory-support
270 | # public
271 |
272 | # vuepress build output
273 | .vuepress/dist
274 |
275 | # vuepress v2.x temp and cache directory
276 | .temp
277 | .cache
278 |
279 | # Docusaurus cache and generated files
280 | .docusaurus
281 |
282 | # Serverless directories
283 | .serverless/
284 |
285 | # FuseBox cache
286 | .fusebox/
287 |
288 | # DynamoDB Local files
289 | .dynamodb/
290 |
291 | # TernJS port file
292 | .tern-port
293 |
294 | # Stores VSCode versions used for testing VSCode extensions
295 | .vscode-test
296 |
297 | # yarn v2
298 | .yarn/cache
299 | .yarn/unplugged
300 | .yarn/build-state.yml
301 | .yarn/install-state.gz
302 | .pnp.*
303 |
--------------------------------------------------------------------------------
/ReactLoader.excalidraw:
--------------------------------------------------------------------------------
1 | {
2 | "type": "excalidraw",
3 | "version": 2,
4 | "source": "https://marketplace.visualstudio.com/items?itemName=pomdtr.excalidraw-editor",
5 | "elements": [
6 | {
7 | "type": "rectangle",
8 | "version": 421,
9 | "versionNonce": 416024419,
10 | "isDeleted": false,
11 | "id": "48ddpPigwfhz59uGm416y",
12 | "fillStyle": "solid",
13 | "strokeWidth": 2,
14 | "strokeStyle": "solid",
15 | "roughness": 1,
16 | "opacity": 100,
17 | "angle": 0,
18 | "x": 1327.9049700930693,
19 | "y": -477.5256748993881,
20 | "strokeColor": "#1e1e1e",
21 | "backgroundColor": "transparent",
22 | "width": 599.0082973010623,
23 | "height": 705.2475047469107,
24 | "seed": 1631885079,
25 | "groupIds": [
26 | "EwIH6d5Rn8VaPDNlnMZhT"
27 | ],
28 | "frameId": null,
29 | "roundness": {
30 | "type": 3
31 | },
32 | "boundElements": [
33 | {
34 | "id": "5c5aXxRFQmUBGU7K6FDtE",
35 | "type": "arrow"
36 | },
37 | {
38 | "id": "fL5XpIxZk5gu22oI7Nu6t",
39 | "type": "arrow"
40 | },
41 | {
42 | "id": "Cb_rUlWl5VITiirvJ_U_W",
43 | "type": "arrow"
44 | }
45 | ],
46 | "updated": 1705953142573,
47 | "link": null,
48 | "locked": false
49 | },
50 | {
51 | "type": "text",
52 | "version": 266,
53 | "versionNonce": 1348091152,
54 | "isDeleted": false,
55 | "id": "7vY0ZYpm071wBnS5puyUZ",
56 | "fillStyle": "solid",
57 | "strokeWidth": 2,
58 | "strokeStyle": "solid",
59 | "roughness": 1,
60 | "opacity": 100,
61 | "angle": 0,
62 | "x": 1461.2690815676451,
63 | "y": -555.3379349712066,
64 | "strokeColor": "#1e1e1e",
65 | "backgroundColor": "transparent",
66 | "width": 299.37591552734375,
67 | "height": 45,
68 | "seed": 1274699543,
69 | "groupIds": [
70 | "EwIH6d5Rn8VaPDNlnMZhT"
71 | ],
72 | "frameId": null,
73 | "roundness": null,
74 | "boundElements": [],
75 | "updated": 1706203062490,
76 | "link": null,
77 | "locked": false,
78 | "fontSize": 36,
79 | "fontFamily": 1,
80 | "text": "Django Template",
81 | "textAlign": "left",
82 | "verticalAlign": "top",
83 | "containerId": null,
84 | "originalText": "Django Template",
85 | "lineHeight": 1.25,
86 | "baseline": 32
87 | },
88 | {
89 | "type": "text",
90 | "version": 301,
91 | "versionNonce": 450986256,
92 | "isDeleted": false,
93 | "id": "nqV5ARNn-XuEToyDvmNFr",
94 | "fillStyle": "solid",
95 | "strokeWidth": 2,
96 | "strokeStyle": "solid",
97 | "roughness": 1,
98 | "opacity": 100,
99 | "angle": 0,
100 | "x": 1368.5923261361602,
101 | "y": -420.0976527944158,
102 | "strokeColor": "#1e1e1e",
103 | "backgroundColor": "transparent",
104 | "width": 278.23306128708333,
105 | "height": 25.900968614361208,
106 | "seed": 998156345,
107 | "groupIds": [
108 | "EwIH6d5Rn8VaPDNlnMZhT"
109 | ],
110 | "frameId": null,
111 | "roundness": null,
112 | "boundElements": [],
113 | "updated": 1706203135561,
114 | "link": null,
115 | "locked": false,
116 | "fontSize": 21.584140511967668,
117 | "fontFamily": 3,
118 | "text": "{% load ReactLoader %}",
119 | "textAlign": "left",
120 | "verticalAlign": "top",
121 | "containerId": null,
122 | "originalText": "{% load ReactLoader %}",
123 | "lineHeight": 1.2,
124 | "baseline": 20.000000000000007
125 | },
126 | {
127 | "type": "text",
128 | "version": 328,
129 | "versionNonce": 1378884368,
130 | "isDeleted": false,
131 | "id": "k3N-GivOOaaFFzrNXztFl",
132 | "fillStyle": "solid",
133 | "strokeWidth": 2,
134 | "strokeStyle": "solid",
135 | "roughness": 1,
136 | "opacity": 100,
137 | "angle": 0,
138 | "x": 1359.550691459918,
139 | "y": -353.2031981010545,
140 | "strokeColor": "#1e1e1e",
141 | "backgroundColor": "transparent",
142 | "width": 400.31573486328125,
143 | "height": 210,
144 | "seed": 875297721,
145 | "groupIds": [
146 | "EwIH6d5Rn8VaPDNlnMZhT"
147 | ],
148 | "frameId": null,
149 | "roundness": null,
150 | "boundElements": [],
151 | "updated": 1706203062493,
152 | "link": null,
153 | "locked": false,
154 | "fontSize": 28,
155 | "fontFamily": 1,
156 | "text": "~~~~~~~~~~~~~~~~~\n~~~~~~~~\n~~~~~~~~~\n~~~~~~~~~~~~~~\n~~~~~~~~~~~~~\n~~~~",
157 | "textAlign": "left",
158 | "verticalAlign": "top",
159 | "containerId": null,
160 | "originalText": "~~~~~~~~~~~~~~~~~\n~~~~~~~~\n~~~~~~~~~\n~~~~~~~~~~~~~~\n~~~~~~~~~~~~~\n~~~~",
161 | "lineHeight": 1.25,
162 | "baseline": 200
163 | },
164 | {
165 | "type": "text",
166 | "version": 381,
167 | "versionNonce": 1059522832,
168 | "isDeleted": false,
169 | "id": "b5kzSPbVM57QvPy9BtwDT",
170 | "fillStyle": "solid",
171 | "strokeWidth": 2,
172 | "strokeStyle": "solid",
173 | "roughness": 1,
174 | "opacity": 100,
175 | "angle": 0,
176 | "x": 1359.5506914599177,
177 | "y": -109.57919116697751,
178 | "strokeColor": "#1e1e1e",
179 | "backgroundColor": "transparent",
180 | "width": 552.298828125,
181 | "height": 27.598085979166054,
182 | "seed": 848222039,
183 | "groupIds": [
184 | "EwIH6d5Rn8VaPDNlnMZhT"
185 | ],
186 | "frameId": null,
187 | "roundness": null,
188 | "boundElements": [],
189 | "updated": 1706203110952,
190 | "link": null,
191 | "locked": false,
192 | "fontSize": 22.99840498263838,
193 | "fontFamily": 3,
194 | "text": "{% jsxComponent \"components/Button.js\" %}",
195 | "textAlign": "left",
196 | "verticalAlign": "top",
197 | "containerId": null,
198 | "originalText": "{% jsxComponent \"components/Button.js\" %}",
199 | "lineHeight": 1.2,
200 | "baseline": 22
201 | },
202 | {
203 | "type": "text",
204 | "version": 441,
205 | "versionNonce": 429537552,
206 | "isDeleted": false,
207 | "id": "9x9TZfZLsr3k7uuJ09iJ2",
208 | "fillStyle": "solid",
209 | "strokeWidth": 2,
210 | "strokeStyle": "solid",
211 | "roughness": 1,
212 | "opacity": 100,
213 | "angle": 0,
214 | "x": 1362.8296042437323,
215 | "y": -40.027594324841345,
216 | "strokeColor": "#1e1e1e",
217 | "backgroundColor": "transparent",
218 | "width": 400.31573486328125,
219 | "height": 210,
220 | "seed": 663645433,
221 | "groupIds": [
222 | "EwIH6d5Rn8VaPDNlnMZhT"
223 | ],
224 | "frameId": null,
225 | "roundness": null,
226 | "boundElements": [],
227 | "updated": 1706203062496,
228 | "link": null,
229 | "locked": false,
230 | "fontSize": 28,
231 | "fontFamily": 1,
232 | "text": "~~~~~~~~~~~~~~~~~\n~~~~~~~~\n~~~~~~~~~\n~~~~~~~~~~~~~~\n~~~~~~~~~~~~~\n~~~~",
233 | "textAlign": "left",
234 | "verticalAlign": "top",
235 | "containerId": null,
236 | "originalText": "~~~~~~~~~~~~~~~~~\n~~~~~~~~\n~~~~~~~~~\n~~~~~~~~~~~~~~\n~~~~~~~~~~~~~\n~~~~",
237 | "lineHeight": 1.25,
238 | "baseline": 200
239 | },
240 | {
241 | "type": "rectangle",
242 | "version": 254,
243 | "versionNonce": 1479919053,
244 | "isDeleted": false,
245 | "id": "4EKeFcGFkThotE4vNopwJ",
246 | "fillStyle": "solid",
247 | "strokeWidth": 2,
248 | "strokeStyle": "solid",
249 | "roughness": 1,
250 | "opacity": 100,
251 | "angle": 0,
252 | "x": 2256.633285127929,
253 | "y": -94.69718508713731,
254 | "strokeColor": "#1e1e1e",
255 | "backgroundColor": "transparent",
256 | "width": 322.1874658505312,
257 | "height": 84.33645009926227,
258 | "seed": 480910957,
259 | "groupIds": [],
260 | "frameId": null,
261 | "roundness": {
262 | "type": 3
263 | },
264 | "boundElements": [
265 | {
266 | "id": "fL5XpIxZk5gu22oI7Nu6t",
267 | "type": "arrow"
268 | },
269 | {
270 | "type": "text",
271 | "id": "kdeJMRyfagbzHoSlDU0rU"
272 | },
273 | {
274 | "id": "qa-ro7yMv_wVQD8Lig5-D",
275 | "type": "arrow"
276 | },
277 | {
278 | "id": "HT80xschFgla7fqyUWoKp",
279 | "type": "arrow"
280 | }
281 | ],
282 | "updated": 1705953142573,
283 | "link": null,
284 | "locked": false
285 | },
286 | {
287 | "type": "text",
288 | "version": 141,
289 | "versionNonce": 1129056643,
290 | "isDeleted": false,
291 | "id": "kdeJMRyfagbzHoSlDU0rU",
292 | "fillStyle": "solid",
293 | "strokeWidth": 2,
294 | "strokeStyle": "solid",
295 | "roughness": 1,
296 | "opacity": 100,
297 | "angle": 0,
298 | "x": 2326.447049791476,
299 | "y": -87.52896003750618,
300 | "strokeColor": "#1e1e1e",
301 | "backgroundColor": "transparent",
302 | "width": 182.5599365234375,
303 | "height": 70,
304 | "seed": 1007312419,
305 | "groupIds": [],
306 | "frameId": null,
307 | "roundness": null,
308 | "boundElements": [],
309 | "updated": 1705953142573,
310 | "link": null,
311 | "locked": false,
312 | "fontSize": 28,
313 | "fontFamily": 1,
314 | "text": "Read JSX & \nComponent",
315 | "textAlign": "center",
316 | "verticalAlign": "middle",
317 | "containerId": "4EKeFcGFkThotE4vNopwJ",
318 | "originalText": "Read JSX & Component",
319 | "lineHeight": 1.25,
320 | "baseline": 64
321 | },
322 | {
323 | "type": "arrow",
324 | "version": 1236,
325 | "versionNonce": 1086362384,
326 | "isDeleted": false,
327 | "id": "fL5XpIxZk5gu22oI7Nu6t",
328 | "fillStyle": "solid",
329 | "strokeWidth": 2,
330 | "strokeStyle": "solid",
331 | "roughness": 1,
332 | "opacity": 100,
333 | "angle": 0,
334 | "x": 1941.768777515311,
335 | "y": -56.673041895551094,
336 | "strokeColor": "#1e1e1e",
337 | "backgroundColor": "transparent",
338 | "width": 301.3383609865375,
339 | "height": 2.2685898149188617,
340 | "seed": 687230029,
341 | "groupIds": [],
342 | "frameId": null,
343 | "roundness": {
344 | "type": 2
345 | },
346 | "boundElements": [
347 | {
348 | "type": "text",
349 | "id": "FybSGq4z7Q3JgyOrXewLu"
350 | }
351 | ],
352 | "updated": 1706203128702,
353 | "link": null,
354 | "locked": false,
355 | "startBinding": {
356 | "elementId": "48ddpPigwfhz59uGm416y",
357 | "gap": 14.855510121179236,
358 | "focus": 0.1855909989123895
359 | },
360 | "endBinding": {
361 | "elementId": "4EKeFcGFkThotE4vNopwJ",
362 | "gap": 13.52614662608039,
363 | "focus": 0.012929327645089953
364 | },
365 | "lastCommittedPoint": null,
366 | "startArrowhead": null,
367 | "endArrowhead": "arrow",
368 | "points": [
369 | [
370 | 0,
371 | 0
372 | ],
373 | [
374 | 301.3383609865375,
375 | 2.2685898149188617
376 | ]
377 | ]
378 | },
379 | {
380 | "type": "text",
381 | "version": 26,
382 | "versionNonce": 2056121840,
383 | "isDeleted": false,
384 | "id": "FybSGq4z7Q3JgyOrXewLu",
385 | "fillStyle": "solid",
386 | "strokeWidth": 2,
387 | "strokeStyle": "solid",
388 | "roughness": 1,
389 | "opacity": 100,
390 | "angle": 0,
391 | "x": 1963.2146444128434,
392 | "y": -98.04172273070219,
393 | "strokeColor": "#1e1e1e",
394 | "backgroundColor": "transparent",
395 | "width": 196.7559051513672,
396 | "height": 35,
397 | "seed": 929153891,
398 | "groupIds": [],
399 | "frameId": null,
400 | "roundness": null,
401 | "boundElements": [],
402 | "updated": 1706203071925,
403 | "link": null,
404 | "locked": false,
405 | "fontSize": 28,
406 | "fontFamily": 1,
407 | "text": "Component File",
408 | "textAlign": "center",
409 | "verticalAlign": "middle",
410 | "containerId": "fL5XpIxZk5gu22oI7Nu6t",
411 | "originalText": "Component File",
412 | "lineHeight": 1.25,
413 | "baseline": 25
414 | },
415 | {
416 | "type": "rectangle",
417 | "version": 425,
418 | "versionNonce": 1670657123,
419 | "isDeleted": false,
420 | "id": "hF6QDLelGfOx_MAN9BX_n",
421 | "fillStyle": "solid",
422 | "strokeWidth": 2,
423 | "strokeStyle": "solid",
424 | "roughness": 1,
425 | "opacity": 100,
426 | "angle": 0,
427 | "x": 2791.8076312034514,
428 | "y": -89.18855123708812,
429 | "strokeColor": "#1e1e1e",
430 | "backgroundColor": "transparent",
431 | "width": 357.6204457386994,
432 | "height": 65.42504095815389,
433 | "seed": 1952283299,
434 | "groupIds": [],
435 | "frameId": null,
436 | "roundness": {
437 | "type": 3
438 | },
439 | "boundElements": [
440 | {
441 | "type": "text",
442 | "id": "6CSdbdQGEFK-d3Dgg7VaT"
443 | },
444 | {
445 | "id": "qa-ro7yMv_wVQD8Lig5-D",
446 | "type": "arrow"
447 | },
448 | {
449 | "id": "rehjvCjxbJShTg8-wNYqv",
450 | "type": "arrow"
451 | },
452 | {
453 | "id": "wwcuKOvQLU5eVidKUJEzC",
454 | "type": "arrow"
455 | }
456 | ],
457 | "updated": 1705953142573,
458 | "link": null,
459 | "locked": false
460 | },
461 | {
462 | "type": "text",
463 | "version": 300,
464 | "versionNonce": 1984034637,
465 | "isDeleted": false,
466 | "id": "6CSdbdQGEFK-d3Dgg7VaT",
467 | "fillStyle": "solid",
468 | "strokeWidth": 2,
469 | "strokeStyle": "solid",
470 | "roughness": 1,
471 | "opacity": 100,
472 | "angle": 0,
473 | "x": 2856.573908760301,
474 | "y": -73.97603075801118,
475 | "strokeColor": "#1e1e1e",
476 | "backgroundColor": "transparent",
477 | "width": 228.087890625,
478 | "height": 35,
479 | "seed": 750530115,
480 | "groupIds": [],
481 | "frameId": null,
482 | "roundness": null,
483 | "boundElements": [],
484 | "updated": 1705953142573,
485 | "link": null,
486 | "locked": false,
487 | "fontSize": 28,
488 | "fontFamily": 1,
489 | "text": "Bundle to js file",
490 | "textAlign": "center",
491 | "verticalAlign": "middle",
492 | "containerId": "hF6QDLelGfOx_MAN9BX_n",
493 | "originalText": "Bundle to js file",
494 | "lineHeight": 1.25,
495 | "baseline": 29
496 | },
497 | {
498 | "type": "rectangle",
499 | "version": 610,
500 | "versionNonce": 788497837,
501 | "isDeleted": false,
502 | "id": "qLw9EoJkzM5QXkKV3s362",
503 | "fillStyle": "solid",
504 | "strokeWidth": 2,
505 | "strokeStyle": "solid",
506 | "roughness": 1,
507 | "opacity": 100,
508 | "angle": 0,
509 | "x": 2757.0833109130463,
510 | "y": 121.49592406955452,
511 | "strokeColor": "#1e1e1e",
512 | "backgroundColor": "transparent",
513 | "width": 397.3053832134475,
514 | "height": 63.149700916305164,
515 | "seed": 664920259,
516 | "groupIds": [],
517 | "frameId": null,
518 | "roundness": {
519 | "type": 3
520 | },
521 | "boundElements": [
522 | {
523 | "type": "text",
524 | "id": "36mtKnHXld57R1oAIkUrz"
525 | },
526 | {
527 | "id": "rehjvCjxbJShTg8-wNYqv",
528 | "type": "arrow"
529 | },
530 | {
531 | "id": "5wTIRTg3yguIEfqz2CGja",
532 | "type": "arrow"
533 | }
534 | ],
535 | "updated": 1705953142573,
536 | "link": null,
537 | "locked": false
538 | },
539 | {
540 | "type": "text",
541 | "version": 546,
542 | "versionNonce": 1726396323,
543 | "isDeleted": false,
544 | "id": "36mtKnHXld57R1oAIkUrz",
545 | "fillStyle": "solid",
546 | "strokeWidth": 2,
547 | "strokeStyle": "solid",
548 | "roughness": 1,
549 | "opacity": 100,
550 | "angle": 0,
551 | "x": 2811.816050127192,
552 | "y": 135.5707745277071,
553 | "strokeColor": "#1e1e1e",
554 | "backgroundColor": "transparent",
555 | "width": 287.83990478515625,
556 | "height": 35,
557 | "seed": 1657720931,
558 | "groupIds": [],
559 | "frameId": null,
560 | "roundness": null,
561 | "boundElements": [],
562 | "updated": 1705953142573,
563 | "link": null,
564 | "locked": false,
565 | "fontSize": 28,
566 | "fontFamily": 1,
567 | "text": "place file at /static",
568 | "textAlign": "center",
569 | "verticalAlign": "middle",
570 | "containerId": "qLw9EoJkzM5QXkKV3s362",
571 | "originalText": "place file at /static",
572 | "lineHeight": 1.25,
573 | "baseline": 29
574 | },
575 | {
576 | "type": "arrow",
577 | "version": 457,
578 | "versionNonce": 1427491651,
579 | "isDeleted": false,
580 | "id": "qa-ro7yMv_wVQD8Lig5-D",
581 | "fillStyle": "solid",
582 | "strokeWidth": 2,
583 | "strokeStyle": "solid",
584 | "roughness": 1,
585 | "opacity": 100,
586 | "angle": 0,
587 | "x": 2591.4849692694015,
588 | "y": -47.41453100392816,
589 | "strokeColor": "#1e1e1e",
590 | "backgroundColor": "transparent",
591 | "width": 189.92077220058127,
592 | "height": 5.420189941265207,
593 | "seed": 1864061347,
594 | "groupIds": [],
595 | "frameId": null,
596 | "roundness": {
597 | "type": 2
598 | },
599 | "boundElements": [
600 | {
601 | "type": "text",
602 | "id": "3-g5I8tSn2ccxOC5WIA8W"
603 | }
604 | ],
605 | "updated": 1705953142573,
606 | "link": null,
607 | "locked": false,
608 | "startBinding": {
609 | "elementId": "4EKeFcGFkThotE4vNopwJ",
610 | "gap": 12.664218290941335,
611 | "focus": 0.2164672478811351
612 | },
613 | "endBinding": {
614 | "elementId": "hF6QDLelGfOx_MAN9BX_n",
615 | "gap": 10.401889733468579,
616 | "focus": 0.046506056244010274
617 | },
618 | "lastCommittedPoint": null,
619 | "startArrowhead": null,
620 | "endArrowhead": "arrow",
621 | "points": [
622 | [
623 | 0,
624 | 0
625 | ],
626 | [
627 | 189.92077220058127,
628 | -5.420189941265207
629 | ]
630 | ]
631 | },
632 | {
633 | "type": "text",
634 | "version": 102,
635 | "versionNonce": 141672045,
636 | "isDeleted": false,
637 | "id": "3-g5I8tSn2ccxOC5WIA8W",
638 | "fillStyle": "solid",
639 | "strokeWidth": 2,
640 | "strokeStyle": "solid",
641 | "roughness": 1,
642 | "opacity": 100,
643 | "angle": 0,
644 | "x": 2632.3389845817164,
645 | "y": -78.93664794235482,
646 | "strokeColor": "#1e1e1e",
647 | "backgroundColor": "transparent",
648 | "width": 51.51997375488281,
649 | "height": 35,
650 | "seed": 1027896557,
651 | "groupIds": [],
652 | "frameId": null,
653 | "roundness": null,
654 | "boundElements": [],
655 | "updated": 1705953142573,
656 | "link": null,
657 | "locked": false,
658 | "fontSize": 28,
659 | "fontFamily": 1,
660 | "text": "JSX",
661 | "textAlign": "center",
662 | "verticalAlign": "middle",
663 | "containerId": "qa-ro7yMv_wVQD8Lig5-D",
664 | "originalText": "JSX",
665 | "lineHeight": 1.25,
666 | "baseline": 29
667 | },
668 | {
669 | "type": "arrow",
670 | "version": 720,
671 | "versionNonce": 1063348963,
672 | "isDeleted": false,
673 | "id": "rehjvCjxbJShTg8-wNYqv",
674 | "fillStyle": "solid",
675 | "strokeWidth": 2,
676 | "strokeStyle": "solid",
677 | "roughness": 1,
678 | "opacity": 100,
679 | "angle": 0,
680 | "x": 2963.6895653947713,
681 | "y": -13.956454892209422,
682 | "strokeColor": "#1e1e1e",
683 | "backgroundColor": "transparent",
684 | "width": 2.223844157943404,
685 | "height": 128.47996196609256,
686 | "seed": 1318285901,
687 | "groupIds": [],
688 | "frameId": null,
689 | "roundness": {
690 | "type": 2
691 | },
692 | "boundElements": [
693 | {
694 | "type": "text",
695 | "id": "bxl7RZx1dInrUN2wUJD5F"
696 | }
697 | ],
698 | "updated": 1705953142573,
699 | "link": null,
700 | "locked": false,
701 | "startBinding": {
702 | "elementId": "hF6QDLelGfOx_MAN9BX_n",
703 | "focus": 0.034521381249021266,
704 | "gap": 9.807055386724812
705 | },
706 | "endBinding": {
707 | "elementId": "qLw9EoJkzM5QXkKV3s362",
708 | "focus": 0.025414300294078127,
709 | "gap": 6.972416995671381
710 | },
711 | "lastCommittedPoint": null,
712 | "startArrowhead": null,
713 | "endArrowhead": "arrow",
714 | "points": [
715 | [
716 | 0,
717 | 0
718 | ],
719 | [
720 | -2.223844157943404,
721 | 128.47996196609256
722 | ]
723 | ]
724 | },
725 | {
726 | "type": "text",
727 | "version": 105,
728 | "versionNonce": 1911122125,
729 | "isDeleted": false,
730 | "id": "bxl7RZx1dInrUN2wUJD5F",
731 | "fillStyle": "solid",
732 | "strokeWidth": 2,
733 | "strokeStyle": "solid",
734 | "roughness": 1,
735 | "opacity": 100,
736 | "angle": 0,
737 | "x": 2840.8153847050744,
738 | "y": 6.1025037892488285,
739 | "strokeColor": "#1e1e1e",
740 | "backgroundColor": "transparent",
741 | "width": 90.94395446777344,
742 | "height": 35,
743 | "seed": 1096302595,
744 | "groupIds": [],
745 | "frameId": null,
746 | "roundness": null,
747 | "boundElements": [],
748 | "updated": 1705953142573,
749 | "link": null,
750 | "locked": false,
751 | "fontSize": 28,
752 | "fontFamily": 1,
753 | "text": ".js File",
754 | "textAlign": "center",
755 | "verticalAlign": "middle",
756 | "containerId": "rehjvCjxbJShTg8-wNYqv",
757 | "originalText": ".js File",
758 | "lineHeight": 1.25,
759 | "baseline": 29
760 | },
761 | {
762 | "type": "rectangle",
763 | "version": 532,
764 | "versionNonce": 79187491,
765 | "isDeleted": false,
766 | "id": "6u7ehXkt72AHfe-YYl_kw",
767 | "fillStyle": "solid",
768 | "strokeWidth": 2,
769 | "strokeStyle": "solid",
770 | "roughness": 1,
771 | "opacity": 100,
772 | "angle": 0,
773 | "x": 2264.564890467509,
774 | "y": 110.15737050534062,
775 | "strokeColor": "#1e1e1e",
776 | "backgroundColor": "transparent",
777 | "width": 322.1874658505312,
778 | "height": 80,
779 | "seed": 27911939,
780 | "groupIds": [],
781 | "frameId": null,
782 | "roundness": {
783 | "type": 3
784 | },
785 | "boundElements": [
786 | {
787 | "type": "text",
788 | "id": "R-wirXAyBr1IRTgL5hOlV"
789 | },
790 | {
791 | "id": "Cb_rUlWl5VITiirvJ_U_W",
792 | "type": "arrow"
793 | },
794 | {
795 | "id": "5wTIRTg3yguIEfqz2CGja",
796 | "type": "arrow"
797 | }
798 | ],
799 | "updated": 1705953142573,
800 | "link": null,
801 | "locked": false
802 | },
803 | {
804 | "type": "text",
805 | "version": 429,
806 | "versionNonce": 2085968269,
807 | "isDeleted": false,
808 | "id": "R-wirXAyBr1IRTgL5hOlV",
809 | "fillStyle": "solid",
810 | "strokeWidth": 2,
811 | "strokeStyle": "solid",
812 | "roughness": 1,
813 | "opacity": 100,
814 | "angle": 0,
815 | "x": 2303.956665690138,
816 | "y": 115.15737050534062,
817 | "strokeColor": "#1e1e1e",
818 | "backgroundColor": "transparent",
819 | "width": 243.40391540527344,
820 | "height": 70,
821 | "seed": 1115426467,
822 | "groupIds": [],
823 | "frameId": null,
824 | "roundness": null,
825 | "boundElements": [],
826 | "updated": 1705953142573,
827 | "link": null,
828 | "locked": false,
829 | "fontSize": 28,
830 | "fontFamily": 1,
831 | "text": "Add to template \nImports",
832 | "textAlign": "center",
833 | "verticalAlign": "middle",
834 | "containerId": "6u7ehXkt72AHfe-YYl_kw",
835 | "originalText": "Add to template Imports",
836 | "lineHeight": 1.25,
837 | "baseline": 64
838 | },
839 | {
840 | "type": "rectangle",
841 | "version": 744,
842 | "versionNonce": 561025475,
843 | "isDeleted": false,
844 | "id": "_nb_r7uRYplTPJOuWatzB",
845 | "fillStyle": "solid",
846 | "strokeWidth": 2,
847 | "strokeStyle": "solid",
848 | "roughness": 1,
849 | "opacity": 100,
850 | "angle": 0,
851 | "x": 2796.2285738153946,
852 | "y": -300.8599224261769,
853 | "strokeColor": "#1e1e1e",
854 | "backgroundColor": "transparent",
855 | "width": 353.3684881521192,
856 | "height": 80,
857 | "seed": 1786049411,
858 | "groupIds": [],
859 | "frameId": null,
860 | "roundness": {
861 | "type": 3
862 | },
863 | "boundElements": [
864 | {
865 | "type": "text",
866 | "id": "sJoHxZ73AmeRzPsWac2XP"
867 | },
868 | {
869 | "id": "wwcuKOvQLU5eVidKUJEzC",
870 | "type": "arrow"
871 | },
872 | {
873 | "id": "7GArb-2_pFFxm1BxlQtYc",
874 | "type": "arrow"
875 | }
876 | ],
877 | "updated": 1705953142573,
878 | "link": null,
879 | "locked": false
880 | },
881 | {
882 | "type": "text",
883 | "version": 659,
884 | "versionNonce": 1491902445,
885 | "isDeleted": false,
886 | "id": "sJoHxZ73AmeRzPsWac2XP",
887 | "fillStyle": "solid",
888 | "strokeWidth": 2,
889 | "strokeStyle": "solid",
890 | "roughness": 1,
891 | "opacity": 100,
892 | "angle": 0,
893 | "x": 2817.554877217626,
894 | "y": -295.8599224261769,
895 | "strokeColor": "#1e1e1e",
896 | "backgroundColor": "transparent",
897 | "width": 310.71588134765625,
898 | "height": 70,
899 | "seed": 1731300131,
900 | "groupIds": [],
901 | "frameId": null,
902 | "roundness": null,
903 | "boundElements": [],
904 | "updated": 1705953142573,
905 | "link": null,
906 | "locked": false,
907 | "fontSize": 28,
908 | "fontFamily": 1,
909 | "text": "Create React Render \nScript",
910 | "textAlign": "center",
911 | "verticalAlign": "middle",
912 | "containerId": "_nb_r7uRYplTPJOuWatzB",
913 | "originalText": "Create React Render Script",
914 | "lineHeight": 1.25,
915 | "baseline": 64
916 | },
917 | {
918 | "type": "rectangle",
919 | "version": 620,
920 | "versionNonce": 1906270563,
921 | "isDeleted": false,
922 | "id": "9HZnp_BH1RhRnqMf1bFom",
923 | "fillStyle": "solid",
924 | "strokeWidth": 2,
925 | "strokeStyle": "solid",
926 | "roughness": 1,
927 | "opacity": 100,
928 | "angle": 0,
929 | "x": 2252.4118748361866,
930 | "y": -474.2741778060989,
931 | "strokeColor": "#1e1e1e",
932 | "backgroundColor": "transparent",
933 | "width": 322.1874658505312,
934 | "height": 80,
935 | "seed": 1261434157,
936 | "groupIds": [],
937 | "frameId": null,
938 | "roundness": {
939 | "type": 3
940 | },
941 | "boundElements": [
942 | {
943 | "type": "text",
944 | "id": "rlP7F3IwzOxBrlfBR5kXn"
945 | },
946 | {
947 | "id": "5c5aXxRFQmUBGU7K6FDtE",
948 | "type": "arrow"
949 | },
950 | {
951 | "id": "7GArb-2_pFFxm1BxlQtYc",
952 | "type": "arrow"
953 | },
954 | {
955 | "id": "HT80xschFgla7fqyUWoKp",
956 | "type": "arrow"
957 | },
958 | {
959 | "id": "t2I8QqNMfMAmyW1LgOgyu",
960 | "type": "arrow"
961 | }
962 | ],
963 | "updated": 1705953142573,
964 | "link": null,
965 | "locked": false
966 | },
967 | {
968 | "type": "text",
969 | "version": 590,
970 | "versionNonce": 59513421,
971 | "isDeleted": false,
972 | "id": "rlP7F3IwzOxBrlfBR5kXn",
973 | "fillStyle": "solid",
974 | "strokeWidth": 2,
975 | "strokeStyle": "solid",
976 | "roughness": 1,
977 | "opacity": 100,
978 | "angle": 0,
979 | "x": 2269.4036637917256,
980 | "y": -469.2741778060989,
981 | "strokeColor": "#1e1e1e",
982 | "backgroundColor": "transparent",
983 | "width": 288.2038879394531,
984 | "height": 70,
985 | "seed": 355649421,
986 | "groupIds": [],
987 | "frameId": null,
988 | "roundness": null,
989 | "boundElements": [],
990 | "updated": 1705953142573,
991 | "link": null,
992 | "locked": false,
993 | "fontSize": 28,
994 | "fontFamily": 1,
995 | "text": "Create Placeholder \nHtml element with ID",
996 | "textAlign": "center",
997 | "verticalAlign": "middle",
998 | "containerId": "9HZnp_BH1RhRnqMf1bFom",
999 | "originalText": "Create Placeholder Html element with ID",
1000 | "lineHeight": 1.25,
1001 | "baseline": 64
1002 | },
1003 | {
1004 | "type": "arrow",
1005 | "version": 1255,
1006 | "versionNonce": 1735333648,
1007 | "isDeleted": false,
1008 | "id": "5c5aXxRFQmUBGU7K6FDtE",
1009 | "fillStyle": "solid",
1010 | "strokeWidth": 2,
1011 | "strokeStyle": "solid",
1012 | "roughness": 1,
1013 | "opacity": 100,
1014 | "angle": 0,
1015 | "x": 2240.592665907191,
1016 | "y": -431.3590662118504,
1017 | "strokeColor": "#1e1e1e",
1018 | "backgroundColor": "transparent",
1019 | "width": 295.78169777719313,
1020 | "height": 3.588338878432012,
1021 | "seed": 1966668419,
1022 | "groupIds": [],
1023 | "frameId": null,
1024 | "roundness": {
1025 | "type": 2
1026 | },
1027 | "boundElements": [
1028 | {
1029 | "type": "text",
1030 | "id": "zn8i5Hsl42h6zoio6rNXg"
1031 | }
1032 | ],
1033 | "updated": 1706203128702,
1034 | "link": null,
1035 | "locked": false,
1036 | "startBinding": {
1037 | "elementId": "9HZnp_BH1RhRnqMf1bFom",
1038 | "focus": -0.019482638204442196,
1039 | "gap": 11.819208928995522
1040 | },
1041 | "endBinding": {
1042 | "elementId": "48ddpPigwfhz59uGm416y",
1043 | "focus": -0.8393321837897294,
1044 | "gap": 17.897700735866124
1045 | },
1046 | "lastCommittedPoint": null,
1047 | "startArrowhead": null,
1048 | "endArrowhead": "arrow",
1049 | "points": [
1050 | [
1051 | 0,
1052 | 0
1053 | ],
1054 | [
1055 | -295.78169777719313,
1056 | 3.588338878432012
1057 | ]
1058 | ]
1059 | },
1060 | {
1061 | "type": "text",
1062 | "version": 117,
1063 | "versionNonce": 1778788336,
1064 | "isDeleted": false,
1065 | "id": "zn8i5Hsl42h6zoio6rNXg",
1066 | "fillStyle": "solid",
1067 | "strokeWidth": 2,
1068 | "strokeStyle": "solid",
1069 | "roughness": 1,
1070 | "opacity": 100,
1071 | "angle": 0,
1072 | "x": 2033.271831972208,
1073 | "y": -447.06489677263437,
1074 | "strokeColor": "#1e1e1e",
1075 | "backgroundColor": "transparent",
1076 | "width": 118.85997009277344,
1077 | "height": 35,
1078 | "seed": 721042221,
1079 | "groupIds": [],
1080 | "frameId": null,
1081 | "roundness": null,
1082 | "boundElements": [],
1083 | "updated": 1706203071924,
1084 | "link": null,
1085 | "locked": false,
1086 | "fontSize": 28,
1087 | "fontFamily": 1,
1088 | "text": "Html tag",
1089 | "textAlign": "center",
1090 | "verticalAlign": "middle",
1091 | "containerId": "5c5aXxRFQmUBGU7K6FDtE",
1092 | "originalText": "Html tag",
1093 | "lineHeight": 1.25,
1094 | "baseline": 25
1095 | },
1096 | {
1097 | "type": "arrow",
1098 | "version": 753,
1099 | "versionNonce": 1491275536,
1100 | "isDeleted": false,
1101 | "id": "Cb_rUlWl5VITiirvJ_U_W",
1102 | "fillStyle": "solid",
1103 | "strokeWidth": 2,
1104 | "strokeStyle": "solid",
1105 | "roughness": 1,
1106 | "opacity": 100,
1107 | "angle": 0,
1108 | "x": 2254.1630007340405,
1109 | "y": 147.2383350178846,
1110 | "strokeColor": "#1e1e1e",
1111 | "backgroundColor": "transparent",
1112 | "width": 306.6996121132677,
1113 | "height": 2.357844398015459,
1114 | "seed": 1922818221,
1115 | "groupIds": [],
1116 | "frameId": null,
1117 | "roundness": {
1118 | "type": 2
1119 | },
1120 | "boundElements": [
1121 | {
1122 | "type": "text",
1123 | "id": "jBaiHlPSt9yb2v-9YWPxi"
1124 | }
1125 | ],
1126 | "updated": 1706203128703,
1127 | "link": null,
1128 | "locked": false,
1129 | "startBinding": {
1130 | "elementId": "6u7ehXkt72AHfe-YYl_kw",
1131 | "focus": 0.038813575708421796,
1132 | "gap": 10.401889733468579
1133 | },
1134 | "endBinding": {
1135 | "elementId": "48ddpPigwfhz59uGm416y",
1136 | "focus": 0.7531758460337967,
1137 | "gap": 20.550121226640954
1138 | },
1139 | "lastCommittedPoint": null,
1140 | "startArrowhead": null,
1141 | "endArrowhead": "arrow",
1142 | "points": [
1143 | [
1144 | 0,
1145 | 0
1146 | ],
1147 | [
1148 | -306.6996121132677,
1149 | -2.357844398015459
1150 | ]
1151 | ]
1152 | },
1153 | {
1154 | "type": "text",
1155 | "version": 82,
1156 | "versionNonce": 1856205808,
1157 | "isDeleted": false,
1158 | "id": "jBaiHlPSt9yb2v-9YWPxi",
1159 | "fillStyle": "solid",
1160 | "strokeWidth": 2,
1161 | "strokeStyle": "solid",
1162 | "roughness": 1,
1163 | "opacity": 100,
1164 | "angle": 0,
1165 | "x": 1995.8655382135153,
1166 | "y": 48.84248477229522,
1167 | "strokeColor": "#1e1e1e",
1168 | "backgroundColor": "transparent",
1169 | "width": 148.09193420410156,
1170 | "height": 35,
1171 | "seed": 1807928899,
1172 | "groupIds": [],
1173 | "frameId": null,
1174 | "roundness": null,
1175 | "boundElements": [],
1176 | "updated": 1706203071926,
1177 | "link": null,
1178 | "locked": false,
1179 | "fontSize": 28,
1180 | "fontFamily": 1,
1181 | "text": "Script Tag",
1182 | "textAlign": "center",
1183 | "verticalAlign": "middle",
1184 | "containerId": "Cb_rUlWl5VITiirvJ_U_W",
1185 | "originalText": "Script Tag",
1186 | "lineHeight": 1.25,
1187 | "baseline": 25
1188 | },
1189 | {
1190 | "type": "arrow",
1191 | "version": 458,
1192 | "versionNonce": 150214723,
1193 | "isDeleted": false,
1194 | "id": "5wTIRTg3yguIEfqz2CGja",
1195 | "fillStyle": "solid",
1196 | "strokeWidth": 2,
1197 | "strokeStyle": "solid",
1198 | "roughness": 1,
1199 | "opacity": 100,
1200 | "angle": 0,
1201 | "x": 2748.807399972868,
1202 | "y": 149.83135761219165,
1203 | "strokeColor": "#1e1e1e",
1204 | "backgroundColor": "transparent",
1205 | "width": 155.90511150793964,
1206 | "height": 2.7840476567237857,
1207 | "seed": 1382424931,
1208 | "groupIds": [],
1209 | "frameId": null,
1210 | "roundness": {
1211 | "type": 2
1212 | },
1213 | "boundElements": [
1214 | {
1215 | "type": "text",
1216 | "id": "zRv3vdhic6Y7pc3xU4xDZ"
1217 | }
1218 | ],
1219 | "updated": 1705953142573,
1220 | "link": null,
1221 | "locked": false,
1222 | "startBinding": {
1223 | "elementId": "qLw9EoJkzM5QXkKV3s362",
1224 | "focus": 0.19744197420815277,
1225 | "gap": 8.275910940178164
1226 | },
1227 | "endBinding": {
1228 | "elementId": "6u7ehXkt72AHfe-YYl_kw",
1229 | "focus": 0.12698174746373617,
1230 | "gap": 6.149932146888204
1231 | },
1232 | "lastCommittedPoint": null,
1233 | "startArrowhead": null,
1234 | "endArrowhead": "arrow",
1235 | "points": [
1236 | [
1237 | 0,
1238 | 0
1239 | ],
1240 | [
1241 | -155.90511150793964,
1242 | 2.7840476567237857
1243 | ]
1244 | ]
1245 | },
1246 | {
1247 | "type": "text",
1248 | "version": 124,
1249 | "versionNonce": 1110098285,
1250 | "isDeleted": false,
1251 | "id": "zRv3vdhic6Y7pc3xU4xDZ",
1252 | "fillStyle": "solid",
1253 | "strokeWidth": 2,
1254 | "strokeStyle": "solid",
1255 | "roughness": 1,
1256 | "opacity": 100,
1257 | "angle": 0,
1258 | "x": 2613.342433886155,
1259 | "y": 132.45648696205143,
1260 | "strokeColor": "#1e1e1e",
1261 | "backgroundColor": "transparent",
1262 | "width": 66.83596801757812,
1263 | "height": 35,
1264 | "seed": 1275992749,
1265 | "groupIds": [],
1266 | "frameId": null,
1267 | "roundness": null,
1268 | "boundElements": [],
1269 | "updated": 1705953142573,
1270 | "link": null,
1271 | "locked": false,
1272 | "fontSize": 28,
1273 | "fontFamily": 1,
1274 | "text": "Path",
1275 | "textAlign": "center",
1276 | "verticalAlign": "middle",
1277 | "containerId": "5wTIRTg3yguIEfqz2CGja",
1278 | "originalText": "Path",
1279 | "lineHeight": 1.25,
1280 | "baseline": 29
1281 | },
1282 | {
1283 | "type": "arrow",
1284 | "version": 1326,
1285 | "versionNonce": 1542330339,
1286 | "isDeleted": false,
1287 | "id": "wwcuKOvQLU5eVidKUJEzC",
1288 | "fillStyle": "solid",
1289 | "strokeWidth": 2,
1290 | "strokeStyle": "solid",
1291 | "roughness": 1,
1292 | "opacity": 100,
1293 | "angle": 0,
1294 | "x": 2967.925428056798,
1295 | "y": -211.8753518882353,
1296 | "strokeColor": "#1e1e1e",
1297 | "backgroundColor": "transparent",
1298 | "width": 0.40046478090198434,
1299 | "height": 108.62778767784232,
1300 | "seed": 2146761155,
1301 | "groupIds": [],
1302 | "frameId": null,
1303 | "roundness": {
1304 | "type": 2
1305 | },
1306 | "boundElements": [
1307 | {
1308 | "type": "text",
1309 | "id": "hJUfyH1IeNV2LMJOF3DOF"
1310 | }
1311 | ],
1312 | "updated": 1705953142574,
1313 | "link": null,
1314 | "locked": false,
1315 | "startBinding": {
1316 | "elementId": "_nb_r7uRYplTPJOuWatzB",
1317 | "gap": 8.984570537941636,
1318 | "focus": 0.027190199767608975
1319 | },
1320 | "endBinding": {
1321 | "elementId": "hF6QDLelGfOx_MAN9BX_n",
1322 | "gap": 14.059012973304846,
1323 | "focus": -0.01824905115566554
1324 | },
1325 | "lastCommittedPoint": null,
1326 | "startArrowhead": null,
1327 | "endArrowhead": "arrow",
1328 | "points": [
1329 | [
1330 | 0,
1331 | 0
1332 | ],
1333 | [
1334 | -0.40046478090198434,
1335 | 108.62778767784232
1336 | ]
1337 | ]
1338 | },
1339 | {
1340 | "type": "text",
1341 | "version": 17,
1342 | "versionNonce": 864685005,
1343 | "isDeleted": false,
1344 | "id": "hJUfyH1IeNV2LMJOF3DOF",
1345 | "fillStyle": "solid",
1346 | "strokeWidth": 2,
1347 | "strokeStyle": "solid",
1348 | "roughness": 1,
1349 | "opacity": 100,
1350 | "angle": 0,
1351 | "x": 2689.6357906032836,
1352 | "y": -266.89703404264526,
1353 | "strokeColor": "#1e1e1e",
1354 | "backgroundColor": "transparent",
1355 | "width": 183.53990173339844,
1356 | "height": 35,
1357 | "seed": 1881810765,
1358 | "groupIds": [],
1359 | "frameId": null,
1360 | "roundness": null,
1361 | "boundElements": [],
1362 | "updated": 1705953142574,
1363 | "link": null,
1364 | "locked": false,
1365 | "fontSize": 28,
1366 | "fontFamily": 1,
1367 | "text": "Render Script",
1368 | "textAlign": "center",
1369 | "verticalAlign": "middle",
1370 | "containerId": "wwcuKOvQLU5eVidKUJEzC",
1371 | "originalText": "Render Script",
1372 | "lineHeight": 1.25,
1373 | "baseline": 29
1374 | },
1375 | {
1376 | "type": "arrow",
1377 | "version": 1039,
1378 | "versionNonce": 592513581,
1379 | "isDeleted": false,
1380 | "id": "7GArb-2_pFFxm1BxlQtYc",
1381 | "fillStyle": "solid",
1382 | "strokeWidth": 2,
1383 | "strokeStyle": "solid",
1384 | "roughness": 1,
1385 | "opacity": 100,
1386 | "angle": 0,
1387 | "x": 2596.98697501123,
1388 | "y": -255.33753810714762,
1389 | "strokeColor": "#1e1e1e",
1390 | "backgroundColor": "transparent",
1391 | "width": 184.63648098363183,
1392 | "height": 2.3342313692265293,
1393 | "seed": 771298669,
1394 | "groupIds": [],
1395 | "frameId": null,
1396 | "roundness": {
1397 | "type": 2
1398 | },
1399 | "boundElements": [
1400 | {
1401 | "type": "text",
1402 | "id": "8PYGtyK3sU7YcbxLHCjFa"
1403 | }
1404 | ],
1405 | "updated": 1705953142574,
1406 | "link": null,
1407 | "locked": false,
1408 | "startBinding": {
1409 | "elementId": "ubSZ2N6MP6huCApVsnVnc",
1410 | "focus": -0.147653438269418,
1411 | "gap": 10.470404579861679
1412 | },
1413 | "endBinding": {
1414 | "elementId": "_nb_r7uRYplTPJOuWatzB",
1415 | "focus": -0.24328807622845455,
1416 | "gap": 14.605117820533223
1417 | },
1418 | "lastCommittedPoint": null,
1419 | "startArrowhead": null,
1420 | "endArrowhead": "arrow",
1421 | "points": [
1422 | [
1423 | 0,
1424 | 0
1425 | ],
1426 | [
1427 | 184.63648098363183,
1428 | 2.3342313692265293
1429 | ]
1430 | ]
1431 | },
1432 | {
1433 | "type": "text",
1434 | "version": 98,
1435 | "versionNonce": 1035844387,
1436 | "isDeleted": false,
1437 | "id": "8PYGtyK3sU7YcbxLHCjFa",
1438 | "fillStyle": "solid",
1439 | "strokeWidth": 2,
1440 | "strokeStyle": "solid",
1441 | "roughness": 1,
1442 | "opacity": 100,
1443 | "angle": 0,
1444 | "x": 2660.9067935907806,
1445 | "y": -457.5147684083752,
1446 | "strokeColor": "#1e1e1e",
1447 | "backgroundColor": "transparent",
1448 | "width": 37.09999084472656,
1449 | "height": 35,
1450 | "seed": 94505891,
1451 | "groupIds": [],
1452 | "frameId": null,
1453 | "roundness": null,
1454 | "boundElements": [],
1455 | "updated": 1705953142574,
1456 | "link": null,
1457 | "locked": false,
1458 | "fontSize": 28,
1459 | "fontFamily": 1,
1460 | "text": "ID",
1461 | "textAlign": "center",
1462 | "verticalAlign": "middle",
1463 | "containerId": "7GArb-2_pFFxm1BxlQtYc",
1464 | "originalText": "ID",
1465 | "lineHeight": 1.25,
1466 | "baseline": 29
1467 | },
1468 | {
1469 | "type": "arrow",
1470 | "version": 496,
1471 | "versionNonce": 1382628493,
1472 | "isDeleted": false,
1473 | "id": "HT80xschFgla7fqyUWoKp",
1474 | "fillStyle": "solid",
1475 | "strokeWidth": 2,
1476 | "strokeStyle": "solid",
1477 | "roughness": 1,
1478 | "opacity": 100,
1479 | "angle": 0,
1480 | "x": 2416.029268809185,
1481 | "y": -108.15886557435715,
1482 | "strokeColor": "#1e1e1e",
1483 | "backgroundColor": "transparent",
1484 | "width": 3.8822606864068803,
1485 | "height": 107.45483366420731,
1486 | "seed": 1399926179,
1487 | "groupIds": [],
1488 | "frameId": null,
1489 | "roundness": {
1490 | "type": 2
1491 | },
1492 | "boundElements": [
1493 | {
1494 | "type": "text",
1495 | "id": "wd4uz3Mn4IcZN0LNJKH_6"
1496 | }
1497 | ],
1498 | "updated": 1705953142574,
1499 | "link": null,
1500 | "locked": false,
1501 | "startBinding": {
1502 | "elementId": "4EKeFcGFkThotE4vNopwJ",
1503 | "focus": -0.019414536078267822,
1504 | "gap": 13.461680487219809
1505 | },
1506 | "endBinding": {
1507 | "elementId": "ubSZ2N6MP6huCApVsnVnc",
1508 | "focus": 0.0257599247494445,
1509 | "gap": 4.809984359043085
1510 | },
1511 | "lastCommittedPoint": null,
1512 | "startArrowhead": null,
1513 | "endArrowhead": "arrow",
1514 | "points": [
1515 | [
1516 | 0,
1517 | 0
1518 | ],
1519 | [
1520 | 3.8822606864068803,
1521 | -107.45483366420731
1522 | ]
1523 | ]
1524 | },
1525 | {
1526 | "type": "text",
1527 | "version": 16,
1528 | "versionNonce": 1363173059,
1529 | "isDeleted": false,
1530 | "id": "wd4uz3Mn4IcZN0LNJKH_6",
1531 | "fillStyle": "solid",
1532 | "strokeWidth": 2,
1533 | "strokeStyle": "solid",
1534 | "roughness": 1,
1535 | "opacity": 100,
1536 | "angle": 0,
1537 | "x": 2349.034432660689,
1538 | "y": -179.3862824064608,
1539 | "strokeColor": "#1e1e1e",
1540 | "backgroundColor": "transparent",
1541 | "width": 137.87193298339844,
1542 | "height": 35,
1543 | "seed": 205138669,
1544 | "groupIds": [],
1545 | "frameId": null,
1546 | "roundness": null,
1547 | "boundElements": [],
1548 | "updated": 1705953142574,
1549 | "link": null,
1550 | "locked": false,
1551 | "fontSize": 28,
1552 | "fontFamily": 1,
1553 | "text": "Component",
1554 | "textAlign": "center",
1555 | "verticalAlign": "middle",
1556 | "containerId": "HT80xschFgla7fqyUWoKp",
1557 | "originalText": "Component",
1558 | "lineHeight": 1.25,
1559 | "baseline": 29
1560 | },
1561 | {
1562 | "type": "rectangle",
1563 | "version": 531,
1564 | "versionNonce": 1514356045,
1565 | "isDeleted": false,
1566 | "id": "ubSZ2N6MP6huCApVsnVnc",
1567 | "fillStyle": "solid",
1568 | "strokeWidth": 2,
1569 | "strokeStyle": "solid",
1570 | "roughness": 1,
1571 | "opacity": 100,
1572 | "angle": 0,
1573 | "x": 2264.329104580837,
1574 | "y": -284.52336656697935,
1575 | "strokeColor": "#1e1e1e",
1576 | "backgroundColor": "transparent",
1577 | "width": 322.1874658505312,
1578 | "height": 64.09968296937183,
1579 | "seed": 1448699171,
1580 | "groupIds": [],
1581 | "frameId": null,
1582 | "roundness": {
1583 | "type": 3
1584 | },
1585 | "boundElements": [
1586 | {
1587 | "type": "text",
1588 | "id": "McsmWH5f54okTS_fbboEk"
1589 | },
1590 | {
1591 | "id": "HT80xschFgla7fqyUWoKp",
1592 | "type": "arrow"
1593 | },
1594 | {
1595 | "id": "7GArb-2_pFFxm1BxlQtYc",
1596 | "type": "arrow"
1597 | },
1598 | {
1599 | "id": "t2I8QqNMfMAmyW1LgOgyu",
1600 | "type": "arrow"
1601 | }
1602 | ],
1603 | "updated": 1705953142574,
1604 | "link": null,
1605 | "locked": false
1606 | },
1607 | {
1608 | "type": "text",
1609 | "version": 459,
1610 | "versionNonce": 1284753923,
1611 | "isDeleted": false,
1612 | "id": "McsmWH5f54okTS_fbboEk",
1613 | "fillStyle": "solid",
1614 | "strokeWidth": 2,
1615 | "strokeStyle": "solid",
1616 | "roughness": 1,
1617 | "opacity": 100,
1618 | "angle": 0,
1619 | "x": 2336.046868572997,
1620 | "y": -269.97352508229346,
1621 | "strokeColor": "#1e1e1e",
1622 | "backgroundColor": "transparent",
1623 | "width": 178.75193786621094,
1624 | "height": 35,
1625 | "seed": 1826015427,
1626 | "groupIds": [],
1627 | "frameId": null,
1628 | "roundness": null,
1629 | "boundElements": [],
1630 | "updated": 1705953142574,
1631 | "link": null,
1632 | "locked": false,
1633 | "fontSize": 28,
1634 | "fontFamily": 1,
1635 | "text": "Generate ID",
1636 | "textAlign": "center",
1637 | "verticalAlign": "middle",
1638 | "containerId": "ubSZ2N6MP6huCApVsnVnc",
1639 | "originalText": "Generate ID",
1640 | "lineHeight": 1.25,
1641 | "baseline": 29
1642 | },
1643 | {
1644 | "type": "arrow",
1645 | "version": 1152,
1646 | "versionNonce": 1323830189,
1647 | "isDeleted": false,
1648 | "id": "t2I8QqNMfMAmyW1LgOgyu",
1649 | "fillStyle": "solid",
1650 | "strokeWidth": 2,
1651 | "strokeStyle": "solid",
1652 | "roughness": 1,
1653 | "opacity": 100,
1654 | "angle": 0,
1655 | "x": 2417.03003464953,
1656 | "y": -292.4293564372527,
1657 | "strokeColor": "#1e1e1e",
1658 | "backgroundColor": "transparent",
1659 | "width": 2.733661577116891,
1660 | "height": 87.2857373488593,
1661 | "seed": 1020460237,
1662 | "groupIds": [],
1663 | "frameId": null,
1664 | "roundness": {
1665 | "type": 2
1666 | },
1667 | "boundElements": [
1668 | {
1669 | "type": "text",
1670 | "id": "C0mD4SEyKGW9a_PhId7pC"
1671 | }
1672 | ],
1673 | "updated": 1705953142574,
1674 | "link": null,
1675 | "locked": false,
1676 | "startBinding": {
1677 | "elementId": "ubSZ2N6MP6huCApVsnVnc",
1678 | "focus": -0.04405651897308518,
1679 | "gap": 7.905989870273288
1680 | },
1681 | "endBinding": {
1682 | "elementId": "9HZnp_BH1RhRnqMf1bFom",
1683 | "focus": 0.005654236551808222,
1684 | "gap": 14.559084019986926
1685 | },
1686 | "lastCommittedPoint": null,
1687 | "startArrowhead": null,
1688 | "endArrowhead": "arrow",
1689 | "points": [
1690 | [
1691 | 0,
1692 | 0
1693 | ],
1694 | [
1695 | -2.733661577116891,
1696 | -87.2857373488593
1697 | ]
1698 | ]
1699 | },
1700 | {
1701 | "type": "text",
1702 | "version": 101,
1703 | "versionNonce": 2083623331,
1704 | "isDeleted": false,
1705 | "id": "C0mD4SEyKGW9a_PhId7pC",
1706 | "fillStyle": "solid",
1707 | "strokeWidth": 2,
1708 | "strokeStyle": "solid",
1709 | "roughness": 1,
1710 | "opacity": 100,
1711 | "angle": 0,
1712 | "x": 2373.9487101175973,
1713 | "y": -268.28870649285864,
1714 | "strokeColor": "#1e1e1e",
1715 | "backgroundColor": "transparent",
1716 | "width": 37.09999084472656,
1717 | "height": 35,
1718 | "seed": 1481890605,
1719 | "groupIds": [],
1720 | "frameId": null,
1721 | "roundness": null,
1722 | "boundElements": [],
1723 | "updated": 1705953142574,
1724 | "link": null,
1725 | "locked": false,
1726 | "fontSize": 28,
1727 | "fontFamily": 1,
1728 | "text": "ID",
1729 | "textAlign": "center",
1730 | "verticalAlign": "middle",
1731 | "containerId": "t2I8QqNMfMAmyW1LgOgyu",
1732 | "originalText": "ID",
1733 | "lineHeight": 1.25,
1734 | "baseline": 29
1735 | },
1736 | {
1737 | "type": "rectangle",
1738 | "version": 111,
1739 | "versionNonce": 1185156621,
1740 | "isDeleted": false,
1741 | "id": "_3NVXjblp0lZZ6oWA-Wc5",
1742 | "fillStyle": "hachure",
1743 | "strokeWidth": 1,
1744 | "strokeStyle": "solid",
1745 | "roughness": 1,
1746 | "opacity": 100,
1747 | "angle": 0,
1748 | "x": 1204.1080336544192,
1749 | "y": -657.7546644776069,
1750 | "strokeColor": "#1e1e1e",
1751 | "backgroundColor": "transparent",
1752 | "width": 2027.309179626322,
1753 | "height": 1005.2494937118909,
1754 | "seed": 1481578627,
1755 | "groupIds": [
1756 | "PjZHqap7DynD__V9uq9g0"
1757 | ],
1758 | "frameId": null,
1759 | "roundness": null,
1760 | "boundElements": [],
1761 | "updated": 1705953142574,
1762 | "link": null,
1763 | "locked": false
1764 | },
1765 | {
1766 | "type": "text",
1767 | "version": 274,
1768 | "versionNonce": 252551152,
1769 | "isDeleted": false,
1770 | "id": "9QJa7GB0hp_M6hV6Q1vok",
1771 | "fillStyle": "hachure",
1772 | "strokeWidth": 1,
1773 | "strokeStyle": "solid",
1774 | "roughness": 1,
1775 | "opacity": 100,
1776 | "angle": 0,
1777 | "x": 1774.3341719112059,
1778 | "y": -746.5845642928854,
1779 | "strokeColor": "#1e1e1e",
1780 | "backgroundColor": "transparent",
1781 | "width": 928.8231201171875,
1782 | "height": 54.348367952806726,
1783 | "seed": 744728451,
1784 | "groupIds": [
1785 | "PjZHqap7DynD__V9uq9g0"
1786 | ],
1787 | "frameId": null,
1788 | "roundness": null,
1789 | "boundElements": [],
1790 | "updated": 1706203062497,
1791 | "link": null,
1792 | "locked": false,
1793 | "fontSize": 43.47869436224538,
1794 | "fontFamily": 1,
1795 | "text": "Django Template React Component Rendrer",
1796 | "textAlign": "left",
1797 | "verticalAlign": "top",
1798 | "containerId": null,
1799 | "originalText": "Django Template React Component Rendrer",
1800 | "lineHeight": 1.25,
1801 | "baseline": 38
1802 | },
1803 | {
1804 | "type": "rectangle",
1805 | "version": 276,
1806 | "versionNonce": 1081132141,
1807 | "isDeleted": false,
1808 | "id": "Gf7lJOJJVdDqQqG8M_Y0Z",
1809 | "fillStyle": "hachure",
1810 | "strokeWidth": 1,
1811 | "strokeStyle": "solid",
1812 | "roughness": 1,
1813 | "opacity": 100,
1814 | "angle": 0,
1815 | "x": 1203.6524540246241,
1816 | "y": -773.9353664329899,
1817 | "strokeColor": "#1e1e1e",
1818 | "backgroundColor": "transparent",
1819 | "width": 2027.309179626322,
1820 | "height": 1122.0724207949334,
1821 | "seed": 1489614275,
1822 | "groupIds": [
1823 | "PjZHqap7DynD__V9uq9g0"
1824 | ],
1825 | "frameId": null,
1826 | "roundness": null,
1827 | "boundElements": [],
1828 | "updated": 1705953142574,
1829 | "link": null,
1830 | "locked": false
1831 | },
1832 | {
1833 | "type": "rectangle",
1834 | "version": 324,
1835 | "versionNonce": 2098953891,
1836 | "isDeleted": false,
1837 | "id": "xql8itph-bpVfG69zpkqX",
1838 | "fillStyle": "hachure",
1839 | "strokeWidth": 1,
1840 | "strokeStyle": "solid",
1841 | "roughness": 1,
1842 | "opacity": 100,
1843 | "angle": 0,
1844 | "x": 1204.6524540246241,
1845 | "y": -874.3457398838482,
1846 | "strokeColor": "#1e1e1e",
1847 | "backgroundColor": "transparent",
1848 | "width": 2027.309179626322,
1849 | "height": 1222.4827942457916,
1850 | "seed": 322433059,
1851 | "groupIds": [
1852 | "PjZHqap7DynD__V9uq9g0"
1853 | ],
1854 | "frameId": null,
1855 | "roundness": null,
1856 | "boundElements": [],
1857 | "updated": 1705953148873,
1858 | "link": null,
1859 | "locked": false
1860 | },
1861 | {
1862 | "type": "text",
1863 | "version": 403,
1864 | "versionNonce": 1779472144,
1865 | "isDeleted": false,
1866 | "id": "YjuZ6AYLjzyEXcL4wDJpu",
1867 | "fillStyle": "hachure",
1868 | "strokeWidth": 1,
1869 | "strokeStyle": "solid",
1870 | "roughness": 1,
1871 | "opacity": 100,
1872 | "angle": 0,
1873 | "x": 1974.4020545566848,
1874 | "y": -851.5520467837131,
1875 | "strokeColor": "#1e1e1e",
1876 | "backgroundColor": "transparent",
1877 | "width": 416.26861572265625,
1878 | "height": 54.348367952806726,
1879 | "seed": 1243763651,
1880 | "groupIds": [
1881 | "SzSYyelrDJDtMBFtnGSLO"
1882 | ],
1883 | "frameId": null,
1884 | "roundness": null,
1885 | "boundElements": [],
1886 | "updated": 1706203062498,
1887 | "link": null,
1888 | "locked": false,
1889 | "fontSize": 43.47869436224538,
1890 | "fontFamily": 1,
1891 | "text": "Data Flow Diagram",
1892 | "textAlign": "left",
1893 | "verticalAlign": "top",
1894 | "containerId": null,
1895 | "originalText": "Data Flow Diagram",
1896 | "lineHeight": 1.25,
1897 | "baseline": 38
1898 | }
1899 | ],
1900 | "appState": {
1901 | "gridSize": null,
1902 | "viewBackgroundColor": "#ffffff"
1903 | },
1904 | "files": {}
1905 | }
--------------------------------------------------------------------------------