diff --git a/scripts/generate.py b/scripts/generate.py index 2c4cae8..d7ded60 100644 --- a/scripts/generate.py +++ b/scripts/generate.py @@ -107,6 +107,7 @@ def regen_all(src_top, dest_top, *, docs=None, db=None): # This includes a virtual headline for ID-referenced documents. all_headlines = [] main_headlines_by_path = {} + main_headline_to_docid = {} for doc in docs: relpath = os.path.relpath(doc.path, src_top) changed = False @@ -151,6 +152,7 @@ def regen_all(src_top, dest_top, *, docs=None, db=None): main_headlines_by_path[doc.path] = main_headline if doc.id is not None: doc_to_headline_remapping['id:' + doc.id] = 'id:' + main_headline.id + main_headline_to_docid[main_headline.id] = doc.id files_generated += 1 elif doc.id is not None: logging.error("Cannot render document from id: {}. {} headlines {} related".format( @@ -159,8 +161,8 @@ def regen_all(src_top, dest_top, *, docs=None, db=None): 'with' if related is not None else 'without' )) - graph = {} # Build graph + graph = {} for headline in all_headlines: links = [] headline_links = list(headline.get_links()) @@ -200,6 +202,8 @@ def regen_all(src_top, dest_top, *, docs=None, db=None): "links": links, "depth": headline.depth, } + if headline.id in main_headline_to_docid: + graph[main_headline_to_docid[headline.id]] = graph[headline.id] topLevelHeadline = headline while isinstance(topLevelHeadline.parent, org_rw.Headline): @@ -306,6 +310,13 @@ def get_headline_with_name(target_name, doc): return None +def assert_id_exists(id, src_headline, graph): + if id not in graph["nodes"]: + raise AssertionError("Cannot follow link to '{}' on headline '{}' ({})" + .format(id, + src_headline.id, + src_headline.title.get_text())) + def print_tree(tree, indentation=0, headline=None): # if headline and headline.id != INDEX_ID: # return @@ -437,6 +448,7 @@ def render_text_tokens(tokens, acc, headline, graph): link_target = chunk.value is_internal_link = True if link_target.startswith('id:'): + assert_id_exists(link_target[3:], headline, graph) link_target = './' + link_target[3:] + '.node.html' elif link_target.startswith('./') or link_target.startswith('../'): if '::' in link_target: @@ -447,6 +459,7 @@ def render_text_tokens(tokens, acc, headline, graph): if target_path not in graph['main_headlines']: logging.warn('Link to doc not in graph: {}'.format(target_path)) else: + assert_id_exists(graph['main_headlines'][target_path].id, headline, graph) link_target = './' + graph['main_headlines'][target_path].id + '.node.html' elif link_target.startswith('attachment:'): logging.warn('Not implemented `attachment:` links. Used on {}'.format(link_target)) @@ -455,6 +468,7 @@ def render_text_tokens(tokens, acc, headline, graph): if target_headline is None: logging.warn('No headline found corresponding to {}. On file {}'.format(link_target, headline.doc.path)) else: + assert_id_exists(target_headline.id, headline, graph) link_target = './' + target_headline.id + '.node.html' else: is_internal_link = False