Welcome to TiddlyWiki created by Jeremy Ruston, Copyright © 2007 UnaMesa Association
! Admin
<<tagging admin>>
! Todo
<<tagging todo>>
Infos tirées d'ici : http://www.patdef.fr/Configurer-apache2-pour-faire-du.html
!! Activer le module ssl
<<<
{{{
a2enmod ssl
}}}
<<<
!! Créer un hôte virtuel avec le port 443
<<<
{{{
sudo nano /etc/apache2/sites-available/monsite.org
<VirtualHost *:443>
...
...
# add ssl protocol
SSLEngine On
SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
SSLCertificateFile /etc/ssl/certs/mondomaine.crt
SSLCertificateKeyFile /etc/ssl/private/mondomaine.key
</VirtualHost>
}}}
<<<
!! Autoriser les hôtes virtuels sur ce port (pas sûr de la description, mais faut le faire quand même)
<<<
{{{
sudo nano /etc/apache2/httpd.conf
NameVirtualHost *:443
}}}
<<<
!! Dire à Apache d'écouter le bon port
<<<
{{{
echo "Listen 443" >> /etc/apache2/ports.conf
}}}
<<<
!! Création de la clé privée (dans un répertoire quelconque)
<<<
{{{
openssl genrsa -out mondomaine.key 1024
}}}
<<<
!! Création de la demande de certificat
<<<
{{{
openssl req -new -key mondomaine.key -out mondomaine.csr
}}}
<<<
!! Création du certificat perso
<<<
{{{
openssl x509 -req -days 365 -in mondomaine.csr -signkey mondomaine.key -out mondomaine.crt
}}}
<<<
!! Installation du certificat
<<<
{{{
cp mondomaine.crt /etc/ssl/certs
cp mondomaine.key /etc/ssl/private
}}}
<<<
! Tout les articles
<<list filter [tag[article]]>>
! Articles triés par tags
<<allTags excludeLists>>
! Editer /etc/inittab
Remplacer (ou commenter)
| #1:2345:respawn:/sbin/getty 38400 tty1
par
| 1:2345:respawn:/bin/login -f YOUR_USER_NAME tty1 </dev/tty1 >/dev/tty1 2>&1
! source
http://forums.debian.net/viewtopic.php?t=29333
/***
|Name:|CloseOnCancelPlugin|
|Description:|Closes the tiddler if you click new tiddler then cancel. Default behaviour is to leave it open|
|Version:|3.0.1 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#CloseOnCancelPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{
merge(config.commands.cancelTiddler,{
handler_mptw_orig_closeUnsaved: config.commands.cancelTiddler.handler,
handler: function(event,src,title) {
this.handler_mptw_orig_closeUnsaved(event,src,title);
if (!store.tiddlerExists(title) && !store.isShadowTiddler(title))
story.closeTiddler(title,true);
return false;
}
});
//}}}
Name: MptwSmoke
Background: #fff
Foreground: #000
PrimaryPale: #aaa
PrimaryLight: #777
PrimaryMid: #111
PrimaryDark: #000
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
Un petit script pour convertir les images du dossier courant d'un format vers un autre (nécessite imagemagick) :
<<<
{{{
#!/bin/bash
## ~/bin/iconvert
for i in *.$1
do
convert $i ${i/.$1/.$2}
echo $i "==>" ${i/.$1/.$2}
done
}}}
<<<
Et pour le lancer : {{{ iconvert png jpg }}}
! Emailbackup, un script de sauvegarde par email
!! Motivations
* La sauvegarde, c'est Bien, c'est Super, c'est INDISPENSABLE !
* Sauvegarder sur une clé USB ou un disque externe placé à côté de l'ordi c'est bien, mais pas top : incendie, vol, ... et tout est perdu, même les sauvegardes !
!! Description d'une sauvegarde idéale
; Facile, rapide, automatique
: parce qu'on est fainéant, pressés et distraits
; Hors-site
: le plus loin possible de l'ordi pour que les données échappent à un désastre qui toucherait tout l'immeuble par exemple
; Fiable
: il faut que le support de la sauvegarde soit solide, tout le temps accessible et lui-même sauvegardé
; Versionnée et datée
: une sauvegarde par jour par exemple, comme ça, si on s'aperçoit qu'il y a un virus dans la version actuelle, on peut "remonter le temps" jusqu'à trouver une version correcte
; Gratuite
: parce qu'on est radin, fauché ou les deux (étudiant)
!! La sauvegarde par email
* Elle est ''hors site'' (à condition de pas héberger le serveur d'emails sur la même machine bien sûr, et on fait attention avec toute ces histoires de cloud et de virtualisation !)
* Le support est ''fiable'' et tout le temps accessible
* On peut la rendre ''versionnée et datée'' en gérant bien : un email par jour
* Elle est ''gratuite'' si on utilise un fournisseur gratuit (GMail et autre) ou sa boite pro/étudiante
* Reste à la rendre ''facile, rapide et automatique''...
!!! Gros défaut de la sauvegarde par email : Elle est ''Publique'' !
Oui, vous avez bien lu, un email est transmis en clair et transite par un nombre indéterminé de machines (serveurs) qui peuvent en garder trace si ça leur chante. C'est pas génial pour sauvegarder des infos privées ...
// Pas de panique, nous allons remédier à ça grâce au chiffrement par [[GPG|http://www.gnupg.org/]]//
!! Script de sauvegarde chiffré par email
Pour répondre à ces problématiques, j'ai développé un petit script Bash (c'est pas grand chose, vous allez voir) qui permet d'automatiser la sauvegarde de fichiers sur une boite email.
Le script prend en paramètre une liste des fichiers ou répertoires à sauvegarder puis il :
* Crée une archive avec tar contenant tout ces fichiers
* Compresse l'archive avec bzip2
* Chiffre l'archive avec gnupg
* Envoie le tout sur l'adresse email en mettant la date et le nom du dossier sauvegardé dans le titre pour faciliter les recherches
Voici le code (a placer dans un fichier {{{emailbackup}}} par exemple):
<<<
{{{
#! /bin/bash
# Compresse, chiffre et sauvegarde par email tout les fichiers et répertoires passés en paramètres
### Paramètre
email_addr=utilisateur@serveur.com
## Nom de l'archive temporaire
tmpfile=`/bin/tempfile --suffix=".tar.bz2"`
## Création et compression de l'archive
if ! tar cjf $tmpfile $* 2>/dev/null
then
echo " !!! Erreur lors de la compression"
rm -f $tmpfile
exit 1
fi
## Chiffrement
if ! gpg -r $USER -e $tmpfile
then
echo " !!! Erreur lors du chiffrement"
rm -f $tmpfile
exit 2
fi
## Email la sauvegarde
if ! mutt -a $tmpfile.gpg -s "[$HOSTNAME:EmailBackup] $* (`date`)" $email_addr <.
then
echo " !!! Erreur lors de l'envoi de l'email"
rm -f $tmpfile $tmpfile.gpg
exit 3
fi
## Supprime le fichier temporaire
/bin/rm -f $tmpfile
/bin/rm -f $tmpfile.gpg
## Supprime le fichier "sent" de mutt
rm ~/sent
exit 0
}}}
<<<
!! Pré-requis
Le script a besoin des paquets suivants : {{{gnupg bzip2 mutt}}}
!! Astuces
* Pour l'utilisation : {{{emailbackup fichier1 repertoire2 fichier3}}}
* Pour la restauration
** on télécharge le fichier {{{filexxxx.tar.bz2.gpg}}}
** {{{gpg filexxxx.tar.bz2.gpg}}} ça donne un {{{filexxxx.tar.bz2}}}
** {{{tar xjf filexxxx.tar.bz2}}} ça décompresse tout dans le répertoire courant
* Avec GMail, il est possible d'utiliser une adresse de destination de la forme "utilisateur+label@gmail.com". Dans ce cas, c'est bien "utilisateur@gmail.com" qui reçoit l'email, mais le label "label" lui est automatiquement affecté. Ça permet de créer un filtre pour archiver automatiquement ces emails sans les faire apparaitre dans la boite de réception (filtre à configurer dans GMail).
* Sauvegarder votre clé GPG sur un autre poste. Si vous la perdez, les sauvegardes seront illisibles.
* L'extension Firefox [[FireGPG|http://fr.getfiregpg.org]] permet de chiffrer et déchiffrer facilement des emails. A utiliser pour la correspondance privée et pour récupérer les sauvegardes.
* Placer un appel à ce script dans le Cron permet d'automatiser cette tâche
* Placer ce script dans le répertoire {{{~/bin}}} devrait permettre de le lancer en invoquant directement son nom (sinon, ajouter {{{~/bin}}} dans le {{{PATH}}})
* Il ne faut pas oublier de supprimer quelques sauvegardes de temps en temps, sinon la boite email peut devenir pleine...
Bonnes sauvegardes.
Dans cet article, nous allons mettre en place un environnement de développement complet pour travailler avec l'excellente carte de développement [[Armadeus|http://armadeus.com]], le tout basé sur Ubuntu 10.04.
! Généralités
Notre environnement de développement sera constitué d'un PC (portable ou station) ayant au minimum une carte réseau ethernet et d'une carte Armadeus (toutes version, mais ici j'utilise une APF9328 devfull). Un port série est aussi indispensable pour paramétrer le "BIOS" de la carte (U-Boot).
La carte Armadeus APF9328 est basée sur un processeur ARM9. Il va donc nous falloir une toolchain de compilation croisée pour être en mesure de fabriquer des programmes fonctionnant sur ARM. La société Armadeus fournis déjà une toolchain complète que nous allons utiliser.
Pour envoyer le programme sur la carte et l'exécuter, nous allons utiliser un partage de fichier par NFS. De cette manière, la carte utilisera un dossier de l'ordinateur comme racine (root /). De cette manière, "envoyer" un programme sur la carte reviens à le copier au bon endroit sur le disque-dur. Simple non ?
Les mises à jour du noyau Linux embarqué sur la carte nécessitent un partage de fichier via TFTP.
Pour faciliter tout ça, nous allons utiliser un IDE : Code::Blocks que nous allons paramétrer pour utiliser la toolchain.
''Note importante'' : pour les utilisateurs Windows ou ne souhaitant pas modifier leur système, il est tout à fait possible d'utiliser une machine virtuelle. Il suffit pour cela d'installer Virtualbox puis de créer une nouvelle machine virtuelle sur laquelle vous installerez Ubuntu 10.04. Il faut ensuite paramétrer le réseau en mode "Pont" (ou "Bridge") et éventuellement le port série.
------
! Première étape : installation et paramétrage des serveurs
!! Serveur TFTP
Adapté de http://doc.ubuntu-fr.org/tftpd
Le serveur TFTP permettra de mettre à jour facilement les logiciels présents sur la carte Armadeus (U-Boot, Linux, Rootfs).
* Passer root : {{{sudo -s}}}
* Installer les paquets : {{{apt-get install xinetd tftpd tftp}}}
* Créer le répertoire partagé : {{{mkdir -m 777 /srv/tftp}}}
* Créer le fichier de config
{{{
cat <<"_" > /etc/xinetd.d/tftp
service tftp
{
protocol = udp
port = 69
socket_type = dgram
wait = yes
user = nobody
server = /usr/sbin/in.tftpd
server_args = /srv/tftp
disable = no
}
_
}}}
* Re-démarrer xinetd : {{{/etc/init.d/xinetd restart}}}
!! Serveur NFS
Le serveur NFS permettra de partager un dossier de l'ordinateur avec la carte Armadeus. Celle-ci démarrera en montant ce répertoire sur sa racine (/).
* Passer root : {{{sudo -s}}}
* Installer les paquets : {{{apt-get install nfs-kernel-server}}}
* Créer le répertoire partagé : {{{mkdir /srv/armadeus}}}
* On se l'approprie : {{{chown login:login /srv/armadeus}}}
* On execute la commande suivante pour ajouter le partage NFS (remplacer //login// par votre identifiant)
{{{
echo "/srv/armadeus/ *(rw,sync,all_squash,anonuid=$(id -u login),anongid=$(id -g login))" >> /etc/exports
}}}
* On re-démarre le serveur : {{{/etc/init.d/nfs-kernel-server restart}}}
----
! Deuxième étape : installation et compilation de la toolchain
La toolchain proposée par la société Armadeus est basée sur Linux et les outils GNU. Elle est installée en téléchargeant les sources puis en les compilant.
La page http://www.armadeus.com/wiki/index.php?title=Toolchain fournis tout les détails sur cette installation., mais nous allons résumer ici.
Nous allons installer la toolchain dans le répertoire {{{/opt/armadeus}}}.
!!! Préparation
Installer les paquets nécessaires :
{{{
sudo apt-get install build-essential gcc g++ autoconf automake libtool bison flex gettext patch subversion texinfo wget git-core
sudo apt-get install libncurses5 libncurses5-dev zlib1g-dev liblzo2-2 liblzo2-dev libacl1 libacl1-dev uuid-dev
** optionnels **
sudo apt-get install libglib2.0-dev
sudo apt-get install libnetpbm10-dev
}}}
Configurer Bash comme interpréteur de scripts par défaut :
{{{
sudo dpkg-reconfigure dash
-> sélectionner "Non" puis valider
}}}
Créer le répertoire pour les sources de la toolchain, on se l'approprie pour faciliter la suite des opérations
{{{
sudo mkdir /opt/armadeus
sudo chown login:login /opt/armadeus
}}}
Lors de la compilation, de nombreuses archives de code-source sont télécharger depuis internet. C'est long et on a pas envie de le refaire, même quant on veut re-compiler complètement la toolchain. Nous allons donc placer ces archives dans un répertoire annexe.
{{{
sudo mkdir /opt/armadeus-downloads
sudo chown login:login /opt/armadeus-downloads
}}}
!!! Téléchargement et compilation de la toolchain
On récupère les sources
{{{
git clone git://armadeus.git.sourceforge.net/gitroot/armadeus/armadeus /opt/armadeus
}}}
On se place ensuite dans le répertoire, et on crée le lien symbolique vers le répertoire de sauvegarde des archives
{{{
cd /opt/armadeus
ln -s /opt/armadeus-downloads ./downloads
}}}
On va utiliser la configuration par défaut pour l'instant et lancer la compilation
{{{
make apf9328_defconfig # adapter en fonction de la carte utilisée
make
}}}
Buildroot, l'outil responsable de gérer la compilation de la toolchain, récupère ensuite les sources de tout les logiciels (GCC, Binutils, ...), les dé-compresse, applique les patchs et les compile.
!!! Configuration de la copie des fichiers vers le TFTP
Nous allons configurer la toolchain pour quelle copie automatiquement les fichiers générés dans le répertoire {{{/srv/tftp}}} :
* lancer {{{make menuconfig}}}
* dans le menu qui apparait, aller dans @@Target Filesystem Options@@
* renseigner les 3 champs intitulés "also copy the image to..." avec la valeur {{{/srv/tftp/}}}
* retourner au menu principal, puis aller dans @@Kernel > Destination for linux kernel binaries@@
* renseigner le champ "Copy kernel to ..." avec {{{/srv/tftp/}}}
* sortir en validant l'enregistrement de la configuration
* lancer {{{make}}}
* les fichiers sont maintenant copisé dans {{{/srv/tftp/}}} après chaque compilation
* pour mettre à jour la carte, saisir "run update_all" dans l'invite de U-Boot
!!! Configuration réseau
* lancer {{{make menuconfig}}}
* aller dans @@Target filesystem options@@
* renseigner les champs suivants :
** server ip : IP du PC hébergeant le serveur TFTP et NFS
** ip address : IP de la carte
** gateway ip : IP du PC
** netmask
* sortir et lancer {{{make}}}
Ces paramètres seront utilisés par défaut par la carte, ils peuvent être modifiés dans U-Boot.
!!! Dé-compression du rootfs dans le partage NFS
{{{
sudo tar xvf /srv/tftp/apf9328-rootfs.arm.tar -C /srv/armadeus
sudo chown -R login:login /srv/armadeus
}}}
----
! Troisième étape : Intégration avec Code::Blocks
!!! Installation et configuration de Code::Block
Voir cet article dédié : [[Code::Blocks|Installer Code::Blocks]]
!!! Configurer Code::Blocks pour utiliser la Toolchain Armadeus
* Lancer Code::Blocks (si c'est la première fois, il demande son compilo par défaut, sélectionner @@GNU GCC Compiler@@ et valider)
* Aller dans @@Settings > Compiler and debugger...@@
* Dans la liste déroulante @@Selected compiler@@, sélectionner @@GNU GCC Compiler@@
* Cliquer su @@Copy@@ en dessous de la liste
* Dans la boite @@Add new compiler@@ qui apparait, entrer @@Armadeus Toolchain for APF9328@@
* Aller dans l'onglet "Toolchain executables" et entrer les valeurs
** Compiler installation directory : {{{/opt/armadeus/buildroot/build_armv4t/staging_dir/usr/}}}
** C compiler : {{{arm-linux-gcc}}}
** C++ compiler : {{{arm-linux-g++}}
** Linker for dynamic libs : {{{arm-linux-g++}}}
** Linker for static libs : {{{arm-linux-ar}}}
** Debugger : {{{arm-linux-gdb}}}
* Valider en bas
!!! Configurer un projet portable PC/Armadeus
* Créer un nouveau projet "Console application" ou "SDL application"
* Dans l'assistant, choisir C ou C++ au choix
* Lui choisir un nom et un dossier
* Dans le choix du compilateur, choisir GCC (pour le PC)
* "Finish"
* Aller dans @@Projects > Properties@@; onglet @@Build target@@
* Cliquer sur "Add", indiquer le nom "apf"
* Sélectionner tout les fichiers dans la liste en bas puis "Valider"
* Aller dans @@Projects > Build options...@@
* Sélectionner "apf" dans la liste à gauche
* Sélectionner "Armadeus Toolchain for APF9328" dans la liste "Selected Compiler"
* Aller dans "Pre/post build step" et insérer le texte suivant dans "Post-build steps"
{{{
cp $(TARGET_OUTPUT_FILE) /srv/armadeus/root/
}}}
* Valider
Le fichier compilé sera ainsi automatiquement copié dans {{{/srv/armadeus/root}}} après chaque compilation, ce qui permettra de le tester sur la carte Armadeus.
Avant de modifier le projet, c'est une bonne idée de faire @@File > Save project as user-template". Ce projet pourra ainsi servir à créer d'autres projets similaires.
----
! Quatrième étape : Configuration de U-Boot
Pour cela, on a besoin d'une connexion série RS232 (port PC ou adaptateur USB/Série).
Nous allons utiliser minicom comme émulateur de terminal : {{{sudo apt-get install minicom}}} (sous windows : hyperterminal fait l'affaire)
Configuration de minicom : {{{sudo minicom -so}}}
* aller dans "Configuration du port série"
* Port série : (/dev/ttyS0 ou /dev/ttyUSB0)
* Débit/Parité/Bits : 115200 8N1
* Contrôles de flux : NON aux deux
* Choisir "Enregistrer sous dfl" puis "sortir de minicom"
* lancer minicom : {{{minicom -o}}}
* Connecter le port série de la carte sur le PC
* Alimenter la carte
Un compte à rebours doit apparaitre, appuyer sur une touche pour entrer dans l'invite de U-Boot
On peut maintenant configurer les variables de U-Boot. Pour cela, il faut exécuter la commande {{{setenv variable valeur}}}
Variables à modifier et nouvelle valeur
* bootdelay 5
* bootcmd run nfsboot
* rootpath /srv/armadeus
* serverpath /srv/tftp/
Ensuite, il faut sauvegarder la configuration en flash grâce à la commande {{{saveenv}}} et on re-démarre la carte : {{{reset}}}
'' Votre environnement de développement est maintenant parfaitement opérationnel ''
----
----
! Extras : trucs et astuces
!!! Configuration de la toolchain, sélection des logiciels inclus
On peut configurer la liste des logiciels à inclure, ainsi que plein d'autres paramètres (emplacement et format des fichiers de sortie, options de compilation, ...) en utilisant les menus dédiés à cet effet :
{{{
cd /opt/armadeus
make menuconfig # configuration de Buildroot, sélection des logiciels inclus
make linux-menuconfig # configuration du noyau et notamment les drivers
}}}
Il est notamment possible d'ajouter la librairie SDL pour faire des programmes graphiques dessinant sur l'écran LCD:
* {{{make menuconfig}}} @@Package selection for the target > Graphic libraries and applications@@ cocher @@SDL@@
!!! Mises à jours de la toolchain
Comme cette toolchain est en constante évolution grâce au travail acharné des développeurs de Armadeus, il est nécessaire de faire des mises à jour de temps en temps.
* Mise à jour simple
{{{
cd /opt/armadeus
git pull
make
}}}
* Mise à jour plus complète (à effectuer si la première méthode ne fonctionne pas ou provoque des erreurs).
{{{
cd /opt/armadeus
rm downloads # pour protéger le répertoire des sources
make distclean
ln -s /opt/armadeus-downloads ./downloads
make apf9328_defconfig
make
}}}
! Déplacement du ROOTFS
Le rootfs est généré par la toolchain sous deux formes distinctes :
* une archive {{{.tar.gz}}}; peut être facilement décompressée dans le partage NFS ou une SDCard
* une archive {{{.jffs2}}} pour être copiée dans la flash interne de la carte Armadeus via Buildroot et TFTP (commande {{{run update_rootfs}}})
Nous avons déjà expliqué auparavant comment décompresser une archive {{{.tar.gz}}} dans le partage NFS. Nous allons ici voir les autres manipulations utiles à connaitre.
!!! ROOTFS.tar.gz -> NFS
Une fois le rootfs généré par la toolchain, il est nécessaire de le placer dans le partage NFS pour que la carte puisse l'utiliser.
Exécuter la commande suivante pour extraire l'archive du rootfs dans {{{/srv/armadeus}}}
{{{
sudo tar xvf /srv/tftp/apf9328-rootfs.arm.tar -C /srv/armadeus
sudo chown -R login:login /srv/armadeus
}}}
!!! NFS -> ROOTFS.tar.gz / .tar.bz2
Une fois qu'on a bien paramétré le dossier {{{/srv/armadeus}}} et qu'il est au poil, il peut être intéressant de créer une archive pour le conserver et, par exemple, l'extraire sur une SDcard.
La commande pour créer une archive du root :
{{{
sudo tar cjvf /home/login/monarchive.tar.bz2 -C /srv/armadeus ./
## enlever le .bz2 et l'option j pour ne pas compresser / remplacer par .gz et z pour compresser avec gzip
}}}
Pour l'extraire sur une SDcard formatée en EXT2 ou EXT3
{{{
sudo tar xjvf /home/monarchive.tar.bz2 -C /media/mmc
}}}
Pour les deux, il est impératif d'être ROOT (avec sudo) pour être autorisé à créer les fichiers spéciaux.
!!! NFS -> ROOTFS.jffs2
Si l'on veut placer notre rootfs dans la flash interne, il faut exécuter les opérations suivantes pour générer le .jffs2 à partir du partage NFS {{{/srv/armadeus}}}:
!!!! Méthode 1 - Utilise la toolchain
{{{
sudo rm -fR /opt/armadeus/buildroot/project_build_armv4t/apf9328/root/*
sudo cp -R /srv/armadeus/* /opt/armadeus/buildroot/project_build_armv4t/apf9328/root/
sudo chown -R login:login /opt/armadeus
make
}}}
Normalement, le .jffs2 généré doit maintenant se retrouver dans {{{/srv/tftp}}}
@@A vérifier, il faut peut-être faire un {{{touch /opt/armadeus/buildroot/project_build_armv4t/apf9328/root/.root}}}@@
!!!! Méthode 2 - Avec les mtd-utils
* Installer le paquet {{{mtd-utils}}} : {{{sudo apt-get install mtd-utils}}}
* Créer l'archive (ligne de commande trouvée en greppant la sortie de make) :
{{{
mkfs.jffs2 -e 0x20000 -p -l -s 0x1000 -D /opt/armadeus/buildroot/target/device/armadeus/rootfs/device_table.txt -d /srv/armadeus/ -o "/srv/tftp/apf9328-rootfs.arm.jffs2"
}}}
On peut aussi utiliser le mkfs.jffs2 situé dans la toolchain (dans ce cas, pas nécessaire d'installer les mtd-utils)
{{{
/opt/armadeus/buildroot/toolchain_build_armv4t/mtd-utils-a8ce7c2668ef0781326f629eef02cef6c3962b8a/mkfs.jffs2 -e 0x20000 -p -l -s 0x1000 -D /opt/armadeus/buildroot/target/device/armadeus/rootfs/device_table.txt -d /srv/armadeus/ -o "/srv/tftp/apf9328-rootfs.arm.jffs2"
}}}
/***
|Name:|ExtentTagButtonPlugin|
|Description:|Adds a New tiddler button in the tag drop down|
|Version:|3.2 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#ExtendTagButtonPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{
window.onClickTag_mptw_orig = window.onClickTag;
window.onClickTag = function(e) {
window.onClickTag_mptw_orig.apply(this,arguments);
var tag = this.getAttribute("tag");
var title = this.getAttribute("tiddler");
// Thanks Saq, you're a genius :)
var popup = Popup.stack[Popup.stack.length-1].popup;
createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");
wikify("<<newTiddler label:'New tiddler' tag:'"+tag+"'>>",createTiddlyElement(popup,"li"));
return false;
}
//}}}
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
See also [[MPTW]].
/***
|Name:|HideWhenPlugin|
|Description:|Allows conditional inclusion/exclusion in templates|
|Version:|3.1 ($Rev: 3919 $)|
|Date:|$Date: 2008-03-13 02:03:12 +1000 (Thu, 13 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#HideWhenPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
For use in ViewTemplate and EditTemplate. Example usage:
{{{<div macro="showWhenTagged Task">[[TaskToolbar]]</div>}}}
{{{<div macro="showWhen tiddler.modifier == 'BartSimpson'"><img src="bart.gif"/></div>}}}
***/
//{{{
window.hideWhenLastTest = false;
window.removeElementWhen = function(test,place) {
window.hideWhenLastTest = test;
if (test) {
removeChildren(place);
place.parentNode.removeChild(place);
}
};
merge(config.macros,{
hideWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( eval(paramString), place);
}},
showWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !eval(paramString), place);
}},
hideWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.tags.containsAll(params), place);
}},
showWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !tiddler.tags.containsAll(params), place);
}},
hideWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.tags.containsAny(params), place);
}},
showWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !tiddler.tags.containsAny(params), place);
}},
hideWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.tags.containsAll(params), place);
}},
showWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !tiddler.tags.containsAll(params), place);
}},
hideWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0]), place);
}},
showWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !(store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0])), place);
}},
hideWhenTitleIs: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.title == params[0], place);
}},
showWhenTitleIs: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.title != params[0], place);
}},
'else': { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !window.hideWhenLastTest, place);
}}
});
//}}}
! Motivation
Il peut être utile dans certains cas de paramétrer un système pour qu'il utilise une adresse IP fixe si jamais le serveur DHCP ne réponds pas. Sous GNU/Linux (et plus particulièrement les systèmes Debian et similaires), cela peut facilement être configuré.
! Procédure
* Éditer le fichier {{{ /etc/dhcp3/dhclient.conf }}}
* Modifier les timeouts pour correspondre aux besoins (plus d'infos : {{{man dhclient.conf}}})
<<<
{{{
timeout 20;
retry 60;
reboot 10;
}}}
<<<
* Ajouter ce bloc à la fin
<<<
{{{
lease {
interface "eth0";
fixed-address 192.168.0.111;
option subnet-mask 255.255.255.0;
expire 0 2030/1/01 00:00:01;
}
}}}
<<<
! Problèmes
Les dates supérieures à 2038 (pour expire, rebind et renew) posent problème sur les systèmes 32bits (c'est dû au fameux bug de 2038 des systèmes Unix : http://en.wikipedia.org/wiki/Year_2038_problem) : dans ce cas, la date est considérée dépassée et le lease n'est pas utilisé.
//{{{
config.formatters.unshift( {
name: "inlinetabs",
match: "\\<tabs",
lookaheadRegExp: /(?:<tabs (.*)>\n)((?:.|\n)*?)(?:\n<\/tabs>)/mg,
handler: function(w)
{
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
{
var cookie = lookaheadMatch[1];
var wrapper = createTiddlyElement(null,"div",null,cookie);
var tabset = createTiddlyElement(wrapper,"div",null,"tabset");
tabset.setAttribute("cookie",cookie);
var validTab = false;
var firstTab = '';
var tabregexp = /(?:<tab (.*)>)(?:(?:\n)?)((?:.|\n)*?)(?:<\/tab>)/mg;
while((m = tabregexp.exec(lookaheadMatch[2])) != null)
{
if (firstTab == '') firstTab = m[1];
var tab = createTiddlyButton(tabset,m[1],m[1],story.onClickInlineTab,"tab tabUnselected");
tab.setAttribute("tab",m[1]);
tab.setAttribute("content",m[2]);
tab.title = m[1];
if(config.options[cookie] == m[1])
validTab = true;
}
if(!validTab)
config.options[cookie] = firstTab;
w.output.appendChild(wrapper);
story.switchInlineTab(tabset,config.options[cookie]);
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
}
})
Story.prototype.switchInlineTab = function(tabset,tab)
{
var cookie = tabset.getAttribute("cookie");
var theTab = null
var nodes = tabset.childNodes;
for(var t=0; t<nodes.length; t++)
if(nodes[t].getAttribute && nodes[t].getAttribute("tab") == tab)
{
theTab = nodes[t];
theTab.className = "tab tabSelected";
}
else
nodes[t].className = "tab tabUnselected"
if(theTab)
{
if(tabset.nextSibling && tabset.nextSibling.className == "tabContents")
tabset.parentNode.removeChild(tabset.nextSibling);
var tabContent = createTiddlyElement(null,"div",null,"tabContents");
tabset.parentNode.insertBefore(tabContent,tabset.nextSibling);
wikify(theTab.getAttribute("content"),tabContent);
if(cookie)
{
config.options[cookie] = tab;
saveOptionCookie(cookie);
}
}
}
Story.prototype.onClickInlineTab = function(e)
{
story.switchInlineTab(this.parentNode,this.getAttribute("tab"));
return false;
}
//}}}
Réalisé sur une Debian Squeeze (2010-03-23)
! Paquets nécessaires
* Indispensables
** build-essential
** cmake
** pkg-config
** libboost-thread-dev
** libboost-signals-dev
* Optionnels (graphique)
** libcv-dev libcvaux-dev libhighgui-dev (~OpenCV)
** libgnomecanvas2-dev
* Optionnels (bindings python)
** python2.6-dev
** swig
* Optionnels (bindings ruby)
** ruby-dev
** swig
* Optionnels (divers / utilité à préciser)
** libgsl0-dev
** libboost-dev (Boost)
* Additionnels pour {{{Stage}}}
** libfltk1.1-dev
** libltdl-dev
** freeglut3-dev (~OpenGL)
* Additionnels pour {{{Gazebo}}}
** libxml2-dev
** libgdal-dev (Geospatial Data Abstration Library, optionnel mais fortement recommandé)
** libode-dev
** libogre-dev
! Note
Les tests ci-dessous ont été effectués avec tout les paquets optionnels installés
! Player
# Télécharger les sources de player sur http://sourceforge.net/projects/playerstage/files/
# Placer ces sources dans un répertoire quelconque (par exemple {{{/usr/local/src}}})
# Dé-compresser
<<<
{{{
tar xvf player-xxx.tar.gz
}}}
<<<
# Aller dans le répertoire des sources, créer un répertoire {{{build}}} et se placer dedans
<<<
{{{
cd player-xxx/
mkdir build
cd build
}}}
<<<
# Lancer la génération du {{{Makefile}}}
<<<
{{{
cmake ../
}}}
<<<
** On peut aussi modifier la configuration en faisant {{{ ccmake ../ }}}
# Lancer la compilation et l'installation (par défaut dans {{{/usr/local}}})
<<<
{{{
make install
}}}
<<<
# Rafraichir la BDD des librairies
<<<
{{{
ldconfig
}}}
<<<
! Stage
# Télécharger, déplacer et dé-compresser l'archive comme pour {{{player}}}
# Créer un dossier {{{build}}}, aller dedans, lancer {{{cmake ../}}}
# Lancer {{{make install}}}
! Gazebo
# Télécharger, déplacer et dé-compresser l'archive comme pour {{{player}}}
# Créer un dossier {{{build}}}, aller dedans, lancer {{{cmake ../}}}
# Lancer {{{make install}}}
Recently I needed to install both ~PHP5 and Ruby on Rails (~RoR) on a server, but some problems occurred…
! The needs
To power a Redmine server (a very nice bug-tracker, project manager and repository browser compatible with mercurial) I needed version 2.2.2 of ~RoR.
In the same time, I need to run various php sites on the same platform, and all that stuff through an Apache-worker server (multi-threaded version).
The problemS
First of all, ~RoR 2.2.2 is not available in Synaptic for Ubuntu 8.10 (only the 2.1.0). I had to manually install it as well as various packages. Hopefully, the gem command is very nice and helped a lot.
Then, Redmine website shows examples running with Webrick, a Ruby HTTP server. I wanted Redmine to run on Apache to have only one HTTP server running. The configuration was simple, but Apache needs the “passenger” module to be able to run ~RoR programs.
Last, the REAL problem : Passenger depends on the “worker” version of apache (multi-threads), while ~PHP needs the “prefork” version.
I had some trouble configuring everything to work flawlessly, so I decided to post here to prevent a memory loss.
Installing ~RoR 2.2.2
First, I installed the ruby package
{{{
sudo apt-get install ruby
}}}
This provides the 1.8.7 version which is OK for redmine.
Then I downloaded and installed the last version of Rubygems (see http://rubyonrails.org/download)
{{{
wget http://rubyforge.org/frs/download.php/45905/rubygems-1.3.1.tgz
tar xvf rubygems-1.3.1.tgz
cd rubygems-1.3.1.tgz
sudo ruby setup.rb
}}}
If I remember correctly, this step was easy and straightforward. Maybe it asked for some ”-dev” packages.
Then I used Rubygems to install ~RoR.
{{{
sudo gem1.8 install rails -v=2.2.2
}}}
The version is important, Redmine will not run with any other version (older or newer)
I installed also rake, rdoc and rmagick the same way.
I remember some trouble installing mysql Ruby module. “gem1.8 install mysql” complained with an obscure message about mkmf, all it needed was in fact some development headers and ruby1.8-dev.
{{{
sudo apt-get install ruby1.8-dev libmysqlclient15-dev
sudo gem1.8 install mysql
sudo apt-get install libopenssl-ruby
}}}
Making Redmine work
To install Redmine, I used SVN to checkout the lastest trunk. I placed the whole directory in /var/serv/redmine and set the correct owner and permissions (see http://www.redmine.org/wiki/redmine/RedmineInstall). I then added a symbolic link:
{{{
sudo ln -s /var/serv/redmine/public /var/www/redmine
}}}
so redmine/public will be accessible from the HTTP server.
I configured a new ~MySQL user “redmine” using the mysql-admin program, it is very easy to use, even for the “database-disabled” people like myself.
I basically followed the installation procedure until the Webrick test; and all worked perfectly.
But I don't want to run Webrick on a fancy port, I want Apache instead…
Configuring Apache for Rails
First, I run various websites on the same server, but I have only one DNS entry; so I wanted Redmine to run in a sub-URI.
I first read the http://www.redmine.org/wiki/redmine/HowTo_Install_Redmine_in_a_sub-URI page, but it was confusing and quite useless in fact.
What I needed was Passenger ( http://www.modrails.com/install.html ).
{{{
sudo gem install passenger
sudo passenger-install-apache2-module
}}}
I needed to apt-get some packages, especially the apache2-threaded-dev.
And this page gave me the information to configure Apache http://www.modrails.com/documentation/Users%20guide.html#deploying_rails_to_sub_uri.
Make some tests, Redmine should now work without Webrick.
Installing ~PHP5 with fcgid
apache2-mod-php5 can not be installed with apache2-worker because it is not thread-safe. Two alternatives : use apache2-prefork or install ~PHP5 as CGI. I prefered the second one, but it can have a big impact on performances. I found the fcgid apache module specifically dedicated to reduce performance problems with CGI.
The page http://typo3.org/development/articles/using-php-with-mod-fcgid/?tx_rlmpofficedocuments_pi1[view]=single&cHash=45a565e1de gave me all needed informations to configured this.
! Conclusion
~RoR + ~PHP5 + Apache-worker installed, everything work flawlessly :)
! Présentation
Code::Blocks (C::B) est un IDE open-source qui possède plein de qualités. Il est similaire en apparence à VisualStudio de MicroSoft, mais présente l'immense avantage de pouvoir fonctionner avec une grande variété de compilateurs et d'outils externes.
Pour en savoir plus : http://www.codeblocks.org/
! Pourquoi un article sur l'installation de C::B ?
Comme C::B est en constante évolution/amélioration, les développeurs ont décidés de ne pas offrir de release régulière (il y en a quelques-unes, mais elles sont obsolètes). ''Note : j'ai peut-être parlé vite, apparement des release plus régulières sont maintenant offertes. La suite reste valable pour qui veut installer une version à jour de C::B entre les releases.
Pour installer C::B, nous avons donc trois choix principaux.
* Installer depuis les dépôts => {{{sudo apt-get install codeblocks}}}
* Installer une nigthly build disponible sur ce forum : http://forums.codeblocks.org/index.php/board,20.0.html
* Compiler C::B depuis les sources.
Je vous laisse lire le forum pour savoir installer une nightly, dans la suite, nous allons compiler C::B.
* Téléchargement et préparation des sources
{{{
svn checkout svn://svn.berlios.de/codeblocks/trunk ~/codeblocks
cd ~/codeblocks
./bootstrap
}}}
* Compilation / Installation
{{{
./configure --with-contrib-plugins=all
make
sudo make install
}}}
/***
|Name:|InstantTimestampPlugin|
|Description:|A handy way to insert timestamps in your tiddler content|
|Version:|1.0.10 ($Rev: 3646 $)|
|Date:|$Date: 2008-02-27 02:34:38 +1000 (Wed, 27 Feb 2008) $|
|Source:|http://mptw.tiddlyspot.com/#InstantTimestampPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Usage
If you enter {ts} in your tiddler content (without the spaces) it will be replaced with a timestamp when you save the tiddler. Full list of formats:
* {ts} or {t} -> timestamp
* {ds} or {d} -> datestamp
* !ts or !t at start of line -> !!timestamp
* !ds or !d at start of line -> !!datestamp
(I added the extra ! since that's how I like it. Remove it from translations below if required)
!!Notes
* Change the timeFormat and dateFormat below to suit your preference.
* See also http://mptw2.tiddlyspot.com/#AutoCorrectPlugin
* You could invent other translations and add them to the translations array below.
***/
//{{{
config.InstantTimestamp = {
// adjust to suit
timeFormat: 'DD/0MM/YY 0hh:0mm',
dateFormat: 'DD/0MM/YY',
translations: [
[/^!ts?$/img, "'!!{{ts{'+now.formatString(config.InstantTimestamp.timeFormat)+'}}}'"],
[/^!ds?$/img, "'!!{{ds{'+now.formatString(config.InstantTimestamp.dateFormat)+'}}}'"],
// thanks Adapted Cat
[/\{ts?\}(?!\}\})/ig,"'{{ts{'+now.formatString(config.InstantTimestamp.timeFormat)+'}}}'"],
[/\{ds?\}(?!\}\})/ig,"'{{ds{'+now.formatString(config.InstantTimestamp.dateFormat)+'}}}'"]
],
excludeTags: [
"noAutoCorrect",
"noTimestamp",
"html",
"CSS",
"css",
"systemConfig",
"systemConfigDisabled",
"zsystemConfig",
"Plugins",
"Plugin",
"plugins",
"plugin",
"javascript",
"code",
"systemTheme",
"systemPalette"
],
excludeTiddlers: [
"StyleSheet",
"StyleSheetLayout",
"StyleSheetColors",
"StyleSheetPrint"
// more?
]
};
TiddlyWiki.prototype.saveTiddler_mptw_instanttimestamp = TiddlyWiki.prototype.saveTiddler;
TiddlyWiki.prototype.saveTiddler = function(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created) {
tags = tags ? tags : []; // just in case tags is null
tags = (typeof(tags) == "string") ? tags.readBracketedList() : tags;
var conf = config.InstantTimestamp;
if ( !tags.containsAny(conf.excludeTags) && !conf.excludeTiddlers.contains(newTitle) ) {
var now = new Date();
var trans = conf.translations;
for (var i=0;i<trans.length;i++) {
newBody = newBody.replace(trans[i][0], eval(trans[i][1]));
}
}
// TODO: use apply() instead of naming all args?
return this.saveTiddler_mptw_instanttimestamp(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created);
}
// you can override these in StyleSheet
setStylesheet(".ts,.ds { font-style:italic; }","instantTimestampStyles");
//}}}
! Présentation
Ce site internet basé sur TiddlyWiki rassemble mes notes, tutoriels, trucs et astuces diverses, etc.. sur les différents logiciels que je suis amené à utiliser.
Le contenu de ce site me sert de référence et d'aide-mémoire, je le partage dans l'espoir qu'il pourrait être utile à quelqu'un d'autre.
Cependant, les informations contenues sur ce site ne sont pas garanties, utilisez à vos risques et périls ;-)
! Licence
Les informations contenues sur ce site sont régies par cette [[Licence]]
! Contact
Si vous le souhaitez, vous pouvez me contacter à cette adresse: [[kubiack@gmail.com|mailto:kubiack@gmail.com]].
/***
|Name:|LessBackupsPlugin|
|Description:|Intelligently limit the number of backup files you create|
|Version:|3.0.1 ($Rev: 2320 $)|
|Date:|$Date: 2007-06-18 22:37:46 +1000 (Mon, 18 Jun 2007) $|
|Source:|http://mptw.tiddlyspot.com/#LessBackupsPlugin|
|Author:|Simon Baird|
|Email:|simon.baird@gmail.com|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Description
You end up with just backup one per year, per month, per weekday, per hour, minute, and second. So total number won't exceed about 200 or so. Can be reduced by commenting out the seconds/minutes/hours line from modes array
!!Notes
Works in IE and Firefox only. Algorithm by Daniel Baird. IE specific code by by Saq Imtiaz.
***/
//{{{
var MINS = 60 * 1000;
var HOURS = 60 * MINS;
var DAYS = 24 * HOURS;
if (!config.lessBackups) {
config.lessBackups = {
// comment out the ones you don't want or set config.lessBackups.modes in your 'tweaks' plugin
modes: [
["YYYY", 365*DAYS], // one per year for ever
["MMM", 31*DAYS], // one per month
["ddd", 7*DAYS], // one per weekday
//["d0DD", 1*DAYS], // one per day of month
["h0hh", 24*HOURS], // one per hour
["m0mm", 1*HOURS], // one per minute
["s0ss", 1*MINS], // one per second
["latest",0] // always keep last version. (leave this).
]
};
}
window.getSpecialBackupPath = function(backupPath) {
var now = new Date();
var modes = config.lessBackups.modes;
for (var i=0;i<modes.length;i++) {
// the filename we will try
var specialBackupPath = backupPath.replace(/(\.)([0-9]+\.[0-9]+)(\.html)$/,
'$1'+now.formatString(modes[i][0]).toLowerCase()+'$3')
// open the file
try {
if (config.browser.isIE) {
var fsobject = new ActiveXObject("Scripting.FileSystemObject")
var fileExists = fsobject.FileExists(specialBackupPath);
if (fileExists) {
var fileObject = fsobject.GetFile(specialBackupPath);
var modDate = new Date(fileObject.DateLastModified).valueOf();
}
}
else {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(specialBackupPath);
var fileExists = file.exists();
if (fileExists) {
var modDate = file.lastModifiedTime;
}
}
}
catch(e) {
// give up
return backupPath;
}
// expiry is used to tell if it's an 'old' one. Eg, if the month is June and there is a
// June file on disk that's more than an month old then it must be stale so overwrite
// note that "latest" should be always written because the expiration period is zero (see above)
var expiry = new Date(modDate + modes[i][1]);
if (!fileExists || now > expiry)
return specialBackupPath;
}
}
// hijack the core function
window.getBackupPath_mptw_orig = window.getBackupPath;
window.getBackupPath = function(localPath) {
return getSpecialBackupPath(getBackupPath_mptw_orig(localPath));
}
//}}}
Les informations contenues sur ce site internet sont régies par la licence suivante :
{{{
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
}}}
Cette licence vous autorise à faire usage des informations contenues sur ce site comme bon vous semble.
Le moteur du site, appelé TiddlyWiki est quand à lui régis par sa propre licence lisible dans le code-source (clic-droit, "Code-source de la page").
/***
|''Name:''|LoadRemoteFileThroughProxy (previous LoadRemoteFileHijack)|
|''Description:''|When the TiddlyWiki file is located on the web (view over http) the content of [[SiteProxy]] tiddler is added in front of the file url. If [[SiteProxy]] does not exist "/proxy/" is added. |
|''Version:''|1.1.0|
|''Date:''|mar 17, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#LoadRemoteFileHijack|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
***/
//{{{
version.extensions.LoadRemoteFileThroughProxy = {
major: 1, minor: 1, revision: 0,
date: new Date("mar 17, 2007"),
source: "http://tiddlywiki.bidix.info/#LoadRemoteFileThroughProxy"};
if (!window.bidix) window.bidix = {}; // bidix namespace
if (!bidix.core) bidix.core = {};
bidix.core.loadRemoteFile = loadRemoteFile;
loadRemoteFile = function(url,callback,params)
{
if ((document.location.toString().substr(0,4) == "http") && (url.substr(0,4) == "http")){
url = store.getTiddlerText("SiteProxy", "/proxy/") + url;
}
return bidix.core.loadRemoteFile(url,callback,params);
}
//}}}
MPTW is a distribution or edition of TiddlyWiki that includes a standard TiddlyWiki core packaged with some plugins designed to improve usability and provide a better way to organise your information. For more information see http://mptw.tiddlyspot.com/.
[[Intro]] [[Articles]] [[Admin]]
Name: MptwBlack
Background: #000
Foreground: #fff
PrimaryPale: #333
PrimaryLight: #555
PrimaryMid: #888
PrimaryDark: #aaa
SecondaryPale: #111
SecondaryLight: #222
SecondaryMid: #555
SecondaryDark: #888
TertiaryPale: #222
TertiaryLight: #666
TertiaryMid: #888
TertiaryDark: #aaa
Error: #300
This is in progress. Help appreciated.
Name: MptwBlue
Background: #fff
Foreground: #000
PrimaryPale: #cdf
PrimaryLight: #57c
PrimaryMid: #114
PrimaryDark: #012
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/***
|Name:|MptwConfigPlugin|
|Description:|Miscellaneous tweaks used by MPTW|
|Version:|1.0 ($Rev: 3646 $)|
|Date:|$Date: 2008-02-27 02:34:38 +1000 (Wed, 27 Feb 2008) $|
|Source:|http://mptw.tiddlyspot.com/#MptwConfigPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#MptwConfigPlugin|
!!Note: instead of editing this you should put overrides in MptwUserConfigPlugin
***/
//{{{
var originalReadOnly = readOnly;
var originalShowBackstage = showBackstage;
config.options.chkHttpReadOnly = false; // means web visitors can experiment with your site by clicking edit
readOnly = false; // needed because the above doesn't work any more post 2.1 (??)
showBackstage = true; // show backstage for same reason
config.options.chkInsertTabs = true; // tab inserts a tab when editing a tiddler
config.views.wikified.defaultText = ""; // don't need message when a tiddler doesn't exist
config.views.editor.defaultText = ""; // don't need message when creating a new tiddler
config.options.chkSaveBackups = true; // do save backups
config.options.txtBackupFolder = 'twbackup'; // put backups in a backups folder
config.options.chkAutoSave = (window.location.protocol == "file:"); // do autosave if we're in local file
config.mptwVersion = "2.5.3";
config.macros.mptwVersion={handler:function(place){wikify(config.mptwVersion,place);}};
if (config.options.txtTheme == '')
config.options.txtTheme = 'MptwTheme';
// add to default GettingStarted
config.shadowTiddlers.GettingStarted += "\n\nSee also [[MPTW]].";
// add select theme and palette controls in default OptionsPanel
config.shadowTiddlers.OptionsPanel = config.shadowTiddlers.OptionsPanel.replace(/(\n\-\-\-\-\nAlso see AdvancedOptions)/, "{{select{<<selectTheme>>\n<<selectPalette>>}}}$1");
// these are used by ViewTemplate
config.mptwDateFormat = 'DD/MM/YY';
config.mptwJournalFormat = 'Journal DD/MM/YY';
//}}}
Name: MptwGreen
Background: #fff
Foreground: #000
PrimaryPale: #9b9
PrimaryLight: #385
PrimaryMid: #031
PrimaryDark: #020
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
Name: MptwRed
Background: #fff
Foreground: #000
PrimaryPale: #eaa
PrimaryLight: #c55
PrimaryMid: #711
PrimaryDark: #500
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
|Name|MptwRounded|
|Description|Mptw Theme with some rounded corners (Firefox only)|
|ViewTemplate|MptwTheme##ViewTemplate|
|EditTemplate|MptwTheme##EditTemplate|
|PageTemplate|MptwTheme##PageTemplate|
|StyleSheet|##StyleSheet|
!StyleSheet
/*{{{*/
[[MptwTheme##StyleSheet]]
.tiddler,
.sliderPanel,
.button,
.tiddlyLink,
.tabContents
{ -moz-border-radius: 1em; }
.tab {
-moz-border-radius-topleft: 0.5em;
-moz-border-radius-topright: 0.5em;
}
#topMenu {
-moz-border-radius-bottomleft: 2em;
-moz-border-radius-bottomright: 2em;
}
/*}}}*/
Name: MptwSmoke
Background: #fff
Foreground: #000
PrimaryPale: #aaa
PrimaryLight: #777
PrimaryMid: #111
PrimaryDark: #000
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
|Name|MptwStandard|
|Description|Mptw Theme with the default TiddlyWiki PageLayout and Styles|
|ViewTemplate|MptwTheme##ViewTemplate|
|EditTemplate|MptwTheme##EditTemplate|
Name: MptwTeal
Background: #fff
Foreground: #000
PrimaryPale: #B5D1DF
PrimaryLight: #618FA9
PrimaryMid: #1a3844
PrimaryDark: #000
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #f8f8f8
TertiaryLight: #bbb
TertiaryMid: #999
TertiaryDark: #888
Error: #f88
|Name|MptwTheme|
|Description|Mptw Theme including custom PageLayout|
|PageTemplate|##PageTemplate|
|ViewTemplate|##ViewTemplate|
|EditTemplate|##EditTemplate|
|StyleSheet|##StyleSheet|
http://mptw.tiddlyspot.com/#MptwTheme ($Rev: 1829 $)
!PageTemplate
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<!-- horizontal MainMenu -->
<div id='topMenu' refresh='content' tiddler='MainMenu'></div>
<!-- original MainMenu menu -->
<!-- <div id='mainMenu' refresh='content' tiddler='MainMenu'></div> -->
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
!ViewTemplate
<!--{{{-->
[[MptwTheme##ViewTemplateToolbar]]
<div class="tagglyTagged" macro="tags"></div>
<div class='titleContainer'>
<span class='title' macro='view title'></span>
<span macro="miniTag"></span>
</div>
<div class='subtitle'>
(updated <span macro='view modified date {{config.mptwDateFormat?config.mptwDateFormat:"MM/0DD/YY"}}'></span>
by <span macro='view modifier link'></span>)
<!--
(<span macro='message views.wikified.createdPrompt'></span>
<span macro='view created date {{config.mptwDateFormat?config.mptwDateFormat:"MM/0DD/YY"}}'></span>)
-->
</div>
<div macro="showWhen tiddler.tags.containsAny(['css','html','pre','systemConfig']) && !tiddler.text.match('{{'+'{')">
<div class='viewer'><pre macro='view text'></pre></div>
</div>
<div macro="else">
<div class='viewer' macro='view text wikified'></div>
</div>
<div class="tagglyTagging" macro="tagglyTagging"></div>
<!--}}}-->
!ViewTemplateToolbar
<!--{{{-->
<div class='toolbar'>
<span macro="showWhenTagged systemConfig">
<span macro="toggleTag systemConfigDisable . '[[disable|systemConfigDisable]]'"></span>
</span>
<span macro="showWhenTagged systemTheme"><span macro="applyTheme"></span></span>
<span macro="showWhenTagged systemPalette"><span macro="applyPalette"></span></span>
<span macro="showWhen tiddler.tags.contains('css') || tiddler.title == 'StyleSheet'"><span macro="refreshAll"></span></span>
<span style="padding:1em;"></span>
<span macro='toolbar closeTiddler closeOthers +editTiddler deleteTiddler > fields syncing permalink references jump'></span> <span macro='newHere label:"new here"'></span>
<span macro='newJournalHere {{config.mptwJournalFormat?config.mptwJournalFormat:"MM/0DD/YY"}}'></span>
</div>
<!--}}}-->
!EditTemplate
<!--{{{-->
<div class="toolbar" macro="toolbar +saveTiddler saveCloseTiddler closeOthers -cancelTiddler cancelCloseTiddler deleteTiddler"></div>
<div class="title" macro="view title"></div>
<div class="editLabel">Title</div><div class="editor" macro="edit title"></div>
<div macro='annotations'></div>
<div class="editLabel">Content</div><div class="editor" macro="edit text"></div>
<div class="editLabel">Tags</div><div class="editor" macro="edit tags"></div>
<div class="editorFooter"><span macro="message views.editor.tagPrompt"></span><span macro="tagChooser"></span></div>
<!--}}}-->
!StyleSheet
/*{{{*/
/* a contrasting background so I can see where one tiddler ends and the other begins */
body {
background: [[ColorPalette::TertiaryLight]];
}
/* sexy colours and font for the header */
.headerForeground {
color: [[ColorPalette::PrimaryPale]];
}
.headerShadow, .headerShadow a {
color: [[ColorPalette::PrimaryMid]];
}
/* separate the top menu parts */
.headerForeground, .headerShadow {
padding: 1em 1em 0;
}
.headerForeground, .headerShadow {
font-family: 'Trebuchet MS' sans-serif;
font-weight:bold;
}
.headerForeground .siteSubtitle {
color: [[ColorPalette::PrimaryLight]];
}
.headerShadow .siteSubtitle {
color: [[ColorPalette::PrimaryMid]];
}
/* make shadow go and down right instead of up and left */
.headerShadow {
left: 1px;
top: 1px;
}
/* prefer monospace for editing */
.editor textarea, .editor input {
font-family: 'Consolas' monospace;
background-color:[[ColorPalette::TertiaryPale]];
}
/* sexy tiddler titles */
.title {
font-size: 250%;
color: [[ColorPalette::PrimaryLight]];
font-family: 'Trebuchet MS' sans-serif;
}
/* more subtle tiddler subtitle */
.subtitle {
padding:0px;
margin:0px;
padding-left:1em;
font-size: 90%;
color: [[ColorPalette::TertiaryMid]];
}
.subtitle .tiddlyLink {
color: [[ColorPalette::TertiaryMid]];
}
/* a little bit of extra whitespace */
.viewer {
padding-bottom:3px;
}
/* don't want any background color for headings */
h1,h2,h3,h4,h5,h6 {
background-color: transparent;
color: [[ColorPalette::Foreground]];
}
/* give tiddlers 3d style border and explicit background */
.tiddler {
background: [[ColorPalette::Background]];
border-right: 2px [[ColorPalette::TertiaryMid]] solid;
border-bottom: 2px [[ColorPalette::TertiaryMid]] solid;
margin-bottom: 1em;
padding:1em 2em 2em 1.5em;
}
/* make options slider look nicer */
#sidebarOptions .sliderPanel {
border:solid 1px [[ColorPalette::PrimaryLight]];
}
/* the borders look wrong with the body background */
#sidebar .button {
border-style: none;
}
/* this means you can put line breaks in SidebarOptions for readability */
#sidebarOptions br {
display:none;
}
/* undo the above in OptionsPanel */
#sidebarOptions .sliderPanel br {
display:inline;
}
/* horizontal main menu stuff */
#displayArea {
margin: 1em 15.7em 0em 1em; /* use the freed up space */
}
#topMenu br {
display: none;
}
#topMenu {
background: [[ColorPalette::PrimaryMid]];
color:[[ColorPalette::PrimaryPale]];
}
#topMenu {
padding:2px;
}
#topMenu .button, #topMenu .tiddlyLink, #topMenu a {
margin-left: 0.5em;
margin-right: 0.5em;
padding-left: 3px;
padding-right: 3px;
color: [[ColorPalette::PrimaryPale]];
font-size: 115%;
}
#topMenu .button:hover, #topMenu .tiddlyLink:hover {
background: [[ColorPalette::PrimaryDark]];
}
/* make 2.2 act like 2.1 with the invisible buttons */
.toolbar {
visibility:hidden;
}
.selected .toolbar {
visibility:visible;
}
/* experimental. this is a little borked in IE7 with the button
* borders but worth it I think for the extra screen realestate */
.toolbar { float:right; }
/* fix for TaggerPlugin. from sb56637. improved by FND */
.popup li .tagger a {
display:inline;
}
/* makes theme selector look a little better */
#sidebarOptions .sliderPanel .select .button {
padding:0.5em;
display:block;
}
#sidebarOptions .sliderPanel .select br {
display:none;
}
/* make it print a little cleaner */
@media print {
#topMenu {
display: none ! important;
}
/* not sure if we need all the importants */
.tiddler {
border-style: none ! important;
margin:0px ! important;
padding:0px ! important;
padding-bottom:2em ! important;
}
.tagglyTagging .button, .tagglyTagging .hidebutton {
display: none ! important;
}
.headerShadow {
visibility: hidden ! important;
}
.tagglyTagged .quickopentag, .tagged .quickopentag {
border-style: none ! important;
}
.quickopentag a.button, .miniTag {
display: none ! important;
}
}
/* get user styles specified in StyleSheet */
[[StyleSheet]]
/*}}}*/
|Name|MptwTrim|
|Description|Mptw Theme with a reduced header to increase useful space|
|ViewTemplate|MptwTheme##ViewTemplate|
|EditTemplate|MptwTheme##EditTemplate|
|StyleSheet|MptwTheme##StyleSheet|
|PageTemplate|##PageTemplate|
!PageTemplate
<!--{{{-->
<!-- horizontal MainMenu -->
<div id='topMenu' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<span refresh='content' tiddler='SiteTitle' style="padding-left:1em;font-weight:bold;"></span>:
<span refresh='content' tiddler='MainMenu'></span>
</div>
<div id='sidebar'>
<div id='sidebarOptions'>
<div refresh='content' tiddler='SideBarOptions'></div>
<div style="margin-left:0.1em;"
macro='slider chkTabSliderPanel SideBarTabs {{"tabs \u00bb"}} "Show Timeline, All, Tags, etc"'></div>
</div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
For upgrading. See [[ImportTiddlers]].
URL: http://mptw.tiddlyspot.com/upgrade.html
/***
|Description:|A place to put your config tweaks so they aren't overwritten when you upgrade MPTW|
See http://www.tiddlywiki.org/wiki/Configuration_Options for other options you can set. In some cases where there are clashes with other plugins it might help to rename this to zzMptwUserConfigPlugin so it gets executed last.
***/
//{{{
// example: set your preferred date format
//config.mptwDateFormat = 'MM/0DD/YY';
//config.mptwJournalFormat = 'Journal MM/0DD/YY';
// example: set the theme you want to start with
//config.options.txtTheme = 'MptwRoundTheme';
// example: switch off autosave, switch on backups and set a backup folder
//config.options.chkSaveBackups = true;
//config.options.chkAutoSave = false;
//config.options.txtBackupFolder = 'backups';
// uncomment to disable 'new means new' functionality for the new journal macro
//config.newMeansNewForJournalsToo = false;
//}}}
/***
|Name:|NewHerePlugin|
|Description:|Creates the new here and new journal macros|
|Version:|3.0 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#NewHerePlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{
merge(config.macros, {
newHere: {
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
wikify("<<newTiddler "+paramString+" tag:[["+tiddler.title+"]]>>",place,null,tiddler);
}
},
newJournalHere: {
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
wikify("<<newJournal "+paramString+" tag:[["+tiddler.title+"]]>>",place,null,tiddler);
}
}
});
//}}}
/***
|Name:|NewMeansNewPlugin|
|Description:|If 'New Tiddler' already exists then create 'New Tiddler (1)' and so on|
|Version:|1.1.1 ($Rev: 2263 $)|
|Date:|$Date: 2007-06-13 04:22:32 +1000 (Wed, 13 Jun 2007) $|
|Source:|http://mptw.tiddlyspot.com/empty.html#NewMeansNewPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Note: I think this should be in the core
***/
//{{{
// change this or set config.newMeansNewForJournalsToo it in MptwUuserConfigPlugin
if (config.newMeansNewForJournalsToo == undefined) config.newMeansNewForJournalsToo = true;
String.prototype.getNextFreeName = function() {
var numberRegExp = / \(([0-9]+)\)$/;
var match = numberRegExp.exec(this);
if (match) {
var num = parseInt(match[1]) + 1;
return this.replace(numberRegExp," ("+num+")");
}
else {
return this + " (1)";
}
}
config.macros.newTiddler.checkForUnsaved = function(newName) {
var r = false;
story.forEachTiddler(function(title,element) {
if (title == newName)
r = true;
});
return r;
}
config.macros.newTiddler.getName = function(newName) {
while (store.getTiddler(newName) || config.macros.newTiddler.checkForUnsaved(newName))
newName = newName.getNextFreeName();
return newName;
}
config.macros.newTiddler.onClickNewTiddler = function()
{
var title = this.getAttribute("newTitle");
if(this.getAttribute("isJournal") == "true") {
title = new Date().formatString(title.trim());
}
// ---- these three lines should be the only difference between this and the core onClickNewTiddler
if (config.newMeansNewForJournalsToo || this.getAttribute("isJournal") != "true")
title = config.macros.newTiddler.getName(title);
var params = this.getAttribute("params");
var tags = params ? params.split("|") : [];
var focus = this.getAttribute("newFocus");
var template = this.getAttribute("newTemplate");
var customFields = this.getAttribute("customFields");
if(!customFields && !store.isShadowTiddler(title))
customFields = String.encodeHashMap(config.defaultCustomFields);
story.displayTiddler(null,title,template,false,null,null);
var tiddlerElem = story.getTiddler(title);
if(customFields)
story.addCustomFields(tiddlerElem,customFields);
var text = this.getAttribute("newText");
if(typeof text == "string")
story.getTiddlerField(title,"text").value = text.format([title]);
for(var t=0;t<tags.length;t++)
story.setTiddlerTag(title,tags[t],+1);
story.focusTiddler(title,focus);
return false;
};
//}}}
/***
|''Name:''|PasswordOptionPlugin|
|''Description:''|Extends TiddlyWiki options with non encrypted password option.|
|''Version:''|1.0.2|
|''Date:''|Apr 19, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#PasswordOptionPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (Beta 5)|
***/
//{{{
version.extensions.PasswordOptionPlugin = {
major: 1, minor: 0, revision: 2,
date: new Date("Apr 19, 2007"),
source: 'http://tiddlywiki.bidix.info/#PasswordOptionPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
license: '[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D]]',
coreVersion: '2.2.0 (Beta 5)'
};
config.macros.option.passwordCheckboxLabel = "Save this password on this computer";
config.macros.option.passwordInputType = "password"; // password | text
setStylesheet(".pasOptionInput {width: 11em;}\n","passwordInputTypeStyle");
merge(config.macros.option.types, {
'pas': {
elementType: "input",
valueField: "value",
eventName: "onkeyup",
className: "pasOptionInput",
typeValue: config.macros.option.passwordInputType,
create: function(place,type,opt,className,desc) {
// password field
config.macros.option.genericCreate(place,'pas',opt,className,desc);
// checkbox linked with this password "save this password on this computer"
config.macros.option.genericCreate(place,'chk','chk'+opt,className,desc);
// text savePasswordCheckboxLabel
place.appendChild(document.createTextNode(config.macros.option.passwordCheckboxLabel));
},
onChange: config.macros.option.genericOnChange
}
});
merge(config.optionHandlers['chk'], {
get: function(name) {
// is there an option linked with this chk ?
var opt = name.substr(3);
if (config.options[opt])
saveOptionCookie(opt);
return config.options[name] ? "true" : "false";
}
});
merge(config.optionHandlers, {
'pas': {
get: function(name) {
if (config.options["chk"+name]) {
return encodeCookie(config.options[name].toString());
} else {
return "";
}
},
set: function(name,value) {config.options[name] = decodeCookie(value);}
}
});
// need to reload options to load passwordOptions
loadOptionsCookie();
/*
if (!config.options['pasPassword'])
config.options['pasPassword'] = '';
merge(config.optionsDesc,{
pasPassword: "Test password"
});
*/
//}}}
/***
|Name:|PrettyDatesPlugin|
|Description:|Provides a new date format ('pppp') that displays times such as '2 days ago'|
|Version:|1.0 ($Rev: 3646 $)|
|Date:|$Date: 2008-02-27 02:34:38 +1000 (Wed, 27 Feb 2008) $|
|Source:|http://mptw.tiddlyspot.com/#PrettyDatesPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Notes
* If you want to you can rename this plugin. :) Some suggestions: LastUpdatedPlugin, RelativeDatesPlugin, SmartDatesPlugin, SexyDatesPlugin.
* Inspired by http://ejohn.org/files/pretty.js
***/
//{{{
Date.prototype.prettyDate = function() {
var diff = (((new Date()).getTime() - this.getTime()) / 1000);
var day_diff = Math.floor(diff / 86400);
if (isNaN(day_diff)) return "";
else if (diff < 0) return "in the future";
else if (diff < 60) return "just now";
else if (diff < 120) return "1 minute ago";
else if (diff < 3600) return Math.floor(diff/60) + " minutes ago";
else if (diff < 7200) return "1 hour ago";
else if (diff < 86400) return Math.floor(diff/3600) + " hours ago";
else if (day_diff == 1) return "Yesterday";
else if (day_diff < 7) return day_diff + " days ago";
else if (day_diff < 14) return "a week ago";
else if (day_diff < 31) return Math.ceil(day_diff/7) + " weeks ago";
else if (day_diff < 62) return "a month ago";
else if (day_diff < 365) return "about " + Math.ceil(day_diff/31) + " months ago";
else if (day_diff < 730) return "a year ago";
else return Math.ceil(day_diff/365) + " years ago";
}
Date.prototype.formatString_orig_mptw = Date.prototype.formatString;
Date.prototype.formatString = function(template) {
return this.formatString_orig_mptw(template).replace(/pppp/,this.prettyDate());
}
// for MPTW. otherwise edit your ViewTemplate as required.
// config.mptwDateFormat = 'pppp (DD/MM/YY)';
config.mptwDateFormat = 'pppp';
//}}}
/***
|Name:|QuickOpenTagPlugin|
|Description:|Changes tag links to make it easier to open tags as tiddlers|
|Version:|3.0.1 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#QuickOpenTagPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{
config.quickOpenTag = {
dropdownChar: (document.all ? "\u25bc" : "\u25be"), // the little one doesn't work in IE?
createTagButton: function(place,tag,excludeTiddler) {
// little hack so we can do this: <<tag PrettyTagName|RealTagName>>
var splitTag = tag.split("|");
var pretty = tag;
if (splitTag.length == 2) {
tag = splitTag[1];
pretty = splitTag[0];
}
var sp = createTiddlyElement(place,"span",null,"quickopentag");
createTiddlyText(createTiddlyLink(sp,tag,false),pretty);
var theTag = createTiddlyButton(sp,config.quickOpenTag.dropdownChar,
config.views.wikified.tag.tooltip.format([tag]),onClickTag);
theTag.setAttribute("tag",tag);
if (excludeTiddler)
theTag.setAttribute("tiddler",excludeTiddler);
return(theTag);
},
miniTagHandler: function(place,macroName,params,wikifier,paramString,tiddler) {
var tagged = store.getTaggedTiddlers(tiddler.title);
if (tagged.length > 0) {
var theTag = createTiddlyButton(place,config.quickOpenTag.dropdownChar,
config.views.wikified.tag.tooltip.format([tiddler.title]),onClickTag);
theTag.setAttribute("tag",tiddler.title);
theTag.className = "miniTag";
}
},
allTagsHandler: function(place,macroName,params) {
var tags = store.getTags(params[0]);
var filter = params[1]; // new feature
var ul = createTiddlyElement(place,"ul");
if(tags.length == 0)
createTiddlyElement(ul,"li",null,"listTitle",this.noTags);
for(var t=0; t<tags.length; t++) {
var title = tags[t][0];
if (!filter || (title.match(new RegExp('^'+filter)))) {
var info = getTiddlyLinkInfo(title);
var theListItem =createTiddlyElement(ul,"li");
var theLink = createTiddlyLink(theListItem,tags[t][0],true);
var theCount = " (" + tags[t][1] + ")";
theLink.appendChild(document.createTextNode(theCount));
var theDropDownBtn = createTiddlyButton(theListItem," " +
config.quickOpenTag.dropdownChar,this.tooltip.format([tags[t][0]]),onClickTag);
theDropDownBtn.setAttribute("tag",tags[t][0]);
}
}
},
// todo fix these up a bit
styles: [
"/*{{{*/",
"/* created by QuickOpenTagPlugin */",
".tagglyTagged .quickopentag, .tagged .quickopentag ",
" { margin-right:1.2em; border:1px solid #eee; padding:2px; padding-right:0px; padding-left:1px; }",
".quickopentag .tiddlyLink { padding:2px; padding-left:3px; }",
".quickopentag a.button { padding:1px; padding-left:2px; padding-right:2px;}",
"/* extra specificity to make it work right */",
"#displayArea .viewer .quickopentag a.button, ",
"#displayArea .viewer .quickopentag a.tiddyLink, ",
"#mainMenu .quickopentag a.tiddyLink, ",
"#mainMenu .quickopentag a.tiddyLink ",
" { border:0px solid black; }",
"#displayArea .viewer .quickopentag a.button, ",
"#mainMenu .quickopentag a.button ",
" { margin-left:0px; padding-left:2px; }",
"#displayArea .viewer .quickopentag a.tiddlyLink, ",
"#mainMenu .quickopentag a.tiddlyLink ",
" { margin-right:0px; padding-right:0px; padding-left:0px; margin-left:0px; }",
"a.miniTag {font-size:150%;} ",
"#mainMenu .quickopentag a.button ",
" /* looks better in right justified main menus */",
" { margin-left:0px; padding-left:2px; margin-right:0px; padding-right:0px; }",
"#topMenu .quickopentag { padding:0px; margin:0px; border:0px; }",
"#topMenu .quickopentag .tiddlyLink { padding-right:1px; margin-right:0px; }",
"#topMenu .quickopentag .button { padding-left:1px; margin-left:0px; border:0px; }",
"/*}}}*/",
""].join("\n"),
init: function() {
// we fully replace these builtins. can't hijack them easily
window.createTagButton = this.createTagButton;
config.macros.allTags.handler = this.allTagsHandler;
config.macros.miniTag = { handler: this.miniTagHandler };
config.shadowTiddlers["QuickOpenTagStyles"] = this.styles;
store.addNotification("QuickOpenTagStyles",refreshStyles);
}
}
config.quickOpenTag.init();
//}}}
Lorsque l'on met à jour une instance en fonctionnement de Redmine, il est nécessaire de prendre quelques précautions : http://www.redmine.org/wiki/redmine/RedmineUpgrade#Step-3-Perform-the-upgrade
* Faire les sauvegardes
* Effectuer la mise à jour : {{{svn update}}}
* Contrôler les droits et le propriétaire des fichiers {{{redmine/log}}} , {{{redmine/file}}} et {{{redmine/tmp}}} : ils doivent appartenir à l'utilisateur chargé de lancer redmine ({{{www-data}}} dans mon cas).
* Effectuer les migrations des bases de données
{{{
sudo rake db:migrate RAILS_ENV="production"
sudo rake db:migrate_plugins RAILS_ENV="production"
}}}
* Faire un peu de nettoyage
{{{
sudo rake tmp:cache:clear
sudo rake tmp:sessions:clear
}}}
* En cas d'erreur 500 avec passenger, enlever le fichier {{{redmine/public/.htaccess}}}
* Lors des mises à jour de Ruby, il peut être nécessaire de mettre à jour passenger :
{{{
gem update --system
gem update passenger
passenger-install-apache2-module
}}}
Bien sûr, pour effectuer toutes ces tâches automatiquement, j'ai écrit un script :
<<<
{{{
#! /bin/sh
# /var/www/redmine-update.sh
## Met à jour Redmine via SVN
# 0 - Stop apache
/etc/init.d/apache2 stop
# 1 - Sauvegardes du répertoire Redmine et de la base MySQL
tar cjf redmine-`date +%F`-backup.tar.bz2 redmine
mysqldump -u<utilisateur> -p<mot de passe> --all-databases | bzip2 -z >mysql-`date +%F`-backup.bz2
# 2 - Met à jour Redmine
svn update redmine
# 3 - Mise à jour des BDD
cd redmine
rake db:migrate RAILS_ENV="production"
rake db:migrate:upgrade_plugin_migrations RAILS_ENV="production"
rake db:migrate_plugins RAILS_ENV="production"
# 4 - Nettoyage
rake tmp:cache:clear
rake tmp:sessions:clear
rake config/initializers/session_store.rb
# 5 - Configure les droits
chown www-data:www-data config/environment.rb
# 6 - Relance apache
/etc/init.d/apache2 restart
}}}
<<<
J'ai placé ce script dans {{{/var/www}}}, à coté du répertoire {{{/var/www/redmine}}} qui contient l'install de Redmine.
Il doit être lancé par ROOT.
/***
|Name:|RenameTagsPlugin|
|Description:|Allows you to easily rename or delete tags across multiple tiddlers|
|Version:|3.0 ($Rev: 5501 $)|
|Date:|$Date: 2008-06-10 23:11:55 +1000 (Tue, 10 Jun 2008) $|
|Source:|http://mptw.tiddlyspot.com/#RenameTagsPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License|http://mptw.tiddlyspot.com/#TheBSDLicense|
Rename a tag and you will be prompted to rename it in all its tagged tiddlers.
***/
//{{{
config.renameTags = {
prompts: {
rename: "Rename the tag '%0' to '%1' in %2 tidder%3?",
remove: "Remove the tag '%0' from %1 tidder%2?"
},
removeTag: function(tag,tiddlers) {
store.suspendNotifications();
for (var i=0;i<tiddlers.length;i++) {
store.setTiddlerTag(tiddlers[i].title,false,tag);
}
store.resumeNotifications();
store.notifyAll();
},
renameTag: function(oldTag,newTag,tiddlers) {
store.suspendNotifications();
for (var i=0;i<tiddlers.length;i++) {
store.setTiddlerTag(tiddlers[i].title,false,oldTag); // remove old
store.setTiddlerTag(tiddlers[i].title,true,newTag); // add new
}
store.resumeNotifications();
store.notifyAll();
},
storeMethods: {
saveTiddler_orig_renameTags: TiddlyWiki.prototype.saveTiddler,
saveTiddler: function(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created) {
if (title != newTitle) {
var tagged = this.getTaggedTiddlers(title);
if (tagged.length > 0) {
// then we are renaming a tag
if (confirm(config.renameTags.prompts.rename.format([title,newTitle,tagged.length,tagged.length>1?"s":""])))
config.renameTags.renameTag(title,newTitle,tagged);
if (!this.tiddlerExists(title) && newBody == "")
// dont create unwanted tiddler
return null;
}
}
return this.saveTiddler_orig_renameTags(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created);
},
removeTiddler_orig_renameTags: TiddlyWiki.prototype.removeTiddler,
removeTiddler: function(title) {
var tagged = this.getTaggedTiddlers(title);
if (tagged.length > 0)
if (confirm(config.renameTags.prompts.remove.format([title,tagged.length,tagged.length>1?"s":""])))
config.renameTags.removeTag(title,tagged);
return this.removeTiddler_orig_renameTags(title);
}
},
init: function() {
merge(TiddlyWiki.prototype,this.storeMethods);
}
}
config.renameTags.init();
//}}}
/***
|Name:|SaveCloseTiddlerPlugin|
|Description:|Provides two extra toolbar commands, saveCloseTiddler and cancelCloseTiddler|
|Version:|3.0 ($Rev: 5502 $)|
|Date:|$Date: 2008-06-10 23:31:39 +1000 (Tue, 10 Jun 2008) $|
|Source:|http://mptw.tiddlyspot.com/#SaveCloseTiddlerPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
To use these you must add them to the tool bar in your EditTemplate
***/
//{{{
merge(config.commands,{
saveCloseTiddler: {
text: 'done/close',
tooltip: 'Save changes to this tiddler and close it',
handler: function(ev,src,title) {
var closeTitle = title;
var newTitle = story.saveTiddler(title,ev.shiftKey);
if (newTitle)
closeTitle = newTitle;
return config.commands.closeTiddler.handler(ev,src,closeTitle);
}
},
cancelCloseTiddler: {
text: 'cancel/close',
tooltip: 'Undo changes to this tiddler and close it',
handler: function(ev,src,title) {
// the same as closeTiddler now actually
return config.commands.closeTiddler.handler(ev,src,title);
}
}
});
//}}}
/***
|Name:|SelectThemePlugin|
|Description:|Lets you easily switch theme and palette|
|Version:|1.0.1 ($Rev: 3646 $)|
|Date:|$Date: 2008-02-27 02:34:38 +1000 (Wed, 27 Feb 2008) $|
|Source:|http://mptw.tiddlyspot.com/#SelectThemePlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!Notes
* Borrows largely from ThemeSwitcherPlugin by Martin Budden http://www.martinswiki.com/#ThemeSwitcherPlugin
* Theme is cookie based. But set a default by setting config.options.txtTheme in MptwConfigPlugin (for example)
* Palette is not cookie based. It actually overwrites your ColorPalette tiddler when you select a palette, so beware.
!Usage
* {{{<<selectTheme>>}}} makes a dropdown selector
* {{{<<selectPalette>>}}} makes a dropdown selector
* {{{<<applyTheme>>}}} applies the current tiddler as a theme
* {{{<<applyPalette>>}}} applies the current tiddler as a palette
* {{{<<applyTheme TiddlerName>>}}} applies TiddlerName as a theme
* {{{<<applyPalette TiddlerName>>}}} applies TiddlerName as a palette
***/
//{{{
config.macros.selectTheme = {
label: {
selectTheme:"select theme",
selectPalette:"select palette"
},
prompt: {
selectTheme:"Select the current theme",
selectPalette:"Select the current palette"
},
tags: {
selectTheme:'systemTheme',
selectPalette:'systemPalette'
}
};
config.macros.selectTheme.handler = function(place,macroName)
{
var btn = createTiddlyButton(place,this.label[macroName],this.prompt[macroName],this.onClick);
// want to handle palettes and themes with same code. use mode attribute to distinguish
btn.setAttribute('mode',macroName);
};
config.macros.selectTheme.onClick = function(ev)
{
var e = ev ? ev : window.event;
var popup = Popup.create(this);
var mode = this.getAttribute('mode');
var tiddlers = store.getTaggedTiddlers(config.macros.selectTheme.tags[mode]);
// for default
if (mode == "selectPalette") {
var btn = createTiddlyButton(createTiddlyElement(popup,'li'),"(default)","default color palette",config.macros.selectTheme.onClickTheme);
btn.setAttribute('theme',"(default)");
btn.setAttribute('mode',mode);
}
for(var i=0; i<tiddlers.length; i++) {
var t = tiddlers[i].title;
var name = store.getTiddlerSlice(t,'Name');
var desc = store.getTiddlerSlice(t,'Description');
var btn = createTiddlyButton(createTiddlyElement(popup,'li'), name?name:t, desc?desc:config.macros.selectTheme.label['mode'], config.macros.selectTheme.onClickTheme);
btn.setAttribute('theme',t);
btn.setAttribute('mode',mode);
}
Popup.show();
return stopEvent(e);
};
config.macros.selectTheme.onClickTheme = function(ev)
{
var mode = this.getAttribute('mode');
var theme = this.getAttribute('theme');
if (mode == 'selectTheme')
story.switchTheme(theme);
else // selectPalette
config.macros.selectTheme.updatePalette(theme);
return false;
};
config.macros.selectTheme.updatePalette = function(title)
{
if (title != "") {
store.deleteTiddler("ColorPalette");
if (title != "(default)")
store.saveTiddler("ColorPalette","ColorPalette",store.getTiddlerText(title),
config.options.txtUserName,undefined,"");
refreshAll();
if(config.options.chkAutoSave)
saveChanges(true);
}
};
config.macros.applyTheme = {
label: "apply",
prompt: "apply this theme or palette" // i'm lazy
};
config.macros.applyTheme.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
var useTiddler = params[0] ? params[0] : tiddler.title;
var btn = createTiddlyButton(place,this.label,this.prompt,config.macros.selectTheme.onClickTheme);
btn.setAttribute('theme',useTiddler);
btn.setAttribute('mode',macroName=="applyTheme"?"selectTheme":"selectPalette"); // a bit untidy here
}
config.macros.selectPalette = config.macros.selectTheme;
config.macros.applyPalette = config.macros.applyTheme;
config.macros.refreshAll = { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
createTiddlyButton(place,"refresh","refresh layout and styles",function() { refreshAll(); });
}};
//}}}
! Objectifs
Servir un répertoire contenant des fichiers pour des personnes authentifiées
! Procédure
!! Création du fichier d'authentification
Ce fichier contiendra les paires login/passwd des utilisateurs autorisés
<<<
{{{
htpasswd -c /chemin/vers/le/fichier/passwd utilisateur
> Entrez le mot de passe 2 fois
## -c crée le fichier, à n'effectuer que la première fois
## pour ajouter un utilisateur :
htpasswd /chemin/vers/le/fichier/passwd utilisateur2
> Entrez le mot de passe 2 fois
}}}
<<<
!! Configuration du vhost
Dans le fichier de configuration du vhost (ou dans le fichier de config de apache, ou dans un .htaccess)
<<<
{{{
<Directory /mon/repertoire>
RewriteEngine on
Options Indexes FollowSymLinks MultiViews -ExecCGI
Order allow,deny
Allow from all
AllowOverride All
AuthType Basic
AuthName "Zone restreinte"
AuthUserFile /chemin/vers/fichier/passwd
Require valid-user
</Directory>
}}}
<<<
trucs et astuces informatiques
<tabs AideMemoire>
<tab Format données>
!1 -- Format des données
|!Option|!Syntaxe|!Résultat|!Anglais|h
|texte en gras|{{{''gras''}}}|''gras''|''bold''|
|texte en italique|{{{//italique//}}}|//italique//|//italic//|
|texte souligné|{{{__souligné__}}}|__souligné__|__underlined__|
|texte barré|{{{--barré--}}}|--barré--|--strikethrough--|
|texte mis en exposant|{{{texte^^exposant^^}}}|texte^^exposant^^|text^^super^^|
|texte mis en indice|{{{texte~~indice~~}}}|texte~~indice~~|text~~sub~~|
|texte mis en évidence|{{{@@mis en évidence@@}}}|@@mis en évidence@@|@@highlighted@@|
|texte en de taille fixe|{{{ {{{taille fixe}}} }}}|{{{taille fixe}}}|{{{monospaced}}}|
|texte bleu|{{{@@color:#00f;texte bleu@@}}}|@@color:#00f;texte bleu@@| .|
|fond vert|{{{@@bgcolor:#0f0;fond vert@@}}}|@@bgcolor:#0f0;fond vert@@| .|
</tab>
<tab Images>
!2 - Format des images
Les 4 formats possibles pour intégrer des images sont les suivants :
|!Affichage|!Syntaxe|!Exemple|h
|Affichage simple d'une image|{{{[img[nom_fichier.ext]]}}}<br><br>{{{[img[Francais.gif]]}}}|[img[Francais.gif]]|
|~|{{{[img[titre|nom_fichier.ext]]}}}<br><br>{{{[img[Ceci est un message d'aide|Francais.gif]]}}}|[img[Ceci est un message d'aide|Francais.gif]]|
|Image servant de lien vers une autre page|{{{[img[nom_fichier.ext][lien]]}}}<br><br>{{{[img[Francais.gif][images/index.html]]}}}|[img[Francais.gif][images/index.html]]|
|~|{{{[img[titre|nom_fichier.ext][lien]]}}}<br><br>{{{[img[Ceci est un message d'aide|Francais.gif][images/index.html]]}}}|[img[Ceci est un message d'aide|Francais.gif][images/index.html]]|
Le message d'aide est optionnel.
[<img[En Français|Francais.gif][images/Francais.gif]][>img[En Anglais|Anglais.gif][images/Anglais.gif]] On peut aussi insérer des images à gauche ou à droite d'un texte, respectivement avec {{{[<img[}}}) et avec {{{[>img[}}}). Il est aussi possible de s'affranchir de ces images @@clear(left):clear(right):display(block) en utilisant des codes CSS @@ tels que {{{@@clear(left):clear(right):display(block) code CSS @@}}}
{{{
[<img[En Français|Francais.gif][images/Francais.gif]][>img[En Anglais|Anglais.gif][images/Anglais.gif]] On peut aussi insérer des images à gauche ou à droite d'un texte, respectivement avec {{{[<img[}}}) et avec {{{[>img[}}}). Il est aussi possible de s'affranchir de ces images @@clear(left):clear(right):display(block) en utilisant des codes CSS @@
}}}
</tab>
<tab Listes et Citations>
!3 -- Listes (//Lists//) et citations (//Blockquotes//)
{{{
* liste simple de niveau 1
** liste simple de niveau 2
*** liste simple de niveau 3
**** liste simple de niveau 4
***** liste simple de niveau 5
# liste numérotée de niveau 1
## liste numérotée de niveau 2
### liste numérotée de niveau 3
#### liste numérotée de niveau 4
##### liste numérotée de niveau 5
; liste de definition : terme défini
: liste de definition : description
}}}
<<<
* liste simple de niveau 1
** liste simple de niveau 2
*** liste simple de niveau 3
**** liste simple de niveau 4
***** liste simple de niveau 5
# liste numérotée de niveau 1
## liste numérotée de niveau 2
### liste numérotée de niveau 3
#### liste numérotée de niveau 4
##### liste numérotée de niveau 5
; liste de definition : terme défini
: liste de definition : description
<<<
{{{
> citation de niveau 1
>> citation de niveau 2
>>> citation de niveau 3
>>>> citation de niveau 4
>>>>> citation de niveau 5
<<<
citation
<<<
}}}
<<<
> citation de niveau 1
>> citation de niveau 2
>>> citation de niveau 3
>>>> citation de niveau 4
>>>>> citation de niveau 5
> citation
<<<
</tab>
<tab Niveaux de Titres>
!4 -- Titre de niveaux (//Titles//)
{{{
!Titre de niveau 1
!!Titre de niveau 2
!!!Titre de niveau 3
!!!!Titre de niveau 4
!!!!!Titre de niveau 5
}}}
<<<
!Titre de niveau 1
!!Titre de niveau 2
!!!Titre de niveau 3
!!!!Titre de niveau 4
!!!!!Titre de niveau 5
<<<
</tab>
<tab Tableaux>
!5 - Tableaux (//Tables//)
{{{
|classe CSS|k
|!titre de colonne 1|!titre de colonne 2|h
|ligne 1, colonne 1|ligne 1, colonne 2|
|ligne 2, colonne 1|ligne 2, colonne 2|
|>|Plusieurs colonnes de large|
|Plusieurs lignes de hauteur| … |
|~| … |
|texte aligné à gauche |espace laissé à droite |
| texte aligné à droite| espace laissé à gauche|
| texte centré | espace laissé à gauche ''et'' à droite |
|Propriété_CSS:valeur;…| … |
|Légende|c
}}}
<<<
|classe CSS|k
|!titre de colonne 1|!titre de colonne 2|h
|ligne 1, colonne 1|ligne 1, colonne 2|
|ligne 2, colonne 1|ligne 2, colonne 2|
|>|Plusieurs colonnes de large|
|Plusieurs lignes de hauteur| … |
|~| … |
|texte aligné à gauche |espace laissé à droite |
| texte aligné à droite| espace laissé à gauche|
| texte centré | espace laissé à gauche ''et'' à droite |
|Propriété_CSS:valeur;…| … |
|Légende|c
<<<
''Note :''
* Le marqueur {{{>}}} fusionne horizontalement une cellule avec celle immédiatement située à sa droite.
* Le marqueur {{{~}}} fusionne verticalement une cellule avec celle immédiatement située au dessus d'elle.
</tab>
<tab Liens>
!6 - Liens et hyperliens
* Les liens
|!Détails|!Syntaxe|!Exemple|!Résultat|h
|Lien interne ou externe|{{{[[texte|WikiWord ou URL]]}}}|{{{[[Page index.html en local|index.html]]}}}|[[Page index.html en local|index.html]]|
|Image|{{{[img[nom de l'image|chemin/image.ext]]}}}|{{{[img[Français|Francais.gif]]}}}|[img[Français|Francais.gif]]|
* Les //~WikiWord// sont des mots réservés qui sont automatiquement transformés en hyperliens vers leurs éléments (//tiddlers//) respectifs
** la transformation automatique peut être annulée en faisant précéder les //~WikiWord// par un signe //tilde// ({{{~}}}). Exemple : {{{~WikiWord}}}
* Les [[LiensEnjolivés]] (//~PrettyLinks//) sont entourés de doubles crochets et contiennent le nom de l'élément concerné. Exemple : {{{[[nom de l'élément]]}}}
** En complément, un titre générique ou une description peuvent être ajoutés. Ils doivent être séparés par un caractère //pipe// ({{{|}}})) ce qui donne {{{[[titre|lien]]}}}<br>'''N.B.:''' Dans ce cas, la cible peut être soit un fichier local, soit l'URL d'un site Web local ou distant.
</tab>
<tab Mise en Page>
!Eléments de Présentation & Feuilles de style
Les //éléments// suivis par ^^(*)^^ ont été modifiés sur ce site.
|>|>| ![[PageTemplate]]^^(*)^^ |
|>|>| [[SiteTitle]]^^(*)^^ - [[SiteSubtitle]]^^(*)^^ |
| [[MainMenu]]^^(*)^^ |[[DefaultTiddlers]]^^(*)^^<br>[[HeaderToolbar]]^^(+)^^<br><br>[[ViewTemplate]]<br>[[EditTemplate]]|[[SideBarOptions]]^^(*)^^ |
|~|~| [[OptionsPanel]]<br>[[AdvancedOptions]] |
|~|~| [[SideBarTabs]] |
|>|>| [[SiteUrl]]^^(*)^^ |
|>|>| ![[SideBarTabs]] |
| [[Timeline|TabTimeline]] | [[All|TabAll]] | [[Tags|TabTags]] |
|>|>| [[More|TabMore]] |
| [[Missing|TabMoreMissing]] | [[Orphans|TabMoreOrphans]] | [[Shadowed|TabMoreShadowed]] |
|>|>|>| ![[StyleSheet]]^^(*)^^ |
| [[Layout|StyleSheetLayout]] | [[Colors|StyleSheetColors]] | [[Print|StyleSheetPrint]] | [[Palette|ColorPalette]] |
</tab>
<tab Divers>
!8 -- Divers
* du code HTML peut être intégré directement dans un élément, en l'entourant par les codes HTML suivants : {{{<html> … </html>}}}
* {{{<br>}}} force un saut de ligne (comme en HTML)
* {{{----}}} insère une ligne horizontale (comme le code {{{<HR> en HTML}}})
* {{{<<Nom de la macro>>}}} appelle l'élément correspondant __//nom de la macro//__
* Pour masquer certaines parties d'un élément et ne pas le faire afficher, il doit être entouré des codes suivants :
** début de la zone de commentaire : {{{/%}}}
** fin de la zone de commentaire : {{{%/}}}
</tab>
</tabs>
Note : ce tiddler a été honteusement repompé de http://www.tiddlywiki.fr/
<<tabs txtMoreTab "Tags" "All Tags" TabAllTags "Miss" "Missing tiddlers" TabMoreMissing "Orph" "Orphaned tiddlers" TabMoreOrphans "Shad" "Shadowed tiddlers" TabMoreShadowed>>
<<allTags excludeLists [a-z]>>
/***
|Name:|TagglyTaggingPlugin|
|Description:|tagglyTagging macro is a replacement for the builtin tagging macro in your ViewTemplate|
|Version:|3.3.1 ($Rev: 9828 $)|
|Date:|$Date: 2009-06-03 21:38:41 +1000 (Wed, 03 Jun 2009) $|
|Source:|http://mptw.tiddlyspot.com/#TagglyTaggingPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!Notes
See http://mptw.tiddlyspot.com/#TagglyTagging
***/
//{{{
merge(String.prototype,{
parseTagExpr: function(debug) {
if (this.trim() == "")
return "(true)";
var anyLogicOp = /(!|&&|\|\||\(|\))/g;
var singleLogicOp = /^(!|&&|\|\||\(|\))$/;
var spaced = this.
// because square brackets in templates are no good
// this means you can use [(With Spaces)] instead of [[With Spaces]]
replace(/\[\(/g," [[").
replace(/\)\]/g,"]] ").
// space things out so we can use readBracketedList. tricky eh?
replace(anyLogicOp," $1 ");
var expr = "";
var tokens = spaced.readBracketedList(false); // false means don't uniq the list. nice one JR!
for (var i=0;i<tokens.length;i++)
if (tokens[i].match(singleLogicOp))
expr += tokens[i];
else
expr += "tiddler.tags.contains('%0')".format([tokens[i].replace(/'/,"\\'")]); // fix single quote bug. still have round bracket bug i think
if (debug)
alert(expr);
return '('+expr+')';
}
});
merge(TiddlyWiki.prototype,{
getTiddlersByTagExpr: function(tagExpr,sortField) {
var result = [];
var expr = tagExpr.parseTagExpr();
store.forEachTiddler(function(title,tiddler) {
if (eval(expr))
result.push(tiddler);
});
if(!sortField)
sortField = "title";
result.sort(function(a,b) {return a[sortField] < b[sortField] ? -1 : (a[sortField] == b[sortField] ? 0 : +1);});
return result;
}
});
config.taggly = {
// for translations
lingo: {
labels: {
asc: "\u2191", // down arrow
desc: "\u2193", // up arrow
title: "title",
modified: "modified",
created: "created",
show: "+",
hide: "-",
normal: "normal",
group: "group",
commas: "commas",
sitemap: "sitemap",
numCols: "cols\u00b1", // plus minus sign
label: "Tagged as '%0':",
exprLabel: "Matching tag expression '%0':",
excerpts: "excerpts",
descr: "descr",
slices: "slices",
contents: "contents",
sliders: "sliders",
noexcerpts: "title only",
noneFound: "(none)"
},
tooltips: {
title: "Click to sort by title",
modified: "Click to sort by modified date",
created: "Click to sort by created date",
show: "Click to show tagging list",
hide: "Click to hide tagging list",
normal: "Click to show a normal ungrouped list",
group: "Click to show list grouped by tag",
sitemap: "Click to show a sitemap style list",
commas: "Click to show a comma separated list",
numCols: "Click to change number of columns",
excerpts: "Click to show excerpts",
descr: "Click to show the description slice",
slices: "Click to show all slices",
contents: "Click to show entire tiddler contents",
sliders: "Click to show tiddler contents in sliders",
noexcerpts: "Click to show entire title only"
},
tooDeepMessage: "* //sitemap too deep...//"
},
config: {
showTaggingCounts: true,
listOpts: {
// the first one will be the default
sortBy: ["title","modified","created"],
sortOrder: ["asc","desc"],
hideState: ["show","hide"],
listMode: ["normal","group","sitemap","commas"],
numCols: ["1","2","3","4","5","6"],
excerpts: ["noexcerpts","excerpts","descr","slices","contents","sliders"]
},
valuePrefix: "taggly.",
excludeTags: ["excludeLists","excludeTagging"],
excerptSize: 50,
excerptMarker: "/%"+"%/",
siteMapDepthLimit: 25
},
getTagglyOpt: function(title,opt) {
var val = store.getValue(title,this.config.valuePrefix+opt);
return val ? val : this.config.listOpts[opt][0];
},
setTagglyOpt: function(title,opt,value) {
// create it silently if it doesn't exist
if (!store.tiddlerExists(title)) {
store.saveTiddler(title,title,config.views.editor.defaultText.format([title]),config.options.txtUserName,new Date(),"");
// <<tagglyTagging expr:"...">> creates a tiddler to store its display settings
// Make those tiddlers less noticeable by tagging as excludeSearch and excludeLists
// Because we don't want to hide real tags, check that they aren't actually tags before doing so
// Also tag them as tagglyExpression for manageability
// (contributed by RA)
if (!store.getTaggedTiddlers(title).length) {
store.setTiddlerTag(title,true,"excludeSearch");
store.setTiddlerTag(title,true,"excludeLists");
store.setTiddlerTag(title,true,"tagglyExpression");
}
}
// if value is default then remove it to save space
return store.setValue(title, this.config.valuePrefix+opt, value == this.config.listOpts[opt][0] ? null : value);
},
getNextValue: function(title,opt) {
var current = this.getTagglyOpt(title,opt);
var pos = this.config.listOpts[opt].indexOf(current);
// supposed to automagically don't let cols cycle up past the number of items
// currently broken in some situations, eg when using an expression
// lets fix it later when we rewrite for jquery
// the columns thing should be jquery table manipulation probably
var limit = (opt == "numCols" ? store.getTaggedTiddlers(title).length : this.config.listOpts[opt].length);
var newPos = (pos + 1) % limit;
return this.config.listOpts[opt][newPos];
},
toggleTagglyOpt: function(title,opt) {
var newVal = this.getNextValue(title,opt);
this.setTagglyOpt(title,opt,newVal);
},
createListControl: function(place,title,type) {
var lingo = config.taggly.lingo;
var label;
var tooltip;
var onclick;
if ((type == "title" || type == "modified" || type == "created")) {
// "special" controls. a little tricky. derived from sortOrder and sortBy
label = lingo.labels[type];
tooltip = lingo.tooltips[type];
if (this.getTagglyOpt(title,"sortBy") == type) {
label += lingo.labels[this.getTagglyOpt(title,"sortOrder")];
onclick = function() {
config.taggly.toggleTagglyOpt(title,"sortOrder");
return false;
}
}
else {
onclick = function() {
config.taggly.setTagglyOpt(title,"sortBy",type);
config.taggly.setTagglyOpt(title,"sortOrder",config.taggly.config.listOpts.sortOrder[0]);
return false;
}
}
}
else {
// "regular" controls, nice and simple
label = lingo.labels[type == "numCols" ? type : this.getNextValue(title,type)];
tooltip = lingo.tooltips[type == "numCols" ? type : this.getNextValue(title,type)];
onclick = function() {
config.taggly.toggleTagglyOpt(title,type);
return false;
}
}
// hide button because commas don't have columns
if (!(this.getTagglyOpt(title,"listMode") == "commas" && type == "numCols"))
createTiddlyButton(place,label,tooltip,onclick,type == "hideState" ? "hidebutton" : "button");
},
makeColumns: function(orig,numCols) {
var listSize = orig.length;
var colSize = listSize/numCols;
var remainder = listSize % numCols;
var upperColsize = colSize;
var lowerColsize = colSize;
if (colSize != Math.floor(colSize)) {
// it's not an exact fit so..
upperColsize = Math.floor(colSize) + 1;
lowerColsize = Math.floor(colSize);
}
var output = [];
var c = 0;
for (var j=0;j<numCols;j++) {
var singleCol = [];
var thisSize = j < remainder ? upperColsize : lowerColsize;
for (var i=0;i<thisSize;i++)
singleCol.push(orig[c++]);
output.push(singleCol);
}
return output;
},
drawTable: function(place,columns,theClass) {
var newTable = createTiddlyElement(place,"table",null,theClass);
var newTbody = createTiddlyElement(newTable,"tbody");
var newTr = createTiddlyElement(newTbody,"tr");
for (var j=0;j<columns.length;j++) {
var colOutput = "";
for (var i=0;i<columns[j].length;i++)
colOutput += columns[j][i];
var newTd = createTiddlyElement(newTr,"td",null,"tagglyTagging"); // todo should not need this class
wikify(colOutput,newTd);
}
return newTable;
},
createTagglyList: function(place,title,isTagExpr) {
switch(this.getTagglyOpt(title,"listMode")) {
case "group": return this.createTagglyListGrouped(place,title,isTagExpr); break;
case "normal": return this.createTagglyListNormal(place,title,false,isTagExpr); break;
case "commas": return this.createTagglyListNormal(place,title,true,isTagExpr); break;
case "sitemap":return this.createTagglyListSiteMap(place,title,isTagExpr); break;
}
},
getTaggingCount: function(title,isTagExpr) {
// thanks to Doug Edmunds
if (this.config.showTaggingCounts) {
var tagCount = config.taggly.getTiddlers(title,'title',isTagExpr).length;
if (tagCount > 0)
return " ("+tagCount+")";
}
return "";
},
getTiddlers: function(titleOrExpr,sortBy,isTagExpr) {
return isTagExpr ? store.getTiddlersByTagExpr(titleOrExpr,sortBy) : store.getTaggedTiddlers(titleOrExpr,sortBy);
},
getExcerpt: function(inTiddlerTitle,title,indent) {
if (!indent)
indent = 1;
var displayMode = this.getTagglyOpt(inTiddlerTitle,"excerpts");
var t = store.getTiddler(title);
if (t && displayMode == "excerpts") {
var text = t.text.replace(/\n/," ");
var marker = text.indexOf(this.config.excerptMarker);
if (marker != -1) {
return " {{excerpt{<nowiki>" + text.substr(0,marker) + "</nowiki>}}}";
}
else if (text.length < this.config.excerptSize) {
return " {{excerpt{<nowiki>" + t.text + "</nowiki>}}}";
}
else {
return " {{excerpt{<nowiki>" + t.text.substr(0,this.config.excerptSize) + "..." + "</nowiki>}}}";
}
}
else if (t && displayMode == "contents") {
return "\n{{contents indent"+indent+"{\n" + t.text + "\n}}}";
}
else if (t && displayMode == "sliders") {
return "<slider slide>\n{{contents{\n" + t.text + "\n}}}\n</slider>";
}
else if (t && displayMode == "descr") {
var descr = store.getTiddlerSlice(title,'Description');
return descr ? " {{excerpt{" + descr + "}}}" : "";
}
else if (t && displayMode == "slices") {
var result = "";
var slices = store.calcAllSlices(title);
for (var s in slices)
result += "|%0|<nowiki>%1</nowiki>|\n".format([s,slices[s]]);
return result ? "\n{{excerpt excerptIndent{\n" + result + "}}}" : "";
}
return "";
},
notHidden: function(t,inTiddler) {
if (typeof t == "string")
t = store.getTiddler(t);
return (!t || !t.tags.containsAny(this.config.excludeTags) ||
(inTiddler && this.config.excludeTags.contains(inTiddler)));
},
// this is for normal and commas mode
createTagglyListNormal: function(place,title,useCommas,isTagExpr) {
var list = config.taggly.getTiddlers(title,this.getTagglyOpt(title,"sortBy"),isTagExpr);
if (this.getTagglyOpt(title,"sortOrder") == "desc")
list = list.reverse();
var output = [];
var first = true;
for (var i=0;i<list.length;i++) {
if (this.notHidden(list[i],title)) {
var countString = this.getTaggingCount(list[i].title);
var excerpt = this.getExcerpt(title,list[i].title);
if (useCommas)
output.push((first ? "" : ", ") + "[[" + list[i].title + "]]" + countString + excerpt);
else
output.push("*[[" + list[i].title + "]]" + countString + excerpt + "\n");
first = false;
}
}
return this.drawTable(place,
this.makeColumns(output,useCommas ? 1 : parseInt(this.getTagglyOpt(title,"numCols"))),
useCommas ? "commas" : "normal");
},
// this is for the "grouped" mode
createTagglyListGrouped: function(place,title,isTagExpr) {
var sortBy = this.getTagglyOpt(title,"sortBy");
var sortOrder = this.getTagglyOpt(title,"sortOrder");
var list = config.taggly.getTiddlers(title,sortBy,isTagExpr);
if (sortOrder == "desc")
list = list.reverse();
var leftOvers = []
for (var i=0;i<list.length;i++)
leftOvers.push(list[i].title);
var allTagsHolder = {};
for (var i=0;i<list.length;i++) {
for (var j=0;j<list[i].tags.length;j++) {
if (list[i].tags[j] != title) { // not this tiddler
if (this.notHidden(list[i].tags[j],title)) {
if (!allTagsHolder[list[i].tags[j]])
allTagsHolder[list[i].tags[j]] = "";
if (this.notHidden(list[i],title)) {
allTagsHolder[list[i].tags[j]] += "**[["+list[i].title+"]]"
+ this.getTaggingCount(list[i].title) + this.getExcerpt(title,list[i].title) + "\n";
leftOvers.setItem(list[i].title,-1); // remove from leftovers. at the end it will contain the leftovers
}
}
}
}
}
var allTags = [];
for (var t in allTagsHolder)
allTags.push(t);
var sortHelper = function(a,b) {
if (a == b) return 0;
if (a < b) return -1;
return 1;
};
allTags.sort(function(a,b) {
var tidA = store.getTiddler(a);
var tidB = store.getTiddler(b);
if (sortBy == "title") return sortHelper(a,b);
else if (!tidA && !tidB) return 0;
else if (!tidA) return -1;
else if (!tidB) return +1;
else return sortHelper(tidA[sortBy],tidB[sortBy]);
});
var leftOverOutput = "";
for (var i=0;i<leftOvers.length;i++)
if (this.notHidden(leftOvers[i],title))
leftOverOutput += "*[["+leftOvers[i]+"]]" + this.getTaggingCount(leftOvers[i]) + this.getExcerpt(title,leftOvers[i]) + "\n";
var output = [];
if (sortOrder == "desc")
allTags.reverse();
else if (leftOverOutput != "")
// leftovers first...
output.push(leftOverOutput);
for (var i=0;i<allTags.length;i++)
if (allTagsHolder[allTags[i]] != "")
output.push("*[["+allTags[i]+"]]" + this.getTaggingCount(allTags[i]) + this.getExcerpt(title,allTags[i]) + "\n" + allTagsHolder[allTags[i]]);
if (sortOrder == "desc" && leftOverOutput != "")
// leftovers last...
output.push(leftOverOutput);
return this.drawTable(place,
this.makeColumns(output,parseInt(this.getTagglyOpt(title,"numCols"))),
"grouped");
},
// used to build site map
treeTraverse: function(title,depth,sortBy,sortOrder,isTagExpr) {
var list = config.taggly.getTiddlers(title,sortBy,isTagExpr);
if (sortOrder == "desc")
list.reverse();
var indent = "";
for (var j=0;j<depth;j++)
indent += "*"
var childOutput = "";
if (depth > this.config.siteMapDepthLimit)
childOutput += indent + this.lingo.tooDeepMessage;
else
for (var i=0;i<list.length;i++)
if (list[i].title != title)
if (this.notHidden(list[i].title,this.config.inTiddler))
childOutput += this.treeTraverse(list[i].title,depth+1,sortBy,sortOrder,false);
if (depth == 0)
return childOutput;
else
return indent + "[["+title+"]]" + this.getTaggingCount(title) + this.getExcerpt(this.config.inTiddler,title,depth) + "\n" + childOutput;
},
// this if for the site map mode
createTagglyListSiteMap: function(place,title,isTagExpr) {
this.config.inTiddler = title; // nasty. should pass it in to traverse probably
var output = this.treeTraverse(title,0,this.getTagglyOpt(title,"sortBy"),this.getTagglyOpt(title,"sortOrder"),isTagExpr);
return this.drawTable(place,
this.makeColumns(output.split(/(?=^\*\[)/m),parseInt(this.getTagglyOpt(title,"numCols"))), // regexp magic
"sitemap"
);
},
macros: {
tagglyTagging: {
handler: function (place,macroName,params,wikifier,paramString,tiddler) {
var parsedParams = paramString.parseParams("tag",null,true);
var refreshContainer = createTiddlyElement(place,"div");
// do some refresh magic to make it keep the list fresh - thanks Saq
refreshContainer.setAttribute("refresh","macro");
refreshContainer.setAttribute("macroName",macroName);
var tag = getParam(parsedParams,"tag");
var expr = getParam(parsedParams,"expr");
if (expr) {
refreshContainer.setAttribute("isTagExpr","true");
refreshContainer.setAttribute("title",expr);
refreshContainer.setAttribute("showEmpty","true");
}
else {
refreshContainer.setAttribute("isTagExpr","false");
if (tag) {
refreshContainer.setAttribute("title",tag);
refreshContainer.setAttribute("showEmpty","true");
}
else {
refreshContainer.setAttribute("title",tiddler.title);
refreshContainer.setAttribute("showEmpty","false");
}
}
this.refresh(refreshContainer);
},
refresh: function(place) {
var title = place.getAttribute("title");
var isTagExpr = place.getAttribute("isTagExpr") == "true";
var showEmpty = place.getAttribute("showEmpty") == "true";
removeChildren(place);
addClass(place,"tagglyTagging");
var countFound = config.taggly.getTiddlers(title,'title',isTagExpr).length
if (countFound > 0 || showEmpty) {
var lingo = config.taggly.lingo;
config.taggly.createListControl(place,title,"hideState");
if (config.taggly.getTagglyOpt(title,"hideState") == "show") {
createTiddlyElement(place,"span",null,"tagglyLabel",
isTagExpr ? lingo.labels.exprLabel.format([title]) : lingo.labels.label.format([title]));
config.taggly.createListControl(place,title,"title");
config.taggly.createListControl(place,title,"modified");
config.taggly.createListControl(place,title,"created");
config.taggly.createListControl(place,title,"listMode");
config.taggly.createListControl(place,title,"excerpts");
config.taggly.createListControl(place,title,"numCols");
config.taggly.createTagglyList(place,title,isTagExpr);
if (countFound == 0 && showEmpty)
createTiddlyElement(place,"div",null,"tagglyNoneFound",lingo.labels.noneFound);
}
}
}
}
},
// todo fix these up a bit
styles: [
"/*{{{*/",
"/* created by TagglyTaggingPlugin */",
".tagglyTagging { padding-top:0.5em; }",
".tagglyTagging li.listTitle { display:none; }",
".tagglyTagging ul {",
" margin-top:0px; padding-top:0.5em; padding-left:2em;",
" margin-bottom:0px; padding-bottom:0px;",
"}",
".tagglyTagging { vertical-align: top; margin:0px; padding:0px; }",
".tagglyTagging table { margin:0px; padding:0px; }",
".tagglyTagging .button { visibility:hidden; margin-left:3px; margin-right:3px; }",
".tagglyTagging .button, .tagglyTagging .hidebutton {",
" color:[[ColorPalette::TertiaryLight]]; font-size:90%;",
" border:0px; padding-left:0.3em;padding-right:0.3em;",
"}",
".tagglyTagging .button:hover, .hidebutton:hover, ",
".tagglyTagging .button:active, .hidebutton:active {",
" border:0px; background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]];",
"}",
".selected .tagglyTagging .button { visibility:visible; }",
".tagglyTagging .hidebutton { color:[[ColorPalette::Background]]; }",
".selected .tagglyTagging .hidebutton { color:[[ColorPalette::TertiaryLight]] }",
".tagglyLabel { color:[[ColorPalette::TertiaryMid]]; font-size:90%; }",
".tagglyTagging ul {padding-top:0px; padding-bottom:0.5em; margin-left:1em; }",
".tagglyTagging ul ul {list-style-type:disc; margin-left:-1em;}",
".tagglyTagging ul ul li {margin-left:0.5em; }",
".editLabel { font-size:90%; padding-top:0.5em; }",
".tagglyTagging .commas { padding-left:1.8em; }",
"/* not technically tagglytagging but will put them here anyway */",
".tagglyTagged li.listTitle { display:none; }",
".tagglyTagged li { display: inline; font-size:90%; }",
".tagglyTagged ul { margin:0px; padding:0px; }",
".excerpt { color:[[ColorPalette::TertiaryDark]]; }",
".excerptIndent { margin-left:4em; }",
"div.tagglyTagging table,",
"div.tagglyTagging table tr,",
"td.tagglyTagging",
" {border-style:none!important; }",
".tagglyTagging .contents { border-bottom:2px solid [[ColorPalette::TertiaryPale]]; padding:0 1em 1em 0.5em;",
" margin-bottom:0.5em; }",
".tagglyTagging .indent1 { margin-left:3em; }",
".tagglyTagging .indent2 { margin-left:4em; }",
".tagglyTagging .indent3 { margin-left:5em; }",
".tagglyTagging .indent4 { margin-left:6em; }",
".tagglyTagging .indent5 { margin-left:7em; }",
".tagglyTagging .indent6 { margin-left:8em; }",
".tagglyTagging .indent7 { margin-left:9em; }",
".tagglyTagging .indent8 { margin-left:10em; }",
".tagglyTagging .indent9 { margin-left:11em; }",
".tagglyTagging .indent10 { margin-left:12em; }",
".tagglyNoneFound { margin-left:2em; color:[[ColorPalette::TertiaryMid]]; font-size:90%; font-style:italic; }",
"/*}}}*/",
""].join("\n"),
init: function() {
merge(config.macros,this.macros);
config.shadowTiddlers["TagglyTaggingStyles"] = this.styles;
store.addNotification("TagglyTaggingStyles",refreshStyles);
}
};
config.taggly.init();
//}}}
/***
InlineSlidersPlugin
By Saq Imtiaz
http://tw.lewcid.org/sandbox/#InlineSlidersPlugin
// syntax adjusted to not clash with NestedSlidersPlugin
// added + syntax to start open instead of closed
***/
//{{{
config.formatters.unshift( {
name: "inlinesliders",
// match: "\\+\\+\\+\\+|\\<slider",
match: "\\<slider",
// lookaheadRegExp: /(?:\+\+\+\+|<slider) (.*?)(?:>?)\n((?:.|\n)*?)\n(?:====|<\/slider>)/mg,
lookaheadRegExp: /(?:<slider)(\+?) (.*?)(?:>)\n((?:.|\n)*?)\n(?:<\/slider>)/mg,
handler: function(w) {
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart ) {
var btn = createTiddlyButton(w.output,lookaheadMatch[2] + " "+"\u00BB",lookaheadMatch[2],this.onClickSlider,"button sliderButton");
var panel = createTiddlyElement(w.output,"div",null,"sliderPanel");
panel.style.display = (lookaheadMatch[1] == '+' ? "block" : "none");
wikify(lookaheadMatch[3],panel);
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
}
},
onClickSlider : function(e) {
if(!e) var e = window.event;
var n = this.nextSibling;
n.style.display = (n.style.display=="none") ? "block" : "none";
return false;
}
});
//}}}
TiddlyWiki est un moteur de wiki très léger, entièrement contenu dans une seule page HTML.
Il est idéal pour tenir à jour un bloc-note, une petite documentation ou publier un petit site internet.
Plus d'infos : http://www.tiddlywiki.com/
/***
|Name:|ToggleTagPlugin|
|Description:|Makes a checkbox which toggles a tag in a tiddler|
|Version:|3.1.0 ($Rev: 4907 $)|
|Date:|$Date: 2008-05-13 03:15:46 +1000 (Tue, 13 May 2008) $|
|Source:|http://mptw.tiddlyspot.com/#ToggleTagPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Usage
{{{<<toggleTag }}}//{{{TagName TiddlerName LabelText}}}//{{{>>}}}
* TagName - the tag to be toggled, default value "checked"
* TiddlerName - the tiddler to toggle the tag in, default value the current tiddler
* LabelText - the text (gets wikified) to put next to the check box, default value is '{{{[[TagName]]}}}' or '{{{[[TagName]] [[TiddlerName]]}}}'
(If a parameter is '.' then the default will be used)
* TouchMod flag - if non empty then touch the tiddlers mod date. Note, can set config.toggleTagAlwaysTouchModDate to always touch mod date
!!Examples
|Code|Description|Example|h
|{{{<<toggleTag>>}}}|Toggles the default tag (checked) in this tiddler|<<toggleTag>>|
|{{{<<toggleTag TagName>>}}}|Toggles the TagName tag in this tiddler|<<toggleTag TagName>>|
|{{{<<toggleTag TagName TiddlerName>>}}}|Toggles the TagName tag in the TiddlerName tiddler|<<toggleTag TagName TiddlerName>>|
|{{{<<toggleTag TagName TiddlerName 'click me'>>}}}|Same but with custom label|<<toggleTag TagName TiddlerName 'click me'>>|
|{{{<<toggleTag . . 'click me'>>}}}|dot means use default value|<<toggleTag . . 'click me'>>|
!!Notes
* If TiddlerName doesn't exist it will be silently created
* Set label to '-' to specify no label
* See also http://mgtd-alpha.tiddlyspot.com/#ToggleTag2
!!Known issues
* Doesn't smoothly handle the case where you toggle a tag in a tiddler that is current open for editing
* Should convert to use named params
***/
//{{{
if (config.toggleTagAlwaysTouchModDate == undefined) config.toggleTagAlwaysTouchModDate = false;
merge(config.macros,{
toggleTag: {
createIfRequired: true,
shortLabel: "[[%0]]",
longLabel: "[[%0]] [[%1]]",
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var tiddlerTitle = tiddler ? tiddler.title : '';
var tag = (params[0] && params[0] != '.') ? params[0] : "checked";
var title = (params[1] && params[1] != '.') ? params[1] : tiddlerTitle;
var defaultLabel = (title == tiddlerTitle ? this.shortLabel : this.longLabel);
var label = (params[2] && params[2] != '.') ? params[2] : defaultLabel;
var touchMod = (params[3] && params[3] != '.') ? params[3] : "";
label = (label == '-' ? '' : label); // dash means no label
var theTiddler = (title == tiddlerTitle ? tiddler : store.getTiddler(title));
var cb = createTiddlyCheckbox(place, label.format([tag,title]), theTiddler && theTiddler.isTagged(tag), function(e) {
if (!store.tiddlerExists(title)) {
if (config.macros.toggleTag.createIfRequired) {
var content = store.getTiddlerText(title); // just in case it's a shadow
store.saveTiddler(title,title,content?content:"",config.options.txtUserName,new Date(),null);
}
else
return false;
}
if ((touchMod != "" || config.toggleTagAlwaysTouchModDate) && theTiddler)
theTiddler.modified = new Date();
store.setTiddlerTag(title,this.checked,tag);
return true;
});
}
}
});
//}}}
/***
Description: Contains the stuff you need to use Tiddlyspot
Note, you also need UploadPlugin, PasswordOptionPlugin and LoadRemoteFileThroughProxy
from http://tiddlywiki.bidix.info for a complete working Tiddlyspot site.
***/
//{{{
// edit this if you are migrating sites or retrofitting an existing TW
config.tiddlyspotSiteId = 'kubiack';
// make it so you can by default see edit controls via http
config.options.chkHttpReadOnly = false;
window.readOnly = false; // make sure of it (for tw 2.2)
window.showBackstage = true; // show backstage too
// disable autosave in d3
if (window.location.protocol != "file:")
config.options.chkGTDLazyAutoSave = false;
// tweak shadow tiddlers to add upload button, password entry box etc
with (config.shadowTiddlers) {
SiteUrl = 'http://'+config.tiddlyspotSiteId+'.tiddlyspot.com';
SideBarOptions = SideBarOptions.replace(/(<<saveChanges>>)/,"$1<<tiddler TspotSidebar>>");
OptionsPanel = OptionsPanel.replace(/^/,"<<tiddler TspotOptions>>");
DefaultTiddlers = DefaultTiddlers.replace(/^/,"[[WelcomeToTiddlyspot]] ");
MainMenu = MainMenu.replace(/^/,"[[WelcomeToTiddlyspot]] ");
}
// create some shadow tiddler content
merge(config.shadowTiddlers,{
'TspotOptions':[
"tiddlyspot password:",
"<<option pasUploadPassword>>",
""
].join("\n"),
'TspotControls':[
"| tiddlyspot password:|<<option pasUploadPassword>>|",
"| site management:|<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . . " + config.tiddlyspotSiteId + ">>//(requires tiddlyspot password)//<br>[[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]], [[download (go offline)|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download]]|",
"| links:|[[tiddlyspot.com|http://tiddlyspot.com/]], [[FAQs|http://faq.tiddlyspot.com/]], [[blog|http://tiddlyspot.blogspot.com/]], email [[support|mailto:support@tiddlyspot.com]] & [[feedback|mailto:feedback@tiddlyspot.com]], [[donate|http://tiddlyspot.com/?page=donate]]|"
].join("\n"),
'WelcomeToTiddlyspot':[
"This document is a ~TiddlyWiki from tiddlyspot.com. A ~TiddlyWiki is an electronic notebook that is great for managing todo lists, personal information, and all sorts of things.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //What now?// @@ Before you can save any changes, you need to enter your password in the form below. Then configure privacy and other site settings at your [[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]] (your control panel username is //" + config.tiddlyspotSiteId + "//).",
"<<tiddler TspotControls>>",
"See also GettingStarted.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Working online// @@ You can edit this ~TiddlyWiki right now, and save your changes using the \"save to web\" button in the column on the right.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Working offline// @@ A fully functioning copy of this ~TiddlyWiki can be saved onto your hard drive or USB stick. You can make changes and save them locally without being connected to the Internet. When you're ready to sync up again, just click \"upload\" and your ~TiddlyWiki will be saved back to tiddlyspot.com.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Help!// @@ Find out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]]. Also visit [[TiddlyWiki.org|http://tiddlywiki.org]] for documentation on learning and using ~TiddlyWiki. New users are especially welcome on the [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]], which is an excellent place to ask questions and get help. If you have a tiddlyspot related problem email [[tiddlyspot support|mailto:support@tiddlyspot.com]].",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Enjoy :)// @@ We hope you like using your tiddlyspot.com site. Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions."
].join("\n"),
'TspotSidebar':[
"<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . . " + config.tiddlyspotSiteId + ">><html><a href='http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download' class='button'>download</a></html>"
].join("\n")
});
//}}}
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 08/06/2010 10:28:28 | Kubiack | [[/|http://kubiack.tiddlyspot.com/]] | [[store.cgi|http://kubiack.tiddlyspot.com/store.cgi]] | . | [[index.html | http://kubiack.tiddlyspot.com/index.html]] | . | ok |
| 08/06/2010 10:31:47 | Kubiack | [[/|http://kubiack.tiddlyspot.com/]] | [[store.cgi|http://kubiack.tiddlyspot.com/store.cgi]] | . | [[index.html | http://kubiack.tiddlyspot.com/index.html]] | . |
| 08/06/2010 11:04:05 | Kubiack | [[/|http://kubiack.tiddlyspot.com/]] | [[store.cgi|http://kubiack.tiddlyspot.com/store.cgi]] | . | [[index.html | http://kubiack.tiddlyspot.com/index.html]] | . | ok |
| 08/06/2010 11:12:30 | Kubiack | [[/|http://kubiack.tiddlyspot.com/]] | [[store.cgi|http://kubiack.tiddlyspot.com/store.cgi]] | . | [[index.html | http://kubiack.tiddlyspot.com/index.html]] | . | ok |
| 08/06/2010 11:14:10 | Kubiack | [[/|http://kubiack.tiddlyspot.com/]] | [[store.cgi|http://kubiack.tiddlyspot.com/store.cgi]] | . | [[index.html | http://kubiack.tiddlyspot.com/index.html]] | . |
| 09/06/2010 22:43:15 | Kubiack | [[/|http://kubiack.tiddlyspot.com/]] | [[store.cgi|http://kubiack.tiddlyspot.com/store.cgi]] | . | [[index.html | http://kubiack.tiddlyspot.com/index.html]] | . | ok |
| 09/06/2010 22:58:18 | Kubiack | [[/|http://kubiack.tiddlyspot.com/]] | [[store.cgi|http://kubiack.tiddlyspot.com/store.cgi]] | . | [[index.html | http://kubiack.tiddlyspot.com/index.html]] | . |
| 23/06/2010 12:06:22 | Kubiack | [[/|http://kubiack.tiddlyspot.com/]] | [[store.cgi|http://kubiack.tiddlyspot.com/store.cgi]] | . | [[index.html | http://kubiack.tiddlyspot.com/index.html]] | . |
| 11/08/2010 10:23:18 | Kubiack | [[/|http://kubiack.tiddlyspot.com/]] | [[store.cgi|http://kubiack.tiddlyspot.com/store.cgi]] | . | [[index.html | http://kubiack.tiddlyspot.com/index.html]] | . | ok |
| 11/08/2010 10:32:32 | Kubiack | [[/|http://kubiack.tiddlyspot.com/]] | [[store.cgi|http://kubiack.tiddlyspot.com/store.cgi]] | . | [[index.html | http://kubiack.tiddlyspot.com/index.html]] | . |
/***
|''Name:''|UploadPlugin|
|''Description:''|Save to web a TiddlyWiki|
|''Version:''|4.1.3|
|''Date:''|Feb 24, 2008|
|''Source:''|http://tiddlywiki.bidix.info/#UploadPlugin|
|''Documentation:''|http://tiddlywiki.bidix.info/#UploadPluginDoc|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
|''Requires:''|PasswordOptionPlugin|
***/
//{{{
version.extensions.UploadPlugin = {
major: 4, minor: 1, revision: 3,
date: new Date("Feb 24, 2008"),
source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
coreVersion: '2.2.0'
};
//
// Environment
//
if (!window.bidix) window.bidix = {}; // bidix namespace
bidix.debugMode = false; // true to activate both in Plugin and UploadService
//
// Upload Macro
//
config.macros.upload = {
// default values
defaultBackupDir: '', //no backup
defaultStoreScript: "store.php",
defaultToFilename: "index.html",
defaultUploadDir: ".",
authenticateUser: true // UploadService Authenticate User
};
config.macros.upload.label = {
promptOption: "Save and Upload this TiddlyWiki with UploadOptions",
promptParamMacro: "Save and Upload this TiddlyWiki in %0",
saveLabel: "save to web",
saveToDisk: "save to disk",
uploadLabel: "upload"
};
config.macros.upload.messages = {
noStoreUrl: "No store URL in parmeters or options",
usernameOrPasswordMissing: "Username or password missing"
};
config.macros.upload.handler = function(place,macroName,params) {
if (readOnly)
return;
var label;
if (document.location.toString().substr(0,4) == "http")
label = this.label.saveLabel;
else
label = this.label.uploadLabel;
var prompt;
if (params[0]) {
prompt = this.label.promptParamMacro.toString().format([this.destFile(params[0],
(params[1] ? params[1]:bidix.basename(window.location.toString())), params[3])]);
} else {
prompt = this.label.promptOption;
}
createTiddlyButton(place, label, prompt, function() {config.macros.upload.action(params);}, null, null, this.accessKey);
};
config.macros.upload.action = function(params)
{
// for missing macro parameter set value from options
if (!params) params = {};
var storeUrl = params[0] ? params[0] : config.options.txtUploadStoreUrl;
var toFilename = params[1] ? params[1] : config.options.txtUploadFilename;
var backupDir = params[2] ? params[2] : config.options.txtUploadBackupDir;
var uploadDir = params[3] ? params[3] : config.options.txtUploadDir;
var username = params[4] ? params[4] : config.options.txtUploadUserName;
var password = config.options.pasUploadPassword; // for security reason no password as macro parameter
// for still missing parameter set default value
if ((!storeUrl) && (document.location.toString().substr(0,4) == "http"))
storeUrl = bidix.dirname(document.location.toString())+'/'+config.macros.upload.defaultStoreScript;
if (storeUrl.substr(0,4) != "http")
storeUrl = bidix.dirname(document.location.toString()) +'/'+ storeUrl;
if (!toFilename)
toFilename = bidix.basename(window.location.toString());
if (!toFilename)
toFilename = config.macros.upload.defaultToFilename;
if (!uploadDir)
uploadDir = config.macros.upload.defaultUploadDir;
if (!backupDir)
backupDir = config.macros.upload.defaultBackupDir;
// report error if still missing
if (!storeUrl) {
alert(config.macros.upload.messages.noStoreUrl);
clearMessage();
return false;
}
if (config.macros.upload.authenticateUser && (!username || !password)) {
alert(config.macros.upload.messages.usernameOrPasswordMissing);
clearMessage();
return false;
}
bidix.upload.uploadChanges(false,null,storeUrl, toFilename, uploadDir, backupDir, username, password);
return false;
};
config.macros.upload.destFile = function(storeUrl, toFilename, uploadDir)
{
if (!storeUrl)
return null;
var dest = bidix.dirname(storeUrl);
if (uploadDir && uploadDir != '.')
dest = dest + '/' + uploadDir;
dest = dest + '/' + toFilename;
return dest;
};
//
// uploadOptions Macro
//
config.macros.uploadOptions = {
handler: function(place,macroName,params) {
var wizard = new Wizard();
wizard.createWizard(place,this.wizardTitle);
wizard.addStep(this.step1Title,this.step1Html);
var markList = wizard.getElement("markList");
var listWrapper = document.createElement("div");
markList.parentNode.insertBefore(listWrapper,markList);
wizard.setValue("listWrapper",listWrapper);
this.refreshOptions(listWrapper,false);
var uploadCaption;
if (document.location.toString().substr(0,4) == "http")
uploadCaption = config.macros.upload.label.saveLabel;
else
uploadCaption = config.macros.upload.label.uploadLabel;
wizard.setButtons([
{caption: uploadCaption, tooltip: config.macros.upload.label.promptOption,
onClick: config.macros.upload.action},
{caption: this.cancelButton, tooltip: this.cancelButtonPrompt, onClick: this.onCancel}
]);
},
options: [
"txtUploadUserName",
"pasUploadPassword",
"txtUploadStoreUrl",
"txtUploadDir",
"txtUploadFilename",
"txtUploadBackupDir",
"chkUploadLog",
"txtUploadLogMaxLine"
],
refreshOptions: function(listWrapper) {
var opts = [];
for(i=0; i<this.options.length; i++) {
var opt = {};
opts.push();
opt.option = "";
n = this.options[i];
opt.name = n;
opt.lowlight = !config.optionsDesc[n];
opt.description = opt.lowlight ? this.unknownDescription : config.optionsDesc[n];
opts.push(opt);
}
var listview = ListView.create(listWrapper,opts,this.listViewTemplate);
for(n=0; n<opts.length; n++) {
var type = opts[n].name.substr(0,3);
var h = config.macros.option.types[type];
if (h && h.create) {
h.create(opts[n].colElements['option'],type,opts[n].name,opts[n].name,"no");
}
}
},
onCancel: function(e)
{
backstage.switchTab(null);
return false;
},
wizardTitle: "Upload with options",
step1Title: "These options are saved in cookies in your browser",
step1Html: "<input type='hidden' name='markList'></input><br>",
cancelButton: "Cancel",
cancelButtonPrompt: "Cancel prompt",
listViewTemplate: {
columns: [
{name: 'Description', field: 'description', title: "Description", type: 'WikiText'},
{name: 'Option', field: 'option', title: "Option", type: 'String'},
{name: 'Name', field: 'name', title: "Name", type: 'String'}
],
rowClasses: [
{className: 'lowlight', field: 'lowlight'}
]}
};
//
// upload functions
//
if (!bidix.upload) bidix.upload = {};
if (!bidix.upload.messages) bidix.upload.messages = {
//from saving
invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
backupSaved: "Backup saved",
backupFailed: "Failed to upload backup file",
rssSaved: "RSS feed uploaded",
rssFailed: "Failed to upload RSS feed file",
emptySaved: "Empty template uploaded",
emptyFailed: "Failed to upload empty template file",
mainSaved: "Main TiddlyWiki file uploaded",
mainFailed: "Failed to upload main TiddlyWiki file. Your changes have not been saved",
//specific upload
loadOriginalHttpPostError: "Can't get original file",
aboutToSaveOnHttpPost: 'About to upload on %0 ...',
storePhpNotFound: "The store script '%0' was not found."
};
bidix.upload.uploadChanges = function(onlyIfDirty,tiddlers,storeUrl,toFilename,uploadDir,backupDir,username,password)
{
var callback = function(status,uploadParams,original,url,xhr) {
if (!status) {
displayMessage(bidix.upload.messages.loadOriginalHttpPostError);
return;
}
if (bidix.debugMode)
alert(original.substr(0,500)+"\n...");
// Locate the storeArea div's
var posDiv = locateStoreArea(original);
if((posDiv[0] == -1) || (posDiv[1] == -1)) {
alert(config.messages.invalidFileError.format([localPath]));
return;
}
bidix.upload.uploadRss(uploadParams,original,posDiv);
};
if(onlyIfDirty && !store.isDirty())
return;
clearMessage();
// save on localdisk ?
if (document.location.toString().substr(0,4) == "file") {
var path = document.location.toString();
var localPath = getLocalPath(path);
saveChanges();
}
// get original
var uploadParams = new Array(storeUrl,toFilename,uploadDir,backupDir,username,password);
var originalPath = document.location.toString();
// If url is a directory : add index.html
if (originalPath.charAt(originalPath.length-1) == "/")
originalPath = originalPath + "index.html";
var dest = config.macros.upload.destFile(storeUrl,toFilename,uploadDir);
var log = new bidix.UploadLog();
log.startUpload(storeUrl, dest, uploadDir, backupDir);
displayMessage(bidix.upload.messages.aboutToSaveOnHttpPost.format([dest]));
if (bidix.debugMode)
alert("about to execute Http - GET on "+originalPath);
var r = doHttp("GET",originalPath,null,null,username,password,callback,uploadParams,null);
if (typeof r == "string")
displayMessage(r);
return r;
};
bidix.upload.uploadRss = function(uploadParams,original,posDiv)
{
var callback = function(status,params,responseText,url,xhr) {
if(status) {
var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
displayMessage(bidix.upload.messages.rssSaved,bidix.dirname(url)+'/'+destfile);
bidix.upload.uploadMain(params[0],params[1],params[2]);
} else {
displayMessage(bidix.upload.messages.rssFailed);
}
};
// do uploadRss
if(config.options.chkGenerateAnRssFeed) {
var rssPath = uploadParams[1].substr(0,uploadParams[1].lastIndexOf(".")) + ".xml";
var rssUploadParams = new Array(uploadParams[0],rssPath,uploadParams[2],'',uploadParams[4],uploadParams[5]);
var rssString = generateRss();
// no UnicodeToUTF8 conversion needed when location is "file" !!!
if (document.location.toString().substr(0,4) != "file")
rssString = convertUnicodeToUTF8(rssString);
bidix.upload.httpUpload(rssUploadParams,rssString,callback,Array(uploadParams,original,posDiv));
} else {
bidix.upload.uploadMain(uploadParams,original,posDiv);
}
};
bidix.upload.uploadMain = function(uploadParams,original,posDiv)
{
var callback = function(status,params,responseText,url,xhr) {
var log = new bidix.UploadLog();
if(status) {
// if backupDir specified
if ((params[3]) && (responseText.indexOf("backupfile:") > -1)) {
var backupfile = responseText.substring(responseText.indexOf("backupfile:")+11,responseText.indexOf("\n", responseText.indexOf("backupfile:")));
displayMessage(bidix.upload.messages.backupSaved,bidix.dirname(url)+'/'+backupfile);
}
var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
displayMessage(bidix.upload.messages.mainSaved,bidix.dirname(url)+'/'+destfile);
store.setDirty(false);
log.endUpload("ok");
} else {
alert(bidix.upload.messages.mainFailed);
displayMessage(bidix.upload.messages.mainFailed);
log.endUpload("failed");
}
};
// do uploadMain
var revised = bidix.upload.updateOriginal(original,posDiv);
bidix.upload.httpUpload(uploadParams,revised,callback,uploadParams);
};
bidix.upload.httpUpload = function(uploadParams,data,callback,params)
{
var localCallback = function(status,params,responseText,url,xhr) {
url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
if (xhr.status == 404)
alert(bidix.upload.messages.storePhpNotFound.format([url]));
if ((bidix.debugMode) || (responseText.indexOf("Debug mode") >= 0 )) {
alert(responseText);
if (responseText.indexOf("Debug mode") >= 0 )
responseText = responseText.substring(responseText.indexOf("\n\n")+2);
} else if (responseText.charAt(0) != '0')
alert(responseText);
if (responseText.charAt(0) != '0')
status = null;
callback(status,params,responseText,url,xhr);
};
// do httpUpload
var boundary = "---------------------------"+"AaB03x";
var uploadFormName = "UploadPlugin";
// compose headers data
var sheader = "";
sheader += "--" + boundary + "\r\nContent-disposition: form-data; name=\"";
sheader += uploadFormName +"\"\r\n\r\n";
sheader += "backupDir="+uploadParams[3] +
";user=" + uploadParams[4] +
";password=" + uploadParams[5] +
";uploaddir=" + uploadParams[2];
if (bidix.debugMode)
sheader += ";debug=1";
sheader += ";;\r\n";
sheader += "\r\n" + "--" + boundary + "\r\n";
sheader += "Content-disposition: form-data; name=\"userfile\"; filename=\""+uploadParams[1]+"\"\r\n";
sheader += "Content-Type: text/html;charset=UTF-8" + "\r\n";
sheader += "Content-Length: " + data.length + "\r\n\r\n";
// compose trailer data
var strailer = new String();
strailer = "\r\n--" + boundary + "--\r\n";
data = sheader + data + strailer;
if (bidix.debugMode) alert("about to execute Http - POST on "+uploadParams[0]+"\n with \n"+data.substr(0,500)+ " ... ");
var r = doHttp("POST",uploadParams[0],data,"multipart/form-data; ;charset=UTF-8; boundary="+boundary,uploadParams[4],uploadParams[5],localCallback,params,null);
if (typeof r == "string")
displayMessage(r);
return r;
};
// same as Saving's updateOriginal but without convertUnicodeToUTF8 calls
bidix.upload.updateOriginal = function(original, posDiv)
{
if (!posDiv)
posDiv = locateStoreArea(original);
if((posDiv[0] == -1) || (posDiv[1] == -1)) {
alert(config.messages.invalidFileError.format([localPath]));
return;
}
var revised = original.substr(0,posDiv[0] + startSaveArea.length) + "\n" +
store.allTiddlersAsHtml() + "\n" +
original.substr(posDiv[1]);
var newSiteTitle = getPageTitle().htmlEncode();
revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");
revised = updateMarkupBlock(revised,"PRE-HEAD","MarkupPreHead");
revised = updateMarkupBlock(revised,"POST-HEAD","MarkupPostHead");
revised = updateMarkupBlock(revised,"PRE-BODY","MarkupPreBody");
revised = updateMarkupBlock(revised,"POST-SCRIPT","MarkupPostBody");
return revised;
};
//
// UploadLog
//
// config.options.chkUploadLog :
// false : no logging
// true : logging
// config.options.txtUploadLogMaxLine :
// -1 : no limit
// 0 : no Log lines but UploadLog is still in place
// n : the last n lines are only kept
// NaN : no limit (-1)
bidix.UploadLog = function() {
if (!config.options.chkUploadLog)
return; // this.tiddler = null
this.tiddler = store.getTiddler("UploadLog");
if (!this.tiddler) {
this.tiddler = new Tiddler();
this.tiddler.title = "UploadLog";
this.tiddler.text = "| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |";
this.tiddler.created = new Date();
this.tiddler.modifier = config.options.txtUserName;
this.tiddler.modified = new Date();
store.addTiddler(this.tiddler);
}
return this;
};
bidix.UploadLog.prototype.addText = function(text) {
if (!this.tiddler)
return;
// retrieve maxLine when we need it
var maxLine = parseInt(config.options.txtUploadLogMaxLine,10);
if (isNaN(maxLine))
maxLine = -1;
// add text
if (maxLine != 0)
this.tiddler.text = this.tiddler.text + text;
// Trunck to maxLine
if (maxLine >= 0) {
var textArray = this.tiddler.text.split('\n');
if (textArray.length > maxLine + 1)
textArray.splice(1,textArray.length-1-maxLine);
this.tiddler.text = textArray.join('\n');
}
// update tiddler fields
this.tiddler.modifier = config.options.txtUserName;
this.tiddler.modified = new Date();
store.addTiddler(this.tiddler);
// refresh and notifiy for immediate update
story.refreshTiddler(this.tiddler.title);
store.notify(this.tiddler.title, true);
};
bidix.UploadLog.prototype.startUpload = function(storeUrl, toFilename, uploadDir, backupDir) {
if (!this.tiddler)
return;
var now = new Date();
var text = "\n| ";
var filename = bidix.basename(document.location.toString());
if (!filename) filename = '/';
text += now.formatString("0DD/0MM/YYYY 0hh:0mm:0ss") +" | ";
text += config.options.txtUserName + " | ";
text += "[["+filename+"|"+location + "]] |";
text += " [[" + bidix.basename(storeUrl) + "|" + storeUrl + "]] | ";
text += uploadDir + " | ";
text += "[[" + bidix.basename(toFilename) + " | " +toFilename + "]] | ";
text += backupDir + " |";
this.addText(text);
};
bidix.UploadLog.prototype.endUpload = function(status) {
if (!this.tiddler)
return;
this.addText(" "+status+" |");
};
//
// Utilities
//
bidix.checkPlugin = function(plugin, major, minor, revision) {
var ext = version.extensions[plugin];
if (!
(ext &&
((ext.major > major) ||
((ext.major == major) && (ext.minor > minor)) ||
((ext.major == major) && (ext.minor == minor) && (ext.revision >= revision))))) {
// write error in PluginManager
if (pluginInfo)
pluginInfo.log.push("Requires " + plugin + " " + major + "." + minor + "." + revision);
eval(plugin); // generate an error : "Error: ReferenceError: xxxx is not defined"
}
};
bidix.dirname = function(filePath) {
if (!filePath)
return;
var lastpos;
if ((lastpos = filePath.lastIndexOf("/")) != -1) {
return filePath.substring(0, lastpos);
} else {
return filePath.substring(0, filePath.lastIndexOf("\\"));
}
};
bidix.basename = function(filePath) {
if (!filePath)
return;
var lastpos;
if ((lastpos = filePath.lastIndexOf("#")) != -1)
filePath = filePath.substring(0, lastpos);
if ((lastpos = filePath.lastIndexOf("/")) != -1) {
return filePath.substring(lastpos + 1);
} else
return filePath.substring(filePath.lastIndexOf("\\")+1);
};
bidix.initOption = function(name,value) {
if (!config.options[name])
config.options[name] = value;
};
//
// Initializations
//
// require PasswordOptionPlugin 1.0.1 or better
bidix.checkPlugin("PasswordOptionPlugin", 1, 0, 1);
// styleSheet
setStylesheet('.txtUploadStoreUrl, .txtUploadBackupDir, .txtUploadDir {width: 22em;}',"uploadPluginStyles");
//optionsDesc
merge(config.optionsDesc,{
txtUploadStoreUrl: "Url of the UploadService script (default: store.php)",
txtUploadFilename: "Filename of the uploaded file (default: in index.html)",
txtUploadDir: "Relative Directory where to store the file (default: . (downloadService directory))",
txtUploadBackupDir: "Relative Directory where to backup the file. If empty no backup. (default: ''(empty))",
txtUploadUserName: "Upload Username",
pasUploadPassword: "Upload Password",
chkUploadLog: "do Logging in UploadLog (default: true)",
txtUploadLogMaxLine: "Maximum of lines in UploadLog (default: 10)"
});
// Options Initializations
bidix.initOption('txtUploadStoreUrl','');
bidix.initOption('txtUploadFilename','');
bidix.initOption('txtUploadDir','');
bidix.initOption('txtUploadBackupDir','');
bidix.initOption('txtUploadUserName','');
bidix.initOption('pasUploadPassword','');
bidix.initOption('chkUploadLog',true);
bidix.initOption('txtUploadLogMaxLine','10');
// Backstage
merge(config.tasks,{
uploadOptions: {text: "upload", tooltip: "Change UploadOptions and Upload", content: '<<uploadOptions>>'}
});
config.backstageTasks.push("uploadOptions");
//}}}
This document is a ~TiddlyWiki from tiddlyspot.com. A ~TiddlyWiki is an electronic notebook that is great for managing todo lists, personal information, and all sorts of things.
@@font-weight:bold;font-size:1.3em;color:#444; //What now?// @@ Before you can save any changes, you need to enter your password in the form below. Then configure privacy and other site settings at your [[control panel|http://kubiack.tiddlyspot.com/controlpanel]] (your control panel username is //kubiack//).
<<tiddler TspotControls>>
See also GettingStarted.
@@font-weight:bold;font-size:1.3em;color:#444; //Working online// @@ You can edit this ~TiddlyWiki right now, and save your changes using the "save to web" button in the column on the right.
@@font-weight:bold;font-size:1.3em;color:#444; //Working offline// @@ A fully functioning copy of this ~TiddlyWiki can be saved onto your hard drive or USB stick. You can make changes and save them locally without being connected to the Internet. When you're ready to sync up again, just click "upload" and your ~TiddlyWiki will be saved back to tiddlyspot.com.
@@font-weight:bold;font-size:1.3em;color:#444; //Help!// @@ Find out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]]. Also visit [[TiddlyWiki.org|http://tiddlywiki.org]] for documentation on learning and using ~TiddlyWiki. New users are especially welcome on the [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]], which is an excellent place to ask questions and get help. If you have a tiddlyspot related problem email [[tiddlyspot support|mailto:support@tiddlyspot.com]].
@@font-weight:bold;font-size:1.3em;color:#444; //Enjoy :)// @@ We hope you like using your tiddlyspot.com site. Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions.
Zenphoto is a very nice PHP/MySQL image gallery; useful to share photos with friends and family.
A nice feature is the automatic image rotation based on EXIF informations placed in the file by the camera. However this feature require lib-GD which is, for some obscure reasons not completely available in standard (Ubuntu/Debian) installation of PHP.
To implement a substitute for this and activate the automatic rotation even on PHP without full support of lib-GD, the following trick can be handy.
* Edit the zenphoto/zp-core/lib-GD.php file.
* At the very beginning of the file, just after the header comments, add the following text:
<<<
{{{
function imagerotate( $source_image, $angle, $bgd_color ) {
$angle = 360-$angle; // GD rotates CCW, imagick rotates CW
$temp_src = tempnam("/tmp","imgrotate_");
$temp_dst = tempnam("/tmp","imgrotate_");
if (!imagepng($source_image,$temp_src)){return false;}
$imagick = new Imagick();
$imagick->readImage($temp_src);
$imagick->rotateImage(new ImagickPixel($bgd_color?$bgd_color:'black'), $angle);
$imagick->writeImage($temp_dst);
$result = imagecreatefrompng($temp_dst);
unlink($temp_dst);
unlink($temp_src);
return $result;
}
}}}
<<<
* Save the file
Now the rotation should work (tested on Zenphoto version 1.2.4, PHP5 with fcgid, Apache2-worker)
Note : I borrowed this from a web forum (I don't remember where) and fixed a small bug (static temp-file names causing collisions with multi-threaded PHP/Apache).
! Tiddlers utiles pour l'administration du site
''Inutiles pour le visiteur ! ''