book-source 0.2.4 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -52,7 +52,7 @@ StructuredDocument.prototype.render = function( renderer ) {
52
52
  title: this.title
53
53
  } ;
54
54
 
55
- var output = this.renderParts( renderer , this.parts , [] ) ;
55
+ var output = this.renderParts( renderer , this.parts , [] , [ {} ] ) ;
56
56
 
57
57
  if ( renderer.document ) {
58
58
  output = renderer.document( meta , output ) ;
@@ -98,14 +98,20 @@ FRAGMENT.structure = {
98
98
  }
99
99
  } ;
100
100
 
101
- StructuredDocument.prototype.renderParts = function( renderer , parts , partStack ) {
101
+ StructuredDocument.prototype.renderParts = function( renderer , parts , partStack , userlandStack ) {
102
102
  var fragment = FRAGMENT[ renderer.type || 'string' ] ,
103
103
  output = fragment.new() ,
104
104
  index = 0 ;
105
105
 
106
106
  for ( let part of parts ) {
107
+ let preFn = 'pre_' + part.type ;
108
+ let postFn = part.type ;
107
109
  let partsOutput = fragment.new() ;
108
110
 
111
+ if ( renderer[ preFn ] ) {
112
+ renderer[ preFn ]( part , partStack , userlandStack , index ) ;
113
+ }
114
+
109
115
  if ( part.parts ) {
110
116
  if ( renderer.group?.[ part.type ] ) {
111
117
  // Some renderer have to group child parts an apply things to each group,
@@ -116,29 +122,38 @@ StructuredDocument.prototype.renderParts = function( renderer , parts , partStac
116
122
  for ( let group of groupList ) {
117
123
  if ( renderer.group[ part.type ][ group.type ] ) {
118
124
  partStack.push( part ) ;
119
- let groupOutput = this.renderParts( renderer , group.parts , partStack ) ;
125
+ userlandStack.push( {} ) ;
126
+
127
+ let groupOutput = this.renderParts( renderer , group.parts , partStack , userlandStack ) ;
128
+
120
129
  partStack.pop() ;
130
+ userlandStack.pop() ;
131
+
121
132
  partsOutput = fragment.concat(
122
133
  partsOutput ,
123
- renderer.group[ part.type ][ group.type ]( part , groupOutput , partStack )
134
+ renderer.group[ part.type ][ group.type ]( part , groupOutput , partStack , userlandStack )
124
135
  ) ;
125
136
  }
126
137
  }
127
138
  }
128
139
  else {
129
140
  partStack.push( part ) ;
141
+ userlandStack.push( {} ) ;
142
+
130
143
  partsOutput = fragment.concat(
131
144
  partsOutput ,
132
- this.renderParts( renderer , part.parts , [ ... partStack , part ] )
145
+ this.renderParts( renderer , part.parts , partStack , userlandStack )
133
146
  ) ;
147
+
134
148
  partStack.pop() ;
149
+ userlandStack.pop() ;
135
150
  }
136
151
  }
137
152
 
138
- if ( renderer[ part.type ] ) {
153
+ if ( renderer[ postFn ] ) {
139
154
  output = fragment.append(
140
155
  output ,
141
- renderer[ part.type ]( part , partsOutput , partStack , index )
156
+ renderer[ postFn ]( part , partsOutput , partStack , userlandStack , index )
142
157
  ) ;
143
158
  }
144
159
 
@@ -1324,8 +1339,7 @@ function parseInlineChildrenOfParent( str , ctx , parent , blockEnd , trim = fal
1324
1339
  // Try to parse non-block content
1325
1340
  function parseInline( str , ctx , blockEnd , trim = false ) {
1326
1341
  //console.log( "parseInline() -- remaining:" , ctx.i , str.slice( ctx.i ) ) ;
1327
- var isSpace , scanEnd ,
1328
- lastWasSpace = WHITE_SPACES.has( str[ ctx.i - 1 ] ) ;
1342
+ var isSpace , scanEnd ;
1329
1343
 
1330
1344
  scanEnd = blockEnd = blockEnd ?? searchEndOfLine( str , ctx.i ) ;
1331
1345
 
@@ -1344,6 +1358,19 @@ function parseInline( str , ctx , blockEnd , trim = false ) {
1344
1358
  scanEnd = last + 1 ;
1345
1359
  }
1346
1360
 
1361
+ parseNestedInline( str , ctx , scanEnd , true ) ;
1362
+ }
1363
+
1364
+
1365
+
1366
+ function parseNestedInline( str , ctx , scanEnd , topLevel = false ) {
1367
+ var isSpace ,
1368
+ lastWasSpace = WHITE_SPACES.has( str[ ctx.i - 1 ] ) ;
1369
+
1370
+ //console.log( "parseInline() -- remaining:" , ctx.i , str.slice( ctx.i ) ) ;
1371
+
1372
+ if ( ! topLevel ) { stack( ctx ) ; }
1373
+
1347
1374
  ctx.iStartOfInlineChunk = ctx.i ;
1348
1375
 
1349
1376
  for ( ; ctx.i < scanEnd ; ctx.i ++ ) {
@@ -1388,8 +1415,10 @@ function parseInline( str , ctx , blockEnd , trim = false ) {
1388
1415
 
1389
1416
  addInlineTextChunk( str , ctx ) ;
1390
1417
 
1391
- ctx.i = blockEnd ;
1418
+ ctx.i = scanEnd ;
1392
1419
  if ( str[ ctx.i ] === '\n' ) { ctx.i ++ ; }
1420
+
1421
+ if ( ! topLevel ) { unstack( ctx ) ; }
1393
1422
  }
1394
1423
 
1395
1424
 
@@ -1467,44 +1496,48 @@ function parseEscape( str , ctx ) {
1467
1496
 
1468
1497
 
1469
1498
 
1470
- function parseEmphasisText( str , ctx , blockEnd ) {
1499
+ function parseEmphasisText( str , ctx , scanEnd ) {
1471
1500
  //console.error( "parseStyledText()" ) ;
1472
1501
  var streak = countStreak( str , ctx.i , '*' ) ;
1473
1502
  if ( streak > 3 ) { return ; }
1474
- var end = searchSwitchCloser( str , ctx.i + streak , '*' , streak , true , false , blockEnd ) ;
1503
+ var end = searchSwitchCloser( str , ctx.i + streak , '*' , streak , true , false , scanEnd ) ;
1475
1504
  if ( end < 0 ) { return ; }
1476
1505
 
1477
- var text = str.slice( ctx.i + streak , end + 1 - streak ) ;
1506
+ ctx.parts.push( new documentParts.EmphasisText( streak ) ) ;
1507
+
1508
+ ctx.i += streak ;
1509
+ parseNestedInline( str , ctx , end + 1 - streak ) ;
1478
1510
 
1479
- ctx.parts.push( new documentParts.EmphasisText( text , streak ) ) ;
1480
1511
  ctx.i = end ;
1481
1512
  ctx.iStartOfInlineChunk = ctx.i + 1 ;
1482
1513
  }
1483
1514
 
1484
1515
 
1485
1516
 
1486
- function parseDecoratedText( str , ctx , blockEnd ) {
1517
+ function parseDecoratedText( str , ctx , scanEnd ) {
1487
1518
  //console.error( "parseStyledText()" ) ;
1488
1519
  var streak = countStreak( str , ctx.i , '_' ) ;
1489
1520
  if ( streak > 2 ) { return ; }
1490
- var end = searchSwitchCloser( str , ctx.i + streak , '_' , streak , true , false , blockEnd ) ;
1521
+ var end = searchSwitchCloser( str , ctx.i + streak , '_' , streak , true , false , scanEnd ) ;
1491
1522
  if ( end < 0 ) { return ; }
1492
1523
 
1493
- var text = str.slice( ctx.i + streak , end + 1 - streak ) ;
1524
+ ctx.parts.push( new documentParts.DecoratedText( streak ) ) ;
1525
+
1526
+ ctx.i += streak ;
1527
+ parseNestedInline( str , ctx , end + 1 - streak ) ;
1494
1528
 
1495
- ctx.parts.push( new documentParts.DecoratedText( text , streak ) ) ;
1496
1529
  ctx.i = end ;
1497
1530
  ctx.iStartOfInlineChunk = ctx.i + 1 ;
1498
1531
  }
1499
1532
 
1500
1533
 
1501
1534
 
1502
- function parseCode( str , ctx , blockEnd ) {
1535
+ function parseCode( str , ctx , scanEnd ) {
1503
1536
  //console.error( "parseStyledText()" ) ;
1504
1537
  var streak = countStreak( str , ctx.i , '`' ) ;
1505
1538
  // Markdown supports inline code inside two pairs of backquote, to allow backquote in code, hence streak can be 2.
1506
1539
  if ( streak > 2 ) { return ; }
1507
- var end = searchSwitchCloser( str , ctx.i + streak , '`' , streak , false , false , blockEnd ) ;
1540
+ var end = searchSwitchCloser( str , ctx.i + streak , '`' , streak , false , false , scanEnd ) ;
1508
1541
  if ( end < 0 ) { return ; }
1509
1542
 
1510
1543
  var sliceStart = ctx.i + streak ,
@@ -1526,27 +1559,39 @@ const STYLE_DATA_MARK = {
1526
1559
  text: true , href: true , style: true , extra: false
1527
1560
  } ;
1528
1561
 
1529
- function parseStyledText( str , ctx , blockEnd ) {
1562
+ function parseStyledText( str , ctx , scanEnd ) {
1530
1563
  //console.error( "parseStyledText()" ) ;
1531
- var end = searchCloser( str , ctx.i + 1 , '[' , ']' , false , blockEnd ) ;
1564
+ var end = searchCloser( str , ctx.i + 1 , '[' , ']' , false , scanEnd ) ;
1532
1565
  if ( end < 0 ) { return ; }
1533
1566
 
1534
- var text = str.slice( ctx.i + 1 , end ) ;
1567
+ //var text = str.slice( ctx.i + 1 , end ) ;
1535
1568
 
1569
+ var start = ctx.i + 1 ;
1536
1570
  ctx.i = end ;
1537
- var data = parseDataMark( str , ctx , STYLE_DATA_MARK , blockEnd ) ;
1571
+ var data = parseDataMark( str , ctx , STYLE_DATA_MARK , scanEnd ) ;
1538
1572
  if ( ! data ) { return ; }
1539
1573
 
1574
+ var fullMarkupEnd = ctx.i ;
1575
+
1540
1576
  var href = data.href?.[ 0 ] ,
1541
1577
  style = data.style?.[ 0 ] ,
1542
1578
  title = data.text?.[ 0 ] ;
1543
1579
 
1544
1580
  if ( href ) {
1545
- ctx.parts.push( new documentParts.Link( text , href , style , title ) ) ;
1581
+ ctx.parts.push( new documentParts.Link( href , style , title ) ) ;
1546
1582
  }
1547
1583
  else if ( style || title ) {
1548
- ctx.parts.push( new documentParts.StyledText( text , style , title ) ) ;
1584
+ ctx.parts.push( new documentParts.StyledText( style , title ) ) ;
1585
+ }
1586
+ else {
1587
+ return ;
1549
1588
  }
1589
+
1590
+ ctx.i = start ;
1591
+ parseNestedInline( str , ctx , end ) ;
1592
+
1593
+ ctx.i = fullMarkupEnd ;
1594
+ ctx.iStartOfInlineChunk = ctx.i + 1 ;
1550
1595
  }
1551
1596
 
1552
1597
 
@@ -1555,16 +1600,16 @@ const IMAGE_DATA_MARK = {
1555
1600
  text: true , href: true , style: false , extra: false
1556
1601
  } ;
1557
1602
 
1558
- function parseImage( str , ctx , blockEnd ) {
1603
+ function parseImage( str , ctx , scanEnd ) {
1559
1604
  //console.error( "parseStyledText()" ) ;
1560
- var end = searchCloser( str , ctx.i + 2 , '[' , ']' , false , blockEnd ) ;
1605
+ var end = searchCloser( str , ctx.i + 2 , '[' , ']' , false , scanEnd ) ;
1561
1606
  if ( end < 0 ) { return ; }
1562
1607
 
1563
1608
  var text = str.slice( ctx.i + 2 , end ) ;
1564
1609
 
1565
1610
  ctx.i = end ;
1566
1611
  ctx.iStartOfInlineChunk = ctx.i + 1 ;
1567
- var data = parseDataMark( str , ctx , IMAGE_DATA_MARK , blockEnd ) ;
1612
+ var data = parseDataMark( str , ctx , IMAGE_DATA_MARK , scanEnd ) ;
1568
1613
  if ( ! data ) { return ; }
1569
1614
 
1570
1615
  var href = data.href?.[ 0 ] ;
@@ -1579,13 +1624,13 @@ function parseImage( str , ctx , blockEnd ) {
1579
1624
 
1580
1625
 
1581
1626
 
1582
- function parseDataMark( str , ctx , allow , blockEnd , forTextElement = true ) {
1627
+ function parseDataMark( str , ctx , allow , scanEnd , forTextElement = true ) {
1583
1628
  var end ,
1584
1629
  data = {} ;
1585
1630
 
1586
1631
  for ( ;; ) {
1587
1632
  if ( str[ ctx.i + 1 ] === '[' && allow.text ) {
1588
- end = searchCloser( str , ctx.i + 2 , '[' , ']' , false , blockEnd ) ;
1633
+ end = searchCloser( str , ctx.i + 2 , '[' , ']' , false , scanEnd ) ;
1589
1634
  if ( end < 0 ) { return ; }
1590
1635
  if ( ! data.text ) { data.text = [] ; }
1591
1636
  data.text.push( str.slice( ctx.i + 2 , end ) ) ;
@@ -1593,7 +1638,7 @@ function parseDataMark( str , ctx , allow , blockEnd , forTextElement = true ) {
1593
1638
  ctx.iStartOfInlineChunk = ctx.i + 1 ;
1594
1639
  }
1595
1640
  else if ( str[ ctx.i + 1 ] === '(' && allow.href ) {
1596
- end = searchCloser( str , ctx.i + 2 , '(' , ')' , true , blockEnd ) ;
1641
+ end = searchCloser( str , ctx.i + 2 , '(' , ')' , true , scanEnd ) ;
1597
1642
  if ( end < 0 ) { return ; }
1598
1643
  if ( ! data.href ) { data.href = [] ; }
1599
1644
  data.href.push( str.slice( ctx.i + 2 , end ) ) ;
@@ -1601,7 +1646,7 @@ function parseDataMark( str , ctx , allow , blockEnd , forTextElement = true ) {
1601
1646
  ctx.iStartOfInlineChunk = ctx.i + 1 ;
1602
1647
  }
1603
1648
  else if ( str[ ctx.i + 1 ] === '<' && allow.style ) {
1604
- end = searchCloser( str , ctx.i + 2 , '<' , '>' , true , blockEnd ) ;
1649
+ end = searchCloser( str , ctx.i + 2 , '<' , '>' , true , scanEnd ) ;
1605
1650
  if ( end < 0 ) { return ; }
1606
1651
  if ( ! data.style ) { data.style = [] ; }
1607
1652
  //data.style.push( str.slice( ctx.i + 2 , end ) ) ;
@@ -1613,7 +1658,7 @@ function parseDataMark( str , ctx , allow , blockEnd , forTextElement = true ) {
1613
1658
  }
1614
1659
  /*
1615
1660
  else if ( str[ ctx.i + 1 ] === '{' && allow.extra ) {
1616
- end = searchCloser( str , ctx.i + 2 , '{' , '}' , false , blockEnd ) ;
1661
+ end = searchCloser( str , ctx.i + 2 , '{' , '}' , false , scanEnd ) ;
1617
1662
  if ( end < 0 ) { return ; }
1618
1663
  if ( ! data.extra ) { data.extra = [] ; }
1619
1664
  data.extra.push( str.slice( ctx.i + 2 , end ) ) ;
@@ -33,15 +33,13 @@ module.exports = documentParts ;
33
33
 
34
34
 
35
35
 
36
- function Part() {
37
- }
36
+ function Part() {}
38
37
 
39
38
  documentParts.Part = Part ;
40
39
 
41
40
 
42
41
 
43
- function InlinePart() {
44
- }
42
+ function InlinePart() {}
45
43
 
46
44
  InlinePart.prototype = Object.create( Part.prototype ) ;
47
45
  InlinePart.prototype.constructor = InlinePart ;
@@ -49,6 +47,16 @@ documentParts.InlinePart = InlinePart ;
49
47
 
50
48
 
51
49
 
50
+ function InlineContainerPart() {
51
+ this.parts = [] ;
52
+ }
53
+
54
+ InlineContainerPart.prototype = Object.create( Part.prototype ) ;
55
+ InlineContainerPart.prototype.constructor = InlineContainerPart ;
56
+ documentParts.InlineContainerPart = InlineContainerPart ;
57
+
58
+
59
+
52
60
  function InlineTextPart( text ) {
53
61
  this.text = text ;
54
62
  }
@@ -82,26 +90,26 @@ documentParts.Text = Text ;
82
90
 
83
91
 
84
92
 
85
- function EmphasisText( text , level ) {
93
+ function EmphasisText( level ) {
86
94
  this.type = 'emphasisText' ;
87
95
  this.level = level ;
88
- InlineTextPart.call( this , text ) ;
96
+ InlineContainerPart.call( this ) ;
89
97
  }
90
98
 
91
- EmphasisText.prototype = Object.create( InlineTextPart.prototype ) ;
99
+ EmphasisText.prototype = Object.create( InlineContainerPart.prototype ) ;
92
100
  EmphasisText.prototype.constructor = EmphasisText ;
93
101
  documentParts.EmphasisText = EmphasisText ;
94
102
 
95
103
 
96
104
 
97
- function DecoratedText( text , level ) {
105
+ function DecoratedText( level ) {
98
106
  this.type = 'decoratedText' ;
99
107
  this.level = level ;
100
108
  this.underline = true ;
101
- InlineTextPart.call( this , text ) ;
109
+ InlineContainerPart.call( this ) ;
102
110
  }
103
111
 
104
- DecoratedText.prototype = Object.create( InlineTextPart.prototype ) ;
112
+ DecoratedText.prototype = Object.create( InlineContainerPart.prototype ) ;
105
113
  DecoratedText.prototype.constructor = DecoratedText ;
106
114
  documentParts.DecoratedText = DecoratedText ;
107
115
 
@@ -118,28 +126,28 @@ documentParts.Code = Code ;
118
126
 
119
127
 
120
128
 
121
- function Link( text , href , style , title ) {
129
+ function Link( href , style , title ) {
122
130
  this.type = 'link' ;
123
131
  this.href = href ;
124
132
  this.style = style || undefined ;
125
- InlineTextPart.call( this , text ) ;
133
+ InlineContainerPart.call( this ) ;
126
134
  this.title = title || undefined ;
127
135
  }
128
136
 
129
- Link.prototype = Object.create( InlineTextPart.prototype ) ;
137
+ Link.prototype = Object.create( InlineContainerPart.prototype ) ;
130
138
  Link.prototype.constructor = Link ;
131
139
  documentParts.Link = Link ;
132
140
 
133
141
 
134
142
 
135
- function StyledText( text , style , title ) {
143
+ function StyledText( style , title ) {
136
144
  this.type = 'styledText' ;
137
145
  this.style = style || undefined ;
138
- InlineTextPart.call( this , text ) ;
146
+ InlineContainerPart.call( this ) ;
139
147
  this.title = title || undefined ;
140
148
  }
141
149
 
142
- StyledText.prototype = Object.create( InlineTextPart.prototype ) ;
150
+ StyledText.prototype = Object.create( InlineContainerPart.prototype ) ;
143
151
  StyledText.prototype.constructor = StyledText ;
144
152
  documentParts.StyledText = StyledText ;
145
153
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "book-source",
3
- "version": "0.2.4",
3
+ "version": "0.3.1",
4
4
  "description": "A lightweight markup language, inspired by Markdown.",
5
5
  "main": "lib/book-source.js",
6
6
  "directories": {