@Override
    public String fileUrl(PageTitle pageTitle, int width, int height) {
      String title = StringTools.safeFilename(pageTitle.getNormalizedFullTitle());

      FileUrlKey key = new FileUrlKey(title, width, height);

      return fileUrls.get(key);
    }
    @Override
    public FullPage retrieveWikitext(ExpansionFrame expansionFrame, PageTitle pageTitle) {
      String title = StringTools.safeFilename(pageTitle.getNormalizedFullTitle());

      ArticleDesc article = articles.get(title);
      if (article == null) return null;

      PageId pageId = new PageId(pageTitle, article.getRevision());
      return new FullPage(pageId, article.getContent());
    }
    public void visit(WtTicks n) {
      if (ticks == null) ticks = new ArrayList<TicksAnalyzer.LineEntry>();

      int tickCount = n.getTickCount();
      switch (tickCount) {
        case 2:
          ticks.add(new LineEntry(null, null, 2));
          ++numItalics;
          break;

        case 3:
          ticks.add(new LineEntry(previous, null, 3));
          ++numBold;
          break;

        case 4:
          ticks.add(new LineEntry(previous, nf.text("'"), 3));
          ++numBold;
          break;

        case 5:
          ticks.add(new LineEntry(null, null, 5));
          ++numBold;
          ++numItalics;
          break;

        default:
          if (n.getTickCount() <= 5) throw new FmtInternalLogicError();

          String excessTicks = StringTools.strrep('\'', tickCount - 5);

          ticks.add(new LineEntry(null, nf.text(excessTicks), 5));
          ++numBold;
          ++numItalics;
          break;
      }
    }