diff --git a/handson/just-news/extensions/app.js b/handson/just-news/extensions/app.js
new file mode 100644
index 0000000..e4f04eb
--- /dev/null
+++ b/handson/just-news/extensions/app.js
@@ -0,0 +1,114 @@
+const optOutQueryKey = 'just_news'
+
+function optOutUrl() {
+ let query = window.location.search
+ if (query) {
+ query += `&${optOutQueryKey}=false`
+ } else {
+ query = `?${optOutQueryKey}=false`
+ }
+ return window.location.origin + window.location.pathname + query
+}
+
+function reconstruct(articleInfo, adSelectors) {
+ const root = document.createElement('html')
+ document.replaceChild(root, document.documentElement)
+ root.innerHTML = [
+ '
',
+ '',
+ '',
+ `${articleInfo.title}`,
+ '',
+ '',
+ '',
+ '',
+ '',
+ ].join('')
+
+ const style = document.createElement('style')
+ style.innerHTML = `@import url('https://fonts.googleapis.com/css?family=Nanum+Gothic|Nanum+Myeongjo&display=swap');
+ body {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin-top: 10px;
+ margin-bottom: 60vh;
+ text-align: center;
+ font-family: 'Nanum Myeongjo', serif;
+ }
+ article {
+ width: 640px;
+ text-align: justify;
+ }
+ .time-stemp {
+ color: #888;
+ font-size: 10pt;
+ text-align: left;
+ }
+ `
+ document.body.append(style)
+
+ const article = root.querySelector('article')
+
+ article.append(articleInfo.content)
+
+ for (const adSelector of adSelectors) {
+ const element = article.querySelector(adSelector)
+ if (element === null) {
+ continue
+ }
+ element.remove()
+ }
+ article.insertAdjacentHTML(
+ 'afterbegin',
+ `작성자: ${articleInfo.repoter}
`
+ )
+ article.insertAdjacentHTML(
+ 'afterbegin',
+ `작성일: ${articleInfo.timeStemp}
`
+ )
+ article.insertAdjacentHTML('afterbegin', `${articleInfo.title}
`)
+ article.insertAdjacentHTML(
+ 'afterbegin',
+ `원본 페이지 보기`
+ )
+}
+
+const sites = {
+ 'mediahub.seoul.go.kr': {
+ title: '#main > h1',
+ timeStemp: '.date',
+ repoter: '.user',
+ content: '.pf-content',
+ },
+ 'www.bloter.net': {
+ title: '.headline',
+ timeStemp: '.publish',
+ repoter: '.author--name',
+ content: '.article--content',
+ },
+}
+
+const sitesAd = {
+ 'mediahub.seoul.go.kr': [],
+ 'www.bloter.net': [
+ '.article--content-ad__container',
+ '.denim-shortcode--title',
+ '.bloter-plus--article',
+ '.related-post--article',
+ '.goog-te-banner',
+ '#goog-gt-tt',
+ ],
+}
+
+const site = sites[location.hostname]
+const adSelectors = sitesAd[location.hostname]
+
+const articleInfo = {
+ title: document.querySelector(site.title).innerText,
+ timeStemp: document.querySelector(site.timeStemp).innerText,
+ repoter: document.querySelector(site.repoter).innerText,
+ content: document.querySelector(site.content).cloneNode(true),
+}
+
+reconstruct(articleInfo, adSelectors)
diff --git a/handson/just-news/extensions/icon.png b/handson/just-news/extensions/icon.png
new file mode 100644
index 0000000..84ef3dc
Binary files /dev/null and b/handson/just-news/extensions/icon.png differ
diff --git a/handson/just-news/extensions/manifest.json b/handson/just-news/extensions/manifest.json
new file mode 100644
index 0000000..c55400f
--- /dev/null
+++ b/handson/just-news/extensions/manifest.json
@@ -0,0 +1,19 @@
+{
+ "name": "just-news",
+ "version": "1.0",
+ "description": "뉴스 기사의 본문을 정돈해서 보여줍니다.",
+ "manifest_version": 2,
+ "icons": {
+ "128": "icon.png"
+ },
+ "content_scripts": [
+ {
+ "matches": [
+ "http://mediahub.seoul.go.kr/archives/*",
+ "*://www.bloter.net/archives/*"
+ ],
+ "js": ["app.js"],
+ "run-at": "document_idle"
+ }
+ ]
+}