17 Commits

Author SHA1 Message Date
ca830713d3 Merge tag 'v0.3.0' from upstream 2022-11-13 21:29:50 +01:00
Soren I. Bjornstad
96f149feaa use API token to upload to PyPi
User/password auth is deprecated for Twine.
2022-08-19 17:32:38 -05:00
Soren I. Bjornstad
a1c946db9e update to latest ZK version, bump version number 2022-08-19 17:27:43 -05:00
Soren I. Bjornstad
04272c3973 also privatize JSON tiddlers
This seems slightly dangerous because we're just applying the same
replacement logic and JSON has a much fussier syntax. However, if any
tiddlers end up invalid we should just get a build failure, so this
doesn't seem highly consequential.
2022-08-19 17:14:06 -05:00
Soren I. Bjornstad
1f56f68448 stop using <<privateperson>> macro
Since we have to do raw links anyway in many cases, it doesn't really
make sense to use two different formats. This also gets around an edge
case where replacement produces invalid syntax if the person to be
replaced is linked within a macro, since the >> of privateperson then
terminates the outside macro -- given my increasing use of footnotes,
this isn't all that uncommon.
2022-08-19 17:09:20 -05:00
Soren I. Bjornstad
3e9ecd4b70 work around ReadTheDocs bug 2022-03-27 15:22:31 -05:00
Soren I. Bjornstad
7be018ea3f pull ZK updates and bump version 2022-03-27 15:19:41 -05:00
Soren I. Bjornstad
8fb496bbfe Merge branch 'new-private-person-replacement-logic' into march-tweaks 2022-03-27 15:14:41 -05:00
dcac80c5ac Replace link text of private person
It is possible that a private person is linked to in a tiddler with the
syntax `[[Jane|MsJaneDoe]]`.

Up to now, the text of the link was not redacted, which could lead to
unintentional privacy leaks.

Therefore, a new parameter `replace_link_text` is introduced for the
`replace_private_people` builder.

When that is set to True, then the link text is also replaced with the
initials.

Signed-off-by: Jacob Kiers <code@kiers.eu>
2022-03-22 23:34:32 +01:00
Soren I. Bjornstad
4875f7c1f5 avoid incrementing iterator when not appropriate
By chance, this hasn't caused any problems yet.
2022-03-16 12:33:20 -05:00
Soren I. Bjornstad
f0bd41f65a implement more robust private-person replacer
The previous method occasionally gave incorrect results because it
performed replacements on an entire line, rather than on individual
instances of the text to replace. This usually worked fine, but in rare
cases could create wrong/ugly output, and with future improvements to
what can be replaced could end up causing leaks.

This was a royal PITA to get working, but I'm fairly sure it's correct
now due to all the doctests. Please add more if you find any regressions
or think of cases that aren't covered.
2022-03-16 09:19:49 -05:00
Soren Bjornstad
d3f6216837 Merge pull request #4 from jacobkiers/allow-specifying-listening-host
Allow setting the host parameter
2022-03-14 21:01:35 -05:00
Soren I. Bjornstad
e14709be40 update copyright notice 2022-03-14 20:59:57 -05:00
bdeaac5d03 Specify listen_host as an option in the config file
Signed-off-by: Jacob Kiers <code@kiers.eu>
2022-03-14 18:22:07 +01:00
Soren I. Bjornstad
4acff2731a remove debug print mistakenly left in 2022-03-11 20:14:30 -06:00
Soren I. Bjornstad
572c3d0316 bump version and allow use of --version to see it 2022-01-23 17:28:19 -06:00
Soren I. Bjornstad
4a6e4e7bc0 don't crash if tzk is used without arguments 2022-01-23 17:22:45 -06:00
63 changed files with 563 additions and 66 deletions

1
.gitignore vendored
View File

@@ -5,3 +5,4 @@ venv/
cli_docs/_build/
dist/
build/
.pypi_token

View File

@@ -1,4 +1,4 @@
Copyright © 2021 Soren Bjornstad.
Copyright © 2021-2022 Soren Bjornstad and the tzk community.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@@ -18,9 +18,9 @@ copyright = '2021 Soren Bjornstad'
author = 'Soren Bjornstad'
# The short X.Y version
version = "0.1.4"
version = "0.3.0"
# The full version, including alpha/beta/rc tags
release = "0.1.4"
release = "0.3.0"
# -- General configuration ---------------------------------------------------

File diff suppressed because one or more lines are too long

View File

@@ -6,4 +6,4 @@ rm -rf build/
rm -f dist/*
mkdir -p dist
python setup.py sdist bdist_wheel
twine upload dist/*
TWINE_PASSWORD=$(cat .pypi_token) twine upload --username '__token__' dist/*

View File

@@ -4,6 +4,7 @@
# docs
sphinx==3.5.4 # newer versions display function names in the wrong color?
sphinx_rtd_theme==0.5.2
Jinja2<3.1 # https://github.com/readthedocs/readthedocs.org/issues/9038
# dev tools
build

View File

@@ -9,7 +9,7 @@ with open("README.md", "r") as fh:
setuptools.setup(
name="tzk",
version="0.1.4",
version="0.3.0",
author="Soren I. Bjornstad",
author_email="zettelkasten@sorenbjornstad.com",
description="Build tool for TiddlyWiki Zettelkasten",

View File

@@ -13,6 +13,8 @@ from tzk import tw
from tzk.util import (BuildError, fail, numerize, require_dependencies, pushd,
TZK_VERSION)
VERSION_INFO = f"tzk version {TZK_VERSION}"
class CliCommand(ABC):
"""
@@ -187,7 +189,7 @@ class VersionCommand(CliCommand):
pass
def execute(self, args: argparse.Namespace) -> None:
print(f"tzk version {TZK_VERSION}")
print(VERSION_INFO)
class BuildCommand(CliCommand):
@@ -392,6 +394,7 @@ def launch():
# go there before doing anything else.
if (not os.path.exists("tzk_config.py")
and os.environ.get('TZK_DIRECTORY')
and len(sys.argv) > 1
and sys.argv[1] != "init"): # we can't init an existing TZK_DIRECTORY
try:
os.chdir(os.environ['TZK_DIRECTORY'])
@@ -408,11 +411,17 @@ def launch():
parser = argparse.ArgumentParser(
description=f"TiddlyZettelKasten {TZK_VERSION} CLI\n"
f"Copyright (c) 2021 Soren Bjornstad.\n"
f"Copyright (c) 2021-2022 Soren Bjornstad and the tzk community.\n"
f"MIT license; see https://github.com/sobjornstad/tzk/blob/master/LICENSE for details.",
epilog="For full documentation, see https://tzk.readthedocs.io/en/latest/.",
formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument(
"--version",
action="version",
version=VERSION_INFO,
help=VersionCommand.help
)
subparsers = parser.add_subparsers()
for command in sorted(CliCommand.__subclasses__(), key=lambda i: i.__name__):

View File

@@ -13,13 +13,14 @@ information about the defined products without actually running any build steps.
from collections.abc import Mapping
from contextlib import contextmanager
import functools
import itertools
import os
from pathlib import Path
import re
import shutil
import subprocess
import tempfile
from typing import Callable, Dict, List, Optional, Set, Sequence, Tuple
from typing import Callable, Dict, Generator, List, Optional, Set, Sequence, Tuple
from tzk import git
from tzk import tw
@@ -359,8 +360,165 @@ def _private_people_replacement_table(
}
def _privatize_line(line: str, replacement_table: Dict[str, str],
replace_link_text: bool = False) -> Optional[str]:
"""
Given a line and a table of replacements to make, replace all instances
of all private people defined in the replacement table.
Basics:
>>> _privatize_line("MsAlice is a test person.", {'MsAlice': 'A.'})
'[[A.|PrivatePerson]] is a test person.'
>>> _privatize_line("This woman, known as MsAlice, is a test person.", \
{'MsAlice': 'A.'})
'This woman, known as [[A.|PrivatePerson]], is a test person.'
>>> _privatize_line("[[MsAlice]] is a test person.", {'MsAlice': 'A.'})
'[[A.|PrivatePerson]] is a test person.'
>>> _privatize_line("When we talk about [[MsAlice]] in the middle of a " \
"sentence, that's fine too.", {'MsAlice': 'A.'})
"When we talk about [[A.|PrivatePerson]] in the middle of a sentence, that's fine too."
Content inside a macro:
>>> _privatize_line('''Text with a footnote.''' \
'''<<fnote "Here's my footnote about MsAlice.">>''', \
{'MsAlice': 'A.'})
'Text with a footnote.<<fnote "Here\\'s my footnote about [[A.|PrivatePerson]].">>'
Links with different text and target:
>>> _privatize_line("We can talk about [[Alice|MsAlice]] " \
"with different text.", {'MsAlice': 'A.'})
'We can talk about [[Alice|PrivatePerson]] with different text.'
Multiple replacements with different people:
>>> _privatize_line("We can have [[MsAlice]] and MrBob talk to each other " \
"in the same line.", {'MsAlice': 'A.', 'MrBob': 'B.'})
'We can have [[A.|PrivatePerson]] and [[B.|PrivatePerson]] talk to each other in the same line.'
Multiple replacements with the same person:
>>> _privatize_line("We can have MsAlice talk to herself (MsAlice) " \
"in the same line.", {'MsAlice': 'A.'})
'We can have [[A.|PrivatePerson]] talk to herself ([[A.|PrivatePerson]]) in the same line.'
>>> _privatize_line("Likewise [[MsAlice]] can do it with brackets " \
"([[MsAlice]]).", {'MsAlice': 'A.'})
'Likewise [[A.|PrivatePerson]] can do it with brackets ([[A.|PrivatePerson]]).'
>>> _privatize_line('We can talk about [[Alice|MsAlice]] lots of ways, ' \
'like MsAlice and [[MsAlice]].', {'MsAlice': 'A.'})
'We can talk about [[Alice|PrivatePerson]] lots of ways, like [[A.|PrivatePerson]] and [[A.|PrivatePerson]].'
Replacements with alternate link text:
>>> _privatize_line('We can talk about [[Alice|MsAlice]] and [[Bob|MrBob]] as well', \
{'MsAlice': 'A.', 'MrBob': 'B.'}, replace_link_text=True)
'We can talk about [[A.|PrivatePerson]] and [[B.|PrivatePerson]] as well'
We don't want to replace places where a CamelCase match is a substring of another
word. This is expected to yield no output because there's nothing to replace:
>>> _privatize_line("But an EmbeddedCamelWithMsAliceInIt isn't her.", \
{'MsAlice': 'A.'})
"""
def iteroccurrences(needle: str) -> Generator[int, int, None]:
"""
Iterate over the start indices of occurrences of substring
``needle`` in the line /line/ in outer scope.
(We have to use outer scope because it can be changed while we're iterating
and the generator is only bound to arguments once.)
"""
idx = -1
while True:
idx = line.find(needle, idx + 1)
if idx == -1:
return
else:
additional_increments = yield idx
if additional_increments is not None:
idx += additional_increments
def anchored_at_one_end(start_index: int, end_index: int) -> bool:
return start_index == 0 or end_index == len(line)
def is_camelcase_link(start_index: int, end_index: int) -> bool:
return (anchored_at_one_end(start_index, end_index)
or (line[start_index-1] != '[' and line[end_index] != ']'))
def is_bare_bracketed_link(start_index: int, end_index: int) -> bool:
return (not anchored_at_one_end(start_index, end_index)
and line[start_index-2:start_index] == '[['
and line[end_index:end_index+2] == ']]')
def is_textual_bracketed_link(start_index: int, end_index: int) -> bool:
return (not anchored_at_one_end(start_index, end_index)
and line[start_index-1] == '|'
and line[end_index:end_index+2] == ']]')
dirty = False
increment_iterator_by = 0
for replace_person, replace_initials in replacement_table.items():
iterator = iteroccurrences(replace_person)
try:
while True:
# NOTE: the "end" index is one after the last index in the string,
# as is needed for slice notation.
if increment_iterator_by:
start_idx = iterator.send(increment_iterator_by)
increment_iterator_by = 0
else:
start_idx = next(iterator)
end_idx = start_idx + len(replace_person)
new_line = None
if is_camelcase_link(start_idx, end_idx):
# camel-case link or unlinked reference in text
def is_spurious_substring():
# If there's not a non-alphanumeric character on both sides of
# the "link", we may be making a clbuttic replacement.
# <https://en.wikipedia.org/wiki/Scunthorpe_problem>
start_ok = start_idx == 0 or not line[start_idx-1].isalnum()
end_ok = end_idx == len(line) or not line[end_idx].isalnum()
return not (start_ok and end_ok)
if not is_spurious_substring():
new_line = (line[0:start_idx]
+ f'[[{replace_initials}|PrivatePerson]]'
+ line[end_idx:])
elif is_bare_bracketed_link(start_idx, end_idx):
# link with the person as the target and text
replacement = replace_initials + '|PrivatePerson'
new_line = line[0:start_idx] + replacement + line[end_idx:]
elif is_textual_bracketed_link(start_idx, end_idx):
# link with the person as the target only;
# beware that you might have put something private in the text
if replace_link_text:
start_of_link = line[0:start_idx].rfind('[[', 0, start_idx) + 2
new_line = line[0:start_of_link] + f"{replace_initials}|PrivatePerson" + line[end_idx:]
else:
new_line = line[0:start_idx] + 'PrivatePerson' + line[end_idx:]
else:
link = line[start_idx:end_idx]
raise ValueError("Unknown type of link '{link}'.")
if new_line:
line = new_line
dirty = True
# If we changed the length of the string by modifying it,
# we need to update our stored position within the string.
increment_iterator_by = len(new_line) - len(line)
except StopIteration:
pass
if dirty:
return line
else:
return None
@tzk_builder
def replace_private_people(initialer: Callable[[str], str] = None, replace_link_text = False) -> None:
def replace_private_people(initialer: Callable[[str], str] = None, replace_link_text: bool = False) -> None:
"""
Replace the names of people who are not marked Public with their initials.
@@ -402,44 +560,18 @@ def replace_private_people(initialer: Callable[[str], str] = None, replace_link_
assert 'public_wiki_folder' in build_state
replacement_table = _private_people_replacement_table(initialer)
from pprint import pprint; pprint(replacement_table)
tid_files = (Path(build_state['public_wiki_folder']) / "tiddlers").glob("**/*.tid")
root = (Path(build_state['public_wiki_folder']) / "tiddlers")
tid_files = itertools.chain(root.glob("**/*.tid"), root.glob("**/*.json"))
for tiddler in tid_files:
dirty = False
with tiddler.open() as f:
lines = f.readlines()
for i in range(len(lines)):
for replace_person, replace_initials in replacement_table.items():
if replace_person in lines[i]:
if '|' + replace_person + ']]' in lines[i]:
# link with the person as the target only;
# beware that you might have put something private in the text
if replace_link_text:
# with this option, the initials are also
# put in the text, solving the warning before
end = lines[i].find('|' + replace_person + ']]')
start = lines[i].rfind('[[', 0, end) + 2
search = f"[[{lines[i][start:end]}|{replace_person}]]"
replace = f"[[{replace_initials}|PrivatePerson]]"
lines[i] = lines[i].replace(search, replace)
else:
lines[i] = lines[i].replace(replace_person, 'PrivatePerson')
elif '[[' + replace_person + ']]' in lines[i]:
# link with the person as the target and text
lines[i] = lines[i].replace(
replace_person,
replace_initials + '|PrivatePerson')
else:
# camel-case link or unlinked reference in text;
# or spurious substring, so rule that out with the '\b' search
lines[i] = re.sub(
r"\b" + re.escape(replace_person) + r"\b",
f'<<privateperson "{replace_initials}">>',
lines[i]
)
dirty = True
private_line = _privatize_line(lines[i], replacement_table, replace_link_text)
if private_line is not None:
lines[i] = private_line
dirty = True
if dirty:
with tiddler.open("w") as f:
f.writelines(lines)

View File

@@ -35,6 +35,10 @@ commit_remote = ""
# http://localhost:8080 in your browser.
listen_port = 8080
# Host to listen on. If you specify "0.0.0.0" it will listen to all network interfaces.
# This is useful for allowing the wiki to be exposed to the network through a container.
listen_host = "127.0.0.1"
# Uncomment if you want to require HTTP basic authentication when serving your wiki.
# **WARNING**: this is NOT secure for use over the open Internet or all but the
# simplest local networks, as the password is sent in the clear. For good

View File

@@ -8,7 +8,7 @@ type: text/vnd.tiddlywiki
<$set name="tr-rendering" value="yes">
<span id="tr-version">1.3.2</span>
<span id="tr-version">1.3.3</span>
{{||$:/plugins/sobjornstad/TiddlyRemember/templates/AnkiDecks}}
{{||$:/plugins/sobjornstad/TiddlyRemember/templates/AnkiTags}}

View File

@@ -2,7 +2,7 @@
"title": "$:/plugins/sobjornstad/TiddlyRemember",
"description": "TiddlyRemember: Embed Anki notes in your TiddlyWiki",
"author": "Soren Bjornstad",
"version": "1.3.2",
"version": "1.3.3",
"core-version": ">=5.1.21",
"source": "https://github.com/sobjornstad/TiddlyRemember",
"list": "readme license",

View File

@@ -0,0 +1,3 @@
title: $:/plugins/tobibeer/appear/defaults/button-class
tc-btn-invisible tc-tiddlylink

View File

@@ -0,0 +1,3 @@
title: $:/plugins/tobibeer/appear/defaults/default-state
$:/temp/appear/

View File

@@ -0,0 +1,3 @@
title: $:/plugins/tobibeer/appear/defaults/keep
yes

View File

@@ -0,0 +1,3 @@
title: $:/plugins/tobibeer/appear/defaults/mode
block

View File

@@ -0,0 +1,3 @@
title: $:/plugins/tobibeer/appear/defaults/show
»

View File

@@ -0,0 +1,13 @@
/*\
title: $:/plugins/tobibeer/appear/popup.js
type: application/javascript
module-type: utils
An enhanced version of the core Popup to support:
* absolute popups
* preview popups
* popup z-index
@preserve
\*/
(function(){"use strict";var t=require("$:/core/modules/utils/dom/popup.js").Popup,e=require("$:/core/modules/widgets/reveal.js").reveal,s=e.prototype.refresh;t.prototype.show=function(t){var e,s=t.domNode,p=$tw.utils.hasClass(s,"tc-popup-absolute"),o=this.popupInfo(s),i=function(t){var e=t,s=0,p=0;do{s+=e.offsetLeft||0;p+=e.offsetTop||0;e=e.offsetParent}while(e);return{left:s,top:p}},l={left:s.offsetLeft,top:s.offsetTop};e=o.popupLevel;if(o.isHandle){e++}this.cancel(e);if(this.findPopup(t.title)===-1){this.popups.push({title:t.title,wiki:t.wiki,domNode:s})}l=p?i(s):l;t.wiki.setTextReference(t.title,"("+l.left+","+l.top+","+s.offsetWidth+","+s.offsetHeight+")");if(this.popups.length>0){this.rootElement.addEventListener("click",this,true)}};t.prototype.popupInfo=function(t){var e,s=false,p=t;while(p&&e===undefined){if($tw.utils.hasClass(p,"tc-popup-handle")||$tw.utils.hasClass(p,"tc-popup-keep")){s=true}if($tw.utils.hasClass(p,"tc-reveal")&&($tw.utils.hasClass(p,"tc-popup")||$tw.utils.hasClass(p,"tc-popup-handle"))){e=parseInt(p.style.zIndex)-1e3}p=p.parentNode}var o={popupLevel:e||0,isHandle:s};return o};t.prototype.handleEvent=function(t){if(t.type==="click"){var e=this.popupInfo(t.target),s=e.popupLevel-1;if(e.isHandle){if(s<0){s=1}else{s++}}this.cancel(s)}};e.prototype.refresh=function(){var t,e,p=this.isOpen;e=s.apply(this,arguments);t=this.domNodes[0];if(this.isOpen&&(p!==this.isOpen||!t.style.zIndex)&&t&&(this.type==="popup"||$tw.utils.hasClass(t,"tc-block-dropdown")&&$tw.utils.hasClass(t,"tc-reveal"))){t.style.zIndex=1e3+$tw.popup.popups.length}return e}})();

View File

@@ -0,0 +1,3 @@
module-type: utils
title: $:/plugins/tobibeer/appear/popup.js
type: application/javascript

View File

@@ -0,0 +1,31 @@
title: $:/plugins/tobibeer/appear/readme
This plugin provides the ''$appear'' widget that can render popups and sliders (inline or block) as well as accordion menus.
!! Attributes
; type
: set to `popup` to have the content appear as a popup
; show
: the button label
; hide
: the hide button label
; mode
: either `block` or `inline`, with respect to the inner content
: any other mode is interpreted as block mode, without the default styles applying, e.g. drop-shadows
; once
: allows to click the button once, then hides it (unless the state is deleted)
; $state
: the widget calculates a state for you, use this to append a simple id
; state
: alternatively, specify a fully qualified state
; keep
: make popups sticky when `yes` or `true`
; handle / handler / variables
: allows to take the popup contents out of the flow and render them elsewhere on the page
: required to properly create popups in table cells and other constained elements
: specify variables to take along
<br>
; documentation / examples / demos...
: http://tobibeer.github.io/tw5-plugins#appear

View File

@@ -0,0 +1,21 @@
tags: $:/tags/Stylesheet
title: $:/plugins/tobibeer/appear/styles
\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline html
<pre>.tc-reveal.appear-block,
.tc-popup.appear {
border-radius: 5px;
padding: 1px 1em;
<<box-shadow "2px 2px 4px rgba(0,0,0,0.3)">>;
}
.tc-popup.appear {
padding: 0 1em;
background: <<colour background>>;
}
.appear-reveal.appear-inline{
margin-left:5px;
}
.appear-reveal.appear-inline.appear-once{
margin-left:0;
}</pre>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
module-type: widget
title: $:/plugins/tobibeer/appear/widget.js
type: application/javascript

View File

@@ -0,0 +1,15 @@
{
"author": "Tobias Beer",
"core-version": ">=5.1.9",
"created": "20220505135225785",
"dependents": "",
"description": "Create popups, sliders or accordion menus with the appear widget.",
"documentation": "https://tobibeer.github.io/tw5-appear",
"list": "readme",
"modified": "20220505135225785",
"plugin-type": "plugin",
"requires": "",
"source": "https://github.com/tobibeer/tw5-appear",
"title": "$:/plugins/tobibeer/appear",
"version": "0.6.2"
}

View File

@@ -0,0 +1,20 @@
title: $:/plugins/tobibeer/preview/config
\define default()
<dt>$(defaults)$$(option)$</dt>
<dd>
//{{$:/plugins/tobibeer/preview/lingo/$(option)$}}<$list
filter="[[$(option)$]prefix[template]]">
{{$(defaults)$$(option)$}}</$list>://<br>
<$edit-text tag=input tiddler="$(defaults)$$(option)$"/>
</dd>
\end
<dl class="preview-defaults">
<$vars defaults="$:/plugins/tobibeer/preview/defaults/">
<$list filter="[all[tiddlers+shadows]removeprefix<defaults>sort[title]]" variable="option">
<<default>>
</$list>
</$vars>
</dl>
<style>.preview-defaults input {width:90%;}</style>

View File

@@ -0,0 +1,3 @@
title: $:/plugins/tobibeer/preview/defaults/class
tc-popup-keep

View File

@@ -0,0 +1,3 @@
title: $:/plugins/tobibeer/preview/defaults/delay
1500

View File

@@ -0,0 +1,3 @@
title: $:/plugins/tobibeer/preview/defaults/exclude
[is[system]] [all[shadows]] [!has[text]]

View File

@@ -0,0 +1,3 @@
title: $:/plugins/tobibeer/preview/defaults/keys
CTRL

View File

@@ -0,0 +1,3 @@
title: $:/plugins/tobibeer/preview/defaults/not
tc-drop-down tc-sidebar-scrollable tc-topbar tc-tiddler-title

View File

@@ -0,0 +1,3 @@
title: $:/plugins/tobibeer/preview/defaults/template
$:/plugins/tobibeer/preview/template

View File

@@ -0,0 +1,11 @@
/*\
title: $:/plugins/tobibeer/preview/keyboard.js
type: application/javascript
module-type: utils
Fixes $:/core/modules/utils/dom/keyboard.js by providing an alternative.
Do not use as an API, let's fix the core.
@preserve
\*/
(function(){"use strict";var e={BACKSPACE:8,TAB:9,ENTER:13,ESCAPE:27,PAGEUP:33,PAGEDOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,INSERT:45,DELETE:46};exports.parseKeyDescriptorTB=function(t){var l,r,y,s=t.toUpperCase().split("+"),K={keyCode:null,shiftKey:false,altKey:false,ctrlKey:false};for(y=0;y<s.length;y++){l=false;r=s[y];if(r.substr(0,1)==="!"){l=true;r=r.substr(1)}if(r==="CTRL"){K.ctrlKey=l?null:true}else if(r==="SHIFT"){K.shiftKey=l?null:true}else if(r==="ALT"){K.altKey=l?null:true}else if(r==="META"){K.metaKey=l?null:true}else if(e[r]){K.keyCode=e[r]}else{K.keyCode=r.charCodeAt(0)}}return K};exports.checkKeyDescriptorTB=function(e,t){var l=!!t.metaKey;return(t.keyCode===null||e.keyCode===t.keyCode)&&(t.shiftKey===null?!e.shiftKey:e.shiftKey===t.shiftKey)&&(t.altKey===null?!e.altKey:e.altKey===t.altKey)&&(t.ctrlKey===null?!e.ctrlKey:e.ctrlKey===t.ctrlKey)&&(t.metaKey===null?!e.metaKey:e.metaKey===l)}})();

View File

@@ -0,0 +1,3 @@
module-type: utils
title: $:/plugins/tobibeer/preview/keyboard.js
type: application/javascript

View File

@@ -0,0 +1,3 @@
title: $:/plugins/tobibeer/preview/lingo/class
css classes applied to the popup

View File

@@ -0,0 +1,3 @@
title: $:/plugins/tobibeer/preview/lingo/delay
delay popup for this many milliseconds

View File

@@ -0,0 +1,3 @@
title: $:/plugins/tobibeer/preview/lingo/exclude
no preview for links to tiddlers matching this filter

View File

@@ -0,0 +1,3 @@
title: $:/plugins/tobibeer/preview/lingo/keys
modifier keys to trigger popup directly on-hover (ctrl, alt+shift, meta, etc...)

View File

@@ -0,0 +1,3 @@
title: $:/plugins/tobibeer/preview/lingo/not
no preview for links inside elements with these classes

View File

@@ -0,0 +1,3 @@
title: $:/plugins/tobibeer/preview/lingo/open
view at ''<<WIKI>>''

View File

@@ -0,0 +1,3 @@
title: $:/plugins/tobibeer/preview/lingo/template
the preview template

View File

@@ -0,0 +1,10 @@
/*\
title: $:/plugins/tobibeer/preview/link.js
type: application/javascript
module-type: startup
Enhances the link widget for on-hover previews
@preserve
\*/
(function(){var e,t=require("$:/core/modules/widgets/link.js").link,i=t.prototype.render,o=t.prototype.handleClickEvent;t.prototype.render=function(){i.apply(this,arguments);var t=this,o=this.wiki,p=this.domNodes[0],r=o.getTiddler(t.to),n="$:/plugins/tobibeer/preview/defaults/",u="$:/temp/tobibeer/preview-",l=$tw.utils.parseKeyDescriptorTB(o.getTextReference(n+"keys","").toUpperCase()),s=o.getTextReference(n+"delay").toUpperCase(),a=function(e){var i=$tw.popup.popupInfo(e),p=i.popupLevel;return o.getTextReference(u+p)&&o.getTextReference(u+p+"-tiddler")===t.to?null:i},f=function(){var i,r=a(p);if(r){i=r.popupLevel;clearTimeout(t.previewTimeout);$tw.popup.cancel(i);i++;o.setText(u+i+"-tiddler","text",null,t.to);if($tw.popup.findPopup(u+i)===-1){setTimeout(function(){$tw.popup.triggerPopup({domNode:p,title:u+i,wiki:o});e=0},50)}}},d=function(){var e,i,r=1,u=o.getTextReference(n+"not","");if(u){$tw.utils.each(u.split(" "),function(e){var t=p;while(t&&r){if($tw.utils.hasClass(t,e)){r=0;return false}t=t.parentNode}})}if(r){i=o.getTextReference(n+"exclude","");e=i?o.filterTiddlers(i):[];if(e.indexOf(t.to)>=0){r=0}}return r};s=s!==undefined?parseInt(s):null;if(s!==null&&isNaN(s)){s=0}if(r){$tw.utils.addClass(p,"tc-popup-handle");$tw.utils.addClass(p,"tc-popup-absolute");["mouseover","mouseout"].forEach(function(i){p.addEventListener(i,function(o){var p=o||window.event;if(i==="mouseover"){if(d()){if(!p.keyCode){p.keyCode=0}if($tw.utils.checkKeyDescriptorTB(p,l)){if(!e){e=1;f()}}else if(s!==null){e=0;t.previewTimeout=setTimeout(f,s)}}}else{e=0;clearTimeout(t.previewTimeout)}})})}};t.prototype.handleClickEvent=function(){o.apply(this,arguments);clearTimeout(this.previewTimeout);$tw.popup.cancel(Math.max(0,$tw.popup.popupInfo(this.domNodes[0]).popupLevel))}})();

View File

@@ -0,0 +1,3 @@
module-type: startup
title: $:/plugins/tobibeer/preview/link.js
type: application/javascript

View File

@@ -0,0 +1,24 @@
tags: $:/tags/PageTemplate
title: $:/plugins/tobibeer/preview/popups
\define state(num)
$:/temp/tobibeer/preview-$num$
\end
\define classes(num)
tc-popup appear appear-block appear-reveal tc-preview-tiddler tc-preview-tiddler-$num$ $(default-classes)$
\end
\define level(num)
<$reveal tag="div" type="popup" state=<<state $num$>> class=<<classes $num$>>>
<$tiddler tiddler={{$:/temp/tobibeer/preview-$num$-tiddler}}>
<$transclude tiddler={{$:/plugins/tobibeer/preview/defaults/template}} mode="block"/>
</$tiddler>
</$reveal>
\end
<$vars default-classes={{$:/plugins/tobibeer/preview/defaults/class}}>
<$list filter="1 2 3 4 5 6 7 8 9">
<$macrocall $name="level" num={{!!title}}/>
</$list>
</$vars>

View File

@@ -0,0 +1,8 @@
title: $:/plugins/tobibeer/preview/readme
The plugin $:/plugins/tobibeer/preview enhances the core <<x LinkWidget>> to display a preview of tiddlers when hovering an internal link.
<br>
; documentation / examples / demos...
: http://tobibeer.github.io/tw5-plugins#preview

View File

@@ -0,0 +1,8 @@
tags: $:/tags/Stylesheet
title: $:/plugins/tobibeer/preview/styles
.tc-popup.tc-preview-tiddler{
max-width:600px;
width:100%;
padding:1em;
}

View File

@@ -0,0 +1,5 @@
title: $:/plugins/tobibeer/preview/template
{{||$:/core/ui/ViewTemplate/tags}}
<$transclude mode="block"/>

View File

@@ -0,0 +1,15 @@
{
"author": "Tobias Beer",
"core-version": ">=5.1.9",
"created": "20220505135243990",
"dependents": "",
"description": "Shows a tiddler preview when hovering internal links",
"documentation": "https://tobibeer.github.io/tw5-preview",
"list": "readme config",
"modified": "20220505135243990",
"plugin-type": "plugin",
"requires": "[[tobibeer/appear|http://tobibeer.github.io/tw5-plugins/#appear]]",
"source": "https://github.com/tobibeer/tw5-preview",
"title": "$:/plugins/tobibeer/preview",
"version": "0.5.6"
}

View File

@@ -1,6 +1,8 @@
created: 20200121230518238
modified: 20210410005001202
creator: soren
modified: 20220622234624323
modifier: soren
title: $:/config/RelinkOnRename
type: text/vnd.tiddlywiki
yes
no

View File

@@ -1,5 +1,7 @@
created: 20200516190911842
modified: 20211113234932630
creator: soren
modified: 20220302210205566
modifier: soren
tags:
title: $:/config/TiddlyRemember/TagMapping
type: text/vnd.tiddlywiki

View File

@@ -1,6 +1,6 @@
created: 20200118003731285
creator: soren
modified: 20200118003737882
modified: 20220215235820508
modifier: soren
title: $:/config/Toolbar/ButtonClass
type: text/vnd.tiddlywiki

View File

@@ -0,0 +1,8 @@
created: 20220622212041227
creator: soren
modified: 20220622212041250
modifier: soren
title: $:/config/shortcuts-mac/save-tiddler
type: text/vnd.tiddlywiki
cmd-Enter

View File

@@ -0,0 +1,8 @@
created: 20220622212047526
creator: soren
modified: 20220622212047547
modifier: soren
title: $:/config/shortcuts-not-mac/save-tiddler
type: text/vnd.tiddlywiki
ctrl-Enter

View File

@@ -0,0 +1,6 @@
created: 20220622212052270
creator: soren
modified: 20220622212052289
modifier: soren
title: $:/config/shortcuts/save-tiddler
type: text/vnd.tiddlywiki

View File

@@ -2,7 +2,7 @@ caption: Spoiler banner
created: 20210622003118415
creator: soren
description: Display a warning banner on fiction tiddlers (any tiddler with a non-empty `universe` field) noting that we don't try to hide spoilers.
modified: 20211107181812051
modified: 20220502164810636
modifier: soren
private: no
public: no

View File

@@ -0,0 +1,8 @@
created: 20220505135343597
creator: soren
modified: 20220505135454120
modifier: soren
title: $:/plugins/tobibeer/preview/defaults/delay
type: text/vnd.tiddlywiki
500

View File

@@ -0,0 +1,8 @@
created: 20220505135432323
creator: soren
modified: 20220505135433494
modifier: soren
title: $:/plugins/tobibeer/preview/defaults/exclude
type: text/vnd.tiddlywiki
[is[system]] [all[shadows]]

View File

@@ -0,0 +1,8 @@
created: 20220505135435971
creator: soren
modified: 20220505135437221
modifier: soren
title: $:/plugins/tobibeer/preview/defaults/keys
type: text/vnd.tiddlywiki
Ctrl

View File

@@ -0,0 +1,11 @@
created: 20220505135633168
creator: soren
modified: 20220505135638189
modifier: soren
title: $:/plugins/tobibeer/preview/template
type: text/vnd.tiddlywiki
{{||$:/core/ui/ViewTemplate/subtitle}}
{{||$:/core/ui/ViewTemplate/tags}}
<$transclude mode="block"/>

View File

@@ -3,7 +3,7 @@ created: 20200419143537510
creator: soren
description: Copy the name of this tiddler to the clipboard
list-after: $:/core/ui/Buttons/info
modified: 20210922125723154
modified: 20220215235957457
modifier: soren
tags: $:/tags/ViewToolbar
title: $:/sib/Buttons/CopyTitleReference
@@ -12,7 +12,7 @@ type: text/vnd.tiddlywiki
\whitespace trim
<$button message="tm-copy-to-clipboard" param={{!!title}} tooltip={{$:/sib/Buttons/CopyTitleReference!!caption}} class=<<tv-config-toolbar-class>>>
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
<i class="far fa-copy" style="font-size:160%; position:relative; bottom:-4px; left:-1px;"/>
<i class="far fa-copy" style="font-size: 160%; position:relative; bottom:-4px; left:-1px;"/>
</$list>
<$list filter="[<tv-config-toolbar-text>match[yes]]">
<span class="tc-btn-text">

View File

@@ -1,8 +1,10 @@
caption: new source
created: 20200822190145295
creator: soren
description: Create a new source tiddler
list-after: $:/core/ui/Buttons/new-tiddler
modified: 20210522014032330
modified: 20220504192240445
modifier: soren
tags: $:/tags/PageControls
title: $:/sib/Buttons/NewSource
type: text/vnd.tiddlywiki
@@ -25,6 +27,6 @@ type: text/vnd.tiddlywiki
readstatus="unread"
author=""
completed=""
year="2021"
year=<<now YYYY>>
/>
</$button>

View File

@@ -1,7 +1,7 @@
created: 20211120164840100
creator: soren
description: Navigate to the parent or a sibling of the current subtiddler. Subtiddler names are separated from that of their supertiddlers by a / (and are not system tiddlers).
modified: 20211120170254112
modified: 20220202173655863
modifier: soren
tags: $:/tags/ViewTemplate
title: $:/sib/Templates/Automatic/Subtiddler
@@ -10,6 +10,7 @@ type: text/vnd.tiddlywiki
\define expand-siblings() <$action-setfield $tiddler="$:/temp/ShowSiblings" $index=<<currentTiddler>> $value="yes" />
\define contract-siblings() <$action-setfield $tiddler="$:/temp/ShowSiblings" $index=<<currentTiddler>> $value="no" />
\define siblings-filter() [prefix<parentTiddlerPlusSlash>!match<currentTiddler>]
<$list filter="[all[current]!is[system]regexp:title[/]]" variable=_>
<$set name="parentTiddler" value={{{ [all[current]split[/]butlast[]join[/]] }}}>
@@ -18,11 +19,13 @@ type: text/vnd.tiddlywiki
This is a subtiddler of <$link to=<<parentTiddler>>/>.<br>
<$reveal stateTitle="$:/temp/ShowSiblings" stateIndex=<<currentTiddler>> type="nomatch" text="yes">
<$button class="tc-btn-invisible tc-tiddlylink" actions=<<expand-siblings>>>{{$:/core/images/right-arrow}} Siblings of this subtiddler</$button>
<$list filter="[prefix<parentTiddlerPlusSlash>!match<currentTiddler>first[]]" variable=_ emptyMessage="This is the only subtiddler.">
<$button class="tc-btn-invisible tc-tiddlylink" actions=<<expand-siblings>>>{{$:/core/images/right-arrow}} Siblings of this subtiddler</$button> (<$count filter=<<siblings-filter>>/>)
</$list>
</$reveal>
<$reveal stateTitle="$:/temp/ShowSiblings" stateIndex=<<currentTiddler>> type="match" text="yes">
<$button class="tc-btn-invisible tc-tiddlylink" actions=<<contract-siblings>>>{{$:/core/images/down-arrow}} Siblings of this subtiddler:</$button><br>
<$list filter="[prefix<parentTiddlerPlusSlash>]">
<$list filter=<<siblings-filter>>>
<$link to=<<currentTiddler>>><$text text={{{ [<currentTiddler>removeprefix<parentTiddlerPlusSlash>] }}}/></$link><br>
</$list>
</$reveal>

View File

@@ -3,7 +3,7 @@ created: 20210701023215046
creator: soren
description: Items we're currently working on but don't need to leave open. Drag and drop a link to a tiddler to add it.
list:
modified: 20211026030511257
modified: 20220716205827340
modifier: soren
tags: Meta Tool
title: $:/sib/Tools/Tray

View File

@@ -10,7 +10,7 @@ import sys
from typing import Any, Callable, Dict, NoReturn
TZK_VERSION = "0.1.4"
TZK_VERSION = "0.3.0"
class BuildError(Exception):