2022-02-20 18:46:21 +01:00
const name = 'Pages Plugin'
const version = '1.0.0'
2022-08-16 00:33:35 -05:00
export const sizes = {
2022-02-20 18:46:21 +01:00
a4 : [ 210 , 297 ] ,
a3 : [ 297 , 420 ] ,
a2 : [ 420 , 594 ] ,
a1 : [ 594 , 841 ] ,
a0 : [ 841 , 1188 ] ,
letter : [ 215.9 , 279.4 ] ,
tabloid : [ 279.4 , 431.8 ] ,
}
2022-08-17 13:11:22 -05:00
/** get a letter to represent an index */
2022-08-17 00:34:25 -05:00
const indexLetter = ( i ) => String . fromCharCode ( 'A' . charCodeAt ( 0 ) + i - 1 )
2022-08-17 13:11:22 -05:00
/ * *
* A plugin to add printer pages
* * /
export const pagesPlugin = ( { size = 'a4' , orientation = 'portrait' , margin = 10 } , printStyle = false /** should the pages be rendered for printing or for screen viewing? */ ) => {
const ls = orientation === 'landscape'
let sheetHeight = sizes [ size ] [ ls ? 1 : 0 ]
let sheetWidth = sizes [ size ] [ ls ? 0 : 1 ]
2022-08-16 00:33:35 -05:00
sheetWidth -= margin
sheetHeight -= margin
2022-08-17 13:11:22 -05:00
return basePlugin ( { sheetWidth , sheetHeight , orientation , printStyle } )
2022-08-16 00:33:35 -05:00
}
2022-08-17 13:11:22 -05:00
/ * *
* The base plugin for adding a layout helper part like pages or fabric
* sheetWidth : the width of the helper part
* sheetHeight : the height of the helper part
* boundary : should the helper part calculate its boundary ?
* responsiveColumns : should the part make more columns if the pattern exceed its width ? ( for pages you want this , for fabric you don ' t )
* printStyle : hould the pages be rendered for printing or for screen viewing ?
* * /
const basePlugin = ( {
sheetWidth ,
sheetHeight ,
boundary = false ,
partName = "pages" ,
responsiveColumns = true ,
printStyle = false
} ) => ( {
2022-02-20 18:46:21 +01:00
name ,
version ,
hooks : {
postLayout : function ( pattern ) {
// Add part
2022-08-16 00:33:35 -05:00
pattern . parts [ partName ] = pattern . Part ( partName )
2022-02-20 18:46:21 +01:00
// Keep part out of layout
2022-08-16 00:33:35 -05:00
pattern . parts [ partName ] . layout = false
2022-03-06 18:54:30 +01:00
// But add the part to the autoLayout property
2022-08-16 00:33:35 -05:00
pattern . autoLayout . parts [ partName ] = {
2022-03-06 18:54:30 +01:00
move : { x : 0 , y : 0 }
}
2022-02-20 18:46:21 +01:00
// Add pages
2022-08-16 00:33:35 -05:00
const { macro } = pattern . parts [ partName ] . shorthand ( )
let { height , width } = pattern
2022-08-17 13:11:22 -05:00
if ( ! responsiveColumns ) width = sheetWidth ;
2022-08-17 00:34:25 -05:00
if ( pattern . settings . layout ? . topLeft ) {
height += pattern . settings . layout . topLeft . y
2022-08-17 13:11:22 -05:00
responsiveColumns && ( width += pattern . settings . layout . topLeft . x )
2022-08-17 00:34:25 -05:00
}
2022-08-17 13:11:22 -05:00
macro ( 'addPages' , { size : [ sheetWidth , sheetHeight ] , height , width } )
2022-08-16 00:33:35 -05:00
if ( boundary ) pattern . parts [ partName ] . boundary ( ) ;
2022-02-20 18:46:21 +01:00
}
} ,
macros : {
2022-08-17 13:11:22 -05:00
/** draft the pages */
2022-02-20 18:46:21 +01:00
addPages : function ( so ) {
2022-08-17 13:11:22 -05:00
const [ h , w ] = so . size
2022-02-20 18:46:21 +01:00
const cols = Math . ceil ( so . width / w )
const rows = Math . ceil ( so . height / h )
2022-08-16 00:33:35 -05:00
const { points , Point , paths , Path , macro } = this . shorthand ( )
2022-02-20 18:46:21 +01:00
let x = 0
let y = 0
let count = 0
for ( let row = 0 ; row < rows ; row ++ ) {
x = 0
for ( let col = 0 ; col < cols ; col ++ ) {
count ++
2022-08-16 00:33:35 -05:00
const pageName = ` _pages__row ${ row } -col ${ col } `
points [ ` ${ pageName } -tl ` ] = new Point ( x , y )
points [ ` ${ pageName } -tr ` ] = new Point ( x + w , y )
points [ ` ${ pageName } -br ` ] = new Point ( x + w , y + h )
points [ ` ${ pageName } -bl ` ] = new Point ( x , y + h )
points [ ` ${ pageName } -circle ` ] = new Point ( x + w / 2 , y + h / 2 )
2022-02-20 18:46:21 +01:00
. attr ( 'data-circle' , 42 )
2022-02-25 08:30:03 +01:00
. attr ( 'data-circle-class' , 'stroke-4xl muted fabric' )
2022-08-17 00:34:25 -05:00
. attr ( 'data-circle-id' , ` ${ pageName } -circle ` )
2022-08-16 00:33:35 -05:00
points [ ` ${ pageName } -text ` ] = new Point ( x + w / 2 , y + h / 2 )
2022-08-17 00:34:25 -05:00
. attr ( 'data-text' , ` ${ indexLetter ( col + 1 ) } ${ row + 1 } ` )
2022-08-16 00:33:35 -05:00
. attr ( 'data-text-class' , 'text-4xl center baseline-center bold muted fill-fabric' )
2022-08-17 00:34:25 -05:00
. attr ( 'data-text-id' , ` ${ pageName } -text ` )
2022-02-20 18:46:21 +01:00
2022-08-16 00:33:35 -05:00
paths [ pageName ] = new Path ( )
2022-08-17 00:34:25 -05:00
. attr ( 'id' , pageName )
2022-08-16 00:33:35 -05:00
. move ( points [ ` ${ pageName } -tl ` ] )
. line ( points [ ` ${ pageName } -bl ` ] )
. line ( points [ ` ${ pageName } -br ` ] )
. line ( points [ ` ${ pageName } -tr ` ] )
2022-02-20 18:46:21 +01:00
. close ( )
2022-08-16 00:33:35 -05:00
2022-08-17 13:11:22 -05:00
if ( ! printStyle ) {
2022-08-16 00:33:35 -05:00
paths [ pageName ] . attr ( 'class' , 'fill-fabric' )
2022-02-20 18:46:21 +01:00
. attr ( 'style' , ` stroke-opacity: 0; fill-opacity: ${ ( col + row ) % 2 === 0 ? 0.03 : 0.09 } ; ` )
2022-08-16 00:33:35 -05:00
}
else {
paths [ pageName ] . attr ( 'class' , 'interfacing stroke-xs' )
2022-08-17 13:11:22 -05:00
// add markers and rulers
2022-08-16 00:33:35 -05:00
macro ( 'addPageMarkers' , { row , col , pageName } )
2022-08-17 00:34:25 -05:00
macro ( 'addRuler' , { xAxis : true , pageName } )
macro ( 'addRuler' , { xAxis : false , pageName } )
2022-08-16 00:33:35 -05:00
}
2022-02-20 18:46:21 +01:00
x += w
}
y += h
}
2022-02-20 19:29:14 +01:00
// Store page count in part
this . pages = { cols , rows , count : cols * rows }
2022-03-06 18:54:30 +01:00
2022-08-16 00:33:35 -05:00
} ,
2022-08-17 13:11:22 -05:00
/** add a ruler to the top left corner of the page */
2022-08-16 00:33:35 -05:00
addRuler ( { xAxis , pageName } ) {
2022-08-17 13:27:40 -05:00
const { points , paths , Path } = this . shorthand ( )
2022-08-17 13:11:22 -05:00
// arbitrary number of units for the ruler
2022-08-16 00:33:35 -05:00
const rulerLength = 2
const isMetric = this . context . settings . units === 'metric'
2022-08-17 13:11:22 -05:00
// distance to the end of the ruler
2022-08-16 00:33:35 -05:00
const endPointDist = [ ( isMetric ? 10 : 25.4 ) * rulerLength , 0 ]
const axisName = xAxis ? 'x' : 'y'
2022-08-17 13:11:22 -05:00
const rulerName = ` ${ pageName } - ${ axisName } `
// start by making an endpoint for the ruler based on the axis
2022-08-16 00:33:35 -05:00
const endPoint = [ endPointDist [ xAxis ? 0 : 1 ] , endPointDist [ xAxis ? 1 : 0 ] ]
2022-08-17 13:11:22 -05:00
points [ ` ${ rulerName } -ruler-end ` ] = points [ ` ${ pageName } -tl ` ] . translate ( endPoint [ 0 ] , endPoint [ 1 ] )
// also make a tick for the end of the ruler
points [ ` ${ rulerName } -ruler-tick ` ] = points [ ` ${ rulerName } -ruler-end ` ] . translate ( xAxis ? 0 : 3 , xAxis ? 3 : 0 )
// add a label to it
2022-08-16 00:33:35 -05:00
. attr ( 'data-text' , rulerLength + ( isMetric ? 'cm' : 'in' ) )
2022-08-17 13:11:22 -05:00
// space the text properly from the end of the line
2022-08-17 00:34:25 -05:00
. attr ( 'data-text-class' , 'fill-interfacing baseline-center' + ( xAxis ? ' center' : '' ) )
2022-08-16 00:33:35 -05:00
. attr ( ` data-text-d ${ xAxis ? 'y' : 'x' } ` , xAxis ? 5 : 3 )
2022-08-17 13:11:22 -05:00
// give the text an explicit id in case we need to hide it later
. attr ( 'data-text-id' , ` ${ rulerName } -ruler-text ` )
// start the path
paths [ ` ${ rulerName } -ruler ` ] = new Path ( )
2022-08-16 00:33:35 -05:00
. move ( points [ ` ${ pageName } -tl ` ] )
2022-08-17 13:11:22 -05:00
// give it an explicit id in case we need to hide it later
. attr ( 'id' , ` ${ rulerName } -ruler ` )
. attr ( 'class' , 'interfacing stroke-xs' )
2022-08-16 00:33:35 -05:00
2022-08-17 13:11:22 -05:00
// get the distance between the smaller ticks on the rule
2022-08-16 00:33:35 -05:00
const division = ( isMetric ? 0.1 : 0.125 ) / rulerLength
2022-08-17 13:11:22 -05:00
// we're going to go by fraction, so we want to do this up to 1
2022-08-16 00:33:35 -05:00
for ( var d = division ; d < 1 ; d += division ) {
2022-08-17 13:11:22 -05:00
// make a start point
points [ ` ${ rulerName } -ruler- ${ d } -end ` ] = points [ ` ${ pageName } -tl ` ] . shiftFractionTowards ( points [ ` ${ rulerName } -ruler-end ` ] , d )
2022-08-16 00:33:35 -05:00
2022-08-17 13:11:22 -05:00
// base tick size on whether this is a major interval or a minor one
2022-08-16 00:33:35 -05:00
let tick = 1 ;
2022-08-17 13:11:22 -05:00
// if this tick indicates a whole unit, extra long
2022-08-16 00:33:35 -05:00
if ( d . toFixed ( 3 ) % ( 1 / rulerLength ) === 0 ) tick = 3
2022-08-17 13:11:22 -05:00
// if this tick indicates half a unit, long
2022-08-16 00:33:35 -05:00
else if ( d . toFixed ( 3 ) % ( 0.5 / rulerLength ) === 0 ) tick = 2
2022-08-17 13:11:22 -05:00
// make a point for the end of the tick
points [ ` ${ rulerName } -ruler- ${ d } -tick ` ] = points [ ` ${ rulerName } -ruler- ${ d } -end ` ] . translate ( xAxis ? 0 : tick , xAxis ? tick : 0 )
2022-08-16 00:33:35 -05:00
2022-08-17 13:11:22 -05:00
// add the whole set to the ruler path
paths [ ` ${ rulerName } -ruler ` ]
. line ( points [ ` ${ rulerName } -ruler- ${ d } -end ` ] )
. line ( points [ ` ${ rulerName } -ruler- ${ d } -tick ` ] )
. line ( points [ ` ${ rulerName } -ruler- ${ d } -end ` ] )
2022-08-16 00:33:35 -05:00
}
2022-08-17 13:11:22 -05:00
// add the end
paths [ ` ${ rulerName } -ruler ` ]
. line ( points [ ` ${ rulerName } -ruler-end ` ] )
. line ( points [ ` ${ rulerName } -ruler-tick ` ] )
2022-08-16 00:33:35 -05:00
} ,
2022-08-17 13:11:22 -05:00
/** add page markers to the given page */
2022-08-16 00:33:35 -05:00
addPageMarkers ( { row , col , pageName } ) {
const { macro , points } = this . shorthand ( )
2022-08-17 13:11:22 -05:00
// these markers are placed on the top and left of the page,
// so skip markers for the top row or leftmost column
2022-08-16 00:33:35 -05:00
if ( row !== 0 ) macro ( 'addPageMarker' , {
along : [ points [ ` ${ pageName } -tl ` ] , points [ ` ${ pageName } -tr ` ] ] ,
label : '' + row ,
isRow : true ,
pageName
} )
if ( col !== 0 ) macro ( 'addPageMarker' , {
along : [ points [ ` ${ pageName } -tl ` ] , points [ ` ${ pageName } -bl ` ] ] ,
2022-08-17 00:34:25 -05:00
label : indexLetter ( col ) ,
2022-08-16 00:33:35 -05:00
isRow : false ,
pageName
} )
} ,
2022-08-17 13:11:22 -05:00
/** add a page marker for either the row of the column */
2022-08-16 00:33:35 -05:00
addPageMarker ( { along , label , isRow , pageName } ) {
2022-08-17 13:27:40 -05:00
const { points , paths , Path } = this . shorthand ( )
2022-08-16 00:33:35 -05:00
const markerName = ` ${ pageName } - ${ isRow ? 'row' : 'col' } -marker `
2022-08-17 13:11:22 -05:00
// get a point on the center of the appropriate side
2022-08-16 00:33:35 -05:00
points [ ` ${ markerName } -center ` ] = along [ 0 ] . shiftFractionTowards ( along [ 1 ] , 0.5 )
2022-08-17 13:11:22 -05:00
// add the label to it
2022-08-16 00:33:35 -05:00
. attr ( 'data-text' , label )
. attr ( 'data-text-class' , 'text-sm center baseline-center bold' )
2022-08-17 13:11:22 -05:00
// give it an explicit ID in case we need to hide it later
2022-08-17 00:34:25 -05:00
. attr ( 'data-text-id' , markerName + '-text' )
2022-08-17 13:11:22 -05:00
// get points to make a diamond around the center point
2022-08-16 00:33:35 -05:00
points [ ` ${ markerName } -r ` ] = points [ ` ${ markerName } -center ` ] . translate ( - 5 , 0 )
points [ ` ${ markerName } -l ` ] = points [ ` ${ markerName } -center ` ] . translate ( 5 , 0 )
points [ ` ${ markerName } -t ` ] = points [ ` ${ markerName } -center ` ] . translate ( 0 , - 5 )
points [ ` ${ markerName } -b ` ] = points [ ` ${ markerName } -center ` ] . translate ( 0 , 5 )
2022-08-17 13:11:22 -05:00
// make a path for the diamond
2022-08-16 00:33:35 -05:00
paths [ markerName ] = new Path ( )
. move ( points [ ` ${ markerName } -r ` ] )
. line ( points [ ` ${ markerName } -t ` ] )
. line ( points [ ` ${ markerName } -l ` ] )
. line ( points [ ` ${ markerName } -b ` ] )
. close ( )
. attr ( 'class' , 'fill-interfacing interfacing' )
2022-08-17 13:11:22 -05:00
// give it an explicit ID in case we need to hide it later
2022-08-17 00:34:25 -05:00
. attr ( 'id' , markerName )
2022-02-20 18:46:21 +01:00
}
}
} )