docs: protected String buildPressGangWebsiteJS(final BuildData buildData) throws BuildProcessingException {
          try {
              final ContentSpec contentSpec = buildData.getContentSpec();
              final StringBuilder retValue = new StringBuilder("pressgang_website_callback([\n");
  
              final JsonStringEncoder encoder = JsonStringEncoder.getInstance();
  
              final List<? extends BaseTopicWrapper<?>> topics = buildData.getBuildDatabase().getAllTopics();
              boolean initial = true;
              for (final BaseTopicWrapper<?> topic : topics) {
                  // Ignore info topics
                  if (topic.hasTag(buildData.getServerEntities().getInfoTagId())) continue;
  
                  // Insert a newline and comma to separate each array variable only after the first variable has been set
                  if (!initial) {
                      retValue.append(",\n");
                  } else {
                      initial = false;
                  }
  
                  // Find the fixed url to use
                  final Integer topicId = topic.getTopicId();
                  final List<ITopicNode> topicNodes = buildData.getBuildDatabase().getTopicNodesForTopicID(topicId);
                  final SpecTopic specTopic = (SpecTopic) topicNodes.get(0);
                  final String fixedUrl = specTopic.getUniqueLinkId(buildData.isUseFixedUrls());
  
                  // Find the new since value to use
                  final List<PropertyTagInTopicWrapper> newSinceProperties = topic.getProperties(
                          buildData.getServerEntities().getPressGangWebsitePropertyTagId());
                  final List<String> values = new ArrayList<String>();
                  if (newSinceProperties != null) {
                      for (final PropertyTagInTopicWrapper newSinceProperty : newSinceProperties) {
                          values.add(newSinceProperty.getValue());
                      }
                      Collections.sort(values);
                  }
  
                  // Opening brace
                  retValue.append("\t{");
  
                  // Data
  
                  retValue.append("\"topicId\":").append(topicId);
                  retValue.append(",\"target\":\"").append(new String(encoder.quoteAsUTF8(fixedUrl), ENCODING)).append("\"");
                  retValue.append(",\"title\":\"").append(new String(encoder.quoteAsUTF8(topic.getTitle()), ENCODING)).append("\"");
                  retValue.append(",\"newSince\":\"").append(
                          values.isEmpty() ? "" : new String(encoder.quoteAsUTF8(values.get(values.size() - 1)), ENCODING)).append("\"");
  
  
                  // Closing brace
                  retValue.append("}");
              }
  
              retValue.append("]");
  
              // Add the content spec id
              retValue.append(", ").append(contentSpec.getId());
  
              // Add the product
              retValue.append(", \"").append(
                      new String(encoder.quoteAsUTF8(DocBookBuildUtilities.getKeyValueNodeText(buildData, contentSpec.getProductNode())),
                              ENCODING)).append("\"");
  
              // Add the title
              retValue.append(", \"").append(
                      new String(encoder.quoteAsUTF8(DocBookBuildUtilities.getKeyValueNodeText(buildData, contentSpec.getTitleNode())),
                              ENCODING)).append("\"");
  
              // Add the version
              if (contentSpec.getVersion() != null) {
                  retValue.append(", \"").append(
                          new String(encoder.quoteAsUTF8(DocBookBuildUtilities.getKeyValueNodeText(buildData, contentSpec.getVersionNode())),
                                  ENCODING)).append("\"");
              } else {
                  retValue.append(", null");
              }
  
              retValue.append(");");
              return retValue.toString();
          } catch (UnsupportedEncodingException e) {
              throw new BuildProcessingException(e);
          }
      }