Merge pull request #2739 from CatoTH/Issue2561-pdf-line-numbering-in-lists
Attempt to mitigate the list / line number problem
This commit is contained in:
commit
4e5adb74e3
@ -380,8 +380,9 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
* Convertes HTML for use with pdfMake
|
||||
* @function
|
||||
* @param {object} html - html
|
||||
* @param {string} lineNumberMode - [inline, outside, none]
|
||||
*/
|
||||
convertHTML = function(html, scope) {
|
||||
convertHTML = function(html, lineNumberMode) {
|
||||
var elementStyles = {
|
||||
"b": ["font-weight:bold"],
|
||||
"strong": ["font-weight:bold"],
|
||||
@ -402,6 +403,31 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
"delete": ["color:red", "text-decoration:line-through"],
|
||||
"insert": ["color:green", "text-decoration:underline"]
|
||||
},
|
||||
/**
|
||||
* Removes all line number nodes (not line-breaks)
|
||||
* and returns an array containing the reoved numbers (as integer, not as node)
|
||||
*
|
||||
* @function
|
||||
* @param {object} element
|
||||
*/
|
||||
extractLineNumbers = function(element) {
|
||||
var foundLineNumbers = [];
|
||||
if (element.nodeName == 'SPAN' && element.getAttribute('class').indexOf('os-line-number') > -1) {
|
||||
foundLineNumbers.push(element.getAttribute('data-line-number'));
|
||||
element.parentNode.removeChild(element);
|
||||
} else {
|
||||
var children = element.childNodes,
|
||||
childrenLength = children.length;
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
foundLineNumbers = _.union(foundLineNumbers, extractLineNumbers(children[i]));
|
||||
if (children.length < childrenLength) {
|
||||
i -= (childrenLength - children.length);
|
||||
childrenLength = children.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
return foundLineNumbers;
|
||||
},
|
||||
/**
|
||||
* Parses Children of the current paragraph
|
||||
* @function
|
||||
@ -593,7 +619,7 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
alreadyConverted.push(st);
|
||||
break;
|
||||
case "span":
|
||||
if (scope.lineNumberMode == "inline") {
|
||||
if (lineNumberMode == "inline") {
|
||||
if (diff_mode != DIFF_MODE_INSERT) {
|
||||
var lineNumberInline = element.getAttribute("data-line-number"),
|
||||
lineNumberObjInline = {
|
||||
@ -604,7 +630,7 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
currentParagraph.text.push(lineNumberObjInline);
|
||||
}
|
||||
parseChildren(alreadyConverted, element, currentParagraph, styles, diff_mode);
|
||||
} else if (scope.lineNumberMode == "outside") {
|
||||
} else if (lineNumberMode == "outside") {
|
||||
var lineNumberOutline;
|
||||
if (diff_mode == DIFF_MODE_INSERT) {
|
||||
lineNumberOutline = "";
|
||||
@ -633,7 +659,7 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
break;
|
||||
case "br":
|
||||
//in case of inline-line-numbers and the os-line-break class ignore the break
|
||||
if (!(scope.lineNumberMode == "inline" && element.getAttribute("class") == "os-line-break")) {
|
||||
if (!(lineNumberMode == "inline" && element.getAttribute("class") == "os-line-break")) {
|
||||
currentParagraph = create("text");
|
||||
alreadyConverted.push(currentParagraph);
|
||||
}
|
||||
@ -686,14 +712,37 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
});
|
||||
break;
|
||||
case "ul":
|
||||
var u = create("ul");
|
||||
parseChildren(u.ul, element, currentParagraph, styles, diff_mode);
|
||||
alreadyConverted.push(u);
|
||||
break;
|
||||
case "ol":
|
||||
var o = create("ol");
|
||||
parseChildren(o.ol, element, currentParagraph, styles, diff_mode);
|
||||
alreadyConverted.push(o);
|
||||
var list = create(nodeName);
|
||||
if (lineNumberMode == "outside") {
|
||||
var lines = extractLineNumbers(element);
|
||||
parseChildren(list[nodeName], element, currentParagraph, styles, diff_mode);
|
||||
if (lines.length > 0) {
|
||||
var listCol = {
|
||||
columns: [{
|
||||
width: 20,
|
||||
stack: []
|
||||
}]
|
||||
};
|
||||
_.forEach(lines, function(line) {
|
||||
listCol.columns[0].stack.push({
|
||||
width: 20,
|
||||
text: line,
|
||||
color: "gray",
|
||||
fontSize: 8,
|
||||
margin: [0, 2.35, 0, 0]
|
||||
});
|
||||
});
|
||||
listCol.columns.push(list);
|
||||
listCol.margin = [0,10,0,0];
|
||||
alreadyConverted.push(listCol);
|
||||
} else {
|
||||
alreadyConverted.push(list);
|
||||
}
|
||||
} else {
|
||||
parseChildren(list[nodeName], element, currentParagraph, styles, diff_mode);
|
||||
alreadyConverted.push(list);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
var temporary = create("text", element.textContent.replace(/\n/g, ""));
|
||||
|
@ -257,9 +257,9 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
* https://github.com/OpenSlides/OpenSlides/issues/2361
|
||||
*/
|
||||
var text = motion.getTextByMode($scope.viewChangeRecommendations.mode, $scope.version);
|
||||
return converter.convertHTML(text, $scope);
|
||||
return converter.convertHTML(text, $scope.lineNumberMode);
|
||||
} else {
|
||||
return converter.convertHTML(motion.getText($scope.version), $scope);
|
||||
return converter.convertHTML(motion.getText($scope.version), $scope.lineNumberMode);
|
||||
}
|
||||
};
|
||||
|
||||
@ -271,7 +271,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
text: gettextCatalog.getString('Reason'),
|
||||
style: 'heading3'
|
||||
});
|
||||
reason.push(converter.convertHTML(motion.getReason($scope.version), $scope));
|
||||
reason.push(converter.convertHTML(motion.getReason($scope.version), $scope.lineNumberMode));
|
||||
}
|
||||
return reason;
|
||||
};
|
||||
|
163
tests/karma/core/pdf.service.test.js
Normal file
163
tests/karma/core/pdf.service.test.js
Normal file
@ -0,0 +1,163 @@
|
||||
describe('pdf', function () {
|
||||
|
||||
beforeEach(module('OpenSlidesApp.core.pdf'));
|
||||
beforeEach(module('OpenSlidesApp.motions.lineNumbering'));
|
||||
|
||||
var PdfMakeConverter,
|
||||
lineNumberingService;
|
||||
|
||||
beforeEach(inject(function (_PdfMakeConverter_, _lineNumberingService_) {
|
||||
PdfMakeConverter = _PdfMakeConverter_;
|
||||
lineNumberingService = _lineNumberingService_;
|
||||
}));
|
||||
|
||||
var defaultmargin = [0, 5],
|
||||
emptyline = JSON.stringify({
|
||||
"stack": [
|
||||
{"text": [], "margin": defaultmargin}]
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('converting html to pdfmake', function () {
|
||||
it('converts a simple html string', function () {
|
||||
var instance = PdfMakeConverter.createInstance();
|
||||
var pdfmake = instance.convertHTML(
|
||||
'<p>Hello <strong>strong</strong> world</p>', 'none'
|
||||
);
|
||||
expect(JSON.stringify(pdfmake[0])).toBe(emptyline);
|
||||
expect(JSON.stringify(pdfmake[1])).toBe(JSON.stringify({
|
||||
"stack": [
|
||||
{
|
||||
"text": [
|
||||
{"text": "Hello "},
|
||||
{"text": "strong", "bold": true},
|
||||
{"text": " world"}
|
||||
], "margin": defaultmargin
|
||||
}
|
||||
]
|
||||
}));
|
||||
expect(JSON.stringify(pdfmake[2])).toBe(emptyline);
|
||||
});
|
||||
|
||||
|
||||
it('converts a simple list', function () {
|
||||
var instance = PdfMakeConverter.createInstance();
|
||||
var pdfmake = instance.convertHTML(
|
||||
'<ul>' +
|
||||
'<li>Point 1</li>' +
|
||||
'<li>Point 2</li>' +
|
||||
'</ul>', 'none'
|
||||
);
|
||||
expect(JSON.stringify(pdfmake[0])).toBe(emptyline);
|
||||
expect(JSON.stringify(pdfmake[1])).toBe(JSON.stringify({
|
||||
"ul": [
|
||||
{"stack": [{"text": [{"text": "Point 1"}]}]},
|
||||
{"stack": [{"text": [{"text": "Point 2"}]}]}
|
||||
]
|
||||
}));
|
||||
expect(JSON.stringify(pdfmake[2])).toBe(emptyline);
|
||||
});
|
||||
|
||||
|
||||
it('converts simple text including line numbers (inline)', function () {
|
||||
var inHtml = "<span>Test</span>",
|
||||
numberedHtml = lineNumberingService.insertLineNumbers(inHtml, 5);
|
||||
var instance = PdfMakeConverter.createInstance();
|
||||
var pdfmake = instance.convertHTML(numberedHtml, 'inline');
|
||||
expect(JSON.stringify(pdfmake)).toBe(JSON.stringify([
|
||||
{
|
||||
"stack": [{
|
||||
"text": [
|
||||
{"text": "1", "color": "gray", "fontSize": 5},
|
||||
{"text": " "},
|
||||
{
|
||||
"text": null,
|
||||
"color": "gray",
|
||||
"fontSize": 5
|
||||
},
|
||||
{"text": "Test"}
|
||||
], "margin": [0, 5]
|
||||
}]
|
||||
}
|
||||
]));
|
||||
});
|
||||
|
||||
|
||||
it('converts simple text including line numbers (outside)', function () {
|
||||
var inHtml = "<p>Test Test2 Test3</p>",
|
||||
numberedHtml = lineNumberingService.insertLineNumbers(inHtml, 5);
|
||||
var instance = PdfMakeConverter.createInstance();
|
||||
var pdfmake = instance.convertHTML(numberedHtml, 'outside');
|
||||
|
||||
expect(JSON.stringify(pdfmake[0])).toBe(emptyline);
|
||||
expect(JSON.stringify(pdfmake[1])).toBe(JSON.stringify({
|
||||
"stack": [{"text": [], "margin": [0, 5]}, {
|
||||
"columns": [{
|
||||
"width": 20,
|
||||
"text": "1",
|
||||
"color": "gray",
|
||||
"fontSize": 8,
|
||||
"margin": [0, 2, 0, 0]
|
||||
}, {"text": [{"text": " "}, {"text": "Test "}]}]
|
||||
}, {"text": []}, {
|
||||
"columns": [{
|
||||
"width": 20,
|
||||
"text": "2",
|
||||
"color": "gray",
|
||||
"fontSize": 8,
|
||||
"margin": [0, 2, 0, 0]
|
||||
}, {"text": [{"text": " "}, {"text": "Test2 "}]}]
|
||||
}, {"text": []}, {
|
||||
"columns": [{
|
||||
"width": 20,
|
||||
"text": "3",
|
||||
"color": "gray",
|
||||
"fontSize": 8,
|
||||
"margin": [0, 2, 0, 0]
|
||||
}, {"text": [{"text": " "}, {"text": "Test3"}]}]
|
||||
}]
|
||||
}));
|
||||
expect(JSON.stringify(pdfmake[2])).toBe(emptyline);
|
||||
});
|
||||
|
||||
it('converts a list including line numbers (outside)', function () {
|
||||
var inHtml = "<ul><li>Item 1</li><li>Item 2</li></ul>",
|
||||
numberedHtml = lineNumberingService.insertLineNumbers(inHtml, 10);
|
||||
|
||||
var instance = PdfMakeConverter.createInstance();
|
||||
var pdfmake = instance.convertHTML(numberedHtml, 'outside');
|
||||
|
||||
expect(JSON.stringify(pdfmake[0])).toBe(emptyline);
|
||||
expect(JSON.stringify(pdfmake[1])).toBe(JSON.stringify({
|
||||
"columns": [
|
||||
{
|
||||
"width": 20,
|
||||
"stack": [
|
||||
{"width": 20, "text": "1", "color": "gray", "fontSize": 8, "margin": [0, 2.35, 0, 0]},
|
||||
{"width": 20, "text": "2", "color": "gray", "fontSize": 8, "margin": [0, 2.35, 0, 0]},
|
||||
{"width": 20, "text": "3", "color": "gray", "fontSize": 8, "margin": [0, 2.35, 0, 0]},
|
||||
{"width": 20, "text": "4", "color": "gray", "fontSize": 8, "margin": [0, 2.35, 0, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ul": [{
|
||||
"stack": [
|
||||
{"text": [{"text": "Item "}]},
|
||||
{"text": [{"text": "1"}]}
|
||||
]
|
||||
}, {
|
||||
"stack": [
|
||||
{"text": [{"text": "Item "}]},
|
||||
{"text": [{"text": "2"}]}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"margin": [0,10,0,0]
|
||||
}));
|
||||
expect(JSON.stringify(pdfmake[2])).toBe(emptyline);
|
||||
})
|
||||
});
|
||||
});
|
@ -19,6 +19,7 @@ module.exports = function(config) {
|
||||
'node_modules/angular-mocks/angular-mocks.js',
|
||||
'openslides/motions/static/js/motions/linenumbering.js',
|
||||
'openslides/motions/static/js/motions/diff.js',
|
||||
'openslides/core/static/js/core/pdf.js',
|
||||
'tests/karma/*/*.test.js'
|
||||
],
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user