manual installation / a known bug
[ikiwiki] / doc / todo / matching_different_kinds_of_links.mdwn
1 [[!tag wishlist]]
2
3 As noted in [[todo/tag_pagespec_function]], there is a "misbehavior" of a `tagged()` pagespec: it matches even pages which have plain links to the tag page.
4
5 And in general, it would be quite useful to be able to distinguish different kinds of links: one more kind, in addition to "tag", is "bug dependency" noted in [[todo/structured_page_data#another_kind_of_links]] and [[todo/tracking_bugs_with_dependencies#another_kind_of_links]].
6
7 It could distinguish the links by the `rel=` attribute. ([[Tags already receive a special rel-class|todo/rel_attribute_for_links]].) This means there is a general need for a syntax to specify user-defined rel-classes on wikilink (then bug deps would simply use their special rel-class, either directly, or through a special directive like `\[[!depends ]]`), and to refer to them in pagespecs (in forward and backward direction).
8
9 Besides pagespecs, the `rel=` attribute could be used for styles. --Ivan Z.
10
11 > FWIW, the `add_link` function introduced in a recent
12 > release adds an abstraction that could be used to get
13 > part of the way there to storing data about different types of
14 > links. That function could easily be extended to take an optional
15 > third parameter specifying the link type.
16
17 > Then there's the question of how to store and access the data. `%links`
18 > does not offer a good way to add additional information about links.
19 > Now, we could toss `%links` entirely and switch to an accessor function,
20 > but let's think about not doing that..
21
22 > The data that seems to be needed is basically a deep hash, so
23 > one could check `$linktype{$page}{tag}{$link}` to see if
24 > the page contains a link of the given type. (Note that pages could
25 > contain links that were duplicates except for their types.)
26
27 > There would be some data duplication, unfortuantly, but if `%linktype`
28 > is not populated for regular wikilinks, it would at least be limited to
29 > tags and other unusual link types, so not too bad.
30
31 > `%linktype` could be stored in `%pagestate`.. if so
32 > the actual use might look like `$pagestate{$page}{linktype}{tag}{$link}`.
33 > That could be implemented by the tag plugin right now
34 > with no core changes. (BTW, then I originally wrote tag, pagestate
35 > was not available, which is why I didn't make it differentiate from
36 > normal links.) Might be better to go ahead and add the variable to
37 > core though. --[[Joey]] 
38
39 >> I've implemented this with the data structure you suggested, except that
40 >> I called it `%typedlinks` instead of `%linktype` (it seemed to make more
41 >> sense that way). I also ported `tag` to it, and added a `tagged_is_strict`
42 >> config option. See below! --[[smcv]]
43
44 I saw somewhere else here some suggestions for the wiki-syntax for specifying the relation name of a link. One more suggestion---[the syntax used in Semantic MediaWiki](http://en.wikipedia.org/wiki/Semantic_MediaWiki#Basic_usage), like this:
45
46 <pre>
47 ... the capital city is \[[Has capital::Berlin]] ...
48 </pre>
49
50 So a part of the effect of [[`\[[!taglink TAG\]\]`|plugins/tag]] could be represented as something like `\[[tag::TAG]]` or (more understandable relation name in what concerns the direction) `\[[tagged::TAG]]`.
51
52 I don't have any opinion on this syntax (whether it's good or not)...--Ivan Z.
53
54 -------
55
56 >> [[!template id=gitbranch author="[[Simon_McVittie|smcv]]" branch=smcv/ready/link-types]]
57 >> [[!tag patch]]
58
59 ## Documentation for smcv's branch
60
61 ### added to [[ikiwiki/pagespec]]
62
63 * "`typedlink(type glob)`" - matches pages that link to a given page (or glob)
64   with a given link type. Plugins can create links with a specific type:
65   for instance, the tag plugin creates links of type `tag`.
66
67 ### added to [[plugins/tag]]
68
69 If the `tagged_is_strict` config option is set, `tagged()` will only match
70 tags explicitly set with [[ikiwiki/directive/tag]] or
71 [[ikiwiki/directive/taglink]]; if not (the default), it will also match
72 any other [[WikiLinks|ikiwiki/WikiLink]] to the tag page.
73
74 ### added to [[plugins/write]]
75
76 #### `%typedlinks`
77
78 The `%typedlinks` hash records links of specific types. Do not modify this
79 hash directly; call `add_link()`. The keys are page names, and the values
80 are hash references. In each page's hash reference, the keys are link types
81 defined by plugins, and the values are hash references with link targets
82 as keys, and 1 as a dummy value, something like this:
83
84         $typedlinks{"foo"} = {
85                 tag => { short_word => 1, metasyntactic_variable => 1 },
86                 next_page => { bar => 1 },
87         };
88
89 Ordinary [[WikiLinks|ikiwiki/WikiLink]] appear in `%links`, but not in
90 `%typedlinks`.
91
92 #### `add_link($$;$)`
93  
94  This adds a link to `%links`, ensuring that duplicate links are not
95  added. Pass it the page that contains the link, and the link text.
96  
97 An optional third parameter sets the link type (`undef` produces an ordinary
98 [[ikiwiki/WikiLink]]).
99
100 ## Review
101
102 Some code refers to `oldtypedlinks`, and other to `oldlinktypes`. --[[Joey]]
103
104 > Oops, I'll fix that. That must mean missing test coverage, too :-(
105 > --s
106
107 >> A test suite for the dependency resolver *would* be nice. --[[Joey]]
108
109 >>> Bug fixed, I think. A test suite for the dependency resolver seems
110 >>> more ambitious than I want to get into right now, but I added a
111 >>> unit test for this part of it... --s
112
113 I'm curious what your reasoning was for adding a new variable
114 rather than using `pagestate`. Was it only because you needed
115 the `old` version to detect change, or was there other complexity?
116 --J
117
118 > You seemed to be more in favour of adding it to the core in
119 > your proposal above, so I assumed that'd be more likely to be
120 > accepted :-) I don't mind one way or the other - `%typedlinks`
121 > costs one core variable, but saves one level of hash nesting. If
122 > you're not sure either, then I think the decision should come down
123 > to which one is easier to document clearly - I'm still unhappy with
124 > my docs for `%typedlinks`, so I'll try to write docs for it as
125 > `pagestate` and see if they work any better. --s
126
127 >> On reflection, I don't think it's any better as a pagestate, and
128 >> the contents of pagestates (so far) aren't documented for other
129 >> plugins' consumption, so I'm inclined to leave it as-is, unless
130 >> you want to veto that. Loose rationale: it needs special handling
131 >> in the core to be a dependency type (I re-used the existing link
132 >> type), it's API beyond a single plugin, and it's really part of
133 >> the core parallel to pagestate rather than being tied to a
134 >> specific plugin. Also, I'd need to special-case it to have
135 >> ikiwiki not delete it from the index, unless I introduced a
136 >> dummy typedlinks plugin (or just hook) that did nothing... --s
137
138 I have not convinced myself this is a real problem, but..
139 If a page has a typed link, there seems to be no way to tell
140 if it also has a separate, regular link. `add_link` will add
141 to `@links` when adding a typed, or untyped link. If only untyped
142 links were recorded there, one could tell the difference. But then
143 typed links would not show up at all in eg, a linkmap,
144 unless it was changed to check for typed links too.
145 (Or, regular links could be recorded in typedlinks too,
146 with a empty type. (Bloaty.)) --J
147
148 > I think I like the semantics as-is - I can't think of any
149 > reason why you'd want to ask the question "does A link to B,
150 > not counting tags and other typed links?". A typed link is
151 > still a link, in my mind at least. --s
152
153 >> Me neither, let's not worry about it. --[[Joey]] 
154
155 I suspect we could get away without having `tagged_is_strict`
156 without too much transitional trouble. --[[Joey]]
157
158 > If you think so, I can delete about 5 LoC. I don't particularly
159 > care either way; [[Jon]] expressed concern about people relying
160 > on the current semantics, on one of the pages requesting this
161 > change. --s
162
163 >> Removed in a newer version of the branch. --s
164
165 I might have been wrong to introduce `typedlink(tag foo)`. It's not
166 very user-friendly, and is more useful as a backend for other plugins
167 that as a feature in its own right - any plugin introducing a link
168 type will probably also want to have its own preprocessor directive
169 to set that link type, and its own pagespec function to match it.
170 I wonder whether to make a `typedlink` plugin that has the typedlink
171 pagespec match function and a new `\[[!typedlink to="foo" type="bar"]]`
172 though... --[[smcv]]
173
174 > I agree, per-type matchers are more friendly and I'm not enamored of the
175 > multi-parameter pagespec syntax. --[[Joey]]
176
177 >> Removed in a newer version of the branch. I re-introduced it as a
178 >> plugin in `smcv/typedlink`, but I don't think we really need it. --s
179
180 ----
181
182 I am ready to merge this, but I noticed one problem -- since `match_tagged`
183 now only matches pages with the tag linktype, a wiki will need to be
184 rebuilt on upgrade in order to get the linktype of existing tags in it
185 recorded. So there needs to be a NEWS item about this and
186 the postinst modified to force the rebuild.
187
188 > Done, although you'll need to plug in an appropriate version number when
189 > you release it. Is there a distinctive reminder string you grep for
190 > during releases? I've used `UNRELEASED` for now. --[[smcv]]
191
192 Also, the ready branch adds `typedlink()` to [[ikiwiki/pagespec]],
193 but you removed that feature as documented above.
194 --[[Joey]]
195
196 > [[Done]]. --s