Converting QuarkXPress files to CSS (Part 2)

In the first part of this series, we covered a lot of ground. We laid the foundation for converting QuarkXPress files to Cascading Style Sheets (CSS) and created all of the subroutines necessary for creating an HTML document and getting our picture boxes to appear. In this, the second part, we will cover getting our QuarkXPress line boxes to appear in our HTML document. This will be a simplified but very similar process to converting the picture boxes to CSS. We will treat line boxes as if they are picture boxes.

We only need to add three additional subroutines to our script from Part 1 to add this new functionality. These three routines are actually just modified versions of the three main routines from Part 1. The reason I chose to create new routines was for the sake of simplicity. The existing routines could be made more universal to handle all box types but I found this to be too complicated to keep track of when writing the code. The only overhead is a slightly larger file size and additional work if modifications are made to the overall script but for my taste this is preferable.

The routines follow. I will only explain the lineStyle( ) routine since the lineProps( ) and convertLineProps( ) routines are only simplified versions of the corresponding routines used for picture boxes.

The first thing I want to point out in dealing with lines is that though lines in QuarkXPress can be less than 1 point (pixel) in width, CSS will not display a line thinner than 1 pixel so we must set a minimum thickness of 1 pixel. This is achieved in the first “if else” control in the lineStyle( ) routine. We simply tell the script that if the thickness of the line box, scaled by our newScale variable, is less than 1 pixel, reset it to 1 pixel. We also use the same “if else” control to make sure that the line thickness is a whole number so we don’t encounter an error in our CSS styles. We check to see if the thickness is a whole number by checking for a remainder when the number is divided by 1 ( lineThickness mod 1). If the number has a remainder, we round the number to the nearest value. Not however that this is done “only” if the number is greater than 1. If it is less than 1, the number is set to 1.

The next section of the lineStyle( ) routine checks to see if the line being addressed is vertical or horizontal. If you are familiar with QuarkXPress line box properties you know that line bounds are different from bounds for picture and text boxes. The bounds of a line describe a path between two points while the bounds for a picture or text box describes the area between four points. To convert line box properties to CSS we must use both the thickness of the line and its coordinates to describe a line as a box with coordinates and width and height. We will be faking a line by describing a small area between four points.

We will need to know whether the line is horizontal or vertical in order to describe this area. This is because the thickness of the line will be use as the width or height of the box depending on its direction. The length of the line will be used to describe the other dimension.

The key test to determine if a line is horizontal or vertical is in the statement if x1 = x2. The first and third bounds tell us the north/south offset of the line from the zero point. Conversely the second and fourth bounds tell us the east/west offset of the line from the zero point. So if x1 = x2 we know the line is horizontal because both its start point and end point are on the same north/south plane. Inverseley if y1 = y2 we know the line is vertical because its start point and end point are both on the same east/west plane. The subroutine then tells the script that if the line is horizontal, then the line thickness is to be used to describe the height of the box and the line length to describe its width. If the opposite is true (the line is vertical) the line thickness describes its width and the length describes its height.

Everything else in this routine is virtually the same as the pBoxStyle( ) routine with the exception that some of the properties that describe picture boxes are not needed for lines. The only properties of lines that we need are width, height and color because it will not be a container for any elements and it will not have a frame.

Line Box Style Sheet

on lineStyle(lineNum, myProps, pW, pH, leftOffset, topOffset)
	set myProps to convertLineProps(myProps)
	set lineThickness to (item 1 of myProps) as integer
	set lineThickness to lineThickness * newScale
	if lineThickness < 1 then
		set lineThickness to 1
	else if lineThickness > 1 and lineThickness mod 2 is not 0 then
		set lineThickness to round lineThickness rounding to nearest
	end if
	set {x1, y1, x2, y2} to item 3 of myProps
	if x1 = x2 then
		-- It's a horizontal line
		set myWidth to y2 - y1
		if myWidth < 0 then
			set myWidth to myWidth * -1
		end if
		set myWidth to myWidth as integer
		set myHeight to lineThickness
		-- it's a vertical line
		set myHeight to x2 - x1
		if myHeight < 0 then
			set myHeight to myHeight * -1
		end if
		set myHeight to myHeight as integer
		set myWidth to lineThickness
	end if
	set myTop to (round x1 rounding to nearest)
	set myLeft to (round y1 rounding to nearest)
	if pW - (myLeft + myWidth) is not 2 then
		set myLeft to myLeft + 2
	end if
	set myBackground to item 4 of myProps
	set myStyle to ¬
		((".linebox" & (lineNum) & space & "{" & cssLineBreak & ¬
			"background:" & myBackground & ";" & cssLineBreak & ¬
			"Position:absolute;" & cssLineBreak & ¬
			"left:" & (myLeft + leftOffset) & "px;" & cssLineBreak & ¬
			"top:" & (myTop + topOffset) & "px;" & cssLineBreak & ¬
			"width:" & myWidth & "px;" & cssLineBreak & ¬
			"height:" & myHeight & "px;" & cssLineBreak & ¬
			"border:" & "0px" & ";" & cssLineBreak & ¬
			"}" & return & return) as string)
	return myStyle
end lineStyle

Get the line box properties:

on LineBoxProps(pageNum)
  tell application "QuarkXPress Passport"
    tell document 1
      tell page pageNum
        set LineProps to {}
        repeat with lineBoxNum from 1 to (count line boxes)
          set {x1, y1, x2, y2} to (coerce ((bounds of line box lineBoxNum) as list) to list)
          set {x1, y1, x2, y2} to {(coerce x1 to real), (coerce y1 to real), (coerce x2 to real), (coerce y2 to real)}
          set lt to width of line box lineBoxNum
          set lt to (coerce lt to real)
          set fc to RGB color value of color of line box lineBoxNum
          set the end of LineProps to {lt, "noValue", {x1, y1, x2, y2}, fc}
        end repeat
        return LineProps
      end tell
    end tell
  end tell
end LineBoxProps

Convert the line box properties:

on convertLineProps(myProps)
	set lt to item 1 of myProps
	set lt to round lt rounding to nearest
	set item 1 of myProps to lt
	set {x1, y1, x2, y2} to item 3 of myProps
	set {x1, y1, x2, y2} to {((x1 * basePX) * newScale), ((y1 * basePX) * newScale), ((x2 * basePX) * newScale), ((y2 * basePX) * newScale)}
	set item 3 of myProps to {x1, y1, x2, y2}
	set bc to item 4 of myProps
	set bc to rgbToHex(2, bc) of me
	set item 4 of myProps to bc
	return myProps
end convertLineProps

So now you can copy thes routines to your script from Part 1. To add this functionality to the script we need only add a few lines of code that will call the routines and add the styles returned to what is written to the CSS and HTML files.

The first piece of code is a single line:

set LineProps to LineBoxProps(1)

This line should be added just after the line

set boxProperties to sortPBoxes(1)

in the script from Part 1.

The second piece of code follows:

Convert the line box properties:

-- Divs for line boxes
repeat with lineNum from 1 to (length of LineProps)
  set myProps to item lineNum of LineProps
  set myStyle to lineStyle(lineNum, myProps, pW, pH, leftOffset, topOffset) of me
  set myCss to myCss & myStyle as string
  set the end of divLst to (("< div class=\"" & ("linebox" & lineNum) & "\"]" & return & "< /div>") as string)
end repeat

Place this piece of code after the repeat loop labeled with the “-- Divs for picture boxes” comment and before the line that says ‘set divData to “”’. And that’s all there is to it. You can now compile your script and run it. The result will be an HTML file that you can open in your browser that will display the picture boxes and line boxes in your QuarkXPress file.

In the next part of this series we will add functionality for converting text boxes to CSS. This will be a more complicated procedure because we will allow for text boxes with multiple columns. Since CSS does not currently allow for multi-column text boxes it will be necessary to convert multi-column text boxes into multiple boxes.