<h1 class="heading-deco terciary">EBSI News</h1>
<p>Welcome to the central hub for all things EBSI! Here you can find all EBSI-related news and learn more about how to get involved with this exciting project. With this page, we aim to empower citizens, businesses and officials by fostering a better understanding of EBSI’s potential.</p>
<p>You can discover our vision for a more connected and digital Europe, as we explore various topics related to Web3 and the decentralisation of public services.</p>
<p>Dive deeper into the world of EBSI today by reading all about EBSI's transformative potential for the public sector!</p>

<h2 class="heading-deco terciary">The latest News</h2>
<p>Browse the news page and find the latest EBSI related stories and information.</p>
<div class="loader"><img src="https://ec.europa.eu/digital-building-blocks/sites/download/attachments/465732214/loader-low.gif" alt=""/></div>
<div id="latest-article">
<ul class="content-by-label-ii"></ul>
</div>
<div class="rest-av-articles">

<div class="load-wrapper"><a class="loadmore-cta btn secondary outline"><span><strong>Load more</strong></span></a></div>
</div>



<img src="https://ec.europa.eu/digital-building-blocks/sites/download/attachments/609583364/dual-pill-primary-node-operators.svg" alt="">

Subscribe to our Newsflash

<p>Receive the latest news, invitations to our webinars and remain updated about the European Blockchain Services Infrastructure.</p>
<p><a class="btn secondary" href="https://ec.europa.eu/newsroom/digital/user-subscriptions/3156/create" target="_blank"><span>Sign up</span><span class="ico-external"></span><span class="sr-only">(opens in a new tab)</span></a></p>
@media screen and ( max-width: 550px ) {
#latest-article { margin-top: 20px!important; }
.home-newsflash .home-newsflash-bg { bottom: -28px!important; left: -87%!important; width: 270%!important; }
.bg-top-curve { background-position: 6%!important; background-size: cover!important; }
}
@media screen and ( max-width: 742px ) {
.content-by-label { gap: 40px!important; }
.content-by-label li { width: 100%!important; max-width: 100%!important; }
}
@media screen and ( max-width: 768px ) {
#latest-article .article-publication { padding: 20px 16px 24px; }
#latest-article .article-publication time { font-size: 16px; color: #4A3D5D; }
#latest-article .labels-container { padding: 0 0 20px; border-bottom: 1px solid #E8E7EB; margin-left: 16px; margin-right: 16px; margin-bottom: 20px; }
#latest-article .ext-article-heading { padding: 0 16px 20px; }
#latest-article .card-content-footer { display: flex; justify-content: flex-end; padding: 0 16px 40px; }
#latest-article .card-content-footer p { margin-bottom: 0; }
.content-by-label .ext-article-heading { flex-grow: 1; padding: 20px 16px; }
.content-by-label .article-publication { padding: 0 16px; margin-bottom: 20px; }
.content-by-label .card-content-footer { display: flex; justify-content: flex-end; padding: 0 16px 40px; }
.content-by-label .labels-container { border-bottom: 1px solid #E8E7EB; margin: 0 16px; padding: 0 0 20px; }
.ext-article-heading h4 { font-size: 20px!important; line-height: 22px!important; }  
}

@media screen and ( min-width: 769px ) {
#latest-article .article-publication { padding: 20px 40px 24px; }
#latest-article .article-publication time { font-size: 16px; color: #4A3D5D; }
#latest-article .labels-container { padding: 0 0 20px; border-bottom: 1px solid #E8E7EB; margin-left: 40px; margin-right: 40px; margin-bottom: 20px; }
#latest-article .ext-article-heading { padding: 0 40px 20px; }
#latest-article .ext-article-heading h3 { font-size: 32px; }
#latest-article .card-content-footer { display: flex; justify-content: flex-end; padding: 0 40px 40px; }
#latest-article .card-content-footer p { margin-bottom: 0; }
.content-by-label .ext-article-heading { flex-grow: 1; padding: 20px; }
.content-by-label .article-publication { padding: 0 20px; margin-bottom: 20px; }
.content-by-label .card-content-footer { display: flex; justify-content: flex-end; padding: 0 20px 40px; }
.content-by-label .labels-container { border-bottom: 1px solid #E8E7EB; margin: 0 20px; padding: 0 0 20px; }
.home-newsflash .home-newsflash-bg { left:-30%!important; width: 100%!important;}
.home-newsflash .btn { margin-bottom: 3rem;} 
}

@media screen and (min-width: 1360px) { 
.home-newsflash .home-newsflash-bg { left:-30%!important; width: 90%!important; }
}



#main-content .container { max-width: 1227px!important; }
.articles-main-section { margin-top: 28px; }
.load-wrapper { display: flex; justify-content: center; align-items: center; margin-top: 40px;  position: relative; z-index: 5; }
.load-wrapper .loadmore-cta { background: white!important; cursor: pointer; }
.loader { position: relative; height: 500px; }
.loader > img { position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%); }
.bg-top-curve {
background-image: url("https://ec.europa.eu/digital-building-blocks/sites/download/attachments/501089469/bg-curve_grants-top.svg");
background-position:right top;
background-repeat: no-repeat;
background-size: contain;
}
.content-by-label .label-details, .content-by-label li > div:first-child, .content-by-label li .details > a  { display: none; }
.content-by-label-ii .label-details, .content-by-label-ii li > div:first-child, .content-by-label-ii li .details > a  { display: none; }
.content-by-label-ii time, .content-by-label time { color: #4A3D5D; }
/*--- HOME NEWSFLASH ---*/ 
.home-newsflash { padding-top: 5rem; padding-bottom:0; margin-top: 5rem; }
.home-newsflash .container { position: relative;}
.home-newsflash .cols { z-index: 5; position: relative;}
.home-newsflash .col-5 { max-width: 472px; }
.home-newsflash .home-newsflash-bg { display: block; z-index: 4; position:absolute; bottom: 0; left:-100%; width: 200%;}
.home-newsflash .home-newsflash-bg p { margin:0; line-height:0;}
.home-newsflash .home-newsflash-bg p img { margin:0; max-width: 100%; height: auto;}
.home-newsflash .btn { margin-bottom: 2rem;} 
/* -------------- */
.labels-container { display: flex; gap: 8px; flex-wrap: wrap; }
.labels-container > div { border: 1px solid #D2CFD6; padding: 4px 8px 4px 8px; border-radius: 4px; font-size: 14px; }
.labels-container > div a { text-decoration: none!important; color: #4A3D5D!important; }
.labels-container > div a:hover { text-decoration: underline!important; } 
.content-by-label .label-details { display: none; }
.category-header { display: flex; gap: 32px; align-items: center; }
.category-header > div { display: flex; justify-content: center; align-items: center; width: 40px; height: 40px; min-width: 40px; max-width: 40px; min-height: 40px; max-height: 40px; border-radius: 50%; background: #00B3EF; }
.category-header > h1 { margin-bottom: 0; }
/* CARDS */
.content-by-label .label-details, .content-by-label li > div:first-child, .content-by-label li .details > a  { display: none; }
.labels-container { display: flex; gap: 8px; flex-wrap: wrap; }
.labels-container > div { border: 1px solid #D2CFD6; padding: 4px 8px 4px 8px; border-radius: 4px; font-size: 14px; }
.labels-container > div a { text-decoration: none!important; color: #4A3D5D!important; }
.labels-container > div a:hover { text-decoration: underline!important; }
.article-publication { display: flex; justify-content: space-between; align-items: center; }
.article-publication p { margin: 0; }
.article-publication > div:first-child { display: flex; align-items: center; order: 2; }
.article-publication > div:first-child .date-upcoming { padding: 0; margin: 0; background: transparent; }
.article-publication > div:first-child .date-upcoming:before { width: 0; }
/* card-design */
.smalltext > p:first-child, .smalltext > p:last-child { display: none; }
.content-by-label li .details { padding: 0; height: 100%; }
.content-by-label .article-wrapper { height: 100%; display: flex; flex-direction: column; }
.content-by-label .article-preview { max-height: 200px; margin-bottom: 21px; }
.content-by-label .article-preview > img { width: 100%; max-height: 200px; height: 200px;}
.content-by-label .article-publication p { color: #4A3D5D; }
.content-by-label .card-content-footer > p { margin-bottom: 0; }
.content-by-label { display: flex; flex-wrap: wrap; gap: 24px; }
.content-by-label li { margin: 0; background: #FFF; box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.10); border-radius: 16px; max-width: 392px; min-width: 327px; width: 48%; z-index: 5; }  
#latest-article { margin: 40px 0 80px; }
#latest-article > ul, .content-by-label-ii { padding: 0; list-style: none; }
#latest-article > ul > li { border-radius: 16px; box-shadow: 0px 4px 20px 0px rgba(0, 55, 100, 0.10); }
#latest-article .smalltext { margin-bottom: 0; padding: 0; }
#latest-article .article-wrapper { display: flex; flex-direction: column; height: 100%; }
#latest-article .article-wrapper p { color: #4A3D5D; }
#latest-article .article-preview { max-height: 480px; overflow: hidden; display: flex; }
#latest-article .article-preview > img { width: 100%; border-top-right-radius: 16px; border-top-left-radius: 16px; object-fit: cover; }
<script>      


$(".smalltext")
  .contents()
  .filter(function () {
    return this.nodeType === 3
  })
  .remove()

const loaderSection = document.querySelector(".loader")
const articleLatestSection = document.querySelector("#latest-article")
const articlesRestSection = document.querySelector(".rest-av-articles")
articleLatestSection.style.display = "none"
articlesRestSection.style.display = "none"

const allCards = (container, ARTICLE_LABEL) => {
  try {
    for (const article of container) {
      const labelHolders = article.querySelectorAll(".aui-label > a")
      const labelList = Array.from(labelHolders)
      const labelsContainer = article.querySelector(".labels-container")
      const labelNames = isArticleValid(ARTICLE_LABEL, labelList)
      setLabels(labelsContainer, labelNames)
      const articleLabels = labelsContainer.getAttribute("data-labels")
      article.setAttribute("article-tags", articleLabels)
    }
  } catch (error) {
    console.error("An error occurred:", error)
  }
}

const isArticleValid = (ARTICLE_LABEL, labelList) => {
  const labelNames = labelList.map((label) => label.textContent.trim())
  const found = labelNames.some((label) => label === ARTICLE_LABEL)
  if (found) {
    const index = labelNames.indexOf(ARTICLE_LABEL)
    if (index !== -1) {
      labelNames.splice(index, 1)
    }
  }
  return labelNames
}

const setLabels = (labelsContainer, labelNames) => {
  labelsContainer.setAttribute("data-labels", labelNames.join(","))
  for (const val of labelNames) {
	if ( val !== 'news') {
    const div = document.createElement("div")
    const anchor = document.createElement("a")
    anchor.setAttribute(
      "href",
      `https://ec.europa.eu/digital-building-blocks/sites/display/EBSI/articles?category=${val}`
    )
    anchor.textContent = constructLabel(val)
    div.appendChild(anchor)
    labelsContainer.appendChild(div)
	}
  }
}

const constructLabel = (val) => {
  let result = null

  const storage = [
    { ede: "EDE" },
    { contextbroker: "Context Broker" },
    { bdti: "BDTI" },
    { success_stories: "Success Stories" },
    { earchiving: "eArchiving" },
    { einvoicing: "eInvoicing" },
    { etranslation: "eTranslation" },
    { esignature: "eSignature" },
    { edelivery: "eDelivery" },
    { eid: "eID" },
    { ssi: "SSI (Self-Sovereign Identity)" },
    { degov: "DeGov" },
    { did: "DID" },
    { w3c: "W3C" },
    { dlt: "DLT" },
    { cef: "CEF" },
    { apis: "APIs" },
    { "early-adopters-programme": "Early Adopters programme" },
    { ebsi: "EBSI" },
	{ "smart-contracts": "Smart Contracts" },
	{ "ebip": "EBIP" },
    { "esspass": "ESSPASS"},
    { "xp-center": 'EBSI Experience Center' },
    { "edic": "EDIC"},
	{ "europeum-edic": "EUROPEUM-EDIC"},
	{ "open-source": "Open Source" }
  ]

  storage.find(function (obj) {
    const [key, value] = Object.entries(obj)[0]
    if (key === val) {
      result = value
      return true
    }
  })
  if (result === null) {
    result = val
      .replace(/-/g, " ")
      .replace(/\b\w/g, (match) => match.toUpperCase())
  }

  return result
}

const addHTMLlink = (container) => {
  container.forEach((card) => {
    const anchorLink = card.querySelector(".details > a").getAttribute("href")
    const articleWrapper = card.querySelector(".article-wrapper")
    const div = document.createElement("div")
    div.classList.add("card-content-footer")
    const p = document.createElement("p")
    const anchor = document.createElement("a")
    anchor.classList.add("link-cta", "text-secondary")
    anchor.setAttribute("aria-label", "Read the article")
    anchor.setAttribute("href", anchorLink)
    const span = document.createElement("span")
    span.textContent = "Read the article"
    anchor.appendChild(span)
    p.appendChild(anchor)
    div.appendChild(p)
    articleWrapper
      ? articleWrapper.appendChild(div)
      : console.log("Article's pool not found")
  })
}

const seperateNewest = (cardArticles, latestArticleContainer) => {
  const allArticles = Array.from(cardArticles)
  const newestArticle = cardArticles[0]

  const newestArticleData2 = newestArticle.cloneNode(true)

  const newestArticleData = {
    title: newestArticle.querySelector(".ext-article-heading").cloneNode(true),
    publication: newestArticle
      .querySelector(".article-publication")
      .cloneNode(true),
    img: newestArticle
      .querySelector(".article-preview > img")
      .getAttribute("src"),
  }

  const restArticles = []

  for (let i = 0; i < cardArticles.length; i++) {
    //i === 0 ? latestArticleContainer.appendChild(cardArticles[i]) : restArticles.push(cardArticles[i])
    i === 0
      ? appendData(latestArticleContainer, cardArticles[i], newestArticleData2)
      : restArticles.push(cardArticles[i])
  }
  const restructuredNewestArticle = document.querySelector(
    ".content-by-label-ii > li"
  )
  return { restructuredNewestArticle, restArticles, allArticles }
}

const appendData = (
  latestArticleContainer,
  firstArticle,
  newestArticleData2
) => {
  latestArticleContainer.appendChild(newestArticleData2)
  firstArticle.remove()
}

const cardArticleModifier = (cardArticles) => {
  for (const article of cardArticles) {
    const h4 = document.createElement("h3")
    const strong = document.createElement("strong")
    const anchor = article.querySelector(".ext-article-heading > a")
    strong.textContent = constructLabel(anchor.textContent)
    h4.appendChild(strong)
    anchor.parentNode.replaceChild(h4, anchor)
  }
}

const pagination = (cardArticles) => {
  const loadCTA = document.querySelector(".loadmore-cta")

  const cardsLimit = 8
  const showOnLoad = () => {
    cardArticles.forEach((article, index) => {
      index > cardsLimit
        ? (article.style.display = "none")
        : (article.style.display = "block")
      index > cardsLimit
        ? (loadCTA.style.display = "flex")
        : (loadCTA.style.display = "none")
    })
  }

  showOnLoad()
}

const loadNextArticles = () => {
  const loadCTA = document.querySelector(".loadmore-cta")
  const hiddenCards = Array.from(
    document.querySelectorAll(".content-by-label > li")
  ).filter(function (liElement) {
    return window.getComputedStyle(liElement).display === "none"
  })
  if (hiddenCards.length <= 6) {
    loadCTA.style.display = "none"
    hiddenCards.forEach((article) => {
      article.style.display = "block"
    })
  } else {
    const nextArray = hiddenCards.slice(0, 6)
    nextArray.forEach((article) => {
      article.style.display = "block"
    })
  }
}

const articleIds = (cardArticles) => {
  const result = []
  for (const article of cardArticles) {
    const id = article.querySelector(".article-publication").getAttribute("id")
    result.push(id)
  }
  return result
}

document.addEventListener("DOMContentLoaded", function () {
  const ARTICLE_LABEL = "newsv2"
  const latestArticleContainer = document.querySelector(
    "#latest-article > .content-by-label-ii"
  )
  const cardArticles = document.querySelectorAll(".content-by-label > li")
  allCards(cardArticles, ARTICLE_LABEL)
  const partition = seperateNewest(cardArticles, latestArticleContainer)

  cardArticleModifier([partition.restructuredNewestArticle])
  cardArticleModifier(partition.restArticles)

  addHTMLlink([partition.restructuredNewestArticle])
  addHTMLlink(partition.restArticles)
  const loadCTA = document.querySelector(".loadmore-cta")
  loadCTA.addEventListener("click", loadNextArticles)
  pagination(partition.restArticles)
  const IDs = articleIds(cardArticles)
  for (const id of IDs) {
    readingTime(id)
  }
})

//---------

async function readingTime(id) {
  try {
    const response = await fetch(
      `https://ec.europa.eu/digital-building-blocks/sites/rest/api/content/${id}?expand=body.view`
    )
    const data = await response.json()
    const pageContent = data.body.view.value
    const parser = new DOMParser()
    const htmlDoc = parser.parseFromString(pageContent, "text/html")
    const allText = htmlDoc.body.innerText
    const allWords = allText.split(/\s+/).filter((word) => word.trim() !== "")
    const numWords = allWords.length - 50
    const cardArticle = document.getElementById(id)
    cardArticle.querySelector(
      ".reading-time > span"
    ).textContent = `${Math.ceil(numWords / 200)}`
    loaderSection.style.display = "none"
    articleLatestSection.style.display = "block"
    articlesRestSection.style.display = "block"
  } catch (error) {
    console.log(error)
  }
}




</script>