How do I see the page objects source of a specific previous version?

I found how to see the page source at a specific revision - by viewing that revision and clicking the Source entry inside the menu.

But I added some Javascript on that page and I can’t find a way to see the source I wrote in a previous version.

Using 14.2.1

As a side question: is the corresponding page objects content loaded when viewing a previous version?

I ask because I’m almost sure (not 100% because I made lots of edits while attempting to integrate a Javascript library to a page) I got and saved a fully functional version of the page before going further with other modifications.

A suggestion:

  • View History
  • Restore the desired version
  • View it / copy it
  • delete the (restored) version

Sure, but, well, I hoped there was an easier way :sweat_smile:

There is. Just load the page specific version of the page.

There are two ways to do this

1/ enable the revision panel for the page, then click on the specific version you want to view and take it from there. See the following:
Screenshot 2022-07-13 at 18.20

If I want to see page version 1.1, then I just click on the 1.1 in the version column.

2/ add a “?rev=x.y” where x.y is the major.minor version numbers of the page you want to look at. This is only useful if you know your version numbers.

It’s easier to enable the revision panel and click on the version you want to see.

Yup, I already have these. I’m talking, though, specifically to the objects content, not the wiki syntax page content - for which viewing a previous version works.

Unless you meant the same as what NorSch suggested, to physically copy a previous version to a new page.

1 Like

Does adding the ‘&rev=x.y’ parameter to the object editor url give you what you need?

I have no pages with different objects to test it on.

Uh, sorry, missed that.

Just tested but no, the objects editor shows the latest version.

yes

It’s easy to check:

  • create a page
  • add a comment
  • in the content of the page add the following
    {{velocity}}
    $!doc.getValue("comment")
    {{velocity}}
    
  • remove the comment, verify that the velocity script returns some empty text
  • on the page history, click the link for the revision which had the comment xobject and verify it displays your comment text in the page’s content.

Hello,

In addition to the objects values of a given version being loaded when you access that version with ?rev=x.y (as vmassol mentioned) , you can also see the raw content of those objetcs if you’re ready to read a little XML.

By further adding &xpage=xml at the end of the URL of your page (after the rev parameter), you will see the XML serialization of the XWiki document . In there, all the objects are present with the raw values of their properties, as they’re saved in the database. The only thing missing is the content of the attachments (but the metadata of the attachments is displayed).

Enjoy XWiki,
Anca

Sorry for the late reply.

I may have used the wrong terminology here, by object editor I meant this one:
immagine

Here, I added a small CSS style:

immagine

This is the latest version of this page:

immagine

I have a previous version, 9.1:

where I had a blue background, you can see it in the diff:

but this is what I see if I open that version:

while I expected this (after I rolled back the previous version)

Thank you, but I’m not sure where I should put that, is this what you mean?

immagine

Yes, like that, but you have a typo: it’s xpage and you put page.

OK, I understand your problem, and it’s “normal” because for a stylesheet extension (and Javascript extension) things are a bit more complex than they seem:

  • when you load a page with an ssx or jsx object - at any version - the “contents” of that page load in multiple requests to the server:
    • your current request
    • in the html result of this request, the ssx and jsx of that page are not included directly, they’re referenced as external resources (with link and javascript tags in the head element of that page) - this is something that xwiki does automatically, it’s part of the stylesheet extension mechanism
    • then, the browser makes one request to the server for each one of these resources to load them

Now, when you request a page at a given version, with rev=, the page in the first request is properly loaded at the version you asked for, including its objects, for the scope of that request only. However, the mechanism that includes links to external resources is not aware of versions - for good reasons that I won’t detail here - and it will include links to the latest ssx and latest jsx of that page. Thus, those separate requests that will fetch the resources (Javascript and style) will actually request the latest versions of those resources, hence your wrongly colored square.

Ha! Corrected, thanks, I see the XML now.

Hmmm, ok, I can take that as it has been designed like that; I guess that answers with a no to my previous question, then:

That’s fine, I asked because I was experimenting at integrating some javascript libraries in successive edits to the same page and at a point I wanted to go back to a previous attempt, but wasn’t able to recognize the correct page version since it didn’t load the previous Javascript content too.

But by comparing the versions I managed to find it.

Since I had the same need in the meantime, I created some code to display objects of a certain document revision:

Browse different versions of the objects from a document.

Step 1 - choose document
Step 2 - choose version
Step 3 - hide/unhide result table columns 

{{template name="locationPicker_macros.vm" /}}

{{velocity}}
#if(!$request.targetPage && !$request.revision )
Select document (type part of document name as filter):
{{html clean="false"}}
<form action="">
#set ($pagePickerParams = {
    'name': 'targetPage',
    'value': [""]
    })

#pagePicker($pagePickerParams)
 <button type="submit">go to revision selection</button>
</form>
{{/html}}
#end
{{/velocity}}



{{groovy}}
 if (request.targetPage != null) {
   fileName = request.getParameterValues("targetPage")[0]
   println "\nselected:\n>"+fileName
   xdoc=xwiki.getDocument( fileName )

   revisions = xdoc.getRevisions().reverse()   // die aktuelle zuerst
   println '{{html clean="false"}}'
   println  '<form action="">'
   println  '<input name="fileName" type="hidden" value="'+fileName+'">'
   println  '<table class="table-bordered" style="width:auto">'
   println  '<tr><td colspan=2><input name="showxml" type="checkbox"> show xml structure</td></tr>'
   println  '<tr><td colspan=2><input name="syntaxhighlight" type="checkbox" checked> do some syntax high lighting</td></tr>'
   println  "<tr><td style='vertical-align:middle'>select revision <br/>to be displayed: </td><td>"
   println '<select name="revision" id="revisionId" size="'+Math.min(10,revisions.size())+'" width="auto">'
   revisions.each { println '<option value="'+it+'">'+it+'</option>'  }
   println '</select></td></tr>'
   println '<tr><td colspan=2><button style="width:100%" type="submit">go - show objects</button></td></tr></table>'
   println '</form>'
   println "{{/html}}"

   println "available objects in newest document revision:"
   xdoc.getxWikiObjects().each{ objectName, objects ->
       println "* "+objectName
     }
}



if (request.revision != null) {
   fileName = request.fileName
   xdoc=xwiki.getDocument( fileName )
   ydoc = xdoc.getDocumentRevision(request.revision)
   tabCount=0
   println "\n== "+fileName+" - Revision: "+ request.revision + "=="
   ydoc.getxWikiObjects().each{ objectName, objects ->

       classFile=xwiki.getDocument(objectName)
       allObjects = ydoc.getObjects(objectName)
       allObjects.eachWithIndex { theObject,index ->
           tabCount++
           cnt=index+1
           print '(% style="border:3pt solid grey;border-radius:6pt;padding:5pt" %)((('
           println "\n=== ("+cnt+") " + objectName+"==="
           print "hide/unhide column {{html clean='false'}} "
           colList = ["A","B","C","D","E","F"]
           if (request.showxml) { colList.add("G") }
           colList.each { 
               print '<button onclick="'
               print "Array.from(document.getElementsByClassName('tab" 
               print  tabCount+it+"')).forEach(function(it) {it.classList.toggle('"+"hidden"+"')})" +'"> '+it+'  </button> ' }
           print "{{/html}}\n"
           classProperties = classFile.getxWikiClass().properties
           result = "(% style='overflow:scroll'%)"                         +
                    "|=(% class='tab"+tabCount+"A' %)(A)\n number"         +
                    "|=(% class='tab"+tabCount+"B' %)(B)\n NAME "          +
                    "|=(% class='tab"+tabCount+"C' %)(C)\n prettyName "    +
                    "|=(% class='tab"+tabCount+"D' %)(D)\n Type "          +
                    "|=(% class='tab"+tabCount+"E' %)(E)\n classType "     +
                    "|=(% class='tab"+tabCount+"F' %)(F)\n getValue(NAME)" 
           if(request.showxml)  { result += "|=(% class='tab"+tabCount+"G' %)(G)\n structure by getBasePropertyClass" }
           result += "\n"

           classProperties.each {
              if(it.type.toString() == "TextAreaClass") { layout="layout='linenumbers'"} else { layout=""}
              result += "|(% class='tab"+tabCount+"A' %)"   + it.number                +
                        "|(% class='tab"+tabCount+"B' %)"   + it.name                  +
                        "|(% class='tab"+tabCount+"C' %)"   + it.prettyName.toString() +
                        "|(% class='tab"+tabCount+"D' %)"   + it.type.toString()       +
                        "|(% class='tab"+tabCount+"E' %)"   + it.classType
              if (theObject==null)  {result +="|(% class='tab"+tabCount+"F' %)null"} 
                      else {
                        theCode = theObject.getValue(it.name).toString()
                        // do some syntax hightlighting
                        if (objectName == "XWiki.WikiMacroClass" && it.name == "code") { 
                          if (theCode.startsWith("{"+"{groovy}}")) { language="groovy"}
                          else if (theCode.startsWith("{"+"{python}"+"}")) { language="python"}
                          else {language="text"}
                        }
                        else if (objectName == "XWiki.JavaScriptExtension" && it.name == "code") { language="javascript"}
                        else { language="text" }
                        if(!request.syntaxhighlight) { language="text" }
                        result += "|(% class='tab"+tabCount+"F' %)((((% width:25%;style='overflow:scroll' %)"   +
                                  "((({{code "+layout+" language='"+language+"'}}" + 
                                   theCode  + 
                                  "{{/code}}))))))" }
              if (request.showxml) {
                  result += "|(% class='tab"+tabCount+"G' %)((((%  style='width:25%;overflow:scroll' %)"   +
                              "((({{code language='xml'}}"         + 
                               it.getBasePropertyClass().toString().replaceAll(/>(<[a-zA-Z])/,">\n  \$1").replaceAll(/<\/classType>/,"</classType>\n")    + 
                              "{{/code}}))))))" 
              }
              result += "\n"
         }
         println result
         print ")))\n\n\n"
      }
   }
}
{{/groovy}}


A document name or a part of it is requested and a document is selected by means of a picker.
Afterwards the revision has to be selected.

All (!) document objects will be shown.

Wow, this is great!