@studyportals/fawkes 5.0.0 → 5.0.1-3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/README.md +158 -0
  2. package/dist/programmes-seo/index.d.ts +6 -0
  3. package/dist/programmes-seo/index.js +2 -0
  4. package/dist/scholarships-seo/index.d.ts +2 -1
  5. package/dist/sitemap-generator-seo/index.d.ts +2 -1
  6. package/dist/src/common/IDocumentationManager.d.ts +5 -0
  7. package/dist/src/common/IPresenter.d.ts +2 -2
  8. package/dist/src/common/IRule.d.ts +1 -0
  9. package/dist/src/common/ISearchIndexabilityManager.d.ts +2 -1
  10. package/dist/src/common/ISeoIndexabilityPolicy.d.ts +4 -0
  11. package/dist/src/common/ISitemapUrlGenerator.d.ts +2 -0
  12. package/dist/src/common/policies/BaseSeoIndexabilityPolicy.d.ts +6 -1
  13. package/dist/src/common/policies/BaseSeoIndexabilityPolicy.js +9 -0
  14. package/dist/src/common/rules/BaseFilterKeyValueRule.d.ts +1 -0
  15. package/dist/src/common/rules/NoFiltersSelectedRule.d.ts +1 -0
  16. package/dist/src/common/rules/NoFiltersSelectedRule.js +3 -0
  17. package/dist/src/common/rules/OnlineAttendanceRule.d.ts +6 -0
  18. package/dist/src/common/rules/OnlineAttendanceRule.js +14 -0
  19. package/dist/src/common/rules/OnlyFiltersSelectedRule.d.ts +1 -0
  20. package/dist/src/common/rules/OnlyFiltersSelectedRule.js +3 -0
  21. package/dist/src/common/rules/SingleValueSelectedForFilterRule.d.ts +1 -0
  22. package/dist/src/common/rules/SingleValueSelectedForFilterRule.js +3 -0
  23. package/dist/src/enums/FilterCombinations.d.ts +20 -0
  24. package/dist/src/enums/FilterCombinations.js +20 -0
  25. package/dist/src/organisations/OrganisationsRuleBasedIndexabilityPolicy.d.ts +11 -0
  26. package/dist/src/organisations/OrganisationsRuleBasedIndexabilityPolicy.js +19 -0
  27. package/dist/src/organisations/SearchIndexabilityManager.d.ts +1 -0
  28. package/dist/src/organisations/SearchIndexabilityManager.js +3 -0
  29. package/dist/src/organisations/policies/OrganisationsSeoIndexabilityPolicy.d.ts +0 -1
  30. package/dist/src/organisations/policies/OrganisationsSeoIndexabilityPolicy.js +0 -3
  31. package/dist/src/organisations/policies/RankedOrganisationsSeoIndexabilityPolicy.d.ts +2 -0
  32. package/dist/src/organisations/policies/RankedOrganisationsSeoIndexabilityPolicy.js +2 -0
  33. package/dist/src/organisations/policies/our-picks/Area.d.ts +2 -0
  34. package/dist/src/organisations/policies/our-picks/Area.js +2 -0
  35. package/dist/src/organisations/policies/our-picks/AreaAttendance.d.ts +4 -2
  36. package/dist/src/organisations/policies/our-picks/AreaAttendance.js +3 -1
  37. package/dist/src/organisations/policies/our-picks/Attendance.d.ts +3 -1
  38. package/dist/src/organisations/policies/our-picks/Attendance.js +3 -1
  39. package/dist/src/organisations/policies/our-picks/Continent.d.ts +2 -0
  40. package/dist/src/organisations/policies/our-picks/Continent.js +2 -0
  41. package/dist/src/organisations/policies/our-picks/Country.d.ts +2 -0
  42. package/dist/src/organisations/policies/our-picks/Country.js +2 -0
  43. package/dist/src/organisations/policies/our-picks/CountryAttendance.d.ts +3 -1
  44. package/dist/src/organisations/policies/our-picks/CountryAttendance.js +3 -1
  45. package/dist/src/organisations/policies/our-picks/Unfiltered.d.ts +2 -0
  46. package/dist/src/organisations/policies/our-picks/Unfiltered.js +2 -0
  47. package/dist/src/organisations/policies/ranked/RankedArea.d.ts +2 -0
  48. package/dist/src/organisations/policies/ranked/RankedArea.js +2 -0
  49. package/dist/src/organisations/policies/ranked/RankedAreaDiscipline.d.ts +2 -0
  50. package/dist/src/organisations/policies/ranked/RankedAreaDiscipline.js +2 -0
  51. package/dist/src/organisations/policies/ranked/RankedAttendance.d.ts +3 -1
  52. package/dist/src/organisations/policies/ranked/RankedAttendance.js +3 -1
  53. package/dist/src/organisations/policies/ranked/RankedAttendanceDiscipline.d.ts +3 -1
  54. package/dist/src/organisations/policies/ranked/RankedAttendanceDiscipline.js +3 -1
  55. package/dist/src/organisations/policies/ranked/RankedContinent.d.ts +2 -0
  56. package/dist/src/organisations/policies/ranked/RankedContinent.js +2 -0
  57. package/dist/src/organisations/policies/ranked/RankedContinentAttendance.d.ts +3 -1
  58. package/dist/src/organisations/policies/ranked/RankedContinentAttendance.js +3 -1
  59. package/dist/src/organisations/policies/ranked/RankedCountry.d.ts +2 -0
  60. package/dist/src/organisations/policies/ranked/RankedCountry.js +2 -0
  61. package/dist/src/organisations/policies/ranked/RankedCountryAttendance.d.ts +3 -1
  62. package/dist/src/organisations/policies/ranked/RankedCountryAttendance.js +3 -1
  63. package/dist/src/organisations/policies/ranked/RankedCountryDiscipline.d.ts +2 -0
  64. package/dist/src/organisations/policies/ranked/RankedCountryDiscipline.js +2 -0
  65. package/dist/src/organisations/policies/ranked/RankedDiscipline.d.ts +2 -0
  66. package/dist/src/organisations/policies/ranked/RankedDiscipline.js +2 -0
  67. package/dist/src/organisations/policies/ranked/RankedUnfiltered.d.ts +2 -0
  68. package/dist/src/organisations/policies/ranked/RankedUnfiltered.js +2 -0
  69. package/dist/src/organisations/rules/AtLeastTwoRankedResultsRule.d.ts +1 -0
  70. package/dist/src/organisations/rules/AtLeastTwoRankedResultsRule.js +3 -0
  71. package/dist/src/organisations/rules/BaseSearchVolumeOrganisationsRule.d.ts +1 -0
  72. package/dist/src/organisations/rules/BaseSearchVolumeOrganisationsRule.js +3 -0
  73. package/dist/src/organisations/rules/ContinentIsEuropeRule.d.ts +1 -0
  74. package/dist/src/organisations/rules/ContinentIsEuropeRule.js +3 -0
  75. package/dist/src/organisations/rules/NoFiltersSelectedRule.d.ts +9 -0
  76. package/dist/src/organisations/rules/NoFiltersSelectedRule.js +17 -0
  77. package/dist/src/organisations/rules/OnlineAttendanceRule.d.ts +1 -0
  78. package/dist/src/organisations/rules/OnlineAttendanceRule.js +3 -0
  79. package/dist/src/organisations/rules/SearchVolumeAreasAttendanceRule.d.ts +1 -0
  80. package/dist/src/organisations/rules/SearchVolumeAreasAttendanceRule.js +3 -0
  81. package/dist/src/organisations/rules/SearchVolumeAreasDisciplineRule.d.ts +1 -0
  82. package/dist/src/organisations/rules/SearchVolumeAreasDisciplineRule.js +3 -0
  83. package/dist/src/organisations/rules/SearchVolumeCountriesAttendanceRule.d.ts +1 -0
  84. package/dist/src/organisations/rules/SearchVolumeCountriesAttendanceRule.js +3 -0
  85. package/dist/src/programmes/IProgrammeSearchApplicationState.d.ts +4 -0
  86. package/dist/src/programmes/IProgrammeSearchApplicationState.js +1 -0
  87. package/dist/src/programmes/IProgrammeSearchDependencies.d.ts +7 -0
  88. package/dist/src/programmes/IProgrammeSearchDependencies.js +1 -0
  89. package/dist/src/programmes/IProgrammesSeoDependencies.d.ts +2 -0
  90. package/dist/src/programmes/IProgrammesSeoDependencies.js +1 -0
  91. package/dist/src/programmes/ProgrammesBaseIndexabilityPolicy.d.ts +7 -0
  92. package/dist/src/programmes/ProgrammesBaseIndexabilityPolicy.js +10 -0
  93. package/dist/src/programmes/SearchIndexabilityManager.d.ts +12 -0
  94. package/dist/src/programmes/SearchIndexabilityManager.js +53 -0
  95. package/dist/src/programmes/policies/Area.d.ts +9 -0
  96. package/dist/src/programmes/policies/Area.js +21 -0
  97. package/dist/src/programmes/policies/Attendance.d.ts +9 -0
  98. package/dist/src/programmes/policies/Attendance.js +22 -0
  99. package/dist/src/programmes/policies/AttendanceDegree.d.ts +9 -0
  100. package/dist/src/programmes/policies/AttendanceDegree.js +25 -0
  101. package/dist/src/programmes/policies/Continent.d.ts +9 -0
  102. package/dist/src/programmes/policies/Continent.js +20 -0
  103. package/dist/src/programmes/policies/ContinentTuitionFee.d.ts +9 -0
  104. package/dist/src/programmes/policies/ContinentTuitionFee.js +23 -0
  105. package/dist/src/programmes/policies/Country.d.ts +9 -0
  106. package/dist/src/programmes/policies/Country.js +20 -0
  107. package/dist/src/programmes/policies/CountryAttendance.d.ts +9 -0
  108. package/dist/src/programmes/policies/CountryAttendance.js +23 -0
  109. package/dist/src/programmes/policies/CountryAttendanceDegree.d.ts +9 -0
  110. package/dist/src/programmes/policies/CountryAttendanceDegree.js +27 -0
  111. package/dist/src/programmes/policies/CountryDegree.d.ts +9 -0
  112. package/dist/src/programmes/policies/CountryDegree.js +23 -0
  113. package/dist/src/programmes/policies/CountryDuration.d.ts +9 -0
  114. package/dist/src/programmes/policies/CountryDuration.js +23 -0
  115. package/dist/src/programmes/policies/CountryDurationDegree.d.ts +9 -0
  116. package/dist/src/programmes/policies/CountryDurationDegree.js +27 -0
  117. package/dist/src/programmes/policies/CountryEducationalForm.d.ts +9 -0
  118. package/dist/src/programmes/policies/CountryEducationalForm.js +24 -0
  119. package/dist/src/programmes/policies/CountryFormat.d.ts +9 -0
  120. package/dist/src/programmes/policies/CountryFormat.js +23 -0
  121. package/dist/src/programmes/policies/CountryTuitionFee.d.ts +9 -0
  122. package/dist/src/programmes/policies/CountryTuitionFee.js +23 -0
  123. package/dist/src/programmes/policies/Discipline.d.ts +9 -0
  124. package/dist/src/programmes/policies/Discipline.js +20 -0
  125. package/dist/src/programmes/policies/DisciplineArea.d.ts +9 -0
  126. package/dist/src/programmes/policies/DisciplineArea.js +22 -0
  127. package/dist/src/programmes/policies/DisciplineAttendance.d.ts +9 -0
  128. package/dist/src/programmes/policies/DisciplineAttendance.js +23 -0
  129. package/dist/src/programmes/policies/DisciplineContinent.d.ts +9 -0
  130. package/dist/src/programmes/policies/DisciplineContinent.js +21 -0
  131. package/dist/src/programmes/policies/DisciplineCountry.d.ts +9 -0
  132. package/dist/src/programmes/policies/DisciplineCountry.js +21 -0
  133. package/dist/src/programmes/policies/DisciplineCountryDegree.d.ts +9 -0
  134. package/dist/src/programmes/policies/DisciplineCountryDegree.js +25 -0
  135. package/dist/src/programmes/policies/DisciplineCountryEducationalForm.d.ts +9 -0
  136. package/dist/src/programmes/policies/DisciplineCountryEducationalForm.js +25 -0
  137. package/dist/src/programmes/policies/DisciplineDegree.d.ts +9 -0
  138. package/dist/src/programmes/policies/DisciplineDegree.js +23 -0
  139. package/dist/src/programmes/policies/DisciplineDuration.d.ts +9 -0
  140. package/dist/src/programmes/policies/DisciplineDuration.js +23 -0
  141. package/dist/src/programmes/policies/DisciplineEducationalForm.d.ts +9 -0
  142. package/dist/src/programmes/policies/DisciplineEducationalForm.js +24 -0
  143. package/dist/src/programmes/policies/DisciplineFormat.d.ts +9 -0
  144. package/dist/src/programmes/policies/DisciplineFormat.js +23 -0
  145. package/dist/src/programmes/policies/DisciplineTuitionFee.d.ts +9 -0
  146. package/dist/src/programmes/policies/DisciplineTuitionFee.js +23 -0
  147. package/dist/src/programmes/policies/DisciplineTuitionFeeAttendance.d.ts +9 -0
  148. package/dist/src/programmes/policies/DisciplineTuitionFeeAttendance.js +26 -0
  149. package/dist/src/programmes/policies/SpecialProgrammes.d.ts +9 -0
  150. package/dist/src/programmes/policies/SpecialProgrammes.js +22 -0
  151. package/dist/src/programmes/policies/TuitionFee.d.ts +9 -0
  152. package/dist/src/programmes/policies/TuitionFee.js +20 -0
  153. package/dist/src/programmes/policies/Unfiltered.d.ts +9 -0
  154. package/dist/src/programmes/policies/Unfiltered.js +14 -0
  155. package/dist/src/programmes/policies/index.d.ts +30 -0
  156. package/dist/src/programmes/policies/index.js +30 -0
  157. package/dist/src/programmes/rules/AffordableTuitionFeeRule.d.ts +8 -0
  158. package/dist/src/programmes/rules/AffordableTuitionFeeRule.js +21 -0
  159. package/dist/src/programmes/rules/AtLeastSevenResultsRule.d.ts +8 -0
  160. package/dist/src/programmes/rules/AtLeastSevenResultsRule.js +16 -0
  161. package/dist/src/programmes/rules/ErasmusOrJointSpecialProgrammesRule.d.ts +8 -0
  162. package/dist/src/programmes/rules/ErasmusOrJointSpecialProgrammesRule.js +22 -0
  163. package/dist/src/programmes/rules/IndexableDegreeRule.d.ts +9 -0
  164. package/dist/src/programmes/rules/IndexableDegreeRule.js +47 -0
  165. package/dist/src/programmes/rules/IndexableDurationRule.d.ts +9 -0
  166. package/dist/src/programmes/rules/IndexableDurationRule.js +28 -0
  167. package/dist/src/programmes/rules/IndexableEducationalFormRule.d.ts +9 -0
  168. package/dist/src/programmes/rules/IndexableEducationalFormRule.js +28 -0
  169. package/dist/src/programmes/rules/IndexablePageNumberRule.d.ts +8 -0
  170. package/dist/src/programmes/rules/IndexablePageNumberRule.js +16 -0
  171. package/dist/src/programmes/rules/MbaDegreeRule.d.ts +8 -0
  172. package/dist/src/programmes/rules/MbaDegreeRule.js +21 -0
  173. package/dist/src/programmes/rules/MbaOrMscDegreeRule.d.ts +8 -0
  174. package/dist/src/programmes/rules/MbaOrMscDegreeRule.js +21 -0
  175. package/dist/src/programmes/rules/NotDistanceLearningPortalRule.d.ts +8 -0
  176. package/dist/src/programmes/rules/NotDistanceLearningPortalRule.js +17 -0
  177. package/dist/src/programmes/rules/OneYearDurationRule.d.ts +8 -0
  178. package/dist/src/programmes/rules/OneYearDurationRule.js +21 -0
  179. package/dist/src/programmes/rules/OnlineAttendanceRule.d.ts +6 -0
  180. package/dist/src/programmes/rules/OnlineAttendanceRule.js +14 -0
  181. package/dist/src/programmes/rules/PartTimeFormatRule.d.ts +8 -0
  182. package/dist/src/programmes/rules/PartTimeFormatRule.js +21 -0
  183. package/dist/src/scholarships/SearchIndexabilityManager.d.ts +2 -0
  184. package/dist/src/scholarships/SearchIndexabilityManager.js +3 -0
  185. package/dist/src/scholarships/policies/Area.d.ts +2 -0
  186. package/dist/src/scholarships/policies/Area.js +2 -0
  187. package/dist/src/scholarships/policies/Country.d.ts +2 -0
  188. package/dist/src/scholarships/policies/Country.js +2 -0
  189. package/dist/src/scholarships/policies/Discipline.d.ts +2 -0
  190. package/dist/src/scholarships/policies/Discipline.js +2 -0
  191. package/dist/src/scholarships/policies/DisciplineCountry.d.ts +2 -0
  192. package/dist/src/scholarships/policies/DisciplineCountry.js +2 -0
  193. package/dist/src/scholarships/policies/Unfiltered.d.ts +2 -0
  194. package/dist/src/scholarships/policies/Unfiltered.js +2 -0
  195. package/dist/src/scholarships/policies/UniversityCountry.d.ts +2 -0
  196. package/dist/src/scholarships/policies/UniversityCountry.js +2 -0
  197. package/dist/src/scholarships/rules/ExceptAustaliaAreasRule.d.ts +1 -0
  198. package/dist/src/scholarships/rules/ExceptAustaliaAreasRule.js +3 -0
  199. package/dist/src/scholarships/rules/SearchVolumeAreasRule.d.ts +1 -0
  200. package/dist/src/scholarships/rules/SearchVolumeAreasRule.js +3 -0
  201. package/dist/src/scholarships/rules/SearchVolumeCountriesDisciplinesRule.d.ts +1 -0
  202. package/dist/src/scholarships/rules/SearchVolumeCountriesDisciplinesRule.js +3 -0
  203. package/dist/src/scholarships/rules/SearchVolumeCountriesRule.d.ts +1 -0
  204. package/dist/src/scholarships/rules/SearchVolumeCountriesRule.js +3 -0
  205. package/dist/src/scholarships/rules/SearchVolumeDisciplinesRule.d.ts +1 -0
  206. package/dist/src/scholarships/rules/SearchVolumeDisciplinesRule.js +3 -0
  207. package/dist/src/sitemap-generator/BaseSitemapUrlGeneratorManager.d.ts +1 -0
  208. package/dist/src/sitemap-generator/BaseSitemapUrlGeneratorManager.js +3 -0
  209. package/dist/src/sitemap-generator/ISitemapUrlGeneratorManager.d.ts +2 -1
  210. package/package.json +13 -2
  211. package/dist/src/common/IRankingApiClient.d.ts +0 -3
  212. package/dist/src/sitemap-generator/SitemapUrlGeneratorManager.d.ts +0 -9
  213. package/dist/src/sitemap-generator/SitemapUrlGeneratorManager.js +0 -34
  214. /package/dist/src/common/{IRankingApiClient.js → IDocumentationManager.js} +0 -0
package/README.md CHANGED
@@ -16,3 +16,161 @@ Link to documentation: https://studyportals.atlassian.net/wiki/x/BwAdvw
16
16
  - organisations
17
17
  - scholarships
18
18
  - sitemap-generator
19
+
20
+ # Automatic Documentation System
21
+
22
+ ## Overview
23
+
24
+ This system automatically generates and maintains documentation for Fawkes
25
+ indexing rules across multiple projects. It creates a hierarchical structure of
26
+ Confluence pages that document all indexing policies and rules, ensuring that
27
+ the documentation is always up-to-date with the actual codebase.
28
+
29
+ Link to documentation:
30
+ [Fawkes Indexing Rules Documentation](https://studyportals.atlassian.net/wiki/spaces/T/pages/3494969354/Fawkes+Indexing+Rules+Documentation)
31
+
32
+ ## Features
33
+
34
+ - **Dynamic Documentation**: Automatically extracts indexing rules and policies
35
+ directly from the codebase
36
+ - **Multi-Page Structure**: Creates a main index page with separate pages for
37
+ each project
38
+ - **Hierarchical Organization**: Structures content as Projects → Policies →
39
+ Rules
40
+ - **Automatic Page Creation**: Intelligently creates or updates pages as needed
41
+ - **Cross-Page Navigation**: Provides intuitive navigation between all pages
42
+
43
+ ## Architecture
44
+
45
+ The system follows SOLID design principles to ensure maintainability and
46
+ extensibility:
47
+
48
+ - **Single Responsibility**: Each class has one specific responsibility
49
+ - **Open/Closed**: Easily extendable without modifying existing code
50
+ - **Liskov Substitution**: Interchangeable components through well-defined
51
+ interfaces
52
+ - **Interface Segregation**: Clean, focused interfaces
53
+ - **Dependency Inversion**: High-level modules depend on abstractions
54
+
55
+ ### Key Components
56
+
57
+ 1. **Content Builder**: Extracts project, policy, and rule data from the Fawkes
58
+ system
59
+ 2. **Policy Fetchers**: Project-specific components that fetch and format policy
60
+ data
61
+ 3. **Document Builder**: Generates structured HTML content for Confluence pages
62
+ 4. **Confluence Updater**: Handles creation and updating of Confluence pages
63
+ 5. **Token Retriever**: Securely retrieves API token for Confluence access
64
+
65
+ ## How It Works
66
+
67
+ 1. The system starts by collecting all project data using the `ContentBuilder`
68
+ 2. For each project, it extracts policies and rules using project-specific
69
+ fetchers
70
+ 3. The `DocumentBuilder` generates the content for the main index page and each
71
+ project page
72
+ 4. The `ConfluenceUpdater` creates or updates pages in Confluence as needed
73
+ 5. Each project page links back to the main index, and the main index links to
74
+ all project pages
75
+
76
+ ## Setup and Configuration
77
+
78
+ ### Environment Variables
79
+
80
+ The system requires the following environment variables:
81
+
82
+ ```
83
+ CONFLUENCE_EMAIL=your-email@example.com
84
+ CONFLUENCE_API_TOKEN=your-api-token
85
+ CONFLUENCE_BASE_URL=https://your-instance.atlassian.net
86
+ CONFLUENCE_SPACE_KEY=YOUR_SPACE_KEY
87
+ CONFLUENCE_MAIN_PAGE_TITLE=Fawkes Indexing Rules Documentation
88
+ ```
89
+
90
+ > **Important Note on Credentials**: Currently, the system uses personal
91
+ > credentials (email and API token) for Confluence access. This is a temporary
92
+ > solution and should be replaced with a team or service account in the future
93
+ > to avoid dependency on a specific individual's account.
94
+
95
+ ### Deployment and Triggering
96
+
97
+ The system runs as an AWS Lambda function and is automatically triggered as part
98
+ of the CI/CD pipeline. This ensures documentation is always updated whenever new
99
+ code is deployed:
100
+
101
+ ```yaml
102
+ # buildspec.yml (excerpt)
103
+ post_build:
104
+ commands:
105
+ - |
106
+ if [ -z "$PR_ID" ]; then
107
+ LAMBDA_NAME="FawkesConfluenceUpdater-$STAGE"
108
+ echo "Invoking Lambda function $LAMBDA_NAME"
109
+ echo '{"source":"cicd-pipeline","timestamp":"'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'"}' > payload.json
110
+ aws lambda invoke --function-name $LAMBDA_NAME --invocation-type Event --payload fileb://payload.json response.json || echo "Lambda invocation failed, but continuing"
111
+ fi
112
+ ```
113
+
114
+ **Trigger Flow:**
115
+
116
+ 1. When code is pushed to the `main` branch, the CI/CD pipeline is triggered
117
+ 2. After successful deployment of a new Fawkes version, the post-build phase
118
+ executes
119
+ 3. The Lambda function is invoked with a simple payload containing the source
120
+ and timestamp
121
+ 4. The Lambda function authenticates with Confluence and executes the
122
+ documentation generation process
123
+ 5. This only happens for production deployments (not PR builds)
124
+
125
+ This automated approach ensures documentation stays in sync with the actual
126
+ codebase without manual intervention.
127
+
128
+ ## Scalability and Extension
129
+
130
+ ### Adding New Projects
131
+
132
+ To add documentation for a new project:
133
+
134
+ 1. Create a new class that implements the `IPolicyFetcher` interface
135
+ 2. Implement the `getProjectName()` and `fetchPolicies()` methods
136
+ 3. Register the new fetcher in the `ContentBuilder` constructor
137
+
138
+ Example:
139
+
140
+ ```typescript
141
+ export class NewProjectPolicyFetcher implements IPolicyFetcher {
142
+ getProjectName(): string {
143
+ return 'New Project Name';
144
+ }
145
+
146
+ fetchPolicies(): IPolicy[] {
147
+ // Implement policy fetching logic
148
+ return [...policies];
149
+ }
150
+ }
151
+
152
+ // Then update ContentBuilder:
153
+ constructor(fetchers?: IPolicyFetcher[]) {
154
+ this.policyFetchers = fetchers || [
155
+ // Existing fetchers
156
+ new NewProjectPolicyFetcher()
157
+ ];
158
+ }
159
+ ```
160
+
161
+ ### Customizing Page Content
162
+
163
+ The `DocumentBuilder` class contains methods for generating page content. To
164
+ customize the format:
165
+
166
+ 1. Modify the `buildMainDocument()` method for changes to the main index page
167
+ 2. Modify the `buildProjectDocument()` method for changes to project pages
168
+ 3. Modify the `buildPolicySection()` and `buildRulesTable()` methods for changes
169
+ to policy and rule sections
170
+
171
+ ## Conclusion
172
+
173
+ This documentation system ensures that Fawkes indexing rules are always
174
+ well-documented and accessible to the team. By automatically generating
175
+ documentation directly from the codebase, it eliminates the risk of
176
+ documentation becoming outdated or inconsistent with the actual implementation.
@@ -0,0 +1,6 @@
1
+ import { ISeoFilterState } from '../src/common/ISeoFilterState';
2
+ import { ISeoInfoBase } from '../src/common/ISeoInfoBase';
3
+ import { IProgrammeSearchApplicationState } from '../src/programmes/IProgrammeSearchApplicationState';
4
+ import { ISearchIndexabilityManager } from '../src/common/ISearchIndexabilityManager';
5
+ import { SearchIndexabilityManager } from '../src/programmes/SearchIndexabilityManager';
6
+ export { ISeoFilterState, ISeoInfoBase, ISearchIndexabilityManager, IProgrammeSearchApplicationState, SearchIndexabilityManager };
@@ -0,0 +1,2 @@
1
+ import { SearchIndexabilityManager } from '../src/programmes/SearchIndexabilityManager';
2
+ export { SearchIndexabilityManager };
@@ -1,4 +1,5 @@
1
+ import { ISeoIndexabilityPolicy } from '../src/common/ISeoIndexabilityPolicy';
1
2
  import { ISeoFilterState, ISearchApplicationState, ISearchIndexabilityManager, ISeoInfoBase } from '../src/common';
2
3
  import { SearchIndexabilityManager } from '../src/scholarships/SearchIndexabilityManager';
3
4
  import { types } from '../src/scholarships/types';
4
- export { ISeoFilterState, ISearchApplicationState, ISearchIndexabilityManager, ISeoInfoBase, SearchIndexabilityManager, types };
5
+ export { ISeoFilterState, ISeoIndexabilityPolicy, ISearchApplicationState, ISearchIndexabilityManager, ISeoInfoBase, SearchIndexabilityManager, types };
@@ -6,6 +6,7 @@ import { ISitemapUrlGeneratorManager } from '../src/sitemap-generator/ISitemapUr
6
6
  import { OrganisationsSitemapUrlGeneratorManager } from '../src/sitemap-generator/OrganisationsSitemapUrlGeneratorManager';
7
7
  import { ScholarshipsSitemapUrlGeneratorManager } from '../src/sitemap-generator/ScholarshipsSitemapUrlGeneratorManager';
8
8
  import { FilterCombinations } from '../src/enums/FilterCombinations';
9
+ import { ISitemapUrlGenerator } from '../src/common/ISitemapUrlGenerator';
9
10
  import { FilterKeyValuesMap } from '../src/common/FilterKeyValuesMap';
10
11
  import { IPresenter } from '../src/common';
11
- export { IOrganisationsClient, IOrganisation, IRankingApiClient, ISearchApiClient, ISitemapUrlGeneratorManager, OrganisationsSitemapUrlGeneratorManager, ScholarshipsSitemapUrlGeneratorManager, FilterCombinations, FilterKeyValuesMap, IPresenter };
12
+ export { IOrganisationsClient, IOrganisation, IRankingApiClient, ISearchApiClient, ISitemapUrlGeneratorManager, OrganisationsSitemapUrlGeneratorManager, ScholarshipsSitemapUrlGeneratorManager, FilterCombinations, ISitemapUrlGenerator, FilterKeyValuesMap, IPresenter };
@@ -0,0 +1,5 @@
1
+ import { ISeoIndexabilityPolicy } from './ISeoIndexabilityPolicy';
2
+ import { ISitemapUrlGenerator } from './ISitemapUrlGenerator';
3
+ export interface IDocumentationManager {
4
+ getPolicies(): ISitemapUrlGenerator[] | ISeoIndexabilityPolicy[];
5
+ }
@@ -1,5 +1,5 @@
1
- import { IFragment } from "../presenters/fragments/IFragment";
2
- import { FilterKey } from "@studyportals/search-filters";
1
+ import { IFragment } from '../presenters/fragments/IFragment';
2
+ import { FilterKey } from '@studyportals/search-filters';
3
3
  export interface IPresenter {
4
4
  readonly filterKey: FilterKey;
5
5
  getFragments(): IFragment[];
@@ -4,4 +4,5 @@ export interface IRule {
4
4
  getName(): string;
5
5
  forSearch(dependencies: ISearchDependencies): Promise<boolean>;
6
6
  forSitemapGenerator(filterKeyValues: FilterKeyValuesMap): Promise<boolean>;
7
+ getDescription(): string;
7
8
  }
@@ -1,3 +1,4 @@
1
- export interface ISearchIndexabilityManager {
1
+ import { IDocumentationManager } from './IDocumentationManager';
2
+ export interface ISearchIndexabilityManager extends IDocumentationManager {
2
3
  shouldIndex(): Promise<boolean>;
3
4
  }
@@ -1,3 +1,7 @@
1
+ import { IRule } from './IRule';
1
2
  export interface ISeoIndexabilityPolicy {
2
3
  shouldIndex(): Promise<boolean>;
4
+ getAllRules(): IRule[];
5
+ getName(): string;
6
+ getDescription(): string;
3
7
  }
@@ -1,5 +1,7 @@
1
1
  import { FilterCombinations } from '../enums/FilterCombinations';
2
+ import { IRule } from './IRule';
2
3
  export interface ISitemapUrlGenerator {
3
4
  filterCombination: FilterCombinations;
4
5
  generateSitemapUrls(): Promise<string[]>;
6
+ getAllRules(): IRule[];
5
7
  }
@@ -4,8 +4,10 @@ import { IRule } from '../IRule';
4
4
  import { FilterKeyValuesMap } from '../FilterKeyValuesMap';
5
5
  import { ISeoIndexabilityPolicy } from '../ISeoIndexabilityPolicy';
6
6
  import { ISitemapUrlGenerator } from '../ISitemapUrlGenerator';
7
- import { FilterCombinations } from '../../../sitemap-generator-seo';
7
+ import { FilterCombinations } from '../../enums/FilterCombinations';
8
8
  export declare abstract class BaseSeoIndexabilityPolicy<TDependencies extends IDependencies> implements ISeoIndexabilityPolicy, ISitemapUrlGenerator {
9
+ abstract readonly name: string;
10
+ abstract readonly description: string;
9
11
  protected readonly dependencies: TDependencies;
10
12
  protected abstract readonly rules: IRule[];
11
13
  constructor(dependencies: TDependencies);
@@ -18,4 +20,7 @@ export declare abstract class BaseSeoIndexabilityPolicy<TDependencies extends ID
18
20
  protected checkRulesForSitemap(filterKeyValues: FilterKeyValuesMap): Promise<boolean>;
19
21
  protected isIndexabilityPolicyDependencies(): boolean;
20
22
  protected isSitemapUrlGeneratorDependencies(): boolean;
23
+ getAllRules(): IRule[];
24
+ getName(): string;
25
+ getDescription(): string;
21
26
  }
@@ -44,4 +44,13 @@ export class BaseSeoIndexabilityPolicy {
44
44
  isSitemapUrlGeneratorDependencies() {
45
45
  return this.dependencies.dependencyType === DependencyTypes.SITEMAP_GENERATOR;
46
46
  }
47
+ getAllRules() {
48
+ return this.rules;
49
+ }
50
+ getName() {
51
+ return this.name;
52
+ }
53
+ getDescription() {
54
+ return this.description;
55
+ }
47
56
  }
@@ -5,6 +5,7 @@ export declare abstract class BaseFilterKeyValueRule implements IRule {
5
5
  private readonly expectedFilterKeyValues;
6
6
  constructor(expectedFilterKeyValues: FilterKeyValuesMap);
7
7
  abstract getName(): string;
8
+ abstract getDescription(): string;
8
9
  forSearch(dependencies: ISearchDependencies): Promise<boolean>;
9
10
  forSitemapGenerator(filterKeyValues: FilterKeyValuesMap): Promise<boolean>;
10
11
  }
@@ -5,4 +5,5 @@ export declare class NoFiltersSelectedRule implements IRule {
5
5
  forSearch(dependencies: ISearchDependencies): Promise<boolean>;
6
6
  forSitemapGenerator(filterKeyValues: FilterKeyValuesMap): Promise<boolean>;
7
7
  getName(): string;
8
+ getDescription(): string;
8
9
  }
@@ -11,4 +11,7 @@ export class NoFiltersSelectedRule {
11
11
  getName() {
12
12
  return 'NoFiltersSelectedRule';
13
13
  }
14
+ getDescription() {
15
+ return 'No filters are selected';
16
+ }
14
17
  }
@@ -0,0 +1,6 @@
1
+ import { BaseFilterKeyValueRule } from '../../common/rules/BaseFilterKeyValueRule';
2
+ export declare class OnlineAttendanceRule extends BaseFilterKeyValueRule {
3
+ constructor();
4
+ getName(): string;
5
+ getDescription(): string;
6
+ }
@@ -0,0 +1,14 @@
1
+ import { FilterKey } from '@studyportals/search-filters';
2
+ import { BaseFilterKeyValueRule } from '../../common/rules/BaseFilterKeyValueRule';
3
+ export class OnlineAttendanceRule extends BaseFilterKeyValueRule {
4
+ constructor() {
5
+ const filterKeyValues = new Map([[FilterKey.DELIVERY_METHOD, ['online']]]);
6
+ super(filterKeyValues);
7
+ }
8
+ getName() {
9
+ return 'OnlineAttendanceRule';
10
+ }
11
+ getDescription() {
12
+ return 'Is indexable if the selected delivery method is online.';
13
+ }
14
+ }
@@ -8,4 +8,5 @@ export declare class OnlyFiltersSelectedRule implements IRule {
8
8
  getName(): string;
9
9
  forSearch(dependencies: ISearchDependencies): Promise<boolean>;
10
10
  forSitemapGenerator(filterKeyValues: FilterKeyValuesMap): Promise<boolean>;
11
+ getDescription(): string;
11
12
  }
@@ -24,4 +24,7 @@ export class OnlyFiltersSelectedRule {
24
24
  }
25
25
  return Promise.resolve(true);
26
26
  }
27
+ getDescription() {
28
+ return `Only ${this.filterKeys.join(', ')} filters are selected`;
29
+ }
27
30
  }
@@ -8,4 +8,5 @@ export declare class SingleValueSelectedForFilterRule implements IRule {
8
8
  getName(): string;
9
9
  forSearch(dependencies: ISearchDependencies): Promise<boolean>;
10
10
  forSitemapGenerator(filterKeyValues: FilterKeyValuesMap): Promise<boolean>;
11
+ getDescription(): string;
11
12
  }
@@ -18,4 +18,7 @@ export class SingleValueSelectedForFilterRule {
18
18
  }
19
19
  return Promise.resolve(true);
20
20
  }
21
+ getDescription() {
22
+ return `Single value is selected for filter ${this.filterKey}`;
23
+ }
21
24
  }
@@ -3,17 +3,37 @@ export declare enum FilterCombinations {
3
3
  AREA_ATTENDANCE = "areaAttendance",
4
4
  AREA_DISCIPLINE = "areaDiscipline",
5
5
  COUNTRY = "country",
6
+ COUNTRY_DEGREE = "countryDegree",
7
+ COUNTRY_DURATION = "countryDuration",
8
+ COUNTRY_FORMAT = "countryFormat",
9
+ COUNTRY_TUITION_FEE = "countryTuitionFee",
10
+ COUNTRY_EDUCATIONAL_FORM = "countryEducationalForm",
11
+ COUNTRY_ATTENDANCE_DEGREE = "countryAttendanceDegree",
12
+ COUNTRY_DURATION_DEGREE = "countryDurationDegree",
6
13
  DISCIPLINE_AREA = "disciplineArea",
7
14
  DISCIPLINE_ATTENDANCE = "disciplineAttendance",
8
15
  DISCIPLINE_COUNTRY = "disciplineCountry",
16
+ DISCIPLINE_CONTINENT = "disciplineContinent",
17
+ DISCIPLINE_DEGREE = "disciplineDegree",
18
+ DISCIPLINE_DURATION = "disciplineDuration",
19
+ DISCIPLINE_FORMAT = "disciplineFormat",
20
+ DISCIPLINE_TUITION_FEE = "disciplineTuitionFee",
21
+ DISCIPLINE_EDUCATIONAL_FORM = "disciplineEducationalForm",
22
+ DISCIPLINE_TUITION_FEE_ATTENDANCE = "disciplineTuitionFeeAttendance",
23
+ DISCIPLINE_COUNTRY_EDUCATIONAL_FORM = "disciplineCountryEducationalForm",
24
+ DISCIPLINE_COUNTRY_DEGREE = "disciplineCountryDegree",
9
25
  DISCIPLINE = "discipline",
10
26
  UNFILTERED = "unfiltered",
11
27
  UNIVERSITY_COUNTRY = "universityCountry",
12
28
  ATTENDANCE_DISCIPLINE = "attendancedDiscipline",
29
+ ATTENDANCE_DEGREE = "attendanceDegree",
13
30
  CONTINENT_ATTENDANCE = "continentAttendance",
14
31
  COUNTRY_ATTENDANCE = "countryAttendance",
15
32
  ATTENDANCE = "attendance",
16
33
  CONTINENT = "continent",
34
+ CONTINENT_TUITION_FEE = "continentTuitionFee",
35
+ TUITION_FEE = "tuitionFee",
36
+ SPECIAL_PROGRAMMES = "specialProgrammes",
17
37
  RANKED_AREA = "rankedArea",
18
38
  RANKED_AREA_DISCIPLINE = "rankedAreaDiscipline",
19
39
  RANKED_ATTENDANCE = "rankedAttendance",
@@ -4,17 +4,37 @@ export var FilterCombinations;
4
4
  FilterCombinations["AREA_ATTENDANCE"] = "areaAttendance";
5
5
  FilterCombinations["AREA_DISCIPLINE"] = "areaDiscipline";
6
6
  FilterCombinations["COUNTRY"] = "country";
7
+ FilterCombinations["COUNTRY_DEGREE"] = "countryDegree";
8
+ FilterCombinations["COUNTRY_DURATION"] = "countryDuration";
9
+ FilterCombinations["COUNTRY_FORMAT"] = "countryFormat";
10
+ FilterCombinations["COUNTRY_TUITION_FEE"] = "countryTuitionFee";
11
+ FilterCombinations["COUNTRY_EDUCATIONAL_FORM"] = "countryEducationalForm";
12
+ FilterCombinations["COUNTRY_ATTENDANCE_DEGREE"] = "countryAttendanceDegree";
13
+ FilterCombinations["COUNTRY_DURATION_DEGREE"] = "countryDurationDegree";
7
14
  FilterCombinations["DISCIPLINE_AREA"] = "disciplineArea";
8
15
  FilterCombinations["DISCIPLINE_ATTENDANCE"] = "disciplineAttendance";
9
16
  FilterCombinations["DISCIPLINE_COUNTRY"] = "disciplineCountry";
17
+ FilterCombinations["DISCIPLINE_CONTINENT"] = "disciplineContinent";
18
+ FilterCombinations["DISCIPLINE_DEGREE"] = "disciplineDegree";
19
+ FilterCombinations["DISCIPLINE_DURATION"] = "disciplineDuration";
20
+ FilterCombinations["DISCIPLINE_FORMAT"] = "disciplineFormat";
21
+ FilterCombinations["DISCIPLINE_TUITION_FEE"] = "disciplineTuitionFee";
22
+ FilterCombinations["DISCIPLINE_EDUCATIONAL_FORM"] = "disciplineEducationalForm";
23
+ FilterCombinations["DISCIPLINE_TUITION_FEE_ATTENDANCE"] = "disciplineTuitionFeeAttendance";
24
+ FilterCombinations["DISCIPLINE_COUNTRY_EDUCATIONAL_FORM"] = "disciplineCountryEducationalForm";
25
+ FilterCombinations["DISCIPLINE_COUNTRY_DEGREE"] = "disciplineCountryDegree";
10
26
  FilterCombinations["DISCIPLINE"] = "discipline";
11
27
  FilterCombinations["UNFILTERED"] = "unfiltered";
12
28
  FilterCombinations["UNIVERSITY_COUNTRY"] = "universityCountry";
13
29
  FilterCombinations["ATTENDANCE_DISCIPLINE"] = "attendancedDiscipline";
30
+ FilterCombinations["ATTENDANCE_DEGREE"] = "attendanceDegree";
14
31
  FilterCombinations["CONTINENT_ATTENDANCE"] = "continentAttendance";
15
32
  FilterCombinations["COUNTRY_ATTENDANCE"] = "countryAttendance";
16
33
  FilterCombinations["ATTENDANCE"] = "attendance";
17
34
  FilterCombinations["CONTINENT"] = "continent";
35
+ FilterCombinations["CONTINENT_TUITION_FEE"] = "continentTuitionFee";
36
+ FilterCombinations["TUITION_FEE"] = "tuitionFee";
37
+ FilterCombinations["SPECIAL_PROGRAMMES"] = "specialProgrammes";
18
38
  FilterCombinations["RANKED_AREA"] = "rankedArea";
19
39
  FilterCombinations["RANKED_AREA_DISCIPLINE"] = "rankedAreaDiscipline";
20
40
  FilterCombinations["RANKED_ATTENDANCE"] = "rankedAttendance";
@@ -0,0 +1,11 @@
1
+ import { PortalType } from '@studyportals/domain-client';
2
+ import { IOrganisationsSeoDependencies } from './types/IOrganisationsSeoDependencies';
3
+ import { SortingOptions } from '../enums/SortingOptions';
4
+ import { BaseSeoIndexabilityPolicy } from '../common/policies/BaseSeoIndexabilityPolicy';
5
+ export declare abstract class OrganisationsRuleBasedIndexabilityPolicy extends BaseSeoIndexabilityPolicy<IOrganisationsSeoDependencies> {
6
+ protected readonly indexablePortalTypes: PortalType[];
7
+ protected abstract readonly sortingOption: SortingOptions;
8
+ constructor(dependencies: IOrganisationsSeoDependencies);
9
+ protected isIndexable(): Promise<boolean>;
10
+ private matchesSortingOption;
11
+ }
@@ -0,0 +1,19 @@
1
+ import { PortalType } from '@studyportals/domain-client';
2
+ import { BaseSeoIndexabilityPolicy } from '../common/policies/BaseSeoIndexabilityPolicy';
3
+ export class OrganisationsRuleBasedIndexabilityPolicy extends BaseSeoIndexabilityPolicy {
4
+ indexablePortalTypes = [PortalType.MASTER];
5
+ constructor(dependencies) {
6
+ super(dependencies);
7
+ }
8
+ async isIndexable() {
9
+ const isIndexable = await super.isIndexable();
10
+ if (!isIndexable) {
11
+ return false;
12
+ }
13
+ return this.indexablePortalTypes.includes(this.dependencies.portalType) && this.matchesSortingOption();
14
+ }
15
+ matchesSortingOption() {
16
+ const dependencies = this.dependencies;
17
+ return dependencies.sortingState.getSelectedOption() === this.sortingOption;
18
+ }
19
+ }
@@ -8,4 +8,5 @@ export declare class SearchIndexabilityManager implements ISearchIndexabilityMan
8
8
  policies: ISeoIndexabilityPolicy[];
9
9
  constructor(portalType: PortalType, seoInfoBase: ISeoInfoBase, filterState: ISeoFilterState, sortingState: ISeoSortingState, applicationState: IOrganisationSearchApplicationState);
10
10
  shouldIndex(): Promise<boolean>;
11
+ getPolicies(): ISeoIndexabilityPolicy[];
11
12
  }
@@ -36,4 +36,7 @@ export class SearchIndexabilityManager {
36
36
  const results = await Promise.all(this.policies.map((policy) => policy.shouldIndex()));
37
37
  return results.some((result) => result);
38
38
  }
39
+ getPolicies() {
40
+ return this.policies;
41
+ }
39
42
  }
@@ -5,7 +5,6 @@ import { SortingOptions } from '../../enums/SortingOptions';
5
5
  export declare abstract class OrganisationsSeoIndexabilityPolicy extends BaseSeoIndexabilityPolicy<IOrganisationsSeoDependencies> {
6
6
  protected readonly indexablePortalTypes: PortalType[];
7
7
  protected abstract readonly sortingOption: SortingOptions;
8
- constructor(dependencies: IOrganisationsSeoDependencies);
9
8
  generateSitemapUrls(): Promise<string[]>;
10
9
  protected isIndexable(): Promise<boolean>;
11
10
  protected getPathWithSortingOption(path: string): string;
@@ -2,9 +2,6 @@ import { PortalType } from '@studyportals/domain-client';
2
2
  import { BaseSeoIndexabilityPolicy } from '../../common/policies/BaseSeoIndexabilityPolicy';
3
3
  export class OrganisationsSeoIndexabilityPolicy extends BaseSeoIndexabilityPolicy {
4
4
  indexablePortalTypes = [PortalType.MASTER];
5
- constructor(dependencies) {
6
- super(dependencies);
7
- }
8
5
  async generateSitemapUrls() {
9
6
  if (this.indexablePortalTypes.includes(this.dependencies.portalType)) {
10
7
  return super.generateSitemapUrls();
@@ -1,6 +1,8 @@
1
+ import { PortalType } from '@studyportals/domain-client';
1
2
  import { SortingOptions } from '../../enums/SortingOptions';
2
3
  import { OrganisationsSeoIndexabilityPolicy } from './OrganisationsSeoIndexabilityPolicy';
3
4
  export declare abstract class RankedOrganisationsSeoIndexabilityPolicy extends OrganisationsSeoIndexabilityPolicy {
5
+ protected readonly indexablePortalTypes: PortalType[];
4
6
  protected readonly sortingOption: SortingOptions;
5
7
  protected addRankedResultsCountRule(): void;
6
8
  protected getPathWithSortingOption(path: string): string;
@@ -1,7 +1,9 @@
1
+ import { PortalType } from '@studyportals/domain-client';
1
2
  import { SortingOptions } from '../../enums/SortingOptions';
2
3
  import { OrganisationsSeoIndexabilityPolicy } from './OrganisationsSeoIndexabilityPolicy';
3
4
  import { AtLeastTwoRankedResultsRule } from '../rules/AtLeastTwoRankedResultsRule';
4
5
  export class RankedOrganisationsSeoIndexabilityPolicy extends OrganisationsSeoIndexabilityPolicy {
6
+ indexablePortalTypes = [PortalType.MASTER];
5
7
  sortingOption = SortingOptions.UNIVERSITY_META_RANKING;
6
8
  addRankedResultsCountRule() {
7
9
  let rankedResultsCountRule;
@@ -4,6 +4,8 @@ import { SingleValueSelectedForFilterRule } from '../../../common/rules/SingleVa
4
4
  import { OrganisationsSeoIndexabilityPolicy } from '../../../organisations/policies/OrganisationsSeoIndexabilityPolicy';
5
5
  import { OnlyFiltersSelectedRule } from '../../../common/rules/OnlyFiltersSelectedRule';
6
6
  export declare class Area extends OrganisationsSeoIndexabilityPolicy {
7
+ readonly name: string;
8
+ readonly description: string;
7
9
  protected readonly sortingOption = SortingOptions.OUR_PICKS;
8
10
  protected readonly rules: (SingleValueSelectedForFilterRule | OnlyFiltersSelectedRule)[];
9
11
  protected generateUrls(): Promise<string[]>;
@@ -6,6 +6,8 @@ import { OrganisationsSeoIndexabilityPolicy } from '../../../organisations/polic
6
6
  import { OnlyFiltersSelectedRule } from '../../../common/rules/OnlyFiltersSelectedRule';
7
7
  import { AreaPresenter } from '../../../presenters/AreaPresenter';
8
8
  export class Area extends OrganisationsSeoIndexabilityPolicy {
9
+ name = 'Area Policy';
10
+ description = 'Controls indexing of pages filtered by geographic areas, ensuring only SEO-valuable regional content with sufficient search volume is indexed.';
9
11
  sortingOption = SortingOptions.OUR_PICKS;
10
12
  rules = [
11
13
  new SingleValueSelectedForFilterRule(FilterKey.AREA),
@@ -4,10 +4,12 @@ import { SearchVolumeAreasAttendanceRule } from '../../../organisations/rules/Se
4
4
  import { SortingOptions } from '../../../enums/SortingOptions';
5
5
  import { SingleValueSelectedForFilterRule } from '../../../common/rules/SingleValueSelectedForFilterRule';
6
6
  import { OnlyFiltersSelectedRule } from '../../../common/rules/OnlyFiltersSelectedRule';
7
- import { OnlineAttendanceRule } from '../../../organisations/rules/OnlineAttendanceRule';
7
+ import { OnlineAttendanceRule } from '../../../common/rules/OnlineAttendanceRule';
8
8
  export declare class AreaAttendance extends OrganisationsSeoIndexabilityPolicy {
9
+ readonly name: string;
10
+ readonly description: string;
9
11
  protected readonly sortingOption = SortingOptions.OUR_PICKS;
10
- protected readonly rules: (SingleValueSelectedForFilterRule | OnlyFiltersSelectedRule | SearchVolumeAreasAttendanceRule | OnlineAttendanceRule)[];
12
+ protected readonly rules: (SingleValueSelectedForFilterRule | OnlyFiltersSelectedRule | OnlineAttendanceRule | SearchVolumeAreasAttendanceRule)[];
11
13
  protected generateUrls(): Promise<string[]>;
12
14
  get filterCombination(): FilterCombinations;
13
15
  }
@@ -5,10 +5,12 @@ import { SearchVolumeAreasAttendanceRule } from '../../../organisations/rules/Se
5
5
  import { SortingOptions } from '../../../enums/SortingOptions';
6
6
  import { SingleValueSelectedForFilterRule } from '../../../common/rules/SingleValueSelectedForFilterRule';
7
7
  import { OnlyFiltersSelectedRule } from '../../../common/rules/OnlyFiltersSelectedRule';
8
- import { OnlineAttendanceRule } from '../../../organisations/rules/OnlineAttendanceRule';
8
+ import { OnlineAttendanceRule } from '../../../common/rules/OnlineAttendanceRule';
9
9
  import { AreaPresenter } from '../../../presenters/AreaPresenter';
10
10
  import { AttendancePresenter } from '../../../presenters/AttendancePresenter';
11
11
  export class AreaAttendance extends OrganisationsSeoIndexabilityPolicy {
12
+ name = 'Area Attendance Policy';
13
+ description = 'Manages indexability for pages filtered by both geographic area and attendance type, optimizing for region-specific study format combinations.';
12
14
  sortingOption = SortingOptions.OUR_PICKS;
13
15
  rules = [
14
16
  new SingleValueSelectedForFilterRule(FilterKey.AREA),
@@ -3,8 +3,10 @@ import { SortingOptions } from '../../../enums/SortingOptions';
3
3
  import { OrganisationsSeoIndexabilityPolicy } from '../../../organisations/policies/OrganisationsSeoIndexabilityPolicy';
4
4
  import { SingleValueSelectedForFilterRule } from '../../../common/rules/SingleValueSelectedForFilterRule';
5
5
  import { OnlyFiltersSelectedRule } from '../../../common/rules/OnlyFiltersSelectedRule';
6
- import { OnlineAttendanceRule } from '../../../organisations/rules/OnlineAttendanceRule';
6
+ import { OnlineAttendanceRule } from '../../../common/rules/OnlineAttendanceRule';
7
7
  export declare class Attendance extends OrganisationsSeoIndexabilityPolicy {
8
+ readonly name: string;
9
+ readonly description: string;
8
10
  protected readonly sortingOption = SortingOptions.OUR_PICKS;
9
11
  protected readonly rules: (SingleValueSelectedForFilterRule | OnlyFiltersSelectedRule | OnlineAttendanceRule)[];
10
12
  protected generateUrls(): Promise<string[]>;
@@ -4,9 +4,11 @@ import { SortingOptions } from '../../../enums/SortingOptions';
4
4
  import { OrganisationsSeoIndexabilityPolicy } from '../../../organisations/policies/OrganisationsSeoIndexabilityPolicy';
5
5
  import { SingleValueSelectedForFilterRule } from '../../../common/rules/SingleValueSelectedForFilterRule';
6
6
  import { OnlyFiltersSelectedRule } from '../../../common/rules/OnlyFiltersSelectedRule';
7
- import { OnlineAttendanceRule } from '../../../organisations/rules/OnlineAttendanceRule';
7
+ import { OnlineAttendanceRule } from '../../../common/rules/OnlineAttendanceRule';
8
8
  import { AttendancePresenter } from '../../../presenters/AttendancePresenter';
9
9
  export class Attendance extends OrganisationsSeoIndexabilityPolicy {
10
+ name = 'Attendance Policy';
11
+ description = 'Determines indexing rules for pages filtered by study format (online, on-campus, etc.), prioritizing formats with demonstrated search demand.';
10
12
  sortingOption = SortingOptions.OUR_PICKS;
11
13
  rules = [
12
14
  new SingleValueSelectedForFilterRule(FilterKey.DELIVERY_METHOD),
@@ -4,6 +4,8 @@ import { OrganisationsSeoIndexabilityPolicy } from '../../../organisations/polic
4
4
  import { SingleValueSelectedForFilterRule } from '../../../common/rules/SingleValueSelectedForFilterRule';
5
5
  import { OnlyFiltersSelectedRule } from '../../../common/rules/OnlyFiltersSelectedRule';
6
6
  export declare class Continent extends OrganisationsSeoIndexabilityPolicy {
7
+ readonly name: string;
8
+ readonly description: string;
7
9
  protected readonly sortingOption = SortingOptions.OUR_PICKS;
8
10
  protected readonly rules: (SingleValueSelectedForFilterRule | OnlyFiltersSelectedRule)[];
9
11
  get filterCombination(): FilterCombinations;
@@ -6,6 +6,8 @@ import { SingleValueSelectedForFilterRule } from '../../../common/rules/SingleVa
6
6
  import { OnlyFiltersSelectedRule } from '../../../common/rules/OnlyFiltersSelectedRule';
7
7
  import { ContinentPresenter } from '../../../presenters/ContinentPresenter';
8
8
  export class Continent extends OrganisationsSeoIndexabilityPolicy {
9
+ name = 'Continent Policy';
10
+ description = 'Governs indexing of continent-level filtered pages, applying rules to index only continental regions with sufficient search volume and content density.';
9
11
  sortingOption = SortingOptions.OUR_PICKS;
10
12
  rules = [
11
13
  new SingleValueSelectedForFilterRule(FilterKey.CONTINENT),