forked from github/kensanata.oddmuse
Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ca2bf3efb | ||
|
|
96bc4e14fa | ||
|
|
ad1059dbb2 | ||
|
|
508396d1d1 | ||
|
|
6d457ff87b | ||
|
|
860cb15324 | ||
|
|
56e76a4883 | ||
|
|
3fa8e0a6b0 | ||
|
|
4c4ab98d47 | ||
|
|
ca62cbf446 | ||
|
|
ef3bde90ac | ||
|
|
7771c541bb | ||
|
|
6adabedefe | ||
|
|
a776c67cd6 | ||
|
|
0ddc1770a3 | ||
|
|
44fa8cfb5a | ||
|
|
96c21c2240 | ||
|
|
1c25325257 | ||
|
|
fd5b4e84b1 | ||
|
|
9beff3748b | ||
|
|
87dedeab85 | ||
|
|
1e73ae22d3 | ||
|
|
5e9b02b5b1 | ||
|
|
deec99c353 | ||
|
|
d1b0ac4ccb | ||
|
|
06881768c3 | ||
|
|
8e1f6c92e3 | ||
|
|
1ebc5192ff | ||
|
|
7c52b7b4c2 | ||
|
|
2936ace022 | ||
|
|
4504ef43ac | ||
|
|
50b71adf2d | ||
|
|
8bb0475ba2 | ||
|
|
0e66af495b | ||
|
|
be6752116b | ||
|
|
36577490a7 | ||
|
|
8e4dcc2240 | ||
|
|
dc4de8212a | ||
|
|
ba2de753dd | ||
|
|
6dd1b7e125 | ||
|
|
aec6e9fb30 | ||
|
|
7b7d90f9f9 | ||
|
|
c937258922 | ||
|
|
08aa098203 | ||
|
|
b0fc1e4cc0 | ||
|
|
ca9eef8c09 | ||
|
|
b90b6e9651 | ||
|
|
f10bbb4f81 | ||
|
|
0116618e36 | ||
|
|
d864045815 | ||
|
|
294e5745e7 | ||
|
|
afc4f7ecba |
90
contrib/anonymize.pl
Normal file
90
contrib/anonymize.pl
Normal file
@@ -0,0 +1,90 @@
|
||||
#! /usr/bin/perl -w
|
||||
|
||||
# Copyright (C) 2013 Alex Schroeder <alex@gnu.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
=head1 Anonymize oldrc.log Files
|
||||
|
||||
This script will read your oldrc.log file and replace the host field
|
||||
with 'Anonymous'. This is what the main script started doing
|
||||
2013-11-30.
|
||||
|
||||
When you run this script, it sets the main lock to prevent maintenance
|
||||
from running. You can therefore run it on a live system.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
|
||||
sub verify_setup {
|
||||
if (not -f 'oldrc.log') {
|
||||
die "Run this script in your data directory.\n"
|
||||
. "The oldrc.log file should be in the same directory.\n";
|
||||
}
|
||||
if (not -d 'temp') {
|
||||
die "Run this script in your data directory.\n"
|
||||
. "The temp directory should be in the same directory.\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub request_lock {
|
||||
if (-d 'temp/lockmain') {
|
||||
die "The wiki is currently locked.\n"
|
||||
. "Rerun this script later.\n";
|
||||
}
|
||||
mkdir('temp/lockmain') or die "Could not create 'temp/lockmain'.\n"
|
||||
. "You probably don't have the file permissions necessary.\n";
|
||||
}
|
||||
|
||||
sub release_lock {
|
||||
rmdir('temp/lockmain') or die "Could not remove 'temp/lockmain'.\n"
|
||||
}
|
||||
|
||||
sub anonymize {
|
||||
open(F, 'oldrc.log') or die "Could not open 'oldrc.log' for reading.\n";
|
||||
open(B, '>oldrc.log~') or die "Could not open 'oldrc.log~' for writing.\n"
|
||||
. "I will not continue without having a backup available.\n";
|
||||
my $FS = "\x1e"; # The FS character is the RECORD SEPARATOR control char
|
||||
my @lines = ();
|
||||
while (my $line = <F>) {
|
||||
next if $line eq "\n"; # some rc.log files are broken and contain empty lines
|
||||
my ($ts, $id, $minor, $summary, $host, @rest) = split(/$FS/o, $line);
|
||||
if ($id eq '[[rollback]]') {
|
||||
# rollback markers are very different
|
||||
push(@lines, $line);
|
||||
} else {
|
||||
# anonymize
|
||||
push(@lines, join($FS, $ts, $id, $minor, $summary, 'Anonymous', @rest));
|
||||
}
|
||||
print B $line;
|
||||
}
|
||||
close(F);
|
||||
open(F, '>', 'oldrc.log') or die "Could not open 'oldrc.log' for writing.\n";
|
||||
for my $line (@lines) {
|
||||
print F $line; # @rest ends with a newline
|
||||
}
|
||||
close(F);
|
||||
print "Wrote anonymized 'oldrc.log'.\n";
|
||||
print "Saved a backup as 'oldrc.log~'\n";
|
||||
}
|
||||
|
||||
sub main {
|
||||
verify_setup();
|
||||
request_lock();
|
||||
anonymize();
|
||||
release_lock();
|
||||
}
|
||||
|
||||
main();
|
||||
698
contrib/oddmuse-curl.el
Normal file
698
contrib/oddmuse-curl.el
Normal file
@@ -0,0 +1,698 @@
|
||||
;;; oddmuse-curl.el -- edit pages on an Oddmuse wiki using curl
|
||||
;;
|
||||
;; Copyright (C) 2006–2013 Alex Schroeder <alex@gnu.org>
|
||||
;; (C) 2007 rubikitch <rubikitch@ruby-lang.org>
|
||||
;;
|
||||
;; Latest version:
|
||||
;; http://git.savannah.gnu.org/cgit/oddmuse.git/plain/contrib/oddmuse-curl.el
|
||||
;; Discussion, feedback:
|
||||
;; http://www.emacswiki.org/cgi-bin/wiki/OddmuseMode
|
||||
;;
|
||||
;; This program is free software: you can redistribute it and/or modify it
|
||||
;; under the terms of the GNU General Public License as published by the Free
|
||||
;; Software Foundation, either version 3 of the License, or (at your option)
|
||||
;; any later version.
|
||||
;;
|
||||
;; This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
;; more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU General Public License along
|
||||
;; with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; A simple mode to edit pages on Oddmuse wikis using Emacs and the command-line
|
||||
;; HTTP client `curl'.
|
||||
;;
|
||||
;; Since text formatting rules depend on the wiki you're writing for, the
|
||||
;; font-locking can only be an approximation.
|
||||
;;
|
||||
;; Put this file in a directory on your `load-path' and
|
||||
;; add this to your init file:
|
||||
;; (require 'oddmuse)
|
||||
;; (oddmuse-mode-initialize)
|
||||
;; And then use M-x oddmuse-edit to start editing.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(eval-when-compile
|
||||
(require 'cl)
|
||||
(require 'sgml-mode)
|
||||
(require 'skeleton))
|
||||
|
||||
(require 'goto-addr)
|
||||
(require 'info)
|
||||
|
||||
(defcustom oddmuse-directory "~/emacs/oddmuse"
|
||||
"Directory to store oddmuse pages."
|
||||
:type '(string)
|
||||
:group 'oddmuse)
|
||||
|
||||
(defcustom oddmuse-wikis
|
||||
'(("TestWiki" "http://www.emacswiki.org/cgi-bin/test"
|
||||
utf-8 "question" nil)
|
||||
("EmacsWiki" "http://www.emacswiki.org/cgi-bin/emacs"
|
||||
utf-8 "uihnscuskc" nil)
|
||||
("CommunityWiki" "http://www.communitywiki.org/cw"
|
||||
utf-8 "question" nil)
|
||||
("OddmuseWiki" "http://www.oddmuse.org/cgi-bin/oddmuse"
|
||||
utf-8 "question" nil)
|
||||
("CampaignWiki" "http://www.campaignwiki.org/wiki/NameOfYourWiki"
|
||||
utf-8 "ts" nil))
|
||||
"Alist mapping wiki names to URLs.
|
||||
|
||||
The elements in this list are:
|
||||
|
||||
NAME, the name of the wiki you provide when calling `oddmuse-edit'.
|
||||
|
||||
URL, the base URL of the script used when posting. If the site
|
||||
uses URL rewriting, then you need to extract the URL from the
|
||||
edit page. Emacs Wiki, for example, usually shows an URL such as
|
||||
http://www.emacswiki.org/emacs/Foo, but when you edit the page
|
||||
and examine the page source, you'll find this:
|
||||
|
||||
<form method=\"post\" action=\"http://www.emacswiki.org/cgi-bin/emacs\"
|
||||
enctype=\"multipart/form-data\" accept-charset=\"utf-8\"
|
||||
class=\"edit text\">...</form>
|
||||
|
||||
Thus, the correct value for URL is
|
||||
http://www.emacswiki.org/cgi-bin/emacs.
|
||||
|
||||
ENCODING, a symbol naming a coding-system.
|
||||
|
||||
SECRET, the secret the wiki uses if it has the Question Asker
|
||||
extension enabled. If you're getting 403 responses (edit denied)
|
||||
eventhough you can do it from a browser, examine your cookie in
|
||||
the browser. For Emacs Wiki, for example, my cookie says:
|
||||
|
||||
euihnscuskc%251e1%251eusername%251eAlexSchroeder
|
||||
|
||||
Use `split-string' and split by \"%251e\" and you'll see that
|
||||
\"euihnscuskc\" is the odd one out. The parameter name is the
|
||||
relevant string (its value is always 1).
|
||||
|
||||
USERNAME, your optional username to provide. It defaults to
|
||||
`oddmuse-username'."
|
||||
:type '(repeat (list (string :tag "Wiki")
|
||||
(string :tag "URL")
|
||||
(choice :tag "Coding System"
|
||||
(const :tag "default" utf-8)
|
||||
(symbol :tag "specify"
|
||||
:validate (lambda (widget)
|
||||
(unless (coding-system-p
|
||||
(widget-value widget))
|
||||
(widget-put widget :error
|
||||
"Not a valid coding system")))))
|
||||
(choice :tag "Secret"
|
||||
(const :tag "default" "question")
|
||||
(string :tag "specify"))
|
||||
(choice :tag "Username"
|
||||
(const :tag "default" nil)
|
||||
(string :tag "specify"))))
|
||||
:group 'oddmuse)
|
||||
|
||||
(defcustom oddmuse-username user-full-name
|
||||
"Username to use when posting.
|
||||
Setting a username is the polite thing to do."
|
||||
:type '(string)
|
||||
:group 'oddmuse)
|
||||
|
||||
(defcustom oddmuse-password ""
|
||||
"Password to use when posting.
|
||||
You only need this if you want to edit locked pages and you
|
||||
know an administrator password."
|
||||
:type '(string)
|
||||
:group 'oddmuse)
|
||||
|
||||
(defcustom oddmuse-use-always-minor nil
|
||||
"When t, set all the minor mode bit to all editions.
|
||||
This can be changed for each edition using `oddmuse-toggle-minor'."
|
||||
:type '(boolean)
|
||||
:group 'oddmuse)
|
||||
|
||||
(defvar oddmuse-get-command
|
||||
"curl --silent %w\"?action=browse;raw=2;\"id=%t"
|
||||
"Command to use for publishing pages.
|
||||
It must print the page to stdout.
|
||||
|
||||
%? '?' character
|
||||
%w URL of the wiki as provided by `oddmuse-wikis'
|
||||
%t URL encoded pagename, eg. HowTo, How_To, or How%20To")
|
||||
|
||||
(defvar oddmuse-history-command
|
||||
"curl --silent %w\"?action=history;raw=1;\"id=%t"
|
||||
"Command to use for reading the history of a page.
|
||||
It must print the history to stdout.
|
||||
|
||||
%? '?' character
|
||||
%w URL of the wiki as provided by `oddmuse-wikis'
|
||||
%t URL encoded pagename, eg. HowTo, How_To, or How%20To")
|
||||
|
||||
(defvar oddmuse-rc-command
|
||||
"curl --silent %w\"?action=rc;raw=1\""
|
||||
"Command to use for Recent Changes.
|
||||
It must print the RSS 3.0 text format to stdout.
|
||||
|
||||
%? '?' character
|
||||
%w URL of the wiki as provided by `oddmuse-wikis'")
|
||||
|
||||
(defvar oddmuse-post-command
|
||||
(concat "curl --silent --write-out '%{http_code}'"
|
||||
" --form title=%t"
|
||||
" --form summary=%s"
|
||||
" --form username=%u"
|
||||
" --form password=%p"
|
||||
" --form %q=1"
|
||||
" --form recent_edit=%m"
|
||||
" --form oldtime=%o"
|
||||
" --form text=\"<-\""
|
||||
" %w")
|
||||
"Command to use for publishing pages.
|
||||
It must accept the page on stdin.
|
||||
|
||||
%? '?' character
|
||||
%t pagename
|
||||
%s summary
|
||||
%u username
|
||||
%p password
|
||||
%q question-asker cookie
|
||||
%m minor edit
|
||||
%o oldtime, a timestamp provided by Oddmuse
|
||||
%w URL of the wiki as provided by `oddmuse-wikis'")
|
||||
|
||||
(defvar oddmuse-link-pattern
|
||||
"\\<[[:upper:]]+[[:lower:]]+\\([[:upper:]]+[[:lower:]]*\\)+\\>"
|
||||
"The pattern used for finding WikiName.")
|
||||
|
||||
(defvar oddmuse-wiki nil
|
||||
"The current wiki.
|
||||
Must match a key from `oddmuse-wikis'.")
|
||||
|
||||
(defvar oddmuse-page-name nil
|
||||
"Pagename of the current buffer.")
|
||||
|
||||
(defvar oddmuse-pages-hash (make-hash-table :test 'equal)
|
||||
"The wiki-name / pages pairs.")
|
||||
|
||||
(defvar oddmuse-index-get-command
|
||||
"curl --silent %w\"?action=index;raw=1\""
|
||||
"Command to use for publishing index pages.
|
||||
It must print the page to stdout.
|
||||
|
||||
%? '?' character
|
||||
%w URL of the wiki as provided by `oddmuse-wikis'
|
||||
")
|
||||
|
||||
(defvar oddmuse-minor nil
|
||||
"Is this edit a minor change?")
|
||||
|
||||
(defvar oddmuse-revision nil
|
||||
"The ancestor of the current page.
|
||||
This is used by Oddmuse to merge changes.")
|
||||
|
||||
(defun oddmuse-mode-initialize ()
|
||||
(add-to-list 'auto-mode-alist
|
||||
`(,(expand-file-name oddmuse-directory) . oddmuse-mode)))
|
||||
|
||||
(defun oddmuse-creole-markup ()
|
||||
"Implement markup rules for the Creole markup extension."
|
||||
(font-lock-add-keywords
|
||||
nil
|
||||
'(("^=[^=\n]+" 0 '(face info-title-1 help-echo "Creole H1")); = h1
|
||||
("^==[^=\n]+" 0 '(face info-title-2 help-echo "Creole H2")); == h2
|
||||
("^===[^=\n]+" 0 '(face info-title-3 help-echo "Creole H3")); === h3
|
||||
("^====+[^=\n]+" 0 '(face info-title-4 help-echo "Creole H4")); ====h4
|
||||
("\\_<//\\(.*\n\\)*?.*?//" 0 '(face italic help-echo "Creole italic")); //italic//
|
||||
("\\*\\*\\(.*\n\\)*?.*?\\*\\*" 0 '(face bold help-echo "Creole bold")); **bold**
|
||||
("__\\(.*\n\\)*?.*?__" 0 '(face underline help-echo "Creole underline")); __underline__
|
||||
("|+=?" 0 '(face font-lock-string-face help-echo "Creole table cell"))
|
||||
("\\\\\\\\[ \t]+" 0 '(face font-lock-warning-face help-echo "Creole line break"))
|
||||
("^#+ " 0 '(face font-lock-constant-face help-echo "Creole ordered list"))
|
||||
("^- " 0 '(face font-lock-constant-face help-echo "Creole ordered list")))))
|
||||
|
||||
(defun oddmuse-bbcode-markup ()
|
||||
"Implement markup rules for the bbcode markup extension."
|
||||
(font-lock-add-keywords
|
||||
nil
|
||||
`(("\\[b\\]\\(.*\n\\)*?.*?\\[/b\\]"
|
||||
0 '(face bold help-echo "BB code bold"))
|
||||
("\\[i\\]\\(.*\n\\)*?.*?\\[/i\\]"
|
||||
0 '(face italic help-echo "BB code italic"))
|
||||
("\\[u\\]\\(.*\n\\)*?.*?\\[/u\\]"
|
||||
0 '(face underline help-echo "BB code underline"))
|
||||
(,(concat "\\[url=" goto-address-url-regexp "\\]")
|
||||
0 '(face font-lock-builtin-face help-echo "BB code url"))
|
||||
("\\[/?\\(img\\|url\\)\\]"
|
||||
0 '(face font-lock-builtin-face help-echo "BB code url or img"))
|
||||
("\\[s\\(trike\\)?\\]\\(.*\n\\)*?.*?\\[/s\\(trike\\)?\\]"
|
||||
0 '(face strike help-echo "BB code strike"))
|
||||
("\\[/?\\(left\\|right\\|center\\)\\]"
|
||||
0 '(face font-lock-constant-face help-echo "BB code alignment")))))
|
||||
|
||||
(defun oddmuse-usemod-markup ()
|
||||
"Implement markup rules for the Usemod markup extension."
|
||||
(font-lock-add-keywords
|
||||
nil
|
||||
'(("^=[^=\n]+=$"
|
||||
0 '(face info-title-1 help-echo "Usemod H1"))
|
||||
("^==[^=\n]+==$"
|
||||
0 '(face info-title-2 help-echo "Usemod H2"))
|
||||
("^===[^=\n]+===$"
|
||||
0 '(face info-title-3 help-echo "Usemod H3"))
|
||||
("^====+[^=\n]+====$"
|
||||
0 '(face info-title-4 help-echo "Usemod H4"))
|
||||
("^ .+?$"
|
||||
0 '(face font-lock-comment-face help-echo "Usemod block"))
|
||||
("^[#]+ "
|
||||
0 '(face font-lock-constant-face help-echo "Usemod ordered list")))))
|
||||
|
||||
(defun oddmuse-usemod-html-markup ()
|
||||
"Implement markup rules for the HTML option in the Usemod markup extension."
|
||||
(font-lock-add-keywords
|
||||
nil
|
||||
'(("<\\(/?[a-z]+\\)" 1 '(face font-lock-function-name-face help-echo "Usemod HTML"))))
|
||||
(set (make-local-variable 'sgml-tag-alist)
|
||||
`(("b") ("code") ("em") ("i") ("strong") ("nowiki")
|
||||
("pre" \n) ("tt") ("u")))
|
||||
(set (make-local-variable 'skeleton-transformation) 'identity))
|
||||
|
||||
(defun oddmuse-extended-markup ()
|
||||
"Implement markup rules for the Markup extension."
|
||||
(font-lock-add-keywords
|
||||
nil
|
||||
'(("\\*\\w+[[:word:]-%.,:;\'\"!? ]*\\*"
|
||||
0 '(face bold help-echo "Markup bold"))
|
||||
("\\_</\\w+[[:word:]-%.,:;\'\"!? ]*/"
|
||||
0 '(face italic help-echo "Markup italic"))
|
||||
("_\\w+[[:word:]-%.,:;\'\"!? ]*_"
|
||||
0 '(face underline help-echo "Markup underline")))))
|
||||
|
||||
(defun oddmuse-basic-markup ()
|
||||
"Implement markup rules for the basic Oddmuse setup without extensions.
|
||||
This function should come come last in `oddmuse-markup-functions'
|
||||
because of such basic patterns as [.*] which are very generic."
|
||||
(font-lock-add-keywords
|
||||
nil
|
||||
`((,oddmuse-link-pattern
|
||||
0 '(face link help-echo "Basic wiki name"))
|
||||
("\\[\\[.*?\\]\\]"
|
||||
0 '(face link help-echo "Basic free link"))
|
||||
(,(concat "\\[" goto-address-url-regexp "\\( .+?\\)?\\]")
|
||||
0 '(face link help-echo "Basic external free link"))
|
||||
("^\\([*]+\\)"
|
||||
0 '(face font-lock-constant-face help-echo "Basic bullet list"))))
|
||||
(goto-address))
|
||||
|
||||
;; Should determine this automatically based on the version? And cache it per wiki?
|
||||
;; http://emacswiki.org/wiki?action=version
|
||||
(defvar oddmuse-markup-functions
|
||||
'(oddmuse-basic-markup
|
||||
oddmuse-extended-markup
|
||||
oddmuse-usemod-markup
|
||||
oddmuse-creole-markup
|
||||
oddmuse-bbcode-markup)
|
||||
"The list of functions to call when `oddmuse-mode' runs.
|
||||
Later functions take precedence because they call `font-lock-add-keywords'
|
||||
which adds the expressions to the front of the existing list.")
|
||||
|
||||
(define-derived-mode oddmuse-mode text-mode "Odd"
|
||||
"Simple mode to edit wiki pages.
|
||||
|
||||
Use \\[oddmuse-follow] to follow links. With prefix, allows you
|
||||
to specify the target page yourself.
|
||||
|
||||
Use \\[oddmuse-post] to post changes. With prefix, allows you to
|
||||
post the page to a different wiki.
|
||||
|
||||
Use \\[oddmuse-edit] to edit a different page. With prefix,
|
||||
forces a reload of the page instead of just popping to the buffer
|
||||
if you are already editing the page.
|
||||
|
||||
Customize `oddmuse-wikis' to add more wikis to the list.
|
||||
|
||||
Font-locking is controlled by `oddmuse-markup-functions'.
|
||||
|
||||
\\{oddmuse-mode-map}"
|
||||
(mapc 'funcall oddmuse-markup-functions)
|
||||
(font-lock-mode 1)
|
||||
(when buffer-file-name
|
||||
(set (make-local-variable 'oddmuse-wiki)
|
||||
(file-name-nondirectory
|
||||
(substring (file-name-directory buffer-file-name) 0 -1)))
|
||||
(set (make-local-variable 'oddmuse-page-name)
|
||||
(file-name-nondirectory buffer-file-name)))
|
||||
(set (make-local-variable 'oddmuse-minor)
|
||||
oddmuse-use-always-minor)
|
||||
(set (make-local-variable 'oddmuse-revision)
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(if (looking-at
|
||||
"\\([0-9]+\\) # Do not delete this line when editing!\n")
|
||||
(prog1 (match-string 1)
|
||||
(replace-match "")
|
||||
(set-buffer-modified-p nil)))))
|
||||
(setq indent-tabs-mode nil))
|
||||
|
||||
(autoload 'sgml-tag "sgml-mode" t)
|
||||
|
||||
(define-key oddmuse-mode-map (kbd "C-c C-t") 'sgml-tag)
|
||||
(define-key oddmuse-mode-map (kbd "C-c C-o") 'oddmuse-follow)
|
||||
(define-key oddmuse-mode-map (kbd "C-c C-m") 'oddmuse-toggle-minor)
|
||||
(define-key oddmuse-mode-map (kbd "C-c C-c") 'oddmuse-post)
|
||||
(define-key oddmuse-mode-map (kbd "C-x C-v") 'oddmuse-revert)
|
||||
(define-key oddmuse-mode-map (kbd "C-c C-f") 'oddmuse-edit)
|
||||
(define-key oddmuse-mode-map (kbd "C-c C-i") 'oddmuse-insert-pagename)
|
||||
(define-key oddmuse-mode-map (kbd "C-c C-h") 'oddmuse-history)
|
||||
(define-key oddmuse-mode-map (kbd "C-c C-r") 'oddmuse-rc)
|
||||
|
||||
;; This has been stolen from simple-wiki-edit
|
||||
;;;###autoload
|
||||
(defun oddmuse-toggle-minor (&optional arg)
|
||||
"Toggle minor mode state."
|
||||
(interactive)
|
||||
(let ((num (prefix-numeric-value arg)))
|
||||
(cond
|
||||
((or (not arg) (equal num 0))
|
||||
(setq oddmuse-minor (not oddmuse-minor)))
|
||||
((> num 0) (set 'oddmuse-minor t))
|
||||
((< num 0) (set 'oddmuse-minor nil)))
|
||||
(message "Oddmuse Minor set to %S" oddmuse-minor)
|
||||
oddmuse-minor))
|
||||
|
||||
(add-to-list 'minor-mode-alist
|
||||
'(oddmuse-minor " [MINOR]"))
|
||||
|
||||
(defun oddmuse-format-command (command)
|
||||
"Internal: Substitute oddmuse format flags according to `url',
|
||||
`oddmuse-page-name', `summary', `oddmuse-username', `question',
|
||||
`oddmuse-password', `oddmuse-revision'."
|
||||
(let ((hatena "?"))
|
||||
(dolist (pair '(("%w" . url)
|
||||
("%t" . oddmuse-page-name)
|
||||
("%s" . summary)
|
||||
("%u" . oddmuse-username)
|
||||
("%m" . oddmuse-minor)
|
||||
("%p" . oddmuse-password)
|
||||
("%q" . question)
|
||||
("%o" . oddmuse-revision)
|
||||
("%\\?" . hatena)))
|
||||
(when (and (boundp (cdr pair)) (stringp (symbol-value (cdr pair))))
|
||||
(setq command (replace-regexp-in-string (car pair)
|
||||
(shell-quote-argument
|
||||
(symbol-value (cdr pair)))
|
||||
command t t))))
|
||||
command))
|
||||
|
||||
(defun oddmuse-read-wiki-and-pagename (&optional required default)
|
||||
"Read an wikiname and a pagename of `oddmuse-wikis' with completion.
|
||||
If provided, REQUIRED and DEFAULT are passed along to `oddmuse-read-pagename'."
|
||||
(let ((wiki (completing-read "Wiki: " oddmuse-wikis nil t oddmuse-wiki)))
|
||||
(list wiki (oddmuse-read-pagename wiki required default))))
|
||||
|
||||
;;;###autoload
|
||||
(defun oddmuse-history (wiki pagename)
|
||||
"Show a page's history on a wiki using `view-mode'.
|
||||
WIKI is the name of the wiki as defined in `oddmuse-wikis',
|
||||
PAGENAME is the pagename of the page you want the history of.
|
||||
Use a prefix argument to force a reload of the page."
|
||||
(interactive (oddmuse-read-wiki-and-pagename t oddmuse-page-name))
|
||||
(let ((name (concat wiki ":" pagename " [history]")))
|
||||
(if (and (get-buffer name)
|
||||
(not current-prefix-arg))
|
||||
(pop-to-buffer (get-buffer name))
|
||||
(let* ((wiki-data (assoc wiki oddmuse-wikis))
|
||||
(url (nth 1 wiki-data))
|
||||
(oddmuse-page-name pagename)
|
||||
(command (oddmuse-format-command oddmuse-history-command))
|
||||
(coding (nth 2 wiki-data))
|
||||
(buf (get-buffer-create name)))
|
||||
(set-buffer buf)
|
||||
(erase-buffer)
|
||||
(let ((max-mini-window-height 1))
|
||||
(shell-command command buf))
|
||||
(pop-to-buffer buf)
|
||||
(goto-address)
|
||||
(view-mode)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun oddmuse-edit (wiki pagename)
|
||||
"Edit a page on a wiki.
|
||||
WIKI is the name of the wiki as defined in `oddmuse-wikis',
|
||||
PAGENAME is the pagename of the page you want to edit.
|
||||
Use a prefix argument to force a reload of the page."
|
||||
(interactive (oddmuse-read-wiki-and-pagename))
|
||||
(make-directory (concat oddmuse-directory "/" wiki) t)
|
||||
(let ((name (concat wiki ":" pagename)))
|
||||
(if (and (get-buffer name)
|
||||
(not current-prefix-arg))
|
||||
(pop-to-buffer (get-buffer name))
|
||||
(let* ((wiki-data (assoc wiki oddmuse-wikis))
|
||||
(url (nth 1 wiki-data))
|
||||
(oddmuse-page-name pagename)
|
||||
(command (oddmuse-format-command oddmuse-get-command))
|
||||
(coding (nth 2 wiki-data))
|
||||
(buf (find-file-noselect (concat oddmuse-directory "/" wiki "/"
|
||||
pagename)))
|
||||
(coding-system-for-read coding)
|
||||
(coding-system-for-write coding))
|
||||
(set-buffer buf)
|
||||
(unless (equal name (buffer-name)) (rename-buffer name))
|
||||
(erase-buffer)
|
||||
(let ((max-mini-window-height 1))
|
||||
(oddmuse-run "Loading" command buf nil))
|
||||
(pop-to-buffer buf)
|
||||
(oddmuse-mode)))))
|
||||
|
||||
(defalias 'oddmuse-go 'oddmuse-edit)
|
||||
|
||||
(autoload 'word-at-point "thingatpt")
|
||||
|
||||
;;;###autoload
|
||||
(defun oddmuse-follow (arg)
|
||||
"Figure out what page we need to visit
|
||||
and call `oddmuse-edit' on it."
|
||||
(interactive "P")
|
||||
(let ((pagename (if arg (oddmuse-read-pagename oddmuse-wiki)
|
||||
(oddmuse-pagename-at-point))))
|
||||
(oddmuse-edit (or oddmuse-wiki
|
||||
(read-from-minibuffer "URL: "))
|
||||
pagename)))
|
||||
|
||||
(defun oddmuse-current-free-link-contents ()
|
||||
"Free link contents if the point is between [[ and ]]."
|
||||
(save-excursion
|
||||
(let* ((pos (point))
|
||||
(start (search-backward "[[" nil t))
|
||||
(end (search-forward "]]" nil t)))
|
||||
(and start end (>= end pos)
|
||||
(replace-regexp-in-string
|
||||
" " "_"
|
||||
(buffer-substring (+ start 2) (- end 2)))))))
|
||||
|
||||
(defun oddmuse-pagename-at-point ()
|
||||
"Page name at point."
|
||||
(let ((pagename (word-at-point)))
|
||||
(cond ((oddmuse-current-free-link-contents))
|
||||
((oddmuse-wikiname-p pagename)
|
||||
pagename)
|
||||
(t
|
||||
(error "No link found at point")))))
|
||||
|
||||
(defun oddmuse-wikiname-p (pagename)
|
||||
"Whether PAGENAME is WikiName or not."
|
||||
(let (case-fold-search)
|
||||
(string-match (concat "^" oddmuse-link-pattern "$") pagename)))
|
||||
|
||||
;; (oddmuse-wikiname-p "WikiName")
|
||||
;; (oddmuse-wikiname-p "not-wikiname")
|
||||
;; (oddmuse-wikiname-p "notWikiName")
|
||||
|
||||
(defun oddmuse-run (mesg command buf on-region)
|
||||
"Print MESG and run COMMAND on the current buffer.
|
||||
MESG should be appropriate for the following uses:
|
||||
\"MESG...\"
|
||||
\"MESG...done\"
|
||||
\"MESG failed: REASON\"
|
||||
Save outpout in BUF and report an appropriate error.
|
||||
ON-REGION indicates whether the commands runs on the region
|
||||
such as when posting, or whether it just runs by itself such
|
||||
as when loading a page."
|
||||
(message "%s..." mesg)
|
||||
;; If ON-REGION, the resulting HTTP CODE is found in BUF, so check
|
||||
;; that, too.
|
||||
(if (and (= 0 (if on-region
|
||||
(shell-command-on-region (point-min) (point-max) command buf)
|
||||
(shell-command command buf)))
|
||||
(or (not on-region)
|
||||
(string= "302" (with-current-buffer buf
|
||||
(buffer-string)))))
|
||||
(message "%s...done" mesg)
|
||||
(let ((err "Unknown error"))
|
||||
(with-current-buffer buf
|
||||
(when (re-search-forward "<h1>\\(.*?\\)\\.?</h1>" nil t)
|
||||
(setq err (match-string 1))))
|
||||
(error "%s...%s" mesg err))))
|
||||
|
||||
;;;###autoload
|
||||
(defun oddmuse-post (summary)
|
||||
"Post the current buffer to the current wiki.
|
||||
The current wiki is taken from `oddmuse-wiki'."
|
||||
(interactive "sSummary: ")
|
||||
;; when using prefix or on a buffer that is not in oddmuse-mode
|
||||
(when (or (not oddmuse-wiki) current-prefix-arg)
|
||||
(set (make-local-variable 'oddmuse-wiki)
|
||||
(completing-read "Wiki: " oddmuse-wikis nil t)))
|
||||
(when (not oddmuse-page-name)
|
||||
(set (make-local-variable 'oddmuse-page-name)
|
||||
(read-from-minibuffer "Pagename: " (buffer-name))))
|
||||
(let* ((list (assoc oddmuse-wiki oddmuse-wikis))
|
||||
(url (nth 1 list))
|
||||
(oddmuse-minor (if oddmuse-minor "on" "off"))
|
||||
(coding (nth 2 list))
|
||||
(coding-system-for-read coding)
|
||||
(coding-system-for-write coding)
|
||||
(question (nth 3 list))
|
||||
(oddmuse-username (or (nth 4 list)
|
||||
oddmuse-username))
|
||||
(command (oddmuse-format-command oddmuse-post-command))
|
||||
(buf (get-buffer-create " *oddmuse-response*"))
|
||||
(text (buffer-string)))
|
||||
(and buffer-file-name (basic-save-buffer))
|
||||
(oddmuse-run "Posting" command buf t)))
|
||||
|
||||
(defun oddmuse-make-completion-table (wiki)
|
||||
"Create pagename completion table for WIKI.
|
||||
If available, return precomputed one."
|
||||
(or (gethash wiki oddmuse-pages-hash)
|
||||
(oddmuse-compute-pagename-completion-table wiki)))
|
||||
|
||||
(defun oddmuse-compute-pagename-completion-table (&optional wiki-arg)
|
||||
"Really fetch the list of pagenames from WIKI.
|
||||
This command is used to reflect new pages to `oddmuse-pages-hash'."
|
||||
(interactive)
|
||||
(let* ((wiki (or wiki-arg
|
||||
(completing-read "Wiki: " oddmuse-wikis nil t oddmuse-wiki)))
|
||||
(url (cadr (assoc wiki oddmuse-wikis)))
|
||||
(command (oddmuse-format-command oddmuse-index-get-command))
|
||||
table)
|
||||
(message "Getting index of all pages...")
|
||||
(prog1
|
||||
(setq table (split-string (shell-command-to-string command)))
|
||||
(puthash wiki table oddmuse-pages-hash)
|
||||
(message "Getting index of all pages...done"))))
|
||||
|
||||
(defun oddmuse-read-pagename (wiki &optional require default)
|
||||
"Read a pagename of WIKI with completion.
|
||||
Optional arguments REQUIRE and DEFAULT are passed on to `completing-read'.
|
||||
Typically you would use t and a `oddmuse-page-name', if that makes sense."
|
||||
(completing-read (if default
|
||||
(concat "Pagename [" default "]: ")
|
||||
"Pagename: ")
|
||||
(oddmuse-make-completion-table wiki)
|
||||
nil require nil nil default))
|
||||
|
||||
;;;###autoload
|
||||
(defun oddmuse-rc (&optional include-minor-edits)
|
||||
"Show Recent Changes.
|
||||
With universal argument, reload."
|
||||
(interactive "P")
|
||||
(let* ((wiki (or oddmuse-wiki
|
||||
(completing-read "Wiki: " oddmuse-wikis nil t)))
|
||||
(name (concat "*" wiki " RC*")))
|
||||
(if (and (get-buffer name)
|
||||
(not current-prefix-arg))
|
||||
(pop-to-buffer (get-buffer name))
|
||||
(let* ((wiki-data (assoc wiki oddmuse-wikis))
|
||||
(url (nth 1 wiki-data))
|
||||
(command (oddmuse-format-command oddmuse-rc-command))
|
||||
(coding (nth 2 wiki-data))
|
||||
(buf (get-buffer-create name))
|
||||
(coding-system-for-read coding)
|
||||
(coding-system-for-write coding))
|
||||
(set-buffer buf)
|
||||
(unless (equal name (buffer-name)) (rename-buffer name))
|
||||
(erase-buffer)
|
||||
(let ((max-mini-window-height 1))
|
||||
(oddmuse-run "Load recent changes" command buf nil))
|
||||
(oddmuse-rc-buffer)
|
||||
(set (make-local-variable 'oddmuse-wiki) wiki)))))
|
||||
|
||||
(defun oddmuse-rc-buffer ()
|
||||
"Parse current buffer as RSS 3.0 and display it correctly."
|
||||
(let (result)
|
||||
(dolist (item (cdr (split-string (buffer-string) "\n\n")));; skip first item
|
||||
(let ((data (mapcar (lambda (line)
|
||||
(when (string-match "^\\(.*?\\): \\(.*\\)" line)
|
||||
(cons (match-string 1 line)
|
||||
(match-string 2 line))))
|
||||
(split-string item "\n"))))
|
||||
(setq result (cons data result))))
|
||||
(erase-buffer)
|
||||
(dolist (item (nreverse result))
|
||||
(insert "[[" (cdr (assoc "title" item)) "]] – "
|
||||
(cdr (assoc "generator" item)) "\n"))
|
||||
(goto-char (point-min))
|
||||
(oddmuse-mode)))
|
||||
|
||||
;;;###autoload
|
||||
(defun oddmuse-revert ()
|
||||
"Revert this oddmuse page."
|
||||
(interactive)
|
||||
(let ((current-prefix-arg 4))
|
||||
(oddmuse-edit oddmuse-wiki oddmuse-page-name)))
|
||||
|
||||
;;;###autoload
|
||||
(defun oddmuse-insert-pagename (pagename)
|
||||
"Insert a PAGENAME of current wiki with completion."
|
||||
(interactive (list (oddmuse-read-pagename oddmuse-wiki)))
|
||||
(insert pagename))
|
||||
|
||||
;;;###autoload
|
||||
(defun emacswiki-post (&optional pagename summary)
|
||||
"Post the current buffer to the EmacsWiki.
|
||||
If this command is invoked interactively: with prefix argument,
|
||||
prompts for pagename, otherwise set pagename as basename of
|
||||
`buffer-file-name'.
|
||||
|
||||
This command is intended to post current EmacsLisp program easily."
|
||||
(interactive)
|
||||
(let* ((oddmuse-wiki "EmacsWiki")
|
||||
(oddmuse-page-name (or pagename
|
||||
(and (not current-prefix-arg)
|
||||
buffer-file-name
|
||||
(file-name-nondirectory buffer-file-name))
|
||||
(oddmuse-read-pagename oddmuse-wiki)))
|
||||
(summary (or summary (read-string "Summary: "))))
|
||||
(oddmuse-post summary)))
|
||||
|
||||
(defun oddmuse-url (wiki pagename)
|
||||
"Get the URL of oddmuse wiki."
|
||||
(condition-case v
|
||||
(concat (or (cadr (assoc wiki oddmuse-wikis)) (error)) "/" pagename)
|
||||
(error nil)))
|
||||
|
||||
;;;###autoload
|
||||
(defun oddmuse-browse-page (wiki pagename)
|
||||
"Ask a WWW browser to load an Oddmuse page.
|
||||
WIKI is the name of the wiki as defined in `oddmuse-wikis',
|
||||
PAGENAME is the pagename of the page you want to browse."
|
||||
(interactive (oddmuse-read-wiki-and-pagename))
|
||||
(browse-url (oddmuse-url wiki pagename)))
|
||||
|
||||
;;;###autoload
|
||||
(defun oddmuse-browse-this-page ()
|
||||
"Ask a WWW browser to load current oddmuse page."
|
||||
(interactive)
|
||||
(oddmuse-browse-page oddmuse-wiki oddmuse-page-name))
|
||||
|
||||
;;;###autoload
|
||||
(defun oddmuse-kill-url ()
|
||||
"Make the URL of current oddmuse page the latest kill in the kill ring."
|
||||
(interactive)
|
||||
(kill-new (oddmuse-url oddmuse-wiki oddmuse-page-name)))
|
||||
|
||||
(provide 'oddmuse)
|
||||
|
||||
;;; oddmuse-curl.el ends here
|
||||
@@ -228,6 +228,12 @@ div.commentshown {
|
||||
p.comment {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
div.comment {
|
||||
font-size: 14pt;
|
||||
}
|
||||
div.comment h2 {
|
||||
margin-top: 5em;
|
||||
}
|
||||
/* comment pages with username, homepage, and email subscription */
|
||||
.comment span { display: block; }
|
||||
.comment span label { display: inline-block; width: 10em; }
|
||||
@@ -380,12 +386,12 @@ div.left p + p { display:table-caption; caption-side:bottom; }
|
||||
p.table a { float:left; width:20ex; }
|
||||
p.table + p { clear:both; }
|
||||
|
||||
/* no bleeding
|
||||
@media screen {
|
||||
/* no bleeding */
|
||||
div.content, div.rc {
|
||||
overflow:hidden;
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
@media print {
|
||||
body {
|
||||
|
||||
@@ -108,6 +108,35 @@ a:active {
|
||||
color:#a41;
|
||||
background-color: inherit;
|
||||
}
|
||||
.button {
|
||||
display: inline-block;
|
||||
font-size: 150%;
|
||||
cursor: pointer;
|
||||
padding: 0.3em 0.5em;
|
||||
text-shadow: 0px -1px 0px #ccc;
|
||||
background-color: #cfa;
|
||||
border: 1px solid #9d8;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0px 1px 3px white inset,
|
||||
0px 1px 3px black;
|
||||
}
|
||||
.button a {
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* table of contents */
|
||||
.toc {
|
||||
font-size: smaller;
|
||||
border-left: 1em solid #886;
|
||||
}
|
||||
.toc ol {
|
||||
list-style-type: none;
|
||||
padding-left: 1em;
|
||||
}
|
||||
.toc a {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* images with links, captions, etc */
|
||||
div.image { display: inline; margin: 1em; font-size: 90%; text-align: center; }
|
||||
|
||||
207
css/oddmuse-2013.css
Normal file
207
css/oddmuse-2013.css
Normal file
@@ -0,0 +1,207 @@
|
||||
@font-face {
|
||||
font-family: 'Gentium Basic';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Gentium Basic'), local('GentiumBasic'), url(http://themes.googleusercontent.com/static/fonts/gentiumbasic/v5/KCktj43blvLkhOTolFn-MVhr3SzZVY8L1R-AhaesIwA.woff) format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Gentium Basic';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Gentium Basic Bold'), local('GentiumBasic-Bold'), url(http://themes.googleusercontent.com/static/fonts/gentiumbasic/v5/2qL6yulgGf0wwgOp-UqGyKuvVGpDTHxx0YlM6XbRIFE.woff) format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Gentium Basic';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local('Gentium Basic Italic'), local('GentiumBasic-Italic'), url(http://themes.googleusercontent.com/static/fonts/gentiumbasic/v5/qoFz4NSMaYC2UmsMAG3lyajIwExuvJl80GezUi4i-sM.woff) format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Gentium Basic';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: local('Gentium Basic Bold Italic'), local('GentiumBasic-BoldItalic'), url(http://themes.googleusercontent.com/static/fonts/gentiumbasic/v5/8N9-c_aQDJ8LbI1NGVMrwjBWbH-5CKom31QWlI8zOIM.woff) format('woff');
|
||||
}
|
||||
|
||||
body {
|
||||
background:#fff;
|
||||
padding:2% 5%;
|
||||
margin:0;
|
||||
font-family: "Gentium Basic", "Bookman Old Style", "Times New Roman", serif;
|
||||
font-size: 18pt;
|
||||
}
|
||||
|
||||
div.header h1 {
|
||||
margin-top:2ex;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #a00;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #d88;
|
||||
}
|
||||
|
||||
div.header h1 a:hover, h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover,
|
||||
a:hover, span.caption a.image:hover {
|
||||
background:#fee;
|
||||
}
|
||||
|
||||
img.logo {
|
||||
float: right;
|
||||
clear: right;
|
||||
border-style:none;
|
||||
background-color:#fff;
|
||||
}
|
||||
|
||||
img {
|
||||
padding: 0.5em;
|
||||
margin: 0 1em;
|
||||
}
|
||||
|
||||
a.image:hover {
|
||||
background:inherit;
|
||||
}
|
||||
|
||||
a.image:hover img {
|
||||
background:#fee;
|
||||
}
|
||||
|
||||
/* a.definition soll aussehen wie h2 */
|
||||
h2, p a.definition {
|
||||
display:block;
|
||||
clear:both;
|
||||
}
|
||||
|
||||
/* Such Link im h1 soll nicht auffallen. */
|
||||
h1, h2, h3, h4, h1 a, h1 a:visited, p a.definition {
|
||||
color:#666;
|
||||
font-size: 30pt;
|
||||
font-weight: normal;
|
||||
margin: 4ex 0 1ex 0;
|
||||
padding: 0;
|
||||
border-bottom: 1px solid #000;
|
||||
}
|
||||
|
||||
h3, h4 {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
div.diff {
|
||||
padding: 1em 3em;
|
||||
}
|
||||
div.old {
|
||||
background-color:#FFFFAF;
|
||||
}
|
||||
div.new {
|
||||
background-color:#CFFFCF;
|
||||
}
|
||||
div.old p, div.new p {
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
div.refer { padding-left:5%; padding-right:5%; font-size:smaller; }
|
||||
div[class="content refer"] p { margin-top:2em; }
|
||||
div.content div.refer hr { display:none; }
|
||||
div.content div.refer { padding:0; font-size:medium; }
|
||||
div.content div.refer p { margin:0; }
|
||||
div.refer a { display:block; }
|
||||
table.history { border-style:none; }
|
||||
td.history { border-style:none; }
|
||||
|
||||
table.user {
|
||||
border-style: none;
|
||||
margin-left: 3em;
|
||||
}
|
||||
table.user tr td {
|
||||
border-style: none;
|
||||
padding:0.5ex 1ex;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight:bold;
|
||||
}
|
||||
dd {
|
||||
margin-bottom:1ex;
|
||||
}
|
||||
|
||||
textarea { width:100%; height:80%; }
|
||||
textarea#summary { height: 3em; }
|
||||
|
||||
div.image span.caption {
|
||||
margin: 0 1em;
|
||||
}
|
||||
li img, img.smiley, .noborder img {
|
||||
border:none;
|
||||
padding:0;
|
||||
margin:0;
|
||||
background:#fff;
|
||||
color:#000;
|
||||
}
|
||||
/* Google +1 */
|
||||
a#plus1 img {
|
||||
background-color: #fff;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
div.header img, div.footer img { border:0; padding:0; margin:0; }
|
||||
|
||||
.left { float:left; }
|
||||
.right { float:right; }
|
||||
div.left .left, div.right .right {
|
||||
float:none;
|
||||
}
|
||||
.center { text-align:center; }
|
||||
|
||||
span.author {
|
||||
color: #501;
|
||||
}
|
||||
span.bar a {
|
||||
padding-right:1ex;
|
||||
}
|
||||
|
||||
.rc .author {
|
||||
color: #655;
|
||||
}
|
||||
|
||||
.rc strong {
|
||||
font-weight: normal;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.rc li {
|
||||
position:relative;
|
||||
padding: 1ex 0;
|
||||
}
|
||||
|
||||
hr {
|
||||
border:none;
|
||||
color:black;
|
||||
background-color:#000;
|
||||
height:2px;
|
||||
margin-top:2ex;
|
||||
}
|
||||
|
||||
div.footer hr {
|
||||
height:4px;
|
||||
margin: 2em 0 1ex 0;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 0.5em;
|
||||
margin-left: 1em;
|
||||
margin-right: 2em;
|
||||
white-space: pre;
|
||||
overflow:hidden;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
div.footer hr {
|
||||
clear:both;
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/anchors.pl">anchors.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Comments_on_Local_Anchor_Extension">Comments on Local Anchor Extension</a></p>';
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/anchors.pl">anchors.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Local_Anchor_Extension">Local Anchor Extension</a></p>';
|
||||
|
||||
push(@MyRules, \&AnchorsRule);
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ sub DoBanHosts {
|
||||
print GetHeader('', Ts('Ban Contributors to %s', NormalToFree($id)));
|
||||
SetParam('rcidonly', $id);
|
||||
SetParam('all', 1);
|
||||
SetParam('showedit', 1);
|
||||
my %contrib = ();
|
||||
for my $line (GetRcLines()) {
|
||||
$contrib{$line->[4]}->{$line->[5]} = 1 if $line->[4];
|
||||
|
||||
@@ -16,6 +16,8 @@ $ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git
|
||||
|
||||
push(@MyRules, \&bbCodeRule);
|
||||
|
||||
$RuleOrder{\&bbCodeRule} = 100; # must come after PortraitSupportRule
|
||||
|
||||
use vars qw($bbBlock);
|
||||
my %bbTitle = qw(h1 1 h2 1 h3 1 h4 1 h5 1 h6 1);
|
||||
|
||||
@@ -36,6 +38,8 @@ sub bbCodeRule {
|
||||
. qq{font-style: normal;"}); }
|
||||
elsif ($tag eq 's' or $tag eq 'strike') {
|
||||
return AddHtmlEnvironment('del'); }
|
||||
elsif ($tag eq 'tt') {
|
||||
return AddHtmlEnvironment('tt'); }
|
||||
elsif ($tag eq 'sub') {
|
||||
return AddHtmlEnvironment('sub'); }
|
||||
elsif ($tag eq 'sup') {
|
||||
@@ -99,7 +103,8 @@ sub bbCodeRule {
|
||||
%translate = qw{b b i i u em color em size em font span url a
|
||||
quote blockquote h1 h1 h2 h2 h3 h3 h4 h4 h5 h5
|
||||
h6 h6 center div left div right div list ul
|
||||
s del strike del sub sub sup sup highlight strong};
|
||||
s del strike del sub sub sup sup highlight strong
|
||||
tt tt};
|
||||
# closing a block level element closes all elements
|
||||
if ($bbBlock eq $translate{$tag}) {
|
||||
/\G([ \t]*\n)*/cg; # eat whitespace after closing block level element
|
||||
|
||||
@@ -24,7 +24,20 @@ sub FixEncoding {
|
||||
OpenPage($id);
|
||||
my $text = $Page{text};
|
||||
utf8::decode($text);
|
||||
Save($id, $text, 'fix encoding', 1) if $text ne $Page{text};
|
||||
Save($id, $text, T('Fix character encoding'), 1) if $text ne $Page{text};
|
||||
ReleaseLock();
|
||||
ReBrowsePage($id);
|
||||
}
|
||||
|
||||
$Action{'fix-escaping'} = \&FixEscaping;
|
||||
|
||||
sub FixEscaping {
|
||||
my $id = shift;
|
||||
ValidIdOrDie($id);
|
||||
RequestLockOrError();
|
||||
OpenPage($id);
|
||||
my $text = UnquoteHtml($Page{text});
|
||||
Save($id, $text, T('Fix HTML escapes'), 1) if $text ne $Page{text};
|
||||
ReleaseLock();
|
||||
ReBrowsePage($id);
|
||||
}
|
||||
@@ -33,8 +46,12 @@ push(@MyAdminCode, \&FixEncodingMenu);
|
||||
|
||||
sub FixEncodingMenu {
|
||||
my ($id, $menuref, $restref) = @_;
|
||||
if ($id) {
|
||||
if ($id && GetParam('username')) {
|
||||
push(@$menuref,
|
||||
ScriptLink('action=fix-encoding;id=' . UrlEncode($id), T('Fix page encoding')));
|
||||
ScriptLink('action=fix-encoding;id=' . UrlEncode($id),
|
||||
T('Fix character encoding')));
|
||||
push(@$menuref,
|
||||
ScriptLink('action=fix-escaping;id=' . UrlEncode($id),
|
||||
T('Fix HTML escapes')));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ You can change this expiry time by setting C<$LnCacheHours>.
|
||||
|
||||
=cut
|
||||
|
||||
push (MyMaintenance, \&LnMaintenance);
|
||||
push (@MyMaintenance, \&LnMaintenance);
|
||||
|
||||
sub LnMaintenance {
|
||||
if (opendir(DIR, $RssDir)) { # cleanup if they should expire anyway
|
||||
|
||||
@@ -71,19 +71,21 @@ sub MacFixEncoding {
|
||||
$UseGrep = 0 if GetParam('search', '') =~ /[x{0080}-\x{fffd}]/;
|
||||
|
||||
# the rest is only necessary if using namespaces.pl
|
||||
return unless defined %Namespaces;
|
||||
while (my ($key, $value) = each %Namespaces) {
|
||||
delete $Namespaces{$key};
|
||||
return unless %Namespaces;
|
||||
my %hash = ();
|
||||
for my $key (keys %Namespaces) {
|
||||
utf8::decode($key);
|
||||
$key = NFC($key);
|
||||
$Namespaces{$key} = $NamespaceRoot . '/' . $key . '/';
|
||||
$hash{$key} = $NamespaceRoot . '/' . $key . '/';
|
||||
}
|
||||
while (my ($key, $value) = each %InterSite) {
|
||||
delete $InterSite{$key};
|
||||
%Namespaces = %hash;
|
||||
%hash = ();
|
||||
for my $key (keys %InterSite) {
|
||||
utf8::decode($key);
|
||||
$key = NFC($key);
|
||||
$InterSite{$key} = $Namespaces{$key} if $Namespaces{$key};
|
||||
$hash{$key} = $Namespaces{$key} if $Namespaces{$key};
|
||||
}
|
||||
%InterSite = %hash;
|
||||
}
|
||||
|
||||
# for drafts.pl
|
||||
|
||||
138
modules/markdown-rule.pl
Normal file
138
modules/markdown-rule.pl
Normal file
@@ -0,0 +1,138 @@
|
||||
#! /usr/bin/perl
|
||||
# Copyright (C) 2014 Alex Schroeder <alex@gnu.org>
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/markdown-rule.pl">markdown-rule.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Markdown_Rule_Extension">Markdown Rule Extension</a></p>';
|
||||
|
||||
push(@MyRules, \&MarkdownRule);
|
||||
# Since we want this package to be a simple add-on, we try and avoid
|
||||
# all conflicts by going *last*. The use of # for numbered lists by
|
||||
# Usemod conflicts with the use of # for headings, for example.
|
||||
$RuleOrder{\&MarkdownRule} = 200;
|
||||
|
||||
# http://daringfireball.net/projects/markdown/syntax
|
||||
# https://help.github.com/articles/markdown-basics
|
||||
# https://help.github.com/articles/github-flavored-markdown
|
||||
|
||||
sub MarkdownRule {
|
||||
# atx headers
|
||||
if ($bol and m~\G(\s*\n)*(#{1,6})[ \t]*~cg) {
|
||||
my $header_depth = length($2);
|
||||
return CloseHtmlEnvironments()
|
||||
. AddHtmlEnvironment("h" . $header_depth);
|
||||
}
|
||||
# end atx header at a newline
|
||||
elsif ((InElement('h1') or InElement('h2') or InElement('h3') or
|
||||
InElement('h4') or InElement('h5') or InElement('h6'))
|
||||
and m/\G\n/cg) {
|
||||
return CloseHtmlEnvironments()
|
||||
. AddHtmlEnvironment("p");
|
||||
}
|
||||
# setext headers
|
||||
elsif ($bol and m/\G((\s*\n)*(.+?)[ \t]*\n(-+|=+)[ \t]*\n)/gc) {
|
||||
return CloseHtmlEnvironments()
|
||||
. (substr($4,0,1) eq '=' ? $q->h2($3) : $q->h3($3))
|
||||
. AddHtmlEnvironment('p');
|
||||
}
|
||||
# > blockquote
|
||||
# with continuation
|
||||
elsif ($bol and m/\G>/gc) {
|
||||
return CloseHtmlEnvironments()
|
||||
. AddHtmlEnvironment('blockquote');
|
||||
}
|
||||
# ***bold and italic***
|
||||
elsif (not InElement('strong') and not InElement('em') and m/\G\*\*\*/cg) {
|
||||
return AddHtmlEnvironment('em') . AddHtmlEnvironment('strong');
|
||||
}
|
||||
# **bold**
|
||||
elsif (m/\G\*\*/cg) {
|
||||
return AddOrCloseHtmlEnvironment('strong');
|
||||
}
|
||||
# *italic*
|
||||
elsif (m/\G\*/cg) {
|
||||
return AddOrCloseHtmlEnvironment('em');
|
||||
}
|
||||
# ~~strikethrough~~ (deleted)
|
||||
elsif (m/\G~~/cg) {
|
||||
return AddOrCloseHtmlEnvironment('del');
|
||||
}
|
||||
# - bullet list
|
||||
elsif ($bol and m/\G(\s*\n)*-[ \t]*/cg
|
||||
or InElement('li') and m/\G(\s*\n)+-[ \t]*/cg) {
|
||||
return CloseHtmlEnvironment('li')
|
||||
. OpenHtmlEnvironment('ul',1) . AddHtmlEnvironment('li');
|
||||
}
|
||||
# 1. numbered list
|
||||
elsif ($bol and m/\G(\s*\n)*\d+\.[ \t]*/cg
|
||||
or InElement('li') and m/\G(\s*\n)+\d+\.[ \t]*/cg) {
|
||||
return CloseHtmlEnvironment('li')
|
||||
. OpenHtmlEnvironment('ol',1) . AddHtmlEnvironment('li');
|
||||
}
|
||||
# beginning of a table
|
||||
elsif ($bol and !InElement('table') and m/\G\|/cg) {
|
||||
# warn pos . " beginning of a table";
|
||||
return OpenHtmlEnvironment('table',1)
|
||||
. AddHtmlEnvironment('tr')
|
||||
. AddHtmlEnvironment('th');
|
||||
}
|
||||
# end of a row and beginning of a new row
|
||||
elsif (InElement('table') and m/\G\|?\n\|/cg) {
|
||||
# warn pos . " end of a row and beginning of a new row";
|
||||
return CloseHtmlEnvironment('tr')
|
||||
. AddHtmlEnvironment('tr')
|
||||
. AddHtmlEnvironment('td');
|
||||
}
|
||||
# otherwise the table ends
|
||||
elsif (InElement('table') and m/\G\|?(\n|$)/cg) {
|
||||
# warn pos . " otherwise the table ends";
|
||||
return CloseHtmlEnvironment('table')
|
||||
. AddHtmlEnvironment('p');
|
||||
}
|
||||
# continuation of the first row
|
||||
elsif (InElement('th') and m/\G\|/cg) {
|
||||
# warn pos . " continuation of the first row";
|
||||
return CloseHtmlEnvironment('th')
|
||||
. AddHtmlEnvironment('th');
|
||||
}
|
||||
# continuation of other rows
|
||||
elsif (InElement('td') and m/\G\|/cg) {
|
||||
# warn pos . " continuation of other rows";
|
||||
return CloseHtmlEnvironment('td')
|
||||
. AddHtmlEnvironment('td');
|
||||
}
|
||||
# whitespace indentation = code
|
||||
elsif ($bol and m/\G(\s*\n)*( .+)\n?/gc) {
|
||||
my $str = substr($2, 4);
|
||||
while (m/\G( .*)\n?/gc) {
|
||||
$str .= "\n" . substr($1, 4);
|
||||
}
|
||||
return OpenHtmlEnvironment('pre',1) . $str; # always level 1
|
||||
}
|
||||
# ``` = code
|
||||
elsif ($bol and m/\G```[ \t]*\n(.*?)\n```[ \t]*(\n|$)/gcs) {
|
||||
return CloseHtmlEnvironments() . $q->pre($1)
|
||||
. AddHtmlEnvironment("p");
|
||||
}
|
||||
# [an example](http://example.com/ "Title")
|
||||
elsif (m/\G\[(.+?)\]\($FullUrlPattern(\s+"(.+?)")?\)/goc) {
|
||||
my ($text, $url, $title) = ($1, $2, $4);
|
||||
$url =~ /^($UrlProtocols)/;
|
||||
my %params;
|
||||
$params{-href} = $url;
|
||||
$params{-class} = "url $1";
|
||||
$params{-title} = $title if $title;
|
||||
return $q->a(\%params, $text);
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Alex Schroeder <alex@gnu.org>
|
||||
# Copyright (C) 2003–2013 Alex Schroeder <alex@gnu.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -303,8 +303,12 @@ resolved to the same target (the local page), which is unexpected.
|
||||
=cut
|
||||
|
||||
|
||||
push(@IndexOptions, ['near', T('Include near pages'), 0,
|
||||
\&ListNearPages]);
|
||||
# IndexOptions must be set in MyInitVariables for translations to
|
||||
# work.
|
||||
push(@MyInitVariables, sub {
|
||||
push(@IndexOptions, ['near', T('Include near pages'), 0,
|
||||
\&ListNearPages]);
|
||||
});
|
||||
|
||||
sub ListNearPages {
|
||||
my %pages = %NearSource;
|
||||
|
||||
@@ -231,7 +231,8 @@ sub NewReCaptchaDoPost {
|
||||
print $q->start_div({-class=>'error'});
|
||||
print $q->p(T('You did not answer correctly.'));
|
||||
print GetFormStart(), ReCaptchaGetQuestion(1),
|
||||
(map { $q->hidden($_, '') }
|
||||
(map { $q->input({-type=>'hidden', -name=>$_,
|
||||
-value=>UnquoteHtml(GetParam($_))}) }
|
||||
qw(title text oldtime summary recent_edit aftertext)), $q->end_form;
|
||||
print $q->end_div();
|
||||
PrintFooter();
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
# Copyright (C) 2004, 2005, 2006 Alex Schroeder <alex@emacswiki.org>
|
||||
# Copyright (C) 2004-2013 Alex Schroeder <alex@gnu.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
# This program is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the
|
||||
# Free Software Foundation, Inc.
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/static-copy.pl">static-copy.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Static_Copy_Extension">Static Copy Extension</a></p>';
|
||||
|
||||
@@ -63,7 +59,11 @@ sub StaticWriteFiles {
|
||||
local *ScriptLink = *StaticScriptLink;
|
||||
local *GetDownloadLink = *StaticGetDownloadLink;
|
||||
foreach my $id (AllPagesList()) {
|
||||
StaticWriteFile($id);
|
||||
if ($StaticAlways > 1
|
||||
or GetParam('html', 0)
|
||||
or PageIsUploadedFile($id)) {
|
||||
StaticWriteFile($id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,16 +122,16 @@ sub StaticFileName {
|
||||
sub StaticWriteFile {
|
||||
my $id = shift;
|
||||
my $raw = GetParam('raw', 0);
|
||||
my $html = GetParam('html', 1);
|
||||
my $filename = StaticFileName($id);
|
||||
OpenPage($id);
|
||||
my ($mimetype, $encoding, $data) = $Page{text} =~ /^\#FILE ([^ \n]+) ?([^ \n]*)\n(.*)/s;
|
||||
return unless $html or $data;
|
||||
open(F,"> $StaticDir/$filename") or ReportError(Ts('Cannot write %s', $filename));
|
||||
if ($data) {
|
||||
StaticFile($id, $mimetype, $data);
|
||||
} elsif ($html) {
|
||||
StaticHtml($id);
|
||||
} else {
|
||||
print "no data for ";
|
||||
}
|
||||
close(F);
|
||||
chmod 0644,"$StaticDir/$filename";
|
||||
|
||||
@@ -672,7 +672,7 @@ ordinary changes
|
||||
normale Änderungen
|
||||
Matching page names:
|
||||
Übereinstimmende Seitennamen:
|
||||
Fix page encoding
|
||||
Fix character encoding
|
||||
Zeichenkodierung korrigieren
|
||||
no summary available
|
||||
keine Zusammenfassug vorhanden
|
||||
|
||||
@@ -50,15 +50,15 @@ test_page(get_page('action=browse id=HomePage username=Alex'),
|
||||
SKIP: {
|
||||
|
||||
eval { require LWP::UserAgent; };
|
||||
skip "LWP::UserAgent not installed", 5 if $@;
|
||||
skip "LWP::UserAgent not installed", 7 if $@;
|
||||
|
||||
eval { require HTTP::Cookies; };
|
||||
skip "HTTP::Cookies not installed", 5 if $@;
|
||||
skip "HTTP::Cookies not installed", 7 if $@;
|
||||
|
||||
my $wiki = 'http://localhost/cgi-bin/wiki.pl';
|
||||
my $ua = LWP::UserAgent->new;
|
||||
my $response = $ua->get("$wiki?action=version");
|
||||
skip("No wiki running at $wiki", 5)
|
||||
skip("No wiki running at $wiki", 7)
|
||||
unless $response->is_success;
|
||||
|
||||
$ua = LWP::UserAgent->new;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env perl
|
||||
# Copyright (C) 2008 Weakish Jiang <weakish@gmail.com>
|
||||
# Copyright (C) 2009 Alex Schroeder <alex@gnu.com>
|
||||
# Copyright (C) 2009-2013 Alex Schroeder <alex@gnu.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
@@ -56,8 +56,6 @@ H<sub>2</sub>O
|
||||
<dl><dt><strong>dt1</strong></dt><dd>dd1</dd></dl>
|
||||
; {{{dt1}}}\n:dd1
|
||||
<dl><dt><code>dt1</code></dt><dd>dd1</dd></dl>
|
||||
;[[http://www.toto.com|toto]] \n :Site of my friend Toto
|
||||
<dl><dt><a class="url http outside" href="http://www.toto.com">toto</a></dt><dd>Site of my friend Toto</dd></dl>
|
||||
; {{{[[http://www.toto.com|toto]]}}} \n : Site of my friend Toto
|
||||
<dl><dt><code>[[http://www.toto.com|toto]]</code></dt><dd>Site of my friend Toto</dd></dl>
|
||||
; what if we have {{{[[http://example.com]]}}} and {{{[[ftp://example.org]]}}}\n: And {{{[[http://example.net]]}}}
|
||||
@@ -75,6 +73,8 @@ H<sub>2</sub>O
|
||||
EOT
|
||||
|
||||
xpath_run_tests(split('\n',<<'EOT'));
|
||||
;[[http://www.toto.com|toto]] \n :Site of my friend Toto
|
||||
//dl/dt[a[@class="url http outside"][@href="http://www.toto.com"][text()="toto"]]/following-sibling::dd[text()="Site of my friend Toto"]
|
||||
##http://example.com##
|
||||
//code/a[@class="url http"][@href="http://example.com"][text()="http://example.com"]
|
||||
##[[wiki page]] will work##
|
||||
|
||||
8
t/css.t
8
t/css.t
@@ -24,13 +24,13 @@ clear_pages();
|
||||
|
||||
# Default
|
||||
xpath_test(get_page('HomePage'),
|
||||
'//link[@type="text/css"][@rel="stylesheet"][@href="http://www.oddmuse.org/oddmuse.css"]');
|
||||
'//link[@type="text/css"][@rel="stylesheet"][@href="http://www.oddmuse.org/default.css"]');
|
||||
|
||||
# StyleSheetPage
|
||||
update_page('css', "em { font-weight: bold; }", 'some css', 0, 1);
|
||||
$page = get_page('HomePage');
|
||||
negative_xpath_test($page,
|
||||
'//link[@type="text/css"][@rel="stylesheet"][@href="http://www.oddmuse.org/oddmuse.css"]');
|
||||
'//link[@type="text/css"][@rel="stylesheet"][@href="http://www.oddmuse.org/default.css"]');
|
||||
xpath_test($page,
|
||||
'//link[@type="text/css"][@rel="stylesheet"][@href="http://localhost/wiki.pl?action=browse;id=css;raw=1;mime-type=text/css"]');
|
||||
|
||||
@@ -38,7 +38,7 @@ xpath_test($page,
|
||||
AppendStringToFile($ConfigFile, "\$StyleSheet = 'http://example.org/test.css';\n");
|
||||
$page = get_page('HomePage');
|
||||
negative_xpath_test($page,
|
||||
'//link[@type="text/css"][@rel="stylesheet"][@href="http://www.oddmuse.org/oddmuse.css"]',
|
||||
'//link[@type="text/css"][@rel="stylesheet"][@href="http://www.oddmuse.org/default.css"]',
|
||||
'//link[@type="text/css"][@rel="stylesheet"][@href="http://localhost/wiki.pl?action=browse;id=css;raw=1;mime-type=text/css"]');
|
||||
xpath_test($page,
|
||||
'//link[@type="text/css"][@rel="stylesheet"][@href="http://example.org/test.css"]');
|
||||
@@ -46,7 +46,7 @@ xpath_test($page,
|
||||
# Parameter
|
||||
$page = get_page('action=browse id=HomePage css=http://example.org/my.css');
|
||||
negative_xpath_test($page,
|
||||
'//link[@type="text/css"][@rel="stylesheet"][@href="http://www.oddmuse.org/oddmuse.css"]',
|
||||
'//link[@type="text/css"][@rel="stylesheet"][@href="http://www.oddmuse.org/default.css"]',
|
||||
'//link[@type="text/css"][@rel="stylesheet"][@href="http://localhost/wiki.pl?action=browse;id=css;raw=1;mime-type=text/css"]',
|
||||
'//link[@type="text/css"][@rel="stylesheet"][@href="http://example.org/test.css"]');
|
||||
xpath_test($page,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2012 Alex Schroeder <alex@gnu.org>
|
||||
# Copyright (C) 2012–2013 Alex Schroeder <alex@gnu.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
require 't/test.pl';
|
||||
package OddMuse;
|
||||
use Test::More tests => 12;
|
||||
use Test::More tests => 22;
|
||||
use utf8; # tests contain UTF-8 characters and it matters
|
||||
|
||||
clear_pages();
|
||||
@@ -26,14 +26,19 @@ test_page_negative(get_page('action=admin'), 'action=fix-encoding');
|
||||
|
||||
# make sure no menu shows up if the page does not exists
|
||||
|
||||
test_page(get_page('action=admin id=foo'), 'action=fix-encoding;id=foo');
|
||||
test_page_negative(get_page('action=admin id=foo'),
|
||||
'action=fix-encoding;id=foo',
|
||||
'action=fix-escaping;id=foo');
|
||||
|
||||
# make sure nothing is saved if the page does not exist
|
||||
|
||||
test_page(get_page('action=fix-encoding id=Example'),
|
||||
'Location: http://localhost/wiki.pl/Example');
|
||||
|
||||
test_page_negative(get_page('action=rc showedit=1'), 'fix encoding');
|
||||
test_page(get_page('action=fix-escaping id=Example'),
|
||||
'Location: http://localhost/wiki.pl/Example');
|
||||
|
||||
test_page_negative(get_page('action=rc all=1 showedit=1'), 'fix');
|
||||
|
||||
# make sure nothing is saved if there is no change
|
||||
|
||||
@@ -43,14 +48,25 @@ test_page(update_page('Example', 'Pilgerstätte für die Göttin'),
|
||||
test_page(get_page('action=fix-encoding id=Example'),
|
||||
'Location: http://localhost/wiki.pl/Example');
|
||||
|
||||
test_page_negative(get_page('action=rc showedit=1'), 'fix encoding');
|
||||
test_page(get_page('action=fix-escaping id=Example'),
|
||||
'Location: http://localhost/wiki.pl/Example');
|
||||
|
||||
# the menu shows up if the page exists
|
||||
test_page_negative(get_page('action=rc all=1 showedit=1'),
|
||||
'Fix Character encoding');
|
||||
|
||||
test_page(get_page('action=admin id=Example'),
|
||||
'action=fix-encoding;id=Example');
|
||||
# the menu doesn't show up if the page exists
|
||||
|
||||
# here is an actual page you need to fix
|
||||
test_page_negative(get_page('action=admin id=Example'),
|
||||
'action=fix-encoding;id=Example',
|
||||
'action=fix-escaping;id=Example');
|
||||
|
||||
# the menu does show up if the page exists and a username is set
|
||||
|
||||
test_page(get_page('action=admin id=Example username=Alex'),
|
||||
'action=fix-encoding;id=Example',
|
||||
'action=fix-escaping;id=Example');
|
||||
|
||||
# here is an actual page with a character encoding error you need to fix
|
||||
|
||||
test_page(update_page('Example', 'Pilgerstätte für die Göttin',
|
||||
'borked encoding'),
|
||||
@@ -62,4 +78,20 @@ test_page(get_page('action=fix-encoding id=Example'),
|
||||
test_page(get_page('Example'),
|
||||
'Pilgerstätte für die Göttin');
|
||||
|
||||
test_page(get_page('action=rc showedit=1'), 'fix encoding');
|
||||
test_page(get_page('action=rc showedit=1'),
|
||||
'Fix character encoding');
|
||||
|
||||
# here is an actual page with an HTML escaping error you need to fix
|
||||
|
||||
test_page(update_page('Example', '&lt;b&gt;bold&lt;/b&gt;',
|
||||
'borked escaping'),
|
||||
'&lt;b&gt;bold&lt;/b&gt;');
|
||||
|
||||
test_page(get_page('action=fix-escaping id=Example'),
|
||||
'Location: http://localhost/wiki.pl/Example');
|
||||
|
||||
test_page(get_page('Example'),
|
||||
'<b>bold</b>');
|
||||
|
||||
test_page(get_page('action=rc showedit=1'),
|
||||
'Fix HTML escapes');
|
||||
|
||||
97
t/markdown-rule.t
Normal file
97
t/markdown-rule.t
Normal file
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env perl
|
||||
# Copyright (C) 2014 Alex Schroeder <alex@gnu.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
require 't/test.pl';
|
||||
package OddMuse;
|
||||
use Test::More tests => 34;
|
||||
clear_pages();
|
||||
|
||||
add_module('markdown-rule.pl');
|
||||
|
||||
# ApplyRules strips trailing newlines, so write tests accordingly.
|
||||
run_tests(split(/\n/,<<'EOT'));
|
||||
1. one
|
||||
<ol><li>one</li></ol>
|
||||
2. one
|
||||
2. one
|
||||
1. one\n2. two
|
||||
<ol><li>one</li><li>two</li></ol>
|
||||
1. one\n\n2. two
|
||||
<ol><li>one</li><li>two</li></ol>
|
||||
- one
|
||||
<ul><li>one</li></ul>
|
||||
- one\n-- Alex
|
||||
<ul><li>one</li><li>- Alex</li></ul>
|
||||
- one\n\n- Alex
|
||||
<ul><li>one</li><li>Alex</li></ul>
|
||||
this is ***bold italic*** yo!
|
||||
this is <em><strong>bold italic</strong></em> yo!
|
||||
this is **bold**
|
||||
this is <strong>bold</strong>
|
||||
**bold**
|
||||
<strong>bold</strong>
|
||||
*italic*
|
||||
<em>italic</em>
|
||||
foo\nbar
|
||||
foo bar
|
||||
foo\n===\nbar
|
||||
<h2>foo</h2><p>bar</p>
|
||||
foo\n---\nbar
|
||||
<h3>foo</h3><p>bar</p>
|
||||
foo\n=== bar
|
||||
foo === bar
|
||||
foo\n=\nbar
|
||||
<h2>foo</h2><p>bar</p>
|
||||
# foo
|
||||
<h1>foo</h1>
|
||||
## foo
|
||||
<h2>foo</h2>
|
||||
### foo
|
||||
<h3>foo</h3>
|
||||
#### foo
|
||||
<h4>foo</h4>
|
||||
##### foo
|
||||
<h5>foo</h5>
|
||||
###### foo
|
||||
<h6>foo</h6>
|
||||
####### foo
|
||||
<h6># foo</h6>
|
||||
## foo ##
|
||||
<h2>foo ##</h2>
|
||||
bar\n##foo\nbar
|
||||
bar <h2>foo</h2><p>bar</p>
|
||||
```\nfoo\n```\nbar
|
||||
<pre>foo</pre><p>bar</p>
|
||||
```\nfoo\n```
|
||||
<pre>foo</pre>
|
||||
```\nfoo\n``` bar
|
||||
``` foo ``` bar
|
||||
|a|b|\n|c|d|\nbar
|
||||
<table><tr><th>a</th><th>b</th></tr><tr><td>c</td><td>d</td></tr></table><p>bar</p>
|
||||
|a|b|\n|c|d|
|
||||
<table><tr><th>a</th><th>b</th></tr><tr><td>c</td><td>d</td></tr></table>
|
||||
|a
|
||||
<table><tr><th>a</th></tr></table>
|
||||
foo ~~bar~~
|
||||
foo <del>bar</del>
|
||||
EOT
|
||||
|
||||
xpath_run_tests(split('\n',<<'EOT'));
|
||||
[an example](http://example.com/ "Title")
|
||||
//a[@class="url http"][@href="http://example.com/"][@title="Title"][text()="an example"]
|
||||
[an example](http://example.com/)
|
||||
//a[@class="url http"][@href="http://example.com/"][text()="an example"]
|
||||
EOT
|
||||
20
t/rc.t
20
t/rc.t
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2006, 2007, 2008, 2009 Alex Schroeder <alex@gnu.org>
|
||||
# Copyright (C) 2006–20013 Alex Schroeder <alex@gnu.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
require 't/test.pl';
|
||||
package OddMuse;
|
||||
use Test::More tests => 83;
|
||||
use Test::More tests => 86;
|
||||
|
||||
clear_pages();
|
||||
|
||||
@@ -23,14 +23,22 @@ clear_pages();
|
||||
# with nothing appropriate in them.
|
||||
|
||||
test_page(get_page('action=rc raw=1'), 'title: Wiki');
|
||||
WriteStringToFile($RcFile, "1${FS}test${FS}${FS}test${FS}${FS}${FS}1${FS}${FS}\n");
|
||||
# ts, id, minor, summary, host, username, revision, languages, cluster
|
||||
WriteStringToFile($RcFile, "1${FS}test${FS}${FS}test${FS}127.0.0.1${FS}${FS}1${FS}${FS}\n");
|
||||
test_page_negative(get_page('action=rc raw=1'), 'title: test');
|
||||
test_page(get_page('action=rc raw=1 from=1'), 'title: Wiki', 'title: test',
|
||||
'description: test', 'link: http://localhost/wiki.pl/test',
|
||||
'description: test', 'generator: 127.0.0.1',
|
||||
'link: http://localhost/wiki.pl/test',
|
||||
'last-modified: 1970-01-01T00:00Z', 'revision: 1');
|
||||
ok(rename($RcFile, $RcOldFile), "renamed $RcFile to $RcOldFile");
|
||||
|
||||
test_page(get_page('action=maintain'),
|
||||
'Moving part of the RecentChanges log file',
|
||||
'Moving 1 log entries');
|
||||
|
||||
# make sure it was anonymized
|
||||
test_page(get_page('action=rc raw=1 from=1'), 'title: Wiki', 'title: test',
|
||||
'description: test', 'link: http://localhost/wiki.pl/test',
|
||||
'description: test', 'generator: Anonymous',
|
||||
'link: http://localhost/wiki.pl/test',
|
||||
'last-modified: 1970-01-01T00:00Z', 'revision: 1');
|
||||
|
||||
# Test that newlines are in fact stripped
|
||||
|
||||
38
t/recaptcha.t
Normal file
38
t/recaptcha.t
Normal file
@@ -0,0 +1,38 @@
|
||||
# Copyright (C) 2013 Alex Schroeder <alex@gnu.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
require 't/test.pl';
|
||||
package OddMuse;
|
||||
use Test::More tests => 5;
|
||||
use utf8; # test data is UTF-8 and it matters
|
||||
|
||||
clear_pages();
|
||||
$ENV{'REMOTE_ADDR'}='127.0.0.1';
|
||||
add_module('recaptcha.pl');
|
||||
|
||||
# The recaptcha module used to corrupt UTF-8 encoding and HTML
|
||||
# escaping.
|
||||
|
||||
# non-existing page and no permission
|
||||
test_page(get_page('title=SandBox text="<b>K%C3%BChlschrank</b>"'),
|
||||
'Status: 403',
|
||||
'<b>Kühlschrank</b>');
|
||||
# update it as an admin
|
||||
test_page(update_page('SandBox', '<b>Kühlschrank</b>', undef, undef, 1),
|
||||
'<b>Kühlschrank</b>');
|
||||
# existing page and no permission
|
||||
test_page(get_page('title=SandBox text="<b>K%C3%BChlschrank-test</b>"'),
|
||||
'Status: 403',
|
||||
'<b>Kühlschrank-test</b>');
|
||||
@@ -70,8 +70,8 @@ update_page('NicePage', 'Evil content.', 'vandal one');
|
||||
update_page('OtherPage', 'Other evil content.', 'another vandal');
|
||||
update_page('NicePage', 'Bad content.', 'vandal two');
|
||||
update_page('EvilPage', 'Spam!', 'vandal three');
|
||||
update_page('AnotherEvilPage', 'More Spam!', 'vandal four');
|
||||
update_page('AnotherEvilPage', 'Still More Spam!', 'vandal five');
|
||||
update_page('AnotherEvilPage', 'More Minor Spam!', 'vandal four', 1);
|
||||
update_page('AnotherEvilPage', 'Still More Minor Spam!', 'vandal five', 1);
|
||||
update_page('MinorPage', 'Ramtatam', 'testerror', 1);
|
||||
|
||||
test_page(get_page('NicePage'), 'Bad content');
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
require 't/test.pl';
|
||||
package OddMuse;
|
||||
use Test::More tests => 16;
|
||||
use Test::More tests => 29;
|
||||
clear_pages();
|
||||
|
||||
add_module('static-copy.pl');
|
||||
@@ -111,6 +111,18 @@ xpath_test(update_page('HomePage', "Static: [[image:Trogs]]"),
|
||||
. '[@src="/static/Trogs.svgz"]'
|
||||
. '[@alt="Trogs"]');
|
||||
|
||||
# delete the static pages and regenerate it
|
||||
ok(unlink("$DataDir/static/Trogs.svgz"), "Deleted $DataDir/static/Trogs.svgz");
|
||||
ok(unlink("$DataDir/static/Logo.png"), "Deleted $DataDir/static/Logo.png");
|
||||
test_page(get_page('action=static raw=1 pwd=foo'), "Trogs", "Logo");
|
||||
ok(-f "$DataDir/static/Trogs.svgz", "$DataDir/static/Trogs.svgz exists");
|
||||
ok(-f "$DataDir/static/Logo.png", "$DataDir/static/Logo.png exists");
|
||||
ok(! -f "$DataDir/static/HomePage.html", "$DataDir/static/HomePage.html does not exist");
|
||||
test_page(get_page('action=static raw=1 pwd=foo html=1'), "Trogs", "Logo", "HomePage");
|
||||
ok(-f "$DataDir/static/Trogs.svgz", "$DataDir/static/Trogs.svgz exists");
|
||||
ok(-f "$DataDir/static/Logo.png", "$DataDir/static/Logo.png exists");
|
||||
ok(-f "$DataDir/static/HomePage.html", "$DataDir/static/HomePage.html exists");
|
||||
|
||||
# Make sure spaces are translated to underscores (fixed in image.pl)
|
||||
add_module('image.pl');
|
||||
|
||||
|
||||
11
t/test.pl
11
t/test.pl
@@ -32,7 +32,16 @@ $UseConfig = 0; # don't read module files
|
||||
$DataDir = 'test-data';
|
||||
$ENV{WikiDataDir} = $DataDir;
|
||||
require 'wiki.pl';
|
||||
$ENV{PATH} = '/usr/local/bin:' . $ENV{PATH}; # location of perl?
|
||||
|
||||
# Try to guess which Perl we should be using. Since we loaded wiki.pl,
|
||||
# our $ENV{PATH} is set to /bin:/usr/bin in order to find diff and
|
||||
# grep.
|
||||
if ($ENV{PERLBREW_PATH}) {
|
||||
$ENV{PATH} = $ENV{PERLBREW_PATH} . ':' . $ENV{PATH};
|
||||
} elsif (-f '/usr/local/bin/perl') {
|
||||
$ENV{PATH} = '/usr/local/bin:' . $ENV{PATH};
|
||||
}
|
||||
|
||||
Init();
|
||||
use vars qw($redirect);
|
||||
|
||||
|
||||
65
wiki.pl
65
wiki.pl
@@ -159,7 +159,7 @@ $DocumentHeader = qq(<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN")
|
||||
. qq( "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n)
|
||||
. qq(<html xmlns="http://www.w3.org/1999/xhtml">);
|
||||
# Checkboxes at the end of the index.
|
||||
@IndexOptions = (['pages', T('Include normal pages'), 1, \&AllPagesList]);
|
||||
@IndexOptions = ();
|
||||
# Display short comments below the GotoBar for special days
|
||||
# Example: %SpecialDays = ('1-1' => 'New Year', '1-2' => 'Next Day');
|
||||
%SpecialDays = ();
|
||||
@@ -306,6 +306,7 @@ sub InitVariables { # Init global session variables for mod_perl!
|
||||
@MyRules = sort {$RuleOrder{$a} <=> $RuleOrder{$b}} @MyRules; # default is 0
|
||||
ReportError(Ts('Cannot create %s', $DataDir) . ": $!", '500 INTERNAL SERVER ERROR')
|
||||
unless -d $DataDir;
|
||||
@IndexOptions = (['pages', T('Include normal pages'), 1, \&AllPagesList]);
|
||||
foreach my $sub (@MyInitVariables) {
|
||||
my $result = &$sub;
|
||||
$Message .= $q->p($@) if $@;
|
||||
@@ -1542,30 +1543,30 @@ sub LatestChanges {
|
||||
sub StripRollbacks {
|
||||
my @result = @_;
|
||||
if (not (GetParam('all', 0) or GetParam('rollback', 0))) { # strip rollbacks
|
||||
my ($skip_to, $end, %rollback);
|
||||
my (%rollback);
|
||||
for (my $i = $#result; $i >= 0; $i--) {
|
||||
# some fields have a different meaning if looking at rollbacks
|
||||
my $ts = $result[$i][0];
|
||||
my $id = $result[$i][1];
|
||||
my $target_ts = $result[$i][2];
|
||||
my $target_id = $result[$i][3];
|
||||
# strip global rollbacks
|
||||
if ($skip_to and $ts <= $skip_to) {
|
||||
splice(@result, $i + 1, $end - $i);
|
||||
$skip_to = 0;
|
||||
} elsif ($id eq '[[rollback]]') {
|
||||
if ($id eq '[[rollback]]') {
|
||||
if ($target_id) {
|
||||
$rollback{$target_id} = $target_ts; # single page rollback
|
||||
splice(@result, $i, 1); # strip marker
|
||||
} else {
|
||||
$end = $i unless $skip_to;
|
||||
$skip_to = $target_ts; # cumulative rollbacks!
|
||||
my $end = $i;
|
||||
while ($ts > $target_ts and $i > 0) {
|
||||
$i--; # quickly skip all these lines
|
||||
$ts = $result[$i][0];
|
||||
}
|
||||
splice(@result, $i + 1, $end - $i);
|
||||
$i++; # compensate $i-- in for loop
|
||||
}
|
||||
} elsif ($rollback{$id} and $ts > $rollback{$id}) {
|
||||
splice(@result, $i, 1); # strip rolled back single pages
|
||||
}
|
||||
}
|
||||
splice(@result, 0, $end + 1) if $skip_to; # strip rest if any
|
||||
} else { # just strip the marker left by DoRollback()
|
||||
for (my $i = $#result; $i >= 0; $i--) {
|
||||
splice(@result, $i, 1) if $result[$i][1] eq '[[rollback]]'; # id
|
||||
@@ -1849,11 +1850,10 @@ sub RcTextRevision {
|
||||
: ($UsePathInfo ? '/' : '?') . UrlEncode($id));
|
||||
print "\n", RcTextItem('title', NormalToFree($id)),
|
||||
RcTextItem('description', $summary),
|
||||
RcTextItem('generator', $username
|
||||
? $username . ' ' . Ts('from %s', $host) : $host),
|
||||
RcTextItem('generator', GetAuthor($host, $username)),
|
||||
RcTextItem('language', join(', ', @{$languages})), RcTextItem('link', $link),
|
||||
RcTextItem('last-modified', TimeToW3($ts)),
|
||||
RcTextItem('revision', $revision);
|
||||
RcTextItem('revision', $revision);
|
||||
}
|
||||
|
||||
sub PrintRcText { # print text rss header and call ProcessRcLines
|
||||
@@ -2078,6 +2078,9 @@ sub DoRollback {
|
||||
my @ids = ();
|
||||
if (not $page) { # cannot just use list length because of ('')
|
||||
return unless UserIsAdminOrError(); # only admins can do mass changes
|
||||
SetParam('showedit', 1); # make GetRcLines return minor edits as well
|
||||
SetParam('all', 1); # prevent LatestChanges from interfering
|
||||
SetParam('rollback', 1); # prevent StripRollbacks from interfering
|
||||
my %ids = map { my ($ts, $id) = @$_; $id => 1; } # make unique via hash
|
||||
GetRcLines($Now - $KeepDays * 86400); # 24*60*60
|
||||
@ids = keys %ids;
|
||||
@@ -2198,6 +2201,13 @@ sub ScriptLinkDiff {
|
||||
return ScriptLink($action, $text, 'diff');
|
||||
}
|
||||
|
||||
sub GetAuthor {
|
||||
my ($host, $username) = @_;
|
||||
return $username . ' ' . Ts('from %s', $host) if $username and $host;
|
||||
return $username if $username;
|
||||
return T($host); # could be 'Anonymous'
|
||||
}
|
||||
|
||||
sub GetAuthorLink {
|
||||
my ($host, $username) = @_;
|
||||
$username = FreeToNormal($username);
|
||||
@@ -2206,11 +2216,11 @@ sub GetAuthorLink {
|
||||
$username = ''; # Just pretend it isn't there.
|
||||
}
|
||||
if ($username and $RecentLink) {
|
||||
return ScriptLink(UrlEncode($username), $name, 'author', undef, Ts('from %s', $host));
|
||||
return ScriptLink(UrlEncode($username), $name, 'author', undef, $host);
|
||||
} elsif ($username) {
|
||||
return $q->span({-class=>'author'}, $name) . ' ' . Ts('from %s', $host);
|
||||
return $q->span({-class=>'author'}, $name);
|
||||
}
|
||||
return $host;
|
||||
return T($host); # could be 'Anonymous'
|
||||
}
|
||||
|
||||
sub GetHistoryLink {
|
||||
@@ -2524,6 +2534,7 @@ sub PrintHtmlDiff {
|
||||
$old = $Page{revision} - 1;
|
||||
}
|
||||
}
|
||||
$summary = $Page{summary} if not $summary and not $new;
|
||||
$summary = $q->p({-class=>'summary'}, T('Summary:') . ' ' . $summary) if $summary;
|
||||
if ($old > 0) { # generate diff if the computed old revision makes sense
|
||||
$diff = GetKeptDiff($text, $old);
|
||||
@@ -3489,8 +3500,7 @@ sub PrintSearchResultEntry {
|
||||
my %entry = %{(shift)}; # get value from reference
|
||||
my $regex = shift;
|
||||
if (GetParam('raw', 0)) {
|
||||
$entry{generator} = $entry{username} . ' ' if $entry{username};
|
||||
$entry{generator} .= Ts('from %s', $entry{host}) if $entry{host};
|
||||
$entry{generator} = GetAuthor($entry{host}, $entry{username});
|
||||
foreach my $key (qw(title description size last-modified generator username host)) {
|
||||
print RcTextItem($key, $entry{$key});
|
||||
}
|
||||
@@ -3794,9 +3804,9 @@ sub MergeRevisions { # merge change from file2 to file3 into file1
|
||||
# Note: all diff and recent-list operations should be done within locks.
|
||||
sub WriteRcLog {
|
||||
my ($id, $summary, $minor, $revision, $username, $host, $languages, $cluster) = @_;
|
||||
my $rc_line = join($FS, $Now, $id, $minor, $summary, $host,
|
||||
my $line = join($FS, $Now, $id, $minor, $summary, $host,
|
||||
$username, $revision, $languages, $cluster);
|
||||
AppendStringToFile($RcFile, $rc_line . "\n");
|
||||
AppendStringToFile($RcFile, $line . "\n");
|
||||
}
|
||||
|
||||
sub UpdateDiffs { # this could be optimized, but isn't frequent enough
|
||||
@@ -3848,17 +3858,18 @@ sub DoMaintain {
|
||||
}
|
||||
# Move the old stuff from rc to temp
|
||||
my @rc = split(/\n/, $data);
|
||||
my $i;
|
||||
for ($i = 0; $i < @rc ; $i++) {
|
||||
my ($ts) = split(/$FS/o, $rc[$i]);
|
||||
my @tmp = ();
|
||||
for my $line (@rc) {
|
||||
my ($ts, $id, $minor, $summary, $host, @rest) = split(/$FS/o, $line);
|
||||
last if ($ts >= $starttime);
|
||||
push(@tmp, join($FS, $ts, $id, $minor, $summary, 'Anonymous', @rest));
|
||||
}
|
||||
print $q->p(Ts('Moving %s log entries.', $i));
|
||||
if ($i) {
|
||||
my @temp = splice(@rc, 0, $i);
|
||||
print $q->p(Ts('Moving %s log entries.', scalar(@tmp)));
|
||||
if (@tmp) {
|
||||
# Write new files, and backups
|
||||
AppendStringToFile($RcOldFile, join("\n",@temp) . "\n");
|
||||
AppendStringToFile($RcOldFile, join("\n", @tmp) . "\n");
|
||||
WriteStringToFile($RcFile . '.old', $data);
|
||||
splice(@rc, 0, scalar(@tmp)); # strip
|
||||
WriteStringToFile($RcFile, @rc ? join("\n",@rc) . "\n" : '');
|
||||
}
|
||||
if (opendir(DIR, $RssDir)) { # cleanup if they should expire anyway
|
||||
|
||||
35
wikipipe
35
wikipipe
@@ -1,35 +0,0 @@
|
||||
#! /usr/bin/perl
|
||||
# Copyright (C) 2005 Alex Schroeder <alex@emacswiki.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the
|
||||
# Free Software Foundation, Inc.
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
use Getopt::Std;
|
||||
use LWP::UserAgent;
|
||||
|
||||
our $opt_b;
|
||||
getopt('b');
|
||||
my $base = $opt_b;
|
||||
my $url = shift;
|
||||
die "Usage: wikipipe [-b base-url] url\n" unless $url;
|
||||
undef $/;
|
||||
|
||||
my $data = <STDIN>;
|
||||
my $ua = new LWP::UserAgent;
|
||||
my %params = (action=>raw, data=>$data, base=>$base);
|
||||
my $response = $ua->post($url, \%params);
|
||||
die $response->status_line unless $response->is_success;
|
||||
print $response->content;
|
||||
Reference in New Issue
Block a user