@internetarchive/bookreader 5.0.0-96 → 5.0.0-97
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.
- package/BookReader/474.js +2 -0
- package/BookReader/474.js.map +1 -0
- package/BookReader/BookReader.css +32 -26
- package/BookReader/BookReader.js +1 -1
- package/BookReader/BookReader.js.map +1 -1
- package/BookReader/bergamot-translator-worker.js +2966 -0
- package/BookReader/bergamot-translator-worker.wasm +0 -0
- package/BookReader/ia-bookreader-bundle.js +1 -1
- package/BookReader/ia-bookreader-bundle.js.map +1 -1
- package/BookReader/images/icon_experiment.svg +1 -0
- package/BookReader/images/translate.svg +1 -0
- package/BookReader/plugins/plugin.experiments.js +1 -1
- package/BookReader/plugins/plugin.experiments.js.map +1 -1
- package/BookReader/plugins/plugin.text_selection.js +1 -1
- package/BookReader/plugins/plugin.text_selection.js.map +1 -1
- package/BookReader/plugins/plugin.translate.js +3 -0
- package/BookReader/plugins/plugin.translate.js.LICENSE.txt +1 -0
- package/BookReader/plugins/plugin.translate.js.map +1 -0
- package/BookReader/plugins/plugin.tts.js +1 -1
- package/BookReader/plugins/plugin.tts.js.map +1 -1
- package/BookReader/plugins/translator-worker.js +2 -0
- package/BookReader/plugins/translator-worker.js.map +1 -0
- package/BookReader/translator-worker.js +475 -0
- package/package.json +6 -3
- package/src/BookNavigator/book-navigator.js +1 -0
- package/src/BookReader/Mode1UpLit.js +6 -1
- package/src/BookReader/Mode2UpLit.js +11 -1
- package/src/BookReader/Navbar/Navbar.js +61 -0
- package/src/BookReader.js +22 -139
- package/src/assets/images/icon_experiment.svg +1 -0
- package/src/assets/images/translate.svg +1 -0
- package/src/css/_BRnav.scss +0 -24
- package/src/css/_BRsearch.scss +0 -5
- package/src/css/_TextSelection.scss +32 -1
- package/src/plugins/plugin.experiments.js +34 -9
- package/src/plugins/plugin.text_selection.js +8 -20
- package/src/plugins/translate/TranslationManager.js +167 -0
- package/src/plugins/translate/plugin.translate.js +414 -0
- package/src/plugins/tts/utils.js +9 -20
- package/src/util/cache.js +20 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
/** @typedef {import("../../BookReader.js").default} BookReader */
|
|
2
3
|
|
|
3
4
|
import 'jquery-ui/ui/widget.js';
|
|
@@ -120,6 +121,66 @@ export class Navbar {
|
|
|
120
121
|
});
|
|
121
122
|
}
|
|
122
123
|
|
|
124
|
+
bindControlClickHandlers() {
|
|
125
|
+
const jIcons = this.$nav.find('.BRicon');
|
|
126
|
+
|
|
127
|
+
// Map of jIcon class -> click handler
|
|
128
|
+
const navigationControls = {
|
|
129
|
+
book_left: () => {
|
|
130
|
+
this.br.trigger(EVENTS.stop);
|
|
131
|
+
this.br.left();
|
|
132
|
+
},
|
|
133
|
+
book_right: () => {
|
|
134
|
+
this.br.trigger(EVENTS.stop);
|
|
135
|
+
this.br.right();
|
|
136
|
+
},
|
|
137
|
+
book_top: this.br.first.bind(this.br),
|
|
138
|
+
book_bottom: this.br.last.bind(this.br),
|
|
139
|
+
book_leftmost: this.br.leftmost.bind(this.br),
|
|
140
|
+
book_rightmost: this.br.rightmost.bind(this.br),
|
|
141
|
+
onepg: () => {
|
|
142
|
+
this.br.switchMode('1up');
|
|
143
|
+
},
|
|
144
|
+
thumb: () => {
|
|
145
|
+
this.br.switchMode('thumb');
|
|
146
|
+
},
|
|
147
|
+
twopg: () => {
|
|
148
|
+
this.br.switchMode('2up');
|
|
149
|
+
},
|
|
150
|
+
zoom_in: () => {
|
|
151
|
+
this.br.trigger(EVENTS.stop);
|
|
152
|
+
this.br.zoom(1);
|
|
153
|
+
this.br.trigger(EVENTS.zoomIn);
|
|
154
|
+
},
|
|
155
|
+
zoom_out: () => {
|
|
156
|
+
this.br.trigger(EVENTS.stop);
|
|
157
|
+
this.br.zoom(-1);
|
|
158
|
+
this.br.trigger(EVENTS.zoomOut);
|
|
159
|
+
},
|
|
160
|
+
full: () => {
|
|
161
|
+
if (this.br.ui == 'embed') {
|
|
162
|
+
const url = this.br.$('.BRembedreturn a').attr('href');
|
|
163
|
+
window.open(url);
|
|
164
|
+
} else {
|
|
165
|
+
this.br.toggleFullscreen();
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// custom event for auto-loan-renew in ia-book-actions
|
|
171
|
+
// - to know if user is actively reading
|
|
172
|
+
this.$nav.find('nav.BRcontrols li button').on('click', () => {
|
|
173
|
+
this.br.trigger(EVENTS.userAction);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
for (const control in navigationControls) {
|
|
177
|
+
jIcons.filter(`.${control}`).on('click.bindNavigationHandlers', () => {
|
|
178
|
+
navigationControls[control]();
|
|
179
|
+
return false;
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
123
184
|
/**
|
|
124
185
|
* Toggle viewmode button to change page view
|
|
125
186
|
*/
|
package/src/BookReader.js
CHANGED
|
@@ -330,6 +330,24 @@ BookReader.prototype.setup = function(options) {
|
|
|
330
330
|
this.hasKeyFocus = true;
|
|
331
331
|
};
|
|
332
332
|
|
|
333
|
+
BookReader.prototype.initializePlugin = function(pluginName) {
|
|
334
|
+
const plugin = new BookReader.PLUGINS[pluginName](this);
|
|
335
|
+
this.plugins[pluginName] = plugin;
|
|
336
|
+
try {
|
|
337
|
+
plugin.setup(this.options.plugins?.[pluginName] ?? {});
|
|
338
|
+
this.options.plugins[pluginName] = plugin.options;
|
|
339
|
+
} catch (e) {
|
|
340
|
+
console.error(`Error setting up plugin ${pluginName} outside of regular cycle`, e);
|
|
341
|
+
throw e;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
try {
|
|
345
|
+
plugin.init();
|
|
346
|
+
} catch (e) {
|
|
347
|
+
console.error(`Error initializing plugin ${pluginName} outside of regular cycle`, e);
|
|
348
|
+
throw e;
|
|
349
|
+
}
|
|
350
|
+
};
|
|
333
351
|
/**
|
|
334
352
|
* Get all the HTML Elements that are being/can be rendered.
|
|
335
353
|
* Includes cached elements which might be rendered again.
|
|
@@ -632,8 +650,10 @@ BookReader.prototype.init = function() {
|
|
|
632
650
|
this.initUIStrings();
|
|
633
651
|
|
|
634
652
|
// Bind to events
|
|
635
|
-
|
|
636
|
-
this.
|
|
653
|
+
this._components.navbar.bindControlClickHandlers();
|
|
654
|
+
for (const plugin of Object.values(this.plugins)) {
|
|
655
|
+
plugin._bindNavigationHandlers();
|
|
656
|
+
}
|
|
637
657
|
this.setupKeyListeners();
|
|
638
658
|
|
|
639
659
|
this.lastScroll = (new Date().getTime());
|
|
@@ -1497,141 +1517,6 @@ exposeOverrideableMethod(Toolbar, '_components.toolbar', 'buildInfoDiv');
|
|
|
1497
1517
|
BookReader.prototype.getToolBarHeight = Toolbar.prototype.getToolBarHeight;
|
|
1498
1518
|
exposeOverrideableMethod(Toolbar, '_components.toolbar', 'getToolBarHeight');
|
|
1499
1519
|
|
|
1500
|
-
/**
|
|
1501
|
-
* Bind navigation handlers
|
|
1502
|
-
*/
|
|
1503
|
-
BookReader.prototype.bindNavigationHandlers = function() {
|
|
1504
|
-
const self = this;
|
|
1505
|
-
const jIcons = this.$('.BRicon');
|
|
1506
|
-
|
|
1507
|
-
// Map of jIcon class -> click handler
|
|
1508
|
-
const navigationControls = {
|
|
1509
|
-
book_left: () => {
|
|
1510
|
-
this.trigger(BookReader.eventNames.stop);
|
|
1511
|
-
this.left();
|
|
1512
|
-
},
|
|
1513
|
-
book_right: () => {
|
|
1514
|
-
this.trigger(BookReader.eventNames.stop);
|
|
1515
|
-
this.right();
|
|
1516
|
-
},
|
|
1517
|
-
book_top: this.first.bind(this),
|
|
1518
|
-
book_bottom: this.last.bind(this),
|
|
1519
|
-
book_leftmost: this.leftmost.bind(this),
|
|
1520
|
-
book_rightmost: this.rightmost.bind(this),
|
|
1521
|
-
onepg: () => {
|
|
1522
|
-
this.switchMode(self.constMode1up);
|
|
1523
|
-
},
|
|
1524
|
-
thumb: () => {
|
|
1525
|
-
this.switchMode(self.constModeThumb);
|
|
1526
|
-
},
|
|
1527
|
-
twopg: () => {
|
|
1528
|
-
this.switchMode(self.constMode2up);
|
|
1529
|
-
},
|
|
1530
|
-
zoom_in: () => {
|
|
1531
|
-
this.trigger(BookReader.eventNames.stop);
|
|
1532
|
-
this.zoom(1);
|
|
1533
|
-
this.trigger(BookReader.eventNames.zoomIn);
|
|
1534
|
-
},
|
|
1535
|
-
zoom_out: () => {
|
|
1536
|
-
this.trigger(BookReader.eventNames.stop);
|
|
1537
|
-
this.zoom(-1);
|
|
1538
|
-
this.trigger(BookReader.eventNames.zoomOut);
|
|
1539
|
-
},
|
|
1540
|
-
full: () => {
|
|
1541
|
-
if (this.ui == 'embed') {
|
|
1542
|
-
const url = this.$('.BRembedreturn a').attr('href');
|
|
1543
|
-
window.open(url);
|
|
1544
|
-
} else {
|
|
1545
|
-
this.toggleFullscreen();
|
|
1546
|
-
}
|
|
1547
|
-
},
|
|
1548
|
-
};
|
|
1549
|
-
|
|
1550
|
-
// custom event for auto-loan-renew in ia-book-actions
|
|
1551
|
-
// - to know if user is actively reading
|
|
1552
|
-
this.$('nav.BRcontrols li button').on('click', () => {
|
|
1553
|
-
this.trigger(BookReader.eventNames.userAction);
|
|
1554
|
-
});
|
|
1555
|
-
|
|
1556
|
-
for (const control in navigationControls) {
|
|
1557
|
-
jIcons.filter(`.${control}`).on('click.bindNavigationHandlers', () => {
|
|
1558
|
-
navigationControls[control]();
|
|
1559
|
-
return false;
|
|
1560
|
-
});
|
|
1561
|
-
}
|
|
1562
|
-
|
|
1563
|
-
const $brNavCntlBtmEl = this.$('.BRnavCntlBtm');
|
|
1564
|
-
const $brNavCntlTopEl = this.$('.BRnavCntlTop');
|
|
1565
|
-
|
|
1566
|
-
this.$('.BRnavCntl').click(
|
|
1567
|
-
function() {
|
|
1568
|
-
const promises = [];
|
|
1569
|
-
// TODO don't use magic constants
|
|
1570
|
-
// TODO move this to a function
|
|
1571
|
-
if ($brNavCntlBtmEl.hasClass('BRdn')) {
|
|
1572
|
-
if (self.refs.$BRtoolbar)
|
|
1573
|
-
promises.push(self.refs.$BRtoolbar.animate(
|
|
1574
|
-
{top: self.getToolBarHeight() * -1},
|
|
1575
|
-
).promise());
|
|
1576
|
-
promises.push(self.$('.BRfooter').animate({bottom: self.getFooterHeight() * -1}).promise());
|
|
1577
|
-
$brNavCntlBtmEl.addClass('BRup').removeClass('BRdn');
|
|
1578
|
-
$brNavCntlTopEl.addClass('BRdn').removeClass('BRup');
|
|
1579
|
-
self.$('.BRnavCntlBtm.BRnavCntl').animate({height:'45px'});
|
|
1580
|
-
self.$('.BRnavCntl').delay(1000).animate({opacity:.75}, 1000);
|
|
1581
|
-
} else {
|
|
1582
|
-
if (self.refs.$BRtoolbar)
|
|
1583
|
-
promises.push(self.refs.$BRtoolbar.animate({top:0}).promise());
|
|
1584
|
-
promises.push(self.$('.BRfooter').animate({bottom:0}).promise());
|
|
1585
|
-
$brNavCntlBtmEl.addClass('BRdn').removeClass('BRup');
|
|
1586
|
-
$brNavCntlTopEl.addClass('BRup').removeClass('BRdn');
|
|
1587
|
-
self.$('.BRnavCntlBtm.BRnavCntl').animate({height:'30px'});
|
|
1588
|
-
self.$('.BRvavCntl').animate({opacity:1});
|
|
1589
|
-
}
|
|
1590
|
-
$.when.apply($, promises).done(function() {
|
|
1591
|
-
// Only do full resize in auto mode and need to recalc. size
|
|
1592
|
-
if (self.mode == self.constMode2up && self.twoPage.autofit != null
|
|
1593
|
-
&& self.twoPage.autofit != 'none'
|
|
1594
|
-
) {
|
|
1595
|
-
self.resize();
|
|
1596
|
-
} else if (self.mode == self.constMode1up && self.onePage.autofit != null
|
|
1597
|
-
&& self.onePage.autofit != 'none') {
|
|
1598
|
-
self.resize();
|
|
1599
|
-
} else {
|
|
1600
|
-
// Don't do a full resize to avoid redrawing images
|
|
1601
|
-
self.resizeBRcontainer();
|
|
1602
|
-
}
|
|
1603
|
-
});
|
|
1604
|
-
},
|
|
1605
|
-
);
|
|
1606
|
-
$brNavCntlBtmEl
|
|
1607
|
-
.on("mouseover", function() {
|
|
1608
|
-
if ($(this).hasClass('BRup')) {
|
|
1609
|
-
self.$('.BRnavCntl').animate({opacity:1},250);
|
|
1610
|
-
}
|
|
1611
|
-
})
|
|
1612
|
-
.on("mouseleave", function() {
|
|
1613
|
-
if ($(this).hasClass('BRup')) {
|
|
1614
|
-
self.$('.BRnavCntl').animate({opacity:.75},250);
|
|
1615
|
-
}
|
|
1616
|
-
});
|
|
1617
|
-
$brNavCntlTopEl
|
|
1618
|
-
.on("mouseover", function() {
|
|
1619
|
-
if ($(this).hasClass('BRdn')) {
|
|
1620
|
-
self.$('.BRnavCntl').animate({opacity:1},250);
|
|
1621
|
-
}
|
|
1622
|
-
})
|
|
1623
|
-
.on("mouseleave", function() {
|
|
1624
|
-
if ($(this).hasClass('BRdn')) {
|
|
1625
|
-
self.$('.BRnavCntl').animate({opacity:.75},250);
|
|
1626
|
-
}
|
|
1627
|
-
});
|
|
1628
|
-
|
|
1629
|
-
// Call _bindNavigationHandlers on the plugins
|
|
1630
|
-
for (const plugin of Object.values(this.plugins)) {
|
|
1631
|
-
plugin._bindNavigationHandlers();
|
|
1632
|
-
}
|
|
1633
|
-
};
|
|
1634
|
-
|
|
1635
1520
|
/**************************/
|
|
1636
1521
|
/** BookModel extensions **/
|
|
1637
1522
|
/**************************/
|
|
@@ -1805,8 +1690,6 @@ BookReader.prototype.initUIStrings = function() {
|
|
|
1805
1690
|
'.book_right': 'Flip right',
|
|
1806
1691
|
'.play': 'Play',
|
|
1807
1692
|
'.pause': 'Pause',
|
|
1808
|
-
'.BRdn': 'Show/hide nav bar', // Would have to keep updating on state change to have just "Hide nav bar"
|
|
1809
|
-
'.BRup': 'Show/hide nav bar',
|
|
1810
1693
|
'.book_top': 'First page',
|
|
1811
1694
|
'.book_bottom': 'Last page',
|
|
1812
1695
|
'.book_leftmost': 'First page',
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><g fill="#fff" fill-rule="evenodd"><path d="m20.5312017 91.3043478h59.513497c1.2006191 0 2.1739131-.973294 2.1739131-2.173913 0-.3822983-.1008154-.7578365-.2922774-1.0887357l-25.7859388-44.5652174c-.3886001-.6716082-1.1057054-1.0851774-1.8816356-1.0851774h-9.4292698c-.7956659 0-1.5277636.4346832-1.9086489 1.1332607l-24.2982884 44.5652174c-.5747365 1.0541176-.1861212 2.3745648.8679964 2.9493012.3192413.1740599.677043.2652642 1.0406524.2652642z"/><path d="m58.2338112 0c3.9857698 0 7.0754101 2.92605669 7.0754101 6.52173913 0 1.94814675-1.1751392 3.49748367-3.1329548 4.78763887-.7622726.5029309-1.2209368 1.3542647-1.2211436 2.2659686l-.0000001 17.2659447c0 1.4033895.3628136 2.7830137 1.0533233 4.0053358l29.9382305 52.9958632c.6905098 1.2223221 1.0533234 2.6019463 1.0533234 4.0053358 0 4.5023213-3.655118 8.1521739-8.1639346 8.1521739h-69.6705953c-1.3692898 0-2.7165851-.3439149-3.9178929-1.0000939-3.95568315-2.1606754-5.40829754-7.1143442-3.24450505-11.0643289l29.09149695-53.106279c.6571256-1.1995773 1.0015367-2.5449317 1.0015367-3.9122489l-.0000001-17.3410875c-.000193-.8514978-.3997534-1.6498707-1.0727831-2.1614374l-.1478555-.104365c-1.8735444-1.2352818-3.0298253-2.70631266-3.1268298-4.53659758l-.00663-.25182269c0-3.59709019 3.085096-6.52173913 7.07541-6.52173913zm0 5.43478261h-17.4163939c-.3341979 0-.655354.0973303-.9634683.29199092l-.1529759.10543374c-.2276736.17021467-.2742532.49276685-.1040386.72044045l.0538074.06119811.0627915.05193913.1617643.10919499c2.2021208 1.45291154 3.5596356 3.87504265 3.6577257 6.49699115l.0057053.3033755.0000002 17.3417027c0 2.2788621-.5740185 4.5211194-1.6692279 6.5204148l-29.0914969 53.106279c-.7212642 1.3166616-.2370594 2.9678845 1.0815017 3.6881097.4004359.2187263.8495344.3333646 1.3059643.3333646h69.6705953c1.5029388 0 2.7213115-1.2166175 2.7213115-2.7173913 0-.4677965-.1209379-.9276713-.3511078-1.3351119l-29.9382305-52.9958633c-1.1508495-2.0372034-1.7555389-4.336577-1.7555389-6.6755596l.0000002-17.2665599c.0005984-2.6392088 1.2800823-5.10829666 3.4230589-6.63488495l.2416409-.16570308c.2977633-.19621921.380081-.59667116.1838618-.89443446-.0526648-.07991901-.1224381-.14713032-.2042705-.1967699-.2372346-.14393755-.4815228-.22451299-.7328507-.24174888z" fill-rule="nonzero"/></g></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><g fill="#FFF"><path d="m55.6227664 40v-10.9816972c0-1.2005631.4447386-2.2302572 1.3342157-3.0890823.8894772-.858825 1.9338187-1.2888775 3.1330245-1.2901574h7.702184v6.5391015l14.2078094-10.6188404-14.2078094-10.5593242v6.6005376h-7.8252813c-3.5579086 0-6.6082065 1.2300012-9.1508934 3.6900038-2.542687 2.4600026-3.8146923 5.4095738-3.8160159 8.8487137v10.8607449z" transform="matrix(-1 0 0 1 129 0)"/><path d="m26.6227664 90v-10.9816972c0-1.2005631.4447386-2.2302572 1.3342157-3.0890823.8894772-.858825 1.9338187-1.2888775 3.1330245-1.2901574h7.702184v6.5391015l14.2078094-10.6188404-14.2078094-10.5593242v6.6005376h-7.8252813c-3.5579086 0-6.6082065 1.2300012-9.1508934 3.6900038-2.542687 2.4600026-3.8146923 5.4095738-3.8160159 8.8487137v10.8607449z" transform="matrix(1 0 0 -1 0 150)"/><g fill-rule="evenodd"><path d="m36.1711896 0c.7952259 0 1.5825239.11678603 2.361894.35035809.7793701.23357205 1.3385895.44226661 1.6776582.62608367.3390687.18381707.9354881.50929765 1.7892582.97644177v53.04711647h-41.11634795c-.26466873-.2667421-.47079323-.6253926-.61837349-1.0759518-.14758025-.4505591-.23600644-.8423796-.26527856-1.1754617v-52.7485865zm-15.8773502 11c-2.6260005.9445399-3.9390007 1.4168099-3.9390007 1.4168099.8613947 1.0405262 1.656859 2.1393299 2.3863927 3.2964109.2700118.4282536.5298575.8568906.7795373 1.2859111l-14.5207687.0008681v3l6.4238969.0000134c.8804258 3.5657294 2.3239844 6.8097976 4.3306759 9.7322048 1.0398193 1.5143213 2.176787 2.9231182 3.410903 4.2263908-3.5068695 3.0329696-7.8850877 5.246602-13.13321774 6.6415991 1.30042972 2.2665279 1.95064458 3.3997919 1.95064458 3.3997919 5.83922866-1.8768332 10.47451876-4.3674587 13.90587026-7.4718765.7278161.6172884 1.4851619 1.2034299 2.2700924 1.7596083 3.2815631 2.3252177 6.8996284 4.2293071 10.8541961 5.7122682 1.3246257-2.1759469 1.9869386-3.2639204 1.9869386-3.2639204-3.7993227-1.4042832-7.2042979-3.1143224-10.2149257-5.1301175-.8119265-.5436333-1.5953934-1.1239157-2.3504008-1.7408472 3.3115726-3.9242615 5.6922469-8.5457291 7.1440766-13.8651104l4.3889918-.0000045v-3l-12.2148765-.0011479c-.3495756-.7520023-.7243601-1.4925223-1.1243535-2.2215599-.7129337-1.2994097-1.4911578-2.5585071-2.3346725-3.7772922zm7.4469262 9.0006565c-1.3612535 4.5640835-3.3583061 8.3614158-5.9911579 11.3919968-1.0548712-1.0913671-2.041101-2.2689312-2.9598238-3.5334282-1.7358278-2.3891311-2.9991645-5.0087964-3.79001-7.858996z"/><path d="m94.1711896 45c.7952259 0 1.5825239.116786 2.361894.3503581.7793701.233572 1.3385895.4422666 1.6776582.6260837.3390687.183817.9354881.5092976 1.7892582.9764417v53.0471165h-41.116348c-.2646687-.2667421-.4707932-.6253926-.6183734-1.0759518-.1475803-.4505591-.2360065-.8423796-.2652786-1.1754617v-52.7485865zm-11.1769203 11h-7.8424068l-13.1518625 33h7.6962751l2.7277937-7.3487395h13.0057306l2.6303725 7.3487395h7.9398281zm-3.8794044 8.25 4.1351351 12.375h-8.5l4.272973-12.375z"/></g></g></svg>
|
package/src/css/_BRnav.scss
CHANGED
|
@@ -35,14 +35,6 @@
|
|
|
35
35
|
border: 3px solid rgba(255,255,255,0.3);
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
-
|
|
39
|
-
.BRnavCntl {
|
|
40
|
-
z-index: $brZindexBase + 5;
|
|
41
|
-
background-color: $brColorDarkBorder;
|
|
42
|
-
}
|
|
43
|
-
.BRnavCntlBtm:hover {
|
|
44
|
-
background-color: $brColorThemeblue;
|
|
45
|
-
}
|
|
46
38
|
}
|
|
47
39
|
|
|
48
40
|
@mixin brNavLight {
|
|
@@ -66,14 +58,6 @@
|
|
|
66
58
|
border: 3px solid rgba($brColorThemeblue,0.3);
|
|
67
59
|
}
|
|
68
60
|
}
|
|
69
|
-
|
|
70
|
-
.BRnavCntl {
|
|
71
|
-
background-color: $brColorLightBorder;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
.BRnavCntlBtm:hover {
|
|
75
|
-
background-color: $brColorThemeblue;
|
|
76
|
-
}
|
|
77
61
|
}
|
|
78
62
|
|
|
79
63
|
@keyframes fadeUp {
|
|
@@ -319,20 +303,12 @@
|
|
|
319
303
|
font-size: .8em;
|
|
320
304
|
vertical-align: top;
|
|
321
305
|
}
|
|
322
|
-
.BRup {
|
|
323
|
-
background-image: url("images/nav_control-up.png");
|
|
324
|
-
background-repeat: no-repeat;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
306
|
|
|
328
307
|
/* Mobile Only */
|
|
329
308
|
@media (max-width: $brBreakPointMobile) {
|
|
330
309
|
/* hide navline chapters and search in mobile */
|
|
331
310
|
.BRnavline .BRchapter { display: none; }
|
|
332
311
|
|
|
333
|
-
.BRnavCntlBtm {
|
|
334
|
-
bottom: $brNavHeightMobile;
|
|
335
|
-
}
|
|
336
312
|
.BRpager.ui-slider {
|
|
337
313
|
height: 10px;
|
|
338
314
|
top: math.div($brNavHeightMobile, 2) - 5px;
|
package/src/css/_BRsearch.scss
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
.BRtextLayer {
|
|
1
|
+
.BRtextLayer, .BRtranslateLayer {
|
|
2
2
|
z-index: 2;
|
|
3
3
|
position: absolute;
|
|
4
4
|
top: 0;
|
|
@@ -8,9 +8,16 @@
|
|
|
8
8
|
// Make it so right-clicking on "blank" part of text layer sends events to the image (for saving)
|
|
9
9
|
pointer-events: none;
|
|
10
10
|
cursor: text;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.BRtextLayer {
|
|
11
14
|
mix-blend-mode: multiply;
|
|
12
15
|
}
|
|
13
16
|
|
|
17
|
+
.BRtranslateLayer {
|
|
18
|
+
hyphens: auto;
|
|
19
|
+
}
|
|
20
|
+
|
|
14
21
|
.BRparagraphElement {
|
|
15
22
|
margin: 0;
|
|
16
23
|
cursor: text;
|
|
@@ -108,3 +115,27 @@
|
|
|
108
115
|
background: #ccbfa7;
|
|
109
116
|
word-spacing: unset !important;
|
|
110
117
|
}
|
|
118
|
+
|
|
119
|
+
.BRtranslateLayer .BRparagraphElement {
|
|
120
|
+
pointer-events: auto;
|
|
121
|
+
overflow-y: auto;
|
|
122
|
+
background: rgba(248, 237, 192, 0.5);
|
|
123
|
+
backdrop-filter: blur(8px);
|
|
124
|
+
color:black;
|
|
125
|
+
line-height: 1em;
|
|
126
|
+
text-align: justify;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.BRtranslateLayer .BRparagraphElement .BRlineElement {
|
|
130
|
+
white-space: break-spaces;
|
|
131
|
+
display: inline-block;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.BRtextLayer.showingTranslation {
|
|
135
|
+
visibility: hidden;
|
|
136
|
+
pointer-events: none;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.BRtranslateLayer .BRparagraphElement.BRtranslateHidden {
|
|
140
|
+
display: none;
|
|
141
|
+
}
|
|
@@ -21,6 +21,9 @@ class ExperimentModel {
|
|
|
21
21
|
/** @type {string} */
|
|
22
22
|
learnMore;
|
|
23
23
|
|
|
24
|
+
/** @type {import("@/src/BookReader.js").default} */
|
|
25
|
+
br;
|
|
26
|
+
|
|
24
27
|
assetRoot = '/BookReader/';
|
|
25
28
|
|
|
26
29
|
enabledLoading = false;
|
|
@@ -46,10 +49,32 @@ export class ExperimentsPlugin extends BookReaderPlugin {
|
|
|
46
49
|
|
|
47
50
|
/** Where the state of this plugin is saved in localStorage */
|
|
48
51
|
localStorageKey: 'BrExperiments',
|
|
52
|
+
|
|
53
|
+
/** The experiments that should be shown in the experiments panel */
|
|
54
|
+
enabledExperiments: ['translate'],
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
/** @type {ExperimentModel[]} */
|
|
52
|
-
|
|
58
|
+
allExperiments = [
|
|
59
|
+
new class extends ExperimentModel {
|
|
60
|
+
name = 'translate';
|
|
61
|
+
title = 'Translate Plugin';
|
|
62
|
+
description = "Translate books directly in your browser.";
|
|
63
|
+
learnMore = 'https://mozilla.github.io/translations/';
|
|
64
|
+
icon = 'images/translate.svg';
|
|
65
|
+
enabled = false;
|
|
66
|
+
async enable({ manual = false}) {
|
|
67
|
+
await importAsScript(this.buildAssetPath('plugins/plugin.translate.js'));
|
|
68
|
+
this.br.initializePlugin('translate');
|
|
69
|
+
}
|
|
70
|
+
async disable() {
|
|
71
|
+
// need to reload to remove translate plugin script
|
|
72
|
+
// Sleep so that the event loop can finish processing before the reload
|
|
73
|
+
sleep(0).then(() => {
|
|
74
|
+
window.location.reload();
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}(),
|
|
53
78
|
new class extends ExperimentModel {
|
|
54
79
|
name = 'hypothesis';
|
|
55
80
|
title = 'Hypothes.is';
|
|
@@ -93,10 +118,11 @@ export class ExperimentsPlugin extends BookReaderPlugin {
|
|
|
93
118
|
return;
|
|
94
119
|
}
|
|
95
120
|
|
|
96
|
-
for (const experiment of this.
|
|
121
|
+
for (const experiment of this.allExperiments) {
|
|
97
122
|
// TODO: imagesBaseURL should be replaced with assetRoot everywhere
|
|
98
123
|
experiment.assetRoot = this.br.options.imagesBaseURL.replace(/images\/$/, '');
|
|
99
124
|
experiment.icon = experiment.buildAssetPath(experiment.icon);
|
|
125
|
+
experiment.br = this.br;
|
|
100
126
|
}
|
|
101
127
|
|
|
102
128
|
this._loadExperimentStates();
|
|
@@ -106,7 +132,7 @@ export class ExperimentsPlugin extends BookReaderPlugin {
|
|
|
106
132
|
|
|
107
133
|
_loadExperimentStates() {
|
|
108
134
|
const savedStates = JSON.parse(localStorage.getItem(this.options.localStorageKey) || '{}');
|
|
109
|
-
this.
|
|
135
|
+
this.allExperiments.forEach(experiment => {
|
|
110
136
|
if (savedStates[experiment.name] !== undefined) {
|
|
111
137
|
experiment.enabled = savedStates[experiment.name];
|
|
112
138
|
if (experiment.enabled) {
|
|
@@ -118,7 +144,7 @@ export class ExperimentsPlugin extends BookReaderPlugin {
|
|
|
118
144
|
|
|
119
145
|
_saveExperimentStates() {
|
|
120
146
|
const states = Object.fromEntries(
|
|
121
|
-
this.
|
|
147
|
+
this.allExperiments.map(experiment => [experiment.name, experiment.enabled]),
|
|
122
148
|
);
|
|
123
149
|
localStorage.setItem(this.options.localStorageKey, JSON.stringify(states));
|
|
124
150
|
}
|
|
@@ -145,13 +171,12 @@ export class ExperimentsPlugin extends BookReaderPlugin {
|
|
|
145
171
|
_render() {
|
|
146
172
|
this.br.shell.menuProviders['experiments'] = {
|
|
147
173
|
id: 'experiments',
|
|
148
|
-
// https://icon-sets.iconify.design/hugeicons/?icon-filter=eco-lab-02&query=lab
|
|
149
174
|
icon: html`
|
|
150
|
-
<
|
|
175
|
+
<img src="${this.br.options.imagesBaseURL}/icon_experiment.svg" width="26"/>
|
|
151
176
|
`,
|
|
152
177
|
label: 'Experiments',
|
|
153
178
|
component: html`<br-experiments-panel
|
|
154
|
-
.experiments="${this.
|
|
179
|
+
.experiments="${this.allExperiments.filter(experiment => this.options.enabledExperiments.includes(experiment.name))}"
|
|
155
180
|
@connected="${e => this._panel = e.target}"
|
|
156
181
|
@toggle="${async e => {
|
|
157
182
|
await this._toggleExperiment(e.detail.experiment, e.detail.enabled);
|
|
@@ -240,14 +265,14 @@ export class BrExperimentToggle extends LitElement {
|
|
|
240
265
|
|
|
241
266
|
render() {
|
|
242
267
|
return html`
|
|
243
|
-
<div class="experiment-card">
|
|
268
|
+
<div class="experiment-card" style="margin-bottom: 10px;">
|
|
244
269
|
<div style="display: flex; align-items: center; gap: 10px;">
|
|
245
270
|
<img src="${this.icon}" style="width: 20px; height: 20px;" alt="" />
|
|
246
271
|
<div style="flex-grow: 1; font-weight: bold;">${this.title}</div>
|
|
247
272
|
</div>
|
|
248
273
|
<p style="opacity: 0.9">
|
|
249
274
|
${this.description}
|
|
250
|
-
|
|
275
|
+
${this.learnMore ? html`<a href="${this.learnMore}" target="_blank">Learn more</a>.` : ''}
|
|
251
276
|
</p>
|
|
252
277
|
<div style="display: flex">
|
|
253
278
|
<div style="flex-grow: 1;"></div>
|
|
@@ -3,31 +3,12 @@ import { createDIVPageLayer } from '../BookReader/PageContainer.js';
|
|
|
3
3
|
import { SelectionObserver } from '../BookReader/utils/SelectionObserver.js';
|
|
4
4
|
import { BookReaderPlugin } from '../BookReaderPlugin.js';
|
|
5
5
|
import { applyVariables } from '../util/strings.js';
|
|
6
|
+
import { Cache } from '../util/cache.js';
|
|
6
7
|
/** @typedef {import('../util/strings.js').StringWithVars} StringWithVars */
|
|
7
8
|
/** @typedef {import('../BookReader/PageContainer.js').PageContainer} PageContainer */
|
|
8
9
|
|
|
9
10
|
const BookReader = /** @type {typeof import('../BookReader').default} */(window.BookReader);
|
|
10
11
|
|
|
11
|
-
/**
|
|
12
|
-
* @template T
|
|
13
|
-
*/
|
|
14
|
-
export class Cache {
|
|
15
|
-
constructor(maxSize = 10) {
|
|
16
|
-
this.maxSize = maxSize;
|
|
17
|
-
/** @type {T[]} */
|
|
18
|
-
this.entries = [];
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @param {T} entry
|
|
23
|
-
*/
|
|
24
|
-
add(entry) {
|
|
25
|
-
if (this.entries.length >= this.maxSize) {
|
|
26
|
-
this.entries.shift();
|
|
27
|
-
}
|
|
28
|
-
this.entries.push(entry);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
12
|
|
|
32
13
|
export class TextSelectionPlugin extends BookReaderPlugin {
|
|
33
14
|
options = {
|
|
@@ -327,6 +308,9 @@ export class TextSelectionPlugin extends BookReaderPlugin {
|
|
|
327
308
|
}
|
|
328
309
|
|
|
329
310
|
const textLayer = createDIVPageLayer(pageContainer.page, 'BRtextLayer');
|
|
311
|
+
// Have to wait to make sure the page container is actually rendered,
|
|
312
|
+
// otherwise width/height are unset after a mode change.
|
|
313
|
+
await Promise.resolve();
|
|
330
314
|
const ratioW = parseFloat(pageContainer.$container[0].style.width) / pageContainer.page.width;
|
|
331
315
|
const ratioH = parseFloat(pageContainer.$container[0].style.height) / pageContainer.page.height;
|
|
332
316
|
textLayer.style.transform = `scale(${ratioW}, ${ratioH})`;
|
|
@@ -356,6 +340,10 @@ export class TextSelectionPlugin extends BookReaderPlugin {
|
|
|
356
340
|
}
|
|
357
341
|
$container.append(textLayer);
|
|
358
342
|
this.stopPageFlip($container);
|
|
343
|
+
this.br.trigger('textLayerRendered', {
|
|
344
|
+
pageIndex,
|
|
345
|
+
pageContainer,
|
|
346
|
+
});
|
|
359
347
|
}
|
|
360
348
|
|
|
361
349
|
/**
|