diff --git a/libs/portals/admin/regulations-admin/src/utils/formatAmendingRegulation.ts b/libs/portals/admin/regulations-admin/src/utils/formatAmendingRegulation.ts index ac3fca2aef41..884527fd26c2 100644 --- a/libs/portals/admin/regulations-admin/src/utils/formatAmendingRegulation.ts +++ b/libs/portals/admin/regulations-admin/src/utils/formatAmendingRegulation.ts @@ -5,7 +5,14 @@ import is from 'date-fns/locale/is' import compact from 'lodash/compact' import flatten from 'lodash/flatten' import uniq from 'lodash/uniq' -import { groupElementsByArticleTitleFromDiv } from './groupByArticleTitle' +import { + allSameDay, + extractArticleTitleDisplay, + getTextWithSpaces, + groupElementsByArticleTitleFromDiv, + isGildisTaka, + removeRegPrefix, +} from './formatAmendingUtils' import { getDeletionOrAddition } from './getDeletionOrAddition' // ---------------------------------------------------------------------- @@ -13,24 +20,12 @@ const PREFIX = 'Reglugerð um ' const PREFIX_AMENDING = 'breytingu á reglugerð nr. ' const PREFIX_REPEALING = 'brottfellingu á reglugerð nr. ' -const removeRegPrefix = (title: string) => { - if (/^Reglugerð/.test(title)) { - return title.replace(/^Reglugerð/, '') - } - return title -} - -const isGildisTaka = (str: string) => { - return /(öðlast|tekur).*gildi|sett.*með.*(?:heimild|stoð)/.test( - (str || '').toLowerCase(), - ) -} - const formatAffectedAndPlaceAffectedAtEnd = ( groups: { formattedRegBody: HTMLText[] date?: Date | undefined }[], + hideAffected?: boolean, ) => { function formatArray(arr: string[]): string { if (arr.length === 1) { @@ -115,7 +110,10 @@ const formatAffectedAndPlaceAffectedAtEnd = ( }) const uniqueGildistaka = uniq(gildsTakaKeepArray) - const joinedAffected = updatedImpactAffectArray.join('. ') + let joinedAffected = updatedImpactAffectArray.join('. ') + if (hideAffected) { + joinedAffected = '' + } const gildistakaReturn = flatten([...uniqueGildistaka, joinedAffected]).join( '', ) as HTMLText @@ -178,11 +176,11 @@ export const formatAmendingRegBody = ( ) => { const regName = removeRegNamePrefix(name) if (repeal) { - const title = regTitle ? regTitle.replace(/^reglugerð\s*/i, '') + ' ' : '' + const title = regTitle ? regTitle.replace(/^reglugerð\s*/i, '').trim() : '' const text = `

Reglugerð nr. ${regName} ${title.replace( /\.$/, '', - )}fellur brott.

` as HTMLText + )} fellur brott.

` as HTMLText const gildistaka = `

Reglugerð þessi er sett með heimild í [].

Reglugerðin öðlast þegar gildi.

` as HTMLText return [text, gildistaka] @@ -232,18 +230,8 @@ export const formatAmendingRegBody = ( if (element.classList.contains('article__title')) { const clone = element.cloneNode(true) - if (clone instanceof Element) { - const emElement = clone.querySelector('em') - if (emElement) { - emElement.parentNode?.removeChild(emElement) - } - - const textContent = clone.textContent?.trim() ?? '' - - articleTitle = textContent - } else { - articleTitle = element.innerText - } + const textContent = getTextWithSpaces(clone) + articleTitle = extractArticleTitleDisplay(textContent) testGroup.title = articleTitle isArticleTitle = true paragraph = 0 // Reset paragraph count for the new article @@ -385,10 +373,8 @@ export const formatAmendingRegBody = ( if (testGroup.isDeletion === true) { const articleTitleNumber = testGroup.title - const grMatch = articleTitleNumber.match(/^\d+\. gr\./) - const articleTitleDisplay = grMatch ? grMatch[0] : articleTitleNumber additionArray.push([ - `

${articleTitleDisplay} ${regNameDisplay} fellur brott.

` as HTMLText, + `

${articleTitleNumber} ${regNameDisplay} fellur brott.

` as HTMLText, ]) } else if (testGroup.isAddition === true) { let prevArticleTitle = '' @@ -401,7 +387,8 @@ export const formatAmendingRegBody = ( ? flatten(testGroup.original) : [] - const prevArticleTitleNumber = prevArticleTitle.match(/^\d+\. gr\./) + const prevArticleTitleNumber = + extractArticleTitleDisplay(prevArticleTitle) let articleDisplayText = '' @@ -449,7 +436,11 @@ export const formatAmendingBodyWithArticlePrefix = ( const additions = flatten(impactAdditionArray) - const htmlForEditor = formatAffectedAndPlaceAffectedAtEnd(additions) + const hideAffected = allSameDay(additions) + const htmlForEditor = formatAffectedAndPlaceAffectedAtEnd( + additions, + hideAffected, + ) const returnArray = compact(htmlForEditor) diff --git a/libs/portals/admin/regulations-admin/src/utils/formatAmendingUtils.ts b/libs/portals/admin/regulations-admin/src/utils/formatAmendingUtils.ts new file mode 100644 index 000000000000..007246a3332a --- /dev/null +++ b/libs/portals/admin/regulations-admin/src/utils/formatAmendingUtils.ts @@ -0,0 +1,89 @@ +import isSameDay from 'date-fns/isSameDay' +import { HTMLText } from '@island.is/regulations' + +export const groupElementsByArticleTitleFromDiv = ( + div: HTMLDivElement, +): HTMLElement[][] => { + const result: HTMLElement[][] = [] + let currentGroup: HTMLElement[] = [] + + Array.from(div.children).forEach((child) => { + const element = child as HTMLElement + if ( + element.classList.contains('article__title') || + element.classList.contains('chapter__title') + ) { + if (currentGroup.length > 0) { + result.push(currentGroup) + } + currentGroup = [element] + } else { + currentGroup.push(element) + } + }) + + if (currentGroup.length > 0) { + result.push(currentGroup) + } + + return result +} + +/** + * Extracts article title number (e.g., '1. gr.' or '1. gr. a') from a string, allowing for Icelandic characters. + */ +export const extractArticleTitleDisplay = (title: string): string => { + const grMatch = title.match(/^\d+\. gr\.(?: [\p{L}])?(?= |$)/u) + const articleTitleDisplay = grMatch ? grMatch[0] : title + return articleTitleDisplay +} + +export const getTextWithSpaces = (element: Node): string => { + let result = '' + + element.childNodes.forEach((node, index) => { + if (node.nodeType === Node.TEXT_NODE) { + result += (node.textContent?.trim() || '') + ' ' + } else if (node.nodeType === Node.ELEMENT_NODE) { + result += getTextWithSpaces(node as HTMLElement) + + // If the current element is not the last node and the next node is also an element or text node, + // add a space between elements + if ( + element.childNodes[index + 1] && + element.childNodes[index + 1].nodeType !== Node.COMMENT_NODE + ) { + result += ' ' + } + } + }) + + return result.trim() // Trim any excess space +} + +export const removeRegPrefix = (title: string) => { + if (/^Reglugerð/.test(title)) { + return title.replace(/^Reglugerð/, '') + } + return title +} + +export const isGildisTaka = (str: string) => { + return /(öðlast|tekur).*gildi|sett.*með.*(?:heimild|stoð)/.test( + (str || '').toLowerCase(), + ) +} + +export type AdditionObject = { + formattedRegBody: HTMLText[] + date: Date | undefined +} + +export const allSameDay = (objects: AdditionObject[]): boolean => { + const validObjects = objects.filter((obj) => obj.date !== undefined) + + if (validObjects.length === 0) return true + const firstDate = validObjects[0].date! + + return validObjects.every((obj) => isSameDay(obj.date!, firstDate)) +} diff --git a/libs/portals/admin/regulations-admin/src/utils/groupByArticleTitle.ts b/libs/portals/admin/regulations-admin/src/utils/groupByArticleTitle.ts deleted file mode 100644 index 96e064372852..000000000000 --- a/libs/portals/admin/regulations-admin/src/utils/groupByArticleTitle.ts +++ /dev/null @@ -1,24 +0,0 @@ -export const groupElementsByArticleTitleFromDiv = ( - div: HTMLDivElement, -): HTMLElement[][] => { - const result: HTMLElement[][] = [] - let currentGroup: HTMLElement[] = [] - - Array.from(div.children).forEach((child) => { - const element = child as HTMLElement - if (element.classList.contains('article__title')) { - if (currentGroup.length > 0) { - result.push(currentGroup) - } - currentGroup = [element] - } else { - currentGroup.push(element) - } - }) - - if (currentGroup.length > 0) { - result.push(currentGroup) - } - - return result -}