|
|
|
|
@@ -2578,7 +2578,7 @@ def compute_all_deps(env):
|
|
|
|
|
|
|
|
|
|
# scan-components-from-source
|
|
|
|
|
def scan_components_from_source(source):
|
|
|
|
|
matches = regex_find_all('\\(~([a-zA-Z_][a-zA-Z0-9_\\-]*)', source)
|
|
|
|
|
matches = regex_find_all('\\(~([a-zA-Z_][a-zA-Z0-9_\\-:/]*)', source)
|
|
|
|
|
return map(lambda m: sx_str('~', m), matches)
|
|
|
|
|
|
|
|
|
|
# components-needed
|
|
|
|
|
@@ -2881,330 +2881,6 @@ def build_affinity_analysis(demo_components, page_plans):
|
|
|
|
|
return {'components': demo_components, 'page-plans': page_plans}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# === Transpiled from router (client-side route matching) ===
|
|
|
|
|
|
|
|
|
|
# split-path-segments
|
|
|
|
|
def split_path_segments(path):
|
|
|
|
|
trimmed = (slice(path, 1) if sx_truthy(starts_with_p(path, '/')) else path)
|
|
|
|
|
trimmed2 = (slice(trimmed, 0, (len(trimmed) - 1)) if sx_truthy(((not sx_truthy(empty_p(trimmed))) if not sx_truthy((not sx_truthy(empty_p(trimmed)))) else ends_with_p(trimmed, '/'))) else trimmed)
|
|
|
|
|
if sx_truthy(empty_p(trimmed2)):
|
|
|
|
|
return []
|
|
|
|
|
else:
|
|
|
|
|
return split(trimmed2, '/')
|
|
|
|
|
|
|
|
|
|
# make-route-segment
|
|
|
|
|
def make_route_segment(seg):
|
|
|
|
|
if sx_truthy((starts_with_p(seg, '<') if not sx_truthy(starts_with_p(seg, '<')) else ends_with_p(seg, '>'))):
|
|
|
|
|
param_name = slice(seg, 1, (len(seg) - 1))
|
|
|
|
|
d = {}
|
|
|
|
|
d['type'] = 'param'
|
|
|
|
|
d['value'] = param_name
|
|
|
|
|
return d
|
|
|
|
|
else:
|
|
|
|
|
d = {}
|
|
|
|
|
d['type'] = 'literal'
|
|
|
|
|
d['value'] = seg
|
|
|
|
|
return d
|
|
|
|
|
|
|
|
|
|
# parse-route-pattern
|
|
|
|
|
def parse_route_pattern(pattern):
|
|
|
|
|
segments = split_path_segments(pattern)
|
|
|
|
|
return map(make_route_segment, segments)
|
|
|
|
|
|
|
|
|
|
# match-route-segments
|
|
|
|
|
def match_route_segments(path_segs, parsed_segs):
|
|
|
|
|
_cells = {}
|
|
|
|
|
if sx_truthy((not sx_truthy((len(path_segs) == len(parsed_segs))))):
|
|
|
|
|
return NIL
|
|
|
|
|
else:
|
|
|
|
|
params = {}
|
|
|
|
|
_cells['matched'] = True
|
|
|
|
|
for_each_indexed(lambda i, parsed_seg: ((lambda path_seg: (lambda seg_type: ((_sx_cell_set(_cells, 'matched', False) if sx_truthy((not sx_truthy((path_seg == get(parsed_seg, 'value'))))) else NIL) if sx_truthy((seg_type == 'literal')) else (_sx_dict_set(params, get(parsed_seg, 'value'), path_seg) if sx_truthy((seg_type == 'param')) else _sx_cell_set(_cells, 'matched', False))))(get(parsed_seg, 'type')))(nth(path_segs, i)) if sx_truthy(_cells['matched']) else NIL), parsed_segs)
|
|
|
|
|
if sx_truthy(_cells['matched']):
|
|
|
|
|
return params
|
|
|
|
|
else:
|
|
|
|
|
return NIL
|
|
|
|
|
|
|
|
|
|
# match-route
|
|
|
|
|
def match_route(path, pattern):
|
|
|
|
|
path_segs = split_path_segments(path)
|
|
|
|
|
parsed_segs = parse_route_pattern(pattern)
|
|
|
|
|
return match_route_segments(path_segs, parsed_segs)
|
|
|
|
|
|
|
|
|
|
# find-matching-route
|
|
|
|
|
def find_matching_route(path, routes):
|
|
|
|
|
_cells = {}
|
|
|
|
|
match_path = ((sx_url_to_path(path) if sx_truthy(sx_url_to_path(path)) else path) if sx_truthy(starts_with_p(path, '/(')) else path)
|
|
|
|
|
path_segs = split_path_segments(match_path)
|
|
|
|
|
_cells['result'] = NIL
|
|
|
|
|
for route in routes:
|
|
|
|
|
if sx_truthy(is_nil(_cells['result'])):
|
|
|
|
|
params = match_route_segments(path_segs, get(route, 'parsed'))
|
|
|
|
|
if sx_truthy((not sx_truthy(is_nil(params)))):
|
|
|
|
|
matched = merge(route, {})
|
|
|
|
|
matched['params'] = params
|
|
|
|
|
_cells['result'] = matched
|
|
|
|
|
return _cells['result']
|
|
|
|
|
|
|
|
|
|
# _fn-to-segment
|
|
|
|
|
def _fn_to_segment(name):
|
|
|
|
|
_match = name
|
|
|
|
|
if _match == 'doc':
|
|
|
|
|
return 'docs'
|
|
|
|
|
elif _match == 'spec':
|
|
|
|
|
return 'specs'
|
|
|
|
|
elif _match == 'bootstrapper':
|
|
|
|
|
return 'bootstrappers'
|
|
|
|
|
elif _match == 'test':
|
|
|
|
|
return 'testing'
|
|
|
|
|
elif _match == 'example':
|
|
|
|
|
return 'examples'
|
|
|
|
|
elif _match == 'protocol':
|
|
|
|
|
return 'protocols'
|
|
|
|
|
elif _match == 'essay':
|
|
|
|
|
return 'essays'
|
|
|
|
|
elif _match == 'plan':
|
|
|
|
|
return 'plans'
|
|
|
|
|
elif _match == 'reference-detail':
|
|
|
|
|
return 'reference'
|
|
|
|
|
else:
|
|
|
|
|
return name
|
|
|
|
|
|
|
|
|
|
# sx-url-to-path
|
|
|
|
|
def sx_url_to_path(url):
|
|
|
|
|
if sx_truthy((not sx_truthy((starts_with_p(url, '/(') if not sx_truthy(starts_with_p(url, '/(')) else ends_with_p(url, ')'))))):
|
|
|
|
|
return NIL
|
|
|
|
|
else:
|
|
|
|
|
inner = slice(url, 2, (len(url) - 1))
|
|
|
|
|
s = replace(replace(replace(inner, '.', '/'), '(', ''), ')', '')
|
|
|
|
|
segs = filter(lambda s: (not sx_truthy(empty_p(s))), split(s, '/'))
|
|
|
|
|
return sx_str('/', join('/', map(_fn_to_segment, segs)))
|
|
|
|
|
|
|
|
|
|
# _count-leading-dots
|
|
|
|
|
def _count_leading_dots(s):
|
|
|
|
|
if sx_truthy(empty_p(s)):
|
|
|
|
|
return 0
|
|
|
|
|
else:
|
|
|
|
|
if sx_truthy(starts_with_p(s, '.')):
|
|
|
|
|
return (1 + _count_leading_dots(slice(s, 1)))
|
|
|
|
|
else:
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
# _strip-trailing-close
|
|
|
|
|
def _strip_trailing_close(s):
|
|
|
|
|
if sx_truthy(ends_with_p(s, ')')):
|
|
|
|
|
return _strip_trailing_close(slice(s, 0, (len(s) - 1)))
|
|
|
|
|
else:
|
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
|
# _index-of-safe
|
|
|
|
|
def _index_of_safe(s, needle):
|
|
|
|
|
idx = index_of(s, needle)
|
|
|
|
|
if sx_truthy((is_nil(idx) if sx_truthy(is_nil(idx)) else (idx < 0))):
|
|
|
|
|
return NIL
|
|
|
|
|
else:
|
|
|
|
|
return idx
|
|
|
|
|
|
|
|
|
|
# _last-index-of
|
|
|
|
|
def _last_index_of(s, needle):
|
|
|
|
|
idx = _index_of_safe(s, needle)
|
|
|
|
|
if sx_truthy(is_nil(idx)):
|
|
|
|
|
return NIL
|
|
|
|
|
else:
|
|
|
|
|
rest_idx = _last_index_of(slice(s, (idx + 1)), needle)
|
|
|
|
|
if sx_truthy(is_nil(rest_idx)):
|
|
|
|
|
return idx
|
|
|
|
|
else:
|
|
|
|
|
return ((idx + 1) + rest_idx)
|
|
|
|
|
|
|
|
|
|
# _pop-sx-url-level
|
|
|
|
|
def _pop_sx_url_level(url):
|
|
|
|
|
stripped = _strip_trailing_close(url)
|
|
|
|
|
close_count = (len(url) - len(_strip_trailing_close(url)))
|
|
|
|
|
if sx_truthy((close_count <= 1)):
|
|
|
|
|
return '/'
|
|
|
|
|
else:
|
|
|
|
|
last_dp = _last_index_of(stripped, '.(')
|
|
|
|
|
if sx_truthy(is_nil(last_dp)):
|
|
|
|
|
return '/'
|
|
|
|
|
else:
|
|
|
|
|
return sx_str(slice(stripped, 0, last_dp), slice(url, (len(url) - (close_count - 1))))
|
|
|
|
|
|
|
|
|
|
# _pop-sx-url-levels
|
|
|
|
|
def _pop_sx_url_levels(url, n):
|
|
|
|
|
if sx_truthy((n <= 0)):
|
|
|
|
|
return url
|
|
|
|
|
else:
|
|
|
|
|
return _pop_sx_url_levels(_pop_sx_url_level(url), (n - 1))
|
|
|
|
|
|
|
|
|
|
# _split-pos-kw
|
|
|
|
|
def _split_pos_kw(tokens, i, pos, kw):
|
|
|
|
|
if sx_truthy((i >= len(tokens))):
|
|
|
|
|
return {'positional': join('.', pos), 'keywords': kw}
|
|
|
|
|
else:
|
|
|
|
|
tok = nth(tokens, i)
|
|
|
|
|
if sx_truthy(starts_with_p(tok, ':')):
|
|
|
|
|
val = (nth(tokens, (i + 1)) if sx_truthy(((i + 1) < len(tokens))) else '')
|
|
|
|
|
return _split_pos_kw(tokens, (i + 2), pos, append(kw, [[tok, val]]))
|
|
|
|
|
else:
|
|
|
|
|
return _split_pos_kw(tokens, (i + 1), append(pos, [tok]), kw)
|
|
|
|
|
|
|
|
|
|
# _parse-relative-body
|
|
|
|
|
def _parse_relative_body(body):
|
|
|
|
|
if sx_truthy(empty_p(body)):
|
|
|
|
|
return {'positional': '', 'keywords': []}
|
|
|
|
|
else:
|
|
|
|
|
return _split_pos_kw(split(body, '.'), 0, [], [])
|
|
|
|
|
|
|
|
|
|
# _extract-innermost
|
|
|
|
|
def _extract_innermost(url):
|
|
|
|
|
stripped = _strip_trailing_close(url)
|
|
|
|
|
suffix = slice(url, len(_strip_trailing_close(url)))
|
|
|
|
|
last_dp = _last_index_of(stripped, '.(')
|
|
|
|
|
if sx_truthy(is_nil(last_dp)):
|
|
|
|
|
return {'before': '/(', 'content': slice(stripped, 2), 'suffix': suffix}
|
|
|
|
|
else:
|
|
|
|
|
return {'before': slice(stripped, 0, (last_dp + 2)), 'content': slice(stripped, (last_dp + 2)), 'suffix': suffix}
|
|
|
|
|
|
|
|
|
|
# _find-kw-in-tokens
|
|
|
|
|
def _find_kw_in_tokens(tokens, i, kw):
|
|
|
|
|
if sx_truthy((i >= len(tokens))):
|
|
|
|
|
return NIL
|
|
|
|
|
else:
|
|
|
|
|
if sx_truthy(((nth(tokens, i) == kw) if not sx_truthy((nth(tokens, i) == kw)) else ((i + 1) < len(tokens)))):
|
|
|
|
|
return nth(tokens, (i + 1))
|
|
|
|
|
else:
|
|
|
|
|
return _find_kw_in_tokens(tokens, (i + 1), kw)
|
|
|
|
|
|
|
|
|
|
# _find-keyword-value
|
|
|
|
|
def _find_keyword_value(content, kw):
|
|
|
|
|
return _find_kw_in_tokens(split(content, '.'), 0, kw)
|
|
|
|
|
|
|
|
|
|
# _replace-kw-in-tokens
|
|
|
|
|
def _replace_kw_in_tokens(tokens, i, kw, value):
|
|
|
|
|
if sx_truthy((i >= len(tokens))):
|
|
|
|
|
return []
|
|
|
|
|
else:
|
|
|
|
|
if sx_truthy(((nth(tokens, i) == kw) if not sx_truthy((nth(tokens, i) == kw)) else ((i + 1) < len(tokens)))):
|
|
|
|
|
return append([kw, value], _replace_kw_in_tokens(tokens, (i + 2), kw, value))
|
|
|
|
|
else:
|
|
|
|
|
return cons(nth(tokens, i), _replace_kw_in_tokens(tokens, (i + 1), kw, value))
|
|
|
|
|
|
|
|
|
|
# _set-keyword-in-content
|
|
|
|
|
def _set_keyword_in_content(content, kw, value):
|
|
|
|
|
current = _find_keyword_value(content, kw)
|
|
|
|
|
if sx_truthy(is_nil(current)):
|
|
|
|
|
return sx_str(content, '.', kw, '.', value)
|
|
|
|
|
else:
|
|
|
|
|
return join('.', _replace_kw_in_tokens(split(content, '.'), 0, kw, value))
|
|
|
|
|
|
|
|
|
|
# _is-delta-value?
|
|
|
|
|
def _is_delta_value_p(s):
|
|
|
|
|
return ((not sx_truthy(empty_p(s))) if not sx_truthy((not sx_truthy(empty_p(s)))) else ((len(s) > 1) if not sx_truthy((len(s) > 1)) else (starts_with_p(s, '+') if sx_truthy(starts_with_p(s, '+')) else starts_with_p(s, '-'))))
|
|
|
|
|
|
|
|
|
|
# _apply-delta
|
|
|
|
|
def _apply_delta(current_str, delta_str):
|
|
|
|
|
cur = parse_int(current_str, NIL)
|
|
|
|
|
delta = parse_int(delta_str, NIL)
|
|
|
|
|
if sx_truthy((is_nil(cur) if sx_truthy(is_nil(cur)) else is_nil(delta))):
|
|
|
|
|
return delta_str
|
|
|
|
|
else:
|
|
|
|
|
return sx_str((cur + delta))
|
|
|
|
|
|
|
|
|
|
# _apply-kw-pairs
|
|
|
|
|
def _apply_kw_pairs(content, kw_pairs):
|
|
|
|
|
if sx_truthy(empty_p(kw_pairs)):
|
|
|
|
|
return content
|
|
|
|
|
else:
|
|
|
|
|
pair = first(kw_pairs)
|
|
|
|
|
kw = first(pair)
|
|
|
|
|
raw_val = nth(pair, 1)
|
|
|
|
|
actual_val = ((lambda current: (raw_val if sx_truthy(is_nil(current)) else _apply_delta(current, raw_val)))(_find_keyword_value(content, kw)) if sx_truthy(_is_delta_value_p(raw_val)) else raw_val)
|
|
|
|
|
return _apply_kw_pairs(_set_keyword_in_content(content, kw, actual_val), rest(kw_pairs))
|
|
|
|
|
|
|
|
|
|
# _apply-keywords-to-url
|
|
|
|
|
def _apply_keywords_to_url(url, kw_pairs):
|
|
|
|
|
if sx_truthy(empty_p(kw_pairs)):
|
|
|
|
|
return url
|
|
|
|
|
else:
|
|
|
|
|
parts = _extract_innermost(url)
|
|
|
|
|
new_content = _apply_kw_pairs(get(parts, 'content'), kw_pairs)
|
|
|
|
|
return sx_str(get(parts, 'before'), new_content, get(parts, 'suffix'))
|
|
|
|
|
|
|
|
|
|
# _normalize-relative
|
|
|
|
|
def _normalize_relative(url):
|
|
|
|
|
if sx_truthy(starts_with_p(url, '(')):
|
|
|
|
|
return url
|
|
|
|
|
else:
|
|
|
|
|
return sx_str('(', url, ')')
|
|
|
|
|
|
|
|
|
|
# resolve-relative-url
|
|
|
|
|
def resolve_relative_url(current, relative):
|
|
|
|
|
canonical = _normalize_relative(relative)
|
|
|
|
|
rel_inner = slice(canonical, 1, (len(canonical) - 1))
|
|
|
|
|
dots = _count_leading_dots(rel_inner)
|
|
|
|
|
body = slice(rel_inner, _count_leading_dots(rel_inner))
|
|
|
|
|
if sx_truthy((dots == 0)):
|
|
|
|
|
return current
|
|
|
|
|
else:
|
|
|
|
|
parsed = _parse_relative_body(body)
|
|
|
|
|
pos_body = get(parsed, 'positional')
|
|
|
|
|
kw_pairs = get(parsed, 'keywords')
|
|
|
|
|
after_nav = ((current if sx_truthy(empty_p(pos_body)) else (lambda stripped: (lambda suffix: sx_str(stripped, '.', pos_body, suffix))(slice(current, len(_strip_trailing_close(current)))))(_strip_trailing_close(current))) if sx_truthy((dots == 1)) else (lambda base: (base if sx_truthy(empty_p(pos_body)) else (sx_str('/(', pos_body, ')') if sx_truthy((base == '/')) else (lambda stripped: (lambda suffix: sx_str(stripped, '.(', pos_body, ')', suffix))(slice(base, len(_strip_trailing_close(base)))))(_strip_trailing_close(base)))))(_pop_sx_url_levels(current, (dots - 1))))
|
|
|
|
|
return _apply_keywords_to_url(after_nav, kw_pairs)
|
|
|
|
|
|
|
|
|
|
# relative-sx-url?
|
|
|
|
|
def relative_sx_url_p(url):
|
|
|
|
|
return ((starts_with_p(url, '(') if not sx_truthy(starts_with_p(url, '(')) else (not sx_truthy(starts_with_p(url, '/(')))) if sx_truthy((starts_with_p(url, '(') if not sx_truthy(starts_with_p(url, '(')) else (not sx_truthy(starts_with_p(url, '/('))))) else starts_with_p(url, '.'))
|
|
|
|
|
|
|
|
|
|
# _url-special-forms
|
|
|
|
|
def _url_special_forms():
|
|
|
|
|
return ['!source', '!inspect', '!diff', '!search', '!raw', '!json']
|
|
|
|
|
|
|
|
|
|
# url-special-form?
|
|
|
|
|
def url_special_form_p(name):
|
|
|
|
|
return (starts_with_p(name, '!') if not sx_truthy(starts_with_p(name, '!')) else contains_p(_url_special_forms(), name))
|
|
|
|
|
|
|
|
|
|
# parse-sx-url
|
|
|
|
|
def parse_sx_url(url):
|
|
|
|
|
if sx_truthy((url == '/')):
|
|
|
|
|
return {'type': 'home', 'raw': url}
|
|
|
|
|
elif sx_truthy(relative_sx_url_p(url)):
|
|
|
|
|
return {'type': 'relative', 'raw': url}
|
|
|
|
|
elif sx_truthy((starts_with_p(url, '/(!') if not sx_truthy(starts_with_p(url, '/(!')) else ends_with_p(url, ')'))):
|
|
|
|
|
inner = slice(url, 2, (len(url) - 1))
|
|
|
|
|
dot_pos = _index_of_safe(inner, '.')
|
|
|
|
|
paren_pos = _index_of_safe(inner, '(')
|
|
|
|
|
end_pos = (len(inner) if sx_truthy((is_nil(dot_pos) if not sx_truthy(is_nil(dot_pos)) else is_nil(paren_pos))) else (paren_pos if sx_truthy(is_nil(dot_pos)) else (dot_pos if sx_truthy(is_nil(paren_pos)) else min(dot_pos, paren_pos))))
|
|
|
|
|
form_name = slice(inner, 0, end_pos)
|
|
|
|
|
rest_part = slice(inner, end_pos)
|
|
|
|
|
inner_expr = (slice(rest_part, 1) if sx_truthy(starts_with_p(rest_part, '.')) else rest_part)
|
|
|
|
|
return {'type': 'special-form', 'form': form_name, 'inner': inner_expr, 'raw': url}
|
|
|
|
|
elif sx_truthy((starts_with_p(url, '/(~') if not sx_truthy(starts_with_p(url, '/(~')) else ends_with_p(url, ')'))):
|
|
|
|
|
name = slice(url, 2, (len(url) - 1))
|
|
|
|
|
return {'type': 'direct-component', 'name': name, 'raw': url}
|
|
|
|
|
elif sx_truthy((starts_with_p(url, '/(') if not sx_truthy(starts_with_p(url, '/(')) else ends_with_p(url, ')'))):
|
|
|
|
|
return {'type': 'absolute', 'raw': url}
|
|
|
|
|
else:
|
|
|
|
|
return {'type': 'path', 'raw': url}
|
|
|
|
|
|
|
|
|
|
# url-special-form-name
|
|
|
|
|
def url_special_form_name(url):
|
|
|
|
|
parsed = parse_sx_url(url)
|
|
|
|
|
if sx_truthy((get(parsed, 'type') == 'special-form')):
|
|
|
|
|
return get(parsed, 'form')
|
|
|
|
|
else:
|
|
|
|
|
return NIL
|
|
|
|
|
|
|
|
|
|
# url-special-form-inner
|
|
|
|
|
def url_special_form_inner(url):
|
|
|
|
|
parsed = parse_sx_url(url)
|
|
|
|
|
if sx_truthy((get(parsed, 'type') == 'special-form')):
|
|
|
|
|
return get(parsed, 'inner')
|
|
|
|
|
else:
|
|
|
|
|
return NIL
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# === Transpiled from signals (reactive signal runtime) ===
|
|
|
|
|
|
|
|
|
|
# signal
|
|
|
|
|
|