#9096 closed enhancement (fixed)
wiki pre-commit hook
Reported by: | Owned by: | Christian Boos | |
---|---|---|---|
Priority: | normal | Milestone: | 0.12 |
Component: | wiki system | Version: | 0.12dev |
Severity: | normal | Keywords: | review |
Cc: | Branch: | ||
Release Notes: | |||
API Changes: | |||
Internal Changes: |
Description
Would be nice to have a feature of wiki pre-commit hook. In my trac.ini
file I would say something like this:
[wiki] pre_commit=/home/trac/pre-commit.sh
Every time anyone makes changes to any wiki page, this shell script is called with params:
pre-commit.sh "pagename" "comment" < "new content"
If the script returns empty string, everything is fine, and the changes are saved to wiki. If the result is not empty, it is interpreted like comments/errors/warnings to certain lines of the wiki page (or to the entire page). Every line will contain one comment, with a prefix (which could be omitted):
crit,7-9:itemized lists are disallowed in specification pages... err,14,32:syntax error, NAME expected... warn,19:it is recommended to use existing CamelCase entities... empty comment line, please use format required by DevelopmentGuidelines
Prefix has three fields (any one of them can be omitted):
- type of error (
err
by default) - lines interval (
7-9
) or line number (14
,19
), entire document by default - position in line (
32
), no position by default
Empty prefix means that this is an error related to entire page.
If and when pre-commit hook returns errors/warnings Trac disables changes and shows errors on their correspondent lines. Or on top of the page, if errors/warnings are related to the entire page.
Attachments (1)
Change History (14)
comment:1 by , 15 years ago
Component: | general → wiki system |
---|---|
Resolution: | → worksforme |
Status: | new → closed |
comment:2 by , 15 years ago
how about post-commit? can I implement a validation of a page when it's already in DB? some pages were created before the pre-commit hook was introduced, and might contain errors/warnings. I would like to have an ability to validate them during rendering.
is it possible as well? thanks.
comment:3 by , 15 years ago
Milestone: | → 0.12 |
---|---|
Resolution: | worksforme |
Status: | closed → reopened |
This seems like an use case for the other method of the IWikiPageManipulator interface, prepare_wiki_page(req, page, fields)
, which like the doc says is Not currently called, but should be provided for future compatibility.
This could be called before rendering, you can then use req.add_warning
and friends to inform the reader about the needed fixes (be careful to show them only to those who can actually edit the page and do something about it ;-) ).
-
trac/wiki/api.py
diff --git a/trac/wiki/api.py b/trac/wiki/api.py
a b class IWikiPageManipulator(Interface): 55 55 """ 56 56 57 57 def prepare_wiki_page(req, page, fields): 58 """Not currently called, but should be provided for future 59 compatibility.""" 58 """Validate a wiki page before rendering it. 59 60 `page` is the `WikiPage` being view and `fields` is currently `{}`. """ 60 61 61 62 def validate_wiki_page(req, page): 62 63 """Validate a wiki page after it's been populated from user input. 64 65 `page` is the `WikiPage` being edited. 63 66 64 67 Must return a list of `(field, message)` tuples, one for each problem 65 68 detected. `field` can be `None` to indicate an overall problem with the -
trac/wiki/web_ui.py
diff --git a/trac/wiki/web_ui.py b/trac/wiki/web_ui.py
a b class WikiModule(Component): 593 593 add_ctxtnav(req, _('Up'), req.href.wiki(parent)) 594 594 self._wiki_ctxtnav(req, page) 595 595 596 # Plugin content validation 597 for manipulator in self.page_manipulators: 598 manipulator.prepare_wiki_page(req, page, {}) 599 596 600 data.update({ 597 601 'context': context, 598 602 'latest_version': latest_page.version,
And here's an example validator (for testing, save as a file, place it below <env>/plugins
):
from trac.core import * from trac.wiki.api import IWikiPageManipulator from trac.web.chrome import add_warning class TracWikiValidator(Component): implements(IWikiPageManipulator) def validate(self, page): lines = page.text.splitlines() if not lines: return ["Page shouldn't be empty"] messages = [] if not lines[0].lstrip().startswith("= "): messages.append("First line must be the page's '= title ='") # etc. return messages # IWikiPageManipulator def prepare_wiki_page(self, req, page, fields): for message in self.validate(page): add_warning(req, message) def validate_wiki_page(self, req, page): for message in self.validate(page): yield ('text', message)
comment:4 by , 15 years ago
Keywords: | review added |
---|---|
Owner: | set to |
Status: | reopened → new |
follow-up: 6 comment:5 by , 15 years ago
The biggest problem for me here is to render the wiki page after validation. I understand how to call pre-commit/post-commit hook, and how to get results from it (thanks for your explanation and examples!). But then I would like to show errors/warnings right inside the lines/paragraphs they are related to.
In order to do this I have to change the way wiki page is rendered in HTML. I should start using <table>
instead of the normal way of rendering. I should add some new column with paragraph lines, etc.
I though that maybe it's better to integrate such a functionality into Trac core? Or it will require me to create a much more complex plugin than in your example. And in such a case maybe it's good to host it then in track-hacks.org?
follow-up: 7 comment:6 by , 15 years ago
Replying to team@…:
But then I would like to show errors/warnings right inside the lines/paragraphs they are related to. In order to do this I have to change the way wiki page is rendered in HTML. I should start using
<table>
instead of the normal way of rendering. I should add some new column with paragraph lines, etc.
This would require a custom subclass of WikiFormatter… plus an IStreamFilter to substitute the normal wikified output with your own. So yes, this is much more work than my simple example.
I though that maybe it's better to integrate such a functionality into Trac core?
Well, I suggest that you watch closely #4431 which is going to be one my priorities for the next release (0.13 that is). It should become much easier to analyse the content of wiki texts, as well as writing custom formatters or even interfering with existing formatter (for example, #1245 or validation like here).
Or it will require me to create a much more complex plugin than in your example. And in such a case maybe it's good to host it then in track-hacks.org?
If you start something like that, then I could also watch it and it could help me shape the way the future WikiEngine will work in order to make this kind of extension easier to write…
In the meantime, if you can see a more useful way how the existing prepare_wiki_page
could be used, let me know. For example, by returning a transformed page, which would not be saved but simply used for preparing the display, you could prepare your table in the wiki directly, see 0.12/WikiHtml.
follow-up: 8 comment:7 by , 15 years ago
In the meantime, if you can see a more useful way how the existing
prepare_wiki_page
could be used, let me know. For example, by returning a transformed page, which would not be saved but simply used for preparing the display, you could prepare your table in the wiki directly, see 0.12/WikiHtml.
This transformed page should actually be stuck into the fields dict under the 'text'
key, so that multiple filters could access it in turn. The page.text
stays unchanged with the original text.
by , 15 years ago
Attachment: | t9096-prepare_wiki_page-r9388.patch added |
---|
wiki web_ui: finally call IWikiPageManipulator.prepare_wiki_page(req, page, fields)
(now making the wiki text modifiable before formatting))
comment:8 by , 15 years ago
Replying to cboos:
This transformed page should actually be stuck into the fields dict under the
'text'
key, so that multiple filters could access it in turn. Thepage.text
stays unchanged with the original text.
Implemented in t9096-prepare_wiki_page-r9388.patch, please review.
comment:10 by , 15 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
No problem, I've tested it, and it works well too ;-)
Thanks for the review, committed as [9390].
follow-up: 12 comment:11 by , 15 years ago
Resolution: | fixed |
---|---|
Status: | closed → reopened |
cboos, could you please explain again, how exactly I can change wiki page content on-fly, before rendering. I want to be able to inject my plugin between Trac database and Trac wiki-to-html renderer. Every page, before converting from wiki to html will be passed to my plugin and it will change its wiki formatting (change in memory, not in DB). I feel that the answer is somewhere in this ticket, but I can't understand it without an example from you :)
Also, please mention which Trac version I should use.
comment:12 by , 15 years ago
Resolution: | → fixed |
---|---|
Status: | reopened → closed |
Replying to team@…:
could you please explain again, how exactly I can change wiki page content on-fly, before rendering.
Implement IWikiPageManipulator
, and in prepare_wiki_page()
, mutate fields['text']
. Initially, it contains the page content from the database. If you change it, the changed content will be rendered.
Also, please mention which Trac version I should use.
Current trunk (0.12dev).
You can program exactly that in a plugin by using the IWikiPageManipulator interface.
There, you can easily fetch whatever you want in the TracIni (e.g.
self.config['wiki'].get('pre-commit')
), then run an external script (e.g. using subprocess), and allow the submission to proceed or fail, in the latter case presenting a list of warnings to the user.