Skip to content

parse package as url path in module_from_template #456

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion docs/source/javascript-components.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,16 @@ Javascript ecosystem. This can be accomplished in different ways for different r
- You want to create polished software that can be **easily shared** with others.


.. _Dynamically Loaded Component:

Dynamically Loaded Components
-----------------------------

.. note::

This method is not recommended in production systems - see
:ref:`Distributing Javascript Components` for more info.
:ref:`Distributing Javascript Components` for more info. Instead, it's best used
during exploratory phases of development.

IDOM makes it easy to draft your code when you're in the early stages of development by
using a CDN_ to dynamically load Javascript packages on the fly. In this example we'll
Expand All @@ -44,6 +47,8 @@ an ``onClick`` handler to the component:
.. example:: material_ui_button_on_click


.. _Custom Javascript Component:

Custom Javascript Components
----------------------------

Expand Down
28 changes: 23 additions & 5 deletions src/idom/web/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from functools import partial
from pathlib import Path
from typing import Any, List, NewType, Optional, Set, Tuple, Union, overload
from urllib.parse import urlparse

from idom.config import IDOM_DEBUG_MODE, IDOM_WED_MODULES_DIR
from idom.core.vdom import ImportSourceDict, VdomDictConstructor, make_vdom_constructor
Expand Down Expand Up @@ -70,11 +71,22 @@ def module_from_template(
resolve_exports: bool = IDOM_DEBUG_MODE.current,
resolve_exports_depth: int = 5,
) -> WebModule:
"""Load a :class:`WebModule` from a :data:`URL_SOURCE` using a known framework
"""Create a :class:`WebModule` from a framework template

This is useful for experimenting with component libraries that do not already
support IDOM's :ref:`Custom Javascript Component` interface.

.. warning::

This approach is not recommended for use in a production setting because the
framework templates may use unpinned dependencies that could change without
warning.cIt's best to author a module adhering to the
:ref:`Custom Javascript Component` interface instead.

Parameters:
template:
The name of the template to use with the given ``package`` (``react`` | ``preact``)
The name of the framework template to use with the given ``package``
(``react`` | ``preact``).
package:
The name of a package to load. May include a file extension (defaults to
``.js`` if not given)
Expand All @@ -87,22 +99,28 @@ def module_from_template(
resolve_exports_depth:
How deeply to search for those exports.
"""
# We do this since the package may be any valid URL path. Thus we may need to strip
# object parameters or query information so we save the resulting template under the
# correct file name.
package_name = urlparse(package).path

# downstream code assumes no trailing slash
cdn = cdn.rstrip("/")

template_file_name = f"{template}{module_name_suffix(package)}"
template_file_name = f"{template}{module_name_suffix(package_name)}"
template_file = Path(__file__).parent / "templates" / template_file_name
if not template_file.exists():
raise ValueError(f"No template for {template_file_name!r} exists")

target_file = _web_module_path(package)
target_file = _web_module_path(package_name)
if not target_file.exists():
target_file.parent.mkdir(parents=True, exist_ok=True)
target_file.write_text(
template_file.read_text().replace("$PACKAGE", package).replace("$CDN", cdn)
)

return WebModule(
source=package + module_name_suffix(package),
source=package_name + module_name_suffix(package_name),
source_type=NAME_SOURCE,
default_fallback=fallback,
file=target_file,
Expand Down