diff --git a/package-lock.json b/package-lock.json index 3c2de25..6198b52 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@lawsafrica/indigo-akn", - "version": "5.5.0", + "version": "5.6.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@lawsafrica/indigo-akn", - "version": "5.5.0", + "version": "5.6.0", "license": "LGPL-3.0-or-later", "dependencies": { "@lawsafrica/dom-anchor-text-quote": "^5.0.0", diff --git a/package.json b/package.json index b93709c..6e1e10b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lawsafrica/indigo-akn", - "version": "5.5.0", + "version": "5.6.0", "description": "Akoma Ntoso support libraries for the Indigo platform.", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/src/grammars.js b/src/grammars.js index c3cd5b3..2d84639 100644 --- a/src/grammars.js +++ b/src/grammars.js @@ -1,4 +1,5 @@ import { htmlToAkn } from "./html"; +import { fixTables } from "./xml"; /** * Base class for grammar models. diff --git a/src/index.js b/src/index.js index 2fd2a99..e42f026 100644 --- a/src/index.js +++ b/src/index.js @@ -3,3 +3,4 @@ export * from './html'; export * from './eids'; export * from './enrichments'; export * from './ranges'; +export * from './xml'; diff --git a/src/xml.js b/src/xml.js new file mode 100644 index 0000000..7d9868b --- /dev/null +++ b/src/xml.js @@ -0,0 +1,119 @@ +/** + * Returns a map of a table, taking all colspans and rowspans into account. + */ +export function mapTable(table) { + let matrix = {}, + rows = table.children; + + for (let y = 0; y < rows.length; y++) { + // set default + if (!matrix[y]) { + matrix[y] = {}; + } + let row = rows[y]; + let cells = row.children; + for (let x = 0; x < cells.length; x++) { + // stash 'x' so we don't end the loop prematurely if it's incremented below + let xPos = x; + let cell = cells[x]; + // set default; increment xPos if needed (skip already occupied cells in current row) + while (matrix[y][xPos]) { + xPos += 1; + } + matrix[y][xPos] = {}; + // mark matrix elements occupied by current cell with true + let colSpanTotal = xPos + Number(cell.getAttribute('colspan') || 1); + let rowSpanTotal = y + Number(cell.getAttribute('rowspan') || 1); + + for (let xx = xPos; xx < colSpanTotal; xx++) { + for (let yy = y; yy < rowSpanTotal; yy++) { + if (!matrix[yy]) { + matrix[yy] = {}; + } + // don't try to make overlapping spans work + if (matrix[yy][xx] === true) { + throw "Cannot parse overlapping spans in table with eId " + table.getAttribute("eId"); + } + matrix[yy][xx] = true; + } + } + } + } + return matrix; +} + +/** + * Fixes a table by inserting missing rows and cells to match the table's matrix. + */ +export function fixTable(table) { + // track the fixes + let removedRow = false, + addedRow = false, + addedCell = false; + // remove empty rows before starting + for (let r = 0; r < table.children.length; r++) { + let row = table.children[r]; + if (!row.children.length) { + table.removeChild(row); + removedRow = true; + } + } + + let xmlns = table.namespaceURI, + tableMap = mapTable(table), + nMappedRows = Object.keys(tableMap).length; + + // add missing rows + let nMissingRows = nMappedRows - table.children.length; + for (let y = 0; y < nMissingRows; y++) { + console.log("adding a missing row to table ", table.getAttribute('eId')); + table.appendChild(document.createElementNS(xmlns, 'tr')); + addedRow = true; + } + + // add missing cells + let nMaxMappedColumns = Math.max(...Object.values(tableMap).map(r => Object.keys(r).length)); + for (let r = 0; r < table.children.length; r++) { + let nMissingCells = nMaxMappedColumns - Object.keys(tableMap[r]).length, + row = table.children[r]; + for (let m = 0; m < nMissingCells; m++) { + console.log("adding a missing cell to table ", table.getAttribute('eId'), " row ", r); + let cell = document.createElementNS(xmlns, 'td'); + cell.appendChild(document.createElementNS(xmlns, 'p')); + row.appendChild(cell); + addedCell = true; + } + } + + // report fixes + if (removedRow || addedRow || addedCell) { + let fixes = []; + if (removedRow) { + fixes.push("removed empty row(s)"); + } + if (addedRow) { + fixes.push("added missing row(s)"); + } + if (addedCell) { + fixes.push("added missing cell(s)"); + } + return `Table with eId ${table.getAttribute('eId')}: ${fixes.join(", ")}`; + } else { + return null; + } +} + +/** + * Fixes all tables in a list of Akoma Ntoso XML elements. + */ +export function fixTables (elementList) { + let fixedTables = []; + for (let i = 0; i < elementList.length; i++) { + let tableList = elementList[i].querySelectorAll("table"); + for (let t = 0; t < tableList.length; t++) { + let fixed = fixTable(tableList[t]); + if (fixed) {fixedTables.push(fixed);} + } + } + return fixedTables; +} diff --git a/tests/xml.js b/tests/xml.js new file mode 100644 index 0000000..3153793 --- /dev/null +++ b/tests/xml.js @@ -0,0 +1,2235 @@ +import { expect } from 'chai'; +import { mapTable, fixTable, fixTables } from "../src/xml"; + +describe('mapTable', () => { + it('should return an accurate map of a table, taking all colspans and rowspans into account', () => { + const xml = `
+ Heading 1 + |
+
+ Heading 2 + |
+
---|---|
+ + | ++ + | +
+ + | +|
+ Content 1 + |
+
+ Content 2 + |
+
+ Heading 1 + |
+
+ Heading 2 + |
+
---|---|
+ + | ++ + | +
+ + | +|
+ Content 1 + |
+
+ Content 2 + |
+
+ Heading 1 + |
+
+ Heading 2 + |
+|
---|---|---|
+ + | ++ + | +|
+ + | +||
+ Content 1 + |
+
+ Content 2 + |
+|
+ Heading 1 + |
+
+ Heading 2 + |
+
---|---|
+ + | ++ + | +
+ + | +|
+ Content 1 + |
+
+ Content 2 + |
+
+ Heading 1 + |
+
+ Heading 2 + |
+ |
---|---|---|
+ + | ++ + | ++ + | +
+ + | +||
+ Content 1 + |
+
+ Content 2 + |
+
+ Heading 1 + |
+
+ Heading 2 + |
+
---|---|
+ + | ++ + | +
+ + | +|
+ Content 1 + |
+
+ Content 2 + |
+
+ Heading 1 + |
+
+ Heading 2 + |
+
---|---|
+ + | ++ + | +
+ + | ++ + | +
+ Content 1 + |
+
+ Content 2 + |
+
+ Heading 1 + |
+
+ Heading 2 + |
+ |
---|---|---|
+ + | ++ + | +|
+ + | +||
+ Content 1 + |
+
+ Content 2 + |
+ |
+ Heading 1 + |
+
+ Heading 2 + |
+ |
---|---|---|
+ + | ++ + | ++ + | +
+ + | +||
+ Content 1 + |
+
+ Content 2 + |
+ |
+ Heading 1 + |
+
+ Heading 2 + |
+ |
---|---|---|
+ + | ++ + | +|
+ + | +||
+ Content 1 + |
+
+ Content 2 + |
+
+ Heading 1 + |
+
+ Heading 2 + |
+
---|---|
+ + | ++ + | +
+ + | ++ + | +
+ Content 1 + |
+
+ Content 2 + |
+
+ Nature of ownership |
+
+ .The percentage of issued shares a person holds in the company - Directly.........%of shares |
+ ||
+ The percentage of voting rights a person holds in the company |
+ |||
+ .A person holds a right to appoint or remove a majority of the members of the board of directors of the company : |
+ |||
+ A person exercises significant influence or control over the company. |
+ |||
+ .A person holds the highest percentage of the issued |
+
+ Address of Department +(To be completed by an official) + |
+ + + | ++ + | +||||||
+ Reference number +(To be completed by an official) + |
+ + + | +|||||||
+ Complete this form by using BLOCK letters and by ticking the appropriate boxes. + |
+ ||||||||
+ Part A: Applications in terms of the Act + |
+ ||||||||
+ Land development +Section 53(2) of the Act and regulations 10(4) and 12) + |
+
+ Y + |
+
+ N + |
+
+ If yes, complete all parts, except part H, of this application form. + |
+ |||||
+ Amendment of land development approval +(Section 53(2) of the Act and regulations 10(5) and 12) + |
+
+ Y + |
+
+ N + |
+
+ If yes, complete all parts, except part H, of this application form. + |
+ |||||
+ Extension of validity period +(Section 57(2) of the Act and regulation 28) + |
+
+ Y + |
+
+ N + |
+
+ If yes, complete all parts, except part G, of this application form. + |
+ |||||
+ Part B: Applicant details + |
+ ||||||||
+ First name(s) + |
+ + + | +|||||||
+ Surname + |
+ + + | +|||||||
+ Company name (If applicable) + |
+ + + | +|||||||
+ Postal address + |
+ + + | +
+ Postal code + |
+ + + | +|||||
+ |
+ + + | +|||||||
+ Tel. + |
+
+ Fax + |
+ + + | +
+ Cell. + |
+ + + | +
+ Part C: Details of owner(s)(If different from applicant) + |
+ |||||||||||||||||
+ Full name(s) + |
+ + + | +||||||||||||||||
+ Physical address(es) + |
+ + + | ++ + | +|||||||||||||||
+ + | +
+ Postal code + |
+ + + | +|||||||||||||||
+ |
+ + + | +||||||||||||||||
+ Tel. + |
+ + + | +
+ Fax + |
+
+ Cell. + |
+ + + | +|||||||||||||
+ Part D: Property details (In accordance with title deed) + |
+ |||||||||||||||||
+ Property description (Number(s) of Erf/ Erven/Portion(s) or Farm(s)) + |
+ + + | +||||||||||||||||
+ Physical address + |
+ + + | +
+ Town/City + |
+ + + | +||||||||||||||
+ Current zoning + |
+ + + | +
+ Extent + |
+
+ m²/ ha + |
+
+ Are there existing buildings? + |
+
+ Y + |
+
+ N + |
+ |||||||||||
+ Current land use + |
+ + + | +||||||||||||||||
+ Title deed number and date + |
+
+ T + |
+ + + | +|||||||||||||||
+ Any restrictive conditions? + |
+
+ Y + |
+
+ N + |
+
+ If yes, list conditions + |
+ + + | +|||||||||||||
+ Is the property encumbered by a bond? + |
+
+ Y + |
+
+ N + |
+
+ If yes, list bondholder(s) + |
+ + + | +|||||||||||||
+ Part E: Pre-application consultation (regulation 11) + |
+ |||||||||||||||||
+ Has there been any pre-application consultation? + |
+
+ Y + |
+
+ N + |
+
+ If yes, complete the information below and attach the minutes of the pre-application consultation. + |
+ ||||||||||||||
+ Official’s name + |
+
+ Reference Number + |
+
+ Date of consultation + |
+
+ Address of Department +(To be completed by an official) + |
+ + + | +||||||||
+ Reference number +(To be completed by an official) + |
+ + + | +||||||||
+ Complete this form using BLOCK letters and ticking the appropriate boxes. + |
+ |||||||||
+ Note: +An appeal to the Provincial Minister must be submitted within 21 days of the date of notification of the decision. + |
+ |||||||||
+ Part A: Appeal + |
+ |||||||||
+ Are you appealing against the decision of the Head of Department? + |
+
+ Y + |
+
+ N + |
+ + + | +||||||
+ Are you appealing against a condition of approval imposed by the Head of Department? + |
+
+ Y + |
+
+ N + |
+
+ If yes, list condition(s) in Part F + |
+ ||||||
+ Are you are appealing because your rights have been affected by the failure of the Head of Department to decide on your application within the prescribed period? + |
+
+ Y + |
+
+ N + |
+ + + | +||||||
+ Date of decision + |
+
+ DD/MM/YYYY + |
+
+ Date of notification + |
+
+ DD/MM/YYYY + |
+ ||||||
+ Part B: Appellant's details + |
+ |||||||||
+ First name(s) + |
+ + + | +||||||||
+ Surname + |
+ + + | +||||||||
+ Company or legal person's name (If applicable) + |
+ + + | +||||||||
+ Physical address + |
+ + + | +||||||||
+ Postal address (If different from physical address) + |
+ + + | +
+ Postal code + |
+ + + | +||||||
+ |
+ + + | +||||||||
+ Tel. + |
+
+ Fax + |
+ + + | +
+ Cell. + |
+ + + | +
+ No. + |
+
+ Security plan + |
+
+ Check box + |
+ |
---|---|---|---|
+ 1. + |
+
+ The floor plan of the proposed site or area. + |
+
+ Yes + |
+
+ No + |
+
+ 2. + |
+
+ The access point (entry and exit). + |
+
+ Yes + |
+
+ No + |
+
+ 3. + |
+
+ The entry/ exit point to be manned at all times. + |
+
+ Yes + |
+
+ No + |
+
+ 4. + |
+
+ Patrons to be searched at point of arrival and departure. + |
+
+ Yes + |
+
+ No + |
+
+ 5. + |
+
+ Storage facilities for licensed firearms to be provided. + |
+
+ Yes + |
+
+ No + |
+
+ 6. + |
+
+ The point of sale to be cordoned off (indicated on the floor plan submitted). + |
+
+ Yes + |
+
+ No + |
+
+ 7. + |
+
+ The restricted part for consumption of liquor to be cordoned off (to be indicated on the floor plan submitted). + |
+
+ Yes + |
+
+ No + |
+
+ 8. + |
+
+ Parking to be provided. + |
+
+ Yes + |
+
+ No + |
+
+ 9. + |
+
+ Ablution facilities for males and females to be provided. + |
+
+ Yes + |
+
+ No + |
+
+ + | ++ + | +
+ 1. Details of licensed outlet or premises + |
+ |
---|---|
+ (a) Name of outlet: + |
+ |
+ (b) Trade name/s (if any): + |
+ |
+ (c) Registration number: + |
+ |
+ (d) Name of the metropolitan municipality/district municipality or local municipality where the licensed premises are situated: + |
+ |
+ (e) Physical business address of applicant: + |
+ |
+ 2. Personal details of the applicant + |
+ |
+ (a) Names and surname: + |
+ |
+ (b) Designation of applicant: + |
+ |
+ (c) Contact details: + |
+ |
+ Cell: __________________________ Tel: __________________________ Fax: __________________________ Email: _________________________________ + |
+ |
+ (Please attach certified copies of the documents requested in terms of regulation 25(3) to this form) +1. During the past 12 months, has the applicant, or any person holding an interest in the applicant, become disqualified from holding this liquor licence, as contemplated in section 40 of the Act? + |
+ |
+ Yes + |
+
+ No + |
+
+ 2. If the answer to the above question is in the affirmative, please provide details of any decision taken by the relevant provincial licensing authority in terms of section 40 of the Act + |
+ |
+ 3. Has the applicant or any of its owners, directors or subsidiaries been indicted or charged with any criminal offence, excluding traffic offences, during the past 12 months? + |
+ |
+ Yes + |
+
+ No + |
+
+ + | +|
+ 4. Has the applicant or any of its subsidiaries been a party to a law suit during the past 12 months? + |
+ |
+ If yes, provide details: __________________________ + |
+
+ Nature of ownership |
+
+ .The percentage of issued shares a person holds in the company - Directly.........%of shares |
+ |||||
+ The percentage of voting rights a person holds in the company |
+ ||||||
+ .A person holds a right to appoint or remove a majority of the members of the board of directors of the company : |
+ ||||||
+ A person exercises significant influence or control over the company. |
+ ||||||
+ .A person holds the highest percentage of the issued |
+ ||||||
+ Address of Department +(To be completed by an official) + |
+ + + | ++ + | +||||||
+ Reference number +(To be completed by an official) + |
+ + + | +|||||||
+ Complete this form by using BLOCK letters and by ticking the appropriate boxes. + |
+ ||||||||
+ Part A: Applications in terms of the Act + |
+ ||||||||
+ Land development +Section 53(2) of the Act and regulations 10(4) and 12) + |
+
+ Y + |
+
+ N + |
+
+ If yes, complete all parts, except part H, of this application form. + |
+ |||||
+ Amendment of land development approval +(Section 53(2) of the Act and regulations 10(5) and 12) + |
+
+ Y + |
+
+ N + |
+
+ If yes, complete all parts, except part H, of this application form. + |
+ |||||
+ Extension of validity period +(Section 57(2) of the Act and regulation 28) + |
+
+ Y + |
+
+ N + |
+
+ If yes, complete all parts, except part G, of this application form. + |
+ |||||
+ Part B: Applicant details + |
+ ||||||||
+ First name(s) + |
+ + + | +|||||||
+ Surname + |
+ + + | +|||||||
+ Company name (If applicable) + |
+ + + | +|||||||
+ Postal address + |
+ + + | +
+ Postal code + |
+ + + | +|||||
+ |
+ + + | +|||||||
+ Tel. + |
+
+ Fax + |
+ + + | +
+ Cell. + |
+ + + | +
+ Part C: Details of owner(s)(If different from applicant) + |
+ |||||||||||||||||
+ Full name(s) + |
+ + + | +||||||||||||||||
+ Physical address(es) + |
+ + + | ++ + | +|||||||||||||||
+ + | +
+ Postal code + |
+ + + | +|||||||||||||||
+ |
+ + + | +||||||||||||||||
+ Tel. + |
+ + + | +
+ Fax + |
+
+ Cell. + |
+ + + | +|||||||||||||
+ Part D: Property details (In accordance with title deed) + |
+ |||||||||||||||||
+ Property description (Number(s) of Erf/ Erven/Portion(s) or Farm(s)) + |
+ + + | +||||||||||||||||
+ Physical address + |
+ + + | +
+ Town/City + |
+ + + | +||||||||||||||
+ Current zoning + |
+ + + | +
+ Extent + |
+
+ m²/ ha + |
+
+ Are there existing buildings? + |
+
+ Y + |
+
+ N + |
+ |||||||||||
+ Current land use + |
+ + + | +||||||||||||||||
+ Title deed number and date + |
+
+ T + |
+ + + | +|||||||||||||||
+ Any restrictive conditions? + |
+
+ Y + |
+
+ N + |
+
+ If yes, list conditions + |
+ + + | +|||||||||||||
+ Is the property encumbered by a bond? + |
+
+ Y + |
+
+ N + |
+
+ If yes, list bondholder(s) + |
+ + + | +|||||||||||||
+ Part E: Pre-application consultation (regulation 11) + |
+ |||||||||||||||||
+ Has there been any pre-application consultation? + |
+
+ Y + |
+
+ N + |
+
+ If yes, complete the information below and attach the minutes of the pre-application consultation. + |
+ ||||||||||||||
+ Official’s name + |
+
+ Reference Number + |
+
+ Date of consultation + |
+
+ Address of Department +(To be completed by an official) + |
+ + + | +||||||||
+ Reference number +(To be completed by an official) + |
+ + + | +||||||||
+ Complete this form using BLOCK letters and ticking the appropriate boxes. + |
+ |||||||||
+ Note: +An appeal to the Provincial Minister must be submitted within 21 days of the date of notification of the decision. + |
+ |||||||||
+ Part A: Appeal + |
+ |||||||||
+ Are you appealing against the decision of the Head of Department? + |
+
+ Y + |
+
+ N + |
+ + + | +||||||
+ Are you appealing against a condition of approval imposed by the Head of Department? + |
+
+ Y + |
+
+ N + |
+
+ If yes, list condition(s) in Part F + |
+ ||||||
+ Are you are appealing because your rights have been affected by the failure of the Head of Department to decide on your application within the prescribed period? + |
+
+ Y + |
+
+ N + |
+ + + | +||||||
+ Date of decision + |
+
+ DD/MM/YYYY + |
+
+ Date of notification + |
+
+ DD/MM/YYYY + |
+ ||||||
+ Part B: Appellant's details + |
+ |||||||||
+ First name(s) + |
+ + + | +||||||||
+ Surname + |
+ + + | +||||||||
+ Company or legal person's name (If applicable) + |
+ + + | +||||||||
+ Physical address + |
+ + + | +||||||||
+ Postal address (If different from physical address) + |
+ + + | +
+ Postal code + |
+ + + | +||||||
+ |
+ + + | +||||||||
+ Tel. + |
+
+ Fax + |
+ + + | +
+ Cell. + |
+ + + | +
+ No. + |
+
+ Security plan + |
+
+ Check box + |
+ |
---|---|---|---|
+ 1. + |
+
+ The floor plan of the proposed site or area. + |
+
+ Yes + |
+
+ No + |
+
+ 2. + |
+
+ The access point (entry and exit). + |
+
+ Yes + |
+
+ No + |
+
+ 3. + |
+
+ The entry/ exit point to be manned at all times. + |
+
+ Yes + |
+
+ No + |
+
+ 4. + |
+
+ Patrons to be searched at point of arrival and departure. + |
+
+ Yes + |
+
+ No + |
+
+ 5. + |
+
+ Storage facilities for licensed firearms to be provided. + |
+
+ Yes + |
+
+ No + |
+
+ 6. + |
+
+ The point of sale to be cordoned off (indicated on the floor plan submitted). + |
+
+ Yes + |
+
+ No + |
+
+ 7. + |
+
+ The restricted part for consumption of liquor to be cordoned off (to be indicated on the floor plan submitted). + |
+
+ Yes + |
+
+ No + |
+
+ 8. + |
+
+ Parking to be provided. + |
+
+ Yes + |
+
+ No + |
+
+ 9. + |
+
+ Ablution facilities for males and females to be provided. + |
+
+ Yes + |
+
+ No + |
+
+ + | ++ + | +
+ 1. Details of licensed outlet or premises + |
+ |
---|---|
+ (a) Name of outlet: + |
+ |
+ (b) Trade name/s (if any): + |
+ |
+ (c) Registration number: + |
+ |
+ (d) Name of the metropolitan municipality/district municipality or local municipality where the licensed premises are situated: + |
+ |
+ (e) Physical business address of applicant: + |
+ |
+ 2. Personal details of the applicant + |
+ |
+ (a) Names and surname: + |
+ |
+ (b) Designation of applicant: + |
+ |
+ (c) Contact details: + |
+ |
+ Cell: __________________________ Tel: __________________________ Fax: __________________________ Email: _________________________________ + |
+ |
+ (Please attach certified copies of the documents requested in terms of regulation 25(3) to this form) +1. During the past 12 months, has the applicant, or any person holding an interest in the applicant, become disqualified from holding this liquor licence, as contemplated in section 40 of the Act? + |
+ |
+ Yes + |
+
+ No + |
+
+ 2. If the answer to the above question is in the affirmative, please provide details of any decision taken by the relevant provincial licensing authority in terms of section 40 of the Act + |
+ |
+ 3. Has the applicant or any of its owners, directors or subsidiaries been indicted or charged with any criminal offence, excluding traffic offences, during the past 12 months? + |
+ |
+ Yes + |
+
+ No + |
+
+ + | +|
+ 4. Has the applicant or any of its subsidiaries been a party to a law suit during the past 12 months? + |
+ |
+ If yes, provide details: __________________________ + |
+
+ Notice of intention to apply for a liquor licence for the undermentioned premises and proof of service +Name of premises +_____________________________________________________________ + |
+ ||||
+ Full name + |
+
+ Surname + |
+
+ I.D. Number + |
+
+ Full address + |
+
+ Signature + |
+
---|---|---|---|---|
+ + | ++ + | ++ + | ++ + | ++ + | +
+ + | +||||
+ + | +