Here's the v0.2 of the filter: {code} /** * Image Filter for SnipSnap Blog/Wiki * * Copyright 2006-2007 Paulo Abrantes (pabrantes@pabrantes.net) * * --LICENSE NOTICE-- * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * --LICENSE NOTICE-- * */ package org.snipsnap.pabrantes.filter; import java.sql.Timestamp; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.radeox.filter.Filter; import org.radeox.filter.context.FilterContext; import org.radeox.filter.regex.RegexReplaceFilter; import org.snipsnap.app.Application; import org.snipsnap.render.filter.context.SnipFilterContext; import org.snipsnap.snip.Snip; import org.snipsnap.snip.SnipSpace; import org.snipsnap.snip.SnipSpaceFactory; public class SmileFilter extends RegexReplaceFilter implements Filter { private static Log log = LogFactory.getLog(SmileFilter.class); private static Snip snip = null; private Timestamp lastModificationDate = null; public SmileFilter() { super(); } private Snip getSnip() { if(snip==null) { String snipRepository = Application.get().getConfiguration().get( "app.smileRepository"); if (snipRepository != null) { SnipSpace space = SnipSpaceFactory.getInstance(); snip = space.load(snipRepository); if (snip == null) { log.warn("It seems the snip is invalid, maybe it still has to be created!"); } } } return snip; } private void loadSmiles() { clearRegex(); this.lastModificationDate = snip.getMTime(); String content = snip.getContent(); String[] smiles = content.split("\\\r\\\n\\\r\\\n"); for (int i = 0; i < smiles.length; i++) { String[] components = smiles[i].split("="); addRegex(components[0], ""); } } private void checkForModifications() { Snip snip = getSnip(); if (snip != null && snip.getMTime() != lastModificationDate) { loadSmiles(); } } @Override public String filter(String text, FilterContext context) { Snip snip = getSnip(); SnipFilterContext filterContext = (SnipFilterContext) context; if (snip != null && !filterContext.getSnip().getName().equals(snip.getName())) { checkForModifications(); return super.filter(text, context); } return text; } } {code} Modifications: - You now define which snip will have the regex=image in the Config snip, under the property app.smileRepository. Example, "app.smileRepository=mySmiles" will point to space/mySmiles snip. - The filter as the following exceptions: ** If the snip being rendered is the smile repository the filter isn't applied. So if a regex and the text are actually the same it doesn't get filtered into an image, becoming IMAGE=imageName on the configuration snip - this was happening to me while testing for example the :S smile. ** If no property at the configuration file was defined filtering is skipped ** If a property at the configuration was specified but with a non-existing snip, filtering will be skipped __but__ problem logged. - If the repository is modified on the fly on the Config property a container restart is needed, no hot swap here I didn't thought it was needed.