From af10917aabd36b6836317041c4c953ed5ed66042 Mon Sep 17 00:00:00 2001 From: staticWagomU Date: Thu, 3 Jul 2025 23:09:56 +0900 Subject: [PATCH 1/9] =?UTF-8?q?chore(deps):=20csv=E3=82=92=E8=AA=AD?= =?UTF-8?q?=E3=81=BF=E8=BE=BC=E3=82=80=E3=81=9F=E3=82=81=E3=81=AE=E3=83=A9?= =?UTF-8?q?=E3=82=A4=E3=83=96=E3=83=A9=E3=83=AA=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2025/package.json | 1 + 2025/pnpm-lock.yaml | 71 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/2025/package.json b/2025/package.json index 483bee9..eb82032 100644 --- a/2025/package.json +++ b/2025/package.json @@ -33,6 +33,7 @@ "devDependencies": { "@antfu/ni": "^25.0.0", "@astrojs/ts-plugin": "^1.10.4", + "@rollup/plugin-dsv": "^3.0.5", "@ryoppippi/eslint-config": "npm:@jsr/ryoppippi__eslint-config@^0.0.25", "eslint": "^9.28.0", "eslint-plugin-astro": "^1.3.1", diff --git a/2025/pnpm-lock.yaml b/2025/pnpm-lock.yaml index 7902983..b05697f 100644 --- a/2025/pnpm-lock.yaml +++ b/2025/pnpm-lock.yaml @@ -54,6 +54,9 @@ importers: '@astrojs/ts-plugin': specifier: ^1.10.4 version: 1.10.4 + '@rollup/plugin-dsv': + specifier: ^3.0.5 + version: 3.0.5(rollup@4.42.0) '@ryoppippi/eslint-config': specifier: npm:@jsr/ryoppippi__eslint-config@^0.0.25 version: '@jsr/ryoppippi__eslint-config@0.0.25(@typescript-eslint/utils@8.24.0(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3))(@vue/compiler-sfc@3.5.13)(astro-eslint-parser@1.2.1)(eslint-plugin-astro@1.3.1(eslint@9.28.0(jiti@2.4.2)))(eslint-plugin-format@1.0.1(eslint@9.28.0(jiti@2.4.2)))(eslint@9.28.0(jiti@2.4.2))(prettier-plugin-astro@0.14.1)(typescript@5.8.3)' @@ -854,6 +857,14 @@ packages: '@rolldown/pluginutils@1.0.0-beta.9': resolution: {integrity: sha512-e9MeMtVWo186sgvFFJOPGy7/d2j2mZhLJIdVW0C/xDluuOvymEATqz6zKsP0ZmXGzQtqlyjz5sC1sYQUoJG98w==} + '@rollup/plugin-dsv@3.0.5': + resolution: {integrity: sha512-q1U4vu7voJkgeltujKya7ByxuWaHg9lYqCFQfWkqcgvIeOlUh52VrQSlgEe1JhN4wIaw5FOflRX3Jv0nqrw9uQ==} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + '@rollup/pluginutils@5.1.4': resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} engines: {node: '>=14.0.0'} @@ -1100,6 +1111,9 @@ packages: '@types/babel__traverse@7.20.7': resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==} + '@types/d3-dsv@3.0.7': + resolution: {integrity: sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==} + '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} @@ -1509,6 +1523,9 @@ packages: comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + comment-parser@1.4.1: resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} engines: {node: '>= 12.0.0'} @@ -1574,6 +1591,10 @@ packages: csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + d3-dsv@2.0.0: + resolution: {integrity: sha512-E+Pn8UJYx9mViuIUkoc93gJGGYut6mSDKy2+XaPwccwkRGlR+LO97L2VCCRjQivTwLHkSnAJG7yo00BWY6QM+w==} + hasBin: true + debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -2117,6 +2138,10 @@ packages: http-cache-semantics@4.2.0: resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -2977,9 +3002,15 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + rw@1.3.3: + resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} + s.color@0.0.15: resolution: {integrity: sha512-AUNrbEUHeKY8XsYr/DYpl+qk5+aM+DChopnWOPEzn8YKzOhv4l2zH6LzZms3tOZP3wwdOyc0RmTciyi46HLIuA==} + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + sass-formatter@0.7.9: resolution: {integrity: sha512-CWZ8XiSim+fJVG0cFLStwDvft1VI7uvXdCNJYXhDvowiv+DsbD1nXLiQ4zrE5UBvj5DWZJ93cwN0NX5PMsr1Pw==} @@ -3091,6 +3122,10 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} + strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} @@ -3153,6 +3188,10 @@ packages: resolution: {integrity: sha512-khrZo4buq4qVmsGzS5yQjKe/WsFvV8fGfOjDQN0q4iy9FjRfPWRgTFrU8u1R2iu/SfWLhY9WnCi4Jhdrcbtg+g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + tosource@2.0.0-alpha.3: + resolution: {integrity: sha512-KAB2lrSS48y91MzFPFuDg4hLbvDiyTjOVgaK7Erw+5AmZXNq4sFRVn8r6yxSLuNs15PaokrDRpS61ERY9uZOug==} + engines: {node: '>=10'} + tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} @@ -4414,6 +4453,16 @@ snapshots: '@rolldown/pluginutils@1.0.0-beta.9': {} + '@rollup/plugin-dsv@3.0.5(rollup@4.42.0)': + dependencies: + '@rollup/pluginutils': 5.1.4(rollup@4.42.0) + '@types/d3-dsv': 3.0.7 + d3-dsv: 2.0.0 + strip-bom: 4.0.0 + tosource: 2.0.0-alpha.3 + optionalDependencies: + rollup: 4.42.0 + '@rollup/pluginutils@5.1.4(rollup@4.42.0)': dependencies: '@types/estree': 1.0.8 @@ -4628,6 +4677,8 @@ snapshots: dependencies: '@babel/types': 7.27.6 + '@types/d3-dsv@3.0.7': {} + '@types/debug@4.1.12': dependencies: '@types/ms': 2.1.0 @@ -5194,6 +5245,8 @@ snapshots: comma-separated-tokens@2.0.3: {} + commander@2.20.3: {} + comment-parser@1.4.1: {} common-ancestor-path@1.0.1: {} @@ -5251,6 +5304,12 @@ snapshots: csstype@3.1.3: {} + d3-dsv@2.0.0: + dependencies: + commander: 2.20.3 + iconv-lite: 0.4.24 + rw: 1.3.3 + debug@3.2.7: dependencies: ms: 2.1.3 @@ -5932,6 +5991,10 @@ snapshots: http-cache-semantics@4.2.0: {} + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + ignore@5.3.2: {} import-fresh@3.3.1: @@ -6922,8 +6985,12 @@ snapshots: dependencies: queue-microtask: 1.2.3 + rw@1.3.3: {} + s.color@0.0.15: {} + safer-buffer@2.1.2: {} + sass-formatter@0.7.9: dependencies: suf-log: 2.5.3 @@ -7092,6 +7159,8 @@ snapshots: dependencies: ansi-regex: 6.1.0 + strip-bom@4.0.0: {} + strip-indent@3.0.0: dependencies: min-indent: 1.0.1 @@ -7151,6 +7220,8 @@ snapshots: dependencies: eslint-visitor-keys: 3.4.3 + tosource@2.0.0-alpha.3: {} + tr46@0.0.3: {} trim-lines@3.0.1: {} From 25a1ee4e24256a52db608b27bb1c30a9482e34c4 Mon Sep 17 00:00:00 2001 From: staticWagomU Date: Thu, 3 Jul 2025 23:10:17 +0900 Subject: [PATCH 2/9] =?UTF-8?q?chore(astro.config):=20dsv=E3=82=92?= =?UTF-8?q?=E7=99=BB=E9=8C=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2025/astro.config.mjs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/2025/astro.config.mjs b/2025/astro.config.mjs index cb9dd38..a6a1fd8 100644 --- a/2025/astro.config.mjs +++ b/2025/astro.config.mjs @@ -1,5 +1,6 @@ import react from '@astrojs/react'; import tailwindcss from '@tailwindcss/vite'; +import dsv from '@rollup/plugin-dsv'; // @ts-check import { defineConfig } from 'astro/config'; @@ -19,6 +20,7 @@ export default defineConfig({ plugins: [ Macros(), tailwindcss(), + dsv(), ], }, From c61efc86da23578c832836c8ace532c5237b41d5 Mon Sep 17 00:00:00 2001 From: staticWagomU Date: Thu, 3 Jul 2025 23:11:24 +0900 Subject: [PATCH 3/9] =?UTF-8?q?chore:=20csv=E3=81=AE=E3=82=B9=E3=82=AD?= =?UTF-8?q?=E3=83=BC=E3=83=9E=E3=82=92=E7=94=A8=E6=84=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2025/src/types/schema.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 2025/src/types/schema.ts diff --git a/2025/src/types/schema.ts b/2025/src/types/schema.ts new file mode 100644 index 0000000..1d0252f --- /dev/null +++ b/2025/src/types/schema.ts @@ -0,0 +1,12 @@ +import { z } from "astro:content"; + +const CsvRowSchema = z.object({ + order_number: z.string(), + name: z.string(), + comment: z.string(), + icon: z.string(), +}); + +const CsvSchema = z.array(CsvRowSchema); + +export { CsvSchema }; From dd573dbb1d8ed20286190a65ea20f3ba10f85bfe Mon Sep 17 00:00:00 2001 From: staticWagomU Date: Thu, 3 Jul 2025 23:11:36 +0900 Subject: [PATCH 4/9] =?UTF-8?q?chore:=20astro=20check=E3=81=A7=E8=90=BD?= =?UTF-8?q?=E3=81=A1=E3=82=8B=E3=81=9F=E3=82=81=E3=80=81d.ts=E3=82=92?= =?UTF-8?q?=E7=94=A8=E6=84=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2025/src/types/csv.d.ts | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 2025/src/types/csv.d.ts diff --git a/2025/src/types/csv.d.ts b/2025/src/types/csv.d.ts new file mode 100644 index 0000000..89ae0fe --- /dev/null +++ b/2025/src/types/csv.d.ts @@ -0,0 +1,4 @@ +declare module "*.csv" { + const value: Array<{ [key: string]: string }>; + export default value; +} From 879ab95d1f13ba0b4622860833a8a58f23ba1a66 Mon Sep 17 00:00:00 2001 From: staticWagomU Date: Fri, 4 Jul 2025 00:05:23 +0900 Subject: [PATCH 5/9] =?UTF-8?q?feat(=E5=80=8B=E4=BA=BA=E3=82=B9=E3=83=9D?= =?UTF-8?q?=E3=83=B3=E3=82=B5=E3=83=BC):=20=E3=82=B3=E3=83=B3=E3=83=9D?= =?UTF-8?q?=E3=83=BC=E3=83=8D=E3=83=B3=E3=83=88=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2025/src/components/Sponsors/Individual.astro | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 2025/src/components/Sponsors/Individual.astro diff --git a/2025/src/components/Sponsors/Individual.astro b/2025/src/components/Sponsors/Individual.astro new file mode 100644 index 0000000..81e5e3d --- /dev/null +++ b/2025/src/components/Sponsors/Individual.astro @@ -0,0 +1,46 @@ +--- +import Card from "../Card.astro"; + +type Props = { + name: string; + src: string; + comment: string; +}; + +const { name, src, comment } = Astro.props; + +let iconUrl = ""; +try { + const module = await import( + `../../assets/individual-sponsors/${src && src !== "" ? src : "no-icon"}.png?url` + ); + iconUrl = module.default; +} catch (e) { + console.error(`Icon not found: ${src}`); +} +--- + + +
+
+ {name} +
+
+ {name} + { + comment && comment !== "" && ( + + {comment} + + ) + } +
+
+
From 48aa44e767c890255f83f714134a0ebfdbcf3566 Mon Sep 17 00:00:00 2001 From: staticWagomU Date: Fri, 4 Jul 2025 00:06:06 +0900 Subject: [PATCH 6/9] =?UTF-8?q?feat(=E5=80=8B=E4=BA=BA=E3=82=B9=E3=83=9D?= =?UTF-8?q?=E3=83=B3=E3=82=B5=E3=83=BC):=20=E3=82=BB=E3=82=AF=E3=82=B7?= =?UTF-8?q?=E3=83=A7=E3=83=B3=E3=82=92=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/Sponsors/Individuals.astro | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 2025/src/components/Sponsors/Individuals.astro diff --git a/2025/src/components/Sponsors/Individuals.astro b/2025/src/components/Sponsors/Individuals.astro new file mode 100644 index 0000000..bdfc7bc --- /dev/null +++ b/2025/src/components/Sponsors/Individuals.astro @@ -0,0 +1,26 @@ +--- +import Individual from "./Individual.astro"; +import rawCsv from "../../data/individual_sponsors.csv"; +import { CsvSchema } from "../../types/schema"; + +const csv = CsvSchema.parse(rawCsv); +--- + +
+

+ 個人スポンサー +

+
+ { + csv + .sort((a, b) => Number(a.order_number) - Number(b.order_number)) + .map((row) => ( + + )) + } +
+
From 45ac4d590dd0718d335a0f209b9c3a7ae0550bab Mon Sep 17 00:00:00 2001 From: staticWagomU Date: Fri, 4 Jul 2025 00:06:28 +0900 Subject: [PATCH 7/9] =?UTF-8?q?feat(=E3=83=88=E3=83=83=E3=83=97):=20?= =?UTF-8?q?=E5=80=8B=E4=BA=BA=E3=82=B9=E3=83=9D=E3=83=B3=E3=82=B5=E3=83=BC?= =?UTF-8?q?=E3=82=BB=E3=82=AF=E3=82=B7=E3=83=A7=E3=83=B3=E3=82=92=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2025/src/components/Sponsors/index.astro | 2 ++ 1 file changed, 2 insertions(+) diff --git a/2025/src/components/Sponsors/index.astro b/2025/src/components/Sponsors/index.astro index d14dcba..fdaa089 100644 --- a/2025/src/components/Sponsors/index.astro +++ b/2025/src/components/Sponsors/index.astro @@ -1,5 +1,6 @@ --- import Card from "../Card.astro"; +import Individuals from "./Individuals.astro"; import Heading from "../Heading.astro"; import { Heart, @@ -102,4 +103,5 @@ import { + From 49a8a1f257878b4398bae8019560647a39d4cdb7 Mon Sep 17 00:00:00 2001 From: staticWagomU Date: Fri, 4 Jul 2025 00:06:54 +0900 Subject: [PATCH 8/9] =?UTF-8?q?fix:=20=E4=B8=8D=E8=A6=81=E3=81=AA=E3=82=B3?= =?UTF-8?q?=E3=83=B3=E3=83=9D=E3=83=BC=E3=83=8D=E3=83=B3=E3=83=88=E3=81=AE?= =?UTF-8?q?=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2025/src/components/Sponsors/individual.astro | 115 ------------------ 1 file changed, 115 deletions(-) delete mode 100644 2025/src/components/Sponsors/individual.astro diff --git a/2025/src/components/Sponsors/individual.astro b/2025/src/components/Sponsors/individual.astro deleted file mode 100644 index b75fb10..0000000 --- a/2025/src/components/Sponsors/individual.astro +++ /dev/null @@ -1,115 +0,0 @@ -
-

- 個人スポンサー -

-
-
-
-
- 田中一郎 -
- 田中一郎 -
-
-
- John Doe -
- John Doe -
-
-
- 鈴木花子 -
- 鈴木花子 -
-
-
- Jane Smith -
- Jane Smith -
-
-
- 佐藤健太 -
- 佐藤健太 -
-
-
- Alex Johnson -
- Alex Johnson -
-
-
- 山田太郎 -
- 山田太郎 -
-
-
- Emily Brown -
- Emily Brown -
-
-
- 伊藤直子 -
- 伊藤直子 -
-
-
- Michael Wilson -
- Michael Wilson -
-
-
- 高橋誠 -
- 高橋誠 -
-
-
- Sarah Davis -
- Sarah Davis -
-
-
-
From d04d8fed52717d9b6fda236962b6274c771a85e4 Mon Sep 17 00:00:00 2001 From: staticWagomU Date: Fri, 4 Jul 2025 00:07:11 +0900 Subject: [PATCH 9/9] =?UTF-8?q?feat(=E5=80=8B=E4=BA=BA=E3=82=B9=E3=83=9D?= =?UTF-8?q?=E3=83=B3=E3=82=B5=E3=83=BC):=20=E5=80=8B=E4=BA=BA=E3=82=B9?= =?UTF-8?q?=E3=83=9D=E3=83=B3=E3=82=B5=E3=83=BC=E3=81=AE=E5=8B=9F=E9=9B=86?= =?UTF-8?q?=E3=83=90=E3=83=8A=E3=83=BC=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/Sponsors/Individuals.astro | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/2025/src/components/Sponsors/Individuals.astro b/2025/src/components/Sponsors/Individuals.astro index bdfc7bc..e3e5fa3 100644 --- a/2025/src/components/Sponsors/Individuals.astro +++ b/2025/src/components/Sponsors/Individuals.astro @@ -1,7 +1,9 @@ --- +import Card from "../Card.astro"; import Individual from "./Individual.astro"; import rawCsv from "../../data/individual_sponsors.csv"; import { CsvSchema } from "../../types/schema"; +import { ExternalLink, Heart } from "@lucide/astro"; const csv = CsvSchema.parse(rawCsv); --- @@ -23,4 +25,25 @@ const csv = CsvSchema.parse(rawCsv); )) } + + +

個人スポンサーになりませんか?

+

+ VimConf 2025 Smallの成功を一緒に作り上げましょう! +

+ + + + + +