added relative addressing option

This commit is contained in:
Amy G. Bowersox 2024-08-09 15:39:14 -06:00
parent 8e5c40a642
commit d278260b90
3 changed files with 38 additions and 15 deletions

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import argparse import argparse
import logging
import shutil import shutil
from pathlib import Path from pathlib import Path
@ -9,31 +10,41 @@ from .mparse import create_markdown_parser
from .template import create_template_environment from .template import create_template_environment
from .tree import SourceIndex, generate_list from .tree import SourceIndex, generate_list
logger = logging.getLogger(__name__)
# The command line parser # The command line parser
parser = argparse.ArgumentParser(prog='dragonglass') parser = argparse.ArgumentParser(prog='dragonglass')
parser.add_argument('source_dir', help='Source directory (Obsidian vault) for the conversion.') parser.add_argument('source_dir', help='Source directory (Obsidian vault) for the conversion.')
parser.add_argument('dest_dir', help='Destination directory for the conversion.') parser.add_argument('dest_dir', help='Destination directory for the conversion.')
parser.add_argument('-C', '--config', help='Specifies an alternate name for the configuration file.') parser.add_argument('-C', '--config', help='Specifies an alternate name for the configuration file.')
parser.add_argument('-D', '--debug', action='store_true', help='Enables debug logging')
parser.add_argument('--dump', action='store_true', help='Dumps the parsed data before writing the destination')
def main() -> int: def main() -> int:
args = parser.parse_args() args = parser.parse_args()
context = Context()
if args.debug:
logging.basicConfig(level=logging.DEBUG)
else:
logging.basicConfig(level=logging.INFO)
context = Context()
context.source_dir = Path(args.source_dir).resolve() context.source_dir = Path(args.source_dir).resolve()
if not (context.source_dir.exists() and context.source_dir.is_dir()): if not (context.source_dir.exists() and context.source_dir.is_dir()):
print(f"{context.source_dir} is not a valid directory") logger.error(f"{context.source_dir} is not a valid directory")
return 1 return 1
dest_dir = Path(args.dest_dir).resolve() dest_dir = Path(args.dest_dir).resolve()
if dest_dir.exists() and not dest_dir.is_dir(): if dest_dir.exists() and not dest_dir.is_dir():
print(f"{dest_dir} exists but is not a valid directory") logger.error(f"{dest_dir} exists but is not a valid directory")
return 1 return 1
context.load_config(args) context.load_config(args)
nodes = generate_list(context.source_dir) nodes = generate_list(context.source_dir)
for node in nodes: for node in nodes:
logger.info(f"Loading metadata for {node}")
context.current_node = node context.current_node = node
node.load_metadata(context.source_dir) node.load_metadata(context.source_dir)
@ -42,9 +53,11 @@ def main() -> int:
mdparse = create_markdown_parser(context) mdparse = create_markdown_parser(context)
for node in nodes: for node in nodes:
context.current_node = node context.current_node = node
logger.info(f"Parsing {node}")
node.parse_markdown(context.source_dir, mdparse) node.parse_markdown(context.source_dir, mdparse)
# TEMP # TEMP
if args.dump:
for node in nodes: for node in nodes:
print(node) print(node)
if node.metadata: if node.metadata:

View File

@ -165,7 +165,9 @@ class ObsidianImages(Extension):
assert self._context.src_index is not None assert self._context.src_index is not None
node, _ = self._context.src_index.lookup(name) node, _ = self._context.src_index.lookup(name)
if node: if node:
return node.link_target(self._context.url_prefix) return node.link_target(self._context.url_prefix,
self._context.current_node if self._context.relative_links else None,
root_path=self._context.source_dir)
return None return None
class ObsidianImageProc(InlineProcessor): class ObsidianImageProc(InlineProcessor):
@ -261,7 +263,9 @@ class ObsidianLinks(Extension):
if not text: if not text:
text = contents text = contents
if node: if node:
return node.link_target(self._context.url_prefix), text return node.link_target(self._context.url_prefix,
self._context.current_node if self._context.relative_links else None,
root_path=self._context.source_dir), text
return None, text return None, text
class ObsidianLinksProc(InlineProcessor): class ObsidianLinksProc(InlineProcessor):

View File

@ -4,9 +4,12 @@ from pathlib import Path
from typing import Any from typing import Any
from urllib.parse import quote as urlquote from urllib.parse import quote as urlquote
import logging
import markdown import markdown
import yaml import yaml
logger = logging.getLogger(__name__)
# The paths that are always to be ignored. # The paths that are always to be ignored.
STATIC_IGNORE = [ STATIC_IGNORE = [
'.obsidian', '.obsidian',
@ -46,10 +49,13 @@ class SourceNode:
p = p.with_suffix('.html') p = p.with_suffix('.html')
return dest_dir / p return dest_dir / p
def link_target(self, prefix: str = "/", rel_to: Any = None) -> str: def link_target(self, prefix: str = "/", rel_to: Any = None, root_path: Path = None) -> str:
xpath = self._path.with_suffix('.html') if self._is_md else self._path xpath = self._path.with_suffix('.html') if self._is_md else self._path
if rel_to is not None: if rel_to is not None:
return urlquote(xpath.relative_to(rel_to._path, walk_up=True).as_posix()) xpath = root_path / xpath
rel_path = root_path / rel_to.path
logger.debug(f"*** Computing path of {xpath} relative to {rel_path}")
return urlquote(xpath.relative_to(rel_path.parent, walk_up=True).as_posix())
return urlquote(prefix + xpath.as_posix()) return urlquote(prefix + xpath.as_posix())
def load_metadata(self, source_dir: Path) -> None: def load_metadata(self, source_dir: Path) -> None: